diff --git a/include/button/button-xbm.h b/include/button/button-xbm.h index 173cdfd9..dd0e3169 100644 --- a/include/button/button-xbm.h +++ b/include/button/button-xbm.h @@ -4,9 +4,19 @@ struct lab_data_buffer; +/** + * button_xbm_from_bitmap() - create button from monochrome bitmap + * @bitmap: bitmap data array in hexadecimal xbm format + * @buffer: cairo-surface-buffer to create + * @rgba: color + * + * Example bitmap: char button[6] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f }; + */ +void button_xbm_from_bitmap(const char *bitmap, struct lab_data_buffer **buffer, + float *rgba); + /* button_xbm_load - Convert xbm file to buffer with cairo surface */ -void button_xbm_load(const char *button_name, const char *alt_name, - struct lab_data_buffer **buffer, const char *fallback_button, +void button_xbm_load(const char *button_name, struct lab_data_buffer **buffer, float *rgba); #endif /* LABWC_BUTTON_XBM_H */ diff --git a/src/button/button-xbm.c b/src/button/button-xbm.c index 2d5c4e4f..4222067c 100644 --- a/src/button/button-xbm.c +++ b/src/button/button-xbm.c @@ -259,16 +259,29 @@ parse_xbm_builtin(const char *button, int size) } void -button_xbm_load(const char *button_name, const char *alt_name, - struct lab_data_buffer **buffer, const char *fallback_button, - float *rgba) +button_xbm_from_bitmap(const char *bitmap, struct lab_data_buffer **buffer, + float *rgba) { struct pixmap pixmap = {0}; if (*buffer) { wlr_buffer_drop(&(*buffer)->base); *buffer = NULL; } + color = u32(rgba); + pixmap = parse_xbm_builtin(bitmap, 6); + *buffer = buffer_create_wrap(pixmap.data, pixmap.width, pixmap.height, + pixmap.width * 4, /* free_on_destroy */ true); +} +void +button_xbm_load(const char *button_name, struct lab_data_buffer **buffer, + float *rgba) +{ + struct pixmap pixmap = {0}; + if (*buffer) { + wlr_buffer_drop(&(*buffer)->base); + *buffer = NULL; + } color = u32(rgba); /* Read file into memory as it's easier to tokenize that way */ @@ -283,20 +296,8 @@ button_xbm_load(const char *button_name, const char *alt_name, free(tokens); } } - if (!pixmap.data && *alt_name) { - button_filename(alt_name, filename, sizeof(filename)); - char *token_buffer = grab_file(filename); - if (token_buffer) { - struct token *tokens = tokenize_xbm(token_buffer); - free(token_buffer); - pixmap = parse_xbm_tokens(tokens); - if (tokens) { - free(tokens); - } - } - } - if (!pixmap.data && fallback_button) { - pixmap = parse_xbm_builtin(fallback_button, 6); + if (!pixmap.data) { + return; } /* Create buffer with free_on_destroy being true */ diff --git a/src/theme.c b/src/theme.c index e7e52ccc..f58b92d5 100644 --- a/src/theme.c +++ b/src/theme.c @@ -219,21 +219,20 @@ load_buttons(struct theme *theme) }, }; char filename[4096] = {0}; - char alt_filename[4096] = {0}; for (size_t i = 0; i < ARRAY_SIZE(buttons); ++i) { struct button *b = &buttons[i]; drop(b->active.buffer); drop(b->inactive.buffer); - /* Try png icon first */ + /* PNG */ snprintf(filename, sizeof(filename), "%s-active.png", b->name); button_png_load(filename, b->active.buffer); snprintf(filename, sizeof(filename), "%s-inactive.png", b->name); button_png_load(filename, b->inactive.buffer); #if HAVE_RSVG - /* Then try svg icon */ + /* SVG */ int size = theme->title_height - 2 * theme->padding_height; if (!*b->active.buffer) { snprintf(filename, sizeof(filename), "%s-active.svg", b->name); @@ -245,19 +244,47 @@ load_buttons(struct theme *theme) } #endif - /* If there were no png/svg buttons, use xbm */ + /* XBM */ snprintf(filename, sizeof(filename), "%s.xbm", b->name); - alt_filename[0] = '\0'; - if (b->alt_name) { - snprintf(alt_filename, sizeof(alt_filename), "%s.xbm", b->alt_name); - } if (!*b->active.buffer) { - button_xbm_load(filename, alt_filename, b->active.buffer, - b->fallback_button, b->active.rgba); + button_xbm_load(filename, b->active.buffer, b->active.rgba); } if (!*b->inactive.buffer) { - button_xbm_load(filename, alt_filename, b->inactive.buffer, - b->fallback_button, b->inactive.rgba); + button_xbm_load(filename, b->inactive.buffer, b->inactive.rgba); + } + + /* + * XBM (alternative name) + * For example max_hover_toggled instead of max_toggled_hover + */ + if (b->alt_name) { + snprintf(filename, sizeof(filename), "%s.xbm", b->name); + } else { + filename[0] = '\0'; + } + if (!*b->active.buffer) { + button_xbm_load(filename, b->active.buffer, b->active.rgba); + } + if (!*b->inactive.buffer) { + button_xbm_load(filename, b->inactive.buffer, b->inactive.rgba); + } + + /* + * Builtin bitmap + * + * Applicable to basic buttons such as max, max_toggled and + * iconify. There are no bitmap fallbacks for *_hover icons. + */ + if (!b->fallback_button) { + continue; + } + if (!*b->active.buffer) { + button_xbm_from_bitmap(b->fallback_button, + b->active.buffer, b->active.rgba); + } + if (!*b->inactive.buffer) { + button_xbm_from_bitmap(b->fallback_button, + b->inactive.buffer, b->inactive.rgba); } }