From 464bedb33ce90dd335c7e737f5601f773b087fa6 Mon Sep 17 00:00:00 2001 From: patrick96 Date: Sun, 10 Jan 2021 23:05:48 +0100 Subject: [PATCH] Store all action info in action_context The renderer is responsible for setting the start and end positions while dispatch does the rest --- include/components/renderer.hpp | 8 +--- include/components/renderer_interface.hpp | 12 ++++- include/components/types.hpp | 15 ------- include/tags/context.hpp | 40 ++++++++++++----- src/components/bar.cpp | 8 ++-- src/components/renderer.cpp | 53 +++++------------------ src/tags/context.cpp | 37 ++++++++++++++++ 7 files changed, 93 insertions(+), 80 deletions(-) diff --git a/include/components/renderer.hpp b/include/components/renderer.hpp index 70bf1009..133ad6c7 100644 --- a/include/components/renderer.hpp +++ b/include/components/renderer.hpp @@ -36,10 +36,10 @@ class renderer : public renderer_interface, public signal_receiver { public: using make_type = unique_ptr; - static make_type make(const bar_settings& bar); + static make_type make(const bar_settings& bar, tags::action_context& action_ctxt); explicit renderer(connection& conn, signal_emitter& sig, const config&, const logger& logger, const bar_settings& bar, - background_manager& background_manager); + background_manager& background_manager, tags::action_context& action_ctxt); ~renderer(); xcb_window_t window() const; @@ -56,9 +56,6 @@ class renderer : public renderer_interface, void action_open(const tags::context& ctxt, mousebtn btn, tags::action_t id) override; void action_close(const tags::context& ctxt, tags::action_t id) override; - std::map get_actions(int x) override; - tags::action_t get_action(mousebtn btn, int x) override; - protected: void fill_background(); void fill_overline(rgba color, double x, double w); @@ -114,7 +111,6 @@ class renderer : public renderer_interface, bool m_pseudo_transparency{false}; alignment m_align; - std::unordered_map m_actions; bool m_fixedcenter; string m_snapshot_dst; diff --git a/include/components/renderer_interface.hpp b/include/components/renderer_interface.hpp index 32e9dbcc..07ce7895 100644 --- a/include/components/renderer_interface.hpp +++ b/include/components/renderer_interface.hpp @@ -7,6 +7,8 @@ POLYBAR_NS class renderer_interface { public: + renderer_interface(tags::action_context& action_ctxt) : m_action_ctxt(action_ctxt){}; + virtual void render_offset(const tags::context& ctxt, int pixels) = 0; virtual void render_text(const tags::context& ctxt, const string&& str) = 0; virtual void change_alignment(const tags::context& ctxt) = 0; @@ -14,8 +16,14 @@ class renderer_interface { virtual void action_open(const tags::context& ctxt, mousebtn btn, tags::action_t id) = 0; virtual void action_close(const tags::context& ctxt, tags::action_t id) = 0; - virtual std::map get_actions(int x) = 0; - virtual tags::action_t get_action(mousebtn btn, int x) = 0; + protected: + /** + * Stores information about actions in the current action cycle. + * + * The renderer is only responsible for updating the start and end positions + * of each action block. + */ + tags::action_context& m_action_ctxt; }; POLYBAR_NS_END diff --git a/include/components/types.hpp b/include/components/types.hpp index dd8cae46..0ec11440 100644 --- a/include/components/types.hpp +++ b/include/components/types.hpp @@ -109,21 +109,6 @@ struct action { string command{}; }; -struct action_block { - mousebtn button{mousebtn::NONE}; - alignment align{alignment::NONE}; - double start_x{0.0}; - double end_x{0.0}; - - unsigned int width() const { - return static_cast(end_x - start_x + 0.5); - } - - bool test(int point) const { - return static_cast(start_x) <= point && static_cast(end_x) > point; - } -}; - struct bar_settings { explicit bar_settings() = default; bar_settings(const bar_settings& other) = default; diff --git a/include/tags/context.hpp b/include/tags/context.hpp index 590a85e4..4c292874 100644 --- a/include/tags/context.hpp +++ b/include/tags/context.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "common.hpp" #include "components/types.hpp" #include "tags/types.hpp" @@ -96,6 +98,26 @@ namespace tags { static constexpr action_t NO_ACTION = -1; + struct action_block { + action_block(const string&& cmd, mousebtn button, alignment align, bool is_open) + : cmd(std::move(cmd)), button(button), align(align), is_open(is_open){}; + + string cmd; + double start_x{0}; + double end_x{0}; + mousebtn button; + alignment align; + bool is_open; + + unsigned int width() const { + return static_cast(end_x - start_x + 0.5); + } + + bool test(int point) const { + return static_cast(start_x) <= point && static_cast(end_x) > point; + } + }; + class action_context { public: void reset(); @@ -103,22 +125,20 @@ namespace tags { action_t action_open(mousebtn btn, const string&& cmd, alignment align); std::pair action_close(mousebtn btn, alignment align); + void set_start(action_t id, double x); + void set_end(action_t id, double x); + + std::map get_actions(int x) const; + action_t has_action(mousebtn btn, int x) const; + string get_action(action_t id) const; bool has_double_click() const; size_t num_actions() const; + std::vector& get_blocks(); + protected: - struct action_block { - action_block(const string&& cmd, mousebtn button, alignment align, bool is_open) - : cmd(std::move(cmd)), button(button), align(align), is_open(is_open){}; - - string cmd; - mousebtn button; - alignment align; - bool is_open; - }; - /** * Stores all currently known action blocks. * diff --git a/src/components/bar.cpp b/src/components/bar.cpp index 88e3e6fd..b06c6029 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -649,10 +649,9 @@ void bar::handle(const evt::motion_notify& evt) { // scroll cursor is less important than click cursor, so we shouldn't return until we are sure there is no click // action bool found_scroll = false; - const auto& actions = m_renderer->get_actions(m_motion_pos); const auto has_action = [&](const vector& buttons) -> bool { for (auto btn : buttons) { - if (actions.at(btn) != tags::NO_ACTION) { + if (m_action_ctxt->has_action(btn, m_motion_pos) != tags::NO_ACTION) { return true; } } @@ -741,7 +740,8 @@ void bar::handle(const evt::button_press& evt) { m_buttonpress_pos = evt->event_x; const auto deferred_fn = [&](size_t) { - tags::action_t action = m_renderer->get_action(m_buttonpress_btn, m_buttonpress_pos); + tags::action_t action = m_action_ctxt->has_action(m_buttonpress_btn, m_buttonpress_pos); + ; if (action != tags::NO_ACTION) { m_log.trace("Found matching input area"); @@ -830,7 +830,7 @@ void bar::handle(const evt::configure_notify&) { bool bar::on(const signals::eventqueue::start&) { m_log.trace("bar: Create renderer"); - m_renderer = renderer::make(m_opts); + m_renderer = renderer::make(m_opts, *m_action_ctxt); m_opts.window = m_renderer->window(); // Subscribe to window enter and leave events diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp index b3cd6744..3872c283 100644 --- a/src/components/renderer.cpp +++ b/src/components/renderer.cpp @@ -21,7 +21,7 @@ static constexpr double BLOCK_GAP{20.0}; /** * Create instance */ -renderer::make_type renderer::make(const bar_settings& bar) { +renderer::make_type renderer::make(const bar_settings& bar, tags::action_context& action_ctxt) { // clang-format off return factory_util::unique( connection::make(), @@ -29,7 +29,8 @@ renderer::make_type renderer::make(const bar_settings& bar) { config::make(), logger::make(), forward(bar), - background_manager::make()); + background_manager::make(), + action_ctxt); // clang-format on } @@ -37,8 +38,9 @@ renderer::make_type renderer::make(const bar_settings& bar) { * Construct renderer instance */ renderer::renderer(connection& conn, signal_emitter& sig, const config& conf, const logger& logger, - const bar_settings& bar, background_manager& background) - : m_connection(conn) + const bar_settings& bar, background_manager& background, tags::action_context& action_ctxt) + : renderer_interface(action_ctxt) + , m_connection(conn) , m_sig(sig) , m_conf(conf) , m_log(logger) @@ -203,7 +205,6 @@ void renderer::begin(xcb_rectangle_t rect) { // Reset state m_rect = rect; - m_actions.clear(); m_align = alignment::NONE; // Clear canvas @@ -250,8 +251,7 @@ void renderer::begin(xcb_rectangle_t rect) { void renderer::end() { m_log.trace_x("renderer: end"); - for (auto& entry : m_actions) { - auto& a = entry.second; + for (auto& a : m_action_ctxt.get_blocks()) { a.start_x += block_x(a.align) + m_rect.x; a.end_x += block_x(a.align) + m_rect.x; } @@ -700,43 +700,11 @@ void renderer::change_alignment(const tags::context& ctxt) { void renderer::action_open(const tags::context&, mousebtn btn, tags::action_t id) { assert(btn != mousebtn::NONE); - action_block block; - block.align = m_align; - block.button = btn; - block.start_x = m_blocks.at(block.align).x; - m_actions[id] = block; + m_action_ctxt.set_start(id, m_blocks.at(m_align).x); } void renderer::action_close(const tags::context&, tags::action_t id) { - auto& block = m_actions[id]; - block.end_x = m_blocks.at(block.align).x; -} - -std::map renderer::get_actions(int x) { - std::map buttons; - - for (int i = static_cast(mousebtn::NONE); i < static_cast(mousebtn::BTN_COUNT); i++) { - buttons[static_cast(i)] = tags::NO_ACTION; - } - - for (auto&& entry : m_actions) { - tags::action_t id; - action_block action; - std::tie(id, action) = entry; - - mousebtn btn = action.button; - - // Higher IDs are higher in the action stack. - if (id > buttons[btn] && action.test(x)) { - buttons[action.button] = id; - } - } - - return buttons; -} - -tags::action_t renderer::get_action(mousebtn btn, int x) { - return get_actions(x)[btn]; + m_action_ctxt.set_end(id, m_blocks.at(m_align).x); } /** @@ -745,8 +713,7 @@ tags::action_t renderer::get_action(mousebtn btn, int x) { void renderer::highlight_clickable_areas() { #ifdef DEBUG_HINTS map hint_num{}; - for (auto&& entry : m_actions) { - auto&& action = entry.second; + for (auto&& action : m_action_ctxt.get_blocks()) { int n = hint_num.find(action.align)->second++; double x = action.start_x; double y = m_rect.y; diff --git a/src/tags/context.cpp b/src/tags/context.cpp index 0ed899e9..5aeb704f 100644 --- a/src/tags/context.cpp +++ b/src/tags/context.cpp @@ -137,6 +137,39 @@ namespace tags { return {NO_ACTION, mousebtn::NONE}; } + void action_context::set_start(action_t id, double x) { + m_action_blocks[id].start_x = x; + } + + void action_context::set_end(action_t id, double x) { + m_action_blocks[id].end_x = x; + } + + std::map action_context::get_actions(int x) const { + std::map buttons; + + for (int i = static_cast(mousebtn::NONE); i < static_cast(mousebtn::BTN_COUNT); i++) { + buttons[static_cast(i)] = tags::NO_ACTION; + } + + for (action_t id = 0; (unsigned)id < m_action_blocks.size(); id++) { + auto action = m_action_blocks[id]; + mousebtn btn = action.button; + + // Higher IDs are higher in the action stack. + if (id > buttons[btn] && action.test(x)) { + buttons[action.button] = id; + } + } + + return buttons; + } + + action_t action_context::has_action(mousebtn btn, int x) const { + // TODO optimize + return get_actions(x)[btn]; + } + string action_context::get_action(action_t id) const { assert(id >= 0 && (unsigned)id < num_actions()); @@ -158,6 +191,10 @@ namespace tags { return m_action_blocks.size(); } + std::vector& action_context::get_blocks() { + return m_action_blocks; + } + } // namespace tags POLYBAR_NS_END