diff --git a/include/components/builder.hpp b/include/components/builder.hpp index 8083005d..c64c094c 100644 --- a/include/components/builder.hpp +++ b/include/components/builder.hpp @@ -58,6 +58,10 @@ class builder { void line_color(string color); void line_color_close(bool force = false); + void overline_color(string color); + void overline_color_close(bool force = false); + void underline_color(string color); + void underline_color_close(bool force = false); void overline(string color = ""); void overline_close(bool force = false); @@ -85,6 +89,8 @@ class builder { {syntaxtag::F, 0}, {syntaxtag::T, 0}, {syntaxtag::U, 0}, + {syntaxtag::Uo, 0}, + {syntaxtag::Uu, 0}, {syntaxtag::O, 0}, {syntaxtag::R, 0}, // clang-format on @@ -95,6 +101,8 @@ class builder { {syntaxtag::B, ""}, {syntaxtag::F, ""}, {syntaxtag::U, ""}, + {syntaxtag::Uu, ""}, + {syntaxtag::Uo, ""}, // clang-format on }; diff --git a/include/components/types.hpp b/include/components/types.hpp index 3108a985..091a514d 100644 --- a/include/components/types.hpp +++ b/include/components/types.hpp @@ -8,7 +8,7 @@ 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, O, R, o, u }; +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 }; @@ -54,6 +54,11 @@ struct border_settings { uint16_t size{0}; }; +struct line_settings { + uint32_t color{0xFF000000}; + uint16_t size{0}; +}; + struct bar_settings { monitor_t monitor; @@ -70,11 +75,12 @@ struct bar_settings { uint32_t background{0xFFFFFFFF}; uint32_t foreground{0xFF0000FF}; - uint32_t linecolor{0xFF000000}; + + line_settings underline; + line_settings overline; map borders; - int8_t lineheight{0}; int8_t spacing{1}; string separator; diff --git a/include/x11/winspec.hpp b/include/x11/winspec.hpp index 68ef431e..c1298923 100644 --- a/include/x11/winspec.hpp +++ b/include/x11/winspec.hpp @@ -116,16 +116,21 @@ class winspec { } xcb_window_t operator<<(cw_flush f) { - if (m_window == XCB_NONE) { + if (!m_window) { m_window = m_connection.generate_id(); } + uint32_t values[16]{0}; + if (m_params != nullptr) { + xutils::pack_values(m_mask, m_params, values); + } + if (f.checked) { m_connection.create_window_checked( - m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border, m_class, m_visual, m_mask, m_params); + m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border, m_class, m_visual, m_mask, values); } else { m_connection.create_window( - m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border, m_class, m_visual, m_mask, m_params); + m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border, m_class, m_visual, m_mask, values); } return m_window; @@ -134,18 +139,17 @@ class winspec { protected: connection& m_connection; uint32_t m_window; - - uint8_t m_depth; - xcb_window_t m_parent; + uint32_t m_parent; int16_t m_x; int16_t m_y; uint16_t m_width; uint16_t m_height; - uint16_t m_border; - uint16_t m_class; + uint8_t m_depth{XCB_COPY_FROM_PARENT}; + uint16_t m_border{XCB_COPY_FROM_PARENT}; + uint16_t m_class{XCB_COPY_FROM_PARENT}; xcb_visualid_t m_visual; uint32_t m_mask; - const xcb_params_cw_t* m_params; + const xcb_params_cw_t* m_params{nullptr}; }; POLYBAR_NS_END diff --git a/src/components/bar.cpp b/src/components/bar.cpp index e092083d..fb4cbe0b 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -8,14 +8,10 @@ #include "utils/color.hpp" #include "utils/math.hpp" #include "utils/string.hpp" -#include "x11/draw.hpp" -#include "x11/draw.hpp" #include "x11/fonts.hpp" #include "x11/graphics.hpp" #include "x11/tray.hpp" #include "x11/wm.hpp" -#include "x11/xlib.hpp" -#include "x11/xutils.hpp" #if ENABLE_I3 #include "utils/i3.hpp" @@ -94,7 +90,23 @@ void bar::bootstrap(bool nodraw) { m_opts.background = color::parse(m_conf.get(bs, "background", color_util::hex(m_opts.background))); m_opts.foreground = color::parse(m_conf.get(bs, "foreground", color_util::hex(m_opts.foreground))); - m_opts.linecolor = color::parse(m_conf.get(bs, "linecolor", color_util::hex(m_opts.linecolor))); + + auto linecolor = color::parse(m_conf.get(bs, "linecolor", "#f00")); + auto lineheight = m_conf.get(bs, "lineheight", 0); + + try { + m_opts.overline.size = m_conf.get(bs, "overline-size", lineheight); + m_opts.overline.color = color::parse(m_conf.get(bs, "overline-color")); + } catch (const key_error& err) { + m_opts.overline.color = linecolor; + } + + try { + m_opts.underline.size = m_conf.get(bs, "underline-size", lineheight); + m_opts.underline.color = color::parse(m_conf.get(bs, "underline-color")); + } catch (const key_error& err) { + m_opts.underline.color = linecolor; + } // }}} // Set border values {{{ @@ -128,7 +140,6 @@ void bar::bootstrap(bool nodraw) { GET_CONFIG_VALUE(bs, m_opts.force_docking, "dock"); GET_CONFIG_VALUE(bs, m_opts.spacing, "spacing"); - GET_CONFIG_VALUE(bs, m_opts.lineheight, "lineheight"); GET_CONFIG_VALUE(bs, m_opts.padding.left, "padding-left"); GET_CONFIG_VALUE(bs, m_opts.padding.right, "padding-right"); GET_CONFIG_VALUE(bs, m_opts.module_margin.left, "module-margin-left"); diff --git a/src/components/builder.cpp b/src/components/builder.cpp index e3c3c7a2..af3ea064 100644 --- a/src/components/builder.cpp +++ b/src/components/builder.cpp @@ -16,6 +16,8 @@ string builder::flush() { 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); @@ -80,6 +82,22 @@ void builder::node(string str, bool add_space) { line_color_close(true); s.erase(0, 5); + } else if ((n = s.find("%{Uu-}")) == 0) { + underline_color_close(true); + s.erase(0, 5); + + } else if ((n = s.find("%{Uo-}")) == 0) { + overline_color_close(true); + s.erase(0, 5); + + } else if ((n = s.find("%{Uu#")) == 0 && (m = s.find("}")) != string::npos) { + underline_color(s.substr(n + 4, m - 4)); + 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)); + s.erase(n, m + 1); + } else if ((n = s.find("%{U#")) == 0 && (m = s.find("}")) != string::npos) { line_color(s.substr(n + 3, m - 3)); s.erase(n, m + 1); @@ -347,9 +365,53 @@ void builder::line_color_close(bool force) { tag_close('U'); } +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 + "}"); +} + +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-}"); +} + +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 + "}"); +} + +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-}"); +} + void builder::overline(string color) { if (!color.empty()) - line_color(color); + overline_color(color); if (m_counters[syntaxtag::o] > 0) return; @@ -367,7 +429,7 @@ void builder::overline_close(bool force) { void builder::underline(string color) { if (!color.empty()) - line_color(color); + underline_color(color); if (m_counters[syntaxtag::u] > 0) return; diff --git a/src/components/parser.cpp b/src/components/parser.cpp index 567373c7..cb25368b 100644 --- a/src/components/parser.cpp +++ b/src/components/parser.cpp @@ -63,10 +63,15 @@ void parser::codeblock(string data) { break; case 'U': - // Ignore tag if it occurs again later in the same block - if (data.find(" U") == string::npos && g_signals::parser::color_change) { - g_signals::parser::color_change(gc::UL, parse_color(value, m_bar.linecolor)); - g_signals::parser::color_change(gc::OL, parse_color(value, m_bar.linecolor)); + if (g_signals::parser::color_change) { + if (value[0] == 'u' && 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' && 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; diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp index 19728b5f..68083dbe 100644 --- a/src/components/renderer.cpp +++ b/src/components/renderer.cpp @@ -3,7 +3,8 @@ #include "x11/connection.hpp" #include "x11/draw.hpp" #include "x11/fonts.hpp" -#include "x11/winspec.hpp" +#include "x11/xlib.hpp" +#include "x11/xutils.hpp" POLYBAR_NS @@ -64,8 +65,8 @@ renderer::renderer(connection& conn, const logger& logger, unique_ptr colors { m_bar.background, m_bar.foreground, - m_bar.linecolor, - m_bar.linecolor, + m_bar.overline.color, + m_bar.underline.color, m_bar.borders.at(edge::TOP).color, m_bar.borders.at(edge::BOTTOM).color, m_bar.borders.at(edge::LEFT).color, @@ -278,19 +279,17 @@ void renderer::fill_border(const map& borders, edge borde } void renderer::fill_overline(int16_t x, uint16_t w) { - if (!m_bar.lineheight || !(m_attributes & static_cast(attribute::o))) + if (!m_bar.overline.size || !(m_attributes & static_cast(attribute::o))) return; - - draw_util::fill( - m_connection, m_pixmap, m_gcontexts.at(gc::OL), x, m_bar.borders.at(edge::TOP).size, w, m_bar.lineheight); + int16_t y{static_cast(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); } void renderer::fill_underline(int16_t x, uint16_t w) { - if (!m_bar.lineheight || !(m_attributes & static_cast(attribute::u))) + if (!m_bar.underline.size || !(m_attributes & static_cast(attribute::u))) return; - - draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::UL), x, - m_bar.size.h - m_bar.borders.at(edge::BOTTOM).size - m_bar.lineheight, w, m_bar.lineheight); + int16_t y{static_cast(m_bar.size.h - m_bar.borders.at(edge::BOTTOM).size - m_bar.underline.size)}; + draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::UL), x, y, w, m_bar.underline.size); } void renderer::draw_character(uint16_t character) {