summarylogtreecommitdiffstats
path: root/tray-na-xembed-Destroy-socket-window-when-ending-the-embe.patch
blob: e39c461dbef7d92c035afb355e2054ae8c7a2fae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
Date: Wed, 1 May 2024 05:56:48 +0200
Subject: tray/na-xembed: Destroy socket window when ending the embedding

Currently when embedding a tray icon is ended we are leaving the X11
socket window around as we don't really destroy it, while we're just
listening for its child destruction.

So, when embedding is ending we need to make sure that:
 - If the plug window is still alive, move it back to its old parent
   (normally that's the root window, but we query for it, to be sure)
 - If the plug window has been already destroyed or reparented (by us or
   by something else), we've to just destroy the socket window

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7614
(cherry picked from commit 50a6e1e3ceb18e52f87534507ccd49884d7f53eb)

Origin: https://gitlab.gnome.org/3v1n0/gnome-shell/-/commits/tray-offscreen-xwindows
Bug-Ubuntu: https://bugs.launchpad.net/bugs/2012388
---
 src/tray/na-xembed.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/src/tray/na-xembed.c b/src/tray/na-xembed.c
index 873d193..1d179af 100644
--- a/src/tray/na-xembed.c
+++ b/src/tray/na-xembed.c
@@ -36,6 +36,7 @@ struct _NaXembedPrivate
   MetaX11Display *x11_display;
   Window socket_window;
   Window plug_window;
+  Window old_parent;
 
   int root_x;
   int root_y;
@@ -140,7 +141,22 @@ na_xembed_end_embedding (NaXembed *xembed)
 {
   NaXembedPrivate *priv = na_xembed_get_instance_private (xembed);
 
+  if (priv->socket_window)
+    {
+      Display *xdisplay = meta_x11_display_get_xdisplay (priv->x11_display);
+
+      if (priv->plug_window && priv->old_parent)
+        XReparentWindow (xdisplay,
+                         priv->plug_window,
+                         priv->old_parent,
+                         0, 0);
+
+      XDestroyWindow (xdisplay, priv->socket_window);
+      priv->socket_window = None;
+    }
+
   priv->plug_window = None;
+  priv->old_parent = None;
   priv->current_width = 0;
   priv->current_height = 0;
   priv->resize_count = 0;
@@ -415,6 +431,18 @@ na_xembed_add_window (NaXembed  *xembed,
                        &socket_attrs);
 
       XUnmapWindow (xdisplay, priv->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */
+
+      if (!priv->old_parent)
+        {
+          g_autofree Window *children = NULL;
+          unsigned int n_children;
+          Window root;
+
+          if (!XQueryTree (xdisplay, priv->plug_window, &root, &priv->old_parent,
+                           &children, &n_children))
+            priv->old_parent = meta_x11_display_get_xroot (priv->x11_display);
+        }
+
       XReparentWindow (xdisplay,
                        priv->plug_window,
                        priv->socket_window,
@@ -565,10 +593,14 @@ xembed_filter_func (MetaX11Display *x11_display,
         /* Note that we get destroy notifies both from SubstructureNotify on
          * our window and StructureNotify on socket->plug_window
          */
+        if (priv->socket_window && xdwe->window == priv->socket_window)
+          priv->socket_window = None;
+
         if (priv->plug_window && (xdwe->window == priv->plug_window))
           {
             g_object_ref (xembed);
             g_signal_emit (xembed, signals[PLUG_REMOVED], 0);
+            priv->plug_window = None;
             na_xembed_end_embedding (xembed);
             g_object_unref (xembed);
           }
@@ -633,6 +665,7 @@ xembed_filter_func (MetaX11Display *x11_display,
           {
             g_object_ref (xembed);
             g_signal_emit (xembed, signals[PLUG_REMOVED], 0);
+            priv->old_parent = None;
             na_xembed_end_embedding (xembed);
             g_object_unref (xembed);
           }
@@ -698,7 +731,7 @@ na_xembed_finalize (GObject *object)
   if (priv->x11_display && priv->event_func_id)
     meta_x11_display_remove_event_func (priv->x11_display, priv->event_func_id);
 
-  if (priv->plug_window)
+  if (priv->plug_window || priv->socket_window)
     na_xembed_end_embedding (xembed);
 
   G_OBJECT_CLASS (na_xembed_parent_class)->finalize (object);