mirror of
https://github.com/polybar/polybar.git
synced 2024-11-11 13:50:56 -05:00
fix(xft): Allocate xft color by value
- Solves the issue with transparency using Xft. - X11 fonts are still affected by the alpha issue. Closes jaagr/lemonbuddy#119
This commit is contained in:
parent
41ba9beeee
commit
efba06dc2d
8 changed files with 84 additions and 43 deletions
|
@ -106,9 +106,9 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||||
// }}}
|
// }}}
|
||||||
// Set bar colors {{{
|
// Set bar colors {{{
|
||||||
|
|
||||||
m_bar.background = color::parse(m_conf.get<string>(bs, "background", m_bar.background.hex()));
|
m_bar.background = color::parse(m_conf.get<string>(bs, "background", m_bar.background.hex_to_rgba()));
|
||||||
m_bar.foreground = color::parse(m_conf.get<string>(bs, "foreground", m_bar.foreground.hex()));
|
m_bar.foreground = color::parse(m_conf.get<string>(bs, "foreground", m_bar.foreground.hex_to_rgba()));
|
||||||
m_bar.linecolor = color::parse(m_conf.get<string>(bs, "linecolor", m_bar.linecolor.hex()));
|
m_bar.linecolor = color::parse(m_conf.get<string>(bs, "linecolor", m_bar.linecolor.hex_to_rgba()));
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
// Set border values {{{
|
// Set border values {{{
|
||||||
|
@ -779,14 +779,14 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||||
*/
|
*/
|
||||||
void on_color_change(gc gc_, color color_) { //{{{
|
void on_color_change(gc gc_, color color_) { //{{{
|
||||||
m_log.trace_x(
|
m_log.trace_x(
|
||||||
"bar: color_change(%i, %s -> %s)", static_cast<int>(gc_), color_.hex(), color_.rgb());
|
"bar: color_change(%i, %s -> %s)", static_cast<int>(gc_), color_.hex_to_rgba(), color_.hex_to_rgb());
|
||||||
|
|
||||||
const uint32_t value_list[32]{color_.value()};
|
|
||||||
m_connection.change_gc(m_gcontexts.at(gc_), XCB_GC_FOREGROUND, value_list);
|
|
||||||
|
|
||||||
if (gc_ == gc::FG) {
|
if (gc_ == gc::FG) {
|
||||||
m_fontmanager->allocate_color(color_);
|
m_fontmanager->allocate_color(color_);
|
||||||
m_xfont_color = color::parse(color_.rgb()).value();
|
m_xfont_color = color_.value();
|
||||||
|
} else {
|
||||||
|
const uint32_t value_list[32]{color_.value()};
|
||||||
|
m_connection.change_gc(m_gcontexts.at(gc_), XCB_GC_FOREGROUND, value_list);
|
||||||
}
|
}
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
|
|
@ -264,7 +264,7 @@ class builder {
|
||||||
void background(string color) {
|
void background(string color) {
|
||||||
if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) {
|
if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) {
|
||||||
color = "#" + color.substr(color.length() - 2);
|
color = "#" + color.substr(color.length() - 2);
|
||||||
auto bg = m_bar.background.hex();
|
auto bg = m_bar.background.hex_to_rgba();
|
||||||
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);
|
||||||
|
@ -295,7 +295,7 @@ class builder {
|
||||||
auto color(color_);
|
auto color(color_);
|
||||||
if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) {
|
if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) {
|
||||||
color = "#" + color.substr(color.length() - 2);
|
color = "#" + color.substr(color.length() - 2);
|
||||||
auto bg = m_bar.foreground.hex();
|
auto bg = m_bar.foreground.hex_to_rgba();
|
||||||
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);
|
||||||
|
@ -315,7 +315,7 @@ class builder {
|
||||||
|
|
||||||
void color_alpha(string alpha_) {
|
void color_alpha(string alpha_) {
|
||||||
auto alpha(alpha_);
|
auto alpha(alpha_);
|
||||||
string val = m_bar.foreground.hex();
|
string val = m_bar.foreground.hex_to_rgba();
|
||||||
if (alpha.find("#") == std::string::npos) {
|
if (alpha.find("#") == std::string::npos) {
|
||||||
alpha = "#" + alpha;
|
alpha = "#" + alpha;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,9 @@ static map<string, class color> g_colorstore;
|
||||||
class color {
|
class color {
|
||||||
public:
|
public:
|
||||||
explicit color(string hex) : m_hex(string_util::upper(hex)) {
|
explicit color(string hex) : m_hex(string_util::upper(hex)) {
|
||||||
m_rgba.v = static_cast<uint32_t>(strtoul(&hex[1], nullptr, 16));
|
m_rgba.v = (strtoul(&hex[1], nullptr, 16));
|
||||||
|
m_rgb = (m_rgba.v << 8) >> 8;
|
||||||
|
|
||||||
// premultiply alpha
|
// premultiply alpha
|
||||||
m_rgba._.r = m_rgba._.r * m_rgba._.a / 255;
|
m_rgba._.r = m_rgba._.r * m_rgba._.a / 255;
|
||||||
m_rgba._.g = m_rgba._.g * m_rgba._.a / 255;
|
m_rgba._.g = m_rgba._.g * m_rgba._.a / 255;
|
||||||
|
@ -33,14 +35,34 @@ class color {
|
||||||
char buffer[7];
|
char buffer[7];
|
||||||
snprintf(buffer, sizeof(buffer), "%06x", v);
|
snprintf(buffer, sizeof(buffer), "%06x", v);
|
||||||
m_hex = "#" + string{buffer};
|
m_hex = "#" + string{buffer};
|
||||||
m_rgba.v = v;
|
m_rgba.v = (strtoul(&m_hex[1], nullptr, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t value() const {
|
uint32_t value() const {
|
||||||
return m_rgba.v;
|
return m_rgba.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
string rgb() const {
|
uint32_t rgb() const {
|
||||||
|
return m_rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t alpha() const {
|
||||||
|
return 0xFF & (value() >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t red() const {
|
||||||
|
return 0xFF & (rgb() >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t green() const {
|
||||||
|
return 0xFF & (rgb() >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t blue() const {
|
||||||
|
return 0xFF & rgb();
|
||||||
|
}
|
||||||
|
|
||||||
|
string hex_to_rgb() const {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
return string_util::from_stream(stringstream()
|
return string_util::from_stream(stringstream()
|
||||||
<< "#"
|
<< "#"
|
||||||
|
@ -52,7 +74,7 @@ class color {
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
string hex() const {
|
string hex_to_rgba() const {
|
||||||
return m_hex;
|
return m_hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +104,7 @@ class color {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
rgba m_rgba;
|
rgba m_rgba;
|
||||||
|
unsigned long m_rgb;
|
||||||
string m_hex;
|
string m_hex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,8 @@ class fontmanager {
|
||||||
explicit fontmanager(connection& conn, const logger& logger)
|
explicit fontmanager(connection& conn, const logger& logger)
|
||||||
: m_connection(conn), m_logger(logger) {
|
: m_connection(conn), m_logger(logger) {
|
||||||
m_display = xlib::get_display();
|
m_display = xlib::get_display();
|
||||||
m_visual = xlib::get_visual();
|
m_visual = xlib::get_visual(conn.default_screen());
|
||||||
m_colormap = XDefaultColormap(m_display, 0);
|
m_colormap = xlib::create_colormap(conn.default_screen());
|
||||||
}
|
}
|
||||||
|
|
||||||
~fontmanager() {
|
~fontmanager() {
|
||||||
|
@ -170,8 +170,15 @@ class fontmanager {
|
||||||
if (!initial_alloc)
|
if (!initial_alloc)
|
||||||
XftColorFree(m_display, m_visual, m_colormap, &m_xftcolor);
|
XftColorFree(m_display, m_visual, m_colormap, &m_xftcolor);
|
||||||
|
|
||||||
if (!XftColorAllocName(m_display, m_visual, m_colormap, xcolor.rgb().c_str(), &m_xftcolor))
|
XRenderColor color;
|
||||||
m_logger.err("Failed to allocate color '%s'", xcolor.hex());
|
|
||||||
|
color.red = (xcolor.red()) << 8;
|
||||||
|
color.green = (xcolor.green()) << 8;
|
||||||
|
color.blue = (xcolor.blue()) << 8;
|
||||||
|
color.alpha = xcolor.alpha() << 8;
|
||||||
|
|
||||||
|
if (!XftColorAllocValue(m_display, m_visual, m_colormap, &color, &m_xftcolor))
|
||||||
|
m_logger.err("Failed to allocate color '%s'", xcolor.hex_to_rgba());
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
void set_gcontext_font(gcontext& gc, xcb_font_t font) { // {{{
|
void set_gcontext_font(gcontext& gc, xcb_font_t font) { // {{{
|
||||||
|
|
|
@ -8,7 +8,7 @@ LEMONBUDDY_NS
|
||||||
|
|
||||||
namespace xlib {
|
namespace xlib {
|
||||||
static Display* g_display = nullptr;
|
static Display* g_display = nullptr;
|
||||||
static Visual* g_visual = nullptr;
|
static XVisualInfo g_visual_info;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get pointer of Xlib Display
|
* Get pointer of Xlib Display
|
||||||
|
@ -22,22 +22,16 @@ namespace xlib {
|
||||||
/**
|
/**
|
||||||
* Get pointer of Xlib visual
|
* Get pointer of Xlib visual
|
||||||
*/
|
*/
|
||||||
inline Visual* get_visual() {
|
inline Visual* get_visual(int screen = 0) {
|
||||||
if (g_visual == nullptr) {
|
if (g_visual_info.visual == nullptr) {
|
||||||
XVisualInfo xv;
|
XMatchVisualInfo(get_display(), screen, 32, TrueColor, &g_visual_info);
|
||||||
xv.depth = 32;
|
|
||||||
int result = 0;
|
|
||||||
auto result_ptr = XGetVisualInfo(get_display(), VisualDepthMask, &xv, &result);
|
|
||||||
|
|
||||||
if (result > 0)
|
|
||||||
g_visual = result_ptr->visual;
|
|
||||||
else
|
|
||||||
g_visual = XDefaultVisual(get_display(), 0);
|
|
||||||
|
|
||||||
free(result_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_visual;
|
return g_visual_info.visual;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Colormap create_colormap(int screen = 0) {
|
||||||
|
return XCreateColormap(get_display(), XRootWindow(get_display(), screen), get_visual(), screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -144,9 +144,9 @@ namespace drawtypes {
|
||||||
// avoid color bleed
|
// avoid color bleed
|
||||||
if (icon_empty && icon_indicator) {
|
if (icon_empty && icon_indicator) {
|
||||||
if (!icon_indicator->m_background.empty() && icon_empty->m_background.empty())
|
if (!icon_indicator->m_background.empty() && icon_empty->m_background.empty())
|
||||||
icon_empty->m_background = bar.background.hex();
|
icon_empty->m_background = bar.background.hex_to_rgba();
|
||||||
if (!icon_indicator->m_foreground.empty() && icon_empty->m_foreground.empty())
|
if (!icon_indicator->m_foreground.empty() && icon_empty->m_foreground.empty())
|
||||||
icon_empty->m_foreground = bar.foreground.hex();
|
icon_empty->m_foreground = bar.foreground.hex_to_rgba();
|
||||||
}
|
}
|
||||||
|
|
||||||
progressbar->set_empty(move(icon_empty));
|
progressbar->set_empty(move(icon_empty));
|
||||||
|
|
|
@ -18,3 +18,6 @@ unit_test("utils/string")
|
||||||
unit_test("components/command_line")
|
unit_test("components/command_line")
|
||||||
unit_test("components/di")
|
unit_test("components/di")
|
||||||
#unit_test("components/logger")
|
#unit_test("components/logger")
|
||||||
|
unit_test("components/x11/color")
|
||||||
|
#unit_test("components/x11/connection")
|
||||||
|
#unit_test("components/x11/window")
|
||||||
|
|
|
@ -7,8 +7,22 @@ int main() {
|
||||||
|
|
||||||
"color"_test = [] {
|
"color"_test = [] {
|
||||||
color test{"#33990022"};
|
color test{"#33990022"};
|
||||||
expect(test.hex() == "#33990022");
|
expect(test.hex_to_rgba() == "#33990022");
|
||||||
expect(test.rgb() == "#1E0006");
|
expect(test.hex_to_rgb() == "#1E0006");
|
||||||
|
};
|
||||||
|
|
||||||
|
"channels"_test = [] {
|
||||||
|
color test{"#eefb9281"};
|
||||||
|
expect(test.alpha() == 0xee);
|
||||||
|
expect(test.red() == 0xfb);
|
||||||
|
expect(test.green() == 0x92);
|
||||||
|
expect(test.blue() == 0x81);
|
||||||
|
};
|
||||||
|
|
||||||
|
"base"_test = [] {
|
||||||
|
color test{"#eefb9281"};
|
||||||
|
auto hex = test.hex_to_rgb();
|
||||||
|
expect(std::strtoul(&hex[0], 0, 16) == 0x000000);
|
||||||
};
|
};
|
||||||
|
|
||||||
"cache"_test = [] {
|
"cache"_test = [] {
|
||||||
|
@ -23,13 +37,13 @@ int main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
"predefined"_test = [] {
|
"predefined"_test = [] {
|
||||||
expect(g_colorblack.hex() == "#FF000000");
|
expect(g_colorblack.hex_to_rgba() == "#FF000000");
|
||||||
expect(g_colorwhite.hex() == "#FFFFFFFF");
|
expect(g_colorwhite.hex_to_rgba() == "#FFFFFFFF");
|
||||||
};
|
};
|
||||||
|
|
||||||
"parse"_test = [] {
|
"parse"_test = [] {
|
||||||
expect(color::parse("#ff9900", g_colorblack).hex() == "#FFFF9900");
|
expect(color::parse("#ff9900", g_colorblack).hex_to_rgba() == "#FFFF9900");
|
||||||
expect(color::parse("invalid", g_colorwhite).hex() == "#FFFFFFFF");
|
expect(color::parse("invalid", g_colorwhite).hex_to_rgba() == "#FFFFFFFF");
|
||||||
expect(color::parse("33990022", g_colorwhite).rgb() == "#1E0006");
|
expect(color::parse("33990022", g_colorwhite).hex_to_rgb() == "#1E0006");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue