actions: Integrate input_handler into module

Only modules can now be action handlers.
This also slightly simplifies the controller because we don't need to
keep track of input handlers, we can just use the module list.
This commit is contained in:
patrick96 2020-11-22 23:05:45 +01:00 committed by Patrick Ziegler
parent 0a1b58a2ed
commit 191fb2972c
10 changed files with 54 additions and 92 deletions

View File

@ -4,14 +4,15 @@
#include "common.hpp" #include "common.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "modules/meta/input_handler.hpp"
POLYBAR_NS POLYBAR_NS
using std::map; using std::map;
// fwd decl // fwd decl
using namespace drawtypes; using namespace drawtypes;
namespace modules {
struct module_interface;
}
class builder { class builder {
public: public:
@ -49,9 +50,9 @@ class builder {
void underline_close(); void underline_close();
void control(controltag tag); void control(controltag tag);
void action(mousebtn index, string action); void action(mousebtn index, string action);
void action(mousebtn btn, const modules::input_handler& handler, string action, string data); void action(mousebtn btn, const modules::module_interface& module, string action, string data);
void action(mousebtn index, string action, const label_t& label); void action(mousebtn index, string action, const label_t& label);
void action(mousebtn btn, const modules::input_handler& handler, string action, string data, const label_t& label); void action(mousebtn btn, const modules::module_interface& module, string action, string data, const label_t& label);
void action_close(); void action_close();
protected: protected:

View File

@ -29,7 +29,6 @@ class logger;
class signal_emitter; class signal_emitter;
namespace modules { namespace modules {
struct module_interface; struct module_interface;
class input_handler;
} // namespace modules } // namespace modules
using module_t = shared_ptr<modules::module_interface>; using module_t = shared_ptr<modules::module_interface>;
using modulemap_t = std::map<alignment, vector<module_t>>; using modulemap_t = std::map<alignment, vector<module_t>>;
@ -117,14 +116,6 @@ class controller
*/ */
modulemap_t m_blocks; modulemap_t m_blocks;
/**
* \brief Input handlers modules
*
* Maps the name of the input handler (module name) to the corresponding input
* handler
*/
std::vector<shared_ptr<modules::input_handler>> m_inputhandlers;
/** /**
* \brief Maximum number of subsequent events to swallow * \brief Maximum number of subsequent events to swallow
*/ */

View File

@ -9,7 +9,6 @@
#include "common.hpp" #include "common.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "errors.hpp" #include "errors.hpp"
#include "modules/meta/input_handler.hpp"
#include "utils/concurrency.hpp" #include "utils/concurrency.hpp"
#include "utils/functional.hpp" #include "utils/functional.hpp"
#include "utils/inotify.hpp" #include "utils/inotify.hpp"
@ -112,6 +111,16 @@ namespace modules {
virtual string name() const = 0; virtual string name() const = 0;
virtual bool running() const = 0; virtual bool running() const = 0;
/**
* Handle action, possibly with data attached
*
* Any implementation is free to ignore the data, if the action does not
* require additional data.
*
* \returns true if the action is supported and false otherwise
*/
virtual bool input(const string& action, const string& data) = 0;
virtual void start() = 0; virtual void start() = 0;
virtual void stop() = 0; virtual void stop() = 0;
virtual void halt(string error_message) = 0; virtual void halt(string error_message) = 0;
@ -122,7 +131,7 @@ namespace modules {
// class definition : module {{{ // class definition : module {{{
template <class Impl> template <class Impl>
class module : public module_interface, public input_handler { class module : public module_interface {
public: public:
module(const bar_settings bar, string name); module(const bar_settings bar, string name);
~module() noexcept; ~module() noexcept;
@ -138,7 +147,6 @@ namespace modules {
string contents(); string contents();
bool input(const string& action, const string& data); bool input(const string& action, const string& data);
string input_handler_name() const;
static constexpr auto TYPE = ""; static constexpr auto TYPE = "";

View File

@ -109,11 +109,6 @@ namespace modules {
return false; return false;
} }
template <typename Impl>
string module<Impl>::input_handler_name() const {
return m_name_raw;
}
// }}} // }}}
// module<Impl> protected {{{ // module<Impl> protected {{{

View File

@ -1,28 +0,0 @@
#pragma once
#include "common.hpp"
POLYBAR_NS
namespace modules {
class input_handler {
public:
virtual ~input_handler() {}
/**
* Handle action, possibly with data attached
*
* Any implementation is free to ignore the data, if the action does not
* require additional data.
*
* \returns true if the action is supported and false otherwise
*/
virtual bool input(const string& action, const string& data) = 0;
/**
* The name of this input handler
*/
virtual string input_handler_name() const = 0;
};
}
POLYBAR_NS_END

View File

@ -9,7 +9,7 @@ namespace modules {
struct module_interface; struct module_interface;
#define DEFINE_UNSUPPORTED_MODULE(MODULE_NAME, MODULE_TYPE) \ #define DEFINE_UNSUPPORTED_MODULE(MODULE_NAME, MODULE_TYPE) \
class MODULE_NAME : public module_interface, public input_handler { \ class MODULE_NAME : public module_interface { \
public: \ public: \
MODULE_NAME(const bar_settings, string) { \ MODULE_NAME(const bar_settings, string) { \
throw application_error("No built-in support for '" + string{MODULE_TYPE} + "'"); \ throw application_error("No built-in support for '" + string{MODULE_TYPE} + "'"); \
@ -33,9 +33,6 @@ namespace modules {
string contents() { \ string contents() { \
return ""; \ return ""; \
} \ } \
string input_handler_name() const { \
return ""; \
} \
bool input(const string&, const string&) { \ bool input(const string&, const string&) { \
return false; \ return false; \
} \ } \

View File

@ -1,12 +1,15 @@
#pragma once #pragma once
#include "common.hpp" #include "common.hpp"
#include "modules/meta/input_handler.hpp"
namespace modules {
struct module_interface;
} // namespace modules
POLYBAR_NS POLYBAR_NS
namespace actions_util { namespace actions_util {
string get_action_string(const modules::input_handler& handler, string action, string data); string get_action_string(const modules::module_interface& module, string action, string data);
/** /**
* Parses an action string of the form "#name.action[.data]". * Parses an action string of the form "#name.action[.data]".

View File

@ -3,10 +3,10 @@
#include <utility> #include <utility>
#include "drawtypes/label.hpp" #include "drawtypes/label.hpp"
#include "utils/actions.hpp"
#include "utils/color.hpp" #include "utils/color.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "utils/time.hpp" #include "utils/time.hpp"
#include "utils/actions.hpp"
POLYBAR_NS POLYBAR_NS
builder::builder(const bar_settings& bar) : m_bar(bar) { builder::builder(const bar_settings& bar) : m_bar(bar) {
@ -440,10 +440,10 @@ void builder::action(mousebtn index, string action) {
} }
/** /**
* Open action tag for the action of the given input_handler * Open action tag for the action of the given module
*/ */
void builder::action(mousebtn btn, const modules::input_handler& handler, string action_name, string data) { void builder::action(mousebtn btn, const modules::module_interface& module, string action_name, string data) {
action(btn, actions_util::get_action_string(handler, action_name, data)); action(btn, actions_util::get_action_string(module, action_name, data));
} }
/** /**
@ -457,12 +457,12 @@ void builder::action(mousebtn index, string action_name, const label_t& label) {
} }
} }
/** /**
* Wrap label in module action tag * Wrap label in module action tag
*/ */
void builder::action(mousebtn btn, const modules::input_handler& handler, string action_name, string data, const label_t& label) { void builder::action(
action(btn, actions_util::get_action_string(handler, action_name, data), label); mousebtn btn, const modules::module_interface& module, string action_name, string data, const label_t& label) {
action(btn, actions_util::get_action_string(module, action_name, data), label);
} }
/** /**

View File

@ -11,6 +11,7 @@
#include "components/types.hpp" #include "components/types.hpp"
#include "events/signal.hpp" #include "events/signal.hpp"
#include "events/signal_emitter.hpp" #include "events/signal_emitter.hpp"
#include "modules/meta/base.hpp"
#include "modules/meta/event_handler.hpp" #include "modules/meta/event_handler.hpp"
#include "modules/meta/factory.hpp" #include "modules/meta/factory.hpp"
#include "utils/actions.hpp" #include "utils/actions.hpp"
@ -146,14 +147,8 @@ bool controller::run(bool writeback, string snapshot_dst) {
size_t started_modules{0}; size_t started_modules{0};
for (const auto& module : m_modules) { for (const auto& module : m_modules) {
auto inp_handler = std::dynamic_pointer_cast<input_handler>(module);
auto evt_handler = dynamic_cast<event_handler_interface*>(&*module); auto evt_handler = dynamic_cast<event_handler_interface*>(&*module);
if (inp_handler) {
m_log.trace("Registering module %s as input handler", module->name_raw());
m_inputhandlers.push_back(inp_handler);
}
if (evt_handler != nullptr) { if (evt_handler != nullptr) {
evt_handler->connect(m_connection); evt_handler->connect(m_connection);
} }
@ -474,20 +469,19 @@ bool controller::try_forward_legacy_action(const string& cmd) {
string action = entry.second.second; string action = entry.second.second;
// Search for the first module that matches the type for this legacy action // Search for the first module that matches the type for this legacy action
for (auto&& mod : m_modules) { for (auto&& module : m_modules) {
if (mod->type() == type) { if (module->type() == type) {
auto handler_ptr = std::dynamic_pointer_cast<input_handler>(mod); auto module_name = module->name_raw();
auto handler_name = handler_ptr->input_handler_name();
// TODO make this message more descriptive and maybe link to some documentation // TODO make this message more descriptive and maybe link to some documentation
// TODO use route to string methods to print action name that should be used. // TODO use route to string methods to print action name that should be used.
if (data.empty()) { if (data.empty()) {
m_log.warn("The action '%s' is deprecated, use '#%s.%s' instead!", cmd, handler_name, action); m_log.warn("The action '%s' is deprecated, use '#%s.%s' instead!", cmd, module_name, action);
} else { } else {
m_log.warn("The action '%s' is deprecated, use '#%s.%s.%s' instead!", cmd, handler_name, action, data); m_log.warn("The action '%s' is deprecated, use '#%s.%s.%s' instead!", cmd, module_name, action, data);
} }
m_log.info( m_log.info(
"Forwarding legacy action '%s' to module '%s' as '%s' with data '%s'", cmd, handler_name, action, data); "Forwarding legacy action '%s' to module '%s' as '%s' with data '%s'", cmd, module_name, action, data);
if (!handler_ptr->input(action, data)) { if (!module->input(action, data)) {
m_log.err("Failed to forward deprecated action to %s module", type); m_log.err("Failed to forward deprecated action to %s module", type);
// Forward to shell if the module cannot accept the action to not break existing behavior. // Forward to shell if the module cannot accept the action to not break existing behavior.
return false; return false;
@ -521,14 +515,14 @@ void controller::process_inputdata() {
// Every command that starts with '#' is considered an action string. // Every command that starts with '#' is considered an action string.
if (cmd.front() == '#') { if (cmd.front() == '#') {
string handler_name; string module_name;
string action; string action;
string data; string data;
try { try {
auto res = actions_util::parse_action_string(cmd); auto res = actions_util::parse_action_string(cmd);
handler_name = std::get<0>(res); module_name = std::get<0>(res);
action = std::get<1>(res); action = std::get<1>(res);
data = std::get<2>(res); data = std::get<2>(res);
} catch (runtime_error& e) { } catch (runtime_error& e) {
@ -536,15 +530,15 @@ void controller::process_inputdata() {
return; return;
} }
m_log.info("Forwarding data to input handlers (name: '%s', action: '%s', data: '%s') ", handler_name, action, data); m_log.info("Forwarding action to modules (name: '%s', action: '%s', data: '%s') ", module_name, action, data);
int num_delivered = 0; int num_delivered = 0;
// Forwards the action to all input handlers that match the name // Forwards the action to all modules that match the name
for (auto&& handler : m_inputhandlers) { for (auto&& module : m_modules) {
if (handler->input_handler_name() == handler_name) { if (module->name_raw() == module_name) {
if (!handler->input(action, data)) { if (!module->input(action, data)) {
m_log.err("The '%s' module does not support the '%s' action.", handler_name, action); m_log.err("The '%s' module does not support the '%s' action.", module_name, action);
} }
num_delivered++; num_delivered++;
@ -552,9 +546,9 @@ void controller::process_inputdata() {
} }
if (num_delivered == 0) { if (num_delivered == 0) {
m_log.err("There exists no input handler with name '%s' (input: %s)", handler_name, cmd); m_log.err("There exists no module with name '%s' (input: %s)", module_name, cmd);
} else { } else {
m_log.info("Delivered input to %d input handler%s", num_delivered, num_delivered > 1 ? "s" : ""); m_log.info("Delivered action to %d module%s", num_delivered, num_delivered > 1 ? "s" : "");
} }
return; return;
} }

View File

@ -4,12 +4,13 @@
#include <stdexcept> #include <stdexcept>
#include "common.hpp" #include "common.hpp"
#include "modules/meta/base.hpp"
POLYBAR_NS POLYBAR_NS
namespace actions_util { namespace actions_util {
string get_action_string(const modules::input_handler& handler, string action, string data) { string get_action_string(const modules::module_interface& module, string action, string data) {
string str = "#" + handler.input_handler_name() + "." + action; string str = "#" + module.name_raw() + "." + action;
if (!data.empty()) { if (!data.empty()) {
str += "." + data; str += "." + data;
} }
@ -28,10 +29,10 @@ namespace actions_util {
throw std::runtime_error("Missing separator between name and action"); throw std::runtime_error("Missing separator between name and action");
} }
auto handler_name = action_str.substr(0, action_sep); auto module_name = action_str.substr(0, action_sep);
if (handler_name.empty()) { if (module_name.empty()) {
throw std::runtime_error("The handler name must not be empty"); throw std::runtime_error("The module name must not be empty");
} }
auto action = action_str.substr(action_sep + 1); auto action = action_str.substr(action_sep + 1);
@ -47,7 +48,7 @@ namespace actions_util {
throw std::runtime_error("The action name must not be empty"); throw std::runtime_error("The action name must not be empty");
} }
return std::tuple<string, string, string>{handler_name, action, data}; return std::tuple<string, string, string>{module_name, action, data};
} }
} // namespace actions_util } // namespace actions_util