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 set_changed; + wf::signal::connection_t grid_changed; + }; + + std::map> 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(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(); + 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 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 @@