Skip to content

Commit 5eb41fa

Browse files
authored
Merge pull request #103 from weihsinyeh/minimize
Add iconify and restore features on window frame
2 parents ceaa9d1 + 5502f5c commit 5eb41fa

File tree

5 files changed

+89
-29
lines changed

5 files changed

+89
-29
lines changed

include/twin.h

Lines changed: 3 additions & 2 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 iconify;
446447
bool client_grab;
447448
bool want_focus;
448449
bool draw_queued;
@@ -459,8 +460,8 @@ struct _twin_window {
459460
*/
460461
typedef enum _twin_icon {
461462
TwinIconMenu,
462-
TwinIconMinimize,
463-
TwinIconMaximize,
463+
TwinIconIconify,
464+
TwinIconRestore,
464465
TwinIconClose,
465466
TwinIconResize,
466467
} twin_icon_t;

src/draw-common.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,17 @@ void twin_shadow_border(twin_pixmap_t *shadow,
163163
offset = min(offset_x, offset_y);
164164

165165
switch (shadow->window->style) {
166+
/*
167+
* Draw a black border starting from the top y position of the window's
168+
* client area plus CONFIG_SHADOW_BLUR / 2 + 1, to prevent twin_stack_blur()
169+
* from blurring shadows over the window frame.
170+
*/
166171
case TwinWindowApplication:
167-
y_start = TWIN_TITLE_HEIGHT;
172+
y_start = TWIN_TITLE_HEIGHT + CONFIG_SHADOW_BLUR / 2 + 1;
168173
break;
169174
case TwinWindowPlain:
170175
default:
171-
y_start = 0;
176+
y_start = CONFIG_SHADOW_BLUR / 2 + 1;
172177
break;
173178
}
174179

src/icon.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ static const signed char _twin_itable[] = {
3939
's',
4040
'e',
4141
#define TWIN_MENU_LEN 43
42-
/* Minimize */
43-
#define TWIN_MINIMIZE_POS TWIN_MENU_POS + TWIN_MENU_LEN
42+
/* Iconify */
43+
#define TWIN_ICONIFY_POS TWIN_MENU_POS + TWIN_MENU_LEN
4444
'm', L(0), G(0.8),
4545
'd', L(0), B(1),
4646
'd', R(1), B(1),
@@ -49,9 +49,9 @@ static const signed char _twin_itable[] = {
4949
'w', G(0.05),
5050
'p',
5151
'e',
52-
#define TWIN_MINIMIZE_LEN 17
53-
/* Maximize */
54-
#define TWIN_MAXIMIZE_POS TWIN_MINIMIZE_POS + TWIN_MINIMIZE_LEN
52+
#define TWIN_ICONIFY_LEN 17
53+
/* Restore */
54+
#define TWIN_RESTORE_POS TWIN_ICONIFY_POS + TWIN_ICONIFY_LEN
5555
'm', L(0), T(0),
5656
'd', L(0), G(0.2),
5757
'd', R(1), G(0.2),
@@ -64,9 +64,9 @@ static const signed char _twin_itable[] = {
6464
'x',
6565
's',
6666
'e',
67-
#define TWIN_MAXIMIZE_LEN 28
67+
#define TWIN_RESTORE_LEN 28
6868
/* Close */
69-
#define TWIN_CLOSE_POS TWIN_MAXIMIZE_POS + TWIN_MAXIMIZE_LEN
69+
#define TWIN_CLOSE_POS TWIN_RESTORE_POS + TWIN_RESTORE_LEN
7070
'm', L(0), T(0),
7171
'd', L(0), T(0.1),
7272
'd', G(0.4), G(0.5),
@@ -103,7 +103,7 @@ static const signed char _twin_itable[] = {
103103
/* clang-format on */
104104

105105
const uint16_t _twin_icons[] = {
106-
TWIN_MENU_POS, TWIN_MINIMIZE_POS, TWIN_MAXIMIZE_POS,
106+
TWIN_MENU_POS, TWIN_ICONIFY_POS, TWIN_RESTORE_POS,
107107
TWIN_CLOSE_POS, TWIN_RESIZE_POS,
108108
};
109109

src/screen.c

Lines changed: 8 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,11 @@ 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 iconified. */
143+
if (p->window->iconify && y >= p->y + TWIN_BW + TWIN_TITLE_HEIGHT + TWIN_BW)
144+
return;
145+
138146
/* bounds check in x */
139147
p_left = left;
140148
if (p_left < p->x)

src/window.c

Lines changed: 63 additions & 17 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->iconify = false;
3940
switch (window->style) {
4041
case TwinWindowApplication:
4142
left = TWIN_BW;
@@ -179,7 +180,7 @@ 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);
182-
return true;
183+
return !window->iconify;
183184
}
184185
return false;
185186
}
@@ -234,8 +235,8 @@ static void twin_window_frame(twin_window_t *window)
234235
twin_fixed_t text_width;
235236
twin_fixed_t title_right;
236237
twin_fixed_t close_x;
237-
twin_fixed_t max_x;
238-
twin_fixed_t min_x;
238+
twin_fixed_t restore_x;
239+
twin_fixed_t iconify_x;
239240
twin_fixed_t resize_x;
240241
twin_fixed_t resize_y;
241242
const char *name;
@@ -265,8 +266,8 @@ static void twin_window_frame(twin_window_t *window)
265266

266267

267268
close_x = c_right - t_arc_2 - icon_size;
268-
max_x = close_x - bw - icon_size;
269-
min_x = max_x - bw - icon_size;
269+
restore_x = close_x - bw - icon_size;
270+
iconify_x = restore_x - bw - icon_size;
270271
resize_x = twin_int_to_fixed(window->client.right);
271272
resize_y = twin_int_to_fixed(window->client.bottom);
272273

@@ -314,14 +315,14 @@ static void twin_window_frame(twin_window_t *window)
314315
twin_icon_draw(pixmap, TwinIconMenu, m);
315316

316317
twin_matrix_identity(&m);
317-
twin_matrix_translate(&m, min_x, icon_y);
318+
twin_matrix_translate(&m, iconify_x, icon_y);
318319
twin_matrix_scale(&m, icon_size, icon_size);
319-
twin_icon_draw(pixmap, TwinIconMinimize, m);
320+
twin_icon_draw(pixmap, TwinIconIconify, m);
320321

321322
twin_matrix_identity(&m);
322-
twin_matrix_translate(&m, max_x, icon_y);
323+
twin_matrix_translate(&m, restore_x, icon_y);
323324
twin_matrix_scale(&m, icon_size, icon_size);
324-
twin_icon_draw(pixmap, TwinIconMaximize, m);
325+
twin_icon_draw(pixmap, TwinIconRestore, m);
325326

326327
twin_matrix_identity(&m);
327328
twin_matrix_translate(&m, close_x, icon_y);
@@ -494,21 +495,66 @@ bool twin_window_dispatch(twin_window_t *window, twin_event_t *event)
494495
twin_event_t ev = *event;
495496
bool delegate = true;
496497

498+
twin_fixed_t bw = twin_int_to_fixed(TWIN_TITLE_BW);
499+
twin_fixed_t t_h = twin_int_to_fixed(window->client.top) - bw;
500+
twin_fixed_t t_arc_2 = t_h * 2 / 3;
501+
twin_fixed_t c_right = twin_int_to_fixed(window->client.right) - bw / 2;
502+
twin_fixed_t name_height = t_h - bw - bw / 2;
503+
twin_fixed_t icon_size = name_height * 8 / 10;
504+
twin_fixed_t menu_x = t_arc_2;
505+
twin_fixed_t text_x = menu_x + icon_size + bw;
506+
twin_fixed_t text_width;
507+
twin_fixed_t title_right;
508+
twin_path_t *path = twin_path_create();
509+
const char *name = window->name;
510+
511+
text_width = twin_width_utf8(path, name);
512+
twin_path_destroy(path);
513+
title_right = (text_x + text_width + bw + icon_size + bw + icon_size + bw +
514+
icon_size + t_arc_2);
515+
516+
if (title_right < c_right)
517+
c_right = title_right;
518+
519+
twin_fixed_t close_x = c_right - t_arc_2 - icon_size;
520+
twin_fixed_t restore_x = close_x - bw - icon_size;
521+
twin_fixed_t iconify_x = restore_x - bw - icon_size;
522+
int local_x, local_y;
523+
497524
switch (ev.kind) {
498525
case TwinEventButtonDown:
526+
local_y = ev.u.pointer.screen_y - window->pixmap->y;
527+
if (local_y >= 0 && local_y <= TWIN_BW + TWIN_TITLE_HEIGHT + TWIN_BW) {
528+
local_x = ev.u.pointer.screen_x - window->pixmap->x;
529+
if (local_x > twin_fixed_to_int(iconify_x) &&
530+
local_x < twin_fixed_to_int(restore_x)) {
531+
window->iconify = true;
532+
twin_pixmap_damage(window->pixmap, 0, 0, window->pixmap->width,
533+
window->pixmap->height);
534+
} else if (local_x > twin_fixed_to_int(restore_x) &&
535+
local_x < twin_fixed_to_int(close_x)) {
536+
window->iconify = false;
537+
twin_pixmap_damage(window->pixmap, 0, 0, window->pixmap->width,
538+
window->pixmap->height);
539+
}
540+
}
499541
case TwinEventActivate:
500542
/* Set window active. */
501543
/*
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.
544+
* A iconified window is inactive. When the box is triggered by
545+
* TwinEventButtonDown and the window is not iconified, it becomes
546+
* active. For a window to be considered active, it must be the topmost
547+
* window on the screen. The window's title bar turns blue to indicate
548+
* the active state.
504549
*/
505-
if (!window->active) {
550+
if (window->iconify)
551+
window->active = false;
552+
else
506553
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-
}
554+
twin_window_frame(window);
555+
if (window != window->screen->top->window) {
556+
window->screen->top->window->active = false;
557+
twin_window_frame(window->screen->top->window);
512558
}
513559
#if defined(CONFIG_DROP_SHADOW)
514560
/* Handle drop shadow. */

0 commit comments

Comments
 (0)