summaryrefslogtreecommitdiff
path: root/gui-libs/wayfire-plugins-extra/files/wayfire-plugins-extra-0.11.2-join-views-multi-view.patch
blob: 9689ad1ab60a7532b0a5d3f3e7a9313c1432d5a4 (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
--- a/src/join-views.cpp
+++ b/src/join-views.cpp
@@ -1,3 +1,5 @@
+#include <map>
+#include <memory>
 #include <wayfire/signal-definitions.hpp>
 #include <wayfire/per-output-plugin.hpp>
 #include <wayfire/plugins/common/shared-core-data.hpp>
@@ -5,41 +7,62 @@
 
 class JoinViewsSingleton
 {
+    /* One geometry-changed connection per mapped view, so every parent keeps
+     * positioning its children -- not just the most recently mapped view. */
+    using geometry_conn_t = wf::signal::connection_t<wf::view_geometry_changed_signal>;
+    std::map<wf::view_interface_t*, std::shared_ptr<geometry_conn_t>> geometry_conns;
+
+    void reposition_children(wayfire_toplevel_view view)
+    {
+        if (!view || !view->is_mapped())
+        {
+            return;
+        }
+
+        auto parent_geometry = view->get_pending_geometry();
+        int cx = parent_geometry.x + parent_geometry.width / 2;
+        int cy = parent_geometry.y + parent_geometry.height / 2;
+        for (auto child : view->children)
+        {
+            auto target = child->get_pending_geometry();
+            target.x = cx - target.width / 2;
+            target.y = cy - target.height / 2;
+            child->set_geometry(target);
+        }
+    }
+
   public:
-    wf::signal::connection_t<wf::view_geometry_changed_signal> on_geometry_changed{[=
-        ] (wf::view_geometry_changed_signal *ev)
+    wf::signal::connection_t<wf::view_mapped_signal> on_view_map{[=] (wf::view_mapped_signal *ev)
         {
-            auto view = wf::toplevel_cast(ev->view);
-            if (!view || !view->is_mapped())
+            auto view = ev->view;
+            if (!view || geometry_conns.count(view.get()))
             {
                 return;
             }
 
-            auto parent_geometry = view->get_pending_geometry();
-            int cx = parent_geometry.x + parent_geometry.width / 2;
-            int cy = parent_geometry.y + parent_geometry.height / 2;
-            for (auto child : view->children)
+            auto conn = std::make_shared<geometry_conn_t>(
+                [=] (wf::view_geometry_changed_signal *gev)
             {
-                auto target = child->get_pending_geometry();
-                target.x = cx - target.width / 2;
-                target.y = cy - target.height / 2;
-                child->set_geometry(target);
-            }
+                reposition_children(gev->view);
+            });
+            view->connect(conn.get());
+            geometry_conns[view.get()] = conn;
         }
     };
 
-    wf::signal::connection_t<wf::view_mapped_signal> on_view_map{[=] (wf::view_mapped_signal *ev)
+    wf::signal::connection_t<wf::view_unmapped_signal> on_view_unmap{[=] (wf::view_unmapped_signal *ev)
         {
-            auto view = ev->view;
-            /* Make sure only a single connection is made */
-            on_geometry_changed.disconnect();
-            view->connect(&on_geometry_changed);
+            if (ev->view)
+            {
+                geometry_conns.erase(ev->view.get());
+            }
         }
     };
 
     void handle_new_output(wf::output_t *output)
     {
         output->connect(&on_view_map);
+        output->connect(&on_view_unmap);
     }
 
     JoinViewsSingleton()