From ac0bacc8afc2f0ed3e1e1a19bdb469f8a4ec557e Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 18 Sep 2013 11:49:05 +0200 Subject: Port of Qt 4's Windows session management This patch aims to implement the session management for Windows. Based on the Qt 4 QApplication windows specific code Task-number: QTBUG-28228 Task-number: QTBUG-33032 Change-Id: I7059298ad9661aebd51e77a03f55a7a04f461479 Reviewed-by: Kai Koehne --- src/plugins/platforms/windows/qtwindowsglobal.h | 9 ++ src/plugins/platforms/windows/qwindowscontext.cpp | 70 ++++++++++++- .../windows/qwindowsguieventdispatcher.cpp | 5 + .../platforms/windows/qwindowsintegration.cpp | 15 ++- .../platforms/windows/qwindowsintegration.h | 5 + .../platforms/windows/qwindowssessionmanager.cpp | 112 +++++++++++++++++++++ .../platforms/windows/qwindowssessionmanager.h | 90 +++++++++++++++++ src/plugins/platforms/windows/windows.pro | 5 + 8 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 src/plugins/platforms/windows/qwindowssessionmanager.cpp create mode 100644 src/plugins/platforms/windows/qwindowssessionmanager.h (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h index e9eb50799e..ee5b6189b2 100644 --- a/src/plugins/platforms/windows/qtwindowsglobal.h +++ b/src/plugins/platforms/windows/qtwindowsglobal.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2013 Samuel Gaist ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -98,6 +99,8 @@ enum WindowsEventType // Simplify event types ActivateApplicationEvent = ApplicationEventFlag + 1, DeactivateApplicationEvent = ApplicationEventFlag + 2, AccessibleObjectFromWindowRequest = ApplicationEventFlag + 3, + QueryEndSessionApplicationEvent = ApplicationEventFlag + 4, + EndSessionApplicationEvent = ApplicationEventFlag + 5, InputMethodStartCompositionEvent = InputMethodEventFlag + 1, InputMethodCompositionEvent = InputMethodEventFlag + 2, InputMethodEndCompositionEvent = InputMethodEventFlag + 3, @@ -214,6 +217,12 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI return QtWindows::WhatsThisEvent; #endif break; +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + case WM_QUERYENDSESSION: + return QtWindows::QueryEndSessionApplicationEvent; + case WM_ENDSESSION: + return QtWindows::EndSessionApplicationEvent; +#endif default: break; } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 8dab1e2b1c..783d50a26a 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2013 Samuel Gaist ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -49,7 +50,12 @@ #include "qwindowsinputcontext.h" #include "qwindowstabletsupport.h" #ifndef QT_NO_ACCESSIBILITY -#include "accessible/qwindowsaccessibility.h" +# include "accessible/qwindowsaccessibility.h" +#endif +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) +# include +# include +# include "qwindowssessionmanager.h" #endif #include "qwindowsscreen.h" #include "qwindowstheme.h" @@ -151,6 +157,14 @@ static inline bool useRTL_Extensions(QSysInfo::WinVersion ver) #endif } +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) +static inline QWindowsSessionManager *platformSessionManager() { + QGuiApplicationPrivate *guiPrivate = static_cast(QObjectPrivate::get(qApp)); + QSessionManagerPrivate *managerPrivate = static_cast(QObjectPrivate::get(guiPrivate->session_manager)); + return static_cast(managerPrivate->platformSessionManager); +} +#endif + /*! \class QWindowsUser32DLL \brief Struct that contains dynamically resolved symbols of User32.dll. @@ -828,7 +842,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::KeyEvent: case QtWindows::InputMethodKeyEvent: case QtWindows::InputMethodKeyDownEvent: +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + return platformSessionManager()->isInterractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); +#else return d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); +#endif case QtWindows::MoveEvent: platformWindow->handleMoved(); return true; @@ -848,7 +866,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); case QtWindows::NonClientMouseEvent: if (platformWindow->frameStrutEventsEnabled()) +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + return platformSessionManager()->isInterractionBlocked() ? true : d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); +#else return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); +#endif break; /* the mouse tracking on windows already handles the reset of the cursor * and does not like somebody else handling it. @@ -864,9 +886,17 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::MouseWheelEvent: case QtWindows::MouseEvent: case QtWindows::LeaveEvent: +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + return platformSessionManager()->isInterractionBlocked() ? true : d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); +#else return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); +#endif case QtWindows::TouchEvent: +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + return platformSessionManager()->isInterractionBlocked() ? true : d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); +#else return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); +#endif case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow(). case QtWindows::FocusOutEvent: handleFocusEvent(et, platformWindow); @@ -910,6 +940,44 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return true; #endif } break; +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + case QtWindows::QueryEndSessionApplicationEvent: { + QWindowsSessionManager *sessionManager = platformSessionManager(); + if (sessionManager->isActive()) // bogus message from windows + return true; + + sessionManager->setActive(true); + sessionManager->blocksInteraction(); + sessionManager->clearCancellation(); + + QGuiApplicationPrivate *qGuiAppPriv = static_cast(QObjectPrivate::get(qApp)); + qGuiAppPriv->commitData(); + + if (lParam & ENDSESSION_LOGOFF) + _flushall(); + + return !sessionManager->wasCanceled(); + } + case QtWindows::EndSessionApplicationEvent: { + QWindowsSessionManager *sessionManager = platformSessionManager(); + + sessionManager->setActive(false); + sessionManager->allowsInteraction(); + bool endsession = (bool) wParam; + + // we receive the message for each toplevel window included internal hidden ones, + // but the aboutToQuit signal should be emitted only once. + QGuiApplicationPrivate *qGuiAppPriv = static_cast(QObjectPrivate::get(qApp)); + if (endsession && !qGuiAppPriv->aboutToQuitEmitted) { + qGuiAppPriv->aboutToQuitEmitted = true; + int index = QGuiApplication::staticMetaObject.indexOfSignal("aboutToQuit()"); + qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0); + // since the process will be killed immediately quit() has no real effect + QGuiApplication::quit(); + } + return true; + } +#endif // !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) default: break; } diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp index 6be71999f6..e7cd0bc6c8 100644 --- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp +++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2013 Samuel Gaist ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -176,6 +177,10 @@ messageDebugEntries[] = { {WM_IME_ENDCOMPOSITION, "WM_IME_ENDCOMPOSITION", true}, {WM_IME_NOTIFY, "WM_IME_NOTIFY", true}, {WM_IME_REQUEST, "WM_IME_REQUEST", true}, +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + {WM_QUERYENDSESSION, "WM_QUERYENDSESSION", true}, + {WM_ENDSESSION, "WM_ENDSESSION", true}, +#endif {WM_DISPLAYCHANGE, "WM_DISPLAYCHANGE", true}, {WM_THEMECHANGED, "WM_THEMECHANGED", true} }; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 5f1f9cf149..d7ac4cfc1e 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2013 Samuel Gaist ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -65,12 +66,15 @@ #endif #include "qwindowsinputcontext.h" #include "qwindowskeymapper.h" -# ifndef QT_NO_ACCESSIBILITY -#include "accessible/qwindowsaccessibility.h" +#ifndef QT_NO_ACCESSIBILITY +# include "accessible/qwindowsaccessibility.h" #endif #include #include +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) +# include "qwindowssessionmanager.h" +#endif #include #include #include @@ -624,6 +628,13 @@ unsigned QWindowsIntegration::options() const return d->m_options; } +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) +QPlatformSessionManager *QWindowsIntegration::createPlatformSessionManager(const QString &id, const QString &key) const +{ + return new QWindowsSessionManager(id, key); +} +#endif + QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const { return d->m_eventDispatcher; diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index b3854d673a..6643b1642e 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2013 Samuel Gaist ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -100,6 +101,10 @@ public: unsigned options() const; +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + virtual QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const; +#endif + private: QScopedPointer d; }; diff --git a/src/plugins/platforms/windows/qwindowssessionmanager.cpp b/src/plugins/platforms/windows/qwindowssessionmanager.cpp new file mode 100644 index 0000000000..efdbb6b279 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowssessionmanager.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Samuel Gaist +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowssessionmanager.h" + +QT_BEGIN_NAMESPACE + +QWindowsSessionManager::QWindowsSessionManager(const QString &id, const QString &key) + : QPlatformSessionManager(id, key) + , m_isActive(false) + , m_blockUserInput(false) + , m_canceled(false) +{ +} + +QWindowsSessionManager::~QWindowsSessionManager() +{ +} + +bool QWindowsSessionManager::allowsInteraction() +{ + m_blockUserInput = false; + return true; +} + +bool QWindowsSessionManager::allowsErrorInteraction() +{ + m_blockUserInput = false; + return true; +} + +void QWindowsSessionManager::blocksInteraction() +{ + m_blockUserInput = true; +} + +bool QWindowsSessionManager::isInterractionBlocked() const +{ + return m_blockUserInput; +} + +void QWindowsSessionManager::release() +{ + if (m_isActive) + m_blockUserInput = true; +} + +void QWindowsSessionManager::cancel() +{ + m_canceled = true; +} + +void QWindowsSessionManager::clearCancellation() +{ + m_canceled = false; +} + +bool QWindowsSessionManager::wasCanceled() const +{ + return m_canceled; +} + +void QWindowsSessionManager::setActive(bool active) +{ + m_isActive = active; +} + +bool QWindowsSessionManager::isActive() const +{ + return m_isActive; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowssessionmanager.h b/src/plugins/platforms/windows/qwindowssessionmanager.h new file mode 100644 index 0000000000..3e21cbabec --- /dev/null +++ b/src/plugins/platforms/windows/qwindowssessionmanager.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Samuel Gaist +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSSESSIONMANAGER_H +#define QWINDOWSSESSIONMANAGER_H + +// +// W A R N I N G +// ------------- +// +// This file is part of the QPA API and is not meant to be used +// in applications. Usage of this API may make your code +// source and binary incompatible with future versions of Qt. +// + +#include + +QT_BEGIN_NAMESPACE + +class QWindowsSessionManager : public QPlatformSessionManager +{ +public: + explicit QWindowsSessionManager(const QString &id, const QString &key); + virtual ~QWindowsSessionManager(); + + bool allowsInteraction() Q_DECL_OVERRIDE; + bool allowsErrorInteraction() Q_DECL_OVERRIDE; + + void blocksInteraction(); + bool isInterractionBlocked() const; + + void release() Q_DECL_OVERRIDE; + + void cancel() Q_DECL_OVERRIDE; + void clearCancellation(); + bool wasCanceled() const; + + void setActive(bool active); + bool isActive() const; + +private: + bool m_isActive; + bool m_blockUserInput; + bool m_canceled; + + Q_DISABLE_COPY(QWindowsSessionManager) +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSSESSIONMANAGER_H diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro index d4e6e558ed..0249e156d9 100644 --- a/src/plugins/platforms/windows/windows.pro +++ b/src/plugins/platforms/windows/windows.pro @@ -108,6 +108,11 @@ contains(QT_CONFIG, opengles2) { SOURCES += qwindowstabletsupport.cpp } +!wince*:!contains( DEFINES, QT_NO_SESSIONMANAGER ) { + SOURCES += qwindowssessionmanager.cpp + HEADERS += qwindowssessionmanager.h +} + contains(QT_CONFIG, freetype) { DEFINES *= QT_NO_FONTCONFIG QT_FREETYPE_DIR = $$QT_SOURCE_TREE/src/3rdparty/freetype -- cgit v1.2.3