Store all action info in action_context

The renderer is responsible for setting the start and end positions
while dispatch does the rest
This commit is contained in:
patrick96 2021-01-10 23:05:48 +01:00 committed by Patrick Ziegler
parent f359540b5d
commit 464bedb33c
7 changed files with 93 additions and 80 deletions

View File

@ -36,10 +36,10 @@ class renderer : public renderer_interface,
public signal_receiver<SIGN_PRIORITY_RENDERER, signals::ui::request_snapshot> { public signal_receiver<SIGN_PRIORITY_RENDERER, signals::ui::request_snapshot> {
public: public:
using make_type = unique_ptr<renderer>; using make_type = unique_ptr<renderer>;
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, 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(); ~renderer();
xcb_window_t window() const; 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_open(const tags::context& ctxt, mousebtn btn, tags::action_t id) override;
void action_close(const tags::context& ctxt, tags::action_t id) override; void action_close(const tags::context& ctxt, tags::action_t id) override;
std::map<mousebtn, tags::action_t> get_actions(int x) override;
tags::action_t get_action(mousebtn btn, int x) override;
protected: protected:
void fill_background(); void fill_background();
void fill_overline(rgba color, double x, double w); void fill_overline(rgba color, double x, double w);
@ -114,7 +111,6 @@ class renderer : public renderer_interface,
bool m_pseudo_transparency{false}; bool m_pseudo_transparency{false};
alignment m_align; alignment m_align;
std::unordered_map<tags::action_t, action_block> m_actions;
bool m_fixedcenter; bool m_fixedcenter;
string m_snapshot_dst; string m_snapshot_dst;

View File

@ -7,6 +7,8 @@ POLYBAR_NS
class renderer_interface { class renderer_interface {
public: 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_offset(const tags::context& ctxt, int pixels) = 0;
virtual void render_text(const tags::context& ctxt, const string&& str) = 0; virtual void render_text(const tags::context& ctxt, const string&& str) = 0;
virtual void change_alignment(const tags::context& ctxt) = 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_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 void action_close(const tags::context& ctxt, tags::action_t id) = 0;
virtual std::map<mousebtn, tags::action_t> get_actions(int x) = 0; protected:
virtual tags::action_t get_action(mousebtn btn, int x) = 0; /**
* 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 POLYBAR_NS_END

View File

@ -109,21 +109,6 @@ struct action {
string command{}; 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<unsigned int>(end_x - start_x + 0.5);
}
bool test(int point) const {
return static_cast<int>(start_x) <= point && static_cast<int>(end_x) > point;
}
};
struct bar_settings { struct bar_settings {
explicit bar_settings() = default; explicit bar_settings() = default;
bar_settings(const bar_settings& other) = default; bar_settings(const bar_settings& other) = default;

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <map>
#include "common.hpp" #include "common.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "tags/types.hpp" #include "tags/types.hpp"
@ -96,6 +98,26 @@ namespace tags {
static constexpr action_t NO_ACTION = -1; 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<unsigned int>(end_x - start_x + 0.5);
}
bool test(int point) const {
return static_cast<int>(start_x) <= point && static_cast<int>(end_x) > point;
}
};
class action_context { class action_context {
public: public:
void reset(); void reset();
@ -103,22 +125,20 @@ namespace tags {
action_t action_open(mousebtn btn, const string&& cmd, alignment align); action_t action_open(mousebtn btn, const string&& cmd, alignment align);
std::pair<action_t, mousebtn> action_close(mousebtn btn, alignment align); std::pair<action_t, mousebtn> action_close(mousebtn btn, alignment align);
void set_start(action_t id, double x);
void set_end(action_t id, double x);
std::map<mousebtn, tags::action_t> get_actions(int x) const;
action_t has_action(mousebtn btn, int x) const;
string get_action(action_t id) const; string get_action(action_t id) const;
bool has_double_click() const; bool has_double_click() const;
size_t num_actions() const; size_t num_actions() const;
std::vector<action_block>& get_blocks();
protected: 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. * Stores all currently known action blocks.
* *

View File

@ -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 // scroll cursor is less important than click cursor, so we shouldn't return until we are sure there is no click
// action // action
bool found_scroll = false; bool found_scroll = false;
const auto& actions = m_renderer->get_actions(m_motion_pos);
const auto has_action = [&](const vector<mousebtn>& buttons) -> bool { const auto has_action = [&](const vector<mousebtn>& buttons) -> bool {
for (auto btn : buttons) { 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; return true;
} }
} }
@ -741,7 +740,8 @@ void bar::handle(const evt::button_press& evt) {
m_buttonpress_pos = evt->event_x; m_buttonpress_pos = evt->event_x;
const auto deferred_fn = [&](size_t) { 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) { if (action != tags::NO_ACTION) {
m_log.trace("Found matching input area"); 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&) { bool bar::on(const signals::eventqueue::start&) {
m_log.trace("bar: Create renderer"); 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(); m_opts.window = m_renderer->window();
// Subscribe to window enter and leave events // Subscribe to window enter and leave events

View File

@ -21,7 +21,7 @@ static constexpr double BLOCK_GAP{20.0};
/** /**
* Create instance * 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 // clang-format off
return factory_util::unique<renderer>( return factory_util::unique<renderer>(
connection::make(), connection::make(),
@ -29,7 +29,8 @@ renderer::make_type renderer::make(const bar_settings& bar) {
config::make(), config::make(),
logger::make(), logger::make(),
forward<decltype(bar)>(bar), forward<decltype(bar)>(bar),
background_manager::make()); background_manager::make(),
action_ctxt);
// clang-format on // clang-format on
} }
@ -37,8 +38,9 @@ renderer::make_type renderer::make(const bar_settings& bar) {
* Construct renderer instance * Construct renderer instance
*/ */
renderer::renderer(connection& conn, signal_emitter& sig, const config& conf, const logger& logger, renderer::renderer(connection& conn, signal_emitter& sig, const config& conf, const logger& logger,
const bar_settings& bar, background_manager& background) const bar_settings& bar, background_manager& background, tags::action_context& action_ctxt)
: m_connection(conn) : renderer_interface(action_ctxt)
, m_connection(conn)
, m_sig(sig) , m_sig(sig)
, m_conf(conf) , m_conf(conf)
, m_log(logger) , m_log(logger)
@ -203,7 +205,6 @@ void renderer::begin(xcb_rectangle_t rect) {
// Reset state // Reset state
m_rect = rect; m_rect = rect;
m_actions.clear();
m_align = alignment::NONE; m_align = alignment::NONE;
// Clear canvas // Clear canvas
@ -250,8 +251,7 @@ void renderer::begin(xcb_rectangle_t rect) {
void renderer::end() { void renderer::end() {
m_log.trace_x("renderer: end"); m_log.trace_x("renderer: end");
for (auto& entry : m_actions) { for (auto& a : m_action_ctxt.get_blocks()) {
auto& a = entry.second;
a.start_x += block_x(a.align) + m_rect.x; a.start_x += block_x(a.align) + m_rect.x;
a.end_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) { void renderer::action_open(const tags::context&, mousebtn btn, tags::action_t id) {
assert(btn != mousebtn::NONE); assert(btn != mousebtn::NONE);
action_block block; m_action_ctxt.set_start(id, m_blocks.at(m_align).x);
block.align = m_align;
block.button = btn;
block.start_x = m_blocks.at(block.align).x;
m_actions[id] = block;
} }
void renderer::action_close(const tags::context&, tags::action_t id) { void renderer::action_close(const tags::context&, tags::action_t id) {
auto& block = m_actions[id]; m_action_ctxt.set_end(id, m_blocks.at(m_align).x);
block.end_x = m_blocks.at(block.align).x;
}
std::map<mousebtn, tags::action_t> renderer::get_actions(int x) {
std::map<mousebtn, tags::action_t> buttons;
for (int i = static_cast<int>(mousebtn::NONE); i < static_cast<int>(mousebtn::BTN_COUNT); i++) {
buttons[static_cast<mousebtn>(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];
} }
/** /**
@ -745,8 +713,7 @@ tags::action_t renderer::get_action(mousebtn btn, int x) {
void renderer::highlight_clickable_areas() { void renderer::highlight_clickable_areas() {
#ifdef DEBUG_HINTS #ifdef DEBUG_HINTS
map<alignment, int> hint_num{}; map<alignment, int> hint_num{};
for (auto&& entry : m_actions) { for (auto&& action : m_action_ctxt.get_blocks()) {
auto&& action = entry.second;
int n = hint_num.find(action.align)->second++; int n = hint_num.find(action.align)->second++;
double x = action.start_x; double x = action.start_x;
double y = m_rect.y; double y = m_rect.y;

View File

@ -137,6 +137,39 @@ namespace tags {
return {NO_ACTION, mousebtn::NONE}; 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<mousebtn, tags::action_t> action_context::get_actions(int x) const {
std::map<mousebtn, tags::action_t> buttons;
for (int i = static_cast<int>(mousebtn::NONE); i < static_cast<int>(mousebtn::BTN_COUNT); i++) {
buttons[static_cast<mousebtn>(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 { string action_context::get_action(action_t id) const {
assert(id >= 0 && (unsigned)id < num_actions()); assert(id >= 0 && (unsigned)id < num_actions());
@ -158,6 +191,10 @@ namespace tags {
return m_action_blocks.size(); return m_action_blocks.size();
} }
std::vector<action_block>& action_context::get_blocks() {
return m_action_blocks;
}
} // namespace tags } // namespace tags
POLYBAR_NS_END POLYBAR_NS_END