mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
csd: position CSD sub-surfaces *outside* the main window
For now, this behavior is controlled with an ifdef. At least kwin seems very buggy when the decorations are positioned like this (but normally you'd use server-side decorations with kwin anyway). This commit also changes 'use_csd' to be a tri-state variable; when instantiating a window it is set to 'unknown'. If there's no decoration manager available (e.g. weston), we immediately set it to 'yes' (use CSDs). Otherwise, we wait for the decoration manager callback to indicate whether we should use CSDs or not.
This commit is contained in:
parent
45ba9f9c8f
commit
2f587f6f3d
4 changed files with 91 additions and 57 deletions
113
render.c
113
render.c
|
|
@ -665,59 +665,74 @@ render_worker_thread(void *_ctx)
|
|||
void
|
||||
render_csd(struct terminal *term)
|
||||
{
|
||||
if (!term->window->use_csd)
|
||||
return;
|
||||
switch (term->window->use_csd) {
|
||||
case CSD_UNKNOWN:
|
||||
case CSD_NO:
|
||||
break;
|
||||
|
||||
const int border_width = csd_border_size * term->scale;
|
||||
const int title_height = csd_title_size * term->scale;
|
||||
case CSD_YES: {
|
||||
const int border_width = csd_border_size * term->scale;
|
||||
const int title_height = csd_title_size * term->scale;
|
||||
|
||||
const int geom[5][4] = {
|
||||
/* X, Y, WIDTH, HEIGHT */
|
||||
{ border_width, border_width, term->width - 2 * border_width, title_height}, /* title */
|
||||
{ 0, border_width, border_width, term->height - 2 * border_width}, /* left */
|
||||
{term->width - border_width, border_width, border_width, term->height - 2 * border_width}, /* right */
|
||||
{ 0, 0, term->width, border_width}, /* top */
|
||||
{ 0, term->height - border_width, term->width, border_width}, /* bottom */
|
||||
};
|
||||
const int geom[5][4] = {
|
||||
/* X, Y, WIDTH, HEIGHT */
|
||||
#if FOOT_CSD_OUTSIDE
|
||||
{ 0, -title_height, term->width, title_height}, /* title */
|
||||
{ -border_width, -title_height, border_width, title_height + term->height}, /* left */
|
||||
{ term->width, -title_height, border_width, title_height + term->height}, /* right */
|
||||
{ -border_width, -title_height - border_width, term->width + 2 * border_width, border_width}, /* top */
|
||||
{ -border_width, term->height, term->width + 2 * border_width, border_width}, /* bottom */
|
||||
#else
|
||||
{ border_width, border_width, term->width - 2 * border_width, title_height}, /* title */
|
||||
{ 0, border_width, border_width, term->height - 2 * border_width}, /* left */
|
||||
{term->width - border_width, border_width, border_width, term->height - 2 * border_width}, /* right */
|
||||
{ 0, 0, term->width, border_width}, /* top */
|
||||
{ 0, term->height - border_width, term->width, border_width}, /* bottom */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct wl_region *region = wl_compositor_create_region(term->wl->compositor);
|
||||
if (region != NULL)
|
||||
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
|
||||
struct wl_region *region = wl_compositor_create_region(term->wl->compositor);
|
||||
if (region != NULL)
|
||||
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
|
||||
|
||||
for (size_t i = 0; i < sizeof(geom) / sizeof(geom[0]); i++) {
|
||||
struct wl_surface *surf = term->window->csd.surface[i];
|
||||
struct wl_subsurface *sub = term->window->csd.sub_surface[i];
|
||||
for (size_t i = 0; i < sizeof(geom) / sizeof(geom[0]); i++) {
|
||||
struct wl_surface *surf = term->window->csd.surface[i];
|
||||
struct wl_subsurface *sub = term->window->csd.sub_surface[i];
|
||||
|
||||
const int x = geom[i][0];
|
||||
const int y = geom[i][1];
|
||||
const int width = geom[i][2];
|
||||
const int height = geom[i][3];
|
||||
const int x = geom[i][0];
|
||||
const int y = geom[i][1];
|
||||
const int width = geom[i][2];
|
||||
const int height = geom[i][3];
|
||||
|
||||
unsigned long cookie = shm_cookie_csd(term, i);
|
||||
struct buffer *buf = shm_get_buffer(term->wl->shm, width, height, cookie);
|
||||
unsigned long cookie = shm_cookie_csd(term, i);
|
||||
struct buffer *buf = shm_get_buffer(term->wl->shm, width, height, cookie);
|
||||
|
||||
pixman_color_t color = color_hex_to_pixman(term->colors.fg);
|
||||
if (!term->visual_focus)
|
||||
pixman_color_dim(&color);
|
||||
pixman_color_t color = color_hex_to_pixman(term->colors.fg);
|
||||
if (!term->visual_focus)
|
||||
pixman_color_dim(&color);
|
||||
|
||||
pixman_image_t *src = pixman_image_create_solid_fill(&color);
|
||||
pixman_image_t *src = pixman_image_create_solid_fill(&color);
|
||||
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, buf->pix, &color, 1,
|
||||
&(pixman_rectangle16_t){0, 0, buf->width, buf->height});
|
||||
pixman_image_unref(src);
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, buf->pix, &color, 1,
|
||||
&(pixman_rectangle16_t){0, 0, buf->width, buf->height});
|
||||
pixman_image_unref(src);
|
||||
|
||||
wl_subsurface_set_position(sub, x, y);
|
||||
wl_subsurface_set_position(sub, x, y);
|
||||
|
||||
wl_surface_attach(surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_set_opaque_region(surf, region);
|
||||
wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height);
|
||||
wl_surface_set_buffer_scale(surf, term->scale);
|
||||
wl_surface_commit(surf);
|
||||
wl_surface_attach(surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_set_opaque_region(surf, region);
|
||||
wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height);
|
||||
wl_surface_set_buffer_scale(surf, term->scale);
|
||||
wl_surface_commit(surf);
|
||||
}
|
||||
|
||||
if (region != NULL)
|
||||
wl_region_destroy(region);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (region != NULL)
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
static void frame_callback(
|
||||
|
|
@ -1043,7 +1058,11 @@ render_search_box(struct terminal *term)
|
|||
assert(term->scale >= 1);
|
||||
const int scale = term->scale;
|
||||
|
||||
const int csd = term->window->use_csd ? csd_border_size * scale : 0;
|
||||
#if FOOT_CSD_OUTSIDE
|
||||
const int csd = 0;
|
||||
#else
|
||||
const int csd = term->window->use_csd == CSD_YES ? csd_border_size * scale : 0;
|
||||
#endif
|
||||
const size_t margin = csd + 3 * scale;
|
||||
|
||||
const size_t width = min(
|
||||
|
|
@ -1144,8 +1163,14 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
height *= scale;
|
||||
|
||||
/* Scaled CSD border + title bar sizes */
|
||||
const int csd_border = term->window->use_csd ? csd_border_size * scale : 0;
|
||||
const int csd_title = term->window->use_csd ? csd_title_size * scale : 0;
|
||||
#if FOOT_CSD_OUTSIDE
|
||||
const int csd_border = 0;
|
||||
const int csd_title = 0;
|
||||
#else
|
||||
const int csd_border = term->window->use_csd == CSD_YES ? csd_border_size * scale : 0;
|
||||
const int csd_title = term->window->use_csd == CSD_YES ? ? csd_title_size * scale : 0;
|
||||
#endif
|
||||
|
||||
const int csd_x = 2 * csd_border;
|
||||
const int csd_y = 2 * csd_border + csd_title;
|
||||
|
||||
|
|
|
|||
26
terminal.c
26
terminal.c
|
|
@ -1633,14 +1633,18 @@ term_visual_focus_in(struct terminal *term)
|
|||
if (term->cursor_blink.active)
|
||||
cursor_blink_start_timer(term);
|
||||
|
||||
#if 1
|
||||
for (int i = 0; i < 5; i++)
|
||||
wl_subsurface_set_desync(term->window->csd.sub_surface[i]);
|
||||
#if 1 /* Weston seems to be buggy with synchronized CSDs */
|
||||
if (term->window->use_csd == CSD_YES) {
|
||||
for (int i = 0; i < 5; i++)
|
||||
wl_subsurface_set_desync(term->window->csd.sub_surface[i]);
|
||||
}
|
||||
#endif
|
||||
render_csd(term);
|
||||
#if 1
|
||||
for (int i = 0; i < 5; i++)
|
||||
wl_subsurface_set_sync(term->window->csd.sub_surface[i]);
|
||||
if (term->window->use_csd == CSD_YES) {
|
||||
for (int i = 0; i < 5; i++)
|
||||
wl_subsurface_set_sync(term->window->csd.sub_surface[i]);
|
||||
}
|
||||
#endif
|
||||
cursor_refresh(term);
|
||||
}
|
||||
|
|
@ -1656,13 +1660,17 @@ term_visual_focus_out(struct terminal *term)
|
|||
cursor_blink_stop_timer(term);
|
||||
|
||||
#if 1
|
||||
for (int i = 0; i < 5; i++)
|
||||
wl_subsurface_set_desync(term->window->csd.sub_surface[i]);
|
||||
if (term->window->use_csd == CSD_YES) {
|
||||
for (int i = 0; i < 5; i++)
|
||||
wl_subsurface_set_desync(term->window->csd.sub_surface[i]);
|
||||
}
|
||||
#endif
|
||||
render_csd(term);
|
||||
#if 1
|
||||
for (int i = 0; i < 5; i++)
|
||||
wl_subsurface_set_sync(term->window->csd.sub_surface[i]);
|
||||
if (term->window->use_csd == CSD_YES) {
|
||||
for (int i = 0; i < 5; i++)
|
||||
wl_subsurface_set_sync(term->window->csd.sub_surface[i]);
|
||||
}
|
||||
#endif
|
||||
cursor_refresh(term);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -551,12 +551,12 @@ xdg_toplevel_decoration_configure(void *data,
|
|||
switch (mode) {
|
||||
case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE:
|
||||
LOG_DBG("using client-side decorations");
|
||||
win->use_csd = true;
|
||||
win->use_csd = CSD_YES;
|
||||
break;
|
||||
|
||||
case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE:
|
||||
LOG_DBG("using server-side decorations");
|
||||
win->use_csd = false;
|
||||
win->use_csd = CSD_NO;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -902,7 +902,7 @@ wayl_win_init(struct terminal *term)
|
|||
|
||||
struct wl_window *win = calloc(1, sizeof(*win));
|
||||
win->term = term;
|
||||
win->use_csd = true;
|
||||
win->use_csd = CSD_UNKNOWN;
|
||||
|
||||
win->surface = wl_compositor_create_surface(wayl->compositor);
|
||||
if (win->surface == NULL) {
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ struct wl_primary {
|
|||
uint32_t serial;
|
||||
};
|
||||
|
||||
#define FOOT_CSD_OUTSIDE 1
|
||||
extern const int csd_border_size;
|
||||
extern const int csd_title_size;
|
||||
|
||||
|
|
@ -94,7 +95,7 @@ struct wl_window {
|
|||
|
||||
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
||||
|
||||
bool use_csd;
|
||||
enum {CSD_UNKNOWN, CSD_NO, CSD_YES } use_csd;
|
||||
|
||||
struct {
|
||||
struct wl_surface *surface[5];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue