Blame SOURCES/0035-Wayland-client-use-wl_keyboard-to-determine-active-s.patch

429548
From 5c180bdc1042e7cb1555e188051f09e219b00ec9 Mon Sep 17 00:00:00 2001
429548
From: =?UTF-8?q?M=C3=A9ven=20Car?= <meven.car@enioka.com>
429548
Date: Wed, 18 Aug 2021 18:28:20 +0200
429548
Subject: [PATCH 35/36] Wayland client: use wl_keyboard to determine active
429548
 state
429548
429548
Commit f497a5bb87270174b8e0106b7eca1992d44ff15d made QWaylandDisplay
429548
use the xdgshell's active state for QWindow::isActive(), instead of
429548
using wl_keyboard activate/deactivate events.
429548
429548
That seems to have been a misunderstanding, since xdgshell activation
429548
is only supposed to be used to determine visual appearance, and there
429548
is an explicit warning not to assume it means focus.
429548
429548
This commit reverts this logic back to listening to wl_keyboard.
429548
It adds a fallback when there is no wl_keyboard available to handle
429548
activated/deactivated events through xdg-shell, in order to fix
429548
QTBUG-53702.
429548
429548
windowStates is handled so that we're not using the Xdg hint for
429548
anything with QWindowSystemInterface::handleWindowStateChanged or
429548
anything where we need to track only having one active.
429548
429548
We are still exposing it for decorations, which is the only reason to
429548
use the Xdghint over keyboard focus - so you can keep the toplevel
429548
active whilst you show a popup.
429548
429548
cherry-pick 40036a1b80e5234e6db7d5cbeff122aa7ee13e20
429548
429548
Change-Id: I4343d2ed9fb5b066cde95628ed0b4ccc84a424db
429548
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
429548
---
429548
 src/client/qwaylanddisplay.cpp                | 19 +++++++++++--------
429548
 src/client/qwaylanddisplay_p.h                |  1 +
429548
 src/client/qwaylandwindow.cpp                 | 13 +++++++++++--
429548
 src/client/qwaylandwindow_p.h                 |  1 +
429548
 .../qwaylandshellintegration_p.h              |  7 +++----
429548
 .../qwaylandxdgshellv5integration.cpp         |  7 -------
429548
 .../qwaylandxdgshellv5integration_p.h         |  1 -
429548
 .../qwaylandxdgshellv6integration.cpp         | 14 --------------
429548
 .../qwaylandxdgshellv6integration_p.h         |  1 -
429548
 .../xdg-shell/qwaylandxdgshell.cpp            | 16 +++++-----------
429548
 .../xdg-shell/qwaylandxdgshellintegration.cpp | 14 --------------
429548
 .../xdg-shell/qwaylandxdgshellintegration_p.h |  1 -
429548
 tests/auto/client/xdgshell/tst_xdgshell.cpp   | 10 +++++++---
429548
 13 files changed, 39 insertions(+), 66 deletions(-)
429548
429548
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
429548
index e0dfe8b2..27303110 100644
429548
--- a/src/client/qwaylanddisplay.cpp
429548
+++ b/src/client/qwaylanddisplay.cpp
429548
@@ -575,14 +575,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
429548
     if (mLastKeyboardFocus == keyboardFocus)
429548
         return;
429548
 
429548
-    if (mWaylandIntegration->mShellIntegration) {
429548
-        mWaylandIntegration->mShellIntegration->handleKeyboardFocusChanged(keyboardFocus, mLastKeyboardFocus);
429548
-    } else {
429548
-        if (keyboardFocus)
429548
-            handleWindowActivated(keyboardFocus);
429548
-        if (mLastKeyboardFocus)
429548
-            handleWindowDeactivated(mLastKeyboardFocus);
429548
-    }
429548
+    if (keyboardFocus)
429548
+        handleWindowActivated(keyboardFocus);
429548
+    if (mLastKeyboardFocus)
429548
+        handleWindowDeactivated(mLastKeyboardFocus);
429548
 
429548
     mLastKeyboardFocus = keyboardFocus;
429548
 }
429548
@@ -627,6 +623,13 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
429548
     return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
429548
 }
429548
 
429548
+bool QWaylandDisplay::isKeyboardAvailable() const
429548
+{
429548
+    return std::any_of(
429548
+            mInputDevices.constBegin(), mInputDevices.constEnd(),
429548
+            [this](const QWaylandInputDevice *device) { return device->keyboard() != nullptr; });
429548
+}
429548
+
429548
 #if QT_CONFIG(cursor)
429548
 
429548
 QWaylandCursor *QWaylandDisplay::waylandCursor()
429548
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
429548
index 3b092bc8..09a1736a 100644
429548
--- a/src/client/qwaylanddisplay_p.h
429548
+++ b/src/client/qwaylanddisplay_p.h
429548
@@ -215,6 +215,7 @@ public:
429548
     void destroyFrameQueue(const FrameQueue &q);
429548
     void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1);
429548
 
429548
+    bool isKeyboardAvailable() const;
429548
 public slots:
429548
     void blockingReadEvents();
429548
     void flushRequests();
429548
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
429548
index c020a58f..ba881cb3 100644
429548
--- a/src/client/qwaylandwindow.cpp
429548
+++ b/src/client/qwaylandwindow.cpp
429548
@@ -96,7 +96,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
429548
 QWaylandWindow::~QWaylandWindow()
429548
 {
429548
     mDisplay->destroyFrameQueue(mFrameQueue);
429548
-    mDisplay->handleWindowDestroyed(this);
429548
 
429548
     delete mWindowDecoration;
429548
 
429548
@@ -266,6 +265,8 @@ void QWaylandWindow::reset()
429548
 
429548
     mMask = QRegion();
429548
     mQueuedBuffer = nullptr;
429548
+
429548
+    mDisplay->handleWindowDestroyed(this);
429548
 }
429548
 
429548
 QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
429548
@@ -1083,10 +1084,18 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
429548
     return true;
429548
 }
429548
 
429548
+Qt::WindowStates QWaylandWindow::windowStates() const
429548
+{
429548
+    return mLastReportedWindowStates;
429548
+}
429548
+
429548
 void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states)
429548
 {
429548
     createDecoration();
429548
-    QWindowSystemInterface::handleWindowStateChanged(window(), states, mLastReportedWindowStates);
429548
+    Qt::WindowStates statesWithoutActive = states & ~Qt::WindowActive;
429548
+    Qt::WindowStates lastStatesWithoutActive = mLastReportedWindowStates & ~Qt::WindowActive;
429548
+    QWindowSystemInterface::handleWindowStateChanged(window(), statesWithoutActive,
429548
+                                                     lastStatesWithoutActive);
429548
     mLastReportedWindowStates = states;
429548
 }
429548
 
429548
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
429548
index 6cc1664b..e0687962 100644
429548
--- a/src/client/qwaylandwindow_p.h
429548
+++ b/src/client/qwaylandwindow_p.h
429548
@@ -148,6 +148,7 @@ public:
429548
     void setWindowState(Qt::WindowStates states) override;
429548
     void setWindowFlags(Qt::WindowFlags flags) override;
429548
     void handleWindowStatesChanged(Qt::WindowStates states);
429548
+    Qt::WindowStates windowStates() const;
429548
 
429548
     void raise() override;
429548
     void lower() override;
429548
diff --git a/src/client/shellintegration/qwaylandshellintegration_p.h b/src/client/shellintegration/qwaylandshellintegration_p.h
429548
index ccad0048..4cc9b3b8 100644
429548
--- a/src/client/shellintegration/qwaylandshellintegration_p.h
429548
+++ b/src/client/shellintegration/qwaylandshellintegration_p.h
429548
@@ -73,11 +73,10 @@ public:
429548
         return true;
429548
     }
429548
     virtual QWaylandShellSurface *createShellSurface(QWaylandWindow *window) = 0;
429548
+    // kept for binary compat with layer-shell-qt
429548
     virtual void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
429548
-        if (newFocus)
429548
-            m_display->handleWindowActivated(newFocus);
429548
-        if (oldFocus)
429548
-            m_display->handleWindowDeactivated(oldFocus);
429548
+        Q_UNUSED(newFocus);
429548
+        Q_UNUSED(oldFocus);
429548
     }
429548
     virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) {
429548
         Q_UNUSED(resource);
429548
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
429548
index 4e25949f..cfc60939 100644
429548
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
429548
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
429548
@@ -85,13 +85,6 @@ QWaylandShellSurface *QWaylandXdgShellV5Integration::createShellSurface(QWayland
429548
     return m_xdgShell->createXdgSurface(window);
429548
 }
429548
 
429548
-void QWaylandXdgShellV5Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
429548
-    if (newFocus && qobject_cast<QWaylandXdgPopupV5 *>(newFocus->shellSurface()))
429548
-        m_display->handleWindowActivated(newFocus);
429548
-    if (oldFocus && qobject_cast<QWaylandXdgPopupV5 *>(oldFocus->shellSurface()))
429548
-        m_display->handleWindowDeactivated(oldFocus);
429548
-}
429548
-
429548
 }
429548
 
429548
 QT_END_NAMESPACE
429548
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
429548
index ce6bdb9e..aed88670 100644
429548
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
429548
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
429548
@@ -67,7 +67,6 @@ public:
429548
     QWaylandXdgShellV5Integration() {}
429548
     bool initialize(QWaylandDisplay *display) override;
429548
     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
429548
-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
429548
 
429548
 private:
429548
     QScopedPointer<QWaylandXdgShellV5> m_xdgShell;
429548
diff --git a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
429548
index 03164316..e8da8ba1 100644
429548
--- a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
429548
+++ b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
429548
@@ -68,20 +68,6 @@ QWaylandShellSurface *QWaylandXdgShellV6Integration::createShellSurface(QWayland
429548
     return m_xdgShell->getXdgSurface(window);
429548
 }
429548
 
429548
-void QWaylandXdgShellV6Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus)
429548
-{
429548
-    if (newFocus) {
429548
-        auto *xdgSurface = qobject_cast<QWaylandXdgSurfaceV6 *>(newFocus->shellSurface());
429548
-        if (xdgSurface && !xdgSurface->handlesActiveState())
429548
-            m_display->handleWindowActivated(newFocus);
429548
-    }
429548
-    if (oldFocus && qobject_cast<QWaylandXdgSurfaceV6 *>(oldFocus->shellSurface())) {
429548
-        auto *xdgSurface = qobject_cast<QWaylandXdgSurfaceV6 *>(oldFocus->shellSurface());
429548
-        if (xdgSurface && !xdgSurface->handlesActiveState())
429548
-            m_display->handleWindowDeactivated(oldFocus);
429548
-    }
429548
-}
429548
-
429548
 }
429548
 
429548
 QT_END_NAMESPACE
429548
diff --git a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
429548
index 261f8cbb..c1bcd5c6 100644
429548
--- a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
429548
+++ b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
429548
@@ -65,7 +65,6 @@ public:
429548
     QWaylandXdgShellV6Integration() {}
429548
     bool initialize(QWaylandDisplay *display) override;
429548
     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
429548
-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
429548
 
429548
 private:
429548
     QScopedPointer<QWaylandXdgShellV6> m_xdgShell;
429548
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
429548
index 7d33dabd..d7d0ddf7 100644
429548
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
429548
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
429548
@@ -67,11 +67,6 @@ QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface)
429548
 
429548
 QWaylandXdgSurface::Toplevel::~Toplevel()
429548
 {
429548
-    if (m_applied.states & Qt::WindowActive) {
429548
-        QWaylandWindow *window = m_xdgSurface->window();
429548
-        window->display()->handleWindowDeactivated(window);
429548
-    }
429548
-
429548
     // The protocol spec requires that the decoration object is deleted before xdg_toplevel.
429548
     delete m_decoration;
429548
     m_decoration = nullptr;
429548
@@ -85,16 +80,15 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
429548
     if (!(m_applied.states & (Qt::WindowMaximized|Qt::WindowFullScreen)))
429548
         m_normalSize = m_xdgSurface->m_window->windowFrameGeometry().size();
429548
 
429548
-    if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive))
429548
+    if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive)
429548
+        && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
429548
         m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window);
429548
 
429548
-    if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive))
429548
+    if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive)
429548
+        && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
429548
         m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window);
429548
 
429548
-    // TODO: none of the other plugins send WindowActive either, but is it on purpose?
429548
-    Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive;
429548
-
429548
-    m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive);
429548
+    m_xdgSurface->m_window->handleWindowStatesChanged(m_pending.states);
429548
 
429548
     if (m_pending.size.isEmpty()) {
429548
         // An empty size in the configure means it's up to the client to choose the size
429548
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
429548
index 8769d971..da0dd6a7 100644
429548
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
429548
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
429548
@@ -69,20 +69,6 @@ QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWi
429548
     return m_xdgShell->getXdgSurface(window);
429548
 }
429548
 
429548
-void QWaylandXdgShellIntegration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus)
429548
-{
429548
-    if (newFocus) {
429548
-        auto *xdgSurface = qobject_cast<QWaylandXdgSurface *>(newFocus->shellSurface());
429548
-        if (xdgSurface && !xdgSurface->handlesActiveState())
429548
-            m_display->handleWindowActivated(newFocus);
429548
-    }
429548
-    if (oldFocus && qobject_cast<QWaylandXdgSurface *>(oldFocus->shellSurface())) {
429548
-        auto *xdgSurface = qobject_cast<QWaylandXdgSurface *>(oldFocus->shellSurface());
429548
-        if (xdgSurface && !xdgSurface->handlesActiveState())
429548
-            m_display->handleWindowDeactivated(oldFocus);
429548
-    }
429548
-}
429548
-
429548
 }
429548
 
429548
 QT_END_NAMESPACE
429548
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
429548
index b6caa6c9..2f929f98 100644
429548
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
429548
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
429548
@@ -65,7 +65,6 @@ public:
429548
     QWaylandXdgShellIntegration() {}
429548
     bool initialize(QWaylandDisplay *display) override;
429548
     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
429548
-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
429548
 
429548
 private:
429548
     QScopedPointer<QWaylandXdgShell> m_xdgShell;
429548
diff --git a/tests/auto/client/xdgshell/tst_xdgshell.cpp b/tests/auto/client/xdgshell/tst_xdgshell.cpp
429548
index e2593314..73d1eb9c 100644
429548
--- a/tests/auto/client/xdgshell/tst_xdgshell.cpp
429548
+++ b/tests/auto/client/xdgshell/tst_xdgshell.cpp
429548
@@ -31,6 +31,7 @@
429548
 #include <QtGui/QOpenGLWindow>
429548
 #include <QtGui/qpa/qplatformnativeinterface.h>
429548
 #include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
429548
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
429548
 
429548
 using namespace MockCompositor;
429548
 
429548
@@ -155,9 +156,12 @@ void tst_xdgshell::configureStates()
429548
     // Toplevel windows don't know their position on xdg-shell
429548
 //    QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
429548
 
429548
-//    QEXPECT_FAIL("", "configure has already been acked, we shouldn't have to wait for isActive", Continue);
429548
-//    QVERIFY(window.isActive());
429548
-    QTRY_VERIFY(window.isActive()); // Just make sure it eventually get's set correctly
429548
+    // window.windowstate() is driven by keyboard focus, however for decorations we want to follow
429548
+    // XDGShell this is internal to QtWayland so it is queried directly
429548
+    auto waylandWindow = static_cast<QtWaylandClient::QWaylandWindow *>(window.handle());
429548
+    Q_ASSERT(waylandWindow);
429548
+    QTRY_VERIFY(waylandWindow->windowStates().testFlag(
429548
+            Qt::WindowActive)); // Just make sure it eventually get's set correctly
429548
 
429548
     const QSize screenSize(640, 480);
429548
     const uint maximizedSerial = exec([=] {
429548
-- 
429548
2.33.1
429548