https://invent.kde.org/plasma/kwin/-/merge_requests/7497

From de5253a788841179a9f167476d34ae0747ce0d67 Mon Sep 17 00:00:00 2001
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
Date: Fri, 4 Apr 2025 14:34:32 +0300
Subject: [PATCH] Simplify xwayland surface association

When kwin starts managing or tracking an X11 window, there should not be
any wl_surface associated with the X11 window.

While on this, also slightly rewire the code so the associate() function
is not called indirectly by setSurface(). It allows us to find all relevant
places where the wl_surface is associated by using code navigation tools
such as "find all references".

(cherry picked from commit cbb86e609b7b39042fb666f6a736f28196ad2cea)
---
 src/events.cpp         |  2 +-
 src/wayland_server.cpp |  4 ++--
 src/x11window.cpp      | 15 ++++-----------
 src/x11window.h        |  4 +++-
 4 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/src/events.cpp b/src/events.cpp
index 6f73c712631..b3afa19ead6 100644
--- a/src/events.cpp
+++ b/src/events.cpp
@@ -658,7 +658,7 @@ void X11Window::clientMessageEvent(xcb_client_message_event_t *e)
         m_surfaceSerial = (uint64_t(e->data.data32[1]) << 32) | e->data.data32[0];
         if (auto w = waylandServer()) {
             if (XwaylandSurfaceV1Interface *xwaylandSurface = w->xwaylandShell()->findSurface(m_surfaceSerial)) {
-                setSurface(xwaylandSurface->surface());
+                associate(xwaylandSurface);
             }
         }
     }
diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp
index 1278713b8d1..6bd34758442 100644
--- a/src/wayland_server.cpp
+++ b/src/wayland_server.cpp
@@ -350,7 +350,7 @@ bool WaylandServer::init()
             return window->surfaceSerial() == surface->serial();
         });
         if (window) {
-            window->setSurface(surface->surface());
+            window->associate(surface);
             return;
         }
 
@@ -358,7 +358,7 @@ bool WaylandServer::init()
             return window->surfaceSerial() == surface->serial();
         });
         if (unmanaged) {
-            unmanaged->setSurface(surface->surface());
+            unmanaged->associate(surface);
             return;
         }
     });
diff --git a/src/x11window.cpp b/src/x11window.cpp
index 1a5c4c16fb2..ab9410bc7a9 100644
--- a/src/x11window.cpp
+++ b/src/x11window.cpp
@@ -33,6 +33,7 @@
 #include "tiles/tilemanager.h"
 #include "virtualdesktops.h"
 #include "wayland/surface.h"
+#include "wayland/xwaylandshell_v1.h"
 #include "wayland_server.h"
 #include "workspace.h"
 #include <KDecoration3/DecoratedWindow>
@@ -588,11 +589,6 @@ bool X11Window::track(xcb_window_t w)
     switch (kwinApp()->operationMode()) {
     case Application::OperationModeWayland:
         // The wayland surface is associated with the override-redirect window asynchronously.
-        if (surface()) {
-            associate();
-        } else {
-            connect(this, &Window::surfaceChanged, this, &X11Window::associate);
-        }
         break;
     case Application::OperationModeX11:
         // We have no way knowing whether the override-redirect window can be painted. Mark it
@@ -1207,11 +1203,6 @@ bool X11Window::manage(xcb_window_t w, bool isMapped)
     switch (kwinApp()->operationMode()) {
     case Application::OperationModeWayland:
         // The wayland surface is associated with the window asynchronously.
-        if (surface()) {
-            associate();
-        } else {
-            connect(this, &Window::surfaceChanged, this, &X11Window::associate);
-        }
         connect(kwinApp(), &Application::xwaylandScaleChanged, this, &X11Window::handleXwaylandScaleChanged);
         break;
     case Application::OperationModeX11:
@@ -5027,8 +5018,10 @@ void X11Window::updateWindowPixmap()
     }
 }
 
-void X11Window::associate()
+void X11Window::associate(XwaylandSurfaceV1Interface *shellSurface)
 {
+    setSurface(shellSurface->surface());
+
     if (surface()->isMapped()) {
         if (m_syncRequest.acked) {
             finishSync();
diff --git a/src/x11window.h b/src/x11window.h
index 797f600d4fb..d97f93764c1 100644
--- a/src/x11window.h
+++ b/src/x11window.h
@@ -39,6 +39,7 @@ namespace KWin
 {
 
 class KillPrompt;
+class XwaylandSurfaceV1Interface;
 
 /**
  * @brief Defines Predicates on how to search for a Client.
@@ -82,6 +83,8 @@ public:
     explicit X11Window();
     ~X11Window() override; ///< Use destroyWindow() or releaseWindow()
 
+    void associate(XwaylandSurfaceV1Interface *shellSurface);
+
     xcb_window_t frameId() const;
     xcb_window_t window() const;
     xcb_window_t wrapperId() const;
@@ -439,7 +442,6 @@ private:
 
     QWindow *findInternalWindow() const;
     void checkOutput();
-    void associate();
     void handleXwaylandScaleChanged();
     void handleCommitted();
 
-- 
GitLab
