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:
parent
928cd92a4f
commit
57d364a2fc
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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<renderer>;
|
||||
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 {
|
||||
|
@ -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 };
|
||||
|
@ -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<text, string> {
|
||||
using base_type::base_type;
|
||||
};
|
||||
struct control : public detail::value_signal<control, controltag> {
|
||||
using base_type::base_type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,7 @@ namespace signals {
|
||||
struct action_begin;
|
||||
struct action_end;
|
||||
struct text;
|
||||
struct control;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user