From 0a474bb2f26cab790a25b9d1f57d3a8528913038 Mon Sep 17 00:00:00 2001
From: patrick96
Date: Wed, 6 Jan 2021 16:53:52 +0100
Subject: [PATCH] Move trivial formatting state into tags::context
The variables storing the current colors, attribute activations and font
were only used in a single place and can easily also be read from the
context.
This allows us to remove a lot of the state of the renderer.
---
include/components/renderer.hpp | 33 +-----
include/components/renderer_interface.hpp | 1 +
include/events/signal.hpp | 33 ------
include/events/signal_fwd.hpp | 11 --
include/tags/context.hpp | 78 ++++++++++++-
include/tags/dispatch.hpp | 3 +-
src/CMakeLists.txt | 1 +
src/components/renderer.cpp | 135 ++++------------------
src/tags/context.cpp | 116 +++++++++++++++++++
src/tags/dispatch.cpp | 62 +++++-----
10 files changed, 251 insertions(+), 222 deletions(-)
create mode 100644 src/tags/context.cpp
diff --git a/include/components/renderer.hpp b/include/components/renderer.hpp
index 77e20837..a6c8f0ec 100644
--- a/include/components/renderer.hpp
+++ b/include/components/renderer.hpp
@@ -32,13 +32,9 @@ struct alignment_block {
double y;
};
-class renderer
- : public renderer_interface,
- public signal_receiver {
+class renderer : public renderer_interface,
+ public signal_receiver {
public:
using make_type = unique_ptr;
static make_type make(const bar_settings& bar);
@@ -58,12 +54,12 @@ class renderer
void reserve_space(edge side, unsigned int w);
#endif
void fill_background();
- void fill_overline(double x, double w);
- void fill_underline(double x, double w);
+ void fill_overline(rgba color, double x, double w);
+ void fill_underline(rgba color, double x, double w);
void fill_borders();
- void draw_text(const string& contents);
void render_offset(const tags::context& ctxt, int pixels) override;
+ void render_text(const tags::context& ctxt, const string&&) override;
protected:
double block_x(alignment a) const;
@@ -75,20 +71,9 @@ class renderer
void highlight_clickable_areas();
bool on(const signals::ui::request_snapshot& evt) override;
- bool on(const signals::parser::change_background& evt) override;
- bool on(const signals::parser::change_foreground& evt) override;
- bool on(const signals::parser::change_underline& evt) override;
- bool on(const signals::parser::change_overline& evt) override;
- bool on(const signals::parser::change_font& evt) override;
bool on(const signals::parser::change_alignment& evt) override;
- bool on(const signals::parser::reverse_colors&) override;
- bool on(const signals::parser::attribute_set& evt) override;
- bool on(const signals::parser::attribute_unset& evt) override;
- bool on(const signals::parser::attribute_toggle& evt) override;
bool on(const signals::parser::action_begin& evt) override;
bool on(const signals::parser::action_end& evt) override;
- bool on(const signals::parser::text& evt) override;
- bool on(const signals::parser::control& evt) override;
protected:
struct reserve_area {
@@ -129,12 +114,6 @@ class renderer
bool m_pseudo_transparency{false};
alignment m_align;
- std::bitset<3> m_attr;
- int m_font{0};
- rgba m_bg{};
- rgba m_fg{};
- rgba m_ol{};
- rgba m_ul{};
vector m_actions;
bool m_fixedcenter;
diff --git a/include/components/renderer_interface.hpp b/include/components/renderer_interface.hpp
index 8adf94d7..d94042f9 100644
--- a/include/components/renderer_interface.hpp
+++ b/include/components/renderer_interface.hpp
@@ -6,6 +6,7 @@ POLYBAR_NS
class renderer_interface {
public:
virtual void render_offset(const tags::context& ctxt, int pixels) = 0;
+ virtual void render_text(const tags::context& ctxt, const string&& str) = 0;
};
POLYBAR_NS_END
diff --git a/include/events/signal.hpp b/include/events/signal.hpp
index 7cc09691..ac776937 100644
--- a/include/events/signal.hpp
+++ b/include/events/signal.hpp
@@ -132,48 +132,15 @@ namespace signals {
} // namespace ui_tray
namespace parser {
- struct change_background : public detail::value_signal {
- using base_type::base_type;
- };
- struct change_foreground : public detail::value_signal {
- using base_type::base_type;
- };
- struct change_underline : public detail::value_signal {
- using base_type::base_type;
- };
- struct change_overline : public detail::value_signal {
- using base_type::base_type;
- };
- struct change_font : public detail::value_signal {
- using base_type::base_type;
- };
struct change_alignment : public detail::value_signal {
using base_type::base_type;
};
- struct reverse_colors : public detail::base_signal {
- using base_type::base_type;
- };
- struct attribute_set : public detail::value_signal {
- using base_type::base_type;
- };
- struct attribute_unset : public detail::value_signal {
- using base_type::base_type;
- };
- struct attribute_toggle : public detail::value_signal {
- using base_type::base_type;
- };
struct action_begin : public detail::value_signal {
using base_type::base_type;
};
struct action_end : public detail::value_signal {
using base_type::base_type;
};
- struct text : public detail::value_signal {
- using base_type::base_type;
- };
- struct control : public detail::value_signal {
- using base_type::base_type;
- };
} // namespace parser
} // namespace signals
diff --git a/include/events/signal_fwd.hpp b/include/events/signal_fwd.hpp
index 790625a4..44cb49db 100644
--- a/include/events/signal_fwd.hpp
+++ b/include/events/signal_fwd.hpp
@@ -45,20 +45,9 @@ namespace signals {
struct mapped_clients;
}
namespace parser {
- struct change_background;
- struct change_foreground;
- struct change_underline;
- struct change_overline;
- struct change_font;
struct change_alignment;
- struct reverse_colors;
- struct attribute_set;
- struct attribute_unset;
- struct attribute_toggle;
struct action_begin;
struct action_end;
- struct text;
- struct control;
} // namespace parser
} // namespace signals
diff --git a/include/tags/context.hpp b/include/tags/context.hpp
index 174ffe88..2f864f14 100644
--- a/include/tags/context.hpp
+++ b/include/tags/context.hpp
@@ -1,11 +1,87 @@
#pragma once
#include "common.hpp"
+#include "components/types.hpp"
+#include "tags/types.hpp"
+#include "utils/color.hpp"
POLYBAR_NS
namespace tags {
- class context {};
+ /**
+ * Stores all the formatting data which comes from formatting tags needed to
+ * render a formatting string.
+ */
+ class context {
+ public:
+ context() = delete;
+ context(const bar_settings& settings);
+
+ /**
+ * Resets to the initial state.
+ *
+ * The initial state depends on the colors set on the bar itself.
+ */
+ void reset();
+
+ void apply_bg(color_value c);
+ void apply_fg(color_value c);
+ void apply_ol(color_value c);
+ void apply_ul(color_value c);
+ void apply_font(int font);
+ void apply_reverse();
+ void apply_alignment(alignment align);
+ void apply_attr(attr_activation act, attribute attr);
+ void apply_reset();
+
+ rgba get_bg() const;
+ rgba get_fg() const;
+ rgba get_ol() const;
+ rgba get_ul() const;
+ int get_font() const;
+ bool has_overline() const;
+ bool has_underline() const;
+ alignment get_alignment() const;
+
+ protected:
+ rgba get_color(color_value c, rgba fallback) const;
+
+ /**
+ * Background color
+ */
+ rgba m_bg;
+ /**
+ * Foreground color
+ */
+ rgba m_fg;
+ /**
+ * Overline color
+ */
+ rgba m_ol;
+ /**
+ * Underline color
+ */
+ rgba m_ul;
+ /**
+ * Font index (1-based)
+ */
+ int m_font;
+ /**
+ * Is overline enabled?
+ */
+ bool m_attr_overline;
+ /**
+ * Is underline enabled?
+ */
+ bool m_attr_underline;
+ /**
+ * Alignment block
+ */
+ alignment m_align;
+
+ private:
+ const bar_settings& m_settings;
+ };
} // namespace tags
POLYBAR_NS_END
diff --git a/include/tags/dispatch.hpp b/include/tags/dispatch.hpp
index 7a022abb..d96818a8 100644
--- a/include/tags/dispatch.hpp
+++ b/include/tags/dispatch.hpp
@@ -29,8 +29,9 @@ namespace tags {
void parse(const bar_settings& bar, renderer_interface&, string data);
protected:
- void text(string&& data);
+ void handle_text(renderer_interface& renderer, context& ctxt, string&& data);
void handle_action(mousebtn btn, bool closing, const string&& cmd);
+ void handle_control(context& ctxt, controltag ctrl);
private:
signal_emitter& m_sig;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dcd58307..22d57efd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -96,6 +96,7 @@ if(BUILD_LIBPOLY)
${src_dir}/modules/xwindow.cpp
${src_dir}/modules/xworkspaces.cpp
+ ${src_dir}/tags/context.cpp
${src_dir}/tags/dispatch.cpp
${src_dir}/tags/parser.cpp
diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp
index c6b84540..bbc270d1 100644
--- a/src/components/renderer.cpp
+++ b/src/components/renderer.cpp
@@ -209,15 +209,8 @@ void renderer::begin(xcb_rectangle_t rect) {
// Reset state
m_rect = rect;
m_actions.clear();
- m_attr.reset();
m_align = alignment::NONE;
- // Reset colors
- m_bg = m_bar.background;
- m_fg = m_bar.foreground;
- m_ul = m_bar.underline.color;
- m_ol = m_bar.overline.color;
-
// Clear canvas
m_context->save();
m_context->clear();
@@ -593,12 +586,12 @@ void renderer::fill_background() {
/**
* Fill overline color
*/
-void renderer::fill_overline(double x, double w) {
- if (m_bar.overline.size && m_attr.test(static_cast(tags::attribute::OVERLINE))) {
+void renderer::fill_overline(rgba color, double x, double w) {
+ if (m_bar.overline.size) {
m_log.trace_x("renderer: overline(x=%f, w=%f)", x, w);
m_context->save();
*m_context << m_comp_ol;
- *m_context << m_ol;
+ *m_context << color;
*m_context << cairo::rect{x, static_cast(m_rect.y), w, static_cast(m_bar.overline.size)};
m_context->fill();
m_context->restore();
@@ -608,12 +601,12 @@ void renderer::fill_overline(double x, double w) {
/**
* Fill underline color
*/
-void renderer::fill_underline(double x, double w) {
- if (m_bar.underline.size && m_attr.test(static_cast(tags::attribute::UNDERLINE))) {
+void renderer::fill_underline(rgba color, double x, double w) {
+ if (m_bar.underline.size) {
m_log.trace_x("renderer: underline(x=%f, w=%f)", x, w);
m_context->save();
*m_context << m_comp_ul;
- *m_context << m_ul;
+ *m_context << color;
*m_context << cairo::rect{x, static_cast(m_rect.y + m_rect.height - m_bar.underline.size), w,
static_cast(m_bar.underline.size)};
m_context->fill();
@@ -670,7 +663,7 @@ void renderer::fill_borders() {
/**
* Draw text contents
*/
-void renderer::draw_text(const string& contents) {
+void renderer::render_text(const tags::context& ctxt, const string&& contents) {
m_log.trace_x("renderer: text(%s)", contents.c_str());
cairo::abspos origin{};
@@ -680,17 +673,19 @@ void renderer::draw_text(const string& contents) {
cairo::textblock block{};
block.align = m_align;
block.contents = contents;
- block.font = m_font;
+ block.font = ctxt.get_font();
block.x_advance = &m_blocks[m_align].x;
block.y_advance = &m_blocks[m_align].y;
block.bg_rect = cairo::rect{0.0, 0.0, 0.0, 0.0};
+ rgba bg = ctxt.get_bg();
+
// Only draw text background if the color differs from
// the background color of the bar itself
// Note: this means that if the user explicitly set text
// background color equal to background-0 it will be ignored
- if (m_bg != m_bar.background) {
- block.bg = m_bg;
+ if (bg != m_bar.background) {
+ block.bg = bg;
block.bg_operator = m_comp_bg;
block.bg_rect.x = m_rect.x;
block.bg_rect.y = m_rect.y;
@@ -700,14 +695,19 @@ void renderer::draw_text(const string& contents) {
m_context->save();
*m_context << origin;
*m_context << m_comp_fg;
- *m_context << m_fg;
+ *m_context << ctxt.get_fg();
*m_context << block;
m_context->restore();
double dx = m_rect.x + m_blocks[m_align].x - origin.x;
if (dx > 0.0) {
- fill_underline(origin.x, dx);
- fill_overline(origin.x, dx);
+ if (ctxt.has_underline()) {
+ fill_underline(ctxt.get_ul(), origin.x, dx);
+ }
+
+ if (ctxt.has_overline()) {
+ fill_overline(ctxt.get_ol(), origin.x, dx);
+ }
}
}
@@ -746,51 +746,6 @@ bool renderer::on(const signals::ui::request_snapshot& evt) {
return true;
}
-bool renderer::on(const signals::parser::change_background& evt) {
- const rgba color{evt.cast()};
- if (color != m_bg) {
- m_log.trace_x("renderer: change_background(#%08x)", color);
- m_bg = color;
- }
- return true;
-}
-
-bool renderer::on(const signals::parser::change_foreground& evt) {
- const rgba color{evt.cast()};
- if (color != m_fg) {
- m_log.trace_x("renderer: change_foreground(#%08x)", color);
- m_fg = color;
- }
- return true;
-}
-
-bool renderer::on(const signals::parser::change_underline& evt) {
- const rgba color{evt.cast()};
- if (color != m_ul) {
- m_log.trace_x("renderer: change_underline(#%08x)", color);
- m_ul = color;
- }
- return true;
-}
-
-bool renderer::on(const signals::parser::change_overline& evt) {
- const rgba color{evt.cast()};
- if (color != m_ol) {
- m_log.trace_x("renderer: change_overline(#%08x)", color);
- m_ol = color;
- }
- return true;
-}
-
-bool renderer::on(const signals::parser::change_font& evt) {
- const int font{evt.cast()};
- if (font != m_font) {
- m_log.trace_x("renderer: change_font(%i)", font);
- m_font = font;
- }
- return true;
-}
-
bool renderer::on(const signals::parser::change_alignment& evt) {
auto align = static_cast(evt.cast());
if (align != m_align) {
@@ -812,30 +767,6 @@ bool renderer::on(const signals::parser::change_alignment& evt) {
return true;
}
-bool renderer::on(const signals::parser::reverse_colors&) {
- m_log.trace_x("renderer: reverse_colors");
- std::swap(m_fg, m_bg);
- return true;
-}
-
-bool renderer::on(const signals::parser::attribute_set& evt) {
- m_log.trace_x("renderer: attribute_set(%i)", static_cast(evt.cast()));
- m_attr.set(static_cast(evt.cast()), true);
- return true;
-}
-
-bool renderer::on(const signals::parser::attribute_unset& evt) {
- m_log.trace_x("renderer: attribute_unset(%i)", static_cast(evt.cast()));
- m_attr.set(static_cast(evt.cast()), false);
- return true;
-}
-
-bool renderer::on(const signals::parser::attribute_toggle& evt) {
- m_log.trace_x("renderer: attribute_toggle(%i)", static_cast(evt.cast()));
- m_attr.flip(static_cast(evt.cast()));
- return true;
-}
-
bool renderer::on(const signals::parser::action_begin& evt) {
auto a = evt.cast();
m_log.trace_x("renderer: action_begin(btn=%i, command=%s)", static_cast(a.button), a.command);
@@ -866,30 +797,4 @@ bool renderer::on(const signals::parser::action_end& evt) {
return true;
}
-bool renderer::on(const signals::parser::text& evt) {
- auto text = evt.cast();
- draw_text(text);
- return true;
-}
-
-bool renderer::on(const signals::parser::control& evt) {
- auto ctrl = evt.cast();
-
- switch (ctrl) {
- case tags::controltag::R:
- m_bg = m_bar.background;
- m_fg = m_bar.foreground;
- m_ul = m_bar.underline.color;
- m_ol = m_bar.overline.color;
- m_font = 0;
- m_attr.reset();
- break;
-
- case tags::controltag::NONE:
- break;
- }
-
- return true;
-}
-
POLYBAR_NS_END
diff --git a/src/tags/context.cpp b/src/tags/context.cpp
new file mode 100644
index 00000000..cd633538
--- /dev/null
+++ b/src/tags/context.cpp
@@ -0,0 +1,116 @@
+#include "tags/context.hpp"
+
+POLYBAR_NS
+
+namespace tags {
+ context::context(const bar_settings& settings) : m_settings(settings) {
+ reset();
+ }
+
+ void context::reset() {
+ apply_reset();
+ m_align = alignment::NONE;
+ }
+
+ void context::apply_bg(color_value c) {
+ m_bg = get_color(c, m_settings.background);
+ }
+
+ void context::apply_fg(color_value c) {
+ m_fg = get_color(c, m_settings.foreground);
+ }
+
+ void context::apply_ol(color_value c) {
+ m_ol = get_color(c, m_settings.overline.color);
+ }
+
+ void context::apply_ul(color_value c) {
+ m_ul = get_color(c, m_settings.underline.color);
+ }
+
+ void context::apply_font(int font) {
+ m_font = std::max(font, 0);
+ }
+
+ void context::apply_reverse() {
+ std::swap(m_bg, m_fg);
+ }
+
+ void context::apply_alignment(alignment align) {
+ m_align = align;
+ }
+
+ void context::apply_attr(attr_activation act, attribute attr) {
+ if (attr == attribute::NONE) {
+ return;
+ }
+
+ bool& current = attr == attribute::OVERLINE ? m_attr_overline : m_attr_underline;
+
+ switch (act) {
+ case attr_activation::ON:
+ current = true;
+ break;
+ case attr_activation::OFF:
+ current = false;
+ break;
+ case attr_activation::TOGGLE:
+ current = !current;
+ break;
+ default:
+ break;
+ }
+ }
+
+ void context::apply_reset() {
+ m_bg = m_settings.background;
+ m_fg = m_settings.foreground;
+ m_ul = m_settings.underline.color;
+ m_ol = m_settings.overline.color;
+ m_font = 0;
+ m_attr_overline = false;
+ m_attr_underline = false;
+ }
+
+ rgba context::get_bg() const {
+ return m_bg;
+ }
+
+ rgba context::get_fg() const {
+ return m_fg;
+ }
+
+ rgba context::get_ol() const {
+ return m_ol;
+ }
+
+ rgba context::get_ul() const {
+ return m_ul;
+ }
+
+ int context::get_font() const {
+ return m_font;
+ }
+
+ bool context::has_overline() const {
+ return m_attr_overline;
+ }
+
+ bool context::has_underline() const {
+ return m_attr_underline;
+ }
+
+ alignment context::get_alignment() const {
+ return m_align;
+ }
+
+ rgba context::get_color(color_value c, rgba fallback) const {
+ if (c.type == color_type::RESET) {
+ return fallback;
+ } else {
+ return c.val;
+ }
+ }
+} // namespace tags
+
+POLYBAR_NS_END
diff --git a/src/tags/dispatch.cpp b/src/tags/dispatch.cpp
index 514fa492..3b1b3ee3 100644
--- a/src/tags/dispatch.cpp
+++ b/src/tags/dispatch.cpp
@@ -14,14 +14,6 @@ POLYBAR_NS
using namespace signals::parser;
namespace tags {
- static rgba get_color(tags::color_value c, rgba fallback) {
- if (c.type == tags::color_type::RESET) {
- return fallback;
- } else {
- return c.val;
- }
- }
-
/**
* Create instance
*/
@@ -41,6 +33,8 @@ namespace tags {
tags::parser p;
p.set(std::move(data));
+ context ctxt(bar);
+
while (p.has_next_element()) {
tags::element el;
try {
@@ -58,36 +52,39 @@ namespace tags {
handle_action(el.tag_data.action.btn, el.tag_data.action.closing, std::move(el.data));
break;
case tags::syntaxtag::B:
- m_sig.emit(change_background{get_color(el.tag_data.color, bar.background)});
+ ctxt.apply_bg(el.tag_data.color);
break;
case tags::syntaxtag::F:
- m_sig.emit(change_foreground{get_color(el.tag_data.color, bar.foreground)});
+ ctxt.apply_fg(el.tag_data.color);
break;
case tags::syntaxtag::T:
- m_sig.emit(change_font{el.tag_data.font});
+ ctxt.apply_font(el.tag_data.font);
break;
case tags::syntaxtag::O:
- renderer.render_offset(tags::context{}, el.tag_data.offset);
+ renderer.render_offset(ctxt, el.tag_data.offset);
break;
case tags::syntaxtag::R:
- m_sig.emit(reverse_colors{});
+ ctxt.apply_reverse();
break;
case tags::syntaxtag::o:
- m_sig.emit(change_overline{get_color(el.tag_data.color, bar.overline.color)});
+ ctxt.apply_ol(el.tag_data.color);
break;
case tags::syntaxtag::u:
- m_sig.emit(change_underline{get_color(el.tag_data.color, bar.underline.color)});
+ ctxt.apply_ul(el.tag_data.color);
break;
case tags::syntaxtag::P:
- m_sig.emit(control{el.tag_data.ctrl});
+ handle_control(ctxt, el.tag_data.ctrl);
break;
case tags::syntaxtag::l:
+ ctxt.apply_alignment(alignment::LEFT);
m_sig.emit(change_alignment{alignment::LEFT});
break;
case tags::syntaxtag::r:
+ ctxt.apply_alignment(alignment::RIGHT);
m_sig.emit(change_alignment{alignment::RIGHT});
break;
case tags::syntaxtag::c:
+ ctxt.apply_alignment(alignment::CENTER);
m_sig.emit(change_alignment{alignment::CENTER});
break;
default:
@@ -96,25 +93,11 @@ namespace tags {
}
break;
case tags::tag_type::ATTR:
- tags::attribute act = el.tag_data.attr;
- switch (el.tag_data.subtype.activation) {
- case tags::attr_activation::ON:
- m_sig.emit(attribute_set{act});
- break;
- case tags::attr_activation::OFF:
- m_sig.emit(attribute_unset{act});
- break;
- case tags::attr_activation::TOGGLE:
- m_sig.emit(attribute_toggle{act});
- break;
- default:
- throw runtime_error("Unrecognized attribute activation: " +
- to_string(static_cast(el.tag_data.subtype.activation)));
- }
+ ctxt.apply_attr(el.tag_data.subtype.activation, el.tag_data.attr);
break;
}
} else {
- text(std::move(el.data));
+ handle_text(renderer, ctxt, std::move(el.data));
}
}
@@ -126,7 +109,7 @@ namespace tags {
/**
* Process text contents
*/
- void dispatch::text(string&& data) {
+ void dispatch::handle_text(renderer_interface& renderer, context& ctxt, string&& data) {
#ifdef DEBUG_WHITESPACE
string::size_type p;
while ((p = data.find(' ')) != string::npos) {
@@ -134,7 +117,7 @@ namespace tags {
}
#endif
- m_sig.emit(signals::parser::text{std::move(data)});
+ renderer.render_text(ctxt, std::move(data));
}
void dispatch::handle_action(mousebtn btn, bool closing, const string&& cmd) {
@@ -166,6 +149,17 @@ namespace tags {
m_sig.emit(action_begin{action{btn, std::move(cmd)}});
}
}
+
+ void dispatch::handle_control(context& ctxt, controltag ctrl) {
+ switch (ctrl) {
+ case controltag::R:
+ ctxt.reset();
+ break;
+ default:
+ throw runtime_error("Unrecognized polybar control tag: " + to_string(static_cast(ctrl)));
+ }
+ }
+
} // namespace tags
POLYBAR_NS_END