Skip to content

Commit 010b437

Browse files
committed
Add minimize and maximize features on window frame
Add a condition in twin_window_dispatch() to handle clicks on the minimize and maximize buttons located on the window frame. The positions of these buttons are calculated for click detection. A minimized window is considered inactive, even if it remains on top of the screen. The window's title bar is blue only when the window is both the topmost and active. Signed-off-by: Wei-Hsin Yeh <weihsinyeh168@gmail.com>
1 parent 0b046ce commit 010b437

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

include/twin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ struct _twin_window {
443443
twin_rect_t client;
444444
twin_rect_t damage;
445445
bool active;
446+
bool minimize;
446447
bool client_grab;
447448
bool want_focus;
448449
bool draw_queued;

src/screen.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
#include "twin_private.h"
1111

12+
#define TWIN_BW 0
13+
#define TWIN_TITLE_HEIGHT 20
14+
1215
twin_screen_t *twin_screen_create(twin_coord_t width,
1316
twin_coord_t height,
1417
twin_put_begin_t put_begin,
@@ -135,6 +138,12 @@ static void twin_screen_span_pixmap(twin_screen_t maybe_unused *screen,
135138
return;
136139
if (p->y + p->height <= y)
137140
return;
141+
142+
/* Skip drawing the window's client area if the window is minimized. */
143+
if (p->window->minimize &&
144+
y >= p->y + TWIN_BW + TWIN_TITLE_HEIGHT + TWIN_BW)
145+
return;
146+
138147
/* bounds check in x */
139148
p_left = left;
140149
if (p_left < p->x)

src/window.c

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ twin_window_t *twin_window_create(twin_screen_t *screen,
3636
window->screen = screen;
3737
window->style = style;
3838
window->active = false;
39+
window->minimize = false;
3940
switch (window->style) {
4041
case TwinWindowApplication:
4142
left = TWIN_BW;
@@ -179,6 +180,9 @@ bool twin_window_valid_range(twin_window_t *window,
179180
y < window->pixmap->y + window->pixmap->height - offset_y) {
180181
if (y < window->pixmap->y + (window->client.top))
181182
return !twin_pixmap_transparent(window->pixmap, x, y);
183+
else
184+
return !window->minimize;
185+
182186
return true;
183187
}
184188
return false;
@@ -494,22 +498,67 @@ bool twin_window_dispatch(twin_window_t *window, twin_event_t *event)
494498
twin_event_t ev = *event;
495499
bool delegate = true;
496500

501+
twin_fixed_t bw = twin_int_to_fixed(TWIN_TITLE_BW);
502+
twin_fixed_t t_h = twin_int_to_fixed(window->client.top) - bw;
503+
twin_fixed_t t_arc_2 = t_h * 2 / 3;
504+
twin_fixed_t c_right = twin_int_to_fixed(window->client.right) - bw / 2;
505+
twin_fixed_t name_height = t_h - bw - bw / 2;
506+
twin_fixed_t icon_size = name_height * 8 / 10;
507+
twin_fixed_t menu_x = t_arc_2;
508+
twin_fixed_t text_x = menu_x + icon_size + bw;
509+
twin_fixed_t text_width;
510+
twin_fixed_t title_right;
511+
twin_path_t *path = twin_path_create();
512+
const char *name = window->name;
513+
514+
text_width = twin_width_utf8(path, name);
515+
twin_path_destroy(path);
516+
title_right = (text_x + text_width + bw + icon_size + bw + icon_size + bw +
517+
icon_size + t_arc_2);
518+
519+
if (title_right < c_right)
520+
c_right = title_right;
521+
522+
twin_fixed_t close_x = c_right - t_arc_2 - icon_size;
523+
twin_fixed_t max_x = close_x - bw - icon_size;
524+
twin_fixed_t min_x = max_x - bw - icon_size;
525+
int local_x, local_y;
526+
497527
switch (ev.kind) {
498528
case TwinEventButtonDown:
529+
local_y = ev.u.pointer.screen_y - window->pixmap->y;
530+
if (local_y >= 0 && local_y <= TWIN_BW + TWIN_TITLE_HEIGHT + TWIN_BW) {
531+
local_x = ev.u.pointer.screen_x - window->pixmap->x;
532+
if (local_x > twin_fixed_to_int(min_x) &&
533+
local_x < twin_fixed_to_int(max_x)) {
534+
window->minimize = true;
535+
twin_pixmap_damage(window->pixmap, 0, 0, window->pixmap->width,
536+
window->pixmap->height);
537+
} else if (local_x > twin_fixed_to_int(max_x) &&
538+
local_x < twin_fixed_to_int(close_x)) {
539+
window->minimize = false;
540+
twin_pixmap_damage(window->pixmap, 0, 0, window->pixmap->width,
541+
window->pixmap->height);
542+
}
543+
}
499544
case TwinEventActivate:
500545
/* Set window active. */
501546
/*
502-
* When the box is trigger by TwinEventButtonDown, its window's title
503-
* bar needs to change color and be put onto the toppest layer.
547+
* If the window is minimized, it is not active. When the box is
548+
* triggered by TwinEventButtonDown and the window is not minimized, the
549+
* window's title bar should change to blue to indicate that it is on
550+
* top of the screen and active.
504551
*/
505-
if (!window->active) {
552+
if (window->minimize)
553+
window->active = false;
554+
else
506555
window->active = true;
507-
twin_window_frame(window);
508-
if (window != window->screen->top->window) {
509-
window->screen->top->window->active = false;
510-
twin_window_frame(window->screen->top->window);
511-
}
556+
twin_window_frame(window);
557+
if (window != window->screen->top->window) {
558+
window->screen->top->window->active = false;
559+
twin_window_frame(window->screen->top->window);
512560
}
561+
513562
#if defined(CONFIG_DROP_SHADOW)
514563
/* Handle drop shadow. */
515564
twin_window_drop_shadow(window);

0 commit comments

Comments
 (0)