From 287a0b4c3cc24a18f5063b7d5743f0b85d6852a1 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Mon, 28 Dec 2015 12:58:32 +0100 Subject: [PATCH] get_colorpixel support for non-true color displays Re-introduce fully-fledged get_colorpixel function, which enables arbitrary color depths for the display. The previous code is kept as an optimization for the case of a true color display, where a X11 roundtrip is unnecessary. --- libi3/get_colorpixel.c | 59 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/libi3/get_colorpixel.c b/libi3/get_colorpixel.c index f81ea6c2..8820938f 100644 --- a/libi3/get_colorpixel.c +++ b/libi3/get_colorpixel.c @@ -9,21 +9,28 @@ #include #include +#include "queue.h" #include "libi3.h" +struct Colorpixel { + char *hex; + uint32_t pixel; + + SLIST_ENTRY(Colorpixel) + colorpixels; +}; + +SLIST_HEAD(colorpixel_head, Colorpixel) +colorpixels; + /* - * Returns the colorpixel to use for the given hex color (think of HTML). Only - * works for true-color (vast majority of cases) at the moment, avoiding a - * roundtrip to X11. + * Returns the colorpixel to use for the given hex color (think of HTML). * * The hex_color has to start with #, for example #FF00FF. * * NOTE that get_colorpixel() does _NOT_ check the given color code for validity. * This has to be done by the caller. * - * NOTE that this function may in the future rely on a global xcb_connection_t - * variable called 'conn' to be present. - * */ uint32_t get_colorpixel(const char *hex) { char strgroups[3][3] = { @@ -34,5 +41,43 @@ uint32_t get_colorpixel(const char *hex) { uint8_t g = strtol(strgroups[1], NULL, 16); uint8_t b = strtol(strgroups[2], NULL, 16); - return (0xFF << 24) | (r << 16 | g << 8 | b); + /* Shortcut: if our screen is true color, no need to do a roundtrip to X11 */ + if (root_screen->root_depth == 24 || root_screen->root_depth == 32) { + return (0xFF << 24) | (r << 16 | g << 8 | b); + } + + /* Lookup this colorpixel in the cache */ + struct Colorpixel *colorpixel; + SLIST_FOREACH(colorpixel, &(colorpixels), colorpixels) { + if (strcmp(colorpixel->hex, hex) == 0) + return colorpixel->pixel; + } + +#define RGB_8_TO_16(i) (65535 * ((i)&0xFF) / 255) + int r16 = RGB_8_TO_16(r); + int g16 = RGB_8_TO_16(g); + int b16 = RGB_8_TO_16(b); + + xcb_alloc_color_reply_t *reply; + + reply = xcb_alloc_color_reply(conn, xcb_alloc_color(conn, root_screen->default_colormap, + r16, g16, b16), + NULL); + + if (!reply) { + LOG("Could not allocate color\n"); + exit(1); + } + + uint32_t pixel = reply->pixel; + free(reply); + + /* Store the result in the cache */ + struct Colorpixel *cache_pixel = scalloc(1, sizeof(struct Colorpixel)); + cache_pixel->hex = sstrdup(hex); + cache_pixel->pixel = pixel; + + SLIST_INSERT_HEAD(&(colorpixels), cache_pixel, colorpixels); + + return pixel; }