mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
csd: initial implementation of minimize/maximize/close buttons
This commit is contained in:
parent
c845c90835
commit
9699c9b8bf
11 changed files with 268 additions and 21 deletions
47
config.c
47
config.c
|
|
@ -372,7 +372,7 @@ parse_section_csd(const char *key, const char *value, struct config *conf,
|
|||
conf->csd.color.border = color;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "titlebar") == 0) {
|
||||
else if (strcmp(key, "titlebar-size") == 0) {
|
||||
unsigned long pixels;
|
||||
if (!str_to_ulong(value, 10, &pixels)) {
|
||||
LOG_ERR("%s:%d: expected an integer: %s", path, lineno, value);
|
||||
|
|
@ -382,7 +382,7 @@ parse_section_csd(const char *key, const char *value, struct config *conf,
|
|||
conf->csd.title_height = pixels;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "border") == 0) {
|
||||
else if (strcmp(key, "border-width") == 0) {
|
||||
unsigned long pixels;
|
||||
if (!str_to_ulong(value, 10, &pixels)) {
|
||||
LOG_ERR("%s:%d: expected an integer: %s", path, lineno, value);
|
||||
|
|
@ -392,6 +392,48 @@ parse_section_csd(const char *key, const char *value, struct config *conf,
|
|||
conf->csd.border_width = pixels;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "button-width") == 0) {
|
||||
unsigned long pixels;
|
||||
if (!str_to_ulong(value, 10, &pixels)) {
|
||||
LOG_ERR("%s:%d: expected an integer: %s", path, lineno, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
conf->csd.button_width = pixels;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "button-minimize-color") == 0) {
|
||||
uint32_t color;
|
||||
if (!str_to_color(value, &color, true, path, lineno)) {
|
||||
LOG_ERR("%s:%d: invalid button-minimize-color: %s", path, lineno, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
conf->csd.color.minimize_set = true;
|
||||
conf->csd.color.minimize = color;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "button-maximize-color") == 0) {
|
||||
uint32_t color;
|
||||
if (!str_to_color(value, &color, true, path, lineno)) {
|
||||
LOG_ERR("%s:%d: invalid button-maximize-color: %s", path, lineno, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
conf->csd.color.maximize_set = true;
|
||||
conf->csd.color.maximize = color;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "button-close-color") == 0) {
|
||||
uint32_t color;
|
||||
if (!str_to_color(value, &color, true, path, lineno)) {
|
||||
LOG_ERR("%s:%d: invalid button-close-color: %s", path, lineno, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
conf->csd.color.close_set = true;
|
||||
conf->csd.color.close = color;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -602,6 +644,7 @@ config_load(struct config *conf, const char *conf_path)
|
|||
.preferred = CONF_CSD_PREFER_SERVER,
|
||||
.title_height = 26,
|
||||
.border_width = 5,
|
||||
.button_width = 22,
|
||||
.color = {
|
||||
.title_set = false,
|
||||
.border_set = false,
|
||||
|
|
|
|||
7
config.h
7
config.h
|
|
@ -41,12 +41,19 @@ struct config {
|
|||
|
||||
int title_height;
|
||||
int border_width;
|
||||
int button_width;
|
||||
|
||||
struct {
|
||||
bool title_set;
|
||||
bool border_set;
|
||||
bool minimize_set;
|
||||
bool maximize_set;
|
||||
bool close_set;
|
||||
uint32_t title;
|
||||
uint32_t border;
|
||||
uint32_t minimize;
|
||||
uint32_t maximize;
|
||||
uint32_t close;
|
||||
} color;
|
||||
} csd;
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,10 @@ applications can change these runtime.
|
|||
This section controls the 16 ANSI colors and the default foreground
|
||||
and background colors. Note that applications can change these runtime.
|
||||
|
||||
The colors are in RRGGBB format. That is, they do *not* have an alpha
|
||||
component. You can configure the background transparency with the
|
||||
_alpha_ option.
|
||||
|
||||
*foreground*
|
||||
Default RRGGBB foreground color. This is the color used when no
|
||||
ANSI color is being used. Default: _dcdccc_.
|
||||
|
|
@ -112,29 +116,43 @@ Decorations). Note that the default is to *not* use CSDs, but instead
|
|||
to use _SSDs_ (Server Side Decorations) when the compositor supports
|
||||
it.
|
||||
|
||||
Note that unlike the colors defined in the _colors_ section, the color
|
||||
values here are in AARRGGBB format. I.e. they contain an alpha
|
||||
component.
|
||||
|
||||
*preferred*
|
||||
Which type of window decorations to prefer: *client* (CSD) or
|
||||
*server* (SSD). Note that this is only a hint to the
|
||||
compositor. Depending on the compositor's configuration and
|
||||
capabilities, it may not have any effect. Default: _server_.
|
||||
|
||||
*titlebar*
|
||||
*titlebar-size*
|
||||
Height, in pixels (but subject to output scaling), of the
|
||||
titlebar, not including the window border. Default: _26_.
|
||||
|
||||
*border*
|
||||
*border-width*
|
||||
Width, in pixels (but subject to output scaling), of the
|
||||
borders. Default: _5_.
|
||||
|
||||
*titlebar-color*
|
||||
Titlebar AARRGGBB color. Note that unlike the other color values,
|
||||
the *titlebar-color* value also has an _alpha_ component. Default:
|
||||
use the default _foreground_ color.
|
||||
Titlebar AARRGGBB color. Default: use the default _foreground_
|
||||
color.
|
||||
|
||||
*border-color*
|
||||
Border AARRGGBB color. Note that unlike the other color values,
|
||||
the *border-color* value also has an _alpha_ component. Default:
|
||||
_transparent_.
|
||||
Border AARRGGBB color. Default: _transparent_.
|
||||
|
||||
*button-width*
|
||||
Width, in pixels (but subject to output scaling), of the
|
||||
minimize/maximize/close buttons. Default: _22_.
|
||||
|
||||
*button-minimize-color*
|
||||
Minimize button's AARRGGBB color. Default: _ff0000ff_.
|
||||
|
||||
*button-maximize-color*
|
||||
Maximize button's AARRGGBB color. Default: _ff00ff00_.
|
||||
|
||||
*button-close-color*
|
||||
Close button's AARRGGBB color. Default: _ffff0000_.
|
||||
|
||||
# FONT FORMAT
|
||||
|
||||
|
|
|
|||
8
footrc
8
footrc
|
|
@ -36,7 +36,11 @@
|
|||
|
||||
[csd]
|
||||
# preferred=server
|
||||
# titlebar=26
|
||||
# border=5
|
||||
# titlebar-size=26
|
||||
# border-width=5
|
||||
# titlebar-color=<foreground color>
|
||||
# border-color=00000000
|
||||
# button-width=22
|
||||
# button-minimize-color=ff0000ff
|
||||
# button-maximize-color=ff00ff00
|
||||
# button-close-color=ffff0000
|
||||
|
|
|
|||
81
input.c
81
input.c
|
|
@ -24,6 +24,7 @@
|
|||
#include "config.h"
|
||||
#include "commands.h"
|
||||
#include "keymap.h"
|
||||
#include "quirks.h"
|
||||
#include "render.h"
|
||||
#include "search.h"
|
||||
#include "selection.h"
|
||||
|
|
@ -708,6 +709,28 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
|
|||
render_xcursor_set(term);
|
||||
break;
|
||||
|
||||
case TERM_SURF_BUTTON_MINIMIZE:
|
||||
case TERM_SURF_BUTTON_MAXIMIZE:
|
||||
case TERM_SURF_BUTTON_CLOSE: {
|
||||
enum csd_surface idx =
|
||||
term->active_surface == TERM_SURF_BUTTON_MINIMIZE ? CSD_SURF_MINIMIZE :
|
||||
term->active_surface == TERM_SURF_BUTTON_MAXIMIZE ? CSD_SURF_MAXIMIZE :
|
||||
CSD_SURF_CLOSE;
|
||||
|
||||
quirk_weston_subsurface_desync_on(term->window->csd.sub_surface[CSD_SURF_TITLE]);
|
||||
quirk_weston_subsurface_desync_on(term->window->csd.sub_surface[idx]);
|
||||
|
||||
render_csd_button(term, idx);
|
||||
|
||||
quirk_weston_subsurface_desync_off(term->window->csd.sub_surface[idx]);
|
||||
quirk_weston_subsurface_desync_off(term->window->csd.sub_surface[CSD_SURF_TITLE]);
|
||||
wl_surface_commit(win->surface);
|
||||
|
||||
term->xcursor = "left_ptr";
|
||||
render_xcursor_set(term);
|
||||
break;
|
||||
}
|
||||
|
||||
case TERM_SURF_NONE:
|
||||
assert(false);
|
||||
break;
|
||||
|
|
@ -746,8 +769,43 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
|
|||
= wl_surface_get_user_data(surface);
|
||||
assert(old_moused == win->term);
|
||||
}
|
||||
|
||||
enum term_surface active_surface = old_moused->active_surface;
|
||||
|
||||
old_moused->active_surface = TERM_SURF_NONE;
|
||||
term_xcursor_update(old_moused);
|
||||
|
||||
switch (active_surface) {
|
||||
case TERM_SURF_BUTTON_MINIMIZE:
|
||||
case TERM_SURF_BUTTON_MAXIMIZE:
|
||||
case TERM_SURF_BUTTON_CLOSE: {
|
||||
enum csd_surface idx =
|
||||
active_surface == TERM_SURF_BUTTON_MINIMIZE ? CSD_SURF_MINIMIZE :
|
||||
active_surface == TERM_SURF_BUTTON_MAXIMIZE ? CSD_SURF_MAXIMIZE :
|
||||
CSD_SURF_CLOSE;
|
||||
|
||||
quirk_weston_subsurface_desync_on(old_moused->window->csd.sub_surface[CSD_SURF_TITLE]);
|
||||
quirk_weston_subsurface_desync_on(old_moused->window->csd.sub_surface[idx]);
|
||||
|
||||
render_csd_button(old_moused, idx);
|
||||
|
||||
quirk_weston_subsurface_desync_off(old_moused->window->csd.sub_surface[idx]);
|
||||
quirk_weston_subsurface_desync_off(old_moused->window->csd.sub_surface[CSD_SURF_TITLE]);
|
||||
wl_surface_commit(old_moused->window->surface);
|
||||
break;
|
||||
}
|
||||
|
||||
case TERM_SURF_NONE:
|
||||
case TERM_SURF_GRID:
|
||||
case TERM_SURF_SEARCH:
|
||||
case TERM_SURF_TITLE:
|
||||
case TERM_SURF_BORDER_LEFT:
|
||||
case TERM_SURF_BORDER_RIGHT:
|
||||
case TERM_SURF_BORDER_TOP:
|
||||
case TERM_SURF_BORDER_BOTTOM:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -787,6 +845,9 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
|
|||
switch (term->active_surface) {
|
||||
case TERM_SURF_NONE:
|
||||
case TERM_SURF_SEARCH:
|
||||
case TERM_SURF_BUTTON_MINIMIZE:
|
||||
case TERM_SURF_BUTTON_MAXIMIZE:
|
||||
case TERM_SURF_BUTTON_CLOSE:
|
||||
break;
|
||||
|
||||
case TERM_SURF_TITLE:
|
||||
|
|
@ -976,6 +1037,26 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
|||
return;
|
||||
}
|
||||
|
||||
case TERM_SURF_BUTTON_MINIMIZE:
|
||||
if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||
xdg_toplevel_set_minimized(term->window->xdg_toplevel);
|
||||
break;
|
||||
|
||||
case TERM_SURF_BUTTON_MAXIMIZE:
|
||||
if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
if (term->window->is_maximized)
|
||||
xdg_toplevel_unset_maximized(term->window->xdg_toplevel);
|
||||
else
|
||||
xdg_toplevel_set_maximized(term->window->xdg_toplevel);
|
||||
}
|
||||
break;
|
||||
|
||||
case TERM_SURF_BUTTON_CLOSE:
|
||||
if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||
term_shutdown(term);
|
||||
//LOG_ERR("unimplemented: terminate");
|
||||
break;
|
||||
|
||||
case TERM_SURF_SEARCH:
|
||||
break;
|
||||
|
||||
|
|
|
|||
79
render.c
79
render.c
|
|
@ -682,6 +682,9 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx)
|
|||
const int title_height = !term->window->is_fullscreen
|
||||
? term->conf->csd.title_height * term->scale : 0;
|
||||
|
||||
const int button_width = !term->window->is_fullscreen
|
||||
? term->conf->csd.button_width * term->scale : 0;
|
||||
|
||||
switch (surf_idx) {
|
||||
case CSD_SURF_TITLE: return (struct csd_data){ 0, -title_height, term->width, title_height};
|
||||
case CSD_SURF_LEFT: return (struct csd_data){-border_width, -title_height, border_width, title_height + term->height};
|
||||
|
|
@ -689,6 +692,11 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx)
|
|||
case CSD_SURF_TOP: return (struct csd_data){-border_width, -title_height - border_width, term->width + 2 * border_width, border_width};
|
||||
case CSD_SURF_BOTTOM: return (struct csd_data){-border_width, term->height, term->width + 2 * border_width, border_width};
|
||||
|
||||
/* Positioned relative to CSD_SURF_TITLE */
|
||||
case CSD_SURF_MINIMIZE: return (struct csd_data){term->width - 3 * button_width, 0, button_width, title_height};
|
||||
case CSD_SURF_MAXIMIZE: return (struct csd_data){term->width - 2 * button_width, 0, button_width, title_height};
|
||||
case CSD_SURF_CLOSE: return (struct csd_data){term->width - 1 * button_width, 0, button_width, title_height};
|
||||
|
||||
case CSD_SURF_COUNT:
|
||||
assert(false);
|
||||
return (struct csd_data){0};
|
||||
|
|
@ -780,6 +788,73 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx)
|
|||
render_csd_part(term, surf, buf, info.width, info.height, &color);
|
||||
}
|
||||
|
||||
void
|
||||
render_csd_button(struct terminal *term, enum csd_surface surf_idx)
|
||||
{
|
||||
assert(surf_idx >= CSD_SURF_MINIMIZE);
|
||||
|
||||
if (term->window->use_csd != CSD_YES)
|
||||
return;
|
||||
|
||||
struct csd_data info = get_csd_data(term, surf_idx);
|
||||
struct wl_surface *surf = term->window->csd.surface[surf_idx];
|
||||
|
||||
if (info.width == 0 || info.height == 0)
|
||||
return;
|
||||
|
||||
unsigned long cookie = shm_cookie_csd(term, surf_idx);
|
||||
struct buffer *buf = shm_get_buffer(
|
||||
term->wl->shm, info.width, info.height, cookie);
|
||||
|
||||
uint32_t _color;
|
||||
uint16_t alpha = 0xffff;
|
||||
bool is_active = false;
|
||||
const bool *is_set = NULL;
|
||||
const uint32_t *conf_color = NULL;
|
||||
|
||||
switch (surf_idx) {
|
||||
case CSD_SURF_MINIMIZE:
|
||||
_color = 0xff0000ff;
|
||||
is_set = &term->conf->csd.color.minimize_set;
|
||||
conf_color = &term->conf->csd.color.minimize;
|
||||
is_active = term->active_surface == TERM_SURF_BUTTON_MINIMIZE;
|
||||
break;
|
||||
|
||||
case CSD_SURF_MAXIMIZE:
|
||||
_color = 0xff00ff00;
|
||||
is_set = &term->conf->csd.color.maximize_set;
|
||||
conf_color = &term->conf->csd.color.maximize;
|
||||
is_active = term->active_surface == TERM_SURF_BUTTON_MAXIMIZE;
|
||||
break;
|
||||
|
||||
case CSD_SURF_CLOSE:
|
||||
_color = 0xffff0000;
|
||||
is_set = &term->conf->csd.color.close_set;
|
||||
conf_color = &term->conf->csd.color.close;
|
||||
is_active = term->active_surface == TERM_SURF_BUTTON_CLOSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_active) {
|
||||
if (*is_set) {
|
||||
_color = *conf_color;
|
||||
alpha = _color >> 24 | (_color >> 24 << 8);
|
||||
}
|
||||
} else {
|
||||
_color = 0;
|
||||
alpha = 0;
|
||||
}
|
||||
|
||||
pixman_color_t color = color_hex_to_pixman_with_alpha(_color, alpha);
|
||||
if (!term->visual_focus)
|
||||
pixman_color_dim(&color);
|
||||
render_csd_part(term, surf, buf, info.width, info.height, &color);
|
||||
}
|
||||
|
||||
void
|
||||
render_csd(struct terminal *term)
|
||||
{
|
||||
|
|
@ -798,7 +873,7 @@ render_csd(struct terminal *term)
|
|||
|
||||
if (width == 0 || height == 0) {
|
||||
/* CSD borders aren't rendered in maximized mode */
|
||||
assert(term->window->is_maximized);
|
||||
assert(term->window->is_maximized || term->window->is_fullscreen);
|
||||
wl_subsurface_set_position(sub, 0, 0);
|
||||
wl_surface_attach(surf, NULL, 0, 0);
|
||||
wl_surface_commit(surf);
|
||||
|
|
@ -811,6 +886,8 @@ render_csd(struct terminal *term)
|
|||
render_csd_title(term);
|
||||
for (size_t i = CSD_SURF_LEFT; i <= CSD_SURF_BOTTOM; i++)
|
||||
render_csd_border(term, i);
|
||||
for (size_t i = CSD_SURF_MINIMIZE; i < CSD_SURF_COUNT; i++)
|
||||
render_csd_button(term, i);
|
||||
}
|
||||
|
||||
static void frame_callback(
|
||||
|
|
|
|||
1
render.h
1
render.h
|
|
@ -19,6 +19,7 @@ bool render_xcursor_set(struct terminal *term);
|
|||
void render_search_box(struct terminal *term);
|
||||
void render_csd(struct terminal *term);
|
||||
void render_csd_title(struct terminal *term);
|
||||
void render_csd_button(struct terminal *term, enum csd_surface surf_idx);
|
||||
|
||||
struct render_worker_context {
|
||||
int my_id;
|
||||
|
|
|
|||
16
terminal.c
16
terminal.c
|
|
@ -2149,16 +2149,22 @@ term_surface_kind(const struct terminal *term, const struct wl_surface *surface)
|
|||
return TERM_SURF_GRID;
|
||||
else if (surface == term->window->search_surface)
|
||||
return TERM_SURF_SEARCH;
|
||||
else if (surface == term->window->csd.surface[0])
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_TITLE])
|
||||
return TERM_SURF_TITLE;
|
||||
else if (surface == term->window->csd.surface[1])
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_LEFT])
|
||||
return TERM_SURF_BORDER_LEFT;
|
||||
else if (surface == term->window->csd.surface[2])
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_RIGHT])
|
||||
return TERM_SURF_BORDER_RIGHT;
|
||||
else if (surface == term->window->csd.surface[3])
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_TOP])
|
||||
return TERM_SURF_BORDER_TOP;
|
||||
else if (surface == term->window->csd.surface[4])
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_BOTTOM])
|
||||
return TERM_SURF_BORDER_BOTTOM;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_MINIMIZE])
|
||||
return TERM_SURF_BUTTON_MINIMIZE;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_MAXIMIZE])
|
||||
return TERM_SURF_BUTTON_MAXIMIZE;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_CLOSE])
|
||||
return TERM_SURF_BUTTON_CLOSE;
|
||||
else
|
||||
return TERM_SURF_NONE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,6 +194,9 @@ enum term_surface {
|
|||
TERM_SURF_BORDER_RIGHT,
|
||||
TERM_SURF_BORDER_TOP,
|
||||
TERM_SURF_BORDER_BOTTOM,
|
||||
TERM_SURF_BUTTON_MINIMIZE,
|
||||
TERM_SURF_BUTTON_MAXIMIZE,
|
||||
TERM_SURF_BUTTON_CLOSE,
|
||||
};
|
||||
|
||||
struct terminal {
|
||||
|
|
|
|||
|
|
@ -47,8 +47,12 @@ csd_instantiate(struct wl_window *win)
|
|||
assert(win->csd.sub_surface[i] == NULL);
|
||||
|
||||
win->csd.surface[i] = wl_compositor_create_surface(wayl->compositor);
|
||||
|
||||
struct wl_surface *parent = i < CSD_SURF_MINIMIZE
|
||||
? win->surface : win->csd.surface[CSD_SURF_TITLE];
|
||||
|
||||
win->csd.sub_surface[i] = wl_subcompositor_get_subsurface(
|
||||
wayl->sub_compositor, win->csd.surface[i], win->surface);
|
||||
wayl->sub_compositor, win->csd.surface[i], parent);
|
||||
|
||||
wl_subsurface_set_sync(win->csd.sub_surface[i]);
|
||||
wl_surface_set_user_data(win->csd.surface[i], win);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,9 @@ enum csd_surface {
|
|||
CSD_SURF_RIGHT,
|
||||
CSD_SURF_TOP,
|
||||
CSD_SURF_BOTTOM,
|
||||
CSD_SURF_MINIMIZE,
|
||||
CSD_SURF_MAXIMIZE,
|
||||
CSD_SURF_CLOSE,
|
||||
CSD_SURF_COUNT,
|
||||
};
|
||||
|
||||
|
|
@ -103,8 +106,8 @@ struct wl_window {
|
|||
enum {CSD_UNKNOWN, CSD_NO, CSD_YES } use_csd;
|
||||
|
||||
struct {
|
||||
struct wl_surface *surface[5];
|
||||
struct wl_subsurface *sub_surface[5];
|
||||
struct wl_surface *surface[CSD_SURF_COUNT];
|
||||
struct wl_subsurface *sub_surface[CSD_SURF_COUNT];
|
||||
int move_timeout_fd;
|
||||
uint32_t serial;
|
||||
} csd;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue