diff options
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 47 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.cpp | 15 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface_p.h | 6 | ||||
-rw-r--r-- | src/plugins/platforms/eglfs/api/qeglfswindow.cpp | 23 | ||||
-rw-r--r-- | src/plugins/platforms/ios/quiview.mm | 15 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 4 |
7 files changed, 57 insertions, 55 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 51653d9f8a..a29ddbe44e 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2213,7 +2213,7 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf } // we may have changed scaling, so trigger resize event if needed if (window->handle()) { - QWindowSystemInterfacePrivate::GeometryChangeEvent gce(window, QHighDpi::fromNativePixels(window->handle()->geometry(), window), QRect()); + QWindowSystemInterfacePrivate::GeometryChangeEvent gce(window, QHighDpi::fromNativePixels(window->handle()->geometry(), window)); processGeometryChangeEvent(&gce); } } @@ -2238,35 +2238,46 @@ void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePr if (!window) return; - QRect newRect = e->newGeometry; - QRect oldRect = e->oldGeometry.isNull() ? window->d_func()->geometry : e->oldGeometry; - - bool isResize = oldRect.size() != newRect.size(); - bool isMove = oldRect.topLeft() != newRect.topLeft(); - - window->d_func()->geometry = newRect; + const QRect lastReportedGeometry = window->d_func()->geometry; + const QRect requestedGeometry = e->requestedGeometry; + const QRect actualGeometry = e->newGeometry; + + // We send size and move events only if the geometry has changed from + // what was last reported, or if the user tried to set a new geometry, + // but the window manager responded by keeping the old geometry. In the + // latter case we send move/resize events with the same geometry as the + // last reported geometry, to indicate that the window wasn't moved or + // resized. Note that this logic does not apply to the property changes + // of the window, as we don't treat them as part of this request/response + // protocol of QWindow/QPA. + const bool isResize = actualGeometry.size() != lastReportedGeometry.size() + || requestedGeometry.size() != actualGeometry.size(); + const bool isMove = actualGeometry.topLeft() != lastReportedGeometry.topLeft() + || requestedGeometry.topLeft() != actualGeometry.topLeft(); + + window->d_func()->geometry = actualGeometry; if (isResize || window->d_func()->resizeEventPending) { - QResizeEvent e(newRect.size(), oldRect.size()); + QResizeEvent e(actualGeometry.size(), lastReportedGeometry.size()); QGuiApplication::sendSpontaneousEvent(window, &e); window->d_func()->resizeEventPending = false; - if (oldRect.width() != newRect.width()) - window->widthChanged(newRect.width()); - if (oldRect.height() != newRect.height()) - window->heightChanged(newRect.height()); + if (actualGeometry.width() != lastReportedGeometry.width()) + window->widthChanged(actualGeometry.width()); + if (actualGeometry.height() != lastReportedGeometry.height()) + window->heightChanged(actualGeometry.height()); } if (isMove) { //### frame geometry - QMoveEvent e(newRect.topLeft(), oldRect.topLeft()); + QMoveEvent e(actualGeometry.topLeft(), lastReportedGeometry.topLeft()); QGuiApplication::sendSpontaneousEvent(window, &e); - if (oldRect.x() != newRect.x()) - window->xChanged(newRect.x()); - if (oldRect.y() != newRect.y()) - window->yChanged(newRect.y()); + if (actualGeometry.x() != lastReportedGeometry.x()) + window->xChanged(actualGeometry.x()); + if (actualGeometry.y() != lastReportedGeometry.y()) + window->yChanged(actualGeometry.y()); } } diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 0be130a40d..233c27dee7 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -273,13 +273,18 @@ void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -/*! - If \a oldRect is null, Qt will use the previously reported geometry instead. - */ -QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect, const QRect &oldRect) +QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry) + : WindowSystemEvent(GeometryChange) + , window(window) + , requestedGeometry(window->handle() ? window->handle()->QPlatformWindow::geometry() : QRect()) + , newGeometry(newGeometry) +{ +} + +QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect) { Q_ASSERT(window); - QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window), QHighDpi::fromNativePixels(oldRect, window)); + QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window)); if (window->handle()) { // Persist the new geometry so that QWindow::geometry() can be queried in the resize event window->handle()->QPlatformWindow::setGeometry(newRect); diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 73ef612a06..7ea7b072f0 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -160,7 +160,7 @@ public: // rect is relative to parent template<typename Delivery = QWindowSystemInterface::DefaultDelivery> - static void handleGeometryChange(QWindow *window, const QRect &newRect, const QRect &oldRect = QRect()); + static void handleGeometryChange(QWindow *window, const QRect &newRect); // region is in local coordinates, do not confuse with geometry which is parent-relative template<typename Delivery = QWindowSystemInterface::DefaultDelivery> diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 55aafc4d15..ef993501f8 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -131,12 +131,10 @@ public: class GeometryChangeEvent : public WindowSystemEvent { public: - GeometryChangeEvent(QWindow *window, const QRect &newGeometry, const QRect &oldGeometry) - : WindowSystemEvent(GeometryChange), window(window), newGeometry(newGeometry), oldGeometry(oldGeometry) - { } + GeometryChangeEvent(QWindow *window, const QRect &newGeometry); QPointer<QWindow> window; + QRect requestedGeometry; QRect newGeometry; - QRect oldGeometry; }; class EnterEvent : public WindowSystemEvent { diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp index 69582a91d3..6aaf0d6d6d 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp @@ -41,6 +41,7 @@ #include <qpa/qwindowsysteminterface.h> #include <qpa/qplatformintegration.h> #include <private/qguiapplication_p.h> +#include <private/qwindow_p.h> #ifndef QT_NO_OPENGL # include <QtGui/private/qopenglcontext_p.h> # include <QtGui/QOpenGLContext> @@ -234,21 +235,19 @@ void QEglFSWindow::setVisible(bool visible) void QEglFSWindow::setGeometry(const QRect &r) { - QRect rect; - bool forceFullscreen = m_flags.testFlag(HasNativeWindow); - if (forceFullscreen) - rect = screen()->availableGeometry(); - else - rect = r; + // Persist the requested rect, like a normal setGeometry call + QPlatformWindow::setGeometry(r); - const bool changed = rect != QPlatformWindow::geometry(); - QPlatformWindow::setGeometry(rect); + // Take care of WM behavior, constrain/modify geometry + QRect rect = r; + if (m_flags.testFlag(HasNativeWindow)) + rect = screen()->availableGeometry(); - // if we corrected the size, trigger a resize event - if (rect != r) - QWindowSystemInterface::handleGeometryChange(window(), rect, r); + // React to the setGeometry, as if from a WM callback + QRect lastReportedGeometry = qt_window_private(window())->geometry; + QWindowSystemInterface::handleGeometryChange(window(), rect); - if (changed) + if (rect != lastReportedGeometry) QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size())); } diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index a1110839ad..dcdb5ae53f 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -151,19 +151,12 @@ qWarning() << m_qioswindow->window() << "is backed by a UIView that has a transform set. This is not supported."; - // The original geometry requested by setGeometry() might be different - // from what we end up with after applying window constraints. - QRect requestedGeometry = m_qioswindow->geometry(); - - QRect actualGeometry = QRectF::fromCGRect(self.frame).toRect(); - - QRect previousGeometry = requestedGeometry != actualGeometry ? - requestedGeometry : qt_window_private(m_qioswindow->window())->geometry; - QWindow *window = m_qioswindow->window(); - QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window, actualGeometry, previousGeometry); + QRect lastReportedGeometry = qt_window_private(window)->geometry; + QRect currentGeometry = QRectF::fromCGRect(self.frame).toRect(); + QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window, currentGeometry); - if (actualGeometry.size() != previousGeometry.size()) { + if (currentGeometry.size() != lastReportedGeometry.size()) { // Trigger expose event on resize [self setNeedsDisplay]; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index dc258a83f9..74c8f45b36 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2077,10 +2077,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * if (!newScreen) return; - // FIXME: In the case of the requestedGeometry not matching the actualGeometry due - // to e.g. the window manager applying restrictions to the geometry, the application - // will never see a move/resize event if the actualGeometry is the same as the current - // geometry, and may think the requested geometry was fulfilled. QWindowSystemInterface::handleGeometryChange(window(), actualGeometry); // QPlatformScreen::screen() is updated asynchronously, so we can't compare it |