summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@digia.com>2013-01-28 15:16:02 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-02-21 14:55:10 +0100
commit22077e1609c8a5af39d48ddfb65066581ef15c0d (patch)
treebf999e3ec88cf5df2ae03ea6b6b5b4b1ebac8336 /src/gui/kernel
parent03b25125986f083a260b421abeed1f1d088d27b3 (diff)
QPA: Add interface for setting the application state explicitly
The motivation for this patch is twofold: 1: we need a way (for iOS/Android) to tell the current window to remove focus from the focus object when the user hides the input panel. Otherwise, if the focus object is e.g a line edit, the cursor will continue to blink inside it, which is wrong. As it stands, telling the active window to deactivate (by calling QWindowSystemInterface::handleWindowActivated(0)), will cause the whole application to deactivate if no windows are active, which is not what we want. 2: Qt currently understands just two application states, Activated and Deactivated. On mobile platforms we can have other states as well, like "suspended" on iOS. So controlling the application state should not depend on window activation, but instead be controlled through a separate API by the platform plugin. This patch will add the following function: QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState) that lets us control the application state from the plugin. This also means that we factor out application state handling from window activation, which also gives us a way to remove focus from a window while keeping the application active. To not break existing desktop platforms that relies on application activation being tied to window activation, we need to make this API opt-in by using a platform integration capability hint. This is not optimal, but found necessary after investigating several other solutions. Which states (other that active/inactive) it makes sense to add to Qt::ApplicationState will be a topic for later patches. Change-Id: Ic6fdd3b66867abb67da43eba04ec86f06d82ff94 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/qguiapplication.cpp27
-rw-r--r--src/gui/kernel/qguiapplication_p.h3
-rw-r--r--src/gui/kernel/qplatformintegration.cpp7
-rw-r--r--src/gui/kernel/qplatformintegration.h3
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp9
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h2
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h12
7 files changed, 59 insertions, 4 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 89b3b9ab89..b8c6e4db20 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -111,6 +111,8 @@ bool QGuiApplicationPrivate::tabletState = false;
QWindow *QGuiApplicationPrivate::tabletPressTarget = 0;
QWindow *QGuiApplicationPrivate::currentMouseWindow = 0;
+Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
+
QPlatformIntegration *QGuiApplicationPrivate::platform_integration = 0;
QPlatformTheme *QGuiApplicationPrivate::platform_theme = 0;
@@ -1274,6 +1276,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
case QWindowSystemInterfacePrivate::WindowStateChanged:
QGuiApplicationPrivate::processWindowStateChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowStateChangedEvent *>(e));
break;
+ case QWindowSystemInterfacePrivate::ApplicationStateChanged:
+ QGuiApplicationPrivate::processApplicationStateChangedEvent(static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e));
+ break;
case QWindowSystemInterfacePrivate::Close:
QGuiApplicationPrivate::processCloseEvent(
static_cast<QWindowSystemInterfacePrivate::CloseEvent *>(e));
@@ -1567,7 +1572,7 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate
QCoreApplication::sendSpontaneousEvent(previous, &focusOut);
QObject::disconnect(previous, SIGNAL(focusObjectChanged(QObject*)),
qApp, SLOT(_q_updateFocusObject(QObject*)));
- } else {
+ } else if (!platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
QEvent appActivate(QEvent::ApplicationActivate);
qApp->sendSpontaneousEvent(qApp, &appActivate);
}
@@ -1577,7 +1582,7 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate
QCoreApplication::sendSpontaneousEvent(QGuiApplicationPrivate::focus_window, &focusIn);
QObject::connect(QGuiApplicationPrivate::focus_window, SIGNAL(focusObjectChanged(QObject*)),
qApp, SLOT(_q_updateFocusObject(QObject*)));
- } else {
+ } else if (!platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
QEvent appActivate(QEvent::ApplicationDeactivate);
qApp->sendSpontaneousEvent(qApp, &appActivate);
}
@@ -1601,6 +1606,24 @@ void QGuiApplicationPrivate::processWindowStateChangedEvent(QWindowSystemInterfa
}
}
+void QGuiApplicationPrivate::processApplicationStateChangedEvent(QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e)
+{
+ if (e->newState == applicationState)
+ return;
+ applicationState = e->newState;
+
+ switch (e->newState) {
+ case Qt::ApplicationActive: {
+ QEvent appActivate(QEvent::ApplicationActivate);
+ qApp->sendSpontaneousEvent(qApp, &appActivate);
+ break; }
+ case Qt::ApplicationInactive: {
+ QEvent appDeactivate(QEvent::ApplicationDeactivate);
+ qApp->sendSpontaneousEvent(qApp, &appDeactivate);
+ break; }
+ }
+}
+
void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce)
{
if (self)
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index e5f08934c1..13b5952e73 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -127,6 +127,8 @@ public:
static void processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e);
static void processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *e);
+ static void processApplicationStateChangedEvent(QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e);
+
static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e);
static void updateFilteredScreenOrientation(QScreen *screen);
@@ -199,6 +201,7 @@ public:
static bool tabletState;
static QWindow *tabletPressTarget;
static QWindow *currentMouseWindow;
+ static Qt::ApplicationState applicationState;
#ifndef QT_NO_CLIPBOARD
static QClipboard *qt_clipboard;
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index 027b9fc9f1..fbc7eeb76f 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -199,6 +199,13 @@ QPlatformServices *QPlatformIntegration::services() const
\value MultipleWindows The platform supports multiple QWindows, i.e. does some kind
of compositing either client or server side. Some platforms might only support a
single fullscreen window.
+
+ \value ApplicationState The platform handles the application state explicitly.
+ This means that QEvent::ApplicationActivate and QEvent::ApplicationDeativate
+ will not be posted automatically. Instead, the platform must handle application
+ state explicitly by using QWindowSystemInterface::handleApplicationStateChanged().
+ If not set, application state will follow window activation, which is the normal
+ behavior for desktop platforms.
*/
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 6e10df9495..55517cf600 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -88,7 +88,8 @@ public:
SharedGraphicsCache,
BufferQueueingOpenGL,
WindowMasks,
- MultipleWindows
+ MultipleWindows,
+ ApplicationState
};
virtual ~QPlatformIntegration() { }
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 5483dc49d0..01100d8555 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -46,6 +46,7 @@
#include "private/qtouchdevice_p.h"
#include <QAbstractEventDispatcher>
#include <qpa/qplatformdrag.h>
+#include <qpa/qplatformintegration.h>
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@@ -122,6 +123,14 @@ void QWindowSystemInterface::handleWindowStateChanged(QWindow *tlw, Qt::WindowSt
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
+void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState)
+{
+ Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState));
+ QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e =
+ new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+}
+
void QWindowSystemInterface::handleGeometryChange(QWindow *tlw, const QRect &newRect)
{
QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect);
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index 687c72bbef..5668f3c0cf 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -138,6 +138,8 @@ public:
static void handleWindowActivated(QWindow *w);
static void handleWindowStateChanged(QWindow *w, Qt::WindowState newState);
+ static void handleApplicationStateChanged(Qt::ApplicationState newState);
+
static void handleExposeEvent(QWindow *tlw, const QRegion &region);
#ifndef QT_NO_DRAGANDDROP
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index d0b728ec4d..3d98ae07c9 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -88,7 +88,8 @@ public:
TabletEnterProximity = UserInputEvent | 0x15,
TabletLeaveProximity = UserInputEvent | 0x16,
PlatformPanel = UserInputEvent | 0x17,
- ContextMenu = UserInputEvent | 0x18
+ ContextMenu = UserInputEvent | 0x18,
+ ApplicationStateChanged = 0x19
};
class WindowSystemEvent {
@@ -152,6 +153,15 @@ public:
Qt::WindowState newState;
};
+ class ApplicationStateChangedEvent : public WindowSystemEvent {
+ public:
+ ApplicationStateChangedEvent(Qt::ApplicationState newState)
+ : WindowSystemEvent(ApplicationStateChanged), newState(newState)
+ { }
+
+ Qt::ApplicationState newState;
+ };
+
class UserEvent : public WindowSystemEvent {
public:
UserEvent(QWindow * w, ulong time, EventType t)