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
@ -106,9 +106,9 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||
// }}}
|
||||
// Set bar colors {{{
|
||||
|
||||
m_bar.background = color::parse(m_conf.get<string>(bs, "background", m_bar.background.hex()));
|
||||
m_bar.foreground = color::parse(m_conf.get<string>(bs, "foreground", m_bar.foreground.hex()));
|
||||
m_bar.linecolor = color::parse(m_conf.get<string>(bs, "linecolor", m_bar.linecolor.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_to_rgba()));
|
||||
m_bar.linecolor = color::parse(m_conf.get<string>(bs, "linecolor", m_bar.linecolor.hex_to_rgba()));
|
||||
|
||||
// }}}
|
||||
// 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_) { //{{{
|
||||
m_log.trace_x(
|
||||
"bar: color_change(%i, %s -> %s)", static_cast<int>(gc_), color_.hex(), color_.rgb());
|
||||
|
||||
const uint32_t value_list[32]{color_.value()};
|
||||
m_connection.change_gc(m_gcontexts.at(gc_), XCB_GC_FOREGROUND, value_list);
|
||||
"bar: color_change(%i, %s -> %s)", static_cast<int>(gc_), color_.hex_to_rgba(), color_.hex_to_rgb());
|
||||
|
||||
if (gc_ == gc::FG) {
|
||||
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) {
|
||||
if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) {
|
||||
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));
|
||||
} else if (color.length() >= 7 && color == "#" + string(color.length() - 1, color[1])) {
|
||||
color = color.substr(0, 4);
|
||||
@ -295,7 +295,7 @@ class builder {
|
||||
auto color(color_);
|
||||
if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) {
|
||||
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));
|
||||
} else if (color.length() >= 7 && color == "#" + string(color.length() - 1, color[1])) {
|
||||
color = color.substr(0, 4);
|
||||
@ -315,7 +315,7 @@ class builder {
|
||||
|
||||
void color_alpha(string alpha_) {
|
||||
auto alpha(alpha_);
|
||||
string val = m_bar.foreground.hex();
|
||||
string val = m_bar.foreground.hex_to_rgba();
|
||||
if (alpha.find("#") == std::string::npos) {
|
||||
alpha = "#" + alpha;
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ static map<string, class color> g_colorstore;
|
||||
class color {
|
||||
public:
|
||||
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
|
||||
m_rgba._.r = m_rgba._.r * m_rgba._.a / 255;
|
||||
m_rgba._.g = m_rgba._.g * m_rgba._.a / 255;
|
||||
@ -33,14 +35,34 @@ class color {
|
||||
char buffer[7];
|
||||
snprintf(buffer, sizeof(buffer), "%06x", v);
|
||||
m_hex = "#" + string{buffer};
|
||||
m_rgba.v = v;
|
||||
m_rgba.v = (strtoul(&m_hex[1], nullptr, 16));
|
||||
}
|
||||
|
||||
uint32_t value() const {
|
||||
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
|
||||
return string_util::from_stream(stringstream()
|
||||
<< "#"
|
||||
@ -52,7 +74,7 @@ class color {
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
string hex() const {
|
||||
string hex_to_rgba() const {
|
||||
return m_hex;
|
||||
}
|
||||
|
||||
@ -82,6 +104,7 @@ class color {
|
||||
|
||||
protected:
|
||||
rgba m_rgba;
|
||||
unsigned long m_rgb;
|
||||
string m_hex;
|
||||
};
|
||||
|
||||
|
@ -51,8 +51,8 @@ class fontmanager {
|
||||
explicit fontmanager(connection& conn, const logger& logger)
|
||||
: m_connection(conn), m_logger(logger) {
|
||||
m_display = xlib::get_display();
|
||||
m_visual = xlib::get_visual();
|
||||
m_colormap = XDefaultColormap(m_display, 0);
|
||||
m_visual = xlib::get_visual(conn.default_screen());
|
||||
m_colormap = xlib::create_colormap(conn.default_screen());
|
||||
}
|
||||
|
||||
~fontmanager() {
|
||||
@ -170,8 +170,15 @@ class fontmanager {
|
||||
if (!initial_alloc)
|
||||
XftColorFree(m_display, m_visual, m_colormap, &m_xftcolor);
|
||||
|
||||
if (!XftColorAllocName(m_display, m_visual, m_colormap, xcolor.rgb().c_str(), &m_xftcolor))
|
||||
m_logger.err("Failed to allocate color '%s'", xcolor.hex());
|
||||
XRenderColor color;
|
||||
|
||||
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) { // {{{
|
||||
|
@ -8,7 +8,7 @@ LEMONBUDDY_NS
|
||||
|
||||
namespace xlib {
|
||||
static Display* g_display = nullptr;
|
||||
static Visual* g_visual = nullptr;
|
||||
static XVisualInfo g_visual_info;
|
||||
|
||||
/**
|
||||
* Get pointer of Xlib Display
|
||||
@ -22,22 +22,16 @@ namespace xlib {
|
||||
/**
|
||||
* Get pointer of Xlib visual
|
||||
*/
|
||||
inline Visual* get_visual() {
|
||||
if (g_visual == nullptr) {
|
||||
XVisualInfo xv;
|
||||
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);
|
||||
inline Visual* get_visual(int screen = 0) {
|
||||
if (g_visual_info.visual == nullptr) {
|
||||
XMatchVisualInfo(get_display(), screen, 32, TrueColor, &g_visual_info);
|
||||
}
|
||||
|
||||
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
|
||||
if (icon_empty && icon_indicator) {
|
||||
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())
|
||||
icon_empty->m_foreground = bar.foreground.hex();
|
||||
icon_empty->m_foreground = bar.foreground.hex_to_rgba();
|
||||
}
|
||||
|
||||
progressbar->set_empty(move(icon_empty));
|
||||
|
@ -18,3 +18,6 @@ unit_test("utils/string")
|
||||
unit_test("components/command_line")
|
||||
unit_test("components/di")
|
||||
#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{"#33990022"};
|
||||
expect(test.hex() == "#33990022");
|
||||
expect(test.rgb() == "#1E0006");
|
||||
expect(test.hex_to_rgba() == "#33990022");
|
||||
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 = [] {
|
||||
@ -23,13 +37,13 @@ int main() {
|
||||
};
|
||||
|
||||
"predefined"_test = [] {
|
||||
expect(g_colorblack.hex() == "#FF000000");
|
||||
expect(g_colorwhite.hex() == "#FFFFFFFF");
|
||||
expect(g_colorblack.hex_to_rgba() == "#FF000000");
|
||||
expect(g_colorwhite.hex_to_rgba() == "#FFFFFFFF");
|
||||
};
|
||||
|
||||
"parse"_test = [] {
|
||||
expect(color::parse("#ff9900", g_colorblack).hex() == "#FFFF9900");
|
||||
expect(color::parse("invalid", g_colorwhite).hex() == "#FFFFFFFF");
|
||||
expect(color::parse("33990022", g_colorwhite).rgb() == "#1E0006");
|
||||
expect(color::parse("#ff9900", g_colorblack).hex_to_rgba() == "#FFFF9900");
|
||||
expect(color::parse("invalid", g_colorwhite).hex_to_rgba() == "#FFFFFFFF");
|
||||
expect(color::parse("33990022", g_colorwhite).hex_to_rgb() == "#1E0006");
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user