From 8ef8900ca2135ee069ded0e0644595eb733a9e0f Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Tue, 20 Dec 2016 13:03:46 +0100 Subject: [PATCH] refactor: Defer buttonpress using taskqueue --- include/components/bar.hpp | 13 ++++--- include/components/types.hpp | 12 ++++++- src/components/bar.cpp | 66 ++++++++++++++++++++++++++---------- src/modules/xkeyboard.cpp | 2 -- 4 files changed, 68 insertions(+), 25 deletions(-) diff --git a/include/components/bar.hpp b/include/components/bar.hpp index 8b569d9d..06d3afb3 100644 --- a/include/components/bar.hpp +++ b/include/components/bar.hpp @@ -19,6 +19,7 @@ class parser; class renderer; class screen; class signal_emitter; +class taskqueue; class tray_manager; class bar : public xpp::event::sink; static make_type make(); - explicit bar(connection& conn, signal_emitter& emitter, const config& config, const logger& logger, - unique_ptr&& screen, unique_ptr&& tray_manager, unique_ptr&& parser); - virtual ~bar(); + explicit bar(connection&, signal_emitter&, const config&, const logger&, unique_ptr&&, + unique_ptr&&, unique_ptr&&, unique_ptr&&); + ~bar(); void parse(string&& data) const; void parse(const string& data, bool force = false); @@ -60,14 +61,18 @@ class bar : public xpp::event::sink m_tray{}; unique_ptr m_renderer{}; unique_ptr m_parser{}; + unique_ptr m_taskqueue; bar_settings m_opts{}; string m_lastinput{}; - std::mutex m_mutex{}; + mousebtn m_buttonpress_btn{mousebtn::NONE}; + int16_t m_buttonpress_pos{0}; + event_timer m_buttonpress{0L, 5L}; + event_timer m_doubleclick{0L, 150L}; }; POLYBAR_NS_END diff --git a/include/components/types.hpp b/include/components/types.hpp index 9aa7fa35..6a0f5b60 100644 --- a/include/components/types.hpp +++ b/include/components/types.hpp @@ -33,7 +33,17 @@ enum class syntaxtag : uint8_t { u, // underline color }; -enum class mousebtn : uint8_t { NONE = 0U, LEFT, MIDDLE, RIGHT, SCROLL_UP, SCROLL_DOWN }; +enum class mousebtn : uint8_t { + NONE = 0U, + LEFT, + MIDDLE, + RIGHT, + SCROLL_UP, + SCROLL_DOWN, + DOUBLE_LEFT, + DOUBLE_MIDDLE, + DOUBLE_RIGHT +}; enum class strut : uint16_t { LEFT = 0U, diff --git a/src/components/bar.cpp b/src/components/bar.cpp index 5a67d446..97e4d0f2 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -7,6 +7,7 @@ #include "components/parser.hpp" #include "components/renderer.hpp" #include "components/screen.hpp" +#include "components/taskqueue.hpp" #include "events/signal.hpp" #include "events/signal_emitter.hpp" #include "utils/bspwm.hpp" @@ -42,7 +43,8 @@ bar::make_type bar::make() { logger::make(), screen::make(), tray_manager::make(), - parser::make()); + parser::make(), + taskqueue::make()); // clang-format on } @@ -52,14 +54,16 @@ bar::make_type bar::make() { * TODO: Break out all tray handling */ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const logger& logger, - unique_ptr&& screen, unique_ptr&& tray_manager, unique_ptr&& parser) + unique_ptr&& screen, unique_ptr&& tray_manager, unique_ptr&& parser, + unique_ptr&& taskqueue) : m_connection(conn) , m_sig(emitter) , m_conf(config) , m_log(logger) , m_screen(forward(screen)) , m_tray(forward(tray_manager)) - , m_parser(forward(parser)) { + , m_parser(forward(parser)) + , m_taskqueue(forward(taskqueue)) { string bs{m_conf.section()}; // Get available RandR outputs @@ -150,6 +154,9 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const actions.emplace_back(action{mousebtn::RIGHT, m_conf.get(bs, "click-right", "")}); actions.emplace_back(action{mousebtn::SCROLL_UP, m_conf.get(bs, "scroll-up", "")}); actions.emplace_back(action{mousebtn::SCROLL_DOWN, m_conf.get(bs, "scroll-down", "")}); + actions.emplace_back(action{mousebtn::DOUBLE_LEFT, m_conf.get(bs, "double-click-left", "")}); + actions.emplace_back(action{mousebtn::DOUBLE_MIDDLE, m_conf.get(bs, "double-click-middle", "")}); + actions.emplace_back(action{mousebtn::DOUBLE_RIGHT, m_conf.get(bs, "double-click-right", "")}); for (auto&& act : actions) { if (!act.command.empty()) { @@ -507,25 +514,48 @@ void bar::handle(const evt::button_press& evt) { } m_log.trace("bar: Received button press: %i at pos(%i, %i)", evt->detail, evt->event_x, evt->event_y); - mousebtn button{static_cast(evt->detail)}; - for (auto&& action : m_renderer->get_actions()) { - if (!action.active && action.button == button && action.test(evt->event_x)) { - m_log.trace("Found matching input area"); - m_sig.emit(button_press{string{action.command}}); - return; + m_buttonpress_btn = static_cast(evt->detail); + m_buttonpress_pos = evt->event_x; + + const auto deferred_fn = [&] { + for (auto&& action : m_renderer->get_actions()) { + if (action.button == m_buttonpress_btn && !action.active && action.test(m_buttonpress_pos)) { + m_log.trace("Found matching input area"); + m_sig.emit(button_press{string{action.command}}); + return; + } } - } - - for (auto&& action : m_opts.actions) { - if (action.button == button && !action.command.empty()) { - m_log.trace("Triggering fallback click handler: %s", action.command); - m_sig.emit(button_press{string{action.command}}); - return; + for (auto&& action : m_opts.actions) { + if (action.button == m_buttonpress_btn && !action.command.empty()) { + m_log.trace("Found matching fallback handler"); + m_sig.emit(button_press{string{action.command}}); + return; + } } - } + m_log.warn("No matching input area found (btn=%i)", static_cast(m_buttonpress_btn)); + }; - m_log.warn("No matching input area found"); + const auto check_double = [&](const xcb_timestamp_t& timestamp, string&& id, mousebtn&& btn) { + if (!m_taskqueue->has_deferred(string{id})) { + m_doubleclick.event = move(timestamp); + m_taskqueue->defer_unique(string{id}, chrono::milliseconds{m_doubleclick.offset}, deferred_fn); + } else if (m_doubleclick.deny(evt->time)) { + m_doubleclick.event = 0; + m_buttonpress_btn = forward(btn); + m_taskqueue->defer_unique(string{id}, 0ms, deferred_fn); + } + }; + + if (evt->detail == static_cast(mousebtn::LEFT)) { + check_double(evt->time, "buttonpress-left", mousebtn::LEFT); + } else if (evt->detail == static_cast(mousebtn::MIDDLE)) { + check_double(evt->time, "buttonpress-middle", mousebtn::MIDDLE); + } else if (evt->detail == static_cast(mousebtn::RIGHT)) { + check_double(evt->time, "buttonpress-right", mousebtn::RIGHT); + } else { + deferred_fn(); + } } /** diff --git a/src/modules/xkeyboard.cpp b/src/modules/xkeyboard.cpp index 7c428cfd..184fba9f 100644 --- a/src/modules/xkeyboard.cpp +++ b/src/modules/xkeyboard.cpp @@ -134,8 +134,6 @@ namespace modules { current_group = 0; } - printf("%zu\n", current_group); - xkb_util::switch_layout(m_connection, XCB_XKB_ID_USE_CORE_KBD, current_group); m_keyboard->current(current_group); m_connection.flush();