From a73de7ce2dde1128a14e968bcdd6c17b3d2d17f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 20 Nov 2017 12:04:50 +0100 Subject: iOS: Harden logic for when it's safe to use the graphics hardware To fix QTBUG-52493 we tied the exposed state of a window to the application being in the foreground. This has the result of a visible flash of black between hiding the launch screen and showing the first frame of the application, as the application is still waiting for UIApplicationStateActive to begin rendering, which happens after iOS hides the launch screen. According to the iOS OpenGL ES Programming Guide, it should be safe to render GL in UIApplicationStateInactive as well, and even in UIApplicationStateBackground, as long as the rendering finishes before the UIApplicationDidEnterBackgroundNotification returns. To ensure that we catch any bugs in this area, checks have been added that verify that no rendering happens while in the background state. Task-number: QTBUG-63229 Task-number: QTBUG-52493 Task-number: QTBUG-55205 Change-Id: Ib42bedbeddd7479ab0fb5e5b7de9f5805658e111 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qopenglcontext.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/gui/kernel') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index cd6f011fcb..ad5e0b518d 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -937,7 +937,9 @@ GLuint QOpenGLContext::defaultFramebufferObject() const /*! Makes the context current in the current thread, against the given - \a surface. Returns \c true if successful. + \a surface. Returns \c true if successful; otherwise returns \c false. + The latter may happen if the surface is not exposed, or the graphics + hardware is not available due to e.g. the application being suspended. If \a surface is 0 this is equivalent to calling doneCurrent(). -- cgit v1.2.3 From e055efb4457cd361c5b3b3caf2b236951ee1706d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 6 Dec 2017 09:06:52 +0100 Subject: Do not allow drag events when window is blocked by modal window Check for QWindowPrivate::blockedByModalWindow in QGuiApplicationPrivate::processDrag(). Task-number: QTBUG-46287 Change-Id: I8f43de8389f34458f9e10b37b94806b47a50d40a Reviewed-by: Gatis Paeglis Reviewed-by: Paul Olav Tvete --- src/gui/kernel/qguiapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gui/kernel') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index f43329afd0..6d37014b38 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2868,7 +2868,7 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM static QPointer currentDragWindow; static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction; QPlatformDrag *platformDrag = platformIntegration()->drag(); - if (!platformDrag) { + if (!platformDrag || (w && w->d_func()->blockedByModalWindow)) { lastAcceptedDropAction = Qt::IgnoreAction; return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect()); } -- cgit v1.2.3 From 782eb1a114c0aaa729925899b2061d47f494435f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 11 Dec 2017 15:15:56 +0100 Subject: Report modifiers correctly in mouse events with evdev and libinput Task-number: QTBUG-60694 Change-Id: I7b1625e5f31e49cd2ab18a83bbd0f65f9b58088d Reviewed-by: Andy Nichols --- src/gui/kernel/qinputdevicemanager.cpp | 44 ++++++++++++++++++++++++++++++++ src/gui/kernel/qinputdevicemanager_p.h | 3 +++ src/gui/kernel/qinputdevicemanager_p_p.h | 2 ++ 3 files changed, 49 insertions(+) (limited to 'src/gui/kernel') diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp index 2d231ae26f..37b1450d5a 100644 --- a/src/gui/kernel/qinputdevicemanager.cpp +++ b/src/gui/kernel/qinputdevicemanager.cpp @@ -92,4 +92,48 @@ void QInputDeviceManager::setCursorPos(const QPoint &pos) emit cursorPositionChangeRequested(pos); } +/*! + \return the keyboard modifier state stored in the QInputDeviceManager object. + + Keyboard input handlers are expected to keep this up-to-date via + setKeyboardModifiers(). + + Querying the state via this function (e.g. from a mouse handler that needs + to include the modifier state in mouse events) is the preferred alternative + over QGuiApplication::keyboardModifiers() since the latter may not report + the current state due to asynchronous QPA event processing. + */ +Qt::KeyboardModifiers QInputDeviceManager::keyboardModifiers() const +{ + Q_D(const QInputDeviceManager); + return d->keyboardModifiers; +} + +void QInputDeviceManager::setKeyboardModifiers(Qt::KeyboardModifiers modsBeforeEvent, int key) +{ + Q_D(QInputDeviceManager); + Qt::KeyboardModifiers mods; + switch (key) { + case Qt::Key_Shift: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::ShiftModifier); + break; + case Qt::Key_Control: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::ControlModifier); + break; + case Qt::Key_Alt: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::AltModifier); + break; + case Qt::Key_Meta: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::MetaModifier); + break; + case Qt::Key_AltGr: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::GroupSwitchModifier); + break; + default: + mods = modsBeforeEvent; + break; + } + d->keyboardModifiers = mods; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h index db9d0596b6..ddf1e6befa 100644 --- a/src/gui/kernel/qinputdevicemanager_p.h +++ b/src/gui/kernel/qinputdevicemanager_p.h @@ -78,6 +78,9 @@ public: void setCursorPos(const QPoint &pos); + Qt::KeyboardModifiers keyboardModifiers() const; + void setKeyboardModifiers(Qt::KeyboardModifiers modsBeforeEvent, int key); + signals: void deviceListChanged(QInputDeviceManager::DeviceType type); void cursorPositionChangeRequested(const QPoint &pos); diff --git a/src/gui/kernel/qinputdevicemanager_p_p.h b/src/gui/kernel/qinputdevicemanager_p_p.h index ae91f3a2ab..0a91252fbc 100644 --- a/src/gui/kernel/qinputdevicemanager_p_p.h +++ b/src/gui/kernel/qinputdevicemanager_p_p.h @@ -69,6 +69,8 @@ public: void setDeviceCount(QInputDeviceManager::DeviceType type, int count); QMap m_deviceCount; + + Qt::KeyboardModifiers keyboardModifiers; }; QT_END_NAMESPACE -- cgit v1.2.3 From ba44cdae38406c429c7fb43863a6883bd0f79cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 1 Dec 2017 19:03:05 +0100 Subject: Teach QPlatformWindow about safe area margins and implement for iOS The safe area margins of a window represent the area that is safe to place content within, without intersecting areas of the screen where system UI is placed, or where a screen bezel may cover the content. QWidget will incorporate the safe area margins into its contents margins, so that they are are never smaller than the safe area margins. This can be disabled by unsetting the Qt::WA_ContentsMarginsRespectsSafeArea widget attribute, which is set by default. QLayouts will automatically use the contents area of a widget for their layout, unless the Qt::WA_LayoutOnEntireRect attribute has been set. This can be used, along with a contents margin of 0 on the actual layout, to allow e.g. a background image to underlay the status bar and other system areas on an iOS device, while still allowing child widgets of that background to be inset based on the safe area. [ChangeLog][iOS/tvOS] Qt will now take the safe area margins of the device into account when computing layouts for QtWidgets. Change-Id: Ife3827ab663f0625c1451e75b14fb8eeffb00754 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qguiapplication.cpp | 14 ++++++++++++++ src/gui/kernel/qguiapplication_p.h | 2 ++ src/gui/kernel/qplatformwindow.cpp | 10 ++++++++++ src/gui/kernel/qplatformwindow.h | 1 + src/gui/kernel/qwindow_p.h | 2 ++ src/gui/kernel/qwindowsysteminterface.cpp | 7 +++++++ src/gui/kernel/qwindowsysteminterface.h | 3 +++ src/gui/kernel/qwindowsysteminterface_p.h | 12 +++++++++++- 8 files changed, 50 insertions(+), 1 deletion(-) (limited to 'src/gui/kernel') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 6d37014b38..cff11367f7 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1759,6 +1759,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv case QWindowSystemInterfacePrivate::WindowScreenChanged: QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast(e)); break; + case QWindowSystemInterfacePrivate::SafeAreaMarginsChanged: + QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(static_cast(e)); + break; case QWindowSystemInterfacePrivate::ApplicationStateChanged: { QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast(e); QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); } @@ -2212,6 +2215,17 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf } } +void QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *wse) +{ + if (wse->window.isNull()) + return; + + // Handle by forwarding directly to QWindowPrivate, instead of sending spontaneous + // QEvent like most other functions, as there's no QEvent type for the safe area + // change, and we don't want to add one until we know that this is a good API. + qt_window_private(wse->window)->processSafeAreaMarginsChanged(); +} + 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 3804667ef3..d67ab61ff8 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -133,6 +133,8 @@ public: static void processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *e); static void processWindowScreenChangedEvent(QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e); + static void processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e); + static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); static void updateFilteredScreenOrientation(QScreen *screen); diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 5062bd1e77..23e492ee7a 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -146,6 +146,16 @@ QMargins QPlatformWindow::frameMargins() const return QMargins(); } +/*! + The safe area margins of a window represent the area that is safe to + place content within, without intersecting areas of the screen where + system UI is placed, or where a screen bezel may cover the content. +*/ +QMargins QPlatformWindow::safeAreaMargins() const +{ + return QMargins(); +} + /*! Reimplemented in subclasses to show the surface if \a visible is \c true, and hide it if \a visible is \c false. diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index 8af8791bb4..2bee55c7e0 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -86,6 +86,7 @@ public: virtual QRect normalGeometry() const; virtual QMargins frameMargins() const; + virtual QMargins safeAreaMargins() const; virtual void setVisible(bool visible); virtual void setWindowFlags(Qt::WindowFlags flags); diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index dd282a671d..568aa1e2fc 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -147,6 +147,8 @@ public: virtual void clearFocusObject(); virtual QRectF closestAcceptableGeometry(const QRectF &rect) const; + virtual void processSafeAreaMarginsChanged() {}; + bool isPopup() const { return (windowFlags & Qt::WindowType_Mask) == Qt::Popup; } static QWindowPrivate *get(QWindow *window) { return window->d_func(); } diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 3f27094845..13f45d236e 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -265,6 +265,13 @@ void QWindowSystemInterface::handleWindowScreenChanged(QWindow *window, QScreen QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } +QT_DEFINE_QPA_EVENT_HANDLER(void, handleSafeAreaMarginsChanged, QWindow *window) +{ + QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e = + new QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent(window); + QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); +} + QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::ApplicationState newState, bool forcePropagate) { Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)); diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index e91c79749d..fb428233ab 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -179,6 +179,9 @@ public: static void handleWindowStateChanged(QWindow *window, Qt::WindowState newState, int oldState = -1); static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen); + template + static void handleSafeAreaMarginsChanged(QWindow *window); + template static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 0f350fb2d2..5b41ccc3a5 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -98,7 +98,8 @@ public: #endif ApplicationStateChanged = 0x19, FlushEvents = 0x20, - WindowScreenChanged = 0x21 + WindowScreenChanged = 0x21, + SafeAreaMarginsChanged = 0x22 }; class WindowSystemEvent { @@ -187,6 +188,15 @@ public: QPointer screen; }; + class SafeAreaMarginsChangedEvent : public WindowSystemEvent { + public: + SafeAreaMarginsChangedEvent(QWindow *w) + : WindowSystemEvent(SafeAreaMarginsChanged), window(w) + { } + + QPointer window; + }; + class ApplicationStateChangedEvent : public WindowSystemEvent { public: ApplicationStateChangedEvent(Qt::ApplicationState newState, bool forcePropagate = false) -- cgit v1.2.3