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)
This commit is contained in:
patrick96 2019-01-12 14:51:54 +01:00 committed by Patrick Ziegler
parent 928cd92a4f
commit 57d364a2fc
10 changed files with 105 additions and 9 deletions

View File

@ -20,6 +20,7 @@ class builder {
public: public:
explicit builder(const bar_settings& bar); explicit builder(const bar_settings& bar);
void reset();
string flush(); string flush();
void append(string text); void append(string text);
void node(string str, bool add_space = false); void node(string str, bool add_space = false);
@ -49,6 +50,7 @@ class builder {
void overline_close(); void overline_close();
void underline(const string& color = ""); void underline(const string& color = "");
void underline_close(); void underline_close();
void control(controltag tag);
void cmd(mousebtn index, string action, bool condition = true); void cmd(mousebtn index, string action, bool condition = true);
void cmd(mousebtn index, string action, const label_t& label); void cmd(mousebtn index, string action, const label_t& label);
void cmd_close(bool condition = true); void cmd_close(bool condition = true);

View File

@ -7,6 +7,7 @@ POLYBAR_NS
class signal_emitter; class signal_emitter;
enum class attribute; enum class attribute;
enum class controltag;
enum class mousebtn; enum class mousebtn;
struct bar_settings; struct bar_settings;
@ -33,6 +34,7 @@ class parser {
attribute parse_attr(const char attr); attribute parse_attr(const char attr);
mousebtn parse_action_btn(const string& data); mousebtn parse_action_btn(const string& data);
string parse_action_cmd(string&& data); string parse_action_cmd(string&& data);
controltag parse_control(const string& data);
private: private:
signal_emitter& m_sig; signal_emitter& m_sig;

View File

@ -36,7 +36,7 @@ class renderer
signals::parser::change_font, signals::parser::change_alignment, signals::parser::reverse_colors, 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::offset_pixel, signals::parser::attribute_set, signals::parser::attribute_unset,
signals::parser::attribute_toggle, signals::parser::action_begin, signals::parser::action_end, signals::parser::attribute_toggle, signals::parser::action_begin, signals::parser::action_end,
signals::parser::text> { signals::parser::text, signals::parser::control> {
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);
@ -85,6 +85,7 @@ class renderer
bool on(const signals::parser::action_begin& evt); bool on(const signals::parser::action_begin& evt);
bool on(const signals::parser::action_end& evt); bool on(const signals::parser::action_end& evt);
bool on(const signals::parser::text& evt); bool on(const signals::parser::text& evt);
bool on(const signals::parser::control& evt);
protected: protected:
struct reserve_area { struct reserve_area {

View File

@ -37,6 +37,18 @@ enum class syntaxtag {
R, // flip colors R, // flip colors
o, // overline color o, // overline color
u, // underline 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 }; enum class mousebtn { NONE = 0, LEFT, MIDDLE, RIGHT, SCROLL_UP, SCROLL_DOWN, DOUBLE_LEFT, DOUBLE_MIDDLE, DOUBLE_RIGHT };

View File

@ -12,6 +12,7 @@ POLYBAR_NS
// fwd // fwd
enum class mousebtn; enum class mousebtn;
enum class syntaxtag; enum class syntaxtag;
enum class controltag;
enum class alignment; enum class alignment;
enum class attribute; enum class attribute;
@ -179,6 +180,9 @@ namespace signals {
struct text : public detail::value_signal<text, string> { struct text : public detail::value_signal<text, string> {
using base_type::base_type; using base_type::base_type;
}; };
struct control : public detail::value_signal<control, controltag> {
using base_type::base_type;
};
} }
} }

View File

@ -59,6 +59,7 @@ namespace signals {
struct action_begin; struct action_begin;
struct action_end; struct action_end;
struct text; struct text;
struct control;
} }
} }

View File

@ -80,6 +80,11 @@ namespace modules {
if (m_changed) { if (m_changed) {
m_log.info("%s: Rebuilding cache", name()); m_log.info("%s: Rebuilding cache", name());
m_cache = CAST_MOD(Impl)->get_output(); 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; m_changed = false;
} }
return m_cache; return m_cache;

View File

@ -9,25 +9,37 @@
POLYBAR_NS POLYBAR_NS
builder::builder(const bar_settings& bar) : m_bar(bar) { 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 /* Add all values as keys so that we never have to check if a key exists in
* the map * the map
*/ */
m_tags.clear();
m_tags[syntaxtag::NONE] = 0; m_tags[syntaxtag::NONE] = 0;
m_tags[syntaxtag::A] = 0; m_tags[syntaxtag::A] = 0;
m_tags[syntaxtag::B] = 0; m_tags[syntaxtag::B] = 0;
m_tags[syntaxtag::F] = 0; m_tags[syntaxtag::F] = 0;
m_tags[syntaxtag::T] = 0; m_tags[syntaxtag::T] = 0;
m_tags[syntaxtag::R] = 0;
m_tags[syntaxtag::o] = 0; m_tags[syntaxtag::o] = 0;
m_tags[syntaxtag::u] = 0; m_tags[syntaxtag::u] = 0;
m_tags[syntaxtag::P] = 0;
m_colors.clear();
m_colors[syntaxtag::B] = string(); m_colors[syntaxtag::B] = string();
m_colors[syntaxtag::F] = string(); m_colors[syntaxtag::F] = string();
m_colors[syntaxtag::o] = string(); m_colors[syntaxtag::o] = string();
m_colors[syntaxtag::u] = string(); m_colors[syntaxtag::u] = string();
m_attrs.clear();
m_attrs[attribute::NONE] = false; m_attrs[attribute::NONE] = false;
m_attrs[attribute::UNDERLINE] = false; m_attrs[attribute::UNDERLINE] = false;
m_attrs[attribute::OVERLINE] = false; m_attrs[attribute::OVERLINE] = false;
m_output.clear();
m_fontindex = 1;
} }
/** /**
@ -64,11 +76,7 @@ string builder::flush() {
string output{m_output}; string output{m_output};
// reset values reset();
m_tags.clear();
m_colors.clear();
m_output.clear();
m_fontindex = 1;
return output; return output;
} }
@ -404,6 +412,24 @@ void builder::underline_close() {
tag_close(attribute::UNDERLINE); 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 * Open command tag
*/ */
@ -504,6 +530,9 @@ void builder::tag_open(syntaxtag tag, const string& value) {
case syntaxtag::O: case syntaxtag::O:
append("%{O" + value + "}"); append("%{O" + value + "}");
break; break;
case syntaxtag::P:
append("%{P" + value + "}");
break;
} }
} }
@ -540,8 +569,6 @@ void builder::tag_close(syntaxtag tag) {
m_tags[tag]--; m_tags[tag]--;
switch (tag) { switch (tag) {
case syntaxtag::NONE:
break;
case syntaxtag::A: case syntaxtag::A:
append("%{A}"); append("%{A}");
break; break;
@ -560,8 +587,9 @@ void builder::tag_close(syntaxtag tag) {
case syntaxtag::o: case syntaxtag::o:
append("%{o-}"); append("%{o-}");
break; break;
case syntaxtag::NONE:
case syntaxtag::R: case syntaxtag::R:
break; case syntaxtag::P:
case syntaxtag::O: case syntaxtag::O:
break; break;
} }

View File

@ -187,6 +187,11 @@ void parser::codeblock(string&& data, const bar_settings& bar) {
break; break;
} }
// Internal Polybar control tags
case 'P':
m_sig.emit(control{parse_control(value)});
break;
default: default:
throw unrecognized_token("Unrecognized token '" + string{tag} + "'"); throw unrecognized_token("Unrecognized token '" + string{tag} + "'");
} }
@ -292,4 +297,19 @@ string parser::parse_action_cmd(string&& data) {
return data.substr(1, end - 1); 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 POLYBAR_NS_END

View File

@ -2,6 +2,7 @@
#include "cairo/context.hpp" #include "cairo/context.hpp"
#include "components/config.hpp" #include "components/config.hpp"
#include "events/signal.hpp" #include "events/signal.hpp"
#include "events/signal_emitter.hpp"
#include "events/signal_receiver.hpp" #include "events/signal_receiver.hpp"
#include "utils/factory.hpp" #include "utils/factory.hpp"
#include "utils/file.hpp" #include "utils/file.hpp"
@ -827,4 +828,24 @@ bool renderer::on(const signals::parser::text& evt) {
return true; 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 POLYBAR_NS_END