#include "modules/ipc.hpp" #include #include "components/ipc.hpp" #include "modules/meta/base.inl" POLYBAR_NS namespace modules { template class module; /** * Load user-defined ipc hooks and * create formatting tags */ ipc_module::ipc_module(const bar_settings& bar, string name_) : static_module(bar, move(name_)) { m_router->register_action_with_data(EVENT_SEND, &ipc_module::action_send); size_t index = 0; for (auto&& command : m_conf.get_list(name(), "hook", {})) { m_hooks.emplace_back(std::make_unique(hook{name() + to_string(++index), command})); } m_log.info("%s: Loaded %d hooks", name(), m_hooks.size()); if ((m_initial = m_conf.get(name(), "initial", 0_z)) && m_initial > m_hooks.size()) { throw module_error("Initial hook out of bounds (defined: " + to_string(m_hooks.size()) + ")"); } // clang-format off m_actions.emplace(make_pair(mousebtn::LEFT, m_conf.get(name(), "click-left", ""s))); m_actions.emplace(make_pair(mousebtn::MIDDLE, m_conf.get(name(), "click-middle", ""s))); m_actions.emplace(make_pair(mousebtn::RIGHT, m_conf.get(name(), "click-right", ""s))); m_actions.emplace(make_pair(mousebtn::SCROLL_UP, m_conf.get(name(), "scroll-up", ""s))); m_actions.emplace(make_pair(mousebtn::SCROLL_DOWN, m_conf.get(name(), "scroll-down", ""s))); m_actions.emplace(make_pair(mousebtn::DOUBLE_LEFT, m_conf.get(name(), "double-click-left", ""s))); m_actions.emplace(make_pair(mousebtn::DOUBLE_MIDDLE, m_conf.get(name(), "double-click-middle", ""s))); m_actions.emplace(make_pair(mousebtn::DOUBLE_RIGHT, m_conf.get(name(), "double-click-right", ""s))); // clang-format on const auto pid_token = [](const string& s) { return string_util::replace_all(s, "%pid%", to_string(getpid())); }; for (auto& action : m_actions) { action.second = pid_token(action.second); } for (auto& hook : m_hooks) { hook->command = pid_token(hook->command); } m_formatter->add(DEFAULT_FORMAT, TAG_OUTPUT, {TAG_OUTPUT}); } /** * Start module and run first defined hook if configured to */ void ipc_module::start() { if (m_initial) { // TODO do this in a thread. auto command = command_util::make_command(m_hooks.at(m_initial - 1)->command); command->exec(false); command->tail([this](string line) { m_output = line; }); } static_module::start(); } /** * Wrap the output with defined mouse actions */ string ipc_module::get_output() { // Get the module output early so that // the format prefix/suffix also gets wrapper // with the cmd handlers string output{module::get_output()}; for (auto&& action : m_actions) { if (!action.second.empty()) { m_builder->action(action.first, action.second); } } m_builder->append(output); return m_builder->flush(); } /** * Output content retrieved from hook commands */ bool ipc_module::build(builder* builder, const string& tag) const { if (tag == TAG_OUTPUT) { builder->node(m_output); return true; } else { return false; } } /** * Map received message hook to the ones * configured from the user config and * execute its command */ void ipc_module::on_message(const string& message) { for (auto&& hook : m_hooks) { if (hook->payload != message) { continue; } m_log.info("%s: Found matching hook (%s)", name(), hook->payload); try { // Clear the output in case the command produces no output m_output.clear(); auto command = command_util::make_command(hook->command); command->exec(false); command->tail([this](string line) { m_output = line; }); } catch (const exception& err) { m_log.err("%s: Failed to execute hook command (err: %s)", err.what()); m_output.clear(); } broadcast(); } } void ipc_module::action_send(const string& data) { m_output = data; broadcast(); } } // namespace modules POLYBAR_NS_END