Blob Blame History Raw
From d533901938a996367d7b6f87b0214f5a17098aed Mon Sep 17 00:00:00 2001
From: Jan Grulich <jgrulich@redhat.com>
Date: Tue, 23 Mar 2021 16:03:22 +0100
Subject: [PATCH] Client: expose toplevel window state

QWaylandWindow has only basic information about window state, like if
it's active or maximized, but it has no information about tiling, which
can be useful for client-side decorations. We also need to bump version
of xdg-shell protocol we support, because additional states are not in
the version currently supported by QtWayland. It shouldn't be a problem
to increase the version as the new version adds just these additional
window states.

Change-Id: I4c46516d9c7296c69ea51a022b3bdb4ca06bef8d
Reviewed-by: David Edmundson <davidedmundson@kde.org>
---
 src/client/qwaylandwindow.cpp                    | 15 +++++++++++++++
 src/client/qwaylandwindow_p.h                    | 16 ++++++++++++++++
 .../xdg-shell/qwaylandxdgshell.cpp               | 16 +++++++++++++++-
 .../xdg-shell/qwaylandxdgshell_p.h               |  3 ++-
 4 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index ba881cb..a1e891d 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -1089,6 +1089,16 @@ Qt::WindowStates QWaylandWindow::windowStates() const
     return mLastReportedWindowStates;
 }

+QWaylandWindow::ToplevelWindowTilingStates QWaylandWindow::toplevelWindowTilingStates() const
+{
+    return mLastReportedToplevelWindowTilingStates;
+}
+
+void QWaylandWindow::handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states)
+{
+    mLastReportedToplevelWindowTilingStates = states;
+}
+
 void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states)
 {
     createDecoration();
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index e068796..f4e5d3d 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -95,6 +95,15 @@ public:
         Vulkan
     };

+    enum ToplevelWindowTilingState {
+        WindowNoState = 0,
+        WindowTiledLeft = 1,
+        WindowTiledRight = 2,
+        WindowTiledTop = 4,
+        WindowTiledBottom = 8
+    };
+    Q_DECLARE_FLAGS(ToplevelWindowTilingStates, ToplevelWindowTilingState)
+
     QWaylandWindow(QWindow *window, QWaylandDisplay *display);
     ~QWaylandWindow() override;

@@ -145,6 +154,9 @@ public:
     void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
     void setOrientationMask(Qt::ScreenOrientations mask);

+    ToplevelWindowTilingStates toplevelWindowTilingStates() const;
+    void handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states);
+
     void setWindowState(Qt::WindowStates states) override;
     void setWindowFlags(Qt::WindowFlags flags) override;
     void handleWindowStatesChanged(Qt::WindowStates states);
@@ -257,6 +269,7 @@ protected:
     QRegion mMask;
     QRegion mOpaqueArea;
     Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState;
+    ToplevelWindowTilingStates mLastReportedToplevelWindowTilingStates = WindowNoState;

     QWaylandShmBackingStore *mBackingStore = nullptr;
     QWaylandBuffer *mQueuedBuffer = nullptr;
@@ -293,6 +306,8 @@ private:
     friend class QWaylandSubSurface;
 };

+Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandWindow::ToplevelWindowTilingStates)
+
 inline QIcon QWaylandWindow::windowIcon() const
 {
     return mWindowIcon;
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
index d7d0ddf..2c6e84b 100644
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
@@ -88,6 +88,7 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
         && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
         m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window);

+    m_xdgSurface->m_window->handleToplevelWindowTilingStatesChanged(m_toplevelStates);
     m_xdgSurface->m_window->handleWindowStatesChanged(m_pending.states);

     if (m_pending.size.isEmpty()) {
@@ -120,6 +121,7 @@ void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t
     size_t numStates = states->size / sizeof(uint32_t);

     m_pending.states = Qt::WindowNoState;
+    m_toplevelStates = QWaylandWindow::WindowNoState;

     for (size_t i = 0; i < numStates; i++) {
         switch (xdgStates[i]) {
@@ -132,6 +134,18 @@ void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t
         case XDG_TOPLEVEL_STATE_FULLSCREEN:
             m_pending.states |= Qt::WindowFullScreen;
             break;
+        case XDG_TOPLEVEL_STATE_TILED_LEFT:
+            m_toplevelStates |= QWaylandWindow::WindowTiledLeft;
+            break;
+        case XDG_TOPLEVEL_STATE_TILED_RIGHT:
+            m_toplevelStates |= QWaylandWindow::WindowTiledRight;
+            break;
+        case XDG_TOPLEVEL_STATE_TILED_TOP:
+            m_toplevelStates |= QWaylandWindow::WindowTiledTop;
+            break;
+        case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
+            m_toplevelStates |= QWaylandWindow::WindowTiledBottom;
+            break;
         default:
             break;
         }
@@ -451,7 +465,7 @@ void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial)
 }

 QWaylandXdgShell::QWaylandXdgShell(QWaylandDisplay *display, uint32_t id, uint32_t availableVersion)
-    : QtWayland::xdg_wm_base(display->wl_registry(), id, qMin(availableVersion, 1u))
+    : QtWayland::xdg_wm_base(display->wl_registry(), id, qMin(availableVersion, 2u))
     , m_display(display)
 {
     display->addRegistryListener(&QWaylandXdgShell::handleRegistryGlobal, this);
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
index 0c98be3..d791213 100644
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
@@ -58,6 +58,7 @@

 #include <QtWaylandClient/qtwaylandclientglobal.h>
 #include <QtWaylandClient/private/qwaylandshellsurface_p.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>

 #include <QtCore/QSize>
 #include <QtGui/QRegion>
@@ -69,7 +70,6 @@ class QWindow;
 namespace QtWaylandClient {

 class QWaylandDisplay;
-class QWaylandWindow;
 class QWaylandInputDevice;
 class QWaylandXdgShell;

@@ -123,6 +123,7 @@ private:
             QSize size = {0, 0};
             Qt::WindowStates states = Qt::WindowNoState;
         }  m_pending, m_applied;
+        QWaylandWindow::ToplevelWindowTilingStates m_toplevelStates = QWaylandWindow::WindowNoState;
         QSize m_normalSize;

         QWaylandXdgSurface *m_xdgSurface = nullptr;