summaryrefslogtreecommitdiffstats
path: root/src/client/qwaylandwindow_p.h
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2018-03-06 13:06:11 +0100
committerJohan Helsing <johan.helsing@qt.io>2018-05-07 11:34:41 +0000
commitc5ab40d2573fde27a14d7c05d8693966c65a400c (patch)
treed93c4647c90b0d72059b9148a6b4ca1d3f7cc272 /src/client/qwaylandwindow_p.h
parent9db98c7e0a2656988d5c549f0618b2ba882f1fc9 (diff)
Client: Add acked configure support and implement it for xdg-shell v6
The problem: The code in QWaylandWindow::setWindowStateInternal made many assumptions about how the shell surface responded to new window states, and when and if they were applied. Particularly: - The shell integrations support different subsets of Qt::WindowStates, so it doesn't make sense to map from states to setFullscreen, setNormal, etc. in QWaylandWindow because it really depends on the shell integration how it should be handled. - Some states are not supported/unknown on some shells and should immediately be rejected. - On some shells, particularly those where the current state is unknown, flags need to be resent even though they didn't change. - Should handleWindowStatesChanged be called immediately (client decides) or should it wait for a configure event (compositor decides)? I.e. the mState variable only makes sense for some shells. Furthermore, when state changes come from the compositors, some shell integrations require that a configure event is acked by the client and that the next committed buffer's size and content matches that configure event. Previously, we would just ack immediately and still send a buffer with the old size before a correct frame was drawn. i.e. sending incorrect acks, which would lead to protocol errors on some compositors. Additionally, QWaylandWindow::createDecoration() also assumed that windows should have decorations unless they are fullscreen. This is not always the case, particularly on ivi-application and probably on future shell integrations for embedded or tiling window managers etc. The Solution: The responsibility of mapping requested window states to Wayland requests have been moved to the QWaylandShellSurface implementation. QWaylandWindow now calls a new virtual, QWaylandShellSurface::requestWindowStates(Qt::WindowStates), instead of trying to be smart about it. The virtual getters and setters for window states have now been removed from the QWaylandShellSurface interface. It's now also the shell surface implementation's responsibility to call QWaylandWindow::handleWindowStatesChanged if and when it knows a new state is effective. QWaylandWindow::configure has been replaced with QWaylandWindow::applyConfigureWhenPossible(), which causes another new virtual, QWaylandShellSurface::applyConfigure(), to be called whenever we're free to resize and change the states of the next buffer (this is when states should be acked). This means that shells that use acked states need to store the pending states themselves, call applyConfigureWhenPossible(), wait for applyConfigure() to be called, call resizeFromApplyConfigure() and handleWindowStatesChanged(), and finally ack the applied state. Acked state for xdg-shell v5 and v6 has now been implemented, which also means we've now: [ChangeLog][QPA plugin] Implemented support for maximizing, minimizing, and setting fullscreen with xdg-shell unstable v6. [ChangeLog][QPA plugin] QWindow::isActive now follows configure events on xdg-shell unstable v6 (like v5). QWaylandWindow::createDecoration queries QWaylandShellSurface::wantsDecoration before creating window decorations, instead of using the previously unreliable QWaylandWindow::isFullscreen(). [ChangeLog][QPA plugin] Window decorations are now automatically disabled for ivi-application. The refactor also removes a couple of hacks: - QWindowSystemInterface::flushWindowSystemEvents() was called in QWaylandWindow::setWindowStates. Since this hack was introduced, the events now have oldState and newState members, and their values seem to make sense (ensured in the tests). - The hack for unminimizing on xdg-shell v5 in QWaylandWindow::createDecoration was not needed anymore. Finally, tests have been added for xdg-shell v6 to ensure that the right Wayland requests are sent, that we respond to configure events from the compositor, and that the Qt events and signals emitted on the client side make sense. Task-number: QTBUG-53702 Task-number: QTBUG-63417 Task-number: QTBUG-63748 Task-number: QTBUG-66928 Change-Id: Ib4c36b69105750f9dbdcc78adcf71e2e994cc70d Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src/client/qwaylandwindow_p.h')
-rw-r--r--src/client/qwaylandwindow_p.h36
1 files changed, 8 insertions, 28 deletions
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 3324bf700..55f3a515f 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -77,23 +77,6 @@ class QWaylandScreen;
class QWaylandShmBackingStore;
class QWaylandPointerEvent;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowConfigure
-{
-public:
- QWaylandWindowConfigure()
- { }
-
- void clear()
- { width = height = edges = 0; }
-
- bool isEmpty() const
- { return !height || !width; }
-
- int width = 0;
- int height = 0;
- uint32_t edges = 0;
-};
-
class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow, public QtWayland::wl_surface
{
Q_OBJECT
@@ -118,8 +101,9 @@ public:
void setWindowIcon(const QIcon &icon) override;
void setGeometry(const QRect &rect) override;
+ void resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset = {0, 0});
- void configure(uint32_t edges, int32_t width, int32_t height);
+ void applyConfigureWhenPossible(); //rename to possible?
using QtWayland::wl_surface::attach;
void attach(QWaylandBuffer *buffer, int x, int y);
@@ -145,8 +129,9 @@ public:
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
void setOrientationMask(Qt::ScreenOrientations mask);
- void setWindowState(Qt::WindowStates state) override;
+ void setWindowState(Qt::WindowStates states) override;
void setWindowFlags(Qt::WindowFlags flags) override;
+ void handleWindowStatesChanged(Qt::WindowStates states);
void raise() override;
void lower() override;
@@ -170,9 +155,6 @@ public:
bool createDecoration();
- inline bool isMaximized() const { return mState & Qt::WindowMaximized; }
- inline bool isFullscreen() const { return mState & Qt::WindowFullScreen; }
-
#if QT_CONFIG(cursor)
void setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor);
void restoreMouseCursor(QWaylandInputDevice *device);
@@ -181,7 +163,7 @@ public:
QWaylandWindow *transientParent() const;
QMutex *resizeMutex() { return &mResizeLock; }
- void doResize();
+ void doApplyConfigure();
void setCanResize(bool canResize);
bool setMouseGrabEnabled(bool grab) override;
@@ -206,7 +188,7 @@ public:
void requestUpdate() override;
public slots:
- void requestResize();
+ void applyConfigure();
protected:
void surface_enter(struct ::wl_output *output) override;
@@ -228,8 +210,7 @@ protected:
QWaitCondition mFrameSyncWait;
QMutex mResizeLock;
- QWaylandWindowConfigure mConfigure;
- bool mRequestResizeSent = false;
+ bool mWaitingToApplyConfigure = false;
bool mCanResize = true;
bool mResizeDirty = false;
bool mResizeAfterSwap;
@@ -241,9 +222,9 @@ protected:
QIcon mWindowIcon;
- Qt::WindowStates mState = Qt::WindowNoState;
Qt::WindowFlags mFlags;
QRegion mMask;
+ Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState;
QWaylandShmBackingStore *mBackingStore = nullptr;
@@ -251,7 +232,6 @@ private slots:
void handleScreenRemoved(QScreen *qScreen);
private:
- bool setWindowStateInternal(Qt::WindowStates flags);
void setGeometry_helper(const QRect &rect);
void initWindow();
void initializeWlSurface();