Skip to content

Commit

Permalink
ipc-rules: add mechanism to connect signals only when a subscriber is…
Browse files Browse the repository at this point in the history
… really there (#2267)
  • Loading branch information
ammen99 authored Mar 26, 2024
1 parent d257b5a commit 8364a65
Showing 1 changed file with 104 additions and 68 deletions.
172 changes: 104 additions & 68 deletions plugins/single_plugins/ipc-rules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,16 +148,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
method_repository->register_method("window-rules/get-focused-output", get_focused_output);
method_repository->register_method("window-rules/close-view", close_view);
method_repository->connect(&on_client_disconnected);
wf::get_core().connect(&on_view_mapped);
wf::get_core().connect(&on_view_unmapped);
wf::get_core().connect(&on_view_set_output);
wf::get_core().connect(&on_view_geometry_changed);
wf::get_core().connect(&on_view_moved_to_wset);
wf::get_core().connect(&on_kbfocus_changed);
wf::get_core().connect(&on_title_changed);
wf::get_core().connect(&on_app_id_changed);
wf::get_core().connect(&on_plugin_activation_changed);
wf::get_core().connect(&on_output_gain_focus);
init_output_tracking();
}

Expand All @@ -183,13 +173,13 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker

void handle_new_output(wf::output_t *output) override
{
output->connect(&_tiled);
output->connect(&_minimized);
output->connect(&_fullscreened);
output->connect(&_stickied);
output->connect(&_view_workspace);
output->connect(&on_wset_changed);
output->connect(&on_wset_workspace_changed);
for (auto& [_, event] : signal_map)
{
if (event.connected_count)
{
event.register_output(output);
}
}

nlohmann::json data;
data["event"] = "output-added";
Expand All @@ -205,6 +195,83 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
send_event_to_subscribes(data, data["event"]);
}

// Template FOO for efficient management of signals: ensure that only actually listened-for signals
// are connected.
struct signal_registration_handler
{
std::function<void()> register_core = [] () {};
std::function<void(wf::output_t*)> register_output = [] (wf::output_t*) {};
std::function<void()> unregister = [] () {};
int connected_count = 0;

void increase_count()
{
connected_count++;
if (connected_count > 1)
{
return;
}

register_core();
for (auto& wo : wf::get_core().output_layout->get_outputs())
{
register_output(wo);
}
}

void decrease_count()
{
connected_count--;
if (connected_count > 0)
{
return;
}

unregister();
}
};

template<class Signal>
static signal_registration_handler get_generic_core_registration_cb(
wf::signal::connection_t<Signal> *conn)
{
return {
.register_core = [=] () { wf::get_core().connect(conn); },
.unregister = [=] () { conn->disconnect(); }
};
}

template<class Signal>
signal_registration_handler get_generic_output_registration_cb(wf::signal::connection_t<Signal> *conn)
{
return {
.register_output = [=] (wf::output_t *wo) { wo->connect(conn); },
.unregister = [=] () { conn->disconnect(); }
};
}

std::map<std::string, signal_registration_handler> signal_map =
{
{"view-mapped", get_generic_core_registration_cb(&on_view_mapped)},
{"view-unmapped", get_generic_core_registration_cb(&on_view_unmapped)},
{"view-set-output", get_generic_core_registration_cb(&on_view_set_output)},
{"view-geometry-changed", get_generic_core_registration_cb(&on_view_geometry_changed)},
{"view-wset-changed", get_generic_core_registration_cb(&on_view_moved_to_wset)},
{"view-focused", get_generic_core_registration_cb(&on_kbfocus_changed)},
{"view-title-changed", get_generic_core_registration_cb(&on_title_changed)},
{"view-app-id-changed", get_generic_core_registration_cb(&on_app_id_changed)},
{"plugin-activation-state-changed", get_generic_core_registration_cb(&on_plugin_activation_changed)},
{"output-gain-focus", get_generic_core_registration_cb(&on_output_gain_focus)},

{"view-tiled", get_generic_output_registration_cb(&_tiled)},
{"view-minimized", get_generic_output_registration_cb(&_minimized)},
{"view-fullscreened", get_generic_output_registration_cb(&_fullscreened)},
{"view-sticky", get_generic_output_registration_cb(&_stickied)},
{"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)},
};

wf::ipc::method_callback get_wayfire_configuration_info = [=] (nlohmann::json)
{
nlohmann::json response;
Expand Down Expand Up @@ -467,27 +534,41 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
return wf::ipc::json_error("Event list contains non-string entries!");
}

subscribed_to.insert((std::string)sub);
if (signal_map.count(sub))
{
subscribed_to.insert((std::string)sub);
}
}
} else
{
for (auto& [ev_name, _] : signal_map)
{
subscribed_to.insert(ev_name);
}
}

for (auto& ev_name : subscribed_to)
{
signal_map[ev_name].increase_count();
}

clients[client] = subscribed_to;
return wf::ipc::json_ok();
};

wf::signal::connection_t<wf::ipc::client_disconnected_signal> on_client_disconnected =
[=] (wf::ipc::client_disconnected_signal *ev)
{
for (auto& ev_name : clients[ev->client])
{
signal_map[ev_name].decrease_count();
}

clients.erase(ev->client);
};

void send_view_to_subscribes(wayfire_view view, std::string event_name)
{
if (clients.empty())
{
return;
}

nlohmann::json event;
event["event"] = event_name;
event["view"] = view_to_json(view);
Expand Down Expand Up @@ -518,11 +599,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
wf::signal::connection_t<wf::view_set_output_signal> on_view_set_output =
[=] (wf::view_set_output_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "view-set-output";
data["output"] = output_to_json(ev->output);
Expand All @@ -533,11 +609,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
wf::signal::connection_t<wf::view_geometry_changed_signal> on_view_geometry_changed =
[=] (wf::view_geometry_changed_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "view-geometry-changed";
data["old-geometry"] = wf::ipc::geometry_to_json(ev->old_geometry);
Expand All @@ -548,11 +619,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
wf::signal::connection_t<wf::view_moved_to_wset_signal> on_view_moved_to_wset =
[=] (wf::view_moved_to_wset_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "view-wset-changed";
data["old-wset"] = wset_to_json(ev->old_wset.get());
Expand All @@ -570,11 +636,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
// Tiled rule handler.
wf::signal::connection_t<wf::view_tiled_signal> _tiled = [=] (wf::view_tiled_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "view-tiled";
data["old-edges"] = ev->old_edges;
Expand Down Expand Up @@ -604,11 +665,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
wf::signal::connection_t<wf::view_change_workspace_signal> _view_workspace =
[=] (wf::view_change_workspace_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "view-workspace-changed";
data["from"] = wf::ipc::point_to_json(ev->from);
Expand All @@ -632,11 +688,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
wf::signal::connection_t<wf::output_plugin_activated_changed_signal> on_plugin_activation_changed =
[=] (wf::output_plugin_activated_changed_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "plugin-activation-state-changed";
data["plugin"] = ev->plugin_name;
Expand All @@ -649,11 +700,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
wf::signal::connection_t<wf::output_gain_focus_signal> on_output_gain_focus =
[=] (wf::output_gain_focus_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "output-gain-focus";
data["output"] = output_to_json(ev->output);
Expand All @@ -663,11 +709,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
wf::signal::connection_t<wf::workspace_set_changed_signal> on_wset_changed =
[=] (wf::workspace_set_changed_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "output-wset-changed";
data["new-wset"] = ev->new_wset ? (int)ev->new_wset->get_id() : -1;
Expand All @@ -680,11 +721,6 @@ class ipc_rules_t : public wf::plugin_interface_t, public wf::per_output_tracker
wf::signal::connection_t<wf::workspace_changed_signal> on_wset_workspace_changed =
[=] (wf::workspace_changed_signal *ev)
{
if (clients.empty())
{
return;
}

nlohmann::json data;
data["event"] = "wset-workspace-changed";
data["previous-workspace"] = wf::ipc::point_to_json(ev->old_viewport);
Expand Down

0 comments on commit 8364a65

Please sign in to comment.