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 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_check_button_press)(yutani_window_t *, int x, int y);
|
||||||
extern int (*decor_get_bounds)(yutani_window_t *, struct decor_bounds *);
|
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
|
* 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_MAXIMIZE 4
|
||||||
#define DECOR_RIGHT 5
|
#define DECOR_RIGHT 5
|
||||||
#define DECOR_MINIMIZE 6
|
#define DECOR_MINIMIZE 6
|
||||||
|
#define DECOR_REDRAW 7
|
||||||
|
|
||||||
#define DECOR_ACTIVE 0
|
#define DECOR_ACTIVE 0
|
||||||
#define DECOR_INACTIVE 1
|
#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 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 reinit_graphics_yutani(gfx_context_t * out, yutani_window_t * window);
|
||||||
extern void release_graphics_yutani(gfx_context_t * gfx);
|
extern void release_graphics_yutani(gfx_context_t * gfx);
|
||||||
|
extern void yutani_internal_refocus(yutani_t * yctx, yutani_window_t * window);
|
||||||
|
|
||||||
_End_C_Header
|
_End_C_Header
|
||||||
|
|
||||||
|
@ -139,6 +139,8 @@ static char * ellipsify(char * input, int font_size, struct TT_Font * font, int
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BUTTON_PAD 5
|
||||||
|
|
||||||
static void render_decorations_fancy(yutani_window_t * window, gfx_context_t * ctx, char * title, int decors_active) {
|
static void render_decorations_fancy(yutani_window_t * window, gfx_context_t * ctx, char * title, int decors_active) {
|
||||||
int width = window->width;
|
int width = window->width;
|
||||||
int height = window->height;
|
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);
|
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 (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],
|
draw_sprite_alpha_paint(ctx, sprites[BUTTON_CLOSE],
|
||||||
width + (BUTTON_OFFSET - 28) * TOTAL_SCALE,
|
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 (width + (BUTTON_OFFSET - 50) * TOTAL_SCALE > bounds.left_width) {
|
||||||
if (!(window->decorator_flags & DECOR_FLAG_NO_MAXIMIZE)) {
|
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],
|
draw_sprite_alpha_paint(ctx, sprites[BUTTON_MAXIMIZE],
|
||||||
width + (BUTTON_OFFSET - 50) * TOTAL_SCALE,
|
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 (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],
|
draw_sprite_alpha_paint(ctx, sprites[BUTTON_MINIMIZE],
|
||||||
width + (BUTTON_OFFSET - 72) * TOTAL_SCALE,
|
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) {
|
static int check_button_press_fancy(yutani_window_t * window, int x, int y) {
|
||||||
if (x >= (int)window->width + (BUTTON_OFFSET - 28) * TOTAL_SCALE &&
|
if (y >= (16 - BUTTON_OFFSET - BUTTON_PAD) * TOTAL_SCALE && y <= (16 - BUTTON_OFFSET + 8 + BUTTON_PAD) * TOTAL_SCALE ) {
|
||||||
x <= (int)window->width + (BUTTON_OFFSET - 18) * TOTAL_SCALE &&
|
if (x >= (int)window->width + (BUTTON_OFFSET - 28 - BUTTON_PAD) * TOTAL_SCALE &&
|
||||||
y >= 16 * TOTAL_SCALE && y <= 26 * TOTAL_SCALE ) {
|
x <= (int)window->width + (BUTTON_OFFSET - 28 + 8 + BUTTON_PAD) * TOTAL_SCALE) {
|
||||||
return DECOR_CLOSE;
|
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 (x >= (int)window->width + (BUTTON_OFFSET - 72) * TOTAL_SCALE &&
|
if (!(window->decorator_flags & DECOR_FLAG_NO_MAXIMIZE)) {
|
||||||
x <= (int)window->width + (BUTTON_OFFSET - 62) * TOTAL_SCALE &&
|
if (x >= (int)window->width + (BUTTON_OFFSET - 50 - BUTTON_PAD) * TOTAL_SCALE &&
|
||||||
y >= 16 * TOTAL_SCALE && y <= 26 * TOTAL_SCALE) {
|
x <= (int)window->width + (BUTTON_OFFSET - 50 + 8 + BUTTON_PAD) * TOTAL_SCALE) {
|
||||||
return DECOR_MINIMIZE;
|
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;
|
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) {
|
int decor_handle_event(yutani_t * yctx, yutani_msg_t * m) {
|
||||||
if (m) {
|
if (m) {
|
||||||
@ -265,10 +267,16 @@ int decor_handle_event(yutani_t * yctx, yutani_msg_t * m) {
|
|||||||
decor_get_bounds(window, &bounds);
|
decor_get_bounds(window, &bounds);
|
||||||
if (!window) return 0;
|
if (!window) return 0;
|
||||||
if (!(window->decorator_flags & DECOR_FLAG_DECORATED)) 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)) {
|
if (within_decors(window, me->new_x, me->new_y)) {
|
||||||
int button = decor_check_button_press(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 (me->command == YUTANI_MOUSE_EVENT_DOWN && me->buttons & YUTANI_MOUSE_BUTTON_LEFT) {
|
||||||
if (!button) {
|
if (!button || button == DECOR_OTHER) {
|
||||||
/* Resize edges */
|
/* Resize edges */
|
||||||
yutani_scale_direction_t resize_direction = check_resize_direction(me, window);
|
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;
|
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)) {
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
decor_hover_window = NULL;
|
||||||
|
decor_hover_button = 0;
|
||||||
|
yutani_internal_refocus(yctx, window);
|
||||||
return button;
|
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 {
|
} else {
|
||||||
if (old_resize_direction != SCALE_NONE) {
|
if (old_resize_direction != SCALE_NONE) {
|
||||||
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESET);
|
yutani_window_show_mouse(yctx, window, YUTANI_CURSOR_TYPE_RESET);
|
||||||
old_resize_direction = SCALE_NONE;
|
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;
|
break;
|
||||||
|
12
lib/yutani.c
12
lib/yutani.c
@ -1156,3 +1156,15 @@ void release_graphics_yutani(gfx_context_t * gfx) {
|
|||||||
}
|
}
|
||||||
free(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