polybar/src/modules/ipc.cpp

134 lines
4.2 KiB
C++
Raw Normal View History

#include "modules/ipc.hpp"
2021-09-21 19:27:42 +00:00
#include <unistd.h>
#include "components/ipc.hpp"
2016-11-20 22:04:31 +00:00
#include "modules/meta/base.inl"
2016-11-19 05:22:44 +00:00
POLYBAR_NS
namespace modules {
2016-11-20 22:04:31 +00:00
template class module<ipc_module>;
/**
* Load user-defined ipc hooks and
* create formatting tags
*/
ipc_module::ipc_module(const bar_settings& bar, string name_) : static_module<ipc_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<string>(name(), "hook", {})) {
m_hooks.emplace_back(std::make_unique<hook>(hook{name() + to_string(++index), command}));
}
m_log.info("%s: Loaded %d hooks", name(), m_hooks.size());
2017-01-13 23:27:29 +00:00
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()) + ")");
}
2017-01-13 23:55:55 +00:00
// clang-format off
2017-01-13 23:27:29 +00:00
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::LEFT, m_conf.get(name(), "click-left", ""s)));
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::MIDDLE, m_conf.get(name(), "click-middle", ""s)));
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::RIGHT, m_conf.get(name(), "click-right", ""s)));
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::SCROLL_UP, m_conf.get(name(), "scroll-up", ""s)));
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::SCROLL_DOWN, m_conf.get(name(), "scroll-down", ""s)));
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::DOUBLE_LEFT, m_conf.get(name(), "double-click-left", ""s)));
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::DOUBLE_MIDDLE, m_conf.get(name(), "double-click-middle", ""s)));
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::DOUBLE_RIGHT, m_conf.get(name(), "double-click-right", ""s)));
2017-01-13 23:55:55 +00:00
// clang-format on
2021-09-21 19:27:42 +00:00
const auto pid_token = [](const string& s) { return string_util::replace_all(s, "%pid%", to_string(getpid())); };
2017-01-13 23:55:55 +00:00
for (auto& action : m_actions) {
action.second = pid_token(action.second);
2017-01-13 23:55:55 +00:00
}
for (auto& hook : m_hooks) {
hook->command = pid_token(hook->command);
2017-01-13 23:55:55 +00:00
}
m_formatter->add(DEFAULT_FORMAT, TAG_OUTPUT, {TAG_OUTPUT});
}
/**
* Start module and run first defined hook if configured to
*/
void ipc_module::start() {
2017-01-13 23:10:55 +00:00
if (m_initial) {
// TODO do this in a thread.
auto command = command_util::make_command<output_policy::REDIRECTED>(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() {
2016-12-05 04:32:10 +00:00
// Get the module output early so that
// the format prefix/suffix also gets wrapper
// with the cmd handlers
string output{module::get_output()};
2017-01-13 23:10:55 +00:00
for (auto&& action : m_actions) {
if (!action.second.empty()) {
m_builder->action(action.first, action.second);
2017-01-13 23:10:55 +00:00
}
2016-11-25 12:55:15 +00:00
}
2016-12-05 04:32:10 +00:00
m_builder->append(output);
return m_builder->flush();
}
/**
* Output content retrieved from hook commands
*/
2016-11-25 12:55:15 +00:00
bool ipc_module::build(builder* builder, const string& tag) const {
if (tag == TAG_OUTPUT) {
builder->node(m_output);
return true;
2016-11-25 12:55:15 +00:00
} else {
return false;
2016-11-25 12:55:15 +00:00
}
}
/**
* Map received message hook to the ones
* configured from the user config and
* execute its command
*/
2016-12-26 09:36:14 +00:00
void ipc_module::on_message(const string& message) {
for (auto&& hook : m_hooks) {
2016-12-26 09:36:14 +00:00
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<output_policy::REDIRECTED>(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
2016-11-19 05:22:44 +00:00
POLYBAR_NS_END