decor: Improve buttons with hover states using focus hack

This commit is contained in:
K. Lange 2023-04-26 18:32:33 +09:00
parent f44b4c4519
commit d2cff8331c
5 changed files with 85 additions and 19 deletions

View File

@ -46,6 +46,8 @@ struct decor_bounds {
extern void (*decor_render_decorations)(yutani_window_t *, gfx_context_t *, char *, int);
extern int (*decor_check_button_press)(yutani_window_t *, int x, int y);
extern int (*decor_get_bounds)(yutani_window_t *, struct decor_bounds *);
extern int decor_hover_button;
extern yutani_window_t * decor_hover_window;
/*
* Run me once to set things up
@ -67,6 +69,7 @@ extern yutani_window_t * decor_show_default_menu(yutani_window_t * window, int y
#define DECOR_MAXIMIZE 4
#define DECOR_RIGHT 5
#define DECOR_MINIMIZE 6
#define DECOR_REDRAW 7
#define DECOR_ACTIVE 0
#define DECOR_INACTIVE 1

View File

@ -567,6 +567,7 @@ extern gfx_context_t * init_graphics_yutani(yutani_window_t * window);
extern gfx_context_t * init_graphics_yutani_double_buffer(yutani_window_t * window);
extern void reinit_graphics_yutani(gfx_context_t * out, yutani_window_t * window);
extern void release_graphics_yutani(gfx_context_t * gfx);
extern void yutani_internal_refocus(yutani_t * yctx, yutani_window_t * window);
_End_C_Header

View File

@ -139,6 +139,8 @@ static char * ellipsify(char * input, int font_size, struct TT_Font * font, int
return out;
}
#define BUTTON_PAD 5
static void render_decorations_fancy(yutani_window_t * window, gfx_context_t * ctx, char * title, int decors_active) {
int width = window->width;
int height = window->height;
@ -238,21 +240,39 @@ static void render_decorations_fancy(yutani_window_t * window, gfx_context_t * c
tt_draw_string(ctx, _tt_font, title_offset, (TEXT_OFFSET + 14) * TOTAL_SCALE, title, title_color);
}
uint32_t h_color = rgb(100,100,100);
uint32_t i_color = (decor_hover_window == window && decor_hover_button) ? ACTIVE_COLOR : title_color;
if (width + (BUTTON_OFFSET - 28) * TOTAL_SCALE > bounds.left_width) {
if (decor_hover_window == window && decor_hover_button == DECOR_CLOSE) {
draw_rounded_rectangle(ctx,
width + (BUTTON_OFFSET - 28 - BUTTON_PAD) * TOTAL_SCALE,
(16 - BUTTON_OFFSET - BUTTON_PAD) * TOTAL_SCALE, 8 + BUTTON_PAD * 2, 8 + BUTTON_PAD * 2, 4, h_color);
}
draw_sprite_alpha_paint(ctx, sprites[BUTTON_CLOSE],
width + (BUTTON_OFFSET - 28) * TOTAL_SCALE,
(16 - BUTTON_OFFSET) * TOTAL_SCALE, 1.0, title_color);
(16 - BUTTON_OFFSET) * TOTAL_SCALE, 1.0, i_color);
if (width + (BUTTON_OFFSET - 50) * TOTAL_SCALE > bounds.left_width) {
if (!(window->decorator_flags & DECOR_FLAG_NO_MAXIMIZE)) {
if (decor_hover_window == window && decor_hover_button == DECOR_MAXIMIZE) {
draw_rounded_rectangle(ctx,
width + (BUTTON_OFFSET - 50 - BUTTON_PAD) * TOTAL_SCALE,
(16 - BUTTON_OFFSET - BUTTON_PAD) * TOTAL_SCALE, 8 + BUTTON_PAD * 2, 8 + BUTTON_PAD * 2, 4, h_color);
}
draw_sprite_alpha_paint(ctx, sprites[BUTTON_MAXIMIZE],
width + (BUTTON_OFFSET - 50) * TOTAL_SCALE,
(16 - BUTTON_OFFSET) * TOTAL_SCALE, 1.0, title_color);
(16 - BUTTON_OFFSET) * TOTAL_SCALE, 1.0, i_color);
if (width + (BUTTON_OFFSET - 72) * TOTAL_SCALE > bounds.left_width) {
if (decor_hover_window == window && decor_hover_button == DECOR_MINIMIZE) {
draw_rounded_rectangle(ctx,
width + (BUTTON_OFFSET - 72 - BUTTON_PAD) * TOTAL_SCALE,
(16 - BUTTON_OFFSET - BUTTON_PAD) * TOTAL_SCALE, 8 + BUTTON_PAD * 2, 8 + BUTTON_PAD * 2, 4, h_color);
}
draw_sprite_alpha_paint(ctx, sprites[BUTTON_MINIMIZE],
width + (BUTTON_OFFSET - 72) * TOTAL_SCALE,
(16 - BUTTON_OFFSET) * TOTAL_SCALE, 1.0, title_color);
(16 - BUTTON_OFFSET) * TOTAL_SCALE, 1.0, i_color);
}
}
}
@ -260,23 +280,27 @@ static void render_decorations_fancy(yutani_window_t * window, gfx_context_t * c
}
static int check_button_press_fancy(yutani_window_t * window, int x, int y) {
if (x >= (int)window->width + (BUTTON_OFFSET - 28) * TOTAL_SCALE &&
x <= (int)window->width + (BUTTON_OFFSET - 18) * TOTAL_SCALE &&
y >= 16 * TOTAL_SCALE && y <= 26 * TOTAL_SCALE ) {
return DECOR_CLOSE;
}
if (!(window->decorator_flags & DECOR_FLAG_NO_MAXIMIZE)) {
if (x >= (int)window->width + (BUTTON_OFFSET - 50) * TOTAL_SCALE &&
x <= (int)window->width + (BUTTON_OFFSET - 40) * TOTAL_SCALE &&
y >= 16 * TOTAL_SCALE && y <= 26 * TOTAL_SCALE) {
return DECOR_MAXIMIZE;
if (y >= (16 - BUTTON_OFFSET - BUTTON_PAD) * TOTAL_SCALE && y <= (16 - BUTTON_OFFSET + 8 + BUTTON_PAD) * TOTAL_SCALE ) {
if (x >= (int)window->width + (BUTTON_OFFSET - 28 - BUTTON_PAD) * TOTAL_SCALE &&
x <= (int)window->width + (BUTTON_OFFSET - 28 + 8 + BUTTON_PAD) * TOTAL_SCALE) {
return DECOR_CLOSE;
}
if (x >= (int)window->width + (BUTTON_OFFSET - 72) * TOTAL_SCALE &&
x <= (int)window->width + (BUTTON_OFFSET - 62) * TOTAL_SCALE &&
y >= 16 * TOTAL_SCALE && y <= 26 * TOTAL_SCALE) {
return DECOR_MINIMIZE;
if (!(window->decorator_flags & DECOR_FLAG_NO_MAXIMIZE)) {
if (x >= (int)window->width + (BUTTON_OFFSET - 50 - BUTTON_PAD) * TOTAL_SCALE &&
x <= (int)window->width + (BUTTON_OFFSET - 50 + 8 + BUTTON_PAD) * TOTAL_SCALE) {
return DECOR_MAXIMIZE;
}
if (x >= (int)window->width + (BUTTON_OFFSET - 72 - BUTTON_PAD) * TOTAL_SCALE &&
x <= (int)window->width + (BUTTON_OFFSET - 72 + 8 + BUTTON_PAD) * TOTAL_SCALE) {
return DECOR_MINIMIZE;
}
}
if (x >= (int)window->width + (BUTTON_OFFSET - 72 - BUTTON_PAD) * TOTAL_SCALE &&
x <= (int)window->width + (BUTTON_OFFSET - 28 + 8 + BUTTON_PAD) * TOTAL_SCALE) {
return DECOR_OTHER;
}
}

View File

@ -253,6 +253,8 @@ static yutani_scale_direction_t check_resize_direction(struct yutani_msg_window_
}
static yutani_scale_direction_t old_resize_direction = SCALE_NONE;
int decor_hover_button = 0;
yutani_window_t * decor_hover_window = NULL;
int decor_handle_event(yutani_t * yctx, yutani_msg_t * m) {
if (m) {
@ -265,10 +267,16 @@ int decor_handle_event(yutani_t * yctx, yutani_msg_t * m) {
decor_get_bounds(window, &bounds);
if (!window) return 0;
if (!(window->decorator_flags & DECOR_FLAG_DECORATED)) return 0;
if (me->command == YUTANI_MOUSE_EVENT_LEAVE && decor_hover_window == window) {
decor_hover_window = NULL;
decor_hover_button = 0;
yutani_internal_refocus(yctx, window);
return DECOR_REDRAW;
}
if (within_decors(window, me->new_x, me->new_y)) {
int button = decor_check_button_press(window, me->new_x, me->new_y);
if (me->command == YUTANI_MOUSE_EVENT_DOWN && me->buttons & YUTANI_MOUSE_BUTTON_LEFT) {
if (!button) {
if (!button || button == DECOR_OTHER) {
/* Resize edges */
yutani_scale_direction_t resize_direction = check_resize_direction(me, window);
@ -317,6 +325,9 @@ int decor_handle_event(yutani_t * yctx, yutani_msg_t * m) {
}
old_resize_direction = resize_direction;
}
} else if (old_resize_direction != SCALE_NONE) {
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESET);
old_resize_direction = SCALE_NONE;
}
}
if (me->command == YUTANI_MOUSE_EVENT_CLICK || close_enough(me)) {
@ -337,13 +348,28 @@ int decor_handle_event(yutani_t * yctx, yutani_msg_t * m) {
default:
break;
}
decor_hover_window = NULL;
decor_hover_button = 0;
yutani_internal_refocus(yctx, window);
return button;
}
if (button != decor_hover_button || window != decor_hover_window) {
decor_hover_button = button;
decor_hover_window = window;
yutani_internal_refocus(yctx, window);
return DECOR_REDRAW;
}
} else {
if (old_resize_direction != SCALE_NONE) {
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESET);
old_resize_direction = SCALE_NONE;
}
if (decor_hover_window == window) {
decor_hover_button = 0;
decor_hover_window = NULL;
yutani_internal_refocus(yctx, window);
return DECOR_REDRAW;
}
}
}
break;

View File

@ -1156,3 +1156,15 @@ void release_graphics_yutani(gfx_context_t * gfx) {
}
free(gfx);
}
void yutani_internal_refocus(yutani_t * yctx, yutani_window_t * window) {
/* Check if a refocus is already in our queue to be processed */
foreach(node, yctx->queued) {
yutani_msg_t * out = (yutani_msg_t *)node->value;
if (out->type == YUTANI_MSG_WINDOW_FOCUS_CHANGE) return;
}
/* Otherwise, produce an artificial one matching the reported focus state of the window */
yutani_msg_t * msg = malloc(sizeof(struct yutani_message) + sizeof(struct yutani_msg_window_focus_change));
yutani_msg_buildx_window_focus_change(msg, window->wid, window->focused);
list_insert(yctx->queued, msg);
}