mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	Support hover icons in titlebar (#1280)
Allow both max_toggled_hover and max_hover_toggled names for icons
This commit is contained in:
		
							parent
							
								
									5d2f594626
								
							
						
					
					
						commit
						c79b8ba8a7
					
				
					 8 changed files with 258 additions and 30 deletions
				
			
		| 
						 | 
					@ -197,6 +197,16 @@ file within a particular theme. The following xbm buttons are supported:
 | 
				
			||||||
- iconify.xbm
 | 
					- iconify.xbm
 | 
				
			||||||
- close.xbm
 | 
					- close.xbm
 | 
				
			||||||
- menu.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
 | 
					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
 | 
					on the theme. Other formats use the suffices "-active" and "-inactive" to align
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@
 | 
				
			||||||
struct lab_data_buffer;
 | 
					struct lab_data_buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* button_xbm_load - Convert xbm file to buffer with cairo surface */
 | 
					/* button_xbm_load - Convert xbm file to buffer with cairo surface */
 | 
				
			||||||
void button_xbm_load(const char *button_name, struct lab_data_buffer **buffer,
 | 
					void button_xbm_load(const char *button_name, const char *alt_name,
 | 
				
			||||||
	char *fallback_button, float *rgba);
 | 
						struct lab_data_buffer **buffer, char *fallback_button, float *rgba);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* LABWC_BUTTON_XBM_H */
 | 
					#endif /* LABWC_BUTTON_XBM_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@
 | 
				
			||||||
#include <wlr/util/box.h>
 | 
					#include <wlr/util/box.h>
 | 
				
			||||||
#include "common/macros.h"
 | 
					#include "common/macros.h"
 | 
				
			||||||
#include "ssd.h"
 | 
					#include "ssd.h"
 | 
				
			||||||
 | 
					#include "view.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FOR_EACH(tmp, ...) \
 | 
					#define FOR_EACH(tmp, ...) \
 | 
				
			||||||
{ \
 | 
					{ \
 | 
				
			||||||
| 
						 | 
					@ -17,7 +18,10 @@
 | 
				
			||||||
struct ssd_button {
 | 
					struct ssd_button {
 | 
				
			||||||
	struct view *view;
 | 
						struct view *view;
 | 
				
			||||||
	enum ssd_part_type type;
 | 
						enum ssd_part_type type;
 | 
				
			||||||
 | 
						struct wlr_scene_node *normal;
 | 
				
			||||||
	struct wlr_scene_node *hover;
 | 
						struct wlr_scene_node *hover;
 | 
				
			||||||
 | 
						struct wlr_scene_node *toggled;
 | 
				
			||||||
 | 
						struct wlr_scene_node *toggled_hover;
 | 
				
			||||||
	struct wlr_scene_node *background;
 | 
						struct wlr_scene_node *background;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_listener destroy;
 | 
						struct wl_listener destroy;
 | 
				
			||||||
| 
						 | 
					@ -96,6 +100,8 @@ struct ssd_part {
 | 
				
			||||||
struct ssd_hover_state {
 | 
					struct ssd_hover_state {
 | 
				
			||||||
	struct view *view;
 | 
						struct view *view;
 | 
				
			||||||
	struct wlr_scene_node *node;
 | 
						struct wlr_scene_node *node;
 | 
				
			||||||
 | 
						struct wlr_scene_node *old_node;
 | 
				
			||||||
 | 
						int maximized;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_buffer;
 | 
					struct wlr_buffer;
 | 
				
			||||||
| 
						 | 
					@ -115,12 +121,16 @@ struct ssd_part *add_scene_buffer(
 | 
				
			||||||
struct ssd_part *add_scene_button(
 | 
					struct ssd_part *add_scene_button(
 | 
				
			||||||
	struct wl_list *part_list, enum ssd_part_type type,
 | 
						struct wl_list *part_list, enum ssd_part_type type,
 | 
				
			||||||
	struct wlr_scene_tree *parent, float *bg_color,
 | 
						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 ssd_part *add_scene_button_corner(
 | 
				
			||||||
	struct wl_list *part_list, enum ssd_part_type type,
 | 
						struct wl_list *part_list, enum ssd_part_type type,
 | 
				
			||||||
	enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
 | 
						enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
 | 
				
			||||||
	struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer,
 | 
						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 */
 | 
					/* SSD internal helpers */
 | 
				
			||||||
struct ssd_part *ssd_get_part(
 | 
					struct ssd_part *ssd_get_part(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,14 +79,28 @@ struct theme {
 | 
				
			||||||
	/* textures */
 | 
						/* textures */
 | 
				
			||||||
	struct lab_data_buffer *button_close_active_unpressed;
 | 
						struct lab_data_buffer *button_close_active_unpressed;
 | 
				
			||||||
	struct lab_data_buffer *button_maximize_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_iconify_active_unpressed;
 | 
				
			||||||
	struct lab_data_buffer *button_menu_active_unpressed;
 | 
						struct lab_data_buffer *button_menu_active_unpressed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct lab_data_buffer *button_close_inactive_unpressed;
 | 
						struct lab_data_buffer *button_close_inactive_unpressed;
 | 
				
			||||||
	struct lab_data_buffer *button_maximize_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_iconify_inactive_unpressed;
 | 
				
			||||||
	struct lab_data_buffer *button_menu_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_left_active_normal;
 | 
				
			||||||
	struct lab_data_buffer *corner_top_right_active_normal;
 | 
						struct lab_data_buffer *corner_top_right_active_normal;
 | 
				
			||||||
	struct lab_data_buffer *corner_top_left_inactive_normal;
 | 
						struct lab_data_buffer *corner_top_left_inactive_normal;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,8 +259,8 @@ parse_xbm_builtin(const char *button, int size)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
button_xbm_load(const char *button_name, struct lab_data_buffer **buffer,
 | 
					button_xbm_load(const char *button_name, const char *alt_name,
 | 
				
			||||||
		char *fallback_button, float *rgba)
 | 
						struct lab_data_buffer **buffer, char *fallback_button, float *rgba)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pixmap pixmap = {0};
 | 
						struct pixmap pixmap = {0};
 | 
				
			||||||
	if (*buffer) {
 | 
						if (*buffer) {
 | 
				
			||||||
| 
						 | 
					@ -282,6 +282,18 @@ button_xbm_load(const char *button_name, struct lab_data_buffer **buffer,
 | 
				
			||||||
			free(tokens);
 | 
								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) {
 | 
						if (!pixmap.data) {
 | 
				
			||||||
		pixmap = parse_xbm_builtin(fallback_button, 6);
 | 
							pixmap = parse_xbm_builtin(fallback_button, 6);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ struct ssd_part *
 | 
				
			||||||
add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type,
 | 
					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,
 | 
							enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
 | 
				
			||||||
		struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer,
 | 
							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;
 | 
						int offset_x;
 | 
				
			||||||
	float invisible[4] = { 0, 0, 0, 0 };
 | 
						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);
 | 
							-offset_x, -rc.theme->border_width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Finally just put a usual theme button on top, using an invisible hitbox */
 | 
						/* 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;
 | 
						return button_root;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,11 +141,9 @@ get_scale_box(struct wlr_buffer *buffer, double container_width,
 | 
				
			||||||
struct ssd_part *
 | 
					struct ssd_part *
 | 
				
			||||||
add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
 | 
					add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
 | 
				
			||||||
		struct wlr_scene_tree *parent, float *bg_color,
 | 
							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);
 | 
						struct ssd_part *button_root = add_scene_part(part_list, type);
 | 
				
			||||||
	parent = wlr_scene_tree_create(parent);
 | 
						parent = wlr_scene_tree_create(parent);
 | 
				
			||||||
	button_root->node = &parent->node;
 | 
						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),
 | 
							wlr_scene_buffer_from_node(icon_part->node),
 | 
				
			||||||
		icon_geo.width, icon_geo.height);
 | 
							icon_geo.width, icon_geo.height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Hover overlay */
 | 
						/* Hover icon */
 | 
				
			||||||
	hover = add_scene_rect(part_list, type, parent, SSD_BUTTON_WIDTH,
 | 
						struct wlr_box hover_geo = get_scale_box(hover_buffer,
 | 
				
			||||||
		rc.theme->title_height, 0, 0, hover_bg)->node;
 | 
							SSD_BUTTON_WIDTH, rc.theme->title_height);
 | 
				
			||||||
	wlr_scene_node_set_enabled(hover, false);
 | 
						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);
 | 
						struct ssd_button *button = ssd_button_descriptor_create(button_root->node);
 | 
				
			||||||
	button->type = type;
 | 
						button->type = type;
 | 
				
			||||||
	button->view = view;
 | 
						button->view = view;
 | 
				
			||||||
	button->hover = hover;
 | 
						button->normal = icon_part->node;
 | 
				
			||||||
 | 
						button->hover = hover_part->node;
 | 
				
			||||||
	button->background = bg_rect->node;
 | 
						button->background = bg_rect->node;
 | 
				
			||||||
 | 
						button->toggled = NULL;
 | 
				
			||||||
 | 
						button->toggled_hover = NULL;
 | 
				
			||||||
	return button_root;
 | 
						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 *
 | 
					struct ssd_part *
 | 
				
			||||||
ssd_get_part(struct wl_list *part_list, enum ssd_part_type type)
 | 
					ssd_get_part(struct wl_list *part_list, enum ssd_part_type type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,8 +34,15 @@ ssd_titlebar_create(struct ssd *ssd)
 | 
				
			||||||
	struct wlr_buffer *menu_button_unpressed;
 | 
						struct wlr_buffer *menu_button_unpressed;
 | 
				
			||||||
	struct wlr_buffer *iconify_button_unpressed;
 | 
						struct wlr_buffer *iconify_button_unpressed;
 | 
				
			||||||
	struct wlr_buffer *maximize_button_unpressed;
 | 
						struct wlr_buffer *maximize_button_unpressed;
 | 
				
			||||||
 | 
						struct wlr_buffer *restore_button_unpressed;
 | 
				
			||||||
	struct wlr_buffer *close_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);
 | 
						ssd->titlebar.tree = wlr_scene_tree_create(ssd->tree);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct ssd_sub_tree *subtree;
 | 
						struct ssd_sub_tree *subtree;
 | 
				
			||||||
| 
						 | 
					@ -51,6 +58,12 @@ ssd_titlebar_create(struct ssd *ssd)
 | 
				
			||||||
			iconify_button_unpressed = &theme->button_iconify_active_unpressed->base;
 | 
								iconify_button_unpressed = &theme->button_iconify_active_unpressed->base;
 | 
				
			||||||
			close_button_unpressed = &theme->button_close_active_unpressed->base;
 | 
								close_button_unpressed = &theme->button_close_active_unpressed->base;
 | 
				
			||||||
			maximize_button_unpressed = &theme->button_maximize_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 {
 | 
							} else {
 | 
				
			||||||
			color = theme->window_inactive_title_bg_color;
 | 
								color = theme->window_inactive_title_bg_color;
 | 
				
			||||||
			corner_top_left = &theme->corner_top_left_inactive_normal->base;
 | 
								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;
 | 
								iconify_button_unpressed = &theme->button_iconify_inactive_unpressed->base;
 | 
				
			||||||
			maximize_button_unpressed =
 | 
								maximize_button_unpressed =
 | 
				
			||||||
				&theme->button_maximize_inactive_unpressed->base;
 | 
									&theme->button_maximize_inactive_unpressed->base;
 | 
				
			||||||
 | 
								restore_button_unpressed = &theme->button_restore_inactive_unpressed->base;
 | 
				
			||||||
			close_button_unpressed = &theme->button_close_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);
 | 
								wlr_scene_node_set_enabled(&parent->node, false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		wl_list_init(&subtree->parts);
 | 
							wl_list_init(&subtree->parts);
 | 
				
			||||||
| 
						 | 
					@ -71,16 +90,18 @@ ssd_titlebar_create(struct ssd *ssd)
 | 
				
			||||||
		/* Buttons */
 | 
							/* Buttons */
 | 
				
			||||||
		add_scene_button_corner(&subtree->parts,
 | 
							add_scene_button_corner(&subtree->parts,
 | 
				
			||||||
			LAB_SSD_BUTTON_WINDOW_MENU, LAB_SSD_PART_CORNER_TOP_LEFT, parent,
 | 
								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,
 | 
							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);
 | 
								width - SSD_BUTTON_WIDTH * 3, view);
 | 
				
			||||||
		add_scene_button(&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent,
 | 
							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);
 | 
								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,
 | 
							add_scene_button_corner(&subtree->parts,
 | 
				
			||||||
			LAB_SSD_BUTTON_CLOSE, LAB_SSD_PART_CORNER_TOP_RIGHT, parent,
 | 
								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);
 | 
								width - SSD_BUTTON_WIDTH * 1, view);
 | 
				
			||||||
	} FOR_EACH_END
 | 
						} FOR_EACH_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,6 +184,18 @@ ssd_titlebar_update(struct ssd *ssd)
 | 
				
			||||||
				if (is_direct_child(part->node, subtree)) {
 | 
									if (is_direct_child(part->node, subtree)) {
 | 
				
			||||||
					wlr_scene_node_set_position(part->node,
 | 
										wlr_scene_node_set_position(part->node,
 | 
				
			||||||
						width - SSD_BUTTON_WIDTH * 2, 0);
 | 
											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;
 | 
									continue;
 | 
				
			||||||
			case LAB_SSD_PART_CORNER_TOP_RIGHT:
 | 
								case LAB_SSD_PART_CORNER_TOP_RIGHT:
 | 
				
			||||||
| 
						 | 
					@ -365,13 +398,24 @@ ssd_update_button_hover(struct wlr_scene_node *node,
 | 
				
			||||||
disable_old_hover:
 | 
					disable_old_hover:
 | 
				
			||||||
	if (hover_state->node) {
 | 
						if (hover_state->node) {
 | 
				
			||||||
		wlr_scene_node_set_enabled(hover_state->node, false);
 | 
							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->view = NULL;
 | 
				
			||||||
		hover_state->node = NULL;
 | 
							hover_state->node = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (button) {
 | 
						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->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);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										105
									
								
								src/theme.c
									
										
									
									
									
								
							
							
						
						
									
										105
									
								
								src/theme.c
									
										
									
									
									
								
							| 
						 | 
					@ -39,6 +39,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct button {
 | 
					struct button {
 | 
				
			||||||
	const char *name;
 | 
						const char *name;
 | 
				
			||||||
 | 
						const char *alt_name;
 | 
				
			||||||
	char fallback_button[6];	/* built-in 6x6 button */
 | 
						char fallback_button[6];	/* built-in 6x6 button */
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		struct lab_data_buffer **buffer;
 | 
							struct lab_data_buffer **buffer;
 | 
				
			||||||
| 
						 | 
					@ -60,7 +61,7 @@ load_buttons(struct theme *theme)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct button buttons[] = {
 | 
						struct button buttons[] = {
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"menu",
 | 
								"menu", NULL,
 | 
				
			||||||
			{ 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00 },
 | 
								{ 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00 },
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				&theme->button_menu_active_unpressed,
 | 
									&theme->button_menu_active_unpressed,
 | 
				
			||||||
| 
						 | 
					@ -72,7 +73,7 @@ load_buttons(struct theme *theme)
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"iconify",
 | 
								"iconify", NULL,
 | 
				
			||||||
			{ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f },
 | 
								{ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f },
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				&theme->button_iconify_active_unpressed,
 | 
									&theme->button_iconify_active_unpressed,
 | 
				
			||||||
| 
						 | 
					@ -84,7 +85,7 @@ load_buttons(struct theme *theme)
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"max",
 | 
								"max", NULL,
 | 
				
			||||||
			{ 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f },
 | 
								{ 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f },
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				&theme->button_maximize_active_unpressed,
 | 
									&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 },
 | 
								{ 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 },
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				&theme->button_close_active_unpressed,
 | 
									&theme->button_close_active_unpressed,
 | 
				
			||||||
| 
						 | 
					@ -107,9 +120,70 @@ load_buttons(struct theme *theme)
 | 
				
			||||||
				theme->window_inactive_button_close_unpressed_image_color,
 | 
									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 filename[4096] = {0};
 | 
				
			||||||
 | 
						char alt_filename[4096] = {0};
 | 
				
			||||||
	for (size_t i = 0; i < ARRAY_SIZE(buttons); ++i) {
 | 
						for (size_t i = 0; i < ARRAY_SIZE(buttons); ++i) {
 | 
				
			||||||
		struct button *b = &buttons[i];
 | 
							struct button *b = &buttons[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,8 +193,16 @@ load_buttons(struct theme *theme)
 | 
				
			||||||
		/* Try png icon first */
 | 
							/* Try png icon first */
 | 
				
			||||||
		snprintf(filename, sizeof(filename), "%s-active.png", b->name);
 | 
							snprintf(filename, sizeof(filename), "%s-active.png", b->name);
 | 
				
			||||||
		button_png_load(filename, b->active.buffer);
 | 
							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);
 | 
							snprintf(filename, sizeof(filename), "%s-inactive.png", b->name);
 | 
				
			||||||
		button_png_load(filename, b->inactive.buffer);
 | 
							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
 | 
					#if HAVE_RSVG
 | 
				
			||||||
		/* Then try svg icon */
 | 
							/* Then try svg icon */
 | 
				
			||||||
| 
						 | 
					@ -129,20 +211,31 @@ load_buttons(struct theme *theme)
 | 
				
			||||||
			snprintf(filename, sizeof(filename), "%s-active.svg", b->name);
 | 
								snprintf(filename, sizeof(filename), "%s-active.svg", b->name);
 | 
				
			||||||
			button_svg_load(filename, b->active.buffer, size);
 | 
								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) {
 | 
							if (!*b->inactive.buffer) {
 | 
				
			||||||
			snprintf(filename, sizeof(filename), "%s-inactive.svg", b->name);
 | 
								snprintf(filename, sizeof(filename), "%s-inactive.svg", b->name);
 | 
				
			||||||
			button_svg_load(filename, b->inactive.buffer, size);
 | 
								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
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* If there were no png/svg buttons, use xbm */
 | 
							/* If there were no png/svg buttons, use xbm */
 | 
				
			||||||
		snprintf(filename, sizeof(filename), "%s.xbm", b->name);
 | 
							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) {
 | 
							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);
 | 
									b->fallback_button, b->active.rgba);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!*b->inactive.buffer) {
 | 
							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);
 | 
									b->fallback_button, b->inactive.rgba);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue