diff --git a/include/components/controller.hpp b/include/components/controller.hpp index 4bedacdf..a697d6f8 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -51,7 +52,7 @@ class controller bool run(bool writeback, string snapshot_dst); bool enqueue(event&& evt); - bool enqueue(string&& input_data); + bool trigger_action(string&& input_data); void stop(bool reload); @@ -60,6 +61,7 @@ class controller void conn_cb(int status, int events); void ipc_cb(string buf); void confwatch_handler(const char* fname, int events, int status); + void notifier_handler(); protected: void read_events(); @@ -95,6 +97,14 @@ class controller std::unique_ptr eloop; + /** + * \brief Async handle to notify the eventloop + * + * This handle is used to notify the eventloop of changes which are not otherwise covered by other handles. + * E.g. click actions. + */ + std::unique_ptr m_notifier{nullptr}; + /** * \brief State flag */ diff --git a/include/events/types.hpp b/include/events/types.hpp index 34a3d965..a39fd0a0 100644 --- a/include/events/types.hpp +++ b/include/events/types.hpp @@ -10,7 +10,6 @@ enum class event_type { NONE = 0, UPDATE, CHECK, - INPUT, QUIT, }; @@ -48,13 +47,6 @@ namespace { return event{static_cast(event_type::UPDATE), force}; } - /** - * Create INPUT event - */ - inline event make_input_evt() { - return event{static_cast(event_type::INPUT)}; - } - /** * Create CHECK event */ diff --git a/src/components/controller.cpp b/src/components/controller.cpp index e5a722a0..e19f2ce8 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -160,12 +160,12 @@ bool controller::enqueue(event&& evt) { /** * Enqueue input data */ -bool controller::enqueue(string&& input_data) { +bool controller::trigger_action(string&& input_data) { if (!m_inputdata.empty()) { m_log.trace("controller: Swallowing input event (pending data)"); } else { m_inputdata = forward(input_data); - return enqueue(make_input_evt()); + UV(uv_async_send, m_notifier.get()); } return false; } @@ -223,6 +223,12 @@ void controller::confwatch_handler(const char* filename, int, int) { stop(true); } +void controller::notifier_handler() { + if (!m_inputdata.empty()) { + process_inputdata(); + } +} + static void ipc_alloc_cb(uv_handle_t*, size_t, uv_buf_t* buf) { buf->base = new char[BUFSIZ]; buf->len = BUFSIZ; @@ -247,6 +253,10 @@ static void ipc_read_cb_wrapper(uv_stream_t* stream, ssize_t nread, const uv_buf } } +static void notifier_cb_wrapper(uv_async_t *handle) { + static_cast(handle->data)->notifier_handler(); +} + /** * Read events from configured file descriptors */ @@ -279,6 +289,10 @@ void controller::read_events() { uv_read_start((uv_stream_t*)ipc_handle.get(), ipc_alloc_cb, ipc_read_cb_wrapper); } + m_notifier = std::make_unique(); + uv_async_init(loop, m_notifier.get(), notifier_cb_wrapper); + m_notifier->data = this; + eloop->run(); } catch (const exception& err) { m_log.err("Fatal Error in eventloop: %s", err.what()); @@ -317,8 +331,6 @@ void controller::process_eventqueue() { } else { on(signals::eventqueue::exit_terminate{}); } - } else if (evt.type == event_type::INPUT) { - process_inputdata(); } else if (evt.type == event_type::UPDATE && evt.flag) { process_update(true); } else { @@ -328,9 +340,6 @@ void controller::process_eventqueue() { if (next.type == event_type::QUIT) { evt = next; break; - } else if (next.type == event_type::INPUT) { - evt = next; - break; } else if (evt.type != next.type) { enqueue(move(next)); break; @@ -342,8 +351,6 @@ void controller::process_eventqueue() { if (evt.type == event_type::UPDATE) { process_update(evt.flag); - } else if (evt.type == event_type::INPUT) { - process_inputdata(); } else if (evt.type == event_type::QUIT) { if (evt.flag) { on(signals::eventqueue::exit_reload{}); @@ -763,7 +770,7 @@ bool controller::on(const signals::ui::button_press& evt) { return false; } - enqueue(move(input)); + trigger_action(move(input)); return true; } @@ -779,7 +786,7 @@ bool controller::on(const signals::ipc::action& evt) { } m_log.info("Enqueuing ipc action: %s", action); - enqueue(move(action)); + trigger_action(move(action)); return true; }