From 57d364a2fc699e0f2413e1d3df4d4f70e7e2576d Mon Sep 17 00:00:00 2001 From: patrick96 Date: Sat, 12 Jan 2019 14:51:54 +0100 Subject: [PATCH] Reset all tags at the end of a module The %{PR} tag is introduced for this. It resets all colors as well as the activation of the underline and overline and font. This has become necessary because we don't track what raw tags a user injects into the formatting string and otherwise their raw tags could bleed through. This doesn't touch action tags because even before raw action tags weren't being tracked. Action tags also have the requirement that they have to be used in pairs, so closing them prematurely could break things (for example with click actions for the entire bar) --- include/components/builder.hpp | 2 ++ include/components/parser.hpp | 2 ++ include/components/renderer.hpp | 3 ++- include/components/types.hpp | 12 +++++++++ include/events/signal.hpp | 4 +++ include/events/signal_fwd.hpp | 1 + include/modules/meta/base.inl | 5 ++++ src/components/builder.cpp | 44 +++++++++++++++++++++++++++------ src/components/parser.cpp | 20 +++++++++++++++ src/components/renderer.cpp | 21 ++++++++++++++++ 10 files changed, 105 insertions(+), 9 deletions(-) diff --git a/include/components/builder.hpp b/include/components/builder.hpp index 830e0e14..27d1ba17 100644 --- a/include/components/builder.hpp +++ b/include/components/builder.hpp @@ -20,6 +20,7 @@ class builder { public: explicit builder(const bar_settings& bar); + void reset(); string flush(); void append(string text); void node(string str, bool add_space = false); @@ -49,6 +50,7 @@ class builder { void overline_close(); void underline(const string& color = ""); void underline_close(); + void control(controltag tag); void cmd(mousebtn index, string action, bool condition = true); void cmd(mousebtn index, string action, const label_t& label); void cmd_close(bool condition = true); diff --git a/include/components/parser.hpp b/include/components/parser.hpp index 8aeba5c0..54cf1f6f 100644 --- a/include/components/parser.hpp +++ b/include/components/parser.hpp @@ -7,6 +7,7 @@ POLYBAR_NS class signal_emitter; enum class attribute; +enum class controltag; enum class mousebtn; struct bar_settings; @@ -33,6 +34,7 @@ class parser { attribute parse_attr(const char attr); mousebtn parse_action_btn(const string& data); string parse_action_cmd(string&& data); + controltag parse_control(const string& data); private: signal_emitter& m_sig; diff --git a/include/components/renderer.hpp b/include/components/renderer.hpp index 42c6a1d8..1de4e1f2 100644 --- a/include/components/renderer.hpp +++ b/include/components/renderer.hpp @@ -36,7 +36,7 @@ class renderer signals::parser::change_font, signals::parser::change_alignment, signals::parser::reverse_colors, signals::parser::offset_pixel, signals::parser::attribute_set, signals::parser::attribute_unset, signals::parser::attribute_toggle, signals::parser::action_begin, signals::parser::action_end, - signals::parser::text> { + signals::parser::text, signals::parser::control> { public: using make_type = unique_ptr; static make_type make(const bar_settings& bar); @@ -85,6 +85,7 @@ class renderer bool on(const signals::parser::action_begin& evt); bool on(const signals::parser::action_end& evt); bool on(const signals::parser::text& evt); + bool on(const signals::parser::control& evt); protected: struct reserve_area { diff --git a/include/components/types.hpp b/include/components/types.hpp index b9810cc0..0eb9fe4f 100644 --- a/include/components/types.hpp +++ b/include/components/types.hpp @@ -37,6 +37,18 @@ enum class syntaxtag { R, // flip colors o, // overline color u, // underline color + P, // Polybar control tag +}; + +/** + * Values for polybar control tags + * + * %{P...} tags are tags for internal polybar control commands, they are not + * part of the public interface + */ +enum class controltag { + NONE = 0, + R, // Reset all open tags (B, F, T, o, u). Used at module edges }; enum class mousebtn { NONE = 0, LEFT, MIDDLE, RIGHT, SCROLL_UP, SCROLL_DOWN, DOUBLE_LEFT, DOUBLE_MIDDLE, DOUBLE_RIGHT }; diff --git a/include/events/signal.hpp b/include/events/signal.hpp index 98e00198..80eebb9b 100644 --- a/include/events/signal.hpp +++ b/include/events/signal.hpp @@ -12,6 +12,7 @@ POLYBAR_NS // fwd enum class mousebtn; enum class syntaxtag; +enum class controltag; enum class alignment; enum class attribute; @@ -179,6 +180,9 @@ namespace signals { struct text : public detail::value_signal { using base_type::base_type; }; + struct control : public detail::value_signal { + using base_type::base_type; + }; } } diff --git a/include/events/signal_fwd.hpp b/include/events/signal_fwd.hpp index 78129ebe..c7b08ade 100644 --- a/include/events/signal_fwd.hpp +++ b/include/events/signal_fwd.hpp @@ -59,6 +59,7 @@ namespace signals { struct action_begin; struct action_end; struct text; + struct control; } } diff --git a/include/modules/meta/base.inl b/include/modules/meta/base.inl index 1845d186..6ce0cc9c 100644 --- a/include/modules/meta/base.inl +++ b/include/modules/meta/base.inl @@ -80,6 +80,11 @@ namespace modules { if (m_changed) { m_log.info("%s: Rebuilding cache", name()); m_cache = CAST_MOD(Impl)->get_output(); + // Make sure builder is really empty + m_builder->flush(); + // Add a reset tag after the module + m_builder->control(controltag::R); + m_cache += m_builder->flush(); m_changed = false; } return m_cache; diff --git a/src/components/builder.cpp b/src/components/builder.cpp index e11abda3..3120906a 100644 --- a/src/components/builder.cpp +++ b/src/components/builder.cpp @@ -9,25 +9,37 @@ POLYBAR_NS builder::builder(const bar_settings& bar) : m_bar(bar) { + reset(); +} + +void builder::reset() { /* Add all values as keys so that we never have to check if a key exists in * the map */ + m_tags.clear(); m_tags[syntaxtag::NONE] = 0; m_tags[syntaxtag::A] = 0; m_tags[syntaxtag::B] = 0; m_tags[syntaxtag::F] = 0; m_tags[syntaxtag::T] = 0; + m_tags[syntaxtag::R] = 0; m_tags[syntaxtag::o] = 0; m_tags[syntaxtag::u] = 0; + m_tags[syntaxtag::P] = 0; + m_colors.clear(); m_colors[syntaxtag::B] = string(); m_colors[syntaxtag::F] = string(); m_colors[syntaxtag::o] = string(); m_colors[syntaxtag::u] = string(); + m_attrs.clear(); m_attrs[attribute::NONE] = false; m_attrs[attribute::UNDERLINE] = false; m_attrs[attribute::OVERLINE] = false; + + m_output.clear(); + m_fontindex = 1; } /** @@ -64,11 +76,7 @@ string builder::flush() { string output{m_output}; - // reset values - m_tags.clear(); - m_colors.clear(); - m_output.clear(); - m_fontindex = 1; + reset(); return output; } @@ -404,6 +412,24 @@ void builder::underline_close() { tag_close(attribute::UNDERLINE); } +/** + * Add a polybar control tag + */ +void builder::control(controltag tag) { + string str; + switch (tag) { + case controltag::R: + str = "R"; + break; + default: + break; + } + + if(!str.empty()) { + tag_open(syntaxtag::P, str); + } +} + /** * Open command tag */ @@ -504,6 +530,9 @@ void builder::tag_open(syntaxtag tag, const string& value) { case syntaxtag::O: append("%{O" + value + "}"); break; + case syntaxtag::P: + append("%{P" + value + "}"); + break; } } @@ -540,8 +569,6 @@ void builder::tag_close(syntaxtag tag) { m_tags[tag]--; switch (tag) { - case syntaxtag::NONE: - break; case syntaxtag::A: append("%{A}"); break; @@ -560,8 +587,9 @@ void builder::tag_close(syntaxtag tag) { case syntaxtag::o: append("%{o-}"); break; + case syntaxtag::NONE: case syntaxtag::R: - break; + case syntaxtag::P: case syntaxtag::O: break; } diff --git a/src/components/parser.cpp b/src/components/parser.cpp index c84e8971..4ec843e5 100644 --- a/src/components/parser.cpp +++ b/src/components/parser.cpp @@ -187,6 +187,11 @@ void parser::codeblock(string&& data, const bar_settings& bar) { break; } + // Internal Polybar control tags + case 'P': + m_sig.emit(control{parse_control(value)}); + break; + default: throw unrecognized_token("Unrecognized token '" + string{tag} + "'"); } @@ -292,4 +297,19 @@ string parser::parse_action_cmd(string&& data) { return data.substr(1, end - 1); } +controltag parser::parse_control(const string& data) { + if(data.length() != 1) { + return controltag::NONE; + } + + switch(data[0]) { + case 'R': + return controltag::R; + break; + default: + return controltag::NONE; + break; + } +} + POLYBAR_NS_END diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp index 302b12ab..a3ac09d2 100644 --- a/src/components/renderer.cpp +++ b/src/components/renderer.cpp @@ -2,6 +2,7 @@ #include "cairo/context.hpp" #include "components/config.hpp" #include "events/signal.hpp" +#include "events/signal_emitter.hpp" #include "events/signal_receiver.hpp" #include "utils/factory.hpp" #include "utils/file.hpp" @@ -827,4 +828,24 @@ bool renderer::on(const signals::parser::text& evt) { return true; } +bool renderer::on(const signals::parser::control& evt) { + auto ctrl = evt.cast(); + + switch(ctrl) { + case 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 controltag::NONE: + break; + } + + return true; +} + POLYBAR_NS_END