diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c12f766..c68ac569 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -188,6 +188,7 @@ * Window title not being updated while window is hidden (https://codeberg.org/dnkl/foot/issues/591). * Crash on badly formatted URIs in e.g. OSC-8 URLs. +* Window being incorrectly resized on CSD/SSD run-time changes. ### Security diff --git a/quirks.c b/quirks.c index 61b6d046..e4fe4a1f 100644 --- a/quirks.c +++ b/quirks.c @@ -46,7 +46,7 @@ quirk_weston_subsurface_desync_off(struct wl_subsurface *sub) void quirk_weston_csd_on(struct terminal *term) { - if (term->window->use_csd != CSD_YES) + if (term->window->csd_mode != CSD_YES) return; if (term->window->is_fullscreen) return; @@ -58,7 +58,7 @@ quirk_weston_csd_on(struct terminal *term) void quirk_weston_csd_off(struct terminal *term) { - if (term->window->use_csd != CSD_YES) + if (term->window->csd_mode != CSD_YES) return; if (term->window->is_fullscreen) return; diff --git a/render.c b/render.c index a1f9ee79..f96ddb9e 100644 --- a/render.c +++ b/render.c @@ -1454,7 +1454,7 @@ struct csd_data { static struct csd_data get_csd_data(const struct terminal *term, enum csd_surface surf_idx) { - xassert(term->window->use_csd == CSD_YES); + xassert(term->window->csd_mode == CSD_YES); /* Only title bar is rendered in maximized mode */ const int border_width = !term->window->is_maximized @@ -1513,7 +1513,7 @@ render_csd_part(struct terminal *term, struct wl_surface *surf, struct buffer *buf, int width, int height, pixman_color_t *color) { - xassert(term->window->use_csd == CSD_YES); + xassert(term->window->csd_mode == CSD_YES); pixman_image_t *src = pixman_image_create_solid_fill(color); @@ -1526,7 +1526,7 @@ render_csd_part(struct terminal *term, static void render_csd_title(struct terminal *term) { - xassert(term->window->use_csd == CSD_YES); + xassert(term->window->csd_mode == CSD_YES); struct csd_data info = get_csd_data(term, CSD_SURF_TITLE); struct wl_surface *surf = term->window->csd.surface[CSD_SURF_TITLE].surf; @@ -1559,7 +1559,7 @@ render_csd_title(struct terminal *term) static void render_csd_border(struct terminal *term, enum csd_surface surf_idx) { - xassert(term->window->use_csd == CSD_YES); + xassert(term->window->csd_mode == CSD_YES); xassert(surf_idx >= CSD_SURF_LEFT && surf_idx <= CSD_SURF_BOTTOM); struct csd_data info = get_csd_data(term, surf_idx); @@ -1745,7 +1745,7 @@ render_csd_button_close(struct terminal *term, struct buffer *buf) static void render_csd_button(struct terminal *term, enum csd_surface surf_idx) { - xassert(term->window->use_csd == CSD_YES); + xassert(term->window->csd_mode == CSD_YES); xassert(surf_idx >= CSD_SURF_MINIMIZE && surf_idx <= CSD_SURF_CLOSE); struct csd_data info = get_csd_data(term, surf_idx); @@ -1827,7 +1827,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx) static void render_csd(struct terminal *term) { - xassert(term->window->use_csd == CSD_YES); + xassert(term->window->csd_mode == CSD_YES); if (term->window->is_fullscreen) return; @@ -3019,7 +3019,7 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da term->grid = term->url_grid_snapshot; } - if (csd && term->window->use_csd == CSD_YES) { + if (csd && term->window->csd_mode == CSD_YES) { quirk_weston_csd_on(term); render_csd(term); quirk_weston_csd_off(term); @@ -3168,7 +3168,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) width = term->conf->size.width; height = term->conf->size.height; - if (term->window->use_csd == CSD_YES) { + if (term->window->csd_mode == CSD_YES) { /* Take CSD title bar into account */ xassert(!term->window->is_fullscreen); height -= term->conf->csd.title_height; @@ -3338,7 +3338,7 @@ damage_view: { bool title_shown = !term->window->is_fullscreen && - term->window->use_csd == CSD_YES; + term->window->csd_mode == CSD_YES; int title_height = title_shown ? term->conf->csd.title_height : 0; xdg_surface_set_window_geometry( @@ -3476,7 +3476,7 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) term->grid = term->url_grid_snapshot; } - if (csd && term->window->use_csd == CSD_YES) { + if (csd && term->window->csd_mode == CSD_YES) { quirk_weston_csd_on(term); render_csd(term); quirk_weston_csd_off(term); @@ -3549,7 +3549,7 @@ render_refresh(struct terminal *term) void render_refresh_csd(struct terminal *term) { - if (term->window->use_csd == CSD_YES) + if (term->window->csd_mode == CSD_YES) term->render.refresh.csd = true; } diff --git a/wayland.c b/wayland.c index 99285db3..301760d8 100644 --- a/wayland.c +++ b/wayland.c @@ -597,14 +597,6 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, */ struct wl_window *win = data; - if (!is_fullscreen && win->use_csd == CSD_YES && width > 0 && height > 0) { - /* - * We include the CSD title bar in our window geometry. Thus, - * the height we call render_resize() with must be adjusted, - * since it expects the size to refer to the main grid only. - */ - height -= win->term->conf->csd.title_height; - } win->configure.is_activated = is_activated; win->configure.is_fullscreen = is_fullscreen; win->configure.is_maximized = is_maximized; @@ -642,23 +634,32 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, bool wasnt_configured = !win->is_configured; bool was_resizing = win->is_resizing; + bool csd_was_enabled = win->csd_mode == CSD_YES && !win->is_fullscreen; + int new_width = win->configure.width; + int new_height = win->configure.height; win->is_configured = true; win->is_maximized = win->configure.is_maximized; + win->is_fullscreen = win->configure.is_fullscreen; win->is_resizing = win->configure.is_resizing; win->is_tiled_top = win->configure.is_tiled_top; win->is_tiled_bottom = win->configure.is_tiled_bottom; win->is_tiled_left = win->configure.is_tiled_left; win->is_tiled_right = win->configure.is_tiled_right; - win->is_tiled = win->is_tiled_top || win->is_tiled_bottom || win->is_tiled_left || win->is_tiled_right; + win->is_tiled = (win->is_tiled_top || + win->is_tiled_bottom || + win->is_tiled_left || + win->is_tiled_right); + win->csd_mode = win->configure.csd_mode; - if (win->is_fullscreen != win->configure.is_fullscreen && win->use_csd == CSD_YES) { - if (win->configure.is_fullscreen) - csd_destroy(win); - else - csd_instantiate(win); - } - win->is_fullscreen = win->configure.is_fullscreen; + bool enable_csd = win->csd_mode == CSD_YES && !win->is_fullscreen; + if (!csd_was_enabled && enable_csd) + csd_instantiate(win); + else if (csd_was_enabled && !enable_csd) + csd_destroy(win); + + if (enable_csd && new_width > 0 && new_height > 0) + new_height -= win->term->conf->csd.title_height; xdg_surface_ack_configure(xdg_surface, serial); @@ -713,10 +714,10 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, * the last, forced, resize *is* necessary. */ bool resized = was_resizing && !win->is_resizing - ? render_resize_force(term, win->configure.width, win->configure.height) - : render_resize(term, win->configure.width, win->configure.height); + ? render_resize_force(term, new_width, new_height) + : render_resize(term, new_width, new_height); #else - bool resized = render_resize(term, win->configure.width, win->configure.height); + bool resized = render_resize(term, new_width, new_height); #endif if (win->configure.is_activated) @@ -752,32 +753,18 @@ xdg_toplevel_decoration_configure(void *data, switch (mode) { case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE: LOG_INFO("using CSD decorations"); - win->use_csd = CSD_YES; - csd_instantiate(win); + win->configure.csd_mode = CSD_YES; break; case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE: LOG_INFO("using SSD decorations"); - win->use_csd = CSD_NO; - csd_destroy(win); + win->configure.csd_mode = CSD_NO; break; default: LOG_ERR("unimplemented: unknown XDG toplevel decoration mode: %u", mode); break; } - - if (win->is_configured && win->use_csd == CSD_YES) { - struct terminal *term = win->term; - - int scale = term->scale; - int width = term->width / scale; - int height = term->height / scale; - - /* Take CSD title bar into account */ - height -= term->conf->csd.title_height; - render_resize_force(term, width, height); - } } static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener = { @@ -1345,7 +1332,7 @@ wayl_win_init(struct terminal *term) } win->term = term; - win->use_csd = CSD_UNKNOWN; + win->csd_mode = CSD_UNKNOWN; win->csd.move_timeout_fd = -1; win->resize_timeout_fd = -1; @@ -1378,7 +1365,7 @@ wayl_win_init(struct terminal *term) if (conf->csd.preferred == CONF_CSD_PREFER_NONE) { /* User specifically do *not* want decorations */ - win->use_csd = CSD_NO; + win->csd_mode = CSD_NO; LOG_INFO("window decorations disabled by user"); } else if (wayl->xdg_decoration_manager != NULL) { win->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( @@ -1397,7 +1384,7 @@ wayl_win_init(struct terminal *term) win->xdg_toplevel_decoration, &xdg_toplevel_decoration_listener, win); } else { /* No decoration manager - thus we *must* draw our own decorations */ - win->use_csd = CSD_YES; + win->csd_mode = CSD_YES; csd_instantiate(win); LOG_WARN("no decoration manager available - using CSDs unconditionally"); } diff --git a/wayland.h b/wayland.h index 6021497f..f62819a4 100644 --- a/wayland.h +++ b/wayland.h @@ -384,6 +384,8 @@ struct wl_url { struct wl_surf_subsurf surf; }; +enum csd_mode {CSD_UNKNOWN, CSD_NO, CSD_YES}; + struct wayland; struct wl_window { struct terminal *term; @@ -396,7 +398,7 @@ struct wl_window { struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; - enum {CSD_UNKNOWN, CSD_NO, CSD_YES } use_csd; + enum csd_mode csd_mode; struct { struct wl_surf_subsurf surface[CSD_SURF_COUNT]; @@ -433,6 +435,7 @@ struct wl_window { bool is_tiled_bottom:1; bool is_tiled_left:1; bool is_tiled_right:1; + enum csd_mode csd_mode; } configure; int resize_timeout_fd;