From 2f587f6f3d29c2dbfc6625e94144bf325263d090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 26 Feb 2020 12:17:58 +0100 Subject: [PATCH] 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. --- render.c | 113 ++++++++++++++++++++++++++++++++--------------------- terminal.c | 26 +++++++----- wayland.c | 6 +-- wayland.h | 3 +- 4 files changed, 91 insertions(+), 57 deletions(-) diff --git a/render.c b/render.c index 91dac6a8..598141ef 100644 --- a/render.c +++ b/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; diff --git a/terminal.c b/terminal.c index b568731c..fe8860ad 100644 --- a/terminal.c +++ b/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); } diff --git a/wayland.c b/wayland.c index 1987c72a..140c3de9 100644 --- a/wayland.c +++ b/wayland.c @@ -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) { diff --git a/wayland.h b/wayland.h index 243df207..617e8185 100644 --- a/wayland.h +++ b/wayland.h @@ -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];