]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Support hover icons in titlebar (#1280)
authorSimon Long <simon@raspberrypi.com>
Wed, 6 Dec 2023 20:33:26 +0000 (20:33 +0000)
committerGitHub <noreply@github.com>
Wed, 6 Dec 2023 20:33:26 +0000 (20:33 +0000)
Allow both max_toggled_hover and max_hover_toggled names for icons

docs/labwc-theme.5.scd
include/button/button-xbm.h
include/ssd-internal.h
include/theme.h
src/button/button-xbm.c
src/ssd/ssd_part.c
src/ssd/ssd_titlebar.c
src/theme.c

index 73be8d27cac3b1219ad58a6a927dbef3ddb89fbb..efd0725911119d0fbae04b3e59a41c8e43c0f464 100644 (file)
@@ -197,6 +197,16 @@ file within a particular theme. The following xbm buttons are supported:
 - iconify.xbm
 - close.xbm
 - menu.xbm
+- max_toggled.xbm
+
+Additional icons can be defined to be shown when the mouse pointer is hovering
+over the button in question:
+
+- max_hover.xbm
+- iconify_hover.xbm
+- close_hover.xbm
+- menu_hover.xbm
+- max_hover_toggled.xbm
 
 One advantage of xbm buttons over other formats is that they change color based
 on the theme. Other formats use the suffices "-active" and "-inactive" to align
index 862a926d83a896026d1c05b26571838337d7c2d6..8b864bd03a155a7ad69b73a37ed583154de56cdb 100644 (file)
@@ -5,7 +5,7 @@
 struct lab_data_buffer;
 
 /* button_xbm_load - Convert xbm file to buffer with cairo surface */
-void button_xbm_load(const char *button_name, struct lab_data_buffer **buffer,
-       char *fallback_button, float *rgba);
+void button_xbm_load(const char *button_name, const char *alt_name,
+       struct lab_data_buffer **buffer, char *fallback_button, float *rgba);
 
 #endif /* LABWC_BUTTON_XBM_H */
index e52ae49d772459f5f4add8a0699f706dfe6daf6c..bfc11018155ff54594821a6a323267561a25dc04 100644 (file)
@@ -5,6 +5,7 @@
 #include <wlr/util/box.h>
 #include "common/macros.h"
 #include "ssd.h"
+#include "view.h"
 
 #define FOR_EACH(tmp, ...) \
 { \
 struct ssd_button {
        struct view *view;
        enum ssd_part_type type;
+       struct wlr_scene_node *normal;
        struct wlr_scene_node *hover;
+       struct wlr_scene_node *toggled;
+       struct wlr_scene_node *toggled_hover;
        struct wlr_scene_node *background;
 
        struct wl_listener destroy;
@@ -96,6 +100,8 @@ struct ssd_part {
 struct ssd_hover_state {
        struct view *view;
        struct wlr_scene_node *node;
+       struct wlr_scene_node *old_node;
+       int maximized;
 };
 
 struct wlr_buffer;
@@ -115,12 +121,16 @@ struct ssd_part *add_scene_buffer(
 struct ssd_part *add_scene_button(
        struct wl_list *part_list, enum ssd_part_type type,
        struct wlr_scene_tree *parent, float *bg_color,
-       struct wlr_buffer *icon_buffer, int x, struct view *view);
+       struct wlr_buffer *icon_buffer, struct wlr_buffer *hover_buffer,
+       int x, struct view *view);
+void
+add_toggled_icon(struct wl_list *part_list, enum ssd_part_type type,
+               struct wlr_buffer *icon_buffer, struct wlr_buffer *hover_buffer);
 struct ssd_part *add_scene_button_corner(
        struct wl_list *part_list, enum ssd_part_type type,
        enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
        struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer,
-       int x, struct view *view);
+       struct wlr_buffer *hover_buffer, int x, struct view *view);
 
 /* SSD internal helpers */
 struct ssd_part *ssd_get_part(
index e211d0f047f87ee686f91de918cd88ecf9973ef3..e814f45140b19400b449196b5b205c6b60737380 100644 (file)
@@ -79,14 +79,28 @@ struct theme {
        /* textures */
        struct lab_data_buffer *button_close_active_unpressed;
        struct lab_data_buffer *button_maximize_active_unpressed;
+       struct lab_data_buffer *button_restore_active_unpressed;
        struct lab_data_buffer *button_iconify_active_unpressed;
        struct lab_data_buffer *button_menu_active_unpressed;
 
        struct lab_data_buffer *button_close_inactive_unpressed;
        struct lab_data_buffer *button_maximize_inactive_unpressed;
+       struct lab_data_buffer *button_restore_inactive_unpressed;
        struct lab_data_buffer *button_iconify_inactive_unpressed;
        struct lab_data_buffer *button_menu_inactive_unpressed;
 
+       struct lab_data_buffer *button_close_active_hover;
+       struct lab_data_buffer *button_maximize_active_hover;
+       struct lab_data_buffer *button_restore_active_hover;
+       struct lab_data_buffer *button_iconify_active_hover;
+       struct lab_data_buffer *button_menu_active_hover;
+
+       struct lab_data_buffer *button_close_inactive_hover;
+       struct lab_data_buffer *button_maximize_inactive_hover;
+       struct lab_data_buffer *button_restore_inactive_hover;
+       struct lab_data_buffer *button_iconify_inactive_hover;
+       struct lab_data_buffer *button_menu_inactive_hover;
+
        struct lab_data_buffer *corner_top_left_active_normal;
        struct lab_data_buffer *corner_top_right_active_normal;
        struct lab_data_buffer *corner_top_left_inactive_normal;
index 9d5583323ee3b98728f040d7aa4951c60a87fe72..6435d65499531308136af4d513cb1bc8e45945d2 100644 (file)
@@ -259,8 +259,8 @@ parse_xbm_builtin(const char *button, int size)
 }
 
 void
-button_xbm_load(const char *button_name, struct lab_data_buffer **buffer,
-               char *fallback_button, float *rgba)
+button_xbm_load(const char *button_name, const char *alt_name,
+       struct lab_data_buffer **buffer, char *fallback_button, float *rgba)
 {
        struct pixmap pixmap = {0};
        if (*buffer) {
@@ -282,6 +282,18 @@ button_xbm_load(const char *button_name, struct lab_data_buffer **buffer,
                        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) {
                pixmap = parse_xbm_builtin(fallback_button, 6);
        }
index 4c72d291743d9a85e72cd7c882d54bdc74d4a6e3..ea53c10410578ac1bc4e2645f99238d76667ef8f 100644 (file)
@@ -82,7 +82,7 @@ struct ssd_part *
 add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type,
                enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
                struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer,
-               int x, struct view *view)
+               struct wlr_buffer *hover_buffer, int x, struct view *view)
 {
        int offset_x;
        float invisible[4] = { 0, 0, 0, 0 };
@@ -108,7 +108,7 @@ add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type,
                -offset_x, -rc.theme->border_width);
 
        /* Finally just put a usual theme button on top, using an invisible hitbox */
-       add_scene_button(part_list, type, parent, invisible, icon_buffer, 0, view);
+       add_scene_button(part_list, type, parent, invisible, icon_buffer, hover_buffer, 0, view);
        return button_root;
 }
 
@@ -141,11 +141,9 @@ get_scale_box(struct wlr_buffer *buffer, double container_width,
 struct ssd_part *
 add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
                struct wlr_scene_tree *parent, float *bg_color,
-               struct wlr_buffer *icon_buffer, int x, struct view *view)
+               struct wlr_buffer *icon_buffer, struct wlr_buffer *hover_buffer,
+               int x, struct view *view)
 {
-       struct wlr_scene_node *hover;
-       float hover_bg[4] = {0.15f, 0.15f, 0.15f, 0.3f};
-
        struct ssd_part *button_root = add_scene_part(part_list, type);
        parent = wlr_scene_tree_create(parent);
        button_root->node = &parent->node;
@@ -166,19 +164,66 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
                wlr_scene_buffer_from_node(icon_part->node),
                icon_geo.width, icon_geo.height);
 
-       /* Hover overlay */
-       hover = add_scene_rect(part_list, type, parent, SSD_BUTTON_WIDTH,
-               rc.theme->title_height, 0, 0, hover_bg)->node;
-       wlr_scene_node_set_enabled(hover, false);
+       /* Hover icon */
+       struct wlr_box hover_geo = get_scale_box(hover_buffer,
+               SSD_BUTTON_WIDTH, rc.theme->title_height);
+       struct ssd_part *hover_part = add_scene_buffer(part_list, type,
+               parent, hover_buffer, hover_geo.x, hover_geo.y);
+
+       /* Make sure big icons are scaled down if necessary */
+       wlr_scene_buffer_set_dest_size(
+               wlr_scene_buffer_from_node(hover_part->node),
+               hover_geo.width, hover_geo.height);
+
+       wlr_scene_node_set_enabled(hover_part->node, false);
 
        struct ssd_button *button = ssd_button_descriptor_create(button_root->node);
        button->type = type;
        button->view = view;
-       button->hover = hover;
+       button->normal = icon_part->node;
+       button->hover = hover_part->node;
        button->background = bg_rect->node;
+       button->toggled = NULL;
+       button->toggled_hover = NULL;
        return button_root;
 }
 
+void
+add_toggled_icon(struct wl_list *part_list, enum ssd_part_type type,
+               struct wlr_buffer *icon_buffer, struct wlr_buffer *hover_buffer)
+{
+       struct ssd_part *part = ssd_get_part(part_list, type);
+       struct ssd_button *button = node_ssd_button_from_node(part->node);
+       struct wlr_scene_tree *parent = wlr_scene_tree_from_node(part->node);
+
+       /* Alternate icon */
+       struct wlr_box icon_geo = get_scale_box(icon_buffer,
+               SSD_BUTTON_WIDTH, rc.theme->title_height);
+
+       struct ssd_part *alticon_part = add_scene_buffer(part_list, type,
+               parent, icon_buffer, icon_geo.x, icon_geo.y);
+
+       wlr_scene_buffer_set_dest_size(
+               wlr_scene_buffer_from_node(alticon_part->node),
+               icon_geo.width, icon_geo.height);
+
+       wlr_scene_node_set_enabled(alticon_part->node, false);
+
+       struct wlr_box hover_geo = get_scale_box(hover_buffer,
+               SSD_BUTTON_WIDTH, rc.theme->title_height);
+       struct ssd_part *althover_part = add_scene_buffer(part_list, type,
+               parent, hover_buffer, hover_geo.x, hover_geo.y);
+
+       wlr_scene_buffer_set_dest_size(
+               wlr_scene_buffer_from_node(althover_part->node),
+               hover_geo.width, hover_geo.height);
+
+       wlr_scene_node_set_enabled(althover_part->node, false);
+
+       button->toggled = alticon_part->node;
+       button->toggled_hover = althover_part->node;
+}
+
 struct ssd_part *
 ssd_get_part(struct wl_list *part_list, enum ssd_part_type type)
 {
index 55cfe51b1ca65a71a41dc33e47d0730fd81d134e..7b2ef2f3a70216fb424e3fb13cb834bc40ffcfcf 100644 (file)
@@ -34,8 +34,15 @@ ssd_titlebar_create(struct ssd *ssd)
        struct wlr_buffer *menu_button_unpressed;
        struct wlr_buffer *iconify_button_unpressed;
        struct wlr_buffer *maximize_button_unpressed;
+       struct wlr_buffer *restore_button_unpressed;
        struct wlr_buffer *close_button_unpressed;
 
+       struct wlr_buffer *menu_button_hover;
+       struct wlr_buffer *iconify_button_hover;
+       struct wlr_buffer *maximize_button_hover;
+       struct wlr_buffer *restore_button_hover;
+       struct wlr_buffer *close_button_hover;
+
        ssd->titlebar.tree = wlr_scene_tree_create(ssd->tree);
 
        struct ssd_sub_tree *subtree;
@@ -51,6 +58,12 @@ ssd_titlebar_create(struct ssd *ssd)
                        iconify_button_unpressed = &theme->button_iconify_active_unpressed->base;
                        close_button_unpressed = &theme->button_close_active_unpressed->base;
                        maximize_button_unpressed = &theme->button_maximize_active_unpressed->base;
+                       restore_button_unpressed = &theme->button_restore_active_unpressed->base;
+                       menu_button_hover = &theme->button_menu_active_hover->base;
+                       iconify_button_hover = &theme->button_iconify_active_hover->base;
+                       close_button_hover = &theme->button_close_active_hover->base;
+                       maximize_button_hover = &theme->button_maximize_active_hover->base;
+                       restore_button_hover = &theme->button_restore_active_hover->base;
                } else {
                        color = theme->window_inactive_title_bg_color;
                        corner_top_left = &theme->corner_top_left_inactive_normal->base;
@@ -59,7 +72,13 @@ ssd_titlebar_create(struct ssd *ssd)
                        iconify_button_unpressed = &theme->button_iconify_inactive_unpressed->base;
                        maximize_button_unpressed =
                                &theme->button_maximize_inactive_unpressed->base;
+                       restore_button_unpressed = &theme->button_restore_inactive_unpressed->base;
                        close_button_unpressed = &theme->button_close_inactive_unpressed->base;
+                       menu_button_hover = &theme->button_menu_inactive_hover->base;
+                       iconify_button_hover = &theme->button_iconify_inactive_hover->base;
+                       close_button_hover = &theme->button_close_inactive_hover->base;
+                       maximize_button_hover = &theme->button_maximize_inactive_hover->base;
+                       restore_button_hover = &theme->button_restore_inactive_hover->base;
                        wlr_scene_node_set_enabled(&parent->node, false);
                }
                wl_list_init(&subtree->parts);
@@ -71,16 +90,18 @@ ssd_titlebar_create(struct ssd *ssd)
                /* Buttons */
                add_scene_button_corner(&subtree->parts,
                        LAB_SSD_BUTTON_WINDOW_MENU, LAB_SSD_PART_CORNER_TOP_LEFT, parent,
-                       corner_top_left, menu_button_unpressed, 0, view);
+                       corner_top_left, menu_button_unpressed, menu_button_hover, 0, view);
                add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent,
-                       color, iconify_button_unpressed,
+                       color, iconify_button_unpressed, iconify_button_hover,
                        width - SSD_BUTTON_WIDTH * 3, view);
                add_scene_button(&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent,
-                       color, maximize_button_unpressed,
+                       color, maximize_button_unpressed, maximize_button_hover,
                        width - SSD_BUTTON_WIDTH * 2, view);
+               add_toggled_icon(&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE,
+                       restore_button_unpressed, restore_button_hover);
                add_scene_button_corner(&subtree->parts,
                        LAB_SSD_BUTTON_CLOSE, LAB_SSD_PART_CORNER_TOP_RIGHT, parent,
-                       corner_top_right, close_button_unpressed,
+                       corner_top_right, close_button_unpressed, close_button_hover,
                        width - SSD_BUTTON_WIDTH * 1, view);
        } FOR_EACH_END
 
@@ -159,10 +180,22 @@ ssd_titlebar_update(struct ssd *ssd)
                                                width - SSD_BUTTON_WIDTH * 3, 0);
                                }
                                continue;
-                       case  LAB_SSD_BUTTON_MAXIMIZE:
+                       case LAB_SSD_BUTTON_MAXIMIZE:
                                if (is_direct_child(part->node, subtree)) {
                                        wlr_scene_node_set_position(part->node,
                                                width - SSD_BUTTON_WIDTH * 2, 0);
+                                       struct ssd_button *button =
+                                               node_ssd_button_from_node(part->node);
+                                       if (button->toggled) {
+                                               wlr_scene_node_set_enabled(button->normal,
+                                                       !maximized);
+                                               wlr_scene_node_set_enabled(button->toggled,
+                                                       maximized);
+                                               wlr_scene_node_set_enabled(button->hover,
+                                                       false);
+                                               wlr_scene_node_set_enabled(button->toggled_hover,
+                                                       false);
+                                       }
                                }
                                continue;
                        case LAB_SSD_PART_CORNER_TOP_RIGHT:
@@ -365,13 +398,24 @@ ssd_update_button_hover(struct wlr_scene_node *node,
 disable_old_hover:
        if (hover_state->node) {
                wlr_scene_node_set_enabled(hover_state->node, false);
+               if (hover_state->maximized == (int)hover_state->view->maximized
+                       || hover_state->maximized == -1) {
+                       wlr_scene_node_set_enabled(hover_state->old_node, true);
+               }
                hover_state->view = NULL;
                hover_state->node = NULL;
        }
        if (button) {
-               wlr_scene_node_set_enabled(button->hover, true);
+               bool maximized = button->view->maximized;
+               if (maximized && !button->toggled) {
+                       maximized = false;
+               }
+               wlr_scene_node_set_enabled(maximized ? button->toggled_hover : button->hover, true);
                hover_state->view = button->view;
-               hover_state->node = button->hover;
+               hover_state->node = maximized ? button->toggled_hover : button->hover;
+               hover_state->old_node = maximized ? button->toggled : button->normal;
+               hover_state->maximized = button->toggled ? (int)button->view->maximized : -1;
+               wlr_scene_node_set_enabled(maximized ? button->toggled : button->normal, false);
        }
 }
 
index 8c9c6cad0d55835edffe7c8e66f292fafdd160c8..1df54389232933f80a19fae8a6f17b082be49910 100644 (file)
@@ -39,6 +39,7 @@
 
 struct button {
        const char *name;
+       const char *alt_name;
        char fallback_button[6];        /* built-in 6x6 button */
        struct {
                struct lab_data_buffer **buffer;
@@ -60,7 +61,7 @@ load_buttons(struct theme *theme)
 {
        struct button buttons[] = {
                {
-                       "menu",
+                       "menu", NULL,
                        { 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00 },
                        {
                                &theme->button_menu_active_unpressed,
@@ -72,7 +73,7 @@ load_buttons(struct theme *theme)
                        },
                },
                {
-                       "iconify",
+                       "iconify", NULL,
                        { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f },
                        {
                                &theme->button_iconify_active_unpressed,
@@ -84,7 +85,7 @@ load_buttons(struct theme *theme)
                        },
                },
                {
-                       "max",
+                       "max", NULL,
                        { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f },
                        {
                                &theme->button_maximize_active_unpressed,
@@ -96,7 +97,19 @@ load_buttons(struct theme *theme)
                        },
                },
                {
-                       "close",
+                       "max_toggled", NULL,
+                       { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f },
+                       {
+                               &theme->button_restore_active_unpressed,
+                               theme->window_active_button_max_unpressed_image_color,
+                       },
+                       {
+                               &theme->button_restore_inactive_unpressed,
+                               theme->window_inactive_button_max_unpressed_image_color,
+                       },
+               },
+               {
+                       "close", NULL,
                        { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 },
                        {
                                &theme->button_close_active_unpressed,
@@ -107,9 +120,70 @@ load_buttons(struct theme *theme)
                                theme->window_inactive_button_close_unpressed_image_color,
                        },
                },
+               {
+                       "menu_hover", NULL,
+                       { 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00 },
+                       {
+                               &theme->button_menu_active_hover,
+                               theme->window_active_button_menu_unpressed_image_color,
+                       },
+                       {
+                               &theme->button_menu_inactive_hover,
+                               theme->window_inactive_button_menu_unpressed_image_color,
+                       },
+               },
+               {
+                       "iconify_hover", NULL,
+                       { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f },
+                       {
+                               &theme->button_iconify_active_hover,
+                               theme->window_active_button_iconify_unpressed_image_color,
+                       },
+                       {
+                               &theme->button_iconify_inactive_hover,
+                               theme->window_inactive_button_iconify_unpressed_image_color,
+                       },
+               },
+               {
+                       "max_hover", NULL,
+                       { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f },
+                       {
+                               &theme->button_maximize_active_hover,
+                               theme->window_active_button_max_unpressed_image_color,
+                       },
+                       {
+                               &theme->button_maximize_inactive_hover,
+                               theme->window_inactive_button_max_unpressed_image_color,
+                       },
+               },
+               {
+                       "max_hover_toggled", "max_toggled_hover",
+                       { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f },
+                       {
+                               &theme->button_restore_active_hover,
+                               theme->window_active_button_max_unpressed_image_color,
+                       },
+                       {
+                               &theme->button_restore_inactive_hover,
+                               theme->window_inactive_button_max_unpressed_image_color,
+                       },
+               },
+               {
+                       "close_hover", NULL,
+                       { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 },
+                       {
+                               &theme->button_close_active_hover,
+                               theme->window_active_button_close_unpressed_image_color,
+                       },
+                       {
+                               &theme->button_close_inactive_hover,
+                               theme->window_inactive_button_close_unpressed_image_color,
+                       },
+               },
        };
 
        char filename[4096] = {0};
+       char alt_filename[4096] = {0};
        for (size_t i = 0; i < ARRAY_SIZE(buttons); ++i) {
                struct button *b = &buttons[i];
 
@@ -119,8 +193,16 @@ load_buttons(struct theme *theme)
                /* Try png icon first */
                snprintf(filename, sizeof(filename), "%s-active.png", b->name);
                button_png_load(filename, b->active.buffer);
+               if (!*b->active.buffer && b->alt_name) {
+                       snprintf(filename, sizeof(filename), "%s-active.png", b->alt_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 (!*b->inactive.buffer && b->alt_name) {
+                       snprintf(filename, sizeof(filename), "%s-inactive.png", b->alt_name);
+                       button_png_load(filename, b->inactive.buffer);
+               }
 
 #if HAVE_RSVG
                /* Then try svg icon */
@@ -129,20 +211,31 @@ load_buttons(struct theme *theme)
                        snprintf(filename, sizeof(filename), "%s-active.svg", b->name);
                        button_svg_load(filename, b->active.buffer, size);
                }
+               if (!*b->active.buffer && b->alt_name) {
+                       snprintf(filename, sizeof(filename), "%s-active.svg", b->alt_name);
+                       button_svg_load(filename, b->active.buffer, size);
+               }
                if (!*b->inactive.buffer) {
                        snprintf(filename, sizeof(filename), "%s-inactive.svg", b->name);
                        button_svg_load(filename, b->inactive.buffer, size);
                }
+               if (!*b->active.buffer && b->alt_name) {
+                       snprintf(filename, sizeof(filename), "%s-inactive.svg", b->alt_name);
+                       button_svg_load(filename, b->inactive.buffer, size);
+               }
 #endif
 
                /* If there were no png/svg buttons, use xbm */
                snprintf(filename, sizeof(filename), "%s.xbm", b->name);
+               if (b->alt_name) {
+                       snprintf(alt_filename, sizeof(alt_filename), "%s.xbm", b->alt_name);
+               }
                if (!*b->active.buffer) {
-                       button_xbm_load(filename, b->active.buffer,
+                       button_xbm_load(filename, alt_filename, b->active.buffer,
                                b->fallback_button, b->active.rgba);
                }
                if (!*b->inactive.buffer) {
-                       button_xbm_load(filename, b->inactive.buffer,
+                       button_xbm_load(filename, alt_filename, b->inactive.buffer,
                                b->fallback_button, b->inactive.rgba);
                }
        }