From d1df98e0cac70fb61d68acfe2412f10102e80441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 14 Jul 2023 12:40:55 +0200 Subject: [PATCH 01/28] =?UTF-8?q?changelog:=20add=20new=20=E2=80=98unrelea?= =?UTF-8?q?sed=E2=80=99=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 206b3d52..b5d21bd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +* [Unreleased](#unreleased) * [1.15.0](#1-15-0) * [1.14.0](#1-14-0) * [1.13.1](#1-13-1) @@ -42,6 +43,16 @@ * [1.2.0](#1-2-0) +## Unreleased +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security +### Contributors + + ## 1.15.0 ### Added From b7100d57160d2ae7a38d5517f1c2cd7155737d88 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 14 Jul 2023 16:53:50 -0700 Subject: [PATCH 02/28] render: use rounding for fractional scale If we truncate the buffer dimensions we may accidentally submit a buffer with inappropriate size. --- CHANGELOG.md | 3 +++ render.c | 4 ++-- terminal.c | 5 ++++- wayland.c | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5d21bd6..5a1eaaa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,9 @@ ### Deprecated ### Removed ### Fixed + +* Use appropriate rounding when applying fractional scales. + ### Security ### Contributors diff --git a/render.c b/render.c index 677856d8..d084a859 100644 --- a/render.c +++ b/render.c @@ -3856,8 +3856,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force) scale = term->scale; } - width *= scale; - height *= scale; + width = round(width * scale); + height = round(height * scale); if (width == 0 && height == 0) { /* diff --git a/terminal.c b/terminal.c index fff55019..485e8ca3 100644 --- a/terminal.c +++ b/terminal.c @@ -778,7 +778,10 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) sixel_cell_size_changed(term); /* Use force, since cell-width/height may have changed */ - render_resize_force(term, term->width / term->scale, term->height / term->scale); + render_resize_force( + term, + round(term->width / term->scale), + round(term->height / term->scale)); return true; } diff --git a/wayland.c b/wayland.c index a25ec0f6..9195797e 100644 --- a/wayland.c +++ b/wayland.c @@ -401,7 +401,9 @@ update_term_for_output_change(struct terminal *term) float old_scale = term->scale; - render_resize(term, term->width / term->scale, term->height / term->scale); + render_resize(term, + round(term->width / term->scale), + round(term->height / term->scale)); term_font_dpi_changed(term, old_scale); term_font_subpixel_changed(term); csd_reload_font(term->window, old_scale); From 8b4cb2457aa5b90d265f59207b4b592ba6adebbc Mon Sep 17 00:00:00 2001 From: CismonX Date: Sun, 16 Jul 2023 17:24:55 +0800 Subject: [PATCH 03/28] input: do not ignore touch events on the CSDs --- input.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/input.c b/input.c index b2b4adf6..53d7acf8 100644 --- a/input.c +++ b/input.c @@ -2739,8 +2739,6 @@ wl_touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial, struct terminal *term = win->term; term->active_surface = term_surface_kind(term, surface); - if (term->active_surface != TERM_SURF_GRID) - return; LOG_DBG("touch_down: touch=%p, x=%d, y=%d", (void *)wl_touch, wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); @@ -2785,6 +2783,7 @@ wl_touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, WL_POINTER_BUTTON_STATE_RELEASED); /* fallthrough */ case TOUCH_STATE_SCROLLING: + term->active_surface = TERM_SURF_NONE; seat->touch.state = TOUCH_STATE_IDLE; break; @@ -2815,7 +2814,7 @@ wl_touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, switch (seat->touch.state) { case TOUCH_STATE_HELD: - if (time <= seat->touch.time) { + if (time <= seat->touch.time && term->active_surface == TERM_SURF_GRID) { if (touch_to_scroll(seat, term, surface_x, surface_y)) seat->touch.state = TOUCH_STATE_SCROLLING; break; From 6de69aa9b726c2e270455ac44a7b8d5177b7332e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 20:08:34 +0200 Subject: [PATCH 04/28] render: fix xcursor scaling with fractional-scale-v1 This worked just after the fractional-scaling branch was merged, but was then broken by the cursor-shape branch, due to a bad rebase of that branch. --- CHANGELOG.md | 3 +++ render.c | 12 +++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a1eaaa5..812e483a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,9 @@ ### Fixed * Use appropriate rounding when applying fractional scales. +* Xcursor not being scaled correctly on `fractional-scale-v1` capable + compositors. + ### Security ### Contributors diff --git a/render.c b/render.c index d084a859..c40d07d0 100644 --- a/render.c +++ b/render.c @@ -4297,11 +4297,15 @@ render_xcursor_update(struct seat *seat) LOG_DBG("setting %scursor shape using a client-side cursor surface", shape == CURSOR_SHAPE_CUSTOM ? "custom " : ""); - const int scale = seat->pointer.scale; + const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; + struct wl_buffer *buf = wl_cursor_image_get_buffer(image); - wl_surface_attach( - seat->pointer.surface.surf, wl_cursor_image_get_buffer(image), 0, 0); + wayl_surface_scale_explicit_width_height( + seat->mouse_focus->window, + &seat->pointer.surface, image->width, image->height, scale); + + wl_surface_attach(seat->pointer.surface.surf, buf, 0, 0); wl_pointer_set_cursor( seat->wl_pointer, seat->pointer.serial, @@ -4311,8 +4315,6 @@ render_xcursor_update(struct seat *seat) wl_surface_damage_buffer( seat->pointer.surface.surf, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_set_buffer_scale(seat->pointer.surface.surf, scale); - xassert(seat->pointer.xcursor_callback == NULL); seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface.surf); wl_callback_add_listener(seat->pointer.xcursor_callback, &xcursor_listener, seat); From da81b63ec0cd51586f896f6e5f55c716cce4d9af Mon Sep 17 00:00:00 2001 From: Ayush Agarwal Date: Sat, 8 Apr 2023 03:11:10 +0530 Subject: [PATCH 05/28] themes: add chiba-dark theme --- themes/chiba-dark | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 themes/chiba-dark diff --git a/themes/chiba-dark b/themes/chiba-dark new file mode 100644 index 00000000..bc3b1420 --- /dev/null +++ b/themes/chiba-dark @@ -0,0 +1,27 @@ +# -*- conf -*- +# theme: Chiba Dark +# author: ayushnix (https://sr.ht/~ayushnix) +# description: A dark theme with bright cyberpunk colors (WCAG AAA compliant) + +[cursor] +color = 181818 cdcdcd + +[colors] +foreground = cdcdcd +background = 181818 +regular0 = 181818 +regular1 = ff8599 +regular2 = 00c545 +regular3 = de9d00 +regular4 = 00b4ff +regular5 = fd71f8 +regular6 = 00bfae +regular7 = cdcdcd +bright0 = 262626 +bright1 = ff9eb2 +bright2 = 19de5e +bright3 = f7b619 +bright4 = 19cdff +bright5 = ff8aff +bright6 = 19d8c7 +bright7 = dadada From 2fd29cbf500a5528445f82c59ac76b1762efa60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 16 Jul 2023 08:27:12 +0200 Subject: [PATCH 06/28] term: (debug): dpi_aware is no longer an enum --- terminal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/terminal.c b/terminal.c index 485e8ca3..213d8c59 100644 --- a/terminal.c +++ b/terminal.c @@ -2099,8 +2099,7 @@ term_font_dpi_changed(struct terminal *term, int old_scale) LOG_DBG("DPI/scale change: DPI-awareness=%s, " "DPI: %.2f -> %.2f, scale: %d -> %d, " "sizing font based on monitor's %s", - term->conf->dpi_aware == DPI_AWARE_AUTO ? "auto" : - term->conf->dpi_aware == DPI_AWARE_YES ? "yes" : "no", + term->conf->dpi_aware ? "yes" : "no", term->font_dpi, dpi, old_scale, term->scale, will_scale_using_dpi ? "DPI" : "scaling factor"); } From 829353a5dad410ce9b6b1ca78f9d86beedc3a90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 16 Jul 2023 08:28:21 +0200 Subject: [PATCH 07/28] term: font_dpi_changed: scale (and old_scale) are floating point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should fix an issue where the font size wasn’t updated when moving the window between outputs whose scaling factors match when truncated. --- terminal.c | 8 ++++---- terminal.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/terminal.c b/terminal.c index 213d8c59..e15e647e 100644 --- a/terminal.c +++ b/terminal.c @@ -1298,7 +1298,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, goto err; /* Load fonts */ - if (!term_font_dpi_changed(term, 0)) + if (!term_font_dpi_changed(term, 0.)) goto err; term->font_subpixel = get_font_subpixel(term); @@ -2081,10 +2081,10 @@ term_font_size_reset(struct terminal *term) } bool -term_font_dpi_changed(struct terminal *term, int old_scale) +term_font_dpi_changed(struct terminal *term, float old_scale) { float dpi = get_font_dpi(term); - xassert(term->scale > 0); + xassert(term->scale > 0.); bool was_scaled_using_dpi = term->font_is_sized_by_dpi; bool will_scale_using_dpi = term->conf->dpi_aware; @@ -2097,7 +2097,7 @@ term_font_dpi_changed(struct terminal *term, int old_scale) if (need_font_reload) { LOG_DBG("DPI/scale change: DPI-awareness=%s, " - "DPI: %.2f -> %.2f, scale: %d -> %d, " + "DPI: %.2f -> %.2f, scale: %.2f -> %.2f, " "sizing font based on monitor's %s", term->conf->dpi_aware ? "yes" : "no", term->font_dpi, dpi, old_scale, term->scale, diff --git a/terminal.h b/terminal.h index 6dace7ac..60d3c3ac 100644 --- a/terminal.h +++ b/terminal.h @@ -739,7 +739,7 @@ bool term_paste_data_to_slave( bool term_font_size_increase(struct terminal *term); bool term_font_size_decrease(struct terminal *term); bool term_font_size_reset(struct terminal *term); -bool term_font_dpi_changed(struct terminal *term, int old_scale); +bool term_font_dpi_changed(struct terminal *term, float old_scale); void term_font_subpixel_changed(struct terminal *term); int term_pt_or_px_as_pixels( From 59f0a721c4663aafd30179e34a38165dd137a0db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 16:12:34 +0200 Subject: [PATCH 08/28] wayland: fractional_scale_preferred_scale(): only push update if scale has changed Also, drop wl_window::have_preferred_scale. Check for scale > 0 instead. --- wayland.c | 13 +++++++++---- wayland.h | 1 - 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/wayland.c b/wayland.c index 9195797e..f6ded585 100644 --- a/wayland.c +++ b/wayland.c @@ -1603,10 +1603,15 @@ static void fractional_scale_preferred_scale( uint32_t scale) { struct wl_window *win = data; - win->scale = (float)scale / 120.; - win->have_preferred_scale = true; - LOG_DBG("fractional scale: %.3f", win->scale); + const float new_scale = (float)scale / 120.; + + if (win->scale == new_scale) + return; + + LOG_DBG("fractional scale: %.2f -> %.2f", win->scale, new_scale); + + win->scale = new_scale; update_term_for_output_change(win->term); } @@ -1971,7 +1976,7 @@ wayl_surface_scale_explicit_width_height( int width, int height, float scale) { - if (wayl_fractional_scaling(win->term->wl) && win->have_preferred_scale) { + if (wayl_fractional_scaling(win->term->wl) && win->scale > 0.) { #if defined(HAVE_FRACTIONAL_SCALE) LOG_DBG("scaling by a factor of %.2f using fractional scaling " "(width=%d, height=%d) ", scale, width, height); diff --git a/wayland.h b/wayland.h index 6d1cd727..9e581b20 100644 --- a/wayland.h +++ b/wayland.h @@ -374,7 +374,6 @@ struct wl_window { bool unmapped; float scale; - bool have_preferred_scale; struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; From b2a29280cbd3fcd825123e7636d511a06b2df242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 16:19:14 +0200 Subject: [PATCH 09/28] wayland: use physical DPI on fractional-scale capable compositors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With legacy scaling, we need to use a "scaled", or "logical" DPI value, that is basically the real DPI value scaled by the monitor’s scaling factor. This is necessary to compensate for the compositor downscaling the surface, for "fake" fractional scaling. But with true fractional scaling, *we* scale the surface to the final size. This means we should *not* use the scaled DPI, but the monitor’s actual DPI. To facilitate this, store both the scaled and the unscaled DPI value in the monitor struct. This patch also changes how we pick the DPI value. Before, we would use the highest DPI value from all the monitors we were mapped on. Now, we use the DPI value from the monitor we were *last* mapped on (typically the window we’re dragging the window *to*). --- terminal.c | 55 +++++++++++++++++++++++------------------------------- wayland.c | 46 +++++++++++++++++++++++++++------------------ wayland.h | 5 ++++- 3 files changed, 55 insertions(+), 51 deletions(-) diff --git a/terminal.c b/terminal.c index e15e647e..a557d632 100644 --- a/terminal.c +++ b/terminal.c @@ -796,41 +796,34 @@ get_font_dpi(const struct terminal *term) * Conceptually, we use the physical monitor specs to calculate * the DPI, and we ignore the output's scaling factor. * - * However, to deal with fractional scaling, where we're told to - * render at e.g. 2x, but are then downscaled by the compositor to - * e.g. 1.25, we use the scaled DPI value multiplied by the scale - * factor instead. + * However, to deal with legacy fractional scaling, where we're + * told to render at e.g. 2x, but are then downscaled by the + * compositor to e.g. 1.25, we use the scaled DPI value multiplied + * by the scale factor instead. * * For integral scaling factors the resulting DPI is the same as * if we had used the physical DPI. * - * For fractional scaling factors we'll get a DPI *larger* than - * the physical DPI, that ends up being right when later + * For legacy fractional scaling factors we'll get a DPI *larger* + * than the physical DPI, that ends up being right when later * downscaled by the compositor. + * + * With the newer fractional-scale-v1 protocol, we use the + * monitor’s real DPI, since we scale everything to the correct + * scaling factor (no downscaling done by the compositor). */ - /* Use highest DPI from outputs we're mapped on */ - double dpi = 0.0; - xassert(term->window != NULL); - tll_foreach(term->window->on_outputs, it) { - if (it->item->dpi > dpi) - dpi = it->item->dpi; - } + xassert(tll_length(term->wl->monitors) > 0); - /* If we're not mapped, use DPI from first monitor. Hopefully this is where we'll get mapped later... */ - if (dpi == 0.) { - tll_foreach(term->wl->monitors, it) { - dpi = it->item.dpi; - break; - } - } + const struct wl_window *win = term->window; + const struct monitor *mon = tll_length(win->on_outputs) > 0 + ? tll_back(win->on_outputs) + : &tll_front(term->wl->monitors); - if (dpi == 0) { - /* No monitors? */ - dpi = 96.; - } - - return dpi; + if (wayl_fractional_scaling(term->wl)) + return mon->dpi.physical; + else + return mon->dpi.scaled; } static enum fcft_subpixel @@ -1285,11 +1278,9 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, reaper_add(term->reaper, term->slave, &fdm_client_terminated, term); /* Guess scale; we're not mapped yet, so we don't know on which - * output we'll be. Pick highest scale we find for now */ - tll_foreach(term->wl->monitors, it) { - if (it->item.scale > term->scale) - term->scale = it->item.scale; - } + * output we'll be. Use scaling factor from first monitor */ + xassert(tll_length(term->wl->monitors) > 0); + term->scale = tll_front(term->wl->monitors).scale; memcpy(term->colors.table, term->conf->colors.table, sizeof(term->colors.table)); @@ -2096,7 +2087,7 @@ term_font_dpi_changed(struct terminal *term, float old_scale) : old_scale != term->scale); if (need_font_reload) { - LOG_DBG("DPI/scale change: DPI-awareness=%s, " + LOG_DBG("DPI/scale change: DPI-aware=%s, " "DPI: %.2f -> %.2f, scale: %.2f -> %.2f, " "sizing font based on monitor's %s", term->conf->dpi_aware ? "yes" : "no", diff --git a/wayland.c b/wayland.c index f6ded585..c4f9e402 100644 --- a/wayland.c +++ b/wayland.c @@ -435,6 +435,9 @@ output_update_ppi(struct monitor *mon) double x_inches = mon->dim.mm.width * 0.03937008; double y_inches = mon->dim.mm.height * 0.03937008; + const int width = mon->dim.px_real.width; + const int height = mon->dim.px_real.height; + mon->ppi.real.x = mon->dim.px_real.width / x_inches; mon->ppi.real.y = mon->dim.px_real.height / y_inches; @@ -457,27 +460,36 @@ output_update_ppi(struct monitor *mon) break; } - int scaled_width = mon->dim.px_scaled.width; - int scaled_height = mon->dim.px_scaled.height; - - if (scaled_width == 0 && scaled_height == 0 && mon->scale > 0) { - /* Estimate scaled width/height if none has been provided */ - scaled_width = mon->dim.px_real.width / mon->scale; - scaled_height = mon->dim.px_real.height / mon->scale; - } + const int scaled_width = mon->dim.px_scaled.width; + const int scaled_height = mon->dim.px_scaled.height; mon->ppi.scaled.x = scaled_width / x_inches; mon->ppi.scaled.y = scaled_height / y_inches; - double px_diag = sqrt(pow(scaled_width, 2) + pow(scaled_height, 2)); - mon->dpi = px_diag / mon->inch * mon->scale; + const double px_diag_physical = sqrt(pow(width, 2) + pow(height, 2)); + mon->dpi.physical = width == 0 && height == 0 + ? 96. + : px_diag_physical / mon->inch; - if (mon->dpi > 1000) { + const double px_diag_scaled = sqrt(pow(scaled_width, 2) + pow(scaled_height, 2)); + mon->dpi.scaled = scaled_width == 0 && scaled_height == 0 + ? 96. + : px_diag_scaled / mon->inch * mon->scale; + + if (mon->dpi.physical > 1000) { if (mon->name != NULL) { - LOG_WARN("%s: DPI=%f is unreasonable, using 96 instead", - mon->name, mon->dpi); + LOG_WARN("%s: DPI=%f (physical) is unreasonable, using 96 instead", + mon->name, mon->dpi.physical); } - mon->dpi = 96; + mon->dpi.physical = 96; + } + + if (mon->dpi.scaled > 1000) { + if (mon->name != NULL) { + LOG_WARN("%s: DPI=%f (logical) is unreasonable, using 96 instead", + mon->name, mon->dpi.scaled); + } + mon->dpi.scaled = 96; } } @@ -1487,14 +1499,12 @@ wayl_init(struct fdm *fdm, struct key_binding_manager *key_binding_manager, tll_foreach(wayl->monitors, it) { LOG_INFO( - "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical), DPI=%.2f", + "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d, DPI=%.2f/%.2f (physical/scaled)", it->item.name, it->item.dim.px_real.width, it->item.dim.px_real.height, it->item.x, it->item.y, (int)round(it->item.refresh), it->item.model != NULL ? it->item.model : it->item.description, it->item.inch, it->item.scale, - it->item.ppi.real.x, it->item.ppi.real.y, - it->item.ppi.scaled.x, it->item.ppi.scaled.y, - it->item.dpi); + it->item.dpi.physical, it->item.dpi.scaled); } wayl->fd = wl_display_get_fd(wayl->display); diff --git a/wayland.h b/wayland.h index 9e581b20..275338a8 100644 --- a/wayland.h +++ b/wayland.h @@ -315,7 +315,10 @@ struct monitor { } scaled; } ppi; - float dpi; + struct { + float scaled; + float physical; + } dpi; int scale; float refresh; From c96863b1882088271dd9867c4fd258a9a5fa6a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 16:19:21 +0200 Subject: [PATCH 10/28] =?UTF-8?q?wayland:=20error=20out=20if=20there=20are?= =?UTF-8?q?n=E2=80=99t=20any=20monitors=20available?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wayland.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wayland.c b/wayland.c index c4f9e402..85140d6f 100644 --- a/wayland.c +++ b/wayland.c @@ -1447,6 +1447,11 @@ wayl_init(struct fdm *fdm, struct key_binding_manager *key_binding_manager, LOG_ERR("no seats available (wl_seat interface too old?)"); goto out; } + if (tll_length(wayl->monitors) == 0) { + LOG_ERR("no monitors available"); + goto out; + } + if (wayl->primary_selection_device_manager == NULL) LOG_WARN("no primary selection available"); From 21d99f8dced335826964ca96b8ba7ccac059e598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 16:21:16 +0200 Subject: [PATCH 11/28] terminal: break out scaling factor updating, and reduce number of calls to render_resize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Break out the logic that updates the terminal’s scaling factor value, from render_resize(), to a new function, term_update_scale(). This allows us to update the scaling factor without a full grid resize. We also change how we pick the scaling factor (when fractional scaling is not in use). Before, we’d use the highest scaling factor from all monitors we were mapped on. Now, we use the scaling factor from the monitor we were *last* mapped on. Then, add a boolean parameter to term_set_fonts(), and when false, *don’t* call render_resize_force(). Also change term_font_dpi_changed() to only return true if the font was changed in any way. Finally, rewrite update_term_for_output_change() to: * Call term_update_scale() before doing anything else * Call render_resize{,_force} *last*, and *only* if either the scale or the fonts were updated. This fixes several things: * A bug where we failed to update the fonts when fractional scaling was in use, and we guessed the initial scale/DPI wrong. The bug happened because updated the internal "preferred" scale value, and a later call to render_resize() updated the terminal’s scale value, but since that code path didn’t call term_font_dpi_changed() (and it shouldn’t), the fonts weren’t resized properly. * It ensures we only resize the grid *once* when the scaling factor, or DPI is changed. Before this, we’d resize it twice. And this happened when e.g. dragging the window between monitors. --- render.c | 29 ++++++------------------ terminal.c | 65 +++++++++++++++++++++++++++++++++++++++++------------- terminal.h | 1 + wayland.c | 34 +++++++++++++++++++++------- 4 files changed, 84 insertions(+), 45 deletions(-) diff --git a/render.c b/render.c index c40d07d0..11149b16 100644 --- a/render.c +++ b/render.c @@ -3841,21 +3841,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) if (term->cell_width == 0 && term->cell_height == 0) return false; - float scale = -1; - if (wayl_fractional_scaling(term->wl)) { - scale = term->window->scale; - } else { - tll_foreach(term->window->on_outputs, it) { - if (it->item->scale > scale) - scale = it->item->scale; - } - } - - if (scale < 0.) { - /* Haven't 'entered' an output yet? */ - scale = term->scale; - } - + const float scale = term->scale; width = round(width * scale); height = round(height * scale); @@ -3942,9 +3928,9 @@ maybe_resize(struct terminal *term, int width, int height, bool force) /* Drop out of URL mode */ urls_reset(term); + LOG_DBG("resized: size=%dx%d (scale=%.2f)", width, height, term->scale); term->width = width; term->height = height; - term->scale = scale; const uint32_t scrollback_lines = term->render.scrollback_lines; @@ -4148,12 +4134,11 @@ maybe_resize(struct terminal *term, int width, int height, bool force) sixel_reflow(term); -#if defined(_DEBUG) && LOG_ENABLE_DBG - LOG_DBG("resize: %dx%d, grid: cols=%d, rows=%d " + LOG_DBG("resized: grid: cols=%d, rows=%d " "(left-margin=%d, right-margin=%d, top-margin=%d, bottom-margin=%d)", - term->width, term->height, term->cols, term->rows, - term->margins.left, term->margins.right, term->margins.top, term->margins.bottom); -#endif + term->cols, term->rows, + term->margins.left, term->margins.right, + term->margins.top, term->margins.bottom); if (term->scroll_region.start >= term->rows) term->scroll_region.start = 0; @@ -4295,7 +4280,7 @@ render_xcursor_update(struct seat *seat) #endif LOG_DBG("setting %scursor shape using a client-side cursor surface", - shape == CURSOR_SHAPE_CUSTOM ? "custom " : ""); + seat->pointer.shape == CURSOR_SHAPE_CUSTOM ? "custom " : ""); const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; diff --git a/terminal.c b/terminal.c index a557d632..86cb365a 100644 --- a/terminal.c +++ b/terminal.c @@ -733,7 +733,8 @@ term_line_height_update(struct terminal *term) } static bool -term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) +term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4], + bool resize_grid) { for (size_t i = 0; i < 4; i++) { xassert(fonts[i] != NULL); @@ -777,11 +778,15 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) sixel_cell_size_changed(term); - /* Use force, since cell-width/height may have changed */ - render_resize_force( - term, - round(term->width / term->scale), - round(term->height / term->scale)); + /* Optimization - some code paths (are forced to) call + * render_resize() after this function */ + if (resize_grid) { + /* Use force, since cell-width/height may have changed */ + render_resize_force( + term, + round(term->width / term->scale), + round(term->height / term->scale)); + } return true; } @@ -899,7 +904,7 @@ font_loader_thread(void *_data) } static bool -reload_fonts(struct terminal *term) +reload_fonts(struct terminal *term, bool resize_grid) { const struct config *conf = term->conf; @@ -1026,7 +1031,7 @@ reload_fonts(struct terminal *term) } } - return success ? term_set_fonts(term, fonts) : success; + return success ? term_set_fonts(term, fonts, resize_grid) : success; } static bool @@ -1044,7 +1049,7 @@ load_fonts_from_conf(struct terminal *term) } } - return reload_fonts(term); + return reload_fonts(term, true); } static void fdm_client_terminated( @@ -1987,7 +1992,7 @@ term_font_size_adjust_by_points(struct terminal *term, float amount) } } - return reload_fonts(term); + return reload_fonts(term, true); } static bool @@ -2010,7 +2015,7 @@ term_font_size_adjust_by_pixels(struct terminal *term, int amount) } } - return reload_fonts(term); + return reload_fonts(term, true); } static bool @@ -2034,7 +2039,7 @@ term_font_size_adjust_by_percent(struct terminal *term, bool increment, float pe } } - return reload_fonts(term); + return reload_fonts(term, true); } bool @@ -2071,6 +2076,36 @@ term_font_size_reset(struct terminal *term) return load_fonts_from_conf(term); } +bool +term_update_scale(struct terminal *term) +{ + const struct wl_window *win = term->window; + + /* + * We have a number of “sources” we can use as scale. We choose + * the scale in the following order: + * + * - “preferred” scale, from the fractional-scale-v1 protocol + * - scaling factor of output we most recently were mapped on + * - if we’re not mapped, use the scaling factor from the first + * available output. + * - if there aren’t any outputs available, use 1.0 + */ + const float new_scale = + (wayl_fractional_scaling(term->wl) && win->scale > 0. + ? win->scale + : (tll_length(win->on_outputs) > 0 + ? tll_back(win->on_outputs)->scale + : 1.)); + + if (new_scale == term->scale) + return false; + + LOG_DBG("scaling factor changed: %.2f -> %.2f", term->scale, new_scale); + term->scale = new_scale; + return true; +} + bool term_font_dpi_changed(struct terminal *term, float old_scale) { @@ -2099,9 +2134,9 @@ term_font_dpi_changed(struct terminal *term, float old_scale) term->font_is_sized_by_dpi = will_scale_using_dpi; if (!need_font_reload) - return true; + return false; - return reload_fonts(term); + return reload_fonts(term, false); } void @@ -3500,7 +3535,7 @@ term_update_ascii_printer(struct terminal *term) #if defined(_DEBUG) && LOG_ENABLE_DBG if (term->ascii_printer != new_printer) { - LOG_DBG("§switching ASCII printer %s -> %s", + LOG_DBG("switching ASCII printer %s -> %s", term->ascii_printer == &ascii_printer_fast ? "fast" : "generic", new_printer == &ascii_printer_fast ? "fast" : "generic"); } diff --git a/terminal.h b/terminal.h index 60d3c3ac..4b1d1d0d 100644 --- a/terminal.h +++ b/terminal.h @@ -736,6 +736,7 @@ bool term_to_slave(struct terminal *term, const void *data, size_t len); bool term_paste_data_to_slave( struct terminal *term, const void *data, size_t len); +bool term_update_scale(struct terminal *term); bool term_font_size_increase(struct terminal *term); bool term_font_size_decrease(struct terminal *term); bool term_font_size_reset(struct terminal *term); diff --git a/wayland.c b/wayland.c index 85140d6f..354a0e78 100644 --- a/wayland.c +++ b/wayland.c @@ -396,17 +396,35 @@ static const struct wl_seat_listener seat_listener = { static void update_term_for_output_change(struct terminal *term) { - if (tll_length(term->window->on_outputs) == 0) - return; + const float old_scale = term->scale; + const float logical_width = term->width / term->scale; + const float logical_height = term->height / term->scale; - float old_scale = term->scale; - - render_resize(term, - round(term->width / term->scale), - round(term->height / term->scale)); - term_font_dpi_changed(term, old_scale); + /* Note: order matters! term_update_scale() must come first */ + bool scale_updated = term_update_scale(term); + bool fonts_updated = term_font_dpi_changed(term, old_scale); term_font_subpixel_changed(term); + csd_reload_font(term->window, old_scale); + + if (fonts_updated) { + /* + * If the fonts have been updated, the cell dimensions have + * changed. This requires a “forced” resize, since the surface + * buffer dimensions may not have been updated (in which case + * render_size() normally shortcuts and returns early). + */ + render_resize_force(term, round(logical_width), round(logical_height)); + } + + else if (scale_updated) { + /* + * A scale update means the surface buffer dimensions have + * been updated, even though the window logical dimensions + * haven’t changed. + */ + render_resize(term, round(logical_width), round(logical_height)); + } } static void From 7fca81dd3fd3cfd5ee6caafacfb61fd19adb0dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 16:28:10 +0200 Subject: [PATCH 12/28] term: get_font_subpixel(): use subpixel from monitor we were *last* mapped on --- terminal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/terminal.c b/terminal.c index 86cb365a..2f0e632c 100644 --- a/terminal.c +++ b/terminal.c @@ -847,7 +847,8 @@ get_font_subpixel(const struct terminal *term) * output or not. * * Thus, when determining which subpixel mode to use, we can't do - * much but select *an* output. So, we pick the first one. + * much but select *an* output. So, we pick the one we were most + * recently mapped on. * * If we're not mapped at all, we pick the first available * monitor, and hope that's where we'll eventually get mapped. @@ -857,7 +858,7 @@ get_font_subpixel(const struct terminal *term) */ if (tll_length(term->window->on_outputs) > 0) - wl_subpixel = tll_front(term->window->on_outputs)->subpixel; + wl_subpixel = tll_back(term->window->on_outputs)->subpixel; else if (tll_length(term->wl->monitors) > 0) wl_subpixel = tll_front(term->wl->monitors).subpixel; else From 5b3b89cb64cb9fb2731fdb828bdc01086432b002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 16:31:37 +0200 Subject: [PATCH 13/28] changelog: monitor metadata is now picked from the one we were last mapped on --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 812e483a..ca9051b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,12 @@ ## Unreleased ### Added ### Changed + +* When window is mapped, use metadata (DPI, scaling factor, subpixel + configuration) from the monitor we were most recently mapped on, + instead of the one least recently. + + ### Deprecated ### Removed ### Fixed From df96b7f4c0bbd69958615b60aaae36611b90a274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 16:31:54 +0200 Subject: [PATCH 14/28] changelog: wrong DPI, and wrong initial font size with fractional scaling --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca9051b4..529ddabe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,14 @@ * Use appropriate rounding when applying fractional scales. * Xcursor not being scaled correctly on `fractional-scale-v1` capable compositors. +* `dpi-aware=yes` being broken on `fractional-scale-v1` capable + compositors (and when a fractional sacling factor is being used) + ([#1404][1404]). +* Initial font size being wrong on `fractional-scale-v1` capable + compositors, with multiple monitors with different scaling factors + connected ([#1404][1404]). + +[1404]: https://codeberg.org/dnkl/foot/issues/1404 ### Security From 4a4f2b5dae6f7303e27d45a1d60aaefb7be2d7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 20:13:50 +0200 Subject: [PATCH 15/28] pgo: add stub for wayl_fractional_scaling() --- pgo/pgo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pgo/pgo.c b/pgo/pgo.c index 6be60363..54618204 100644 --- a/pgo/pgo.c +++ b/pgo/pgo.c @@ -96,6 +96,7 @@ wayl_win_init(struct terminal *term, const char *token) void wayl_win_destroy(struct wl_window *win) {} void wayl_win_alpha_changed(struct wl_window *win) {} bool wayl_win_set_urgent(struct wl_window *win) { return true; } +bool wayl_fractional_scaling(const struct wayland *wayl) { return true; } bool spawn(struct reaper *reaper, const char *cwd, char *const argv[], From 0b8791d1c5d1bc71daff481874e6c9e44d0dba79 Mon Sep 17 00:00:00 2001 From: xdavidwu Date: Tue, 18 Jul 2023 21:09:24 +0800 Subject: [PATCH 16/28] wayland: fix pointer cap lost handling Before this, on compositor without cursor-shape support, a pointer capability lost of the seat makes foot crash. --- wayland.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index 354a0e78..7e51bfe9 100644 --- a/wayland.c +++ b/wayland.c @@ -341,8 +341,10 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, } else { if (seat->wl_pointer != NULL) { #if defined(HAVE_CURSOR_SHAPE) - wp_cursor_shape_device_v1_destroy(seat->pointer.shape_device); - seat->pointer.shape_device = NULL; + if (seat->pointer.shape_device != NULL) { + wp_cursor_shape_device_v1_destroy(seat->pointer.shape_device); + seat->pointer.shape_device = NULL; + } #endif wl_pointer_release(seat->wl_pointer); From 023a1b8da65f0f3d0c038dae658c1627e51ac7e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 18 Jul 2023 16:12:43 +0200 Subject: [PATCH 17/28] changelog: crash on pointer capability loss --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 529ddabe..31cd9400 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,8 +65,11 @@ * Initial font size being wrong on `fractional-scale-v1` capable compositors, with multiple monitors with different scaling factors connected ([#1404][1404]). +* Crash when _pointer capability_ is removed from a seat, on + compositors without `cursor-shape-v1 support` ([#1411][1411]). [1404]: https://codeberg.org/dnkl/foot/issues/1404 +[1411]: https://codeberg.org/dnkl/foot/pulls/1411 ### Security From 27b4c2ac2da7dc7b82e014786e9a8e9919888e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 18 Jul 2023 16:18:53 +0200 Subject: [PATCH 18/28] themes: starlight: update to V4 This also updates the default theme in foot, as well as the documentation. Closes #1409 --- CHANGELOG.md | 3 +++ config.c | 24 ++++++++++++------------ doc/foot.ini.5.scd | 12 ++++++------ foot.ini | 34 +++++++++++++++++----------------- themes/starlight | 30 +++++++++++++++--------------- 5 files changed, 53 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31cd9400..8a7e33bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,9 @@ * When window is mapped, use metadata (DPI, scaling factor, subpixel configuration) from the monitor we were most recently mapped on, instead of the one least recently. +* Starlight theme (the default theme) updated to [V4][starlight-v4] + +[starlight-v4]: https://github.com/CosmicToast/starlight/blob/v4/CHANGELOG.md#v4 ### Deprecated diff --git a/config.c b/config.c index 735ccd74..58a655e6 100644 --- a/config.c +++ b/config.c @@ -49,22 +49,22 @@ static const size_t min_csd_border_width = 5; static const uint32_t default_color_table[256] = { // Regular 0x242424, - 0xcf1745, - 0x3ecf5b, - 0xcfcf17, - 0x0ba6da, - 0xd926ac, - 0x17cfa1, + 0xf62b5a, + 0x47b413, + 0xe3c401, + 0x24acd4, + 0xf2affd, + 0x13c299, 0xe6e6e6, // Bright 0x616161, - 0xff1a53, - 0x17e640, - 0xecff1a, - 0x1ac6ff, - 0xf53dc7, - 0x1affc6, + 0xff4d51, + 0x35d450, + 0xe9e836, + 0x5dc5f8, + 0xfeabf2, + 0x24dfc4, 0xffffff, // 6x6x6 RGB cube diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 7fee8387..ae91ddf5 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -563,15 +563,15 @@ can configure the background transparency with the _alpha_ option. *regular0*, *regular1* *..* *regular7* The eight basic ANSI colors (Black, Red, Green, Yellow, Blue, - Magenta, Cyan, White). Default: _242424_, _cf1745_, _3ecf5b_, - _cfcf17_, _0ba6da_, _d926ac_, _17cfa1_, _e6e6e6_ (starlight - theme). + Magenta, Cyan, White). Default: _242424_, _f62b5a_, _47b413_, + _e3c401_, _24acd4_, _f2affd_, _13c299_, _e6e6e6_ (starlight + theme, V4). *bright0*, *bright1* *..* *bright7* The eight bright ANSI colors (Black, Red, Green, Yellow, Blue, - Magenta, Cyan, White). Default: _616161_, _ff1a53_, _17e640_, - _ecff1a_, _1ac6ff_, _f53dc7_, _1affc6_, _ffffff_ (starlight - theme). + Magenta, Cyan, White). Default: _616161_, _ff4d51_, _35d450_, + _e9e836_, _5dc5f8_, _feabf2_, _24dfc4_, _ffffff_ (starlight + theme, V4). *dim0*, *dim1* *..* *dim7* Custom colors to use with dimmed colors. Dimmed colors do not have diff --git a/foot.ini b/foot.ini index b4e4c603..359b2cf7 100644 --- a/foot.ini +++ b/foot.ini @@ -75,27 +75,27 @@ [colors] # alpha=1.0 -# background=002b36 -# foreground=839496 +# background=242424 +# foreground=ffffff ## Normal/regular colors (color palette 0-7) -# regular0=073642 # black -# regular1=dc322f # red -# regular2=859900 # green -# regular3=b58900 # yellow -# regular4=268bd2 # blue -# regular5=d33682 # magenta -# regular6=2aa198 # cyan -# regular7=eee8d5 # white +# regular0=242424 # black +# regular1=f62b5a # red +# regular2=47b413 # green +# regular3=e3c401 # yellow +# regular4=24acd4 # blue +# regular5=f2affd # magenta +# regular6=13c299 # cyan +# regular7=e6e6e6 # white ## Bright colors (color palette 8-15) -# bright0=08404f # bright black -# bright1=e35f5c # bright red -# bright2=9fb700 # bright green -# bright3=d9a400 # bright yellow -# bright4=4ba1de # bright blue -# bright5=dc619d # bright magenta -# bright6=32c1b6 # bright cyan +# bright0=616161 # bright black +# bright1=ff4d51 # bright red +# bright2=35d450 # bright green +# bright3=e9e836 # bright yellow +# bright4=5dc5f8 # bright blue +# bright5=feabf2 # bright magenta +# bright6=24dfc4 # bright cyan # bright7=ffffff # bright white ## dimmed colors (see foot.ini(5) man page) diff --git a/themes/starlight b/themes/starlight index 9b30b399..ed39f277 100644 --- a/themes/starlight +++ b/themes/starlight @@ -1,24 +1,24 @@ # -*- conf -*- -# Theme: starlight (https://github.com/CosmicToast/starlight) +# Theme: starlight V4 (https://github.com/CosmicToast/starlight) [colors] foreground = FFFFFF background = 242424 regular0 = 242424 -regular1 = CF1745 -regular2 = 3ECF5B -regular3 = CFCF17 -regular4 = 0BA6DA -regular5 = D926AC -regular6 = 17CFA1 -regular7 = E6E6E6 +regular1 = f62b5a +regular2 = 47b413 +regular3 = e3c401 +regular4 = 24acd4 +regular5 = f2affd +regular6 = 13c299 +regular7 = e6e6e6 bright0 = 616161 -bright1 = FF1A53 -bright2 = 17E640 -bright3 = ECFF1A -bright4 = 1AC6FF -bright5 = F53DC7 -bright6 = 1AFFC6 -bright7 = FFFFFF +bright1 = ff4d51 +bright2 = 35d450 +bright3 = e9e836 +bright4 = 5dc5f8 +bright5 = feabf2 +bright6 = 24dfc4 +bright7 = ffffff From fdd753263b3ebe96a83c73fbf560773dce04efd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 18 Jul 2023 16:13:36 +0200 Subject: [PATCH 19/28] term: destroy: unref key bindings *after* destroying window This fixes a crash-on-exit on compositors that emit a _"keyboard leave"_ event when a surface is unmapped. In our case, destroying the window (where we unmap it) in term_destroy(), lead to a crash in term_mouse_grabbed(), due to key_binding_for() returning NULL. The call chain in this is case is, roughly: term_destroy() -> wayl_win_destroy() -> keyboard_leave() -> term_xcursor_update_for_seat() -> term_mouse_grabbed() --- CHANGELOG.md | 2 ++ terminal.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a7e33bb..9f9d040d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,8 @@ connected ([#1404][1404]). * Crash when _pointer capability_ is removed from a seat, on compositors without `cursor-shape-v1 support` ([#1411][1411]). +* Crash on exit, if the mouse is hovering over the foot window (does + not happen on all compositors) [1404]: https://codeberg.org/dnkl/foot/issues/1404 [1411]: https://codeberg.org/dnkl/foot/pulls/1411 diff --git a/terminal.c b/terminal.c index 2f0e632c..c22646f2 100644 --- a/terminal.c +++ b/terminal.c @@ -1607,8 +1607,6 @@ term_destroy(struct terminal *term) if (term == NULL) return 0; - key_binding_unref(term->wl->key_binding_manager, term->conf); - tll_foreach(term->wl->terms, it) { if (it->item == term) { tll_remove(term->wl->terms, it); @@ -1654,6 +1652,8 @@ term_destroy(struct terminal *term) } mtx_unlock(&term->render.workers.lock); + key_binding_unref(term->wl->key_binding_manager, term->conf); + urls_reset(term); free(term->vt.osc.data); From 648f6016e3cc62ff895c37206680223c531bcc5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 19 Jul 2023 16:37:25 +0200 Subject: [PATCH 20/28] changelog: spelling: sacling -> scaling --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f9d040d..5e051081 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,7 +63,7 @@ * Xcursor not being scaled correctly on `fractional-scale-v1` capable compositors. * `dpi-aware=yes` being broken on `fractional-scale-v1` capable - compositors (and when a fractional sacling factor is being used) + compositors (and when a fractional scaling factor is being used) ([#1404][1404]). * Initial font size being wrong on `fractional-scale-v1` capable compositors, with multiple monitors with different scaling factors From 899b768b744c74e88e54e6d8eb32f53accea79d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 19 Jul 2023 16:34:42 +0200 Subject: [PATCH 21/28] =?UTF-8?q?render:=20disable=20transparency=20when?= =?UTF-8?q?=20we=E2=80=99re=20fullscreened?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wayland protocol recommends (or mandates?) that compositors render a black background behind fullscreened transparent windows. I.e. you never see what’s _actually_ behind the window. So, if you have a white, but semi-transparent background in foot, it’ll be rendered in a shade of gray. Given this, it’s better to simply disable transparency while we’re fullscreened. That way, we at least get the "correct" background color. Closes #1416 --- CHANGELOG.md | 3 +++ render.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e051081..9958e293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,8 +51,11 @@ configuration) from the monitor we were most recently mapped on, instead of the one least recently. * Starlight theme (the default theme) updated to [V4][starlight-v4] +* Background transparency (alpha) is now disabled in fullscreened + windows ([#1416][1416]). [starlight-v4]: https://github.com/CosmicToast/starlight/blob/v4/CHANGELOG.md#v4 +[1416]: https://codeberg.org/dnkl/foot/issues/1416 ### Deprecated diff --git a/render.c b/render.c index 11149b16..7d7c6348 100644 --- a/render.c +++ b/render.c @@ -526,8 +526,35 @@ render_cell(struct terminal *term, pixman_image_t *pix, uint32_t swap = _fg; _fg = _bg; _bg = swap; - } else if (cell->attrs.bg_src == COLOR_DEFAULT) - alpha = term->colors.alpha; + } + + else if (cell->attrs.bg_src == COLOR_DEFAULT) { + if (term->window->is_fullscreen) { + /* + * Note: disable transparency when fullscreened. + * + * This is because the wayland protocol recommends + * (mandates even?) the compositor render a black + * background behind fullscreened transparent windows. + * + * In other words, transparency does not work when + * fullscreened, in the sense that you don't see + * what's behind the window. + * + * And if we keep our alpha channel, the background + * color will just look weird. For example, if the + * background color is white, and alpha is 0.5, then + * the window will be drawn in a shade of gray while + * fullscreened. + * + * By disabling the alpha channel, the window will at + * least be rendered in the intended background color. + */ + xassert(alpha == 0xffff); + } else { + alpha = term->colors.alpha; + } + } } if (unlikely(is_selected && _fg == _bg)) { From a49281ced3fb27d6fa0f59f7964c5c0cc07b3829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 19 Jul 2023 16:39:56 +0200 Subject: [PATCH 22/28] =?UTF-8?q?render:=20OSD:=20don=E2=80=99t=20mark=20s?= =?UTF-8?q?urface=20as=20being=20opaque,=20when=20it=E2=80=99s=20not?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + render.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9958e293..7ef784f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ compositors without `cursor-shape-v1 support` ([#1411][1411]). * Crash on exit, if the mouse is hovering over the foot window (does not happen on all compositors) +* Visual glitches when CSD titlebar is transparent. [1404]: https://codeberg.org/dnkl/foot/issues/1404 [1411]: https://codeberg.org/dnkl/foot/pulls/1411 diff --git a/render.c b/render.c index 7d7c6348..11c2456a 100644 --- a/render.c +++ b/render.c @@ -1953,12 +1953,15 @@ render_osd(struct terminal *term, const struct wayl_sub_surface *sub_surf, wl_surface_attach(sub_surf->surface.surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(sub_surf->surface.surf, 0, 0, buf->width, buf->height); - struct wl_region *region = wl_compositor_create_region(term->wl->compositor); - if (region != NULL) { - wl_region_add(region, 0, 0, buf->width, buf->height); - wl_surface_set_opaque_region(sub_surf->surface.surf, region); - wl_region_destroy(region); - } + if (alpha == 0xffff) { + struct wl_region *region = wl_compositor_create_region(term->wl->compositor); + if (region != NULL) { + wl_region_add(region, 0, 0, buf->width, buf->height); + wl_surface_set_opaque_region(sub_surf->surface.surf, region); + wl_region_destroy(region); + } + } else + wl_surface_set_opaque_region(sub_surf->surface.surf, NULL); wl_surface_commit(sub_surf->surface.surf); quirk_weston_subsurface_desync_off(sub_surf->sub); From c3b119ea81a7b6bf01cf8ba064ab9df8f7c92f1e Mon Sep 17 00:00:00 2001 From: CismonX Date: Thu, 20 Jul 2023 07:00:14 +0800 Subject: [PATCH 23/28] vt: improve handling of HTS Do not insert existing positions into the tab stop list. This prevents a performance issue when iterating through an extremely long tab stop list. Also corrects the behaviour of CBT. --- vt.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/vt.c b/vt.c index 2ee2dbaf..51b69c7e 100644 --- a/vt.c +++ b/vt.c @@ -436,6 +436,27 @@ UNITTEST xassert(term.vt.private == expected); } +static void +tab_set(struct terminal *term) +{ + int col = term->grid->cursor.point.col; + + if (tll_length(term->tab_stops) == 0 || tll_back(term->tab_stops) < col) { + tll_push_back(term->tab_stops, col); + return; + } + + tll_foreach(term->tab_stops, it) { + if (it->item < col) { + continue; + } + if (it->item > col) { + tll_insert_before(term->tab_stops, it, col); + } + break; + } +} + static void action_esc_dispatch(struct terminal *term, uint8_t final) { @@ -478,14 +499,7 @@ action_esc_dispatch(struct terminal *term, uint8_t final) break; case 'H': - tll_foreach(term->tab_stops, it) { - if (it->item >= term->grid->cursor.point.col) { - tll_insert_before(term->tab_stops, it, term->grid->cursor.point.col); - break; - } - } - - tll_push_back(term->tab_stops, term->grid->cursor.point.col); + tab_set(term); break; case 'M': From c12db68363131d189d8410bf2994d70919229021 Mon Sep 17 00:00:00 2001 From: Max Gautier Date: Thu, 9 Mar 2023 14:13:57 +0100 Subject: [PATCH 24/28] footclient: fallback logic when socket paths don't exist Even if WAYLAND_DISPLAY / XDG_RUNTIME_DIR are defined, if we can't find the corresponding socket, we fallback to the path used when they are not defined. --- client.c | 15 +++++++++------ doc/footclient.1.scd | 5 +++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/client.c b/client.c index 99c7c1e8..41be68a9 100644 --- a/client.c +++ b/client.c @@ -374,16 +374,19 @@ main(int argc, char *const *argv) const char *xdg_runtime = getenv("XDG_RUNTIME_DIR"); if (xdg_runtime != NULL) { const char *wayland_display = getenv("WAYLAND_DISPLAY"); - if (wayland_display != NULL) + if (wayland_display != NULL) { snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/foot-%s.sock", xdg_runtime, wayland_display); - else + connected = (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == 0); + } + if (!connected) { + LOG_WARN("%s: failed to connect, will now try %s/foot.sock", + addr.sun_path, xdg_runtime); snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/foot.sock", xdg_runtime); - - if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == 0) - connected = true; - else + connected = (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == 0); + } + if (!connected) LOG_WARN("%s: failed to connect, will now try /tmp/foot.sock", addr.sun_path); } diff --git a/doc/footclient.1.scd b/doc/footclient.1.scd index 1464700c..7d89b9ed 100644 --- a/doc/footclient.1.scd +++ b/doc/footclient.1.scd @@ -146,6 +146,11 @@ terminfo entries manually, by copying *foot* and *foot-direct* to Used to construct the default _PATH_ for the *--server-socket* option, when no explicit argument is given (see above). +If the socket at default _PATH_ does not exist, *footclient* will +fallback to the less specific path, with the following priority: +*$XDG\_RUNTIME\_DIR/foot-$WAYLAND\_DISPLAY.sock*, +*$XDG\_RUNTIME\_DIR/foot.sock*, */tmp/foot.sock*. + ## Variables set in the child process *TERM* From d3ffb0bde1a8c7a7eff43d1e32a38d314c5adc8a Mon Sep 17 00:00:00 2001 From: Max Gautier Date: Tue, 14 Feb 2023 09:49:32 +0100 Subject: [PATCH 25/28] Ties systemd units to graphical-session.target - wayland-instance template target was a mistake. Systemd does not support simultaneous same user session, so stop trying to go against that. - Only start systemd units in Wayland environments. --- foot-server@.service.in => foot-server.service.in | 6 +++--- foot-server.socket | 9 +++++++++ foot-server@.socket | 5 ----- meson.build | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) rename foot-server@.service.in => foot-server.service.in (58%) create mode 100644 foot-server.socket delete mode 100644 foot-server@.socket diff --git a/foot-server@.service.in b/foot-server.service.in similarity index 58% rename from foot-server@.service.in rename to foot-server.service.in index c40bb454..47b81267 100644 --- a/foot-server@.service.in +++ b/foot-server.service.in @@ -1,13 +1,13 @@ [Service] ExecStart=@bindir@/foot --server=3 -Environment=WAYLAND_DISPLAY=%i UnsetEnvironment=LISTEN_PID LISTEN_FDS LISTEN_FDNAMES NonBlocking=true [Unit] Requires=%N.socket -Description=Foot terminal server mode for WAYLAND_DISPLAY=%i +Description=Foot terminal server mode Documentation=man:foot(1) +PartOf=graphical-session.target [Install] -WantedBy=wayland-instance@.target +WantedBy=graphical-session.target diff --git a/foot-server.socket b/foot-server.socket new file mode 100644 index 00000000..997e4363 --- /dev/null +++ b/foot-server.socket @@ -0,0 +1,9 @@ +[Socket] +ListenStream=%t/foot.sock + +[Unit] +PartOf=graphical-session.target +ConditionEnvironment=WAYLAND_DISPLAY + +[Install] +WantedBy=graphical-session.target diff --git a/foot-server@.socket b/foot-server@.socket deleted file mode 100644 index 71db51cb..00000000 --- a/foot-server@.socket +++ /dev/null @@ -1,5 +0,0 @@ -[Socket] -ListenStream=%t/foot-%i.sock - -[Install] -WantedBy=wayland-instance@.target diff --git a/meson.build b/meson.build index 1a00153c..cdccfa7e 100644 --- a/meson.build +++ b/meson.build @@ -329,13 +329,13 @@ if systemd.found() or custom_systemd_units_dir != '' configure_file( configuration: configuration, - input: 'foot-server@.service.in', + input: 'foot-server.service.in', output: '@BASENAME@', install_dir: systemd_units_dir ) install_data( - 'foot-server@.socket', + 'foot-server.socket', install_dir: systemd_units_dir) endif From 555edd60d45b987fb77792356fc2cfdd00a52ce7 Mon Sep 17 00:00:00 2001 From: Max Gautier Date: Tue, 14 Feb 2023 12:11:40 +0100 Subject: [PATCH 26/28] Update documentation regarding systemd units --- doc/foot.1.scd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 770c7f32..3da6fd7e 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -121,14 +121,14 @@ the foot command line of a socket provided by a supervision daemon (such as systemd or s6), and use that socket as it's own. - Two systemd units (foot-server@.{service,socket}) are provided to use that - feature with systemd. They need to be instantiated with the value of - $WAYLAND_DISPLAY (multiples instances can co-exists). + Two systemd units (foot-server.{service,socket}) are provided to use that + feature with systemd. To use socket activation, only enable the + socket unit. Note that starting *foot --server* as a systemd service will use - the environment of the systemd user instance; thus, if you need specific - environment variables, you'll need to import them using *systemctl --user - import-environment* or use a drop-in for the foot-server service. + the environment of the systemd user instance; thus, you'll need + to import *$WAYLAND_DISPLAY* in it using *systemctl --user + import-environment WAYLAND_DISPLAY*. *-H*,*--hold* Remain open after child process exits. From 478474d0ceb10c0151a2ba3684d6e95cd0bf75ff Mon Sep 17 00:00:00 2001 From: Max Gautier Date: Tue, 14 Feb 2023 12:04:26 +0100 Subject: [PATCH 27/28] Changelog: standard system target + footclient fallback --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ef784f2..29380684 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,9 +53,16 @@ * Starlight theme (the default theme) updated to [V4][starlight-v4] * Background transparency (alpha) is now disabled in fullscreened windows ([#1416][1416]). +* Foot server systemd units now use the standard + graphical-session.target ([#1281][1281]). +* If `$XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock` does not exist, + `footclient` now tries `$XDG_RUNTIME_DIR/foot.sock`, then + `/tmp/foot.sock`, even if `$WAYLAND_DISPLAY` and/or + `$XDG_RUNTIME_DIR` are defined ([#1281][1281]). [starlight-v4]: https://github.com/CosmicToast/starlight/blob/v4/CHANGELOG.md#v4 [1416]: https://codeberg.org/dnkl/foot/issues/1416 +[1281]: https://codeberg.org/dnkl/foot/pulls/1281 ### Deprecated From b3255465f1d4d5a96fbd7acee846db0e14026507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 21 Jul 2023 08:17:32 +0200 Subject: [PATCH 28/28] render: change baseline calculation, to center it within the line Before this patch, fonts were anchored to the top of the line. With this patch, it is instead centered. Closes #1302 --- CHANGELOG.md | 3 +++ render.c | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29380684..bda563dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,10 +59,13 @@ `footclient` now tries `$XDG_RUNTIME_DIR/foot.sock`, then `/tmp/foot.sock`, even if `$WAYLAND_DISPLAY` and/or `$XDG_RUNTIME_DIR` are defined ([#1281][1281]). +* Font baseline calculation: try to center the text within the line, + instead of anchoring it at the top ([#1302][1302]). [starlight-v4]: https://github.com/CosmicToast/starlight/blob/v4/CHANGELOG.md#v4 [1416]: https://codeberg.org/dnkl/foot/issues/1416 [1281]: https://codeberg.org/dnkl/foot/pulls/1281 +[1302]: https://codeberg.org/dnkl/foot/issues/1302 ### Deprecated diff --git a/render.c b/render.c index 11c2456a..48957a0a 100644 --- a/render.c +++ b/render.c @@ -305,7 +305,12 @@ color_brighten(const struct terminal *term, uint32_t color) static inline int font_baseline(const struct terminal *term) { - return term->font_y_ofs + term->fonts[0]->ascent; + const struct fcft_font *font = term->fonts[0]; + const int line_height = term->cell_height; + const int font_height = font->ascent + font->descent; + const int glyph_top_y = round((line_height - font_height) / 2.); + + return term->font_y_ofs + glyph_top_y + font->ascent; } static void