diff --git a/include/components/controller.hpp b/include/components/controller.hpp index a3a9ad5b..e14d3b9d 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -42,6 +42,7 @@ class controller { void bootstrap_modules(); + void on_ipc_action(const ipc_action& message); void on_mouse_event(string input); void on_unrecognized_action(string input); void on_update(); diff --git a/include/components/ipc.hpp b/include/components/ipc.hpp index 3516567d..01dc31ed 100644 --- a/include/components/ipc.hpp +++ b/include/components/ipc.hpp @@ -16,6 +16,10 @@ struct ipc_hook { static constexpr auto prefix{"hook:"}; string payload; }; +struct ipc_action { + static constexpr auto prefix{"action:"}; + string payload; +}; /** * Component used for inter-process communication. @@ -31,18 +35,21 @@ class ipc { void attach_callback(callback&& cb); void attach_callback(callback&& cb); + void attach_callback(callback&& cb); void receive_messages(); protected: void parse(const string& payload) const; void delegate(const ipc_command& msg) const; void delegate(const ipc_hook& msg) const; + void delegate(const ipc_action& msg) const; private: const logger& m_log; vector> m_command_callbacks; vector> m_hook_callbacks; + vector> m_action_callbacks; stateflag m_running{false}; diff --git a/src/components/controller.cpp b/src/components/controller.cpp index 5f35f7ee..5d9b6b9b 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -107,8 +107,9 @@ void controller::bootstrap(bool writeback, bool dump_wmname) { if (m_conf.get(m_conf.bar_section(), "enable-ipc", false)) { m_log.trace("controller: Create IPC handler"); m_ipc = configure_ipc().create(); + m_ipc->attach_callback(bind(&controller::on_ipc_action, this, placeholders::_1)); } else { - m_log.warn("Inter-process communication support disabled"); + m_log.info("Inter-process messaging disabled"); } // Listen for events on the root window to be able to @@ -389,7 +390,7 @@ void controller::bootstrap_modules() { module.reset(new menu_module(bar, m_log, m_conf, module_name)); else if (type == "custom/ipc") { if (!m_ipc) - throw application_error("Inter-process communication support needs to be enabled"); + throw application_error("Inter-process messaging needs to be enabled"); module.reset(new ipc_module(bar, m_log, m_conf, module_name)); m_ipc->attach_callback( bind(&ipc_module::on_message, dynamic_cast(module.get()), placeholders::_1)); @@ -416,6 +417,24 @@ void controller::bootstrap_modules() { throw application_error("No modules created"); } +/** + * Callback for received ipc actions + */ +void controller::on_ipc_action(const ipc_action& message) { + string action = message.payload.substr(strlen(ipc_action::prefix)); + + if (action.empty()) { + m_log.err("Cannot enqueue empty IPC action"); + return; + } + + eventloop::entry_t evt{static_cast(event_type::INPUT)}; + snprintf(evt.data, sizeof(evt.data), "%s", action.c_str()); + + m_log.info("Enqueuing IPC action: %s", action); + m_eventloop->enqueue(evt); +} + /** * Callback for clicked bar actions */ diff --git a/src/components/ipc.cpp b/src/components/ipc.cpp index 6537222d..ea993f56 100644 --- a/src/components/ipc.cpp +++ b/src/components/ipc.cpp @@ -41,6 +41,13 @@ void ipc::attach_callback(callback&& cb) { m_hook_callbacks.emplace_back(cb); } +/** + * Register listener callback for ipc_action messages + */ +void ipc::attach_callback(callback&& cb) { + m_action_callbacks.emplace_back(cb); +} + /** * Start listening for event messages */ @@ -71,6 +78,8 @@ void ipc::parse(const string& payload) const { delegate(ipc_command{payload}); } else if (payload.find(ipc_hook::prefix) == 0) { delegate(ipc_hook{payload}); + } else if (payload.find(ipc_action::prefix) == 0) { + delegate(ipc_action{payload}); } else { m_log.warn("Received unknown ipc message: (payload=%s)", payload); } @@ -96,4 +105,14 @@ void ipc::delegate(const ipc_hook& message) const { m_log.warn("Unhandled message (payload=%s)", message.payload); } +/** + * Send ipc message to attached listeners + */ +void ipc::delegate(const ipc_action& message) const { + if (!m_action_callbacks.empty()) + for (auto&& callback : m_action_callbacks) callback(message); + else + m_log.warn("Unhandled message (payload=%s)", message.payload); +} + LEMONBUDDY_NS_END