|
If the user moves the Dialog using the mouse, and then tries to resize
it (also using the mouse), they will observe two issues:
1. As soon as resizing was started, the dialog jumped to the coodrinate
specified by the x and y properties. Depending on the OS, it could
jump back after the resizing is finished (Windows), or stay at that
position (macOS).
2. If the resizing is started in such a way, that topLeft coordinate is
involved, it didn't actually change (apart from jumping as described
in point 1), but instead the width and height were changed in an
unintuitive way.
The first problem is caused by the fact that
QQuickPopupPositioner::reposition() method used x and y properties to
get the requested position. However, when the dialog is moved using
the mouse, only the effective position is updated.
The second problem is more involved.
When the user starts resizing from the topLeft corner, we end up in
QGuiApplicationPrivate::processGeometryChangeEvent(), which registers
that both resize and move events have happened. The code processes the
resize event first, so here's what happens:
1. The window geometry is updated (we'll use that fact later)
2. The resize event is generated and sent.
2.1. This resize event triggers QQuickPopupWindow::resizeEvent(),
which updates the popup item's width and height.
2.2. Each of width and height updates calls geometryChange(), which
ends up in QQuickPopup::geometryChange(). That, in turn, calls
QQuickPopupPositioner::reposition().
2.3. The reposition() call changes the position of the popupWindow
using the current topLeft value. IIUC, this schedules another
system geometry change event to the event loop.
3. After that we're back to QGuiApplicationPrivate, and generate the
move event.
3.1. This move event is handled in QQuickPopupWindow::moveEvent(),
which simply updates the effective position (without moving
anything).
4. After that we handle the move event from the reposition() call
(the one that is generated at point 2.3). And here we update the
effective position back to the old value.
To fix both issues, use the fact that the window's geometry is actually
updated at the very beginning (point 1 above), so we already know
the new topLeft when handling the resize event.
Use this value to temporary update x and y member variables (directly,
without touching the properties), before setting the width and height.
That means that the reposition() calls will use the proper top-left
position to do the positioning. Once we're done, restore the actual
x and y values, because they can differ from the effective pos.
The fix is sub-optimal, but seems to have the least possible impact
on other code (like normal Popup behavior or general geometry updates
handling).
Writing unit-tests for such case is not really possible, since the
testlib does not allow to simulate the interaction with the
non-client part of the window, so simply provide a manual test.
Fixes: QTBUG-130623
Pick-to: 6.8
Change-Id: I8209c8a648d95f3b83ae15a77b48bf04eeb1c154
Reviewed-by: Oliver Eftevaag <[email protected]>
|