diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2017-06-28 13:56:47 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2017-07-07 18:09:43 +0000 |
commit | 3a31c708790ba2bb3cf3dab32a17a83659a1acde (patch) | |
tree | f0c58fbedbabfd83ab94ce30cfe1bd8daae10530 /src/gui/kernel | |
parent | 9381ca77b2e7b3224c7872828dbeb802e717e263 (diff) |
Ensure all platforms send geometry events if request was not fulfilled
The logic of deciding whether or not to send resize and move events
has been centralized in QGuiApplication. This ensures that if a
window with geometry 100,100+200x200 is moved and resized to e.g.
0,0+100x100, but the window manager denies the request (because the
window would e.g. overlap with system UI), and issues a geometry
update with the original geometry, 100,100+200x200, we will still
treat that as warrant of a move/resize event to the application,
so the application knows that its position and size is as before.
[ChangeLog][Qt Gui][QPA] QWindowSystemInterfacePrivate::handleGeometryChange
no longer takes the old geometry as an argument.
Task-number: QTBUG-57608
Change-Id: I1d471cc7a257fef958bdb1e56184fa95489403a3
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/gui/kernel')
-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 |
4 files changed, 42 insertions, 28 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 { |