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:
Michael Carlberg 2016-10-30 02:18:39 +01:00
parent 41ba9beeee
commit efba06dc2d
8 changed files with 84 additions and 43 deletions

View File

@ -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);
}
} //}}}

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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) { // {{{

View File

@ -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);
}
/**

View File

@ -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));

View File

@ -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")

View File

@ -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");
};
}