125b51e
From d533901938a996367d7b6f87b0214f5a17098aed Mon Sep 17 00:00:00 2001
125b51e
From: Jan Grulich <jgrulich@redhat.com>
125b51e
Date: Tue, 23 Mar 2021 16:03:22 +0100
125b51e
Subject: [PATCH] Client: expose toplevel window state
125b51e
125b51e
QWaylandWindow has only basic information about window state, like if
125b51e
it's active or maximized, but it has no information about tiling, which
125b51e
can be useful for client-side decorations. We also need to bump version
125b51e
of xdg-shell protocol we support, because additional states are not in
125b51e
the version currently supported by QtWayland. It shouldn't be a problem
125b51e
to increase the version as the new version adds just these additional
125b51e
window states.
125b51e
125b51e
Change-Id: I4c46516d9c7296c69ea51a022b3bdb4ca06bef8d
125b51e
Reviewed-by: David Edmundson <davidedmundson@kde.org>
125b51e
---
125b51e
 src/client/qwaylandwindow.cpp                    | 15 +++++++++++++++
125b51e
 src/client/qwaylandwindow_p.h                    | 16 ++++++++++++++++
125b51e
 .../xdg-shell/qwaylandxdgshell.cpp               | 16 +++++++++++++++-
125b51e
 .../xdg-shell/qwaylandxdgshell_p.h               |  3 ++-
125b51e
 4 files changed, 48 insertions(+), 2 deletions(-)
125b51e
125b51e
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
125b51e
index c35ccab15..65a914976 100644
125b51e
--- a/src/client/qwaylandwindow.cpp
125b51e
+++ b/src/client/qwaylandwindow.cpp
125b51e
@@ -1107,6 +1107,21 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
125b51e
     return true;
125b51e
 }
125b51e
125b51e
+QWaylandWindow::ToplevelWindowTilingStates QWaylandWindow::toplevelWindowTilingStates() const
125b51e
+{
125b51e
+    return mLastReportedToplevelWindowTilingStates;
125b51e
+}
125b51e
+
125b51e
+void QWaylandWindow::handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states)
125b51e
+{
125b51e
+    mLastReportedToplevelWindowTilingStates = states;
125b51e
+}
125b51e
+
125b51e
+Qt::WindowStates QWaylandWindow::windowStates() const
125b51e
+{
125b51e
+    return mLastReportedWindowStates;
125b51e
+}
125b51e
+
125b51e
 void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states)
125b51e
 {
125b51e
     createDecoration();
125b51e
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
125b51e
index 5f134568b..1d743f4e4 100644
125b51e
--- a/src/client/qwaylandwindow_p.h
125b51e
+++ b/src/client/qwaylandwindow_p.h
125b51e
@@ -95,6 +95,15 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformW
125b51e
         Vulkan
125b51e
     };
125b51e
125b51e
+    enum ToplevelWindowTilingState {
125b51e
+        WindowNoState = 0,
125b51e
+        WindowTiledLeft = 1,
125b51e
+        WindowTiledRight = 2,
125b51e
+        WindowTiledTop = 4,
125b51e
+        WindowTiledBottom = 8
125b51e
+    };
125b51e
+    Q_DECLARE_FLAGS(ToplevelWindowTilingStates, ToplevelWindowTilingState)
125b51e
+
125b51e
     QWaylandWindow(QWindow *window, QWaylandDisplay *display);
125b51e
     ~QWaylandWindow() override;
125b51e
125b51e
@@ -145,6 +154,10 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformW
125b51e
     void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
125b51e
     void setOrientationMask(Qt::ScreenOrientations mask);
125b51e
125b51e
+    ToplevelWindowTilingStates toplevelWindowTilingStates() const;
125b51e
+    void handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states);
125b51e
+
125b51e
+    Qt::WindowStates windowStates() const;
125b51e
     void setWindowState(Qt::WindowStates states) override;
125b51e
     void setWindowFlags(Qt::WindowFlags flags) override;
125b51e
     void handleWindowStatesChanged(Qt::WindowStates states);
125b51e
@@ -260,6 +273,7 @@ public slots:
125b51e
     QRegion mMask;
125b51e
     QRegion mOpaqueArea;
125b51e
     Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState;
125b51e
+    ToplevelWindowTilingStates mLastReportedToplevelWindowTilingStates = WindowNoState;
125b51e
125b51e
     QWaylandShmBackingStore *mBackingStore = nullptr;
125b51e
     QWaylandBuffer *mQueuedBuffer = nullptr;
125b51e
@@ -295,6 +309,8 @@ public slots:
125b51e
     friend class QWaylandSubSurface;
125b51e
 };
125b51e
125b51e
+Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandWindow::ToplevelWindowTilingStates)
125b51e
+
125b51e
 inline QIcon QWaylandWindow::windowIcon() const
125b51e
 {
125b51e
     return mWindowIcon;
125b51e
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
125b51e
index 965bc261d..5d9a21f81 100644
125b51e
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
125b51e
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
125b51e
@@ -94,6 +94,7 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
125b51e
     // TODO: none of the other plugins send WindowActive either, but is it on purpose?
125b51e
     Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive;
125b51e
125b51e
+    m_xdgSurface->m_window->handleToplevelWindowTilingStatesChanged(m_toplevelStates);
125b51e
     m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive);
125b51e
125b51e
     if (m_pending.size.isEmpty()) {
125b51e
@@ -126,6 +127,7 @@ void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t
125b51e
     size_t numStates = states->size / sizeof(uint32_t);
125b51e
125b51e
     m_pending.states = Qt::WindowNoState;
125b51e
+    m_toplevelStates = QWaylandWindow::WindowNoState;
125b51e
125b51e
     for (size_t i = 0; i < numStates; i++) {
125b51e
         switch (xdgStates[i]) {
125b51e
@@ -138,6 +140,18 @@ void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t
125b51e
         case XDG_TOPLEVEL_STATE_FULLSCREEN:
125b51e
             m_pending.states |= Qt::WindowFullScreen;
125b51e
             break;
125b51e
+        case XDG_TOPLEVEL_STATE_TILED_LEFT:
125b51e
+            m_toplevelStates |= QWaylandWindow::WindowTiledLeft;
125b51e
+            break;
125b51e
+        case XDG_TOPLEVEL_STATE_TILED_RIGHT:
125b51e
+            m_toplevelStates |= QWaylandWindow::WindowTiledRight;
125b51e
+            break;
125b51e
+        case XDG_TOPLEVEL_STATE_TILED_TOP:
125b51e
+            m_toplevelStates |= QWaylandWindow::WindowTiledTop;
125b51e
+            break;
125b51e
+        case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
125b51e
+            m_toplevelStates |= QWaylandWindow::WindowTiledBottom;
125b51e
+            break;
125b51e
         default:
125b51e
             break;
125b51e
         }
125b51e
@@ -469,7 +483,7 @@ void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial)
125b51e
 }
125b51e
125b51e
 QWaylandXdgShell::QWaylandXdgShell(QWaylandDisplay *display, uint32_t id, uint32_t availableVersion)
125b51e
-    : QtWayland::xdg_wm_base(display->wl_registry(), id, qMin(availableVersion, 1u))
125b51e
+    : QtWayland::xdg_wm_base(display->wl_registry(), id, qMin(availableVersion, 2u))
125b51e
     , m_display(display)
125b51e
 {
125b51e
     display->addRegistryListener(&QWaylandXdgShell::handleRegistryGlobal, this);
125b51e
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
125b51e
index 5aeec2eb9..e3a90c547 100644
125b51e
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
125b51e
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
125b51e
@@ -58,6 +58,7 @@
125b51e
125b51e
 #include <QtWaylandClient/qtwaylandclientglobal.h>
125b51e
 #include <QtWaylandClient/private/qwaylandshellsurface_p.h>
125b51e
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
125b51e
125b51e
 #include <QtCore/QSize>
125b51e
 #include <QtGui/QRegion>
125b51e
@@ -69,7 +70,6 @@ class QWindow;
125b51e
 namespace QtWaylandClient {
125b51e
125b51e
 class QWaylandDisplay;
125b51e
-class QWaylandWindow;
125b51e
 class QWaylandInputDevice;
125b51e
 class QWaylandXdgShell;
125b51e
125b51e
@@ -125,6 +125,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgSurface : public QWaylandShellSurface,
125b51e
             QSize size = {0, 0};
125b51e
             Qt::WindowStates states = Qt::WindowNoState;
125b51e
         }  m_pending, m_applied;
125b51e
+        QWaylandWindow::ToplevelWindowTilingStates m_toplevelStates = QWaylandWindow::WindowNoState;
125b51e
         QSize m_normalSize;
125b51e
125b51e
         QWaylandXdgSurface *m_xdgSurface = nullptr;