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
#include <boost/di.hpp>
#include <cassert>
#include <cerrno>
#include <cstring>
#include <map>

View File

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

View File

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

View File

@ -12,6 +12,8 @@ class logger;
class renderer {
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,
const bar_settings& bar, const vector<string>& fonts);
@ -27,26 +29,29 @@ class renderer {
void set_foreground(const uint32_t color);
void set_underline(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_attribute(const attribute attr, const bool state);
void toggle_attribute(const attribute attr);
bool check_attribute(const attribute attr);
void fill_background();
void fill_border(const map<edge, border_settings>& borders, edge border);
void fill_overline(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_textstring(const char* text, size_t len);
void draw_character(const uint16_t character);
void draw_textstring(const char* text, const size_t len);
int16_t shift_content(int16_t x, int16_t shift_x);
int16_t shift_content(int16_t shift_x);
void begin_action(const mousebtn btn, const string& cmd);
void begin_action(const mousebtn btn, const string cmd);
void end_action(const mousebtn btn);
const vector<action_block> get_actions();
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();
private:
@ -67,16 +72,13 @@ class renderer {
vector<action_block> m_actions;
// bool m_autosize{false};
int m_currentx{0};
int m_attributes{0};
uint16_t m_currentx{0U};
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};
uint32_t m_background{0};
uint32_t m_foreground{0};
uint32_t m_underline{0};
uint32_t m_overline{0};
xcb_font_t m_gcfont{XCB_NONE};
edge m_reserve_at{edge::NONE};
uint16_t m_reserve;

View File

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

View File

@ -6,14 +6,28 @@
POLYBAR_NS
enum class edge : uint8_t { NONE = 0, 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 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 gc : uint8_t { NONE = 0, BG, FG, OL, UL, BT, BB, BL, BR };
enum class edge : uint8_t { NONE = 0U, TOP, BOTTOM, LEFT, RIGHT, ALL };
enum class alignment : uint8_t { NONE = 0U, LEFT, CENTER, RIGHT };
enum class attribute : uint8_t { NONE = 0U, UNDERLINE, OVERLINE };
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 {
LEFT = 0,
LEFT = 0U,
RIGHT,
TOP,
BOTTOM,
@ -33,45 +47,45 @@ struct position {
};
struct size {
uint16_t w{0};
uint16_t h{0};
uint16_t w{1U};
uint16_t h{1U};
};
struct side_values {
uint16_t left{0};
uint16_t right{0};
uint16_t left{0U};
uint16_t right{0U};
};
struct edge_values {
uint16_t left{0};
uint16_t right{0};
uint16_t top{0};
uint16_t bottom{0};
uint16_t left{0U};
uint16_t right{0U};
uint16_t top{0U};
uint16_t bottom{0U};
};
struct border_settings {
uint32_t color{0xFF000000};
uint16_t size{0};
uint16_t size{0U};
};
struct line_settings {
uint32_t color{0xFF000000};
uint16_t size{0};
uint16_t size{0U};
};
struct bar_settings {
monitor_t monitor;
edge origin{edge::TOP};
struct size size{0, 0};
struct size size {
1U, 1U
};
position pos{0, 0};
position offset{0, 0};
position center{0, 0};
side_values padding{0, 0};
side_values margin{0, 0};
side_values module_margin{0, 2};
edge_values strut{0, 0, 0, 0};
side_values padding{0U, 0U};
side_values margin{0U, 0U};
side_values module_margin{0U, 2U};
edge_values strut{0U, 0U, 0U, 0U};
uint32_t background{0xFFFFFFFF};
uint32_t foreground{0xFF000000};
@ -81,7 +95,7 @@ struct bar_settings {
map<edge, border_settings> borders;
int8_t spacing{1};
uint8_t spacing{1U};
string separator;
string wmname;
@ -89,8 +103,12 @@ struct bar_settings {
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};
if (local_coords) {
rect.x = 0;
rect.y = 0;
}
rect.y += borders.at(edge::TOP).size;
rect.height -= borders.at(edge::TOP).size;
rect.height -= borders.at(edge::BOTTOM).size;

View File

@ -28,20 +28,22 @@
#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@"
#define BSPWM_SOCKET_PATH "@SETTING_BSPWM_SOCKET_PATH@"
#define BSPWM_STATUS_PREFIX "@SETTING_BSPWM_STATUS_PREFIX@"
#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@"
static constexpr const char* BUILDER_SPACE_TOKEN{"%__"};
static const int8_t DEFAULT_FONT_INDEX{-1};
auto version_details = [](const std::vector<std::string>& args) {
for (auto&& arg : args) {

View File

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

View File

@ -88,7 +88,23 @@ namespace color_util {
inline uint32_t parse(string hex, uint32_t fallback = 0) {
if ((hex = parse_hex(hex)).empty())
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);
~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);
@ -72,7 +72,7 @@ class font_manager {
Colormap m_colormap{};
map<uint8_t, font_t> m_fonts;
int8_t m_fontindex{-1};
int8_t m_fontindex{DEFAULT_FONT_INDEX};
XftColor m_xftcolor{};
XftDraw* m_xftdraw{nullptr};

View File

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

View File

@ -19,6 +19,8 @@
POLYBAR_NS
namespace ph = std::placeholders;
/**
* Configure injection module
*/
@ -47,21 +49,6 @@ bar::bar(connection& conn, const config& config, const logger& logger, unique_pt
*/
bar::~bar() {
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);
}
@ -152,52 +139,6 @@ void bar::bootstrap(bool nodraw) {
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_connection.attach_sink(this, 1);
@ -210,11 +151,33 @@ void bar::bootstrap(bool nodraw) {
reconfigure_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
try {
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();
try {
parser parser(m_opts);
parser parser{m_log, m_opts};
parser(data);
} catch (const unrecognized_token& err) {
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_connection.flush();
}
/**
@ -666,7 +634,6 @@ void bar::handle(const evt::expose& evt) {
* pseudo-transparent background when it changes
*/
void bar::handle(const evt::property_notify& evt) {
(void)evt;
#if DEBUG
string atom_name = m_connection.get_atom_name(evt->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 (!g_signals::bar::visibility_change) {
return;
return m_log.trace("bar: no callback handler set for bar visibility change");
}
try {

View File

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

View File

@ -430,7 +430,7 @@ void controller::bootstrap_modules() {
module_count++;
} 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, "F-}%{F#", "F#");
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, "Uo-}%{Uo#", "Uo#");
block_contents = string_util::replace_all(block_contents, "u-}%{u#", "u#");
block_contents = string_util::replace_all(block_contents, "o-}%{o#", "o#");
// Join consecutive tags
contents += string_util::replace_all(block_contents, "}%{", " ");
@ -564,14 +564,23 @@ void controller::on_update() {
if (m_writeback) {
std::cout << contents << std::endl;
} else {
m_bar->parse(contents);
return;
}
try {
m_bar->parse(contents);
} 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());
}
}
POLYBAR_NS_END

View File

@ -1,3 +1,6 @@
#include <cassert>
#include "components/logger.hpp"
#include "components/parser.hpp"
#include "components/signals.hpp"
#include "components/types.hpp"
@ -6,14 +9,35 @@
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) {
size_t pos;
m_log.trace_x("parser: %s", data);
while (data.length()) {
if (data.compare(0, 2, "%{") == 0 && (pos = data.find("}")) != string::npos) {
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) {
size_t pos;
@ -38,7 +62,7 @@ void parser::codeblock(string data) {
if (data.empty())
break;
char tag = data[0];
char tag{data[0]};
string value;
// Remove the tag
@ -51,90 +75,77 @@ void parser::codeblock(string data) {
switch (tag) {
case 'B':
// Ignore tag if it occurs again later in the same block
if (data.find(" B") == string::npos && g_signals::parser::color_change)
g_signals::parser::color_change(gc::BG, parse_color(value, m_bar.background));
g_signals::parser::background_change(parse_color(value, m_bar.background));
break;
case 'F':
// Ignore tag if it occurs again later in the same block
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);
}
g_signals::parser::foreground_change(parse_color(value, m_bar.foreground));
break;
case 'T':
if (data.find(" T") == string::npos && g_signals::parser::font_change)
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;
case 'O':
if (g_signals::parser::pixel_offset)
g_signals::parser::pixel_offset(std::atoi(value.c_str()));
g_signals::parser::pixel_offset(atoi(value.c_str()));
break;
case 'l':
if (g_signals::parser::alignment_change)
g_signals::parser::alignment_change(alignment::LEFT);
break;
case 'c':
if (g_signals::parser::alignment_change)
g_signals::parser::alignment_change(alignment::CENTER);
break;
case 'r':
if (g_signals::parser::alignment_change)
g_signals::parser::alignment_change(alignment::RIGHT);
break;
case '+':
if (g_signals::parser::attribute_set)
g_signals::parser::attribute_set(parse_attr(value[0]));
break;
case '-':
if (g_signals::parser::attribute_unset)
g_signals::parser::attribute_unset(parse_attr(value[0]));
break;
case '!':
g_signals::parser::attribute_toggle(parse_attr(value[0]));
break;
case 'A':
if (isdigit(data[0]) || data[0] == ':') {
value = parse_action_cmd(data);
mousebtn btn = parse_action_btn(data);
m_actions.push_back(static_cast<int>(btn));
if (g_signals::parser::action_block_open)
g_signals::parser::action_block_open(btn, value);
// make sure we strip the correct length (btn+wrapping colons)
if (data[0] != ':')
if (value[0] != ':')
value += "0";
value += "::";
} else if (!m_actions.empty()) {
if (g_signals::parser::action_block_close)
g_signals::parser::action_block_close(parse_action_btn(data));
g_signals::parser::action_block_close(parse_action_btn(value));
m_actions.pop_back();
}
break;
@ -149,12 +160,12 @@ void parser::codeblock(string data) {
}
/**
* Parse text strings
* Process text contents
*/
size_t parser::text(string data) {
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
size_t next_tag = data.find("%{");
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);
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
if (g_signals::parser::unicode_text_write)
g_signals::parser::unicode_text_write((utf[0] & 0x1f) << 6 | (utf[1] & 0x3f));
return 2;
} 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));
return 3;
} 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);
return 4;
} 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);
return 5;
} 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);
return 6;
} else { // invalid utf-8 sequence
if (g_signals::parser::ascii_text_write)
g_signals::parser::ascii_text_write(utf[0]);
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 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) {
if (s.empty() || s == "-") {
if (s.empty() || s[0] == '-') {
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) {
switch (s) {
attribute parser::parse_attr(const char attr) {
switch (attr) {
case 'o':
return attribute::o;
break;
return attribute::OVERLINE;
case 'u':
return attribute::u;
break;
return attribute::UNDERLINE;
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) {
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) {
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
}
/**
* Construct renderer instance
*/
renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manager> font_manager,
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) {
@ -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_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 values[16]{0};
xcb_params_cw_t params;
// clang-format off
XCB_AUX_ADD_PARAM(&mask, &params, back_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, colormap, m_colormap);
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);
// clang-format on
XCB_AUX_ADD_PARAM(&mask, &params, event_mask,
XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS);
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,
@ -74,17 +76,17 @@ renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manag
};
// clang-format on
for (int i = 1; i <= 8; i++) {
for (int i = 0; i < 8; i++) {
uint32_t mask{0};
uint32_t value_list[32]{0};
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);
xutils::pack_values(mask, &params, value_list);
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_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) {
fontindex++;
vector<string> fd = string_util::split(f, ';');
vector<string> fd{string_util::split(f, ';')};
string pattern{fd[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 {
return m_window;
}
/**
* Begin render routine
*/
void renderer::begin() {
m_log.trace_x("renderer: begin");
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS
for (auto&& action : m_actions) {
m_connection.destroy_window(action.hint);
}
#endif
m_currentx = m_bar.borders.at(edge::LEFT).size;
m_currentx = m_bar.inner_area(true).x;
m_attributes = 0;
m_actions.clear();
fill_border(m_bar.borders, edge::ALL);
fill_background();
m_fontmanager->create_xftdraw(m_pixmap, m_colormap);
}
/**
* End render routine
*/
void renderer::end() {
m_log.trace_x("renderer: end");
redraw();
m_fontmanager->destroy_xftdraw();
@ -155,74 +171,104 @@ void renderer::end() {
m_reserve_at = edge::NONE;
}
/**
* Redraw window contents
*/
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) {
rect.x += m_reserve;
rect.width -= m_reserve;
r.x += m_reserve;
r.width -= m_reserve;
} 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), rect.x, rect.y, rect.x, rect.y, rect.width, rect.height);
m_connection.flush();
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);
}
/**
* Reserve space at given edge
*/
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_reserve = w;
m_reserve_at = side;
}
/**
* Change value of background gc
*/
void renderer::set_background(const uint32_t color) {
if (color == m_background)
return;
if (m_colors[gc::BG] == color) {
return m_log.trace_x("renderer: ignoring unchanged background color(#%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_background = color;
m_colors[gc::BG] = color;
shift_content(0);
}
/**
* Change value of foreground gc
*/
void renderer::set_foreground(const uint32_t color) {
if (color == m_foreground)
return;
if (m_colors[gc::FG] == color) {
return m_log.trace_x("renderer: ignoring unchanged foreground color(#%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_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) {
if (color == m_foreground)
return;
if (m_colors[gc::UL] == color) {
return m_log.trace_x("renderer: ignoring unchanged underline color(#%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_underline = color;
m_colors[gc::UL] = color;
}
/**
* Change value of overline gc
*/
void renderer::set_overline(const uint32_t color) {
if (color == m_foreground)
return;
if (m_colors[gc::OL] == color) {
return m_log.trace_x("renderer: ignoring unchanged overline color(#%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_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_fontindex = font;
}
/**
* Change current alignment
*/
void renderer::set_alignment(const alignment align) {
if (align == m_alignment) {
return;
} else if (align == alignment::LEFT) {
return m_log.trace_x("renderer: ignoring unchanged alignment(%i)", static_cast<uint8_t>(align));
}
if (align == alignment::LEFT) {
m_currentx = m_bar.borders.at(edge::LEFT).size;
} else if (align == alignment::RIGHT) {
m_currentx = m_bar.borders.at(edge::RIGHT).size;
@ -240,17 +286,40 @@ void renderer::set_alignment(const alignment align) {
m_alignment = align;
}
/**
* Enable/remove attribute
*/
void renderer::set_attribute(const attribute attr, bool state) {
m_log.trace_x("renderer: set_attribute(%i, %i)", static_cast<uint8_t>(attr), state);
if (state) {
m_attributes |= static_cast<uint8_t>(attr);
m_attributes |= 1U << static_cast<uint8_t>(attr);
} 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() {
m_log.trace_x("renderer: fill_background");
xcb_rectangle_t rect{0, 0, m_bar.size.w, m_bar.size.h};
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);
}
/**
* Fill border area
*/
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) {
if (border != edge::ALL && b.first != border)
continue;
if (b.second.size <= 0)
if (!b.second.size || (border != edge::ALL && b.first != border))
continue;
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) {
if (!m_bar.overline.size || !(m_attributes & static_cast<int>(attribute::o)))
return;
int16_t y{static_cast<int16_t>(m_bar.borders.at(edge::TOP).size)};
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::OL), x, y, w, m_bar.overline.size);
if (!check_attribute(attribute::OVERLINE)) {
return m_log.trace_x("renderer: not filling overline (flag unset)");
} else if (!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) {
if (!m_bar.underline.size || !(m_attributes & static_cast<int>(attribute::u)))
return;
int16_t y{static_cast<int16_t>(m_bar.size.h - m_bar.borders.at(edge::BOTTOM).size - m_bar.underline.size)};
if (!check_attribute(attribute::UNDERLINE)) {
return m_log.trace_x("renderer: not filling underline (flag unset)");
} 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);
}
/**
* 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) {
m_log.trace_x("renderer: draw_character(\"%c\")", character);
auto& font = m_fontmanager->match_char(character);
if (!font) {
return;
return m_log.warn("No suitable font found (character=%i)", character);
}
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) {
m_log.trace_x("renderer: draw_textstring(\"%s\")", text);
for (size_t n = 0; n < len; n++) {
vector<uint16_t> chars;
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]);
if (!font) {
return;
return m_log.warn("No suitable font found (character=%i)", chars[0]);
}
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;
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);
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) {
/**
* Create new action block at the current position
*/
void renderer::begin_action(const mousebtn btn, const string cmd) {
action_block action{};
action.button = btn;
action.align = m_alignment;
@ -443,6 +506,9 @@ void renderer::begin_action(const mousebtn btn, const string& cmd) {
m_actions.emplace_back(action);
}
/**
* End action block at the current position
*/
void renderer::end_action(const mousebtn btn) {
for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) {
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() {
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() {
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS
m_log.info("Drawing debug hints");
map<alignment, int> hint_num{{
{alignment::LEFT, 0}, {alignment::CENTER, 0}, {alignment::RIGHT, 0},
}};
@ -489,8 +616,6 @@ void renderer::debughints() {
continue;
}
m_log.info("Drawing clickable area hints");
hint_num[action.align]++;
auto x = action.start_x;
@ -507,8 +632,6 @@ void renderer::debughints() {
XCB_WINDOW_CLASS_INPUT_OUTPUT, m_screen->root_visual, mask, values);
m_connection.map_window(action.hint);
}
m_connection.flush();
#endif
}

View File

@ -6,20 +6,24 @@ POLYBAR_NS
/**
* Signals used to communicate with the bar window
*/
callback<string> g_signals::bar::action_click{nullptr};
callback<bool> g_signals::bar::visibility_change{nullptr};
callback<const string> g_signals::bar::action_click{nullptr};
callback<const bool> g_signals::bar::visibility_change{nullptr};
/**
* 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 attribute> g_signals::parser::attribute_set{nullptr};
callback<const attribute> g_signals::parser::attribute_unset{nullptr};
callback<const mousebtn, string> g_signals::parser::action_block_open{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 attribute> g_signals::parser::attribute_toggle{nullptr};
callback<const int8_t> g_signals::parser::font_change{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::unicode_text_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
*/
callback<uint16_t> g_signals::tray::report_slotcount{nullptr};
callback<const uint16_t> g_signals::tray::report_slotcount{nullptr};
POLYBAR_NS_END

View File

@ -1,5 +1,5 @@
#include "x11/color.hpp"
#include "components/types.hpp"
#include "x11/color.hpp"
#include "drawtypes/progressbar.hpp"
#include "utils/math.hpp"
@ -7,6 +7,9 @@
POLYBAR_NS
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) {
m_fill = forward<decltype(fill)>(fill);
}
@ -82,8 +85,7 @@ namespace drawtypes {
* Create a progressbar by loading values
* from the configuration
*/
progressbar_t load_progressbar(
const bar_settings& bar, const config& conf, string section, string name) {
progressbar_t load_progressbar(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
name = string_util::ltrim(string_util::rtrim(name, '>'), '<');

View File

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

View File

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

View File

@ -55,11 +55,11 @@ namespace modules {
if (tag == TAG_LABEL_TOGGLE && m_level == -1) {
builder->cmd(mousebtn::LEFT, string(EVENT_MENU_OPEN) + "0");
builder->node(m_labelopen);
builder->cmd_close(true);
builder->cmd_close();
} else if (tag == TAG_LABEL_TOGGLE && m_level > -1) {
builder->cmd(mousebtn::LEFT, EVENT_MENU_CLOSE);
builder->node(m_labelclose);
builder->cmd_close(true);
builder->cmd_close();
} else if (tag == TAG_MENU && m_level > -1) {
for (auto&& item : m_levels[m_level]->items) {
if (item != m_levels[m_level]->items.front())
@ -68,7 +68,7 @@ namespace modules {
builder->node(m_labelseparator, true);
builder->cmd(mousebtn::LEFT, item->exec);
builder->node(item->label);
builder->cmd_close(true);
builder->cmd_close();
}
} else {
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());
if (m_percentage < 100)
m_builder->cmd_close(true);
m_builder->cmd_close();
if (m_percentage > 0)
m_builder->cmd_close(true);
m_builder->cmd_close();
} else {
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) {
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);
return false;
} else if (fontindex == -1) {
} else if (fontindex == DEFAULT_FONT_INDEX) {
fontindex = m_fonts.size();
m_logger.trace("font_manager: Assign font '%s' to index '%d'", name.c_str(), fontindex);
} 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) {
if (index <= 0) {
m_fontindex = -1;
m_fontindex = DEFAULT_FONT_INDEX;
return;
}
@ -95,7 +95,7 @@ void font_manager::set_preferred_font(int8_t index) {
font_t& font_manager::match_char(uint16_t chr) {
static font_t notfound;
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);
if (iter != m_fonts.end() && has_glyph(iter->second, chr))
return iter->second;

View File

@ -30,4 +30,10 @@ int main() {
uint32_t colorC{0x00ffffff};
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");
};
}