yutani: window minimization, first pass

This commit is contained in:
K. Lange 2023-04-14 20:52:01 +09:00
parent 534aca26de
commit 2a18c192e4
8 changed files with 147 additions and 10 deletions

View File

@ -61,6 +61,8 @@ static void notify_subscribers(yutani_globals_t * yg);
static void mouse_stop_drag(yutani_globals_t * yg);
static void window_move(yutani_globals_t * yg, yutani_server_window_t * window, int x, int y);
static yutani_server_window_t * top_at(yutani_globals_t * yg, uint16_t x, uint16_t y);
static void window_unminimize(yutani_globals_t * yg, yutani_server_window_t * window);
static void window_finish_minimize(yutani_globals_t * yg, yutani_server_window_t * w);
#define ENABLE_BLUR_BEHIND
#ifdef ENABLE_BLUR_BEHIND
@ -256,6 +258,7 @@ static void unorder_window(yutani_globals_t * yg, yutani_server_window_t * w) {
}
list_t * zorder_owner = window_zorder_owner(yg, index);
if (!zorder_owner) return;
node_t * n = list_find(zorder_owner, w);
if (!n) return;
list_delete(zorder_owner, n);
@ -324,6 +327,10 @@ static void set_focused_window(yutani_globals_t * yg, yutani_server_window_t * w
return; /* Already focused */
}
if (w->minimized) {
window_unminimize(yg,w);
}
if (yg->focused_window) {
/* Send focus change to old focused window */
yutani_msg_buildx_window_focus_change_alloc(response);
@ -412,6 +419,7 @@ static yutani_server_window_t * server_window_create(yutani_globals_t * yg, int
win->server_flags = flags;
win->opacity = 255;
win->hidden = 1;
win->minimized = 0;
char key[1024];
YUTANI_SHMKEY(yg->server_ident, key, 1024, win);
@ -618,8 +626,7 @@ static void draw_cursor(yutani_globals_t * yg, int x, int y, int cursor) {
* around the cursor, but it is relatively slow.
*/
static yutani_server_window_t * check_top_at(yutani_globals_t * yg, yutani_server_window_t * w, uint16_t x, uint16_t y){
if (!w) return NULL;
if (w->hidden) return NULL;
if (!w || w->hidden || w->minimized) return NULL;
int32_t _x = -1, _y = -1;
yutani_device_to_window(w, x, y, &_x, &_y);
if (_x < 0 || _x >= w->width || _y < 0 || _y >= w->height) return NULL;
@ -726,7 +733,7 @@ static inline int matrix_is_translation(gfx_matrix_t m) {
*/
static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * window, int x, int y) {
if (window->hidden) {
if (window->hidden || window->minimized) {
return 0;
}
@ -777,6 +784,10 @@ static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * wi
list_insert(yg->windows_to_remove, window);
return 0;
}
if (yutani_is_minimizing_animation[window->anim_mode]) {
list_insert(yg->windows_to_minimize, window);
return 0;
}
window->anim_mode = 0;
window->anim_start = 0;
} else {
@ -808,6 +819,20 @@ static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * wi
}
}
break;
case YUTANI_EFFECT_MINIMIZE:
{
frame = yutani_animation_lengths[window->anim_mode] - frame;
} /* fallthrough */
case YUTANI_EFFECT_UNMINIMIZE:
{
double time_diff = ((double)frame / (float)yutani_animation_lengths[window->anim_mode]);
double x = 0.5 + time_diff * 0.5;
opacity *= time_diff;
//int t_x = (window->width * (1.0 - x)) / 2;
//gfx_matrix_translate(m, t_x, 0.0);
gfx_matrix_scale(m, 1.0, x);
}
break;
default:
break;
}
@ -882,7 +907,7 @@ static void yutani_post_vbox_rects(yutani_globals_t * yg) {
struct Rect * rects = (struct Rect *)(tmp+sizeof(int32_t));
#define DO_WINDOW(win) if (win && !win->hidden && *count < 255 ) { \
#define DO_WINDOW(win) if (win && !win->hidden && !win->minimized && *count < 255 ) { \
rects->x = (win)->x; \
rects->y = (win)->y; \
rects->xe = (win)->x + (win)->width; \
@ -1277,6 +1302,13 @@ static void redraw_windows(yutani_globals_t * yg) {
free(node);
}
while (yg->windows_to_minimize->tail) {
node_t * node = list_pop(yg->windows_to_minimize);
window_finish_minimize(yg, node->value);
free(node);
}
}
if (yg->screenshot_frame) {
@ -1392,6 +1424,27 @@ static void window_remove_from_client(yutani_globals_t * yg, yutani_server_windo
}
}
static void window_finish_minimize(yutani_globals_t * yg, yutani_server_window_t * w) {
if (w->minimized) return;
w->minimized = 1;
w->anim_mode = 0;
w->anim_start = 0;
unorder_window(yg,w);
if (w == yg->focused_window) {
yg->focused_window = NULL;
if (yg->menu_zs->tail && yg->menu_zs->tail->value) {
set_focused_window(yg, yg->menu_zs->tail->value);
} else if (yg->mid_zs->tail && yg->mid_zs->tail->value) {
set_focused_window(yg, yg->mid_zs->tail->value);
}
}
list_insert(yg->minimized_zs, w);
notify_subscribers(yg);
}
/**
* Actually remove a window and free the associated resources.
*/
@ -1445,6 +1498,9 @@ static uint32_t ad_flags(yutani_globals_t * yg, yutani_server_window_t * win) {
if (win == yg->focused_window) {
flags |= 1;
}
if (win->minimized) {
flags |= 2;
}
return flags;
}
@ -1584,6 +1640,28 @@ static void window_reveal(yutani_globals_t * yg, yutani_server_window_t * window
window->anim_start = yutani_current_time(yg);
}
static void window_unminimize(yutani_globals_t * yg, yutani_server_window_t * window) {
if (!window->minimized) return;
node_t * n = list_find(yg->minimized_zs, window);
if (n) {
list_delete(yg->minimized_zs, n);
free(n);
}
list_insert(yg->mid_zs, window);
window->z = 1;
window->minimized = 0;
window->anim_mode = YUTANI_EFFECT_UNMINIMIZE; //yutani_pick_animation(window->server_flags, 0);
window->anim_start = yutani_current_time(yg);
}
static void window_minimize(yutani_globals_t * yg, yutani_server_window_t * window) {
window->anim_mode = YUTANI_EFFECT_MINIMIZE; //yutani_pick_animation(window->server_flags, 0);
window->anim_start = yutani_current_time(yg);
}
/**
* Process a key event.
*
@ -1622,6 +1700,12 @@ static void handle_key_event(yutani_globals_t * yg, struct yutani_msg_key_event
mark_window(yg,focused);
return;
}
if ((ke->event.action == KEY_ACTION_DOWN) &&
(ke->event.modifiers & KEY_MOD_LEFT_SUPER) &&
(ke->event.keycode == 'a')) {
window_minimize(yg,focused);
return;
}
#endif
if ((ke->event.action == KEY_ACTION_DOWN) &&
(ke->event.modifiers & KEY_MOD_LEFT_ALT) &&
@ -2371,6 +2455,8 @@ int main(int argc, char * argv[]) {
yg->menu_zs = list_create();
yg->overlay_zs = list_create();
yg->windows_to_remove = list_create();
yg->windows_to_minimize = list_create();
yg->minimized_zs = list_create();
yg->window_subscribers = list_create();
@ -2734,6 +2820,9 @@ int main(int argc, char * argv[]) {
break;
case YUTANI_MSG_QUERY_WINDOWS:
{
foreach (node, yg->minimized_zs) {
yutani_query_result(yg, p->source, node->value);
}
yutani_query_result(yg, p->source, yg->bottom_z);
foreach (node, yg->mid_zs) {
yutani_query_result(yg, p->source, node->value);
@ -2897,6 +2986,11 @@ int main(int argc, char * argv[]) {
pex_send(yg->server, w->owner, response->size, (char *)response);
}
break;
case YUTANI_SPECIAL_REQUEST_MINIMIZE:
if (w) {
window_minimize(yg,w);
}
break;
case YUTANI_SPECIAL_REQUEST_CLIPBOARD:
{
yutani_msg_buildx_clipboard_alloc(response, yg->clipboard_size);

View File

@ -66,6 +66,7 @@ extern yutani_window_t * decor_show_default_menu(yutani_window_t * window, int y
#define DECOR_RESIZE 3 /* Resize button */
#define DECOR_MAXIMIZE 4
#define DECOR_RIGHT 5
#define DECOR_MINIMIZE 6
#define DECOR_ACTIVE 0
#define DECOR_INACTIVE 1

View File

@ -61,8 +61,8 @@ static int yutani_animation_lengths[] = {
0, /* None */
200, /* Fade In */
200, /* Fade Out */
0, /* Minimize */
0, /* Unminimized */
200, /* Minimize */
200, /* Unminimized */
100, /* Squeeze in */
100, /* Squeeze out */
10, /* Disappear */
@ -79,6 +79,17 @@ static int yutani_is_closing_animation[] = {
1,
};
static int yutani_is_minimizing_animation[] = {
0,
0,
0,
1,
0,
0,
0,
0
};
/* Debug Options */
#define YUTANI_DEBUG_WINDOW_BOUNDS 1
#define YUTANI_DEBUG_WINDOW_SHAPES 1
@ -161,6 +172,7 @@ typedef struct YutaniServerWindow {
/* Window is hidden? */
int hidden;
int minimized;
} yutani_server_window_t;
typedef struct YutaniGlobals {
@ -312,6 +324,9 @@ typedef struct YutaniGlobals {
uint64_t resize_release_time;
int32_t resizing_init_w;
int32_t resizing_init_h;
list_t * windows_to_minimize;
list_t * minimized_zs;
} yutani_globals_t;
struct key_bind {

View File

@ -488,6 +488,7 @@ struct yutani_msg_clipboard {
*/
#define YUTANI_SPECIAL_REQUEST_MAXIMIZE 1
#define YUTANI_SPECIAL_REQUEST_PLEASE_CLOSE 2
#define YUTANI_SPECIAL_REQUEST_MINIMIZE 3
#define YUTANI_SPECIAL_REQUEST_CLIPBOARD 10

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

View File

@ -44,9 +44,10 @@ static struct TT_Font * _tt_font = NULL;
#define BUTTON_CLOSE 0
#define BUTTON_MAXIMIZE 1
#define ACTIVE 2
#define INACTIVE 11
static sprite_t * sprites[20];
#define BUTTON_MINIMIZE 2
#define ACTIVE 3
#define INACTIVE 12
static sprite_t * sprites[21];
#define TEXT_OFFSET ((window->decorator_flags & DECOR_FLAG_TILED) ? 5 : 10)
#define BUTTON_OFFSET ((window->decorator_flags & DECOR_FLAG_TILED) ? 5 : 0)
@ -247,6 +248,12 @@ static void render_decorations_fancy(yutani_window_t * window, gfx_context_t * c
draw_sprite_alpha_paint(ctx, sprites[BUTTON_MAXIMIZE],
width + (BUTTON_OFFSET - 50) * TOTAL_SCALE,
(16 - BUTTON_OFFSET) * TOTAL_SCALE, 1.0, title_color);
if (width + (BUTTON_OFFSET - 72) * TOTAL_SCALE > bounds.left_width) {
draw_sprite_alpha_paint(ctx, sprites[BUTTON_MINIMIZE],
width + (BUTTON_OFFSET - 72) * TOTAL_SCALE,
(16 - BUTTON_OFFSET) * TOTAL_SCALE, 1.0, title_color);
}
}
}
}
@ -265,6 +272,12 @@ static int check_button_press_fancy(yutani_window_t * window, int x, int y) {
y >= 16 * TOTAL_SCALE && y <= 26 * TOTAL_SCALE) {
return DECOR_MAXIMIZE;
}
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;
}
}
return 0;
@ -273,6 +286,7 @@ static int check_button_press_fancy(yutani_window_t * window, int x, int y) {
void decor_init() {
init_sprite(BUTTON_CLOSE, TTK_FANCY_PATH "button-close.png");
init_sprite(BUTTON_MAXIMIZE, TTK_FANCY_PATH "button-maximize.png");
init_sprite(BUTTON_MINIMIZE, TTK_FANCY_PATH "button-minimize.png");
create_borders_from_spritesheet(ACTIVE, TTK_FANCY_PATH "borders-active.png");
create_borders_from_spritesheet(INACTIVE, TTK_FANCY_PATH "borders-inactive.png");

View File

@ -122,6 +122,10 @@ static void _decor_maximize(yutani_t * yctx, yutani_window_t * window) {
}
}
static void _decor_minimize(yutani_t * yctx, yutani_window_t * window) {
yutani_special_request(yctx, window, YUTANI_SPECIAL_REQUEST_MINIMIZE);
}
static yutani_window_t * _decor_menu_owner_window = NULL;
static struct MenuList * _decor_menu = NULL;
@ -320,6 +324,9 @@ int decor_handle_event(yutani_t * yctx, yutani_msg_t * m) {
case DECOR_MAXIMIZE:
_decor_maximize(yctx, window);
break;
case DECOR_MINIMIZE:
_decor_minimize(yctx, window);
break;
default:
break;
}

View File

@ -79,13 +79,18 @@ static int widget_draw_windowlist(struct PanelWidget * this, gfx_context_t * ctx
}
}
uint32_t text_color = TEXT_COLOR;
if (j == focused_app) text_color = HILIGHT_COLOR;
else if (ad->flags & 1) text_color = FOCUS_COLOR;
else if (ad->flags & 2) text_color = premultiply(rgba(_RED(TEXT_COLOR),_GRE(TEXT_COLOR),_BLU(TEXT_COLOR),127));
if (title_width >= MIN_TEXT_WIDTH) {
/* Ellipsifiy the title */
char * s = ellipsify(ad->name, 14, font, title_width - 4, NULL);
sprite_t * icon = icon_get_48(ad->icon);
gfx_context_t * subctx = init_graphics_subregion(ctx, i, 0, w, ctx->height);
draw_sprite_scaled_alpha(subctx, icon, w - 48 - 2, 0, 48, 48, (ad->flags & 1) ? 1.0 : 0.7);
tt_draw_string_shadow(subctx, font, s, 14, 2, TEXT_Y_OFFSET, (j == focused_app) ? HILIGHT_COLOR : (ad->flags & 1) ? FOCUS_COLOR : TEXT_COLOR, rgb(0,0,0), 4);
tt_draw_string_shadow(subctx, font, s, 14, 2, TEXT_Y_OFFSET, text_color, rgb(0,0,0), 4);
free(subctx);
free(s);
} else {