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