Details
-
Suggestion
-
Resolution: Unresolved
-
Not Evaluated
-
None
-
None
-
None
Description
On Wayland, geometry updates occur asynchronously. With some protocols, Qt cannot resize until it receives an acknowledgement from the compositor. For example, one such protocol is layer-shell. In the layer-shell protocol, Qt needs to tell the compositor the desired size, then the compositor will re-layout the windows and tell Qt the size that it should paint at.
The problem is that if QWindow::move() is called while there are pending resize requests, the window may end up with a wrong size. It's due to QWindow::move() being implemented as setGeometry(newX, newY, oldWidth, oldHeight). QPA can't determine whether it's asked to move the window, resize the window, or both.
- QWindow::resize(geometryA.size()): call QWaylandWindow::setGeometry(), which in its turn will ask the compositor to resize the window to geometryA.size()
- QWindow::resize(geometryB.size()): call QWaylandWindow::setGeometry(), which in its turn will ask the compositor to resize the window to geometryB.size()
- the compositor has processed geometryA, and the window is resized to geometryA.size() by calling QWaylandWindow::setGeometry() (but with the code path that asks the compositor to resize the window disabled)
- QWindow::move(other position) -> it's going to result in the window also asking the compositor to resize it to geometryA.size()
- the compositor has processed geometryB, and the window is resized to geometryB.size()
- the compositor has processed geometryA (caused by QWindow::move()), and the window is resized to geometryA.size()
Ideally, such an asynchronous geometry issue would be fixed by introducing a new geometry, e.g. QWindow::desiredGeometry(), that would be used exclusively for window resizing. QWindow::geometry() would reflect the current geometry, it could be used for painting and input processing. A huge problem with it is that it's going to be a too API breaking design change even though it's a reasonable API choice in long term.
An alternative option might be to add QPlatformWindow::move() and QPlatformWindow::resize() functions so QPA has more context when it's requested to change the window geometry. This approach was attempted in https://github.com/zzag/qtbase/tree/work/zzag/qpa-move-resize and https://github.com/zzag/qtwayland/tree/work/zzag/qpa-move-resize, and it was confirmed that it helps to mitigate windows ending up with wrong size due to async geometry issues.