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
110
111
|
diff --git a/plugins/ipc-rules/ipc-events.hpp b/plugins/ipc-rules/ipc-events.hpp
index 7ad265a..c8bcbf4 100644
--- a/plugins/ipc-rules/ipc-events.hpp
+++ b/plugins/ipc-rules/ipc-events.hpp
@@ -41,6 +41,7 @@ class ipc_rules_events_methods_t : public wf::per_output_tracker_mixin_t<>
method_repository->unregister_method("window-rules/events/watch");
method_repository->unregister_method("window-rules/unblock-map");
fini_output_tracking();
+ grid_watches.clear();
}
void handle_new_output(wf::output_t *output) override
@@ -55,7 +56,68 @@ class ipc_rules_events_methods_t : public wf::per_output_tracker_mixin_t<>
}
void handle_output_removed(wf::output_t *output) override
- {}
+ {
+ grid_watches.erase(output);
+ }
+
+ // Grid signals belong to workspace sets, not outputs. Follow the currently
+ // attached set, and disconnect before an output or subscription disappears.
+ struct grid_watch_t
+ {
+ wf::signal::connection_t<wf::workspace_set_changed_signal> set_changed;
+ wf::signal::connection_t<wf::workspace_grid_changed_signal> grid_changed;
+ };
+
+ std::map<wf::output_t*, std::unique_ptr<grid_watch_t>> grid_watches;
+
+ void bind_workspace_grid(wf::output_t *output)
+ {
+ auto& watch = *grid_watches.at(output);
+ watch.grid_changed.disconnect();
+ auto wset = output->wset();
+ if (!wset)
+ {
+ return;
+ }
+
+ watch.grid_changed = [this, output, weak = std::weak_ptr<wf::workspace_set_t>(wset)]
+ (wf::workspace_grid_changed_signal *ev)
+ {
+ auto set = weak.lock();
+ if (!set || output->wset() != set)
+ {
+ return;
+ }
+
+ wf::json_t data;
+ data["event"] = "wset-grid-changed";
+ data["output"] = (int)output->get_id();
+ data["wset"] = (int)set->get_id();
+ data["previous-grid"] = wf::ipc::dimensions_to_json(ev->old_grid_size);
+ data["new-grid"] = wf::ipc::dimensions_to_json(ev->new_grid_size);
+ data["output-data"] = ipc_rules::output_to_json(output);
+ data["wset-data"] = ipc_rules::wset_to_json(set.get());
+ send_event_to_subscribes(data, "wset-grid-changed");
+ };
+ wset->connect(&watch.grid_changed);
+ }
+
+ void watch_workspace_grid(wf::output_t *output)
+ {
+ if (grid_watches.count(output))
+ {
+ return;
+ }
+
+ auto watch = std::make_unique<grid_watch_t>();
+ watch->set_changed = [this, output] (wf::workspace_set_changed_signal*)
+ {
+ bind_workspace_grid(output);
+ };
+ output->connect(&watch->set_changed);
+ grid_watches[output] = std::move(watch);
+ bind_workspace_grid(output);
+ }
wf::signal::connection_t<wf::ipc_rules::detail::custom_event_signal_t> on_custom_event =
[=] (wf::ipc_rules::detail::custom_event_signal_t *ev)
@@ -155,6 +217,10 @@ class ipc_rules_events_methods_t : public wf::per_output_tracker_mixin_t<>
{"view-workspace-changed", get_generic_output_registration_cb(&_view_workspace)},
{"output-wset-changed", get_generic_output_registration_cb(&on_wset_changed)},
{"wset-workspace-changed", get_generic_output_registration_cb(&on_wset_workspace_changed)},
+ {"wset-grid-changed", {
+ .register_output = [this] (wf::output_t *output) { watch_workspace_grid(output); },
+ .unregister = [this] () { grid_watches.clear(); },
+ }},
};
struct client_watch_state_t
diff --git a/metadata/core.xml b/metadata/core.xml
--- a/metadata/core.xml
+++ b/metadata/core.xml
@@ -45,13 +45,13 @@
<option name="vwidth" type="int">
<_short>Horizontal virtual size</_short>
- <_long>Sets the number of horizontal workspaces. Currently, cannot be changed at runtime.</_long>
+ <_long>Sets the number of horizontal workspaces. Changes apply at runtime; the current workspace and windows on removed workspaces are kept within the remaining grid.</_long>
<default>3</default>
<min>1</min>
</option>
<option name="vheight" type="int">
<_short>Vertical virtual size</_short>
- <_long>Sets the number of vertical workspaces. Currently, cannot be changed at runtime.</_long>
+ <_long>Sets the number of vertical workspaces. Changes apply at runtime; the current workspace and windows on removed workspaces are kept within the remaining grid.</_long>
<default>3</default>
<min>1</min>
</option>
|