decor: Improve buttons with hover states using focus hack
This commit is contained in:
parent
f44b4c4519
commit
d2cff8331c
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
12
lib/yutani.c
12
lib/yutani.c
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user