refactor: Cleanup handling of syntax tags

This commit is contained in:
Michael Carlberg 2016-11-24 19:24:47 +01:00
parent 199a825494
commit 84d58e7619
25 changed files with 863 additions and 716 deletions

View file

@ -5,7 +5,6 @@
#endif #endif
#include <boost/di.hpp> #include <boost/di.hpp>
#include <cassert>
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
#include <map> #include <map>

View file

@ -25,88 +25,74 @@ using namespace drawtypes;
class builder { class builder {
public: public:
explicit builder(const bar_settings bar, bool lazy = false) : m_bar(bar), m_lazy(lazy) {} explicit builder(const bar_settings bar) : m_bar(bar) {}
void set_lazy(bool mode);
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);
void node(string str, int font_index, bool add_space = false); void node(string str, int font_index, bool add_space = false);
// void node(progressbar_t bar, float perc, bool add_space = false);
void node(label_t label, bool add_space = false); void node(label_t label, bool add_space = false);
// void node(ramp_t ramp, float perc, bool add_space = false);
// void node(animation_t animation, bool add_space = false);
void offset(int pixels = 0); void offset(int pixels = 0);
void space(int width = DEFAULT_SPACING); void space(int width = DEFAULT_SPACING);
void remove_trailing_space(int width = DEFAULT_SPACING); void remove_trailing_space(int width = DEFAULT_SPACING);
void invert();
void font(int index); void font(int index);
void font_close(bool force = false); void font_close();
void background(string color); void background(string color);
void background_close(bool force = false); void background_close();
void color(string color);
void color(string color_); void color_alpha(string alpha);
void color_alpha(string alpha_); void color_close();
void color_close(bool force = false);
void line_color(string color); void line_color(string color);
void line_color_close(bool force = false); void line_color_close();
void overline_color(string color); void overline_color(string color);
void overline_color_close(bool force = false); void overline_color_close();
void underline_color(string color); void underline_color(string color);
void underline_color_close(bool force = false); void underline_color_close();
void overline(string color = ""); void overline(string color = "");
void overline_close(bool force = false); void overline_close();
void underline(string color = ""); void underline(string color = "");
void underline_close(bool force = false); void underline_close();
void cmd(mousebtn index, string action, bool condition = true); void cmd(mousebtn index, string action, bool condition = true);
void cmd_close(bool force = false); void cmd_close();
protected: protected:
void tag_open(char tag, string value); string background_hex();
void tag_close(char tag); string foreground_hex();
void tag_open(syntaxtag tag, string value);
void tag_open(attribute attr);
void tag_close(syntaxtag tag);
void tag_close(attribute attr);
private: private:
const bar_settings m_bar; const bar_settings m_bar;
string m_output; string m_output;
bool m_lazy = true;
map<syntaxtag, int> m_counters{ map<syntaxtag, int> m_tags{
// clang-format off // clang-format off
{syntaxtag::A, 0}, {syntaxtag::A, 0},
{syntaxtag::B, 0}, {syntaxtag::B, 0},
{syntaxtag::F, 0}, {syntaxtag::F, 0},
{syntaxtag::T, 0}, {syntaxtag::T, 0},
{syntaxtag::U, 0}, {syntaxtag::u, 0},
{syntaxtag::Uo, 0}, {syntaxtag::o, 0},
{syntaxtag::Uu, 0}, // clang-format on
{syntaxtag::O, 0},
{syntaxtag::R, 0},
// clang-format on
}; };
map<syntaxtag, string> m_colors{ map<syntaxtag, string> m_colors{
// clang-format off // clang-format off
{syntaxtag::B, ""}, {syntaxtag::B, ""},
{syntaxtag::F, ""}, {syntaxtag::F, ""},
{syntaxtag::U, ""}, {syntaxtag::u, ""},
{syntaxtag::Uu, ""}, {syntaxtag::o, ""},
{syntaxtag::Uo, ""}, // clang-format on
// clang-format on
}; };
int m_fontindex = 1; uint8_t m_attributes{static_cast<uint8_t>(attribute::NONE)};
uint8_t m_fontindex{1};
string m_background;
string m_foreground;
}; };
POLYBAR_NS_END POLYBAR_NS_END

View file

@ -4,15 +4,17 @@
POLYBAR_NS POLYBAR_NS
class logger;
struct bar_settings; struct bar_settings;
enum class attribute : uint8_t; enum class attribute : uint8_t;
enum class mousebtn : uint8_t; enum class mousebtn : uint8_t;
DEFINE_ERROR(unrecognized_token); DEFINE_ERROR(unrecognized_token);
DEFINE_ERROR(unrecognized_attribute);
class parser { class parser {
public: public:
explicit parser(const bar_settings& bar); explicit parser(const logger& logger, const bar_settings& bar);
void operator()(string data); void operator()(string data);
void codeblock(string data); void codeblock(string data);
size_t text(string data); size_t text(string data);
@ -25,6 +27,7 @@ class parser {
string parse_action_cmd(string data); string parse_action_cmd(string data);
private: private:
const logger& m_log;
const bar_settings& m_bar; const bar_settings& m_bar;
vector<int> m_actions; vector<int> m_actions;
}; };

View file

@ -12,6 +12,8 @@ class logger;
class renderer { class renderer {
public: public:
enum class gc : uint8_t { BG, FG, OL, UL, BT, BB, BL, BR };
explicit renderer(connection& conn, const logger& logger, unique_ptr<font_manager> font_manager, explicit renderer(connection& conn, const logger& logger, unique_ptr<font_manager> font_manager,
const bar_settings& bar, const vector<string>& fonts); const bar_settings& bar, const vector<string>& fonts);
@ -27,26 +29,29 @@ class renderer {
void set_foreground(const uint32_t color); void set_foreground(const uint32_t color);
void set_underline(const uint32_t color); void set_underline(const uint32_t color);
void set_overline(const uint32_t color); void set_overline(const uint32_t color);
void set_fontindex(const uint8_t font); void set_fontindex(const int8_t font);
void set_alignment(const alignment align); void set_alignment(const alignment align);
void set_attribute(const attribute attr, const bool state); void set_attribute(const attribute attr, const bool state);
void toggle_attribute(const attribute attr);
bool check_attribute(const attribute attr);
void fill_background(); void fill_background();
void fill_border(const map<edge, border_settings>& borders, edge border); void fill_border(const map<edge, border_settings>& borders, edge border);
void fill_overline(int16_t x, uint16_t w); void fill_overline(int16_t x, uint16_t w);
void fill_underline(int16_t x, uint16_t w); void fill_underline(int16_t x, uint16_t w);
void fill_shift(const int16_t px);
void draw_character(uint16_t character); void draw_character(const uint16_t character);
void draw_textstring(const char* text, size_t len); void draw_textstring(const char* text, const size_t len);
int16_t shift_content(int16_t x, int16_t shift_x); void begin_action(const mousebtn btn, const string cmd);
int16_t shift_content(int16_t shift_x);
void begin_action(const mousebtn btn, const string& cmd);
void end_action(const mousebtn btn); void end_action(const mousebtn btn);
const vector<action_block> get_actions(); const vector<action_block> get_actions();
protected: protected:
int16_t shift_content(const int16_t x, const int16_t shift_x);
int16_t shift_content(const int16_t shift_x);
void debughints(); void debughints();
private: private:
@ -67,16 +72,13 @@ class renderer {
vector<action_block> m_actions; vector<action_block> m_actions;
// bool m_autosize{false}; // bool m_autosize{false};
int m_currentx{0}; uint16_t m_currentx{0U};
int m_attributes{0};
alignment m_alignment{alignment::NONE}; alignment m_alignment{alignment::NONE};
map<gc, uint32_t> m_colors;
uint8_t m_attributes{0U};
int8_t m_fontindex{DEFAULT_FONT_INDEX};
xcb_font_t m_gcfont{0}; xcb_font_t m_gcfont{XCB_NONE};
uint32_t m_background{0};
uint32_t m_foreground{0};
uint32_t m_underline{0};
uint32_t m_overline{0};
edge m_reserve_at{edge::NONE}; edge m_reserve_at{edge::NONE};
uint16_t m_reserve; uint16_t m_reserve;

View file

@ -12,7 +12,6 @@ enum class mousebtn : uint8_t;
enum class syntaxtag : uint8_t; enum class syntaxtag : uint8_t;
enum class alignment : uint8_t; enum class alignment : uint8_t;
enum class attribute : uint8_t; enum class attribute : uint8_t;
enum class gc : uint8_t;
// }}} // }}}
@ -26,14 +25,18 @@ namespace g_signals {
} }
namespace parser { namespace parser {
extern callback<const uint32_t> background_change;
extern callback<const uint32_t> foreground_change;
extern callback<const uint32_t> underline_change;
extern callback<const uint32_t> overline_change;
extern callback<const alignment> alignment_change; extern callback<const alignment> alignment_change;
extern callback<const attribute> attribute_set; extern callback<const attribute> attribute_set;
extern callback<const attribute> attribute_unset; extern callback<const attribute> attribute_unset;
extern callback<const mousebtn, string> action_block_open; extern callback<const attribute> attribute_toggle;
extern callback<const mousebtn> action_block_close;
extern callback<const gc, const uint32_t> color_change;
extern callback<const int8_t> font_change; extern callback<const int8_t> font_change;
extern callback<const int16_t> pixel_offset; extern callback<const int16_t> pixel_offset;
extern callback<const mousebtn, const string> action_block_open;
extern callback<const mousebtn> action_block_close;
extern callback<const uint16_t> ascii_text_write; extern callback<const uint16_t> ascii_text_write;
extern callback<const uint16_t> unicode_text_write; extern callback<const uint16_t> unicode_text_write;
extern callback<const char*, const size_t> string_write; extern callback<const char*, const size_t> string_write;
@ -41,7 +44,6 @@ namespace g_signals {
namespace tray { namespace tray {
extern callback<const uint16_t> report_slotcount; extern callback<const uint16_t> report_slotcount;
extern callback<const uint32_t> clear_bg;
} }
} }

View file

@ -6,14 +6,28 @@
POLYBAR_NS POLYBAR_NS
enum class edge : uint8_t { NONE = 0, TOP, BOTTOM, LEFT, RIGHT, ALL }; enum class edge : uint8_t { NONE = 0U, TOP, BOTTOM, LEFT, RIGHT, ALL };
enum class alignment : uint8_t { NONE = 0, LEFT, CENTER, RIGHT };
enum class syntaxtag : uint8_t { NONE = 0, A, B, F, T, U, Uu, Uo, O, R, o, u }; enum class alignment : uint8_t { NONE = 0U, LEFT, CENTER, RIGHT };
enum class attribute : uint8_t { NONE = 0, o = 1 << 0, u = 1 << 1 };
enum class mousebtn : uint8_t { NONE = 0, LEFT, MIDDLE, RIGHT, SCROLL_UP, SCROLL_DOWN }; enum class attribute : uint8_t { NONE = 0U, UNDERLINE, OVERLINE };
enum class gc : uint8_t { NONE = 0, BG, FG, OL, UL, BT, BB, BL, BR };
enum class syntaxtag : uint8_t {
NONE = 0U,
A, // mouse action
B, // background color
F, // foreground color
T, // font index
O, // pixel offset
R, // flip colors
o, // overline color
u, // underline color
};
enum class mousebtn : uint8_t { NONE = 0U, LEFT, MIDDLE, RIGHT, SCROLL_UP, SCROLL_DOWN };
enum class strut : uint16_t { enum class strut : uint16_t {
LEFT = 0, LEFT = 0U,
RIGHT, RIGHT,
TOP, TOP,
BOTTOM, BOTTOM,
@ -33,45 +47,45 @@ struct position {
}; };
struct size { struct size {
uint16_t w{0}; uint16_t w{1U};
uint16_t h{0}; uint16_t h{1U};
}; };
struct side_values { struct side_values {
uint16_t left{0}; uint16_t left{0U};
uint16_t right{0}; uint16_t right{0U};
}; };
struct edge_values { struct edge_values {
uint16_t left{0}; uint16_t left{0U};
uint16_t right{0}; uint16_t right{0U};
uint16_t top{0}; uint16_t top{0U};
uint16_t bottom{0}; uint16_t bottom{0U};
}; };
struct border_settings { struct border_settings {
uint32_t color{0xFF000000}; uint32_t color{0xFF000000};
uint16_t size{0}; uint16_t size{0U};
}; };
struct line_settings { struct line_settings {
uint32_t color{0xFF000000}; uint32_t color{0xFF000000};
uint16_t size{0}; uint16_t size{0U};
}; };
struct bar_settings { struct bar_settings {
monitor_t monitor; monitor_t monitor;
edge origin{edge::TOP}; edge origin{edge::TOP};
struct size size {
struct size size{0, 0}; 1U, 1U
};
position pos{0, 0}; position pos{0, 0};
position offset{0, 0}; position offset{0, 0};
position center{0, 0}; position center{0, 0};
side_values padding{0, 0}; side_values padding{0U, 0U};
side_values margin{0, 0}; side_values margin{0U, 0U};
side_values module_margin{0, 2}; side_values module_margin{0U, 2U};
edge_values strut{0, 0, 0, 0}; edge_values strut{0U, 0U, 0U, 0U};
uint32_t background{0xFFFFFFFF}; uint32_t background{0xFFFFFFFF};
uint32_t foreground{0xFF000000}; uint32_t foreground{0xFF000000};
@ -81,7 +95,7 @@ struct bar_settings {
map<edge, border_settings> borders; map<edge, border_settings> borders;
int8_t spacing{1}; uint8_t spacing{1U};
string separator; string separator;
string wmname; string wmname;
@ -89,8 +103,12 @@ struct bar_settings {
bool force_docking{false}; bool force_docking{false};
const xcb_rectangle_t inner_area() const { const xcb_rectangle_t inner_area(bool local_coords = false) const {
xcb_rectangle_t rect{pos.x, pos.y, size.w, size.h}; xcb_rectangle_t rect{pos.x, pos.y, size.w, size.h};
if (local_coords) {
rect.x = 0;
rect.y = 0;
}
rect.y += borders.at(edge::TOP).size; rect.y += borders.at(edge::TOP).size;
rect.height -= borders.at(edge::TOP).size; rect.height -= borders.at(edge::TOP).size;
rect.height -= borders.at(edge::BOTTOM).size; rect.height -= borders.at(edge::BOTTOM).size;

View file

@ -28,20 +28,22 @@
#endif #endif
#endif #endif
#define BUILDER_SPACE_TOKEN "%__" static constexpr const char* ALSA_SOUNDCARD{"default"};
static constexpr const char* BSPWM_SOCKET_PATH{"/tmp/bspwm_0_0-socket"};
static constexpr const char* BSPWM_STATUS_PREFIX{"W"};
static constexpr const char* CONNECTION_TEST_IP{"8.8.8.8"};
static constexpr const char* PATH_ADAPTER{"/sys/class/power_supply/%adapter%"};
static constexpr const char* PATH_BACKLIGHT_MAX{"/sys/class/backlight/%card%/max_brightness"};
static constexpr const char* PATH_BACKLIGHT_VAL{"/sys/class/backlight/%card%/brightness"};
static constexpr const char* PATH_BATTERY{"/sys/class/power_supply/%battery%"};
static constexpr const char* PATH_CPU_INFO{"/proc/stat"};
static constexpr const char* PATH_MEMORY_INFO{"/proc/meminfo"};
static constexpr const char* PATH_MESSAGING_FIFO{"/tmp/polybar_mqueue.%pid%"};
static constexpr const char* PATH_TEMPERATURE_INFO{"/sys/class/thermal/thermal_zone%zone%/temp"};
#define ALSA_SOUNDCARD "@SETTING_ALSA_SOUNDCARD@" static constexpr const char* BUILDER_SPACE_TOKEN{"%__"};
#define BSPWM_SOCKET_PATH "@SETTING_BSPWM_SOCKET_PATH@"
#define BSPWM_STATUS_PREFIX "@SETTING_BSPWM_STATUS_PREFIX@" static const int8_t DEFAULT_FONT_INDEX{-1};
#define CONNECTION_TEST_IP "@SETTING_CONNECTION_TEST_IP@"
#define PATH_ADAPTER "@SETTING_PATH_ADAPTER@"
#define PATH_BACKLIGHT_MAX "@SETTING_PATH_BACKLIGHT_MAX@"
#define PATH_BACKLIGHT_VAL "@SETTING_PATH_BACKLIGHT_VAL@"
#define PATH_BATTERY "@SETTING_PATH_BATTERY@"
#define PATH_CPU_INFO "@SETTING_PATH_CPU_INFO@"
#define PATH_MEMORY_INFO "@SETTING_PATH_MEMORY_INFO@"
#define PATH_MESSAGING_FIFO "@SETTING_PATH_MESSAGING_FIFO@"
#define PATH_TEMPERATURE_INFO "@SETTING_PATH_TEMPERATURE_INFO@"
auto version_details = [](const std::vector<std::string>& args) { auto version_details = [](const std::vector<std::string>& args) {
for (auto&& arg : args) { for (auto&& arg : args) {

View file

@ -12,11 +12,7 @@ POLYBAR_NS
namespace drawtypes { namespace drawtypes {
class progressbar : public non_copyable_mixin<progressbar> { class progressbar : public non_copyable_mixin<progressbar> {
public: public:
explicit progressbar( explicit progressbar(const bar_settings bar, int width, string format);
const bar_settings& bar, int width, string format, bool lazy_builder_closing = true)
: m_builder(make_unique<builder>(bar, lazy_builder_closing))
, m_format(format)
, m_width(width) {}
void set_fill(icon_t&& fill); void set_fill(icon_t&& fill);
void set_empty(icon_t&& empty); void set_empty(icon_t&& empty);
@ -44,8 +40,7 @@ namespace drawtypes {
using progressbar_t = shared_ptr<progressbar>; using progressbar_t = shared_ptr<progressbar>;
progressbar_t load_progressbar( progressbar_t load_progressbar(const bar_settings& bar, const config& conf, string section, string name);
const bar_settings& bar, const config& conf, string section, string name);
} }
POLYBAR_NS_END POLYBAR_NS_END

View file

@ -88,7 +88,23 @@ namespace color_util {
inline uint32_t parse(string hex, uint32_t fallback = 0) { inline uint32_t parse(string hex, uint32_t fallback = 0) {
if ((hex = parse_hex(hex)).empty()) if ((hex = parse_hex(hex)).empty())
return fallback; return fallback;
return std::strtoul(&hex[1], nullptr, 16); return strtoul(&hex[1], nullptr, 16);
}
inline string simplify_hex(string hex) {
// convert #ffrrggbb to #rrggbb
if (hex.length() == 9 && hex[1] == 'f' && hex[2] == 'f') {
hex.erase(1, 2);
}
// convert #rrggbb to #rgb
if (hex.length() == 7) {
if (hex[1] == hex[2] && hex[3] == hex[4] && hex[5] == hex[6]) {
hex = {'#', hex[1], hex[3], hex[5]};
}
}
return hex;
} }
} }

View file

@ -42,7 +42,7 @@ class font_manager {
explicit font_manager(connection& conn, const logger& logger); explicit font_manager(connection& conn, const logger& logger);
~font_manager(); ~font_manager();
bool load(string name, int8_t fontindex = -1, int8_t offset_y = 0); bool load(string name, int8_t fontindex = DEFAULT_FONT_INDEX, int8_t offset_y = 0);
void set_preferred_font(int8_t index); void set_preferred_font(int8_t index);
@ -72,7 +72,7 @@ class font_manager {
Colormap m_colormap{}; Colormap m_colormap{};
map<uint8_t, font_t> m_fonts; map<uint8_t, font_t> m_fonts;
int8_t m_fontindex{-1}; int8_t m_fontindex{DEFAULT_FONT_INDEX};
XftColor m_xftcolor{}; XftColor m_xftcolor{};
XftDraw* m_xftdraw{nullptr}; XftDraw* m_xftdraw{nullptr};

View file

@ -1,3 +1,4 @@
#include <cassert>
#include <thread> #include <thread>
#include "adapters/mpd.hpp" #include "adapters/mpd.hpp"

View file

@ -19,6 +19,8 @@
POLYBAR_NS POLYBAR_NS
namespace ph = std::placeholders;
/** /**
* Configure injection module * Configure injection module
*/ */
@ -47,21 +49,6 @@ bar::bar(connection& conn, const config& config, const logger& logger, unique_pt
*/ */
bar::~bar() { bar::~bar() {
std::lock_guard<std::mutex> guard(m_mutex); std::lock_guard<std::mutex> guard(m_mutex);
// Disconnect signal handlers {{{
g_signals::parser::alignment_change = nullptr;
g_signals::parser::attribute_set = nullptr;
g_signals::parser::attribute_unset = nullptr;
g_signals::parser::action_block_open = nullptr;
g_signals::parser::action_block_close = nullptr;
g_signals::parser::color_change = nullptr;
g_signals::parser::font_change = nullptr;
g_signals::parser::pixel_offset = nullptr;
g_signals::parser::ascii_text_write = nullptr;
g_signals::parser::unicode_text_write = nullptr;
g_signals::parser::string_write = nullptr;
g_signals::tray::report_slotcount = nullptr; // }}}
m_connection.detach_sink(this, 1); m_connection.detach_sink(this, 1);
} }
@ -152,52 +139,6 @@ void bar::bootstrap(bool nodraw) {
return; return;
} }
m_log.trace("bar: Attach parser signal handlers");
{
// clang-format off
g_signals::parser::alignment_change = [this](const alignment align) {
m_renderer->set_alignment(align);
};
g_signals::parser::attribute_set = [this](const attribute attr) {
m_renderer->set_attribute(attr, true);
};
g_signals::parser::attribute_unset = [this](const attribute attr) {
m_renderer->set_attribute(attr, false);
};
g_signals::parser::action_block_open = [this](const mousebtn btn, string cmd) {
m_renderer->begin_action(btn, cmd);
};
g_signals::parser::action_block_close = [this](const mousebtn btn) {
m_renderer->end_action(btn);
};
g_signals::parser::color_change= [this](const gc gcontext, const uint32_t color) {
if (gcontext == gc::BG)
m_renderer->set_background(color);
else if (gcontext == gc::FG)
m_renderer->set_foreground(color);
else if (gcontext == gc::UL)
m_renderer->set_underline(color);
else if (gcontext == gc::OL)
m_renderer->set_overline(color);
};
g_signals::parser::font_change = [this](const int8_t font) {
m_renderer->set_fontindex(font);
};
g_signals::parser::pixel_offset = [this](const int16_t px) {
m_renderer->shift_content(px);
};
g_signals::parser::ascii_text_write = [this](const uint16_t c) {
m_renderer->draw_character(c);
};
g_signals::parser::unicode_text_write = [this](const uint16_t c) {
m_renderer->draw_character(c);
};
g_signals::parser::string_write = [this](const char* text, const size_t len) {
m_renderer->draw_textstring(text, len);
};
// clang-format on
}
m_log.trace("bar: Attaching sink to registry"); m_log.trace("bar: Attaching sink to registry");
m_connection.attach_sink(this, 1); m_connection.attach_sink(this, 1);
@ -210,11 +151,33 @@ void bar::bootstrap(bool nodraw) {
reconfigure_window(); reconfigure_window();
m_connection.map_window(m_window); m_connection.map_window(m_window);
m_connection.flush();
m_log.trace("bar: Attach parser signal handlers");
g_signals::parser::background_change = bind(&renderer::set_background, m_renderer.get(), ph::_1);
g_signals::parser::foreground_change = bind(&renderer::set_foreground, m_renderer.get(), ph::_1);
g_signals::parser::underline_change = bind(&renderer::set_underline, m_renderer.get(), ph::_1);
g_signals::parser::overline_change = bind(&renderer::set_overline, m_renderer.get(), ph::_1);
g_signals::parser::pixel_offset = bind(&renderer::fill_shift, m_renderer.get(), ph::_1);
g_signals::parser::alignment_change = bind(&renderer::set_alignment, m_renderer.get(), ph::_1);
g_signals::parser::attribute_set = bind(&renderer::set_attribute, m_renderer.get(), ph::_1, true);
g_signals::parser::attribute_unset = bind(&renderer::set_attribute, m_renderer.get(), ph::_1, false);
g_signals::parser::attribute_toggle = bind(&renderer::toggle_attribute, m_renderer.get(), ph::_1);
g_signals::parser::action_block_open = bind(&renderer::begin_action, m_renderer.get(), ph::_1, ph::_2);
g_signals::parser::action_block_close = bind(&renderer::end_action, m_renderer.get(), ph::_1);
g_signals::parser::font_change = bind(&renderer::set_fontindex, m_renderer.get(), ph::_1);
g_signals::parser::ascii_text_write = bind(&renderer::draw_character, m_renderer.get(), ph::_1);
g_signals::parser::unicode_text_write = bind(&renderer::draw_character, m_renderer.get(), ph::_1);
g_signals::parser::string_write = bind(&renderer::draw_textstring, m_renderer.get(), ph::_1, ph::_2);
// Render empty bar // Render empty bar
m_renderer->begin(); try {
m_renderer->end(); m_renderer->begin();
m_renderer->end();
} catch (const exception& err) {
throw application_error("Failed to output empty bar window (reason: " + string{err.what()} + ")");
}
m_connection.flush();
} }
/** /**
@ -404,13 +367,18 @@ void bar::parse(string data, bool force) {
m_renderer->begin(); m_renderer->begin();
try { try {
parser parser(m_opts); parser parser{m_log, m_opts};
parser(data); parser(data);
} catch (const unrecognized_token& err) { } catch (const unrecognized_token& err) {
m_log.err("Unrecognized syntax token '%s'", err.what()); m_log.err("Unrecognized syntax token '%s'", err.what());
} catch (const unrecognized_attribute& err) {
m_log.err("Unrecognized attribute '%s'", err.what());
} catch (const exception& err) {
m_log.err("Error parsing contents (err: %s)", err.what());
} }
m_renderer->end(); m_renderer->end();
m_connection.flush();
} }
/** /**
@ -666,7 +634,6 @@ void bar::handle(const evt::expose& evt) {
* pseudo-transparent background when it changes * pseudo-transparent background when it changes
*/ */
void bar::handle(const evt::property_notify& evt) { void bar::handle(const evt::property_notify& evt) {
(void)evt;
#if DEBUG #if DEBUG
string atom_name = m_connection.get_atom_name(evt->atom).name(); string atom_name = m_connection.get_atom_name(evt->atom).name();
m_log.trace("bar: property_notify(%s)", atom_name); m_log.trace("bar: property_notify(%s)", atom_name);
@ -674,7 +641,7 @@ void bar::handle(const evt::property_notify& evt) {
if (evt->window == m_window && evt->atom == WM_STATE) { if (evt->window == m_window && evt->atom == WM_STATE) {
if (!g_signals::bar::visibility_change) { if (!g_signals::bar::visibility_change) {
return; return m_log.trace("bar: no callback handler set for bar visibility change");
} }
try { try {

View file

@ -6,41 +6,57 @@
POLYBAR_NS POLYBAR_NS
void builder::set_lazy(bool mode) { /**
m_lazy = mode; * Flush contents of the builder and return built string
} *
* This will also close any unclosed tags
*/
string builder::flush() { string builder::flush() {
while (m_counters[syntaxtag::A] > 0) cmd_close(true); if (m_tags[syntaxtag::A])
while (m_counters[syntaxtag::B] > 0) background_close(true); cmd_close();
while (m_counters[syntaxtag::F] > 0) color_close(true); if (m_tags[syntaxtag::B])
while (m_counters[syntaxtag::T] > 0) font_close(true); background_close();
while (m_counters[syntaxtag::Uo] > 0) overline_color_close(true); if (m_tags[syntaxtag::F])
while (m_counters[syntaxtag::Uu] > 0) underline_color_close(true); color_close();
while (m_counters[syntaxtag::U] > 0) line_color_close(true); if (m_tags[syntaxtag::T])
while (m_counters[syntaxtag::u] > 0) underline_close(true); font_close();
while (m_counters[syntaxtag::o] > 0) overline_close(true); if (m_tags[syntaxtag::o])
overline_color_close();
if (m_tags[syntaxtag::u])
underline_color_close();
if ((m_attributes >> static_cast<uint8_t>(attribute::UNDERLINE)) & 1U)
underline_close();
if ((m_attributes >> static_cast<uint8_t>(attribute::OVERLINE)) & 1U)
overline_close();
string output = m_output.data(); string output = m_output.data();
// reset values // reset values
m_output.clear(); for (auto& counter : m_tags) counter.second = 0;
for (auto& counter : m_counters) counter.second = 0;
for (auto& value : m_colors) value.second = ""; for (auto& value : m_colors) value.second = "";
m_output.clear();
m_fontindex = 1; m_fontindex = 1;
return string_util::replace_all(output, string{BUILDER_SPACE_TOKEN}, " "); return string_util::replace_all(output, string{BUILDER_SPACE_TOKEN}, " ");
} }
/**
* Insert raw text string
*/
void builder::append(string text) { void builder::append(string text) {
string str(text); string str(text);
auto len = str.length(); size_t len{str.length()};
if (len > 2 && str[0] == '"' && str[len - 1] == '"') if (len > 2 && str[0] == '"' && str[len - 1] == '"')
m_output += str.substr(1, len - 2); m_output += str.substr(1, len - 2);
else else
m_output += str; m_output += str;
} }
/**
* Insert text node
*
* This will also parse raw syntax tags
*/
void builder::node(string str, bool add_space) { void builder::node(string str, bool add_space) {
string::size_type n, m; string::size_type n, m;
string s(str); string s(str);
@ -50,7 +66,7 @@ void builder::node(string str, bool add_space) {
break; break;
} else if ((n = s.find("%{F-}")) == 0) { } else if ((n = s.find("%{F-}")) == 0) {
color_close(true); color_close();
s.erase(0, 5); s.erase(0, 5);
} else if ((n = s.find("%{F#")) == 0 && (m = s.find("}")) != string::npos) { } else if ((n = s.find("%{F#")) == 0 && (m = s.find("}")) != string::npos) {
@ -61,7 +77,7 @@ void builder::node(string str, bool add_space) {
s.erase(n, m + 1); s.erase(n, m + 1);
} else if ((n = s.find("%{B-}")) == 0) { } else if ((n = s.find("%{B-}")) == 0) {
background_close(true); background_close();
s.erase(0, 5); s.erase(0, 5);
} else if ((n = s.find("%{B#")) == 0 && (m = s.find("}")) != string::npos) { } else if ((n = s.find("%{B#")) == 0 && (m = s.find("}")) != string::npos) {
@ -69,7 +85,7 @@ void builder::node(string str, bool add_space) {
s.erase(n, m + 1); s.erase(n, m + 1);
} else if ((n = s.find("%{T-}")) == 0) { } else if ((n = s.find("%{T-}")) == 0) {
font_close(true); font_close();
s.erase(0, 5); s.erase(0, 5);
} else if ((n = s.find("%{T")) == 0 && (m = s.find("}")) != string::npos) { } else if ((n = s.find("%{T")) == 0 && (m = s.find("}")) != string::npos) {
@ -77,23 +93,23 @@ void builder::node(string str, bool add_space) {
s.erase(n, m + 1); s.erase(n, m + 1);
} else if ((n = s.find("%{U-}")) == 0) { } else if ((n = s.find("%{U-}")) == 0) {
line_color_close(true); line_color_close();
s.erase(0, 5); s.erase(0, 5);
} else if ((n = s.find("%{Uu-}")) == 0) { } else if ((n = s.find("%{u-}")) == 0) {
underline_color_close(true); underline_color_close();
s.erase(0, 6); s.erase(0, 5);
} else if ((n = s.find("%{Uo-}")) == 0) { } else if ((n = s.find("%{o-}")) == 0) {
overline_color_close(true); overline_color_close();
s.erase(0, 6); s.erase(0, 5);
} else if ((n = s.find("%{Uu#")) == 0 && (m = s.find("}")) != string::npos) { } else if ((n = s.find("%{u#")) == 0 && (m = s.find("}")) != string::npos) {
underline_color(s.substr(n + 4, m - 4)); underline_color(s.substr(n + 3, m - 3));
s.erase(n, m + 1); s.erase(n, m + 1);
} else if ((n = s.find("%{Uo#")) == 0 && (m = s.find("}")) != string::npos) { } else if ((n = s.find("%{o#")) == 0 && (m = s.find("}")) != string::npos) {
overline_color(s.substr(n + 4, m - 4)); overline_color(s.substr(n + 3, m - 3));
s.erase(n, m + 1); s.erase(n, m + 1);
} else if ((n = s.find("%{U#")) == 0 && (m = s.find("}")) != string::npos) { } else if ((n = s.find("%{U#")) == 0 && (m = s.find("}")) != string::npos) {
@ -109,15 +125,15 @@ void builder::node(string str, bool add_space) {
s.erase(0, 5); s.erase(0, 5);
} else if ((n = s.find("%{-u}")) == 0) { } else if ((n = s.find("%{-u}")) == 0) {
underline_close(true); underline_close();
s.erase(0, 5); s.erase(0, 5);
} else if ((n = s.find("%{-o}")) == 0) { } else if ((n = s.find("%{-o}")) == 0) {
overline_close(true); overline_close();
s.erase(0, 5); s.erase(0, 5);
} else if ((n = s.find("%{A}")) == 0) { } else if ((n = s.find("%{A}")) == 0) {
cmd_close(true); cmd_close();
s.erase(0, 4); s.erase(0, 4);
} else if ((n = s.find("%{")) == 0 && (m = s.find("}")) != string::npos) { } else if ((n = s.find("%{")) == 0 && (m = s.find("}")) != string::npos) {
@ -138,35 +154,36 @@ void builder::node(string str, bool add_space) {
space(); space();
} }
/**
* Insert text node with specific font index
*
* @see builder::node
*/
void builder::node(string str, int font_index, bool add_space) { void builder::node(string str, int font_index, bool add_space) {
font(font_index); font(font_index);
node(str, add_space); node(str, add_space);
font_close(); font_close();
} }
// void builder::node(progressbar_t bar, float perc, bool add_space) { /**
// if (!bar) * Insert tags for given label
// return; */
// node(bar->get_output(math_util::cap<float>(0, 100, perc)), add_space);
// }
void builder::node(label_t label, bool add_space) { void builder::node(label_t label, bool add_space) {
if (!label || !*label) if (!label || !*label)
return; return;
auto text = label->get(); string text{label->get()};
if (label->m_maxlen > 0 && text.length() > label->m_maxlen) { if (label->m_maxlen > 0 && text.length() > label->m_maxlen) {
text = text.substr(0, label->m_maxlen) + "..."; text = text.substr(0, label->m_maxlen) + "...";
} }
if ((label->m_overline.empty() && m_counters[syntaxtag::o] > 0) || // if ((label->m_overline.empty() && m_tags[syntaxtag::o] > 0) || (m_tags[syntaxtag::o] > 0 && label->m_margin > 0))
(m_counters[syntaxtag::o] > 0 && label->m_margin > 0)) // overline_close();
overline_close(true); // if ((label->m_underline.empty() && m_tags[syntaxtag::u] > 0) || (m_tags[syntaxtag::u] > 0 && label->m_margin > 0))
if ((label->m_underline.empty() && m_counters[syntaxtag::u] > 0) || // underline_close();
(m_counters[syntaxtag::u] > 0 && label->m_margin > 0))
underline_close(true);
// TODO: Replace with margin-left
if (label->m_margin > 0) if (label->m_margin > 0)
space(label->m_margin); space(label->m_margin);
@ -175,46 +192,48 @@ void builder::node(label_t label, bool add_space) {
if (!label->m_underline.empty()) if (!label->m_underline.empty())
underline(label->m_underline); underline(label->m_underline);
background(label->m_background); if (!label->m_background.empty())
color(label->m_foreground); background(label->m_background);
if (!label->m_foreground.empty())
color(label->m_foreground);
// TODO: Replace with padding-left
if (label->m_padding > 0) if (label->m_padding > 0)
space(label->m_padding); space(label->m_padding);
node(text, label->m_font, add_space); node(text, label->m_font, add_space);
// TODO: Replace with padding-right
if (label->m_padding > 0) if (label->m_padding > 0)
space(label->m_padding); space(label->m_padding);
color_close(m_lazy && label->m_margin > 0); if (!label->m_background.empty())
background_close(m_lazy && label->m_margin > 0); background_close();
if (!label->m_foreground.empty())
color_close();
if (!label->m_underline.empty() || (label->m_margin > 0 && m_counters[syntaxtag::u] > 0)) if (!label->m_underline.empty() || (label->m_margin > 0 && m_tags[syntaxtag::u] > 0))
underline_close(m_lazy && label->m_margin > 0); underline_close();
if (!label->m_overline.empty() || (label->m_margin > 0 && m_counters[syntaxtag::o] > 0)) if (!label->m_overline.empty() || (label->m_margin > 0 && m_tags[syntaxtag::o] > 0))
overline_close(m_lazy && label->m_margin > 0); overline_close();
// TODO: Replace with margin-right
if (label->m_margin > 0) if (label->m_margin > 0)
space(label->m_margin); space(label->m_margin);
} }
// void builder::node(ramp_t ramp, float perc, bool add_space) { /**
// if (!ramp) * Insert tag that will offset the contents by given pixels
// return; */
// node(ramp->get_by_percentage(math_util::cap<float>(0, 100, perc)), add_space);
// }
// void builder::node(animation_t animation, bool add_space) {
// if (!animation)
// return;
// node(animation->get(), add_space);
// }
void builder::offset(int pixels) { void builder::offset(int pixels) {
if (pixels != 0) if (pixels == 0)
tag_open('O', std::to_string(pixels)); return;
tag_open(syntaxtag::O, to_string(pixels));
} }
/**
* Insert spaces
*/
void builder::space(int width) { void builder::space(int width) {
if (width == DEFAULT_SPACING) if (width == DEFAULT_SPACING)
width = m_bar.spacing; width = m_bar.spacing;
@ -224,6 +243,9 @@ void builder::space(int width) {
append(str); append(str);
} }
/**
* Remove trailing space
*/
void builder::remove_trailing_space(int width) { void builder::remove_trailing_space(int width) {
if (width == DEFAULT_SPACING) if (width == DEFAULT_SPACING)
width = m_bar.spacing; width = m_bar.spacing;
@ -235,87 +257,70 @@ void builder::remove_trailing_space(int width) {
m_output = m_output.substr(0, m_output.length() - spacing); m_output = m_output.substr(0, m_output.length() - spacing);
} }
void builder::invert() { /**
tag_open('R', ""); * Insert tag to alter the current font index
} */
void builder::font(int index) { void builder::font(int index) {
if (index <= 0 && m_counters[syntaxtag::T] > 0)
font_close(true);
if (index <= 0 || index == m_fontindex)
return;
if (m_lazy && m_counters[syntaxtag::T] > 0)
font_close(true);
m_counters[syntaxtag::T]++;
m_fontindex = index; m_fontindex = index;
tag_open('T', std::to_string(index)); tag_open(syntaxtag::T, to_string(index));
} }
void builder::font_close(bool force) { /**
if ((!force && m_lazy) || m_counters[syntaxtag::T] <= 0) * Insert tag to reset the font index
return; */
void builder::font_close() {
m_counters[syntaxtag::T]--;
m_fontindex = 1; m_fontindex = 1;
tag_close('T'); tag_close(syntaxtag::T);
} }
/**
* Insert tag to alter the current background color
*/
void builder::background(string color) { void builder::background(string color) {
if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) { if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) {
string bg{background_hex()};
color = "#" + color.substr(color.length() - 2); color = "#" + color.substr(color.length() - 2);
auto bg = color_util::hex<uint16_t>(m_bar.background);
color += bg.substr(bg.length() - (bg.length() < 6 ? 3 : 6)); color += bg.substr(bg.length() - (bg.length() < 6 ? 3 : 6));
} else if (color.length() >= 7 && color == "#" + string(color.length() - 1, color[1])) { } else if (color.length() >= 7 && color == "#" + string(color.length() - 1, color[1])) {
color = color.substr(0, 4); color = color.substr(0, 4);
} }
if (color.empty() && m_counters[syntaxtag::B] > 0) color = color_util::simplify_hex(color);
background_close(true);
if (color.empty() || color == m_colors[syntaxtag::B])
return;
if (m_lazy && m_counters[syntaxtag::B] > 0)
background_close(true);
m_counters[syntaxtag::B]++;
m_colors[syntaxtag::B] = color; m_colors[syntaxtag::B] = color;
tag_open('B', color); tag_open(syntaxtag::B, color);
} }
void builder::background_close(bool force) { /**
if ((!force && m_lazy) || m_counters[syntaxtag::B] <= 0) * Insert tag to reset the background color
return; */
void builder::background_close() {
m_counters[syntaxtag::B]--;
m_colors[syntaxtag::B] = ""; m_colors[syntaxtag::B] = "";
tag_close('B'); tag_close(syntaxtag::B);
} }
void builder::color(string color_) { /**
auto color(color_); * Insert tag to alter the current foreground color
*/
void builder::color(string color) {
if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) { if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) {
string fg{foreground_hex()};
color = "#" + color.substr(color.length() - 2); color = "#" + color.substr(color.length() - 2);
auto fg = color_util::hex<uint16_t>(m_bar.foreground);
color += fg.substr(fg.length() - (fg.length() < 6 ? 3 : 6)); color += fg.substr(fg.length() - (fg.length() < 6 ? 3 : 6));
} else if (color.length() >= 7 && color == "#" + string(color.length() - 1, color[1])) { } else if (color.length() >= 7 && color == "#" + string(color.length() - 1, color[1])) {
color = color.substr(0, 4); color = color.substr(0, 4);
} }
if (color.empty() && m_counters[syntaxtag::F] > 0) color = color_util::simplify_hex(color);
color_close(true);
if (color.empty() || color == m_colors[syntaxtag::F])
return;
if (m_lazy && m_counters[syntaxtag::F] > 0)
color_close(true);
m_counters[syntaxtag::F]++;
m_colors[syntaxtag::F] = color; m_colors[syntaxtag::F] = color;
tag_open('F', color); tag_open(syntaxtag::F, color);
} }
void builder::color_alpha(string alpha_) { /**
auto alpha(alpha_); * Insert tag to alter the alpha value of the default foreground color
string val = color_util::hex<uint16_t>(m_bar.foreground); */
void builder::color_alpha(string alpha) {
string val{foreground_hex()};
if (alpha.find("#") == std::string::npos) { if (alpha.find("#") == std::string::npos) {
alpha = "#" + alpha; alpha = "#" + alpha;
} }
@ -332,117 +337,103 @@ void builder::color_alpha(string alpha_) {
color((alpha.substr(0, 3) + val.substr(val.size() - 6)).substr(0, 9)); color((alpha.substr(0, 3) + val.substr(val.size() - 6)).substr(0, 9));
} }
void builder::color_close(bool force) { /**
if ((!force && m_lazy) || m_counters[syntaxtag::F] <= 0) * Insert tag to reset the foreground color
return; */
void builder::color_close() {
m_counters[syntaxtag::F]--;
m_colors[syntaxtag::F] = ""; m_colors[syntaxtag::F] = "";
tag_close('F'); tag_close(syntaxtag::F);
} }
/**
* Insert tag to alter the current overline/underline color
*/
void builder::line_color(string color) { void builder::line_color(string color) {
if (color.empty() && m_counters[syntaxtag::U] > 0) overline_color(color);
line_color_close(true); underline_color(color);
if (color.empty() || color == m_colors[syntaxtag::U])
return;
if (m_lazy && m_counters[syntaxtag::U] > 0)
line_color_close(true);
m_counters[syntaxtag::U]++;
m_colors[syntaxtag::U] = color;
tag_open('U', color);
} }
void builder::line_color_close(bool force) { /**
if ((!force && m_lazy) || m_counters[syntaxtag::U] <= 0) * Close overline/underline color tag
return; */
void builder::line_color_close() {
m_counters[syntaxtag::U]--; overline_color_close();
m_colors[syntaxtag::U] = ""; underline_color_close();
tag_close('U');
} }
/**
* Insert tag to alter the current overline color
*/
void builder::overline_color(string color) { void builder::overline_color(string color) {
if (color.empty() && m_counters[syntaxtag::Uo] > 0) color = color_util::simplify_hex(color);
overline_color_close(true); m_colors[syntaxtag::o] = color;
if (color.empty() || color == m_colors[syntaxtag::Uo]) tag_open(syntaxtag::o, color);
return; tag_open(attribute::OVERLINE);
if (m_lazy && m_counters[syntaxtag::Uo] > 0)
overline_color_close(true);
m_counters[syntaxtag::Uo]++;
m_colors[syntaxtag::Uo] = color;
append("%{Uo" + color + "}");
} }
void builder::overline_color_close(bool force) { /**
if ((!force && m_lazy) || m_counters[syntaxtag::Uo] <= 0) * Close underline color tag
return; */
void builder::overline_color_close() {
m_counters[syntaxtag::Uo]--; m_colors[syntaxtag::o] = "";
m_colors[syntaxtag::Uo] = ""; tag_close(syntaxtag::o);
append("%{Uu-}");
} }
/**
* Insert tag to alter the current underline color
*/
void builder::underline_color(string color) { void builder::underline_color(string color) {
if (color.empty() && m_counters[syntaxtag::Uu] > 0) color = color_util::simplify_hex(color);
underline_color_close(true); m_colors[syntaxtag::u] = color;
if (color.empty() || color == m_colors[syntaxtag::Uu]) tag_open(syntaxtag::u, color);
return; tag_open(attribute::UNDERLINE);
if (m_lazy && m_counters[syntaxtag::Uu] > 0)
underline_color_close(true);
m_counters[syntaxtag::Uu]++;
m_colors[syntaxtag::Uu] = color;
append("%{Uu" + color + "}");
} }
void builder::underline_color_close(bool force) { /**
if ((!force && m_lazy) || m_counters[syntaxtag::Uu] <= 0) * Close underline color tag
return; */
void builder::underline_color_close() {
m_counters[syntaxtag::Uu]--; tag_close(syntaxtag::u);
m_colors[syntaxtag::Uu] = ""; m_colors[syntaxtag::u] = "";
append("%{Uu-}");
} }
/**
* Insert tag to enable the overline attribute
*/
void builder::overline(string color) { void builder::overline(string color) {
if (!color.empty()) if (!color.empty())
overline_color(color); overline_color(color);
if (m_counters[syntaxtag::o] > 0) else
return; tag_open(attribute::OVERLINE);
m_counters[syntaxtag::o]++;
append("%{+o}");
} }
void builder::overline_close(bool force) { /**
if ((!force && m_lazy) || m_counters[syntaxtag::o] <= 0) * Close overline attribute tag
return; */
void builder::overline_close() {
m_counters[syntaxtag::o]--; tag_close(attribute::OVERLINE);
append("%{-o}");
} }
/**
* Insert tag to enable the underline attribute
*/
void builder::underline(string color) { void builder::underline(string color) {
if (!color.empty()) if (!color.empty())
underline_color(color); underline_color(color);
if (m_counters[syntaxtag::u] > 0) else
return; tag_open(attribute::UNDERLINE);
m_counters[syntaxtag::u]++;
append("%{+u}");
} }
void builder::underline_close(bool force) { /**
if ((!force && m_lazy) || m_counters[syntaxtag::u] <= 0) * Close underline attribute tag
return; */
void builder::underline_close() {
m_counters[syntaxtag::u]--; tag_close(attribute::UNDERLINE);
append("%{-u}");
} }
/**
* Open command tag
*/
void builder::cmd(mousebtn index, string action, bool condition) { void builder::cmd(mousebtn index, string action, bool condition) {
int button = static_cast<int>(index); int button = static_cast<int>(index);
@ -455,23 +446,148 @@ void builder::cmd(mousebtn index, string action, bool condition) {
action = string_util::replace_all(action, "{", "\\{"); action = string_util::replace_all(action, "{", "\\{");
action = string_util::replace_all(action, "%", "\x0025"); action = string_util::replace_all(action, "%", "\x0025");
append("%{A" + std::to_string(button) + ":" + action + ":}"); tag_open(syntaxtag::A, to_string(button) + ":" + action + ":");
m_counters[syntaxtag::A]++;
} }
void builder::cmd_close(bool force) { /**
if (m_counters[syntaxtag::A] > 0 || force) * Close command tag
append("%{A}"); */
if (m_counters[syntaxtag::A] > 0) void builder::cmd_close() {
m_counters[syntaxtag::A]--; tag_close(syntaxtag::A);
} }
void builder::tag_open(char tag, string value) { /**
append("%{" + string({tag}) + value + "}"); * Get default background hex string
*/
string builder::background_hex() {
if (m_background.empty())
m_background = color_util::hex<uint16_t>(m_bar.background);
return m_background;
} }
void builder::tag_close(char tag) { /**
append("%{" + string({tag}) + "-}"); * Get default foreground hex string
*/
string builder::foreground_hex() {
if (m_foreground.empty())
m_foreground = color_util::hex<uint16_t>(m_bar.foreground);
return m_foreground;
}
/**
* Insert directive to change value of given tag
*/
void builder::tag_open(syntaxtag tag, string value) {
if (m_tags.find(tag) != m_tags.end())
m_tags[tag]++;
switch (tag) {
case syntaxtag::NONE:
break;
case syntaxtag::A:
append("%{A" + value + "}");
break;
case syntaxtag::F:
append("%{F" + value + "}");
break;
case syntaxtag::B:
append("%{B" + value + "}");
break;
case syntaxtag::T:
append("%{T" + value + "}");
break;
case syntaxtag::u:
append("%{u" + value + "}");
break;
case syntaxtag::o:
append("%{o" + value + "}");
break;
case syntaxtag::R:
append("%{R}");
break;
case syntaxtag::O:
append("%{O" + value + "}");
break;
}
}
/**
* Insert directive to use given attribute unless already set
*/
void builder::tag_open(attribute attr) {
if ((m_attributes >> static_cast<uint8_t>(attr)) & 1U)
return;
m_attributes |= 1U << static_cast<uint8_t>(attr);
switch (attr) {
case attribute::NONE:
break;
case attribute::UNDERLINE:
append("%{+u}");
break;
case attribute::OVERLINE:
append("%{+o}");
break;
}
}
/**
* Insert directive to reset given tag if it's open and closable
*/
void builder::tag_close(syntaxtag tag) {
if (!m_tags[tag] || m_tags.find(tag) == m_tags.end())
return;
m_tags[tag]--;
switch (tag) {
case syntaxtag::NONE:
break;
case syntaxtag::A:
append("%{A}");
break;
case syntaxtag::F:
append("%{F-}");
break;
case syntaxtag::B:
append("%{B-}");
break;
case syntaxtag::T:
append("%{T-}");
break;
case syntaxtag::u:
append("%{u-}");
break;
case syntaxtag::o:
append("%{o-}");
break;
case syntaxtag::R:
break;
case syntaxtag::O:
break;
}
}
/**
* Insert directive to remove given attribute if set
*/
void builder::tag_close(attribute attr) {
if (!((m_attributes >> static_cast<uint8_t>(attr)) & 1U))
return;
m_attributes &= ~(1U << static_cast<uint8_t>(attr));
switch (attr) {
case attribute::NONE:
break;
case attribute::UNDERLINE:
append("%{-u}");
break;
case attribute::OVERLINE:
append("%{-o}");
break;
}
} }
POLYBAR_NS_END POLYBAR_NS_END

View file

@ -430,7 +430,7 @@ void controller::bootstrap_modules() {
module_count++; module_count++;
} catch (const std::runtime_error& err) { } catch (const std::runtime_error& err) {
m_log.err("Disabling module \"%s\" (error: %s)", module_name, err.what()); m_log.err("Disabling module \"%s\" (reason: %s)", module_name, err.what());
} }
} }
} }
@ -555,8 +555,8 @@ void controller::on_update() {
block_contents = string_util::replace_all(block_contents, "B-}%{B#", "B#"); block_contents = string_util::replace_all(block_contents, "B-}%{B#", "B#");
block_contents = string_util::replace_all(block_contents, "F-}%{F#", "F#"); block_contents = string_util::replace_all(block_contents, "F-}%{F#", "F#");
block_contents = string_util::replace_all(block_contents, "U-}%{U#", "U#"); block_contents = string_util::replace_all(block_contents, "U-}%{U#", "U#");
block_contents = string_util::replace_all(block_contents, "Uu-}%{Uu#", "Uu#"); block_contents = string_util::replace_all(block_contents, "u-}%{u#", "u#");
block_contents = string_util::replace_all(block_contents, "Uo-}%{Uo#", "Uo#"); block_contents = string_util::replace_all(block_contents, "o-}%{o#", "o#");
// Join consecutive tags // Join consecutive tags
contents += string_util::replace_all(block_contents, "}%{", " "); contents += string_util::replace_all(block_contents, "}%{", " ");
@ -564,13 +564,22 @@ void controller::on_update() {
if (m_writeback) { if (m_writeback) {
std::cout << contents << std::endl; std::cout << contents << std::endl;
} else { return;
m_bar->parse(contents);
} }
if (!m_trayactivated) { try {
m_trayactivated = true; m_bar->parse(contents);
m_bar->activate_tray(); } catch (const exception& err) {
m_log.err("Failed to update bar contents (reason: %s)", err.what());
}
try {
if (!m_trayactivated) {
m_trayactivated = true;
m_bar->activate_tray();
}
} catch (const exception& err) {
m_log.err("Failed to active tray manager (reason: %s)", err.what());
} }
} }

View file

@ -1,3 +1,6 @@
#include <cassert>
#include "components/logger.hpp"
#include "components/parser.hpp" #include "components/parser.hpp"
#include "components/signals.hpp" #include "components/signals.hpp"
#include "components/types.hpp" #include "components/types.hpp"
@ -6,14 +9,35 @@
POLYBAR_NS POLYBAR_NS
parser::parser(const bar_settings& bar) : m_bar(bar) {} /**
* Construct parser instance
*/
parser::parser(const logger& logger, const bar_settings& bar) : m_log(logger), m_bar(bar) {
assert(g_signals::parser::background_change != nullptr);
assert(g_signals::parser::foreground_change != nullptr);
assert(g_signals::parser::underline_change != nullptr);
assert(g_signals::parser::overline_change != nullptr);
assert(g_signals::parser::alignment_change != nullptr);
assert(g_signals::parser::attribute_set != nullptr);
assert(g_signals::parser::attribute_unset != nullptr);
assert(g_signals::parser::attribute_toggle != nullptr);
assert(g_signals::parser::font_change != nullptr);
assert(g_signals::parser::pixel_offset != nullptr);
assert(g_signals::parser::action_block_open != nullptr);
assert(g_signals::parser::action_block_close != nullptr);
assert(g_signals::parser::ascii_text_write != nullptr);
assert(g_signals::parser::unicode_text_write != nullptr);
assert(g_signals::parser::string_write != nullptr);
}
/** /**
* Parse input data * Process input string
*/ */
void parser::operator()(string data) { void parser::operator()(string data) {
size_t pos; size_t pos;
m_log.trace_x("parser: %s", data);
while (data.length()) { while (data.length()) {
if (data.compare(0, 2, "%{") == 0 && (pos = data.find("}")) != string::npos) { if (data.compare(0, 2, "%{") == 0 && (pos = data.find("}")) != string::npos) {
codeblock(data.substr(2, pos - 2)); codeblock(data.substr(2, pos - 2));
@ -27,7 +51,7 @@ void parser::operator()(string data) {
} }
/** /**
* Parse contents in tag blocks, i.e: %{...} * Process contents within tag blocks, i.e: %{...}
*/ */
void parser::codeblock(string data) { void parser::codeblock(string data) {
size_t pos; size_t pos;
@ -38,7 +62,7 @@ void parser::codeblock(string data) {
if (data.empty()) if (data.empty())
break; break;
char tag = data[0]; char tag{data[0]};
string value; string value;
// Remove the tag // Remove the tag
@ -51,72 +75,61 @@ void parser::codeblock(string data) {
switch (tag) { switch (tag) {
case 'B': case 'B':
// Ignore tag if it occurs again later in the same block g_signals::parser::background_change(parse_color(value, m_bar.background));
if (data.find(" B") == string::npos && g_signals::parser::color_change)
g_signals::parser::color_change(gc::BG, parse_color(value, m_bar.background));
break; break;
case 'F': case 'F':
// Ignore tag if it occurs again later in the same block g_signals::parser::foreground_change(parse_color(value, m_bar.foreground));
if (data.find(" F") == string::npos && g_signals::parser::color_change)
g_signals::parser::color_change(gc::FG, parse_color(value, m_bar.foreground));
break;
case 'U':
if (g_signals::parser::color_change) {
if (value[0] == 'u') {
if (data.find(" Uu") == string::npos)
g_signals::parser::color_change(gc::UL, parse_color(value.substr(1), m_bar.underline.color));
} else if (value[0] == 'o') {
if (data.find(" Uo") == string::npos)
g_signals::parser::color_change(gc::OL, parse_color(value.substr(1), m_bar.overline.color));
} else if (data.find(" U") == string::npos) {
g_signals::parser::color_change(gc::UL, parse_color(value, m_bar.underline.color));
g_signals::parser::color_change(gc::OL, parse_color(value, m_bar.overline.color));
}
}
break;
case 'R':
if (g_signals::parser::color_change) {
g_signals::parser::color_change(gc::BG, m_bar.foreground);
g_signals::parser::color_change(gc::FG, m_bar.background);
}
break; break;
case 'T': case 'T':
if (data.find(" T") == string::npos && g_signals::parser::font_change) g_signals::parser::font_change(parse_fontindex(value));
g_signals::parser::font_change(parse_fontindex(value)); break;
case 'U':
g_signals::parser::underline_change(parse_color(value, m_bar.underline.color));
g_signals::parser::overline_change(parse_color(value, m_bar.overline.color));
break;
case 'u':
g_signals::parser::underline_change(parse_color(value, m_bar.underline.color));
break;
case 'o':
g_signals::parser::overline_change(parse_color(value, m_bar.overline.color));
break;
case 'R':
g_signals::parser::background_change(m_bar.foreground);
g_signals::parser::foreground_change(m_bar.background);
break; break;
case 'O': case 'O':
if (g_signals::parser::pixel_offset) g_signals::parser::pixel_offset(atoi(value.c_str()));
g_signals::parser::pixel_offset(std::atoi(value.c_str()));
break; break;
case 'l': case 'l':
if (g_signals::parser::alignment_change) g_signals::parser::alignment_change(alignment::LEFT);
g_signals::parser::alignment_change(alignment::LEFT);
break; break;
case 'c': case 'c':
if (g_signals::parser::alignment_change) g_signals::parser::alignment_change(alignment::CENTER);
g_signals::parser::alignment_change(alignment::CENTER);
break; break;
case 'r': case 'r':
if (g_signals::parser::alignment_change) g_signals::parser::alignment_change(alignment::RIGHT);
g_signals::parser::alignment_change(alignment::RIGHT);
break; break;
case '+': case '+':
if (g_signals::parser::attribute_set) g_signals::parser::attribute_set(parse_attr(value[0]));
g_signals::parser::attribute_set(parse_attr(value[0]));
break; break;
case '-': case '-':
if (g_signals::parser::attribute_unset) g_signals::parser::attribute_unset(parse_attr(value[0]));
g_signals::parser::attribute_unset(parse_attr(value[0])); break;
case '!':
g_signals::parser::attribute_toggle(parse_attr(value[0]));
break; break;
case 'A': case 'A':
@ -125,16 +138,14 @@ void parser::codeblock(string data) {
mousebtn btn = parse_action_btn(data); mousebtn btn = parse_action_btn(data);
m_actions.push_back(static_cast<int>(btn)); m_actions.push_back(static_cast<int>(btn));
if (g_signals::parser::action_block_open) g_signals::parser::action_block_open(btn, value);
g_signals::parser::action_block_open(btn, value);
// make sure we strip the correct length (btn+wrapping colons) // make sure we strip the correct length (btn+wrapping colons)
if (data[0] != ':') if (value[0] != ':')
value += "0"; value += "0";
value += "::"; value += "::";
} else if (!m_actions.empty()) { } else if (!m_actions.empty()) {
if (g_signals::parser::action_block_close) g_signals::parser::action_block_close(parse_action_btn(value));
g_signals::parser::action_block_close(parse_action_btn(data));
m_actions.pop_back(); m_actions.pop_back();
} }
break; break;
@ -149,12 +160,12 @@ void parser::codeblock(string data) {
} }
/** /**
* Parse text strings * Process text contents
*/ */
size_t parser::text(string data) { size_t parser::text(string data) {
uint8_t* utf = (uint8_t*)data.c_str(); uint8_t* utf = (uint8_t*)data.c_str();
if (g_signals::parser::string_write && utf[0] < 0x80) { if (utf[0] < 0x80) {
// grab all consecutive ascii chars // grab all consecutive ascii chars
size_t next_tag = data.find("%{"); size_t next_tag = data.find("%{");
if (next_tag != string::npos) { if (next_tag != string::npos) {
@ -165,39 +176,29 @@ size_t parser::text(string data) {
; ;
g_signals::parser::string_write(data.substr(0, n).c_str(), n); g_signals::parser::string_write(data.substr(0, n).c_str(), n);
return n; return n;
} else if (utf[0] < 0x80) {
if (g_signals::parser::ascii_text_write)
g_signals::parser::ascii_text_write(utf[0]);
return 1;
} else if ((utf[0] & 0xe0) == 0xc0) { // 2 byte utf-8 sequence } else if ((utf[0] & 0xe0) == 0xc0) { // 2 byte utf-8 sequence
if (g_signals::parser::unicode_text_write) g_signals::parser::unicode_text_write((utf[0] & 0x1f) << 6 | (utf[1] & 0x3f));
g_signals::parser::unicode_text_write((utf[0] & 0x1f) << 6 | (utf[1] & 0x3f));
return 2; return 2;
} else if ((utf[0] & 0xf0) == 0xe0) { // 3 byte utf-8 sequence } else if ((utf[0] & 0xf0) == 0xe0) { // 3 byte utf-8 sequence
if (g_signals::parser::unicode_text_write) g_signals::parser::unicode_text_write((utf[0] & 0xf) << 12 | (utf[1] & 0x3f) << 6 | (utf[2] & 0x3f));
g_signals::parser::unicode_text_write((utf[0] & 0xf) << 12 | (utf[1] & 0x3f) << 6 | (utf[2] & 0x3f));
return 3; return 3;
} else if ((utf[0] & 0xf8) == 0xf0) { // 4 byte utf-8 sequence } else if ((utf[0] & 0xf8) == 0xf0) { // 4 byte utf-8 sequence
if (g_signals::parser::unicode_text_write) g_signals::parser::unicode_text_write(0xfffd);
g_signals::parser::unicode_text_write(0xfffd);
return 4; return 4;
} else if ((utf[0] & 0xfc) == 0xf8) { // 5 byte utf-8 sequence } else if ((utf[0] & 0xfc) == 0xf8) { // 5 byte utf-8 sequence
if (g_signals::parser::unicode_text_write) g_signals::parser::unicode_text_write(0xfffd);
g_signals::parser::unicode_text_write(0xfffd);
return 5; return 5;
} else if ((utf[0] & 0xfe) == 0xfc) { // 6 byte utf-8 sequence } else if ((utf[0] & 0xfe) == 0xfc) { // 6 byte utf-8 sequence
if (g_signals::parser::unicode_text_write) g_signals::parser::unicode_text_write(0xfffd);
g_signals::parser::unicode_text_write(0xfffd);
return 6; return 6;
} else { // invalid utf-8 sequence } else { // invalid utf-8 sequence
if (g_signals::parser::ascii_text_write) g_signals::parser::ascii_text_write(utf[0]);
g_signals::parser::ascii_text_write(utf[0]);
return 1; return 1;
} }
} }
/** /**
* TODO: docstring * Process color hex string and convert it to the correct value
*/ */
uint32_t parser::parse_color(string s, uint32_t fallback) { uint32_t parser::parse_color(string s, uint32_t fallback) {
uint32_t color{0}; uint32_t color{0};
@ -207,10 +208,10 @@ uint32_t parser::parse_color(string s, uint32_t fallback) {
} }
/** /**
* TODO: docstring * Process font index and convert it to the correct value
*/ */
int8_t parser::parse_fontindex(string s) { int8_t parser::parse_fontindex(string s) {
if (s.empty() || s == "-") { if (s.empty() || s[0] == '-') {
return -1; return -1;
} }
@ -222,22 +223,21 @@ int8_t parser::parse_fontindex(string s) {
} }
/** /**
* TODO: docstring * Process attribute token and convert it to the correct value
*/ */
attribute parser::parse_attr(const char s) { attribute parser::parse_attr(const char attr) {
switch (s) { switch (attr) {
case 'o': case 'o':
return attribute::o; return attribute::OVERLINE;
break;
case 'u': case 'u':
return attribute::u; return attribute::UNDERLINE;
break; default:
throw unrecognized_attribute(string{attr});
} }
return attribute::NONE;
} }
/** /**
* TODO: docstring * Process action button token and convert it to the correct value
*/ */
mousebtn parser::parse_action_btn(string data) { mousebtn parser::parse_action_btn(string data) {
if (data[0] == ':') if (data[0] == ':')
@ -251,7 +251,7 @@ mousebtn parser::parse_action_btn(string data) {
} }
/** /**
* TODO: docstring * Process action command string
*/ */
string parser::parse_action_cmd(string data) { string parser::parse_action_cmd(string data) {
size_t start, end; size_t start, end;

View file

@ -22,6 +22,9 @@ di::injector<unique_ptr<renderer>> configure_renderer(const bar_settings& bar, c
// clang-format on // clang-format on
} }
/**
* Construct renderer instance
*/
renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manager> font_manager, renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manager> font_manager,
const bar_settings& bar, const vector<string>& fonts) const bar_settings& bar, const vector<string>& fonts)
: m_connection(conn), m_log(logger), m_fontmanager(forward<decltype(font_manager)>(font_manager)), m_bar(bar) { : m_connection(conn), m_log(logger), m_fontmanager(forward<decltype(font_manager)>(font_manager)), m_bar(bar) {
@ -35,20 +38,19 @@ renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manag
m_connection.create_colormap(XCB_COLORMAP_ALLOC_NONE, m_colormap, screen->root, m_visual->visual_id); m_connection.create_colormap(XCB_COLORMAP_ALLOC_NONE, m_colormap, screen->root, m_visual->visual_id);
m_window = m_connection.generate_id(); m_window = m_connection.generate_id();
m_log.trace("renderer: Create window %s", m_connection.id(m_window)); m_log.trace("renderer: Create window (xid=%s)", m_connection.id(m_window));
{ {
uint32_t mask{0}; uint32_t mask{0};
uint32_t values[16]{0}; uint32_t values[16]{0};
xcb_params_cw_t params; xcb_params_cw_t params;
// clang-format off
XCB_AUX_ADD_PARAM(&mask, &params, back_pixel, 0); XCB_AUX_ADD_PARAM(&mask, &params, back_pixel, 0);
XCB_AUX_ADD_PARAM(&mask, &params, border_pixel, 0); XCB_AUX_ADD_PARAM(&mask, &params, border_pixel, 0);
XCB_AUX_ADD_PARAM(&mask, &params, backing_store, XCB_BACKING_STORE_WHEN_MAPPED); XCB_AUX_ADD_PARAM(&mask, &params, backing_store, XCB_BACKING_STORE_WHEN_MAPPED);
XCB_AUX_ADD_PARAM(&mask, &params, colormap, m_colormap); XCB_AUX_ADD_PARAM(&mask, &params, colormap, m_colormap);
XCB_AUX_ADD_PARAM(&mask, &params, override_redirect, m_bar.force_docking); XCB_AUX_ADD_PARAM(&mask, &params, override_redirect, m_bar.force_docking);
XCB_AUX_ADD_PARAM(&mask, &params, event_mask, XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS); XCB_AUX_ADD_PARAM(&mask, &params, event_mask,
// clang-format on XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS);
xutils::pack_values(mask, &params, values); xutils::pack_values(mask, &params, values);
m_connection.create_window(32, m_window, screen->root, m_bar.pos.x, m_bar.pos.y, m_bar.size.w, m_bar.size.h, 0, m_connection.create_window(32, m_window, screen->root, m_bar.pos.x, m_bar.pos.y, m_bar.size.w, m_bar.size.h, 0,
@ -74,17 +76,17 @@ renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manag
}; };
// clang-format on // clang-format on
for (int i = 1; i <= 8; i++) { for (int i = 0; i < 8; i++) {
uint32_t mask{0}; uint32_t mask{0};
uint32_t value_list[32]{0}; uint32_t value_list[32]{0};
xcb_params_gc_t params; xcb_params_gc_t params;
XCB_AUX_ADD_PARAM(&mask, &params, foreground, colors[i - 1]);
XCB_AUX_ADD_PARAM(&mask, &params, foreground, colors[i]);
XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 0); XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 0);
xutils::pack_values(mask, &params, value_list); xutils::pack_values(mask, &params, value_list);
m_gcontexts.emplace(gc(i), m_connection.generate_id()); m_gcontexts.emplace(gc(i), m_connection.generate_id());
m_colors.emplace(gc(i), colors[i]);
m_log.trace("renderer: Create gcontext (gc=%i, xid=%s)", i, m_connection.id(m_gcontexts.at(gc(i)))); m_log.trace("renderer: Create gcontext (gc=%i, xid=%s)", i, m_connection.id(m_gcontexts.at(gc(i))));
m_connection.create_gc(m_gcontexts.at(gc(i)), m_pixmap, mask, value_list); m_connection.create_gc(m_gcontexts.at(gc(i)), m_pixmap, mask, value_list);
} }
@ -100,7 +102,7 @@ renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manag
for (auto f : fonts) { for (auto f : fonts) {
fontindex++; fontindex++;
vector<string> fd = string_util::split(f, ';'); vector<string> fd{string_util::split(f, ';')};
string pattern{fd[0]}; string pattern{fd[0]};
int offset{0}; int offset{0};
@ -123,27 +125,41 @@ renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manag
} }
} }
/**
* Get output window
*/
xcb_window_t renderer::window() const { xcb_window_t renderer::window() const {
return m_window; return m_window;
} }
/**
* Begin render routine
*/
void renderer::begin() { void renderer::begin() {
m_log.trace_x("renderer: begin");
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS #if DEBUG and DRAW_CLICKABLE_AREA_HINTS
for (auto&& action : m_actions) { for (auto&& action : m_actions) {
m_connection.destroy_window(action.hint); m_connection.destroy_window(action.hint);
} }
#endif #endif
m_currentx = m_bar.borders.at(edge::LEFT).size; m_currentx = m_bar.inner_area(true).x;
m_attributes = 0; m_attributes = 0;
m_actions.clear(); m_actions.clear();
fill_border(m_bar.borders, edge::ALL);
fill_background(); fill_background();
m_fontmanager->create_xftdraw(m_pixmap, m_colormap); m_fontmanager->create_xftdraw(m_pixmap, m_colormap);
} }
/**
* End render routine
*/
void renderer::end() { void renderer::end() {
m_log.trace_x("renderer: end");
redraw(); redraw();
m_fontmanager->destroy_xftdraw(); m_fontmanager->destroy_xftdraw();
@ -155,74 +171,104 @@ void renderer::end() {
m_reserve_at = edge::NONE; m_reserve_at = edge::NONE;
} }
/**
* Redraw window contents
*/
void renderer::redraw() { void renderer::redraw() {
m_log.info("renderer: redrawing"); m_log.info("Redrawing");
xcb_rectangle_t rect{0, 0, m_bar.size.w, m_bar.size.h}; xcb_rectangle_t r{0, 0, m_bar.size.w, m_bar.size.h};
if (m_reserve_at == edge::LEFT) { if (m_reserve_at == edge::LEFT) {
rect.x += m_reserve; r.x += m_reserve;
rect.width -= m_reserve; r.width -= m_reserve;
} else if (m_reserve_at == edge::RIGHT) { } else if (m_reserve_at == edge::RIGHT) {
rect.width -= m_reserve; r.width -= m_reserve;
} }
fill_border(m_bar.borders, edge::ALL); m_connection.copy_area(m_pixmap, m_window, m_gcontexts.at(gc::FG), r.x, r.y, r.x, r.y, r.width, r.height);
m_connection.copy_area(
m_pixmap, m_window, m_gcontexts.at(gc::FG), rect.x, rect.y, rect.x, rect.y, rect.width, rect.height);
m_connection.flush();
} }
/**
* Reserve space at given edge
*/
void renderer::reserve_space(edge side, uint16_t w) { void renderer::reserve_space(edge side, uint16_t w) {
m_log.trace_x("renderer: reserve_space(%i, %i)", static_cast<uint8_t>(side), w); m_log.trace_x("renderer: reserve_space(%i, %i)", static_cast<uint8_t>(side), w);
m_reserve = w; m_reserve = w;
m_reserve_at = side; m_reserve_at = side;
} }
/**
* Change value of background gc
*/
void renderer::set_background(const uint32_t color) { void renderer::set_background(const uint32_t color) {
if (color == m_background) if (m_colors[gc::BG] == color) {
return; return m_log.trace_x("renderer: ignoring unchanged background color(#%08x)", color);
}
m_log.trace_x("renderer: set_background(#%08x)", color); m_log.trace_x("renderer: set_background(#%08x)", color);
m_connection.change_gc(m_gcontexts.at(gc::BG), XCB_GC_FOREGROUND, &color); m_connection.change_gc(m_gcontexts.at(gc::BG), XCB_GC_FOREGROUND, &color);
m_background = color; m_colors[gc::BG] = color;
shift_content(0); shift_content(0);
} }
/**
* Change value of foreground gc
*/
void renderer::set_foreground(const uint32_t color) { void renderer::set_foreground(const uint32_t color) {
if (color == m_foreground) if (m_colors[gc::FG] == color) {
return; return m_log.trace_x("renderer: ignoring unchanged foreground color(#%08x)", color);
}
m_log.trace_x("renderer: set_foreground(#%08x)", color); m_log.trace_x("renderer: set_foreground(#%08x)", color);
m_connection.change_gc(m_gcontexts.at(gc::FG), XCB_GC_FOREGROUND, &color); m_connection.change_gc(m_gcontexts.at(gc::FG), XCB_GC_FOREGROUND, &color);
m_fontmanager->allocate_color(color); m_fontmanager->allocate_color(color);
m_foreground = color; m_colors[gc::FG] = color;
} }
/**
* Change value of underline gc
*/
void renderer::set_underline(const uint32_t color) { void renderer::set_underline(const uint32_t color) {
if (color == m_foreground) if (m_colors[gc::UL] == color) {
return; return m_log.trace_x("renderer: ignoring unchanged underline color(#%08x)", color);
}
m_log.trace_x("renderer: set_underline(#%08x)", color); m_log.trace_x("renderer: set_underline(#%08x)", color);
m_connection.change_gc(m_gcontexts.at(gc::UL), XCB_GC_FOREGROUND, &color); m_connection.change_gc(m_gcontexts.at(gc::UL), XCB_GC_FOREGROUND, &color);
m_underline = color; m_colors[gc::UL] = color;
} }
/**
* Change value of overline gc
*/
void renderer::set_overline(const uint32_t color) { void renderer::set_overline(const uint32_t color) {
if (color == m_foreground) if (m_colors[gc::OL] == color) {
return; return m_log.trace_x("renderer: ignoring unchanged overline color(#%08x)", color);
}
m_log.trace_x("renderer: set_overline(#%08x)", color); m_log.trace_x("renderer: set_overline(#%08x)", color);
m_connection.change_gc(m_gcontexts.at(gc::OL), XCB_GC_FOREGROUND, &color); m_connection.change_gc(m_gcontexts.at(gc::OL), XCB_GC_FOREGROUND, &color);
m_overline = color; m_colors[gc::OL] = color;
} }
void renderer::set_fontindex(const uint8_t font) { /**
m_log.trace_x("renderer: set_fontindex(%i)", static_cast<uint8_t>(font)); * Change preferred font index used when matching glyphs
*/
void renderer::set_fontindex(const int8_t font) {
if (m_fontindex == font) {
return m_log.trace_x("renderer: ignoring unchanged font index(%i)", static_cast<int8_t>(font));
}
m_log.trace_x("renderer: set_fontindex(%i)", static_cast<int8_t>(font));
m_fontmanager->set_preferred_font(font); m_fontmanager->set_preferred_font(font);
m_fontindex = font;
} }
/**
* Change current alignment
*/
void renderer::set_alignment(const alignment align) { void renderer::set_alignment(const alignment align) {
if (align == m_alignment) { if (align == m_alignment) {
return; return m_log.trace_x("renderer: ignoring unchanged alignment(%i)", static_cast<uint8_t>(align));
} else if (align == alignment::LEFT) { }
if (align == alignment::LEFT) {
m_currentx = m_bar.borders.at(edge::LEFT).size; m_currentx = m_bar.borders.at(edge::LEFT).size;
} else if (align == alignment::RIGHT) { } else if (align == alignment::RIGHT) {
m_currentx = m_bar.borders.at(edge::RIGHT).size; m_currentx = m_bar.borders.at(edge::RIGHT).size;
@ -240,17 +286,40 @@ void renderer::set_alignment(const alignment align) {
m_alignment = align; m_alignment = align;
} }
/**
* Enable/remove attribute
*/
void renderer::set_attribute(const attribute attr, bool state) { void renderer::set_attribute(const attribute attr, bool state) {
m_log.trace_x("renderer: set_attribute(%i, %i)", static_cast<uint8_t>(attr), state); m_log.trace_x("renderer: set_attribute(%i, %i)", static_cast<uint8_t>(attr), state);
if (state) { if (state) {
m_attributes |= static_cast<uint8_t>(attr); m_attributes |= 1U << static_cast<uint8_t>(attr);
} else { } else {
m_attributes ^= static_cast<uint8_t>(attr); m_attributes &= ~(1U << static_cast<uint8_t>(attr));
} }
} }
/**
* Toggle attribute
*/
void renderer::toggle_attribute(const attribute attr) {
m_log.trace_x("renderer: toggle_attribute(%i)", static_cast<uint8_t>(attr));
m_attributes ^= 1U << static_cast<uint8_t>(attr);
}
/**
* Check if the given attribute is set
*/
bool renderer::check_attribute(const attribute attr) {
return (m_attributes >> static_cast<uint8_t>(attr)) & 1U;
}
/**
* Fill background area
*/
void renderer::fill_background() { void renderer::fill_background() {
m_log.trace_x("renderer: fill_background");
xcb_rectangle_t rect{0, 0, m_bar.size.w, m_bar.size.h}; xcb_rectangle_t rect{0, 0, m_bar.size.w, m_bar.size.h};
if (m_reserve_at == edge::LEFT) { if (m_reserve_at == edge::LEFT) {
@ -263,11 +332,14 @@ void renderer::fill_background() {
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), rect.x, rect.y, rect.width, rect.height); draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), rect.x, rect.y, rect.width, rect.height);
} }
/**
* Fill border area
*/
void renderer::fill_border(const map<edge, border_settings>& borders, edge border) { void renderer::fill_border(const map<edge, border_settings>& borders, edge border) {
m_log.trace_x("renderer: fill_border(%i)", static_cast<uint8_t>(border));
for (auto&& b : borders) { for (auto&& b : borders) {
if (border != edge::ALL && b.first != border) if (!b.second.size || (border != edge::ALL && b.first != border))
continue;
if (b.second.size <= 0)
continue; continue;
switch (b.first) { switch (b.first) {
@ -295,25 +367,52 @@ void renderer::fill_border(const map<edge, border_settings>& borders, edge borde
} }
} }
/**
* Fill overline area
*/
void renderer::fill_overline(int16_t x, uint16_t w) { void renderer::fill_overline(int16_t x, uint16_t w) {
if (!m_bar.overline.size || !(m_attributes & static_cast<int>(attribute::o))) if (!check_attribute(attribute::OVERLINE)) {
return; return m_log.trace_x("renderer: not filling overline (flag unset)");
int16_t y{static_cast<int16_t>(m_bar.borders.at(edge::TOP).size)}; } else if (!m_bar.overline.size) {
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::OL), x, y, w, m_bar.overline.size); return m_log.trace_x("renderer: not filling overline (size=0)");
}
m_log.trace_x("renderer: fill_overline(%i, #%08x)", m_bar.overline.size, m_colors[gc::OL]);
const xcb_rectangle_t inner{m_bar.inner_area(true)};
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::OL), x, inner.y, w, m_bar.overline.size);
} }
/**
* Fill underline area
*/
void renderer::fill_underline(int16_t x, uint16_t w) { void renderer::fill_underline(int16_t x, uint16_t w) {
if (!m_bar.underline.size || !(m_attributes & static_cast<int>(attribute::u))) if (!check_attribute(attribute::UNDERLINE)) {
return; return m_log.trace_x("renderer: not filling underline (flag unset)");
int16_t y{static_cast<int16_t>(m_bar.size.h - m_bar.borders.at(edge::BOTTOM).size - m_bar.underline.size)}; } else if (!m_bar.underline.size) {
return m_log.trace_x("renderer: not filling underline (size=0)");
}
m_log.trace_x("renderer: fill_underline(%i, #%08x)", m_bar.underline.size, m_colors[gc::UL]);
const xcb_rectangle_t inner{m_bar.inner_area(true)};
int16_t y{static_cast<int16_t>(inner.height - m_bar.underline.size)};
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::UL), x, y, w, m_bar.underline.size); draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::UL), x, y, w, m_bar.underline.size);
} }
/**
* Shift filled area by given pixels
*/
void renderer::fill_shift(const int16_t px) {
shift_content(px);
}
/**
* Draw character glyph
*/
void renderer::draw_character(uint16_t character) { void renderer::draw_character(uint16_t character) {
m_log.trace_x("renderer: draw_character(\"%c\")", character);
auto& font = m_fontmanager->match_char(character); auto& font = m_fontmanager->match_char(character);
if (!font) { if (!font) {
return; return m_log.warn("No suitable font found (character=%i)", character);
} }
if (font->ptr && font->ptr != m_gcfont) { if (font->ptr && font->ptr != m_gcfont) {
@ -340,7 +439,12 @@ void renderer::draw_character(uint16_t character) {
} }
} }
/**
* Draw character glyphs
*/
void renderer::draw_textstring(const char* text, size_t len) { void renderer::draw_textstring(const char* text, size_t len) {
m_log.trace_x("renderer: draw_textstring(\"%s\")", text);
for (size_t n = 0; n < len; n++) { for (size_t n = 0; n < len; n++) {
vector<uint16_t> chars; vector<uint16_t> chars;
chars.emplace_back(text[n]); chars.emplace_back(text[n]);
@ -348,7 +452,7 @@ void renderer::draw_textstring(const char* text, size_t len) {
auto& font = m_fontmanager->match_char(chars[0]); auto& font = m_fontmanager->match_char(chars[0]);
if (!font) { if (!font) {
return; return m_log.warn("No suitable font found (character=%i)", chars[0]);
} }
if (font->ptr && font->ptr != m_gcfont) { if (font->ptr && font->ptr != m_gcfont) {
@ -386,51 +490,10 @@ void renderer::draw_textstring(const char* text, size_t len) {
} }
} }
int16_t renderer::shift_content(int16_t x, int16_t shift_x) { /**
int delta = shift_x; * Create new action block at the current position
*/
if (m_alignment == alignment::CENTER) { void renderer::begin_action(const mousebtn btn, const string cmd) {
int base_x = m_bar.size.w;
base_x -= m_bar.borders.at(edge::RIGHT).size;
base_x /= 2;
base_x += m_bar.borders.at(edge::LEFT).size;
m_connection.copy_area(
m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), base_x - x / 2, 0, base_x - (x + shift_x) / 2, 0, x, m_bar.size.h);
x = base_x - (x + shift_x) / 2 + x;
delta /= 2;
} else if (m_alignment == alignment::RIGHT) {
m_connection.copy_area(m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), m_bar.size.w - x, 0, m_bar.size.w - x - shift_x,
0, x, m_bar.size.h);
x = m_bar.size.w - shift_x - m_bar.borders.at(edge::RIGHT).size;
if (m_reserve_at == edge::RIGHT)
x -= m_reserve;
}
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), x, 0, m_bar.size.w - x, m_bar.size.h);
// Translate pos of clickable areas
if (m_alignment != alignment::LEFT) {
for (auto&& action : m_actions) {
if (action.active || action.align != m_alignment)
continue;
action.start_x -= delta;
action.end_x -= delta;
}
}
m_currentx += shift_x;
fill_underline(x, shift_x);
fill_overline(x, shift_x);
return x;
}
int16_t renderer::shift_content(int16_t shift_x) {
return shift_content(m_currentx, shift_x);
}
void renderer::begin_action(const mousebtn btn, const string& cmd) {
action_block action{}; action_block action{};
action.button = btn; action.button = btn;
action.align = m_alignment; action.align = m_alignment;
@ -443,6 +506,9 @@ void renderer::begin_action(const mousebtn btn, const string& cmd) {
m_actions.emplace_back(action); m_actions.emplace_back(action);
} }
/**
* End action block at the current position
*/
void renderer::end_action(const mousebtn btn) { void renderer::end_action(const mousebtn btn) {
for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) { for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) {
if (!action->active || action->button != btn) if (!action->active || action->button != btn)
@ -474,12 +540,73 @@ void renderer::end_action(const mousebtn btn) {
} }
} }
/**
* Get all action blocks
*/
const vector<action_block> renderer::get_actions() { const vector<action_block> renderer::get_actions() {
return m_actions; return m_actions;
} }
/**
* Shift contents by given pixel value
*/
int16_t renderer::shift_content(const int16_t x, const int16_t shift_x) {
m_log.trace_x("renderer: shift_content(%i)", shift_x);
int delta = shift_x;
int x2{x};
if (m_alignment == alignment::CENTER) {
int base_x = m_bar.size.w;
base_x -= m_bar.borders.at(edge::RIGHT).size;
base_x /= 2;
base_x += m_bar.borders.at(edge::LEFT).size;
m_connection.copy_area(
m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), base_x - x / 2, 0, base_x - (x + shift_x) / 2, 0, x, m_bar.size.h);
x2 = base_x - (x + shift_x) / 2 + x;
delta /= 2;
} else if (m_alignment == alignment::RIGHT) {
m_connection.copy_area(m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), m_bar.size.w - x, 0, m_bar.size.w - x - shift_x,
0, x, m_bar.size.h);
x2 = m_bar.size.w - shift_x - m_bar.borders.at(edge::RIGHT).size;
if (m_reserve_at == edge::RIGHT)
x2 -= m_reserve;
}
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), x2, 0, m_bar.size.w - x, m_bar.size.h);
// Translate pos of clickable areas
if (m_alignment != alignment::LEFT) {
for (auto&& action : m_actions) {
if (action.active || action.align != m_alignment)
continue;
action.start_x -= delta;
action.end_x -= delta;
}
}
m_currentx += shift_x;
fill_underline(x2, shift_x);
fill_overline(x2, shift_x);
return x2;
}
/**
* Shift contents by given pixel value
*/
int16_t renderer::shift_content(const int16_t shift_x) {
return shift_content(m_currentx, shift_x);
}
/**
* Draw debugging hints onto the output window
*/
void renderer::debughints() { void renderer::debughints() {
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS #if DEBUG and DRAW_CLICKABLE_AREA_HINTS
m_log.info("Drawing debug hints");
map<alignment, int> hint_num{{ map<alignment, int> hint_num{{
{alignment::LEFT, 0}, {alignment::CENTER, 0}, {alignment::RIGHT, 0}, {alignment::LEFT, 0}, {alignment::CENTER, 0}, {alignment::RIGHT, 0},
}}; }};
@ -489,8 +616,6 @@ void renderer::debughints() {
continue; continue;
} }
m_log.info("Drawing clickable area hints");
hint_num[action.align]++; hint_num[action.align]++;
auto x = action.start_x; auto x = action.start_x;
@ -507,8 +632,6 @@ void renderer::debughints() {
XCB_WINDOW_CLASS_INPUT_OUTPUT, m_screen->root_visual, mask, values); XCB_WINDOW_CLASS_INPUT_OUTPUT, m_screen->root_visual, mask, values);
m_connection.map_window(action.hint); m_connection.map_window(action.hint);
} }
m_connection.flush();
#endif #endif
} }

View file

@ -6,20 +6,24 @@ POLYBAR_NS
/** /**
* Signals used to communicate with the bar window * Signals used to communicate with the bar window
*/ */
callback<string> g_signals::bar::action_click{nullptr}; callback<const string> g_signals::bar::action_click{nullptr};
callback<bool> g_signals::bar::visibility_change{nullptr}; callback<const bool> g_signals::bar::visibility_change{nullptr};
/** /**
* Signals used to communicate with the input parser * Signals used to communicate with the input parser
*/ */
callback<const uint32_t> g_signals::parser::background_change{nullptr};
callback<const uint32_t> g_signals::parser::foreground_change{nullptr};
callback<const uint32_t> g_signals::parser::underline_change{nullptr};
callback<const uint32_t> g_signals::parser::overline_change{nullptr};
callback<const alignment> g_signals::parser::alignment_change{nullptr}; callback<const alignment> g_signals::parser::alignment_change{nullptr};
callback<const attribute> g_signals::parser::attribute_set{nullptr}; callback<const attribute> g_signals::parser::attribute_set{nullptr};
callback<const attribute> g_signals::parser::attribute_unset{nullptr}; callback<const attribute> g_signals::parser::attribute_unset{nullptr};
callback<const mousebtn, string> g_signals::parser::action_block_open{nullptr}; callback<const attribute> g_signals::parser::attribute_toggle{nullptr};
callback<const mousebtn> g_signals::parser::action_block_close{nullptr};
callback<const gc, const uint32_t> g_signals::parser::color_change{nullptr};
callback<const int8_t> g_signals::parser::font_change{nullptr}; callback<const int8_t> g_signals::parser::font_change{nullptr};
callback<const int16_t> g_signals::parser::pixel_offset{nullptr}; callback<const int16_t> g_signals::parser::pixel_offset{nullptr};
callback<const mousebtn, const string> g_signals::parser::action_block_open{nullptr};
callback<const mousebtn> g_signals::parser::action_block_close{nullptr};
callback<const uint16_t> g_signals::parser::ascii_text_write{nullptr}; callback<const uint16_t> g_signals::parser::ascii_text_write{nullptr};
callback<const uint16_t> g_signals::parser::unicode_text_write{nullptr}; callback<const uint16_t> g_signals::parser::unicode_text_write{nullptr};
callback<const char*, const size_t> g_signals::parser::string_write{nullptr}; callback<const char*, const size_t> g_signals::parser::string_write{nullptr};
@ -27,6 +31,6 @@ callback<const char*, const size_t> g_signals::parser::string_write{nullptr};
/** /**
* Signals used to communicate with the tray manager * Signals used to communicate with the tray manager
*/ */
callback<uint16_t> g_signals::tray::report_slotcount{nullptr}; callback<const uint16_t> g_signals::tray::report_slotcount{nullptr};
POLYBAR_NS_END POLYBAR_NS_END

View file

@ -1,5 +1,5 @@
#include "x11/color.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "x11/color.hpp"
#include "drawtypes/progressbar.hpp" #include "drawtypes/progressbar.hpp"
#include "utils/math.hpp" #include "utils/math.hpp"
@ -7,6 +7,9 @@
POLYBAR_NS POLYBAR_NS
namespace drawtypes { namespace drawtypes {
progressbar::progressbar(const bar_settings bar, int width, string format)
: m_builder(make_unique<builder>(bar)), m_format(format), m_width(width) {}
void progressbar::set_fill(icon_t&& fill) { void progressbar::set_fill(icon_t&& fill) {
m_fill = forward<decltype(fill)>(fill); m_fill = forward<decltype(fill)>(fill);
} }
@ -82,8 +85,7 @@ namespace drawtypes {
* Create a progressbar by loading values * Create a progressbar by loading values
* from the configuration * from the configuration
*/ */
progressbar_t load_progressbar( progressbar_t load_progressbar(const bar_settings& bar, const config& conf, string section, string name) {
const bar_settings& bar, const config& conf, string section, string name) {
// Remove the start and end tag from the name in case a format tag is passed // Remove the start and end tag from the name in case a format tag is passed
name = string_util::ltrim(string_util::rtrim(name, '>'), '<'); name = string_util::ltrim(string_util::rtrim(name, '>'), '<');

View file

@ -332,7 +332,7 @@ namespace modules {
builder->cmd(mousebtn::LEFT, event); builder->cmd(mousebtn::LEFT, event);
builder->node(ws.second); builder->node(ws.second);
builder->cmd_close(true); builder->cmd_close();
} else { } else {
builder->node(ws.second); builder->node(ws.second);
} }
@ -340,8 +340,8 @@ namespace modules {
} }
if (m_scroll) { if (m_scroll) {
builder->cmd_close(true); builder->cmd_close();
builder->cmd_close(true); builder->cmd_close();
} }
return workspace_n > 0; return workspace_n > 0;

View file

@ -155,15 +155,15 @@ namespace modules {
if (m_click) { if (m_click) {
builder->cmd(mousebtn::LEFT, string{EVENT_CLICK} + to_string(ws.get()->index)); builder->cmd(mousebtn::LEFT, string{EVENT_CLICK} + to_string(ws.get()->index));
builder->node(ws.get()->label); builder->node(ws.get()->label);
builder->cmd_close(true); builder->cmd_close();
} else { } else {
builder->node(ws.get()->label); builder->node(ws.get()->label);
} }
} }
if (m_scroll) { if (m_scroll) {
builder->cmd_close(true); builder->cmd_close();
builder->cmd_close(true); builder->cmd_close();
} }
return true; return true;

View file

@ -55,11 +55,11 @@ namespace modules {
if (tag == TAG_LABEL_TOGGLE && m_level == -1) { if (tag == TAG_LABEL_TOGGLE && m_level == -1) {
builder->cmd(mousebtn::LEFT, string(EVENT_MENU_OPEN) + "0"); builder->cmd(mousebtn::LEFT, string(EVENT_MENU_OPEN) + "0");
builder->node(m_labelopen); builder->node(m_labelopen);
builder->cmd_close(true); builder->cmd_close();
} else if (tag == TAG_LABEL_TOGGLE && m_level > -1) { } else if (tag == TAG_LABEL_TOGGLE && m_level > -1) {
builder->cmd(mousebtn::LEFT, EVENT_MENU_CLOSE); builder->cmd(mousebtn::LEFT, EVENT_MENU_CLOSE);
builder->node(m_labelclose); builder->node(m_labelclose);
builder->cmd_close(true); builder->cmd_close();
} else if (tag == TAG_MENU && m_level > -1) { } else if (tag == TAG_MENU && m_level > -1) {
for (auto&& item : m_levels[m_level]->items) { for (auto&& item : m_levels[m_level]->items) {
if (item != m_levels[m_level]->items.front()) if (item != m_levels[m_level]->items.front())
@ -68,7 +68,7 @@ namespace modules {
builder->node(m_labelseparator, true); builder->node(m_labelseparator, true);
builder->cmd(mousebtn::LEFT, item->exec); builder->cmd(mousebtn::LEFT, item->exec);
builder->node(item->label); builder->node(item->label);
builder->cmd_close(true); builder->cmd_close();
} }
} else { } else {
return false; return false;

View file

@ -1,104 +0,0 @@
#include "modules/meta/inotify_module.hpp"
#include "modules/backlight.hpp"
#include "modules/battery.hpp"
POLYBAR_NS
namespace modules {
// public {{{
template <class Impl>
void inotify_module<Impl>::start() {
CAST_MOD(Impl)->m_mainthread = thread(&inotify_module::runner, this);
}
// }}}
// protected {{{
template <class Impl>
void inotify_module<Impl>::runner() {
try {
// Send initial broadcast to warmup cache
if (CONST_MOD(Impl).running()) {
CAST_MOD(Impl)->on_event(nullptr);
CAST_MOD(Impl)->broadcast();
}
while (CONST_MOD(Impl).running()) {
CAST_MOD(Impl)->poll_events();
}
} catch (const module_error& err) {
CAST_MOD(Impl)->halt(err.what());
} catch (const std::exception& err) {
CAST_MOD(Impl)->halt(err.what());
}
}
template <class Impl>
void inotify_module<Impl>::watch(string path, int mask) {
this->m_log.trace("%s: Attach inotify at %s", CONST_MOD(Impl).name(), path);
m_watchlist.insert(make_pair(path, mask));
}
template <class Impl>
void inotify_module<Impl>::idle() {
CAST_MOD(Impl)->sleep(200ms);
}
template <class Impl>
void inotify_module<Impl>::poll_events() {
vector<inotify_util::watch_t> watches;
try {
for (auto&& w : m_watchlist) {
watches.emplace_back(inotify_util::make_watch(w.first));
watches.back()->attach(w.second);
}
} catch (const system_error& e) {
watches.clear();
this->m_log.err("%s: Error while creating inotify watch (what: %s)", CONST_MOD(Impl).name(), e.what());
CAST_MOD(Impl)->sleep(0.1s);
return;
}
while (CONST_MOD(Impl).running()) {
std::unique_lock<concurrency_util::spin_lock> guard(this->m_lock);
{
for (auto&& w : watches) {
this->m_log.trace_x("%s: Poll inotify watch %s", CONST_MOD(Impl).name(), w->path());
if (w->poll(1000 / watches.size())) {
auto event = w->get_event();
for (auto&& w : watches) {
try {
w->remove();
} catch (const system_error&) {
}
}
if (CAST_MOD(Impl)->on_event(event.get()))
CAST_MOD(Impl)->broadcast();
CAST_MOD(Impl)->idle();
return;
}
if (!CONST_MOD(Impl).running())
break;
}
}
guard.unlock();
CAST_MOD(Impl)->idle();
}
}
// }}}
template class inotify_module<backlight_module>;
template class inotify_module<battery_module>;
}
POLYBAR_NS_END

View file

@ -142,9 +142,9 @@ namespace modules {
m_builder->node(static_module::get_output()); m_builder->node(static_module::get_output());
if (m_percentage < 100) if (m_percentage < 100)
m_builder->cmd_close(true); m_builder->cmd_close();
if (m_percentage > 0) if (m_percentage > 0)
m_builder->cmd_close(true); m_builder->cmd_close();
} else { } else {
m_builder->node(static_module::get_output()); m_builder->node(static_module::get_output());
} }

View file

@ -38,10 +38,10 @@ font_manager::~font_manager() {
} }
bool font_manager::load(string name, int8_t fontindex, int8_t offset_y) { bool font_manager::load(string name, int8_t fontindex, int8_t offset_y) {
if (fontindex != -1 && m_fonts.find(fontindex) != m_fonts.end()) { if (fontindex != DEFAULT_FONT_INDEX && m_fonts.find(fontindex) != m_fonts.end()) {
m_logger.warn("A font with index '%i' has already been loaded, skip...", fontindex); m_logger.warn("A font with index '%i' has already been loaded, skip...", fontindex);
return false; return false;
} else if (fontindex == -1) { } else if (fontindex == DEFAULT_FONT_INDEX) {
fontindex = m_fonts.size(); fontindex = m_fonts.size();
m_logger.trace("font_manager: Assign font '%s' to index '%d'", name.c_str(), fontindex); m_logger.trace("font_manager: Assign font '%s' to index '%d'", name.c_str(), fontindex);
} else { } else {
@ -80,7 +80,7 @@ bool font_manager::load(string name, int8_t fontindex, int8_t offset_y) {
void font_manager::set_preferred_font(int8_t index) { void font_manager::set_preferred_font(int8_t index) {
if (index <= 0) { if (index <= 0) {
m_fontindex = -1; m_fontindex = DEFAULT_FONT_INDEX;
return; return;
} }
@ -95,7 +95,7 @@ void font_manager::set_preferred_font(int8_t index) {
font_t& font_manager::match_char(uint16_t chr) { font_t& font_manager::match_char(uint16_t chr) {
static font_t notfound; static font_t notfound;
if (!m_fonts.empty()) { if (!m_fonts.empty()) {
if (m_fontindex != -1 && size_t(m_fontindex) <= m_fonts.size()) { if (m_fontindex != DEFAULT_FONT_INDEX && size_t(m_fontindex) <= m_fonts.size()) {
auto iter = m_fonts.find(m_fontindex); auto iter = m_fonts.find(m_fontindex);
if (iter != m_fonts.end() && has_glyph(iter->second, chr)) if (iter != m_fonts.end() && has_glyph(iter->second, chr))
return iter->second; return iter->second;

View file

@ -30,4 +30,10 @@ int main() {
uint32_t colorC{0x00ffffff}; uint32_t colorC{0x00ffffff};
expect(color_util::hex<uint16_t>(colorC).compare("#00ffffff") == 0); expect(color_util::hex<uint16_t>(colorC).compare("#00ffffff") == 0);
}; };
"simplify"_test = [] {
expect(color_util::simplify_hex("#ff223344") == "#234");
expect(color_util::simplify_hex("#ee223344") == "#ee223344");
expect(color_util::simplify_hex("#ff234567") == "#234567");
};
} }