Skip to content

Add minimize and maximize features on window frame #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/twin.h
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ struct _twin_window {
twin_rect_t client;
twin_rect_t damage;
bool active;
bool minimize;
bool client_grab;
bool want_focus;
bool draw_queued;
Expand Down
9 changes: 7 additions & 2 deletions src/draw-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,17 @@ void twin_shadow_border(twin_pixmap_t *shadow,
offset = min(offset_x, offset_y);

switch (shadow->window->style) {
/*
* Draw a black border starting from the top y position of the window's
* client area plus CONFIG_SHADOW_BLUR / 2 + 1, to prevent twin_stack_blur()
* from blurring shadows over the window frame.
*/
case TwinWindowApplication:
y_start = TWIN_TITLE_HEIGHT;
y_start = TWIN_TITLE_HEIGHT + CONFIG_SHADOW_BLUR / 2 + 1;
break;
case TwinWindowPlain:
default:
y_start = 0;
y_start = CONFIG_SHADOW_BLUR / 2 + 1;
break;
}

Expand Down
9 changes: 9 additions & 0 deletions src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

#include "twin_private.h"

#define TWIN_BW 0
#define TWIN_TITLE_HEIGHT 20

twin_screen_t *twin_screen_create(twin_coord_t width,
twin_coord_t height,
twin_put_begin_t put_begin,
Expand Down Expand Up @@ -135,6 +138,12 @@ static void twin_screen_span_pixmap(twin_screen_t maybe_unused *screen,
return;
if (p->y + p->height <= y)
return;

/* Skip drawing the window's client area if the window is minimized. */
if (p->window->minimize &&
y >= p->y + TWIN_BW + TWIN_TITLE_HEIGHT + TWIN_BW)
return;

/* bounds check in x */
p_left = left;
if (p_left < p->x)
Expand Down
64 changes: 55 additions & 9 deletions src/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ twin_window_t *twin_window_create(twin_screen_t *screen,
window->screen = screen;
window->style = style;
window->active = false;
window->minimize = false;
switch (window->style) {
case TwinWindowApplication:
left = TWIN_BW;
Expand Down Expand Up @@ -179,7 +180,7 @@ bool twin_window_valid_range(twin_window_t *window,
y < window->pixmap->y + window->pixmap->height - offset_y) {
if (y < window->pixmap->y + (window->client.top))
return !twin_pixmap_transparent(window->pixmap, x, y);
return true;
return !window->minimize;
}
return false;
}
Expand Down Expand Up @@ -494,21 +495,66 @@ bool twin_window_dispatch(twin_window_t *window, twin_event_t *event)
twin_event_t ev = *event;
bool delegate = true;

twin_fixed_t bw = twin_int_to_fixed(TWIN_TITLE_BW);
twin_fixed_t t_h = twin_int_to_fixed(window->client.top) - bw;
twin_fixed_t t_arc_2 = t_h * 2 / 3;
twin_fixed_t c_right = twin_int_to_fixed(window->client.right) - bw / 2;
twin_fixed_t name_height = t_h - bw - bw / 2;
twin_fixed_t icon_size = name_height * 8 / 10;
twin_fixed_t menu_x = t_arc_2;
twin_fixed_t text_x = menu_x + icon_size + bw;
twin_fixed_t text_width;
twin_fixed_t title_right;
twin_path_t *path = twin_path_create();
const char *name = window->name;

text_width = twin_width_utf8(path, name);
twin_path_destroy(path);
title_right = (text_x + text_width + bw + icon_size + bw + icon_size + bw +
icon_size + t_arc_2);

if (title_right < c_right)
c_right = title_right;

twin_fixed_t close_x = c_right - t_arc_2 - icon_size;
twin_fixed_t max_x = close_x - bw - icon_size;
twin_fixed_t min_x = max_x - bw - icon_size;
int local_x, local_y;

switch (ev.kind) {
case TwinEventButtonDown:
local_y = ev.u.pointer.screen_y - window->pixmap->y;
if (local_y >= 0 && local_y <= TWIN_BW + TWIN_TITLE_HEIGHT + TWIN_BW) {
local_x = ev.u.pointer.screen_x - window->pixmap->x;
if (local_x > twin_fixed_to_int(min_x) &&
local_x < twin_fixed_to_int(max_x)) {
window->minimize = true;
twin_pixmap_damage(window->pixmap, 0, 0, window->pixmap->width,
window->pixmap->height);
} else if (local_x > twin_fixed_to_int(max_x) &&
local_x < twin_fixed_to_int(close_x)) {
window->minimize = false;
twin_pixmap_damage(window->pixmap, 0, 0, window->pixmap->width,
window->pixmap->height);
}
}
case TwinEventActivate:
/* Set window active. */
/*
* When the box is trigger by TwinEventButtonDown, its window's title
* bar needs to change color and be put onto the toppest layer.
* A minimized window is inactive. When the box is triggered by
* TwinEventButtonDown and the window is not minimized, it becomes
* active. For a window to be considered active, it must be the topmost
* window on the screen. The window's title bar turns blue to indicate
* the active state.
*/
if (!window->active) {
if (window->minimize)
window->active = false;
else
window->active = true;
twin_window_frame(window);
if (window != window->screen->top->window) {
window->screen->top->window->active = false;
twin_window_frame(window->screen->top->window);
}
twin_window_frame(window);
if (window != window->screen->top->window) {
window->screen->top->window->active = false;
twin_window_frame(window->screen->top->window);
}
#if defined(CONFIG_DROP_SHADOW)
/* Handle drop shadow. */
Expand Down