From 7bb756ccbc8e71c7935105d3339ffc355d29ec46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 18 Sep 2020 21:29:39 +0200 Subject: [PATCH 01/70] =?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 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 540f96b3..03e64784 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +* [Unreleased](#Unreleased) * [1.5.0](#1-5-0) * [1.4.4](#1-4-4) * [1.4.3](#1-4-3) @@ -12,6 +13,17 @@ * [1.2.1](#1-2-1) * [1.2.0](#1-2-0) + +## Unreleased +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security +### Contributors + + ## 1.5.0 ### Deprecated From 585fd7ad1f2764791cc7074735a89114a70d62cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Sep 2020 17:33:44 +0200 Subject: [PATCH 02/70] install: say _why_ ncurses and scdoc is needed --- INSTALL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index a12aedbe..d51f932a 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -52,8 +52,8 @@ In addition to the dev variant of the packages above, you need: * meson * ninja * wayland protocols -* ncurses -* scdoc +* ncurses (needed to generate terminfo) +* scdoc (for man page generation) * [tllist](https://codeberg.org/dnkl/tllist) [^1] A note on compilers; in general, foot runs **much** faster when From 59ca98f989129efc1f4a77929921571a8e06949f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 27 Sep 2020 14:31:39 +0200 Subject: [PATCH 03/70] =?UTF-8?q?input:=20mouse:=20match=20binding=20if=20?= =?UTF-8?q?binding=E2=80=99s=20click=20count=20is=20*less*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow a mouse binding to match even if its click count is less than the actual click count. If there are multiple bindings that match, use the one with the highest click count (that less than, or equal to the actual click count). Closes #146 --- CHANGELOG.md | 7 +++++++ input.c | 24 ++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03e64784..3fbc2cc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,13 @@ ### Deprecated ### Removed ### Fixed + +* Mouse bindings now match even if the actual click count is larger + than specified in the binding. This allows you to, for example, + quickly press the middle-button to paste multiple times + (https://codeberg.org/dnkl/foot/issues/146). + + ### Security ### Contributors diff --git a/input.c b/input.c index cfa99574..cc14d41b 100644 --- a/input.c +++ b/input.c @@ -1526,6 +1526,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, * applications */ mods &= ~(1 << seat->kbd.mod_shift); + const struct mouse_binding *match = NULL; + tll_foreach(seat->mouse.bindings, it) { const struct mouse_binding *binding = &it->item; @@ -1539,19 +1541,25 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, continue; } - if (binding->count != seat->mouse.count) { + if (binding->count > seat->mouse.count) { /* Not correct click count */ continue; } + if (match == NULL || binding->count > match->count) + match = binding; + } + + if (match != NULL) { seat->mouse.consumed = execute_binding( - seat, term, binding->action, NULL, serial); - break; + seat, term, match->action, NULL, serial); } } else { /* Seat does NOT have a keyboard - use mouse bindings *without* modifiers */ + const struct config_mouse_binding *match = NULL; + tll_foreach(seat->wayl->conf->bindings.mouse, it) { const struct config_mouse_binding *binding = &it->item; @@ -1560,7 +1568,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, continue; } - if (binding->count != seat->mouse.count) { + if (binding->count > seat->mouse.count) { /* Incorrect click count */ continue; } @@ -1571,9 +1579,13 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, continue; } + if (match == NULL || binding->count > match->count) + match = binding; + } + + if (match != NULL) { seat->mouse.consumed = execute_binding( - seat, term, binding->action, NULL, serial); - break; + seat, term, match->action, NULL, serial); } } From 0caa9c4173b1df677df408435c47a0bc3bde4770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 10:03:00 +0200 Subject: [PATCH 04/70] term: add term_damage_cursor() and term_damage_margins() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit term_damage_cursor() damages the cell where the cursor is currently at. This can be used to ensure the cursor is re-drawn, if there aren’t any other pending updates. term_damage_margins() requests the margins be redrawn the next time we render the grid. --- terminal.c | 13 +++++++++++++ terminal.h | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/terminal.c b/terminal.c index 5e0dc65a..0840a45c 100644 --- a/terminal.c +++ b/terminal.c @@ -1626,6 +1626,19 @@ term_damage_view(struct terminal *term) term_damage_rows_in_view(term, 0, term->rows - 1); } +void +term_damage_cursor(struct terminal *term) +{ + term->grid->cur_row->cells[term->grid->cursor.point.col].attrs.clean = 0; + term->grid->cur_row->dirty = true; +} + +void +term_damage_margins(struct terminal *term) +{ + term->render.margins = true; +} + void term_damage_scroll(struct terminal *term, enum damage_type damage_type, struct scroll_region region, int lines) diff --git a/terminal.h b/terminal.h index 12e93ce2..13339c3b 100644 --- a/terminal.h +++ b/terminal.h @@ -388,6 +388,8 @@ struct terminal { bool title; } pending; + bool margins; /* Someone explicitly requested a refresh of the margins */ + int scrollback_lines; /* Number of scrollback lines, from conf (TODO: move out from render struct?) */ struct { @@ -512,6 +514,9 @@ void term_damage_rows_in_view(struct terminal *term, int start, int end); void term_damage_all(struct terminal *term); void term_damage_view(struct terminal *term); +void term_damage_cursor(struct terminal *term); +void term_damage_margins(struct terminal *term); + void term_reset_view(struct terminal *term); void term_damage_scroll( From 97f20b4dd6d9e6e194279dc4219548b3daac4df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 10:04:41 +0200 Subject: [PATCH 05/70] render: term->render.margins is used to explicitly tell us to re-render margins --- render.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/render.c b/render.c index 43bcf5eb..86f028f7 100644 --- a/render.c +++ b/render.c @@ -1568,7 +1568,7 @@ static const struct wl_callback_listener frame_listener = { }; static void -grid_render(struct terminal *term, bool redraw_margins) +grid_render(struct terminal *term) { if (term->is_shutting_down) return; @@ -1588,7 +1588,7 @@ grid_render(struct terminal *term, bool redraw_margins) if (term->render.last_buf != buf || term->flash.active || term->render.was_flashing || term->is_searching != term->render.was_searching || - redraw_margins) + term->render.margins) { if (term->render.last_buf != NULL && term->render.last_buf->width == buf->width && @@ -1596,7 +1596,7 @@ grid_render(struct terminal *term, bool redraw_margins) !term->flash.active && !term->render.was_flashing && term->is_searching == term->render.was_searching && - !redraw_margins) + !term->render.margins) { static bool has_warned = false; if (!has_warned) { @@ -1972,13 +1972,11 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da term->window->frame_callback = NULL; bool grid = term->render.pending.grid; - bool margins = term->render.pending.margins; bool csd = term->render.pending.csd; bool search = term->render.pending.search; bool title = term->render.pending.title; term->render.pending.grid = false; - term->render.pending.margins = false; term->render.pending.csd = false; term->render.pending.search = false; term->render.pending.title = false; @@ -1995,11 +1993,8 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da if (search && term->is_searching) render_search_box(term); - if ((grid || margins) && - (!term->delayed_render_timer.is_armed || csd || search)) - { - grid_render(term, margins); - } + if (grid && (!term->delayed_render_timer.is_armed || csd || search)) + grid_render(term); } /* Move to terminal.c? */ @@ -2336,13 +2331,11 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) assert(term->window->is_configured); bool grid = term->render.refresh.grid; - bool margins = term->render.refresh.margins; bool csd = term->render.refresh.csd; bool search = term->render.refresh.search; bool title = term->render.refresh.title; term->render.refresh.grid = false; - term->render.refresh.margins = false; term->render.refresh.csd = false; term->render.refresh.search = false; term->render.refresh.title = false; @@ -2357,12 +2350,11 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) render_update_title(term); if (search) render_search_box(term); - if (grid || margins) - grid_render(term, margins); + if (grid) + grid_render(term); } else { /* Tells the frame callback to render again */ term->render.pending.grid |= grid; - term->render.pending.margins |= margins; term->render.pending.csd |= csd; term->render.pending.search |= search; term->render.pending.title |= title; From 5924892bbe63e1338b314521009ecc7c31009d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 10:05:52 +0200 Subject: [PATCH 06/70] =?UTF-8?q?osc:=20don=E2=80=99t=20explicitly=20call?= =?UTF-8?q?=20render=5Frefresh()=20when=20changing=20the=20color=20palette?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doing so will schedule the renderer “as soon as possible”. I.e we’re by-passing the regular scheduler, and thus we’re by-passing the user’s setting of the delayed-render-* timers. The fact that we’re scheduling “as soon as possible” also means we’re much more likely to trigger flickering, or color flashes, if the application is changing colors which are on the screen. To handle changes to the cursor color(s), use the new term_damage_cursor() instead of render_refresh(). To handle background color changes, which affect the margins, use the new term_damage_margins() instead of render_refresh_margins(), Closes #141 --- osc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/osc.c b/osc.c index 7e22d7c1..384cf401 100644 --- a/osc.c +++ b/osc.c @@ -589,7 +589,6 @@ osc_dispatch(struct terminal *term) } } - render_refresh(term); break; } @@ -635,8 +634,7 @@ osc_dispatch(struct terminal *term) } term_damage_view(term); - render_refresh(term); - render_refresh_margins(term); + term_damage_margins(term); break; } @@ -664,7 +662,8 @@ osc_dispatch(struct terminal *term) term->cursor_color.cursor = 0; /* Invert fg/bg */ else term->cursor_color.cursor = 1u << 31 | color; - render_refresh(term); + + term_damage_cursor(term); break; case 30: /* Set tab title */ @@ -705,7 +704,6 @@ osc_dispatch(struct terminal *term) } } - render_refresh(term); break; } @@ -716,22 +714,20 @@ osc_dispatch(struct terminal *term) LOG_DBG("resetting foreground"); term->colors.fg = term->colors.default_fg; term_damage_view(term); - render_refresh(term); break; case 111: /* Reset default text background color */ LOG_DBG("resetting background"); term->colors.bg = term->colors.default_bg; term_damage_view(term); - render_refresh(term); - render_refresh_margins(term); + term_damage_margins(term); break; case 112: LOG_DBG("resetting cursor color"); term->cursor_color.text = term->default_cursor_color.text; term->cursor_color.cursor = term->default_cursor_color.cursor; - render_refresh(term); + term_damage_cursor(term); break; case 555: From af2873987ff20d86d7d587f005c2897e90a6f18f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 10:08:59 +0200 Subject: [PATCH 07/70] render: remove render_refresh_margins() --- render.c | 6 ------ render.h | 1 - terminal.h | 2 -- 3 files changed, 9 deletions(-) diff --git a/render.c b/render.c index 86f028f7..210eaf47 100644 --- a/render.c +++ b/render.c @@ -2385,12 +2385,6 @@ render_refresh(struct terminal *term) term->render.refresh.grid = true; } -void -render_refresh_margins(struct terminal *term) -{ - term->render.refresh.margins = true; -} - void render_refresh_csd(struct terminal *term) { diff --git a/render.h b/render.h index 3f8cf540..05c79322 100644 --- a/render.h +++ b/render.h @@ -13,7 +13,6 @@ bool render_resize(struct terminal *term, int width, int height); bool render_resize_force(struct terminal *term, int width, int height); void render_refresh(struct terminal *term); -void render_refresh_margins(struct terminal *term); void render_refresh_csd(struct terminal *term); void render_refresh_search(struct terminal *term); void render_refresh_title(struct terminal *term); diff --git a/terminal.h b/terminal.h index 13339c3b..60a4aba4 100644 --- a/terminal.h +++ b/terminal.h @@ -373,7 +373,6 @@ struct terminal { /* Scheduled for rendering, as soon-as-possible */ struct { bool grid; - bool margins; bool csd; bool search; bool title; @@ -382,7 +381,6 @@ struct terminal { /* Scheduled for rendering, in the next frame callback */ struct { bool grid; - bool margins; bool csd; bool search; bool title; From acd1d6a4a313ba3407482036403c7b0c442671dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 10:11:03 +0200 Subject: [PATCH 08/70] changelog: fixed color flashes with OSC 4,10,11 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fbc2cc0..ca17ca4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ than specified in the binding. This allows you to, for example, quickly press the middle-button to paste multiple times (https://codeberg.org/dnkl/foot/issues/146). +* Color flashes when changing the color palette with OSC 4,10,11 + (https://codeberg.org/dnkl/foot/issues/141). ### Security From b12ce3d7d787522a866658d01f606fdea66b0517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Sep 2020 18:35:40 +0200 Subject: [PATCH 09/70] grid: reflow: retain scrollback position Closes #142 --- CHANGELOG.md | 2 ++ grid.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca17ca4a..a2b30c01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ (https://codeberg.org/dnkl/foot/issues/146). * Color flashes when changing the color palette with OSC 4,10,11 (https://codeberg.org/dnkl/foot/issues/141). +* Scrollback position is now retained when resizing the window + (https://codeberg.org/dnkl/foot/issues/142). ### Security diff --git a/grid.c b/grid.c index e4b7c063..5f2b4277 100644 --- a/grid.c +++ b/grid.c @@ -65,6 +65,9 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, const int old_rows = grid->num_rows; const int old_cols = grid->num_cols; + /* Is viewpoint tracking current grid offset? */ + const bool view_follows = grid->view == grid->offset; + int new_col_idx = 0; int new_row_idx = 0; @@ -97,9 +100,14 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, tll_push_back(tracking_points, &cursor); tll_push_back(tracking_points, &saved_cursor); + struct coord viewport = {0, grid->view}; + if (!view_follows) + tll_push_back(tracking_points, &viewport); + for (size_t i = 0; i < tracking_points_count; i++) tll_push_back(tracking_points, _tracking_points[i]); + /* * Walk the old grid */ @@ -308,7 +316,8 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, grid->offset += new_rows; while (new_grid[grid->offset] == NULL) grid->offset = (grid->offset + 1) & (new_rows - 1); - grid->view = grid->offset; + + grid->view = view_follows ? grid->offset : viewport.row; /* Ensure all visible rows have been allocated */ for (int r = 0; r < new_screen_rows; r++) { From 0e9eea85af6bcc7d1c54435dc0b3c3f496827036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Sep 2020 18:48:41 +0200 Subject: [PATCH 10/70] grid: reflow: handle viewport being too far down when enlarging the window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the viewport is close to the bottom, but not *at* the bottom, and we’re enlarging the window, the translated viewport will be too far down. --- grid.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/grid.c b/grid.c index 5f2b4277..d8fc2842 100644 --- a/grid.c +++ b/grid.c @@ -317,8 +317,6 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, while (new_grid[grid->offset] == NULL) grid->offset = (grid->offset + 1) & (new_rows - 1); - grid->view = view_follows ? grid->offset : viewport.row; - /* Ensure all visible rows have been allocated */ for (int r = 0; r < new_screen_rows; r++) { int idx = (grid->offset + r) & (new_rows - 1); @@ -326,6 +324,23 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, new_grid[idx] = grid_row_alloc(new_cols, true); } + grid->view = view_follows ? grid->offset : viewport.row; + + /* If enlarging the window, the old viewport may be too far down, + * with unallocated rows. Make sure this cannot happen */ + while (true) { + int idx = (grid->view + new_screen_rows - 1) & (new_rows - 1); + if (new_grid[idx] != NULL) + break; + grid->view--; + if (grid->view < 0) + grid->view += new_rows; + } + for (size_t r = 0; r < new_screen_rows; r++) { + int idx = (grid->view + r) & (new_rows - 1); + assert(new_grid[idx] != NULL); + } + /* Free old grid */ for (int r = 0; r < grid->num_rows; r++) grid_row_free(old_grid[r]); From 661fa98cb203894c154869d47a228d44e6b74b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Sep 2020 18:53:05 +0200 Subject: [PATCH 11/70] =?UTF-8?q?grid:=20reflow:=20fix=20release=20build;?= =?UTF-8?q?=20=E2=80=98idx=E2=80=99=20is=20only=20used=20in=20an=20assert(?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- grid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grid.c b/grid.c index d8fc2842..a79b4493 100644 --- a/grid.c +++ b/grid.c @@ -6,6 +6,7 @@ #define LOG_MODULE "grid" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "macros.h" #include "sixel.h" #include "util.h" #include "xmalloc.h" @@ -337,7 +338,7 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, grid->view += new_rows; } for (size_t r = 0; r < new_screen_rows; r++) { - int idx = (grid->view + r) & (new_rows - 1); + int UNUSED idx = (grid->view + r) & (new_rows - 1); assert(new_grid[idx] != NULL); } From 8e04b086158730b615803c45368f1fe7a6bce95e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 27 Sep 2020 11:11:45 +0200 Subject: [PATCH 12/70] input: trackpad scroll: correctly convert pixel movements to line movements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trackpad scroll movements are in pixels. Foot previously “translated” these directly to line movements (i.e. a one pixel scroll event was translated into a one line scroll). Now we use the line height of the terminal and correctly convert pixels to lines. This makes the trackpad scroll speed in foot consistent with the scroll speed in e.g. Alacritty and Kitty. --- CHANGELOG.md | 4 ++++ input.c | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2b30c01..0eb90527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ (https://codeberg.org/dnkl/foot/issues/141). * Scrollback position is now retained when resizing the window (https://codeberg.org/dnkl/foot/issues/142). +* Trackpad scrolling speed. Note that it is much slower compared to + previous foot versions. Use the **multiplier** option in `foot.ini` + if you find the new speed too slow + (https://codeberg.org/dnkl/foot/issues/144). ### Security diff --git a/input.c b/input.c index cc14d41b..20c1381c 100644 --- a/input.c +++ b/input.c @@ -1688,6 +1688,8 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, if (seat->mouse.have_discrete) return; + assert(seat->mouse_focus != NULL); + /* * Aggregate scrolled amount until we get at least 1.0 * @@ -1697,10 +1699,12 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, seat->mouse.axis_aggregated += seat->wayl->conf->scrollback.multiplier * wl_fixed_to_double(value); - if (fabs(seat->mouse.axis_aggregated) >= 1.) { - mouse_scroll(seat, round(seat->mouse.axis_aggregated)); - seat->mouse.axis_aggregated = 0.; - } + if (fabs(seat->mouse.axis_aggregated) < seat->mouse_focus->cell_height) + return; + + int lines = seat->mouse.axis_aggregated / seat->mouse_focus->cell_height; + mouse_scroll(seat, lines); + seat->mouse.axis_aggregated -= (double)lines * seat->mouse_focus->cell_height; } static void From 1bc9c1c23078563903484dbb7b60384566ee5f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 09:49:21 +0200 Subject: [PATCH 13/70] changelog: reword trackpad scrolling speed entry --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eb90527..49cdb284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,11 @@ previous foot versions. Use the **multiplier** option in `foot.ini` if you find the new speed too slow (https://codeberg.org/dnkl/foot/issues/144). +* Trackpad scrolling speed to better match the mouse scrolling speed, + and to be consistent with other (Wayland) terminal emulators. Note + that it is (much) slower compared to previous foot versions. Use the + **multiplier** option in `foot.ini` if you find the new speed too + slow (https://codeberg.org/dnkl/foot/issues/144). ### Security From bf17026ed79366065b9f15940e287f847d23f79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 09:50:17 +0200 Subject: [PATCH 14/70] config: change default multiplier from 1.0 -> 3.0 --- config.c | 2 +- doc/foot.ini.5.scd | 2 +- foot.ini | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.c b/config.c index 418c9c37..c69af59d 100644 --- a/config.c +++ b/config.c @@ -1869,7 +1869,7 @@ config_load(struct config *conf, const char *conf_path, .format = SCROLLBACK_INDICATOR_FORMAT_TEXT, .text = wcsdup(L""), }, - .multiplier = 1., + .multiplier = 3., }, .colors = { .fg = default_foreground, diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 7467d0b8..e51a5470 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -99,7 +99,7 @@ in this order: *multiplier* Amount to multiply mouse scrolling with. It is a decimal number, - i.e. fractions are allowed. Default: _1.0_. + i.e. fractions are allowed. Default: _3.0_. *indicator-position* Configures the style of the scrollback position indicator. One of diff --git a/foot.ini b/foot.ini index 5e8dc47e..952bf00c 100644 --- a/foot.ini +++ b/foot.ini @@ -12,7 +12,7 @@ [scrollback] # lines=1000 -# multiplier=1.0 +# multiplier=3.0 # indicator-position=relative # indicator-format= From 8181113e3cbe65c932eb78d847781359fe02ecdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 19:41:53 +0200 Subject: [PATCH 15/70] changelog: multiplier default value changed from 1.0 -> 3.0 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49cdb284..2344b81f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ ## Unreleased ### Added ### Changed + +* Default value of the **multiplier** option in `foot.ini` from `1.0` + to `3.0`. + + ### Deprecated ### Removed ### Fixed From aa3fcc1251abb8e6f55b0071f99cc5f666449b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 19:43:39 +0200 Subject: [PATCH 16/70] =?UTF-8?q?changelog:=20multiplier:=20the=20option?= =?UTF-8?q?=20belongs=20to=20the=20=E2=80=98scrollback=E2=80=99=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2344b81f..89f0de13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,8 +18,8 @@ ### Added ### Changed -* Default value of the **multiplier** option in `foot.ini` from `1.0` - to `3.0`. +* Default value of the **scrollback.multiplier** option in `foot.ini` + from `1.0` to `3.0`. ### Deprecated From 3c057fb6001637c89018e5647076f7c481d8ac00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Sep 2020 19:47:29 +0200 Subject: [PATCH 17/70] =?UTF-8?q?changelog:=20trackpad=20scrolling:=20?= =?UTF-8?q?=E2=80=98multiplier=E2=80=99=20is=20in=20the=20=E2=80=98scrollb?= =?UTF-8?q?ack=E2=80=99=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89f0de13..67d38093 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,8 +41,8 @@ * Trackpad scrolling speed to better match the mouse scrolling speed, and to be consistent with other (Wayland) terminal emulators. Note that it is (much) slower compared to previous foot versions. Use the - **multiplier** option in `foot.ini` if you find the new speed too - slow (https://codeberg.org/dnkl/foot/issues/144). + **scrollback.multiplier** option in `foot.ini` if you find the new + speed too slow (https://codeberg.org/dnkl/foot/issues/144). ### Security From 852fc049c860fc9004101fcb5cecfead719d04cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Oct 2020 18:34:48 +0200 Subject: [PATCH 18/70] config: ignore key/value pairs following an invalid section name When we detected an invalid section name, we correctly logged this and warned the user. However, the internal state machine now had an invalid section enum value. This caused a crash when the next key/value pair was to be parsed and we tried to lookup which parser function to call. Closes #159. --- CHANGELOG.md | 2 ++ config.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67d38093..3bbc4fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,8 @@ that it is (much) slower compared to previous foot versions. Use the **scrollback.multiplier** option in `foot.ini` if you find the new speed too slow (https://codeberg.org/dnkl/foot/issues/144). +* Crash when `foot.ini` contains an invalid section name + (https://codeberg.org/dnkl/foot/issues/159). ### Security diff --git a/config.c b/config.c index c69af59d..ff5d6c59 100644 --- a/config.c +++ b/config.c @@ -1673,6 +1673,11 @@ parse_config_file(FILE *f, struct config *conf, const char *path, bool errors_ar continue; } + if (section >= SECTION_COUNT) { + /* Last section name was invalid; ignore all keys in it */ + continue; + } + char *key = strtok(key_value, "="); if (key == NULL) { LOG_AND_NOTIFY_ERR("%s:%d: syntax error: no key specified", path, lineno); @@ -1711,6 +1716,8 @@ parse_config_file(FILE *f, struct config *conf, const char *path, bool errors_ar LOG_DBG("section=%s, key='%s', value='%s', comment='%s'", section_info[section].name, key, value, comment); + assert(section >= 0 && section < SECTION_COUNT); + parser_fun_t section_parser = section_info[section].fun; assert(section_parser != NULL); From 5aa170b9f65b0316b10d38e3b69cca96c4c4ea5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Oct 2020 18:38:54 +0200 Subject: [PATCH 19/70] =?UTF-8?q?doc:=20foot.ini:=20the=20tweak=20section?= =?UTF-8?q?=20is=20called=20=E2=80=98tweak=E2=80=99,=20not=20=E2=80=98twea?= =?UTF-8?q?ks=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/foot.ini.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index e51a5470..2db03ce8 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -475,7 +475,7 @@ _Examples_: - Dina:weight=bold:slant=italic - Courier New:size=12 -# TWEAKS +# TWEAK This section is for advanced users and describes configuration options that can be used to tweak foot's low-level behavior. From a53e8c28661f3267555a3e06ce7ef3b90a9cfbe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 8 Oct 2020 19:53:11 +0200 Subject: [PATCH 20/70] render: apply opacity correctly when in reverse video mode --- CHANGELOG.md | 1 + render.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bbc4fa4..66a8dc01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ speed too slow (https://codeberg.org/dnkl/foot/issues/144). * Crash when `foot.ini` contains an invalid section name (https://codeberg.org/dnkl/foot/issues/159). +* Background opacity when in _reverse video_ mode. ### Security diff --git a/render.c b/render.c index 210eaf47..20d66512 100644 --- a/render.c +++ b/render.c @@ -403,7 +403,9 @@ render_cell(struct terminal *term, pixman_image_t *pix, pixman_color_t fg = color_hex_to_pixman(_fg); pixman_color_t bg = color_hex_to_pixman_with_alpha( - _bg, _bg == term->colors.bg ? term->colors.alpha : 0xffff); + _bg, + (_bg == (term->reverse ? term->colors.fg : term->colors.bg) + ? term->colors.alpha : 0xffff)); if (cell->attrs.dim) color_dim(&fg); @@ -549,8 +551,12 @@ render_margin(struct terminal *term, struct buffer *buf, const int line_count = end_line - start_line; uint32_t _bg = !term->reverse ? term->colors.bg : term->colors.fg; + pixman_color_t bg = color_hex_to_pixman_with_alpha( - _bg, _bg == term->colors.bg ? term->colors.alpha : 0xffff); + _bg, + (_bg == (term->reverse ? term->colors.fg : term->colors.bg) + ? term->colors.alpha : 0xffff)); + if (term->is_searching) color_dim(&bg); From 6714c3343fca264b43e9db4c37586f01e85304c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 8 Oct 2020 19:53:30 +0200 Subject: [PATCH 21/70] =?UTF-8?q?doc:=20foot.ini:=20it=E2=80=99s=20foot.in?= =?UTF-8?q?i,=20not=20foot.init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/foot.ini.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 2db03ce8..18d0526e 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -16,7 +16,7 @@ in this order: - *~/.config/foot/foot.ini* - *XDG_CONFIG_HOME/footrc* - *~/.config/footrc* -- *XDG_CONFIG_DIRS/foot/foot.init* +- *XDG_CONFIG_DIRS/foot/foot.ini* # SECTION: default From 8257954bfa0a9b8acebf9d30dd7b17c4b6c29cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 8 Oct 2020 19:53:49 +0200 Subject: [PATCH 22/70] =?UTF-8?q?doc:=20foot.ini:=20=E2=80=9Ctop=20at?= =?UTF-8?q?=E2=80=9D=20->=20=E2=80=9Ctop=20of=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/foot.ini.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 18d0526e..c522d942 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -104,7 +104,7 @@ in this order: *indicator-position* Configures the style of the scrollback position indicator. One of *none*, *fixed* or *relative*. *none* disables the indicator - completely. *fixed* always renders the indicator near the top at + completely. *fixed* always renders the indicator near the top of the window, and *relative* renders the indicator at the position corresponding to the current scrollback position. Default: _relative_. From 9de744ae39b6303f45ca3f06d66d8bd0b212be98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 8 Oct 2020 19:54:06 +0200 Subject: [PATCH 23/70] =?UTF-8?q?doc:=20foot.ini:=20mention=20that=20?= =?UTF-8?q?=E2=80=98lines=E2=80=99=20is=20rounded=20up=20to=20nearest=20po?= =?UTF-8?q?wer=20of=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/foot.ini.5.scd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index c522d942..60da2d67 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -95,7 +95,9 @@ in this order: # SECTION: scrollback *lines* - Number of scrollback lines. Default: _1000_. + Number of scrollback lines. The maximum number of allocated lines + will be this value plus the number of visible lines, rounded up to + the nearest power of 2. Default: _1000_. *multiplier* Amount to multiply mouse scrolling with. It is a decimal number, From ab618dd1927758a02ad597f3b0df5fa37ad1cc2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 8 Oct 2020 19:54:28 +0200 Subject: [PATCH 24/70] =?UTF-8?q?doc:=20foot.1:=20remove=20=E2=80=98--?= =?UTF-8?q?=E2=80=99=20from=20example=20command=20line?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/foot.1.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index c8fbddc7..601c23f8 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -18,7 +18,7 @@ will start a new terminal window with your default shell. You can override the default shell by appending a custom command to the foot command line - *foot -- sh -c "echo hello world && sleep 5"* + *foot sh -c "echo hello world && sleep 5"* # OPTIONS From 2c515c27e5daa34d37f683b06b2ca9d9f7e546b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 2 Oct 2020 20:54:45 +0200 Subject: [PATCH 25/70] sixel: fold long line --- sixel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sixel.c b/sixel.c index c6fe1a10..f9c11037 100644 --- a/sixel.c +++ b/sixel.c @@ -484,7 +484,9 @@ sixel_unhook(struct terminal *term) sixel_overwrite_by_rectangle( term, cursor->row, image.pos.col, image.rows, image.cols); - LOG_DBG("generating %dx%d pixman image at %d-%d", image.width, image.height, image.pos.row, image.pos.row + image.rows); + LOG_DBG("generating %dx%d pixman image at %d-%d", + image.width, image.height, + image.pos.row, image.pos.row + image.rows); image.pix = pixman_image_create_bits_no_clear( PIXMAN_a8r8g8b8, From 7a7ba599c3f14c3e86645fc7e23225f513ef5414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 2 Oct 2020 20:55:10 +0200 Subject: [PATCH 26/70] =?UTF-8?q?sixel:=20overwrite-by-rectangle=20expects?= =?UTF-8?q?=20=E2=80=98width=E2=80=99=20to=20not=20exceed=20screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a crash when the emitted sixel extends beyond the right margin. The crash only happens when there are other sixel images already emitted. Fixes part of #151 --- CHANGELOG.md | 2 ++ sixel.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66a8dc01..7afc1e35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,8 @@ * Crash when `foot.ini` contains an invalid section name (https://codeberg.org/dnkl/foot/issues/159). * Background opacity when in _reverse video_ mode. +* Crash when writing a sixel image that extends outside the terminal's + right margin (https://codeberg.org/dnkl/foot/issues/151). ### Security diff --git a/sixel.c b/sixel.c index f9c11037..0600a434 100644 --- a/sixel.c +++ b/sixel.c @@ -482,7 +482,8 @@ sixel_unhook(struct terminal *term) }; sixel_overwrite_by_rectangle( - term, cursor->row, image.pos.col, image.rows, image.cols); + term, cursor->row, image.pos.col, + image.rows, min(image.cols, term->cols - image.pos.col)); LOG_DBG("generating %dx%d pixman image at %d-%d", image.width, image.height, From cdcdfe527c353bf55c3aaf9f843ee2e7c3cf9b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 2 Oct 2020 20:56:44 +0200 Subject: [PATCH 27/70] sixel: fix sheared image when image crosses scrollback wrap-around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a sixel image crosses the scrollback wrap-around, it is split up into (at least) two pieces. We use cursor->point.col for all pieces’ x-coordinate. This caused the final image to appear sheared, since we do a carriage-return (after a number of linefeeds) after each piece - this causes the cursor’s position to be reset to the left margin. The solution is simple; remember the cursor’s initial x-coordinate, and use that to position all image pieces. Closes #151. --- CHANGELOG.md | 3 +++ sixel.c | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7afc1e35..64e94377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,9 @@ * Background opacity when in _reverse video_ mode. * Crash when writing a sixel image that extends outside the terminal's right margin (https://codeberg.org/dnkl/foot/issues/151). +* Sixel image at non-zero column positions getting sheared at + seemingly random occasions + (https://codeberg.org/dnkl/foot/issues/151). ### Security diff --git a/sixel.c b/sixel.c index 0600a434..747e3d00 100644 --- a/sixel.c +++ b/sixel.c @@ -448,6 +448,16 @@ sixel_unhook(struct terminal *term) int pixel_rows_left = term->sixel.image.height; const int stride = term->sixel.image.width * sizeof(uint32_t); + /* + * Need to 'remember' current cursor column. + * + * If we split up the sixel (to avoid scrollback wrap-around), we + * will emit a carriage-return (after several linefeeds), which + * will reset the cursor column to 0. If we use _that_ column for + * the subsequent image parts, the image will look sheared. + */ + const int start_col = term->grid->cursor.point.col; + /* We do not allow sixels to cross the scrollback wrap-around, as * this makes intersection calculations much more complicated */ while (pixel_rows_left > 0) { @@ -478,7 +488,7 @@ sixel_unhook(struct terminal *term) .height = height, .rows = (height + term->cell_height - 1) / term->cell_height, .cols = (width + term->cell_width - 1) / term->cell_width, - .pos = (struct coord){cursor->col, cur_row}, + .pos = (struct coord){start_col, cur_row}, }; sixel_overwrite_by_rectangle( From 9cccc76520a3eac3957d22bf9becd68d378521cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 3 Oct 2020 22:41:20 +0200 Subject: [PATCH 28/70] =?UTF-8?q?term:=20re-calculate=20sixel=20images?= =?UTF-8?q?=E2=80=99=20rows/cols=20values=20when=20cell=20size=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terminal.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/terminal.c b/terminal.c index 0840a45c..a34ecb1a 100644 --- a/terminal.c +++ b/terminal.c @@ -1524,6 +1524,20 @@ term_font_size_adjust(struct terminal *term, double amount) * So we delete them. */ sixel_destroy_all(term); + } else if (term->cell_width != old_cell_width || + term->cell_height != old_cell_height) + { + tll_foreach(term->normal.sixel_images, it) { + struct sixel *six = &it->item; + six->rows = (six->height + term->cell_height - 1) / term->cell_height; + six->cols = (six->width + term->cell_width - 1) / term->cell_width; + } + + tll_foreach(term->alt.sixel_images, it) { + struct sixel *six = &it->item; + six->rows = (six->height + term->cell_height - 1) / term->cell_height; + six->cols = (six->width + term->cell_width - 1) / term->cell_width; + } } return true; } From e694f293ac982b751accbe2d218596cf17ba711e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 3 Oct 2020 22:42:03 +0200 Subject: [PATCH 29/70] sixel: overwrite: remove asserts Sixels may extend outside the visible screen area --- sixel.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/sixel.c b/sixel.c index 747e3d00..84a3ec96 100644 --- a/sixel.c +++ b/sixel.c @@ -211,11 +211,6 @@ static void sixel_overwrite(struct terminal *term, struct sixel *six, int row, int col, int height, int width) { - assert(row >= 0); - assert(row + height <= term->grid->num_rows); - assert(col >= 0); - assert(col + width <= term->grid->num_cols); - int rel_above = min(max(row - six->pos.row, 0), six->rows); int rel_below = max(min(row + height - six->pos.row, six->rows), 0); int rel_left = min(max(col - six->pos.col, 0), six->cols); @@ -315,11 +310,6 @@ static void _sixel_overwrite_by_rectangle( struct terminal *term, int row, int col, int height, int width) { - assert(row >= 0); - assert(row + height <= term->grid->num_rows); - assert(col >= 0); - assert(col + width <= term->grid->num_cols); - const int start = row; const int end = row + height - 1; @@ -492,8 +482,7 @@ sixel_unhook(struct terminal *term) }; sixel_overwrite_by_rectangle( - term, cursor->row, image.pos.col, - image.rows, min(image.cols, term->cols - image.pos.col)); + term, cursor->row, image.pos.col, image.rows, image.cols); LOG_DBG("generating %dx%d pixman image at %d-%d", image.width, image.height, From 368305aa598aef4de84cb5823229a7d954a7e371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 3 Oct 2020 22:42:34 +0200 Subject: [PATCH 30/70] =?UTF-8?q?sixel:=20overwrite:=20calculate=20split-u?= =?UTF-8?q?p=20image=20pieces=E2=80=99=20rows/cols=20from=20their=20width/?= =?UTF-8?q?height?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sixel.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sixel.c b/sixel.c index 84a3ec96..88da4e28 100644 --- a/sixel.c +++ b/sixel.c @@ -232,8 +232,6 @@ sixel_overwrite(struct terminal *term, struct sixel *six, imgs[0] = (struct sixel){ .width = six->width, .height = rel_above * term->cell_height, - .rows = rel_above, - .cols = six->cols, .pos = six->pos, }; imgs[0].data = xmalloc(imgs[0].width * imgs[0].height * sizeof(uint32_t)); @@ -244,8 +242,6 @@ sixel_overwrite(struct terminal *term, struct sixel *six, imgs[1] = (struct sixel){ .width = six->width, .height = six->height - rel_below * term->cell_height, - .rows = six->rows - rel_below, - .cols = six->cols, .pos = (struct coord){ six->pos.col, (six->pos.row + rel_below) & (term->grid->num_rows - 1)}, @@ -261,8 +257,6 @@ sixel_overwrite(struct terminal *term, struct sixel *six, imgs[2] = (struct sixel){ .width = rel_left * term->cell_width, .height = min(term->cell_height, six->height - rel_above * term->cell_height), - .rows = 1, - .cols = rel_left, .pos = (struct coord){ six->pos.col, (six->pos.row + rel_above) & (term->grid->num_rows - 1)}, @@ -279,8 +273,6 @@ sixel_overwrite(struct terminal *term, struct sixel *six, imgs[3] = (struct sixel){ .width = six->width - rel_right * term->cell_width, .height = min(term->cell_height, six->height - rel_above * term->cell_height), - .rows = 1, - .cols = six->cols - rel_right, .pos = (struct coord){ six->pos.col + rel_right, (six->pos.row + rel_above) & (term->grid->num_rows - 1)}, @@ -297,6 +289,9 @@ sixel_overwrite(struct terminal *term, struct sixel *six, if (imgs[i].data == NULL) continue; + imgs[i].rows = (imgs[i].height + term->cell_height - 1) / term->cell_height; + imgs[i].cols = (imgs[i].width + term->cell_width - 1) / term->cell_width; + imgs[i].pix = pixman_image_create_bits_no_clear( PIXMAN_a8r8g8b8, imgs[i].width, imgs[i].height, From c4b84249a883c001dfaaa753ba504baf54b7c217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 3 Oct 2020 23:00:34 +0200 Subject: [PATCH 31/70] grid: reflow: re-insert sixels *after* new grid offset has been set Also make sure to destroy sixels that are too big to fit in the scrollback. Fixes issues with the sixel list not being sorted correctly. --- grid.c | 91 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/grid.c b/grid.c index a79b4493..84ee5313 100644 --- a/grid.c +++ b/grid.c @@ -83,9 +83,10 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, * at the output that is *oldest* */ int offset = grid->offset + old_screen_rows; - tll(struct sixel) old_sixels = tll_init(); + tll(struct sixel) untranslated_sixels = tll_init(); + tll(struct sixel) translated_sixels = tll_init(); tll_foreach(grid->sixel_images, it) - tll_push_back(old_sixels, it->item); + tll_push_back(untranslated_sixels, it->item); tll_free(grid->sixel_images); /* Turn cursor coordinates into grid absolute coordinates */ @@ -108,7 +109,6 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, for (size_t i = 0; i < tracking_points_count; i++) tll_push_back(tracking_points, _tracking_points[i]); - /* * Walk the old grid */ @@ -122,7 +122,7 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, continue; /* Map sixels on current "old" row to current "new row" */ - tll_foreach(old_sixels, it) { + tll_foreach(untranslated_sixels, it) { if (it->item.pos.row != old_row_idx) continue; @@ -131,47 +131,17 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, /* Make sure it doesn't cross the wrap-around after being re-based */ int end = (sixel.pos.row + sixel.rows - 1) & (new_rows - 1); + if (end < sixel.pos.row) { /* TODO: split instead of destroying */ sixel_destroy(&it->item); } else { - - /* Insert sixel into the *sorted* list. */ - - /* Based on rebase_row() in sixel.c */ - /* Uses 'old' offset to ensure old sixels are treated as such */ -#define rebase_row(t, row) \ - (((row) - (grid->offset + new_screen_rows) + new_rows) & (new_rows - 1)) - - int end_row = rebase_row(term, sixel.pos.row + sixel.rows - 1); - - /* - * TODO: this is basically sixel_insert(), except we - * cannot use it since: - * - * a) we don't have a 'term' reference - * b) the grid hasn't been fully * updated yet - * (e.g. grid->num_rows is invalid etc). - */ - - bool inserted = false; - tll_foreach(grid->sixel_images, it2) { - const struct sixel *s = &it2->item; - if (rebase_row(term, s->pos.row + s->rows - 1) < end_row) { - tll_insert_before(grid->sixel_images, it2, sixel); - inserted = true; - break; - } - } - - if (!inserted) - tll_push_back(grid->sixel_images, sixel); - + /* Insert sixel into the translated, but *unsorted* list. */ + tll_push_back(translated_sixels, sixel); } /* Sixel has been either re-mapped, or destroyed */ - tll_remove(old_sixels, it); -#undef rebase_row + tll_remove(untranslated_sixels, it); } #define line_wrap() \ @@ -372,9 +342,50 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, grid->saved_cursor.lcf = false; /* Free sixels we failed to "map" to the new grid */ - tll_foreach(old_sixels, it) + tll_foreach(untranslated_sixels, it) sixel_destroy(&it->item); - tll_free(old_sixels); + tll_free(untranslated_sixels); + + /* Based on rebase_row() in sixel.c */ + /* Uses 'old' offset to ensure old sixels are treated as such */ +#define rebase_row(t, row) \ + (((row) - (grid->offset + new_screen_rows) + new_rows) & (new_rows - 1)) + + /* Re-add translated sixels, sorted according to the new grid offset */ + tll_foreach(translated_sixels, it) { + int end_row = rebase_row(term, it->item.pos.row + it->item.rows - 1); + + /* + * TODO: this is basically sixel_insert(), except we + * cannot use it since: + * + * a) we don't have a 'term' reference + * b) the grid hasn't been fully * updated yet + * (e.g. grid->num_rows is invalid etc). + */ + + if (it->item.rows >= new_rows) { + sixel_destroy(&it->item); + continue; + } + + assert(it->item.rows < new_rows); + + bool inserted = false; + tll_foreach(grid->sixel_images, it2) { + const struct sixel *s = &it2->item; + if (rebase_row(term, s->pos.row + s->rows - 1) < end_row) { + tll_insert_before(grid->sixel_images, it2, it->item); + inserted = true; + break; + } + } + + if (!inserted) + tll_push_back(grid->sixel_images, it->item); + } + tll_free(translated_sixels); +#undef rebase_row tll_free(tracking_points); } From 5e5036bec9831bb65bcf3379fe2a838e0c2b7bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 11:00:50 +0200 Subject: [PATCH 32/70] sixel: debug: more fine-grained verification of sixel image list * Verify no sixel crosses the scrollback wrap-around * Verify no sixels overlap --- sixel.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/sixel.c b/sixel.c index 88da4e28..9cec4f62 100644 --- a/sixel.c +++ b/sixel.c @@ -110,7 +110,7 @@ rebase_row(const struct terminal *term, int abs_row) } static bool -verify_sixel_list_order(const struct terminal *term) +verify_list_order(const struct terminal *term) { #if defined(_DEBUG) int prev_row = INT_MAX; @@ -146,6 +146,65 @@ verify_sixel_list_order(const struct terminal *term) return true; } +static bool +verify_no_wraparound_crossover(const struct terminal *term) +{ +#if defined(_DEBUG) + tll_foreach(term->grid->sixel_images, it) { + const struct sixel *six = &it->item; + + assert(six->pos.row >= 0); + assert(six->pos.row < term->grid->num_rows); + + int end = (six->pos.row + six->rows) & (term->grid->num_rows - 1); + assert(end >= six->pos.row); + } +#endif + return true; +} + +#include + +static bool +verify_no_overlap(const struct terminal *term) +{ +#if defined(_DEBUG) + tll_foreach(term->grid->sixel_images, it) { + const struct sixel *six1 = &it->item; + + pixman_region32_t rect1; + pixman_region32_init_rect( + &rect1, six1->pos.col, six1->pos.row, six1->cols, six1->rows); + + tll_foreach(term->grid->sixel_images, it2) { + const struct sixel *six2 = &it2->item; + + if (six1 == six2) + continue; + + pixman_region32_t rect2; + pixman_region32_init_rect( + &rect2, six2->pos.col, + six2->pos.row, six2->cols, six2->rows); + + pixman_region32_t intersection; + pixman_region32_intersect(&intersection, &rect1, &rect2); + + assert(!pixman_region32_not_empty(&intersection)); + } + } +#endif + return true; +} + +static bool +verify_sixels(const struct terminal *term) +{ + return (verify_no_wraparound_crossover(term) && + verify_list_order(term) && + verify_no_overlap(term)); +} + static void sixel_insert(struct terminal *term, struct sixel sixel) { @@ -166,9 +225,8 @@ out: tll_foreach(term->grid->sixel_images, it) { LOG_DBG(" rows=%d+%d", it->item.pos.row, it->item.rows); } -#else - verify_sixel_list_order(term); #endif + verify_sixels(term); } void @@ -185,7 +243,7 @@ sixel_scroll_up(struct terminal *term, int rows) break; } - verify_sixel_list_order(term); + verify_sixels(term); } void @@ -204,7 +262,7 @@ sixel_scroll_down(struct terminal *term, int rows) break; } - verify_sixel_list_order(term); + verify_sixels(term); } static void From 74c7373efcfe1d86a273b58a3e87559a88865e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:09:24 +0200 Subject: [PATCH 33/70] sixel: add sixel_cell_size_changed() This function should be called *after* the cell dimensions have changed, but *before* resizing/reflowing the grids. --- sixel.c | 24 ++++++++++++++++++++++++ sixel.h | 1 + 2 files changed, 25 insertions(+) diff --git a/sixel.c b/sixel.c index 9cec4f62..110c8ab5 100644 --- a/sixel.c +++ b/sixel.c @@ -484,6 +484,30 @@ sixel_overwrite_at_cursor(struct terminal *term, int width) term, term->grid->cursor.point.row, term->grid->cursor.point.col, width); } +void +sixel_cell_size_changed(struct terminal *term) +{ + struct grid *g = term->grid; + + term->grid = &term->normal; + tll_foreach(term->normal.sixel_images, it) { + struct sixel *six = &it->item; + six->rows = (six->height + term->cell_height - 1) / term->cell_height; + six->cols = (six->width + term->cell_width - 1) / term->cell_width; + } + verify_sixels(term); + + term->grid = &term->alt; + tll_foreach(term->alt.sixel_images, it) { + struct sixel *six = &it->item; + six->rows = (six->height + term->cell_height - 1) / term->cell_height; + six->cols = (six->width + term->cell_width - 1) / term->cell_width; + } + verify_sixels(term); + + term->grid = g; +} + void sixel_unhook(struct terminal *term) { diff --git a/sixel.h b/sixel.h index 666b8c40..ac763bb0 100644 --- a/sixel.h +++ b/sixel.h @@ -16,6 +16,7 @@ void sixel_destroy_all(struct terminal *term); void sixel_scroll_up(struct terminal *term, int rows); void sixel_scroll_down(struct terminal *term, int rows); +void sixel_cell_size_changed(struct terminal *term); /* * Remove sixel data from the specified location. Used when printing * or erasing characters, and when emitting new sixel images, to From 0876c7eafe7bace4acde765305e2e4d38415ce7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:10:06 +0200 Subject: [PATCH 34/70] =?UTF-8?q?sixel:=20verify-no-wraparound-crossover:?= =?UTF-8?q?=20fix=20calculation=20of=20=E2=80=98end=E2=80=99=20row?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sixel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sixel.c b/sixel.c index 110c8ab5..32af3a65 100644 --- a/sixel.c +++ b/sixel.c @@ -156,7 +156,7 @@ verify_no_wraparound_crossover(const struct terminal *term) assert(six->pos.row >= 0); assert(six->pos.row < term->grid->num_rows); - int end = (six->pos.row + six->rows) & (term->grid->num_rows - 1); + int end = (six->pos.row + six->rows - 1) & (term->grid->num_rows - 1); assert(end >= six->pos.row); } #endif From da866f6453861dda3cc517be034fe688adafeb74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:10:25 +0200 Subject: [PATCH 35/70] sixel: verify-sixels: check for bad list order last --- sixel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sixel.c b/sixel.c index 32af3a65..84b889fd 100644 --- a/sixel.c +++ b/sixel.c @@ -201,8 +201,8 @@ static bool verify_sixels(const struct terminal *term) { return (verify_no_wraparound_crossover(term) && - verify_list_order(term) && - verify_no_overlap(term)); + verify_no_overlap(term) && + verify_list_order(term)); } static void From 660d6a06eb8456a10474a9dd9bc18b1b13dcc5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:10:56 +0200 Subject: [PATCH 36/70] term: update sixel rows/cols *after* cell dimension change, *before* resize This fixes an issue where we resized+reflowed with bad rows/cols values in the sixels. --- terminal.c | 66 ++++++++++++++++++++++-------------------------------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/terminal.c b/terminal.c index a34ecb1a..f931ba7d 100644 --- a/terminal.c +++ b/terminal.c @@ -605,12 +605,38 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) term->fonts[i] = fonts[i]; } + const int old_cell_width = term->cell_width; + const int old_cell_height = term->cell_height; + term->cell_width = term->fonts[0]->space_advance.x > 0 ? term->fonts[0]->space_advance.x : term->fonts[0]->max_advance.x; term->cell_height = max(term->fonts[0]->height, term->fonts[0]->ascent + term->fonts[0]->descent); LOG_INFO("cell width=%d, height=%d", term->cell_width, term->cell_height); + if (term->cell_width < old_cell_width || + term->cell_height < old_cell_height) + { + /* + * The cell size has decreased. + * + * This means sixels, which we cannot resize, no longer fit + * into their "allocated" grid space. + * + * To be able to fit them, we would have to change the grid + * content. Inserting empty lines _might_ seem acceptable, but + * we'd also need to insert empty columns, which would break + * existing layout completely. + * + * So we delete them. + */ + sixel_destroy_all(term); + } else if (term->cell_width != old_cell_width || + term->cell_height != old_cell_height) + { + 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); return true; @@ -1501,45 +1527,7 @@ term_font_size_adjust(struct terminal *term, double amount) term->font_sizes[i].px_size = -1; } - const int old_cell_width = term->cell_width; - const int old_cell_height = term->cell_height; - - if (!reload_fonts(term)) - return false; - - if (term->cell_width < old_cell_width || - term->cell_height < old_cell_height) - { - /* - * The cell size has decreased. - * - * This means sixels, which we cannot resize, no longer fit - * into their "allocated" grid space. - * - * To be able to fit them, we would have to change the grid - * content. Inserting empty lines _might_ seem acceptable, but - * we'd also need to insert empty columns, which would break - * existing layout completely. - * - * So we delete them. - */ - sixel_destroy_all(term); - } else if (term->cell_width != old_cell_width || - term->cell_height != old_cell_height) - { - tll_foreach(term->normal.sixel_images, it) { - struct sixel *six = &it->item; - six->rows = (six->height + term->cell_height - 1) / term->cell_height; - six->cols = (six->width + term->cell_width - 1) / term->cell_width; - } - - tll_foreach(term->alt.sixel_images, it) { - struct sixel *six = &it->item; - six->rows = (six->height + term->cell_height - 1) / term->cell_height; - six->cols = (six->width + term->cell_width - 1) / term->cell_width; - } - } - return true; + return reload_fonts(term); } bool From 2e7afc615c4b3a32a383da2efad8e30dc3fd9eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:12:44 +0200 Subject: [PATCH 37/70] sixel: implement reflow Move sixel reflow from grid_reflow() to sixel_reflow(). This lets us use internal sixel functions to update the sixels. Note that grid_reflow() still needs to remap the sixelss coordinates. --- grid.c | 55 +------------------------------------------------------ sixel.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ sixel.h | 2 ++ 3 files changed, 51 insertions(+), 54 deletions(-) diff --git a/grid.c b/grid.c index 84ee5313..a779c1b3 100644 --- a/grid.c +++ b/grid.c @@ -84,7 +84,6 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, int offset = grid->offset + old_screen_rows; tll(struct sixel) untranslated_sixels = tll_init(); - tll(struct sixel) translated_sixels = tll_init(); tll_foreach(grid->sixel_images, it) tll_push_back(untranslated_sixels, it->item); tll_free(grid->sixel_images); @@ -129,18 +128,7 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, struct sixel sixel = it->item; sixel.pos.row = new_row_idx; - /* Make sure it doesn't cross the wrap-around after being re-based */ - int end = (sixel.pos.row + sixel.rows - 1) & (new_rows - 1); - - if (end < sixel.pos.row) { - /* TODO: split instead of destroying */ - sixel_destroy(&it->item); - } else { - /* Insert sixel into the translated, but *unsorted* list. */ - tll_push_back(translated_sixels, sixel); - } - - /* Sixel has been either re-mapped, or destroyed */ + tll_push_back(grid->sixel_images, sixel); tll_remove(untranslated_sixels, it); } @@ -346,46 +334,5 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, sixel_destroy(&it->item); tll_free(untranslated_sixels); - /* Based on rebase_row() in sixel.c */ - /* Uses 'old' offset to ensure old sixels are treated as such */ -#define rebase_row(t, row) \ - (((row) - (grid->offset + new_screen_rows) + new_rows) & (new_rows - 1)) - - /* Re-add translated sixels, sorted according to the new grid offset */ - tll_foreach(translated_sixels, it) { - int end_row = rebase_row(term, it->item.pos.row + it->item.rows - 1); - - /* - * TODO: this is basically sixel_insert(), except we - * cannot use it since: - * - * a) we don't have a 'term' reference - * b) the grid hasn't been fully * updated yet - * (e.g. grid->num_rows is invalid etc). - */ - - if (it->item.rows >= new_rows) { - sixel_destroy(&it->item); - continue; - } - - assert(it->item.rows < new_rows); - - bool inserted = false; - tll_foreach(grid->sixel_images, it2) { - const struct sixel *s = &it2->item; - if (rebase_row(term, s->pos.row + s->rows - 1) < end_row) { - tll_insert_before(grid->sixel_images, it2, it->item); - inserted = true; - break; - } - } - - if (!inserted) - tll_push_back(grid->sixel_images, it->item); - } - tll_free(translated_sixels); -#undef rebase_row - tll_free(tracking_points); } diff --git a/sixel.c b/sixel.c index 84b889fd..52eaa406 100644 --- a/sixel.c +++ b/sixel.c @@ -508,6 +508,54 @@ sixel_cell_size_changed(struct terminal *term) term->grid = g; } +void +sixel_reflow(struct terminal *term) +{ + struct grid *g = term->grid; + + for (size_t i = 0; i < 2; i++) { + struct grid *grid = i == 0 ? &term->normal : &term->alt; + + term->grid = grid; + + /* Need the “real” list to be empty from the beginning */ + tll(struct sixel) copy = tll_init(); + tll_foreach(grid->sixel_images, it) + tll_push_back(copy, it->item); + tll_free(grid->sixel_images); + + tll_rforeach(copy, it) { + struct sixel *six = &it->item; + int start = six->pos.row; + int end = (start + six->rows - 1) & (grid->num_rows - 1); + + if (end < start) { + /* Crosses scrollback wrap-around */ + /* TOOD: split image */ + sixel_destroy(six); + continue; + } + + if (six->rows > grid->num_rows) { + /* Image too large */ + /* TODO: keep bottom part? */ + sixel_destroy(six); + continue; + } + + /* Sixels that didn’t overlap may now do so, which isn’t + * allowed of course */ + _sixel_overwrite_by_rectangle( + term, six->pos.row, six->pos.col, six->rows, six->cols); + sixel_insert(term, it->item); + } + + tll_free(copy); + } + + term->grid = g; +} + void sixel_unhook(struct terminal *term) { diff --git a/sixel.h b/sixel.h index ac763bb0..6cd7324e 100644 --- a/sixel.h +++ b/sixel.h @@ -17,6 +17,8 @@ void sixel_scroll_up(struct terminal *term, int rows); void sixel_scroll_down(struct terminal *term, int rows); void sixel_cell_size_changed(struct terminal *term); +void sixel_reflow(struct terminal *term); + /* * Remove sixel data from the specified location. Used when printing * or erasing characters, and when emitting new sixel images, to From af7fd00909c7da55b966b90293b6551a308bf725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:13:40 +0200 Subject: [PATCH 38/70] sixel: unhook: only call render_refresh() once --- sixel.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sixel.c b/sixel.c index 52eaa406..0d69e658 100644 --- a/sixel.c +++ b/sixel.c @@ -618,11 +618,10 @@ sixel_unhook(struct terminal *term) image.width, image.height, img_data, stride); - + /* Allocate space *first*, then insert */ for (size_t i = 0; i < image.rows; i++) term_linefeed(term); term_carriage_return(term); - render_refresh(term); sixel_insert(term, image); @@ -635,6 +634,8 @@ sixel_unhook(struct terminal *term) term->sixel.image.height = 0; term->sixel.max_col = 0; term->sixel.pos = (struct coord){0, 0}; + + render_refresh(term); } static unsigned From e19ee5f4d16f4cba0c093e8f49454939a6035bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:14:09 +0200 Subject: [PATCH 39/70] render: resize: call sixel_reflow() after reflowing grids --- render.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/render.c b/render.c index 20d66512..a5df70f7 100644 --- a/render.c +++ b/render.c @@ -20,6 +20,7 @@ #include "grid.h" #include "quirks.h" #include "selection.h" +#include "sixel.h" #include "shm.h" #include "util.h" #include "xmalloc.h" @@ -2165,6 +2166,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force) term->cols = new_cols; term->rows = new_rows; + sixel_reflow(term); + LOG_DBG("resize: %dx%d, 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, From e8f703eb6544867c191ce3e9b2277c12599fab57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:32:29 +0200 Subject: [PATCH 40/70] =?UTF-8?q?sixel:=20verify-no-overlap:=20initialize?= =?UTF-8?q?=20=E2=80=98intersection=E2=80=99=20pixman=20region?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sixel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sixel.c b/sixel.c index 0d69e658..bea90414 100644 --- a/sixel.c +++ b/sixel.c @@ -188,6 +188,7 @@ verify_no_overlap(const struct terminal *term) six2->pos.row, six2->cols, six2->rows); pixman_region32_t intersection; + pixman_region32_init(&intersection); pixman_region32_intersect(&intersection, &rect1, &rect2); assert(!pixman_region32_not_empty(&intersection)); From 29d00684627640e4fa908964a2ea04af0707bc58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:32:53 +0200 Subject: [PATCH 41/70] sixel: verify-no-overlap: free pixman regions --- sixel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sixel.c b/sixel.c index bea90414..54eea50c 100644 --- a/sixel.c +++ b/sixel.c @@ -192,7 +192,12 @@ verify_no_overlap(const struct terminal *term) pixman_region32_intersect(&intersection, &rect1, &rect2); assert(!pixman_region32_not_empty(&intersection)); + + pixman_region32_fini(&intersection); + pixman_region32_fini(&rect2); } + + pixman_region32_fini(&rect1); } #endif return true; From 74703822fb59f9c5ffd3684b16f3df3f6681a7e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 13:33:56 +0200 Subject: [PATCH 42/70] sixel: TOOD -> TODO (fixes codespell build error) --- sixel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sixel.c b/sixel.c index 54eea50c..157bcc09 100644 --- a/sixel.c +++ b/sixel.c @@ -537,7 +537,7 @@ sixel_reflow(struct terminal *term) if (end < start) { /* Crosses scrollback wrap-around */ - /* TOOD: split image */ + /* TODO: split image */ sixel_destroy(six); continue; } From 6a8130c12278d9f24791bc3508e96fcd33e1490f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 14:03:45 +0200 Subject: [PATCH 43/70] sixel: scroll: call sixel_erase() instead of sixel_destroy() This ensures the screen is updated correctly. Without this, the sixel image would remain on screen until force-refreshed by some other means. --- sixel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sixel.c b/sixel.c index 157bcc09..4de17c11 100644 --- a/sixel.c +++ b/sixel.c @@ -243,7 +243,7 @@ sixel_scroll_up(struct terminal *term, int rows) int six_start = rebase_row(term, six->pos.row); if (six_start < rows) { - sixel_destroy(six); + sixel_erase(term, six); tll_remove(term->grid->sixel_images, it); } else break; @@ -262,7 +262,7 @@ sixel_scroll_down(struct terminal *term, int rows) int six_end = rebase_row(term, six->pos.row + six->rows - 1); if (six_end >= term->grid->num_rows - rows) { - sixel_destroy(six); + sixel_erase(term, six); tll_remove(term->grid->sixel_images, it); } else break; From 96a20c9df7f7a3d10ad3ce1e215e049857835536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 14:05:37 +0200 Subject: [PATCH 44/70] =?UTF-8?q?sixel:=20overwrite-by-rectangle:=20assert?= =?UTF-8?q?=20sixels=20don=E2=80=99t=20cross=20scrollback=20wrap-around?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sixel.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sixel.c b/sixel.c index 4de17c11..8c95e70b 100644 --- a/sixel.c +++ b/sixel.c @@ -372,23 +372,26 @@ _sixel_overwrite_by_rectangle( const int start = row; const int end = row + height - 1; + /* We should never generate scrollback wrapping sixels */ + assert(end < term->grid->num_rows); + const int scrollback_rel_start = rebase_row(term, start); tll_foreach(term->grid->sixel_images, it) { struct sixel *six = &it->item; const int six_start = six->pos.row; - const int six_end = (six_start + six->rows - 1) & (term->grid->num_rows - 1); + const int six_end = (six_start + six->rows - 1); const int six_scrollback_rel_end = rebase_row(term, six_end); + /* We should never generate scrollback wrapping sixels */ + assert(six_end < term->grid->num_rows); + if (six_scrollback_rel_end < scrollback_rel_start) { /* All remaining sixels are *before* our rectangle */ break; } - /* We should never generate scrollback wrapping sixels */ - assert(six_end >= six_start); - if ((start <= six_start && end >= six_start) || /* Crosses sixel start boundary */ (start <= six_end && end >= six_end) || /* Crosses sixel end boundary */ (start >= six_start && end <= six_end)) /* Fully within sixel range */ From 5a2cc9c9ae744e8b5026e02dfc4c568c4e7ad95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 19:10:54 +0200 Subject: [PATCH 45/70] =?UTF-8?q?sixel:=20verify-list-order:=20add=20an=20?= =?UTF-8?q?=E2=80=98index=E2=80=99=20variable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will make it easier when debugging assertions in this function. --- sixel.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sixel.c b/sixel.c index 8c95e70b..07b16031 100644 --- a/sixel.c +++ b/sixel.c @@ -117,6 +117,9 @@ verify_list_order(const struct terminal *term) int prev_col = -1; int prev_col_count = 0; + /* To aid debugging */ + size_t idx = 0; + tll_foreach(term->grid->sixel_images, it) { int row = rebase_row(term, it->item.pos.row + it->item.rows - 1); int col = it->item.pos.col; @@ -141,6 +144,7 @@ verify_list_order(const struct terminal *term) prev_row = row; prev_col = col; prev_col_count = col_count; + idx++; } #endif return true; From 47c884da536bc03e18521a95f9f164dce927f147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 19:11:40 +0200 Subject: [PATCH 46/70] =?UTF-8?q?sixel:=20scroll-up:=20don=E2=80=99t=20bre?= =?UTF-8?q?ak=20out=20early=20of=20loop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function loops the list of sixels, and discards those that would be scrolled out if the grid offset is moved forward by the specified number of rows. The criteria is when the rebased row value is less than the number of rows to scroll. A rebased row number is a zero-based number starting at the beginning of the scrollback. Thus, when scrolling 5 rows, rows with a rebased row number between 0-4 will be scrolled out. For performance reasons, we used to break out of the loop as soon as a row number *larger* than the scroll count. This however does not work. The sixels are sorted by their *end* row. While this works in most cases (think images outputted in the shell in the normal screen), it doesn’t always. In the alt screen, where applications can print images just about anywhere, it is possible to have *any* start row number anywhere in the sixel list. Just as long as their *end* row numbers are sorted. For example, a huuuge sixel that covers the entire scrollback. This sixel will naturally be first in the list (and thus sixel_scroll_up() will visit it *last*, since it iterates the list in reverse), but should still be destroyed when scrolling. --- sixel.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sixel.c b/sixel.c index 07b16031..e584d677 100644 --- a/sixel.c +++ b/sixel.c @@ -246,11 +246,21 @@ sixel_scroll_up(struct terminal *term, int rows) struct sixel *six = &it->item; int six_start = rebase_row(term, six->pos.row); + if (six_start < rows) { sixel_erase(term, six); tll_remove(term->grid->sixel_images, it); - } else - break; + } else { + /* + * Unfortunately, we cannot break here. + * + * The sixels are sorted on their *end* row. This means + * there may be a sixel with a top row that will be + * scrolled out *anywhere* in the list (think of a huuuuge + * sixel that covers the entire scrollback) + */ + //break; + } } verify_sixels(term); From f834ae8addef13cd0faecd66b519aa1267094026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 19:17:33 +0200 Subject: [PATCH 47/70] sixel: unhook: look total number of sixels This helps debug sixel overwrites, as it makes it more visible when there are sixels that _should_ have been removed. --- sixel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sixel.c b/sixel.c index e584d677..2696f211 100644 --- a/sixel.c +++ b/sixel.c @@ -658,6 +658,9 @@ sixel_unhook(struct terminal *term) term->sixel.max_col = 0; term->sixel.pos = (struct coord){0, 0}; + LOG_DBG("you now have %zu sixels in current grid", + tll_length(term->grid->sixel_images)); + render_refresh(term); } From 3540031dc66f4b55941c6c2fbe476042bc3bcebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 19:22:47 +0200 Subject: [PATCH 48/70] =?UTF-8?q?sixel:=20cell-size-changed:=20don?= =?UTF-8?q?=E2=80=99t=20verify=20sixels=20here?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The state after this function is an intermediate state and isn’t necessarily valid. This sixels needs to be ‘reflowed’ to ensure a valid state. This is something that should be done by the caller after the text grid has been reflowed and the sixel coordinates have been re-mapped to the new grid. TODO: can/should we update the sixel cols/rows in sixel_reflow() instead? --- sixel.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sixel.c b/sixel.c index 2696f211..ee34df0a 100644 --- a/sixel.c +++ b/sixel.c @@ -518,7 +518,6 @@ sixel_cell_size_changed(struct terminal *term) six->rows = (six->height + term->cell_height - 1) / term->cell_height; six->cols = (six->width + term->cell_width - 1) / term->cell_width; } - verify_sixels(term); term->grid = &term->alt; tll_foreach(term->alt.sixel_images, it) { @@ -526,7 +525,6 @@ sixel_cell_size_changed(struct terminal *term) six->rows = (six->height + term->cell_height - 1) / term->cell_height; six->cols = (six->width + term->cell_width - 1) / term->cell_width; } - verify_sixels(term); term->grid = g; } From eec097173979d198042447739a687891ebae1ac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 19:28:22 +0200 Subject: [PATCH 49/70] sixel: scroll up/down: early return when list is empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Branch tagged as ‘likely’ for performance reason --- sixel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sixel.c b/sixel.c index ee34df0a..76b42b25 100644 --- a/sixel.c +++ b/sixel.c @@ -242,6 +242,9 @@ out: void sixel_scroll_up(struct terminal *term, int rows) { + if (likely(tll_length(term->grid->sixel_images) == 0)) + return; + tll_rforeach(term->grid->sixel_images, it) { struct sixel *six = &it->item; @@ -269,6 +272,9 @@ sixel_scroll_up(struct terminal *term, int rows) void sixel_scroll_down(struct terminal *term, int rows) { + if (likely(tll_length(term->grid->sixel_images) == 0)) + return; + assert(term->grid->num_rows >= rows); tll_foreach(term->grid->sixel_images, it) { From 0a802c2693672d84478a3fc22313552ee56a7822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Oct 2020 19:29:48 +0200 Subject: [PATCH 50/70] =?UTF-8?q?sixel:=20verify-*:=20don=E2=80=99t=20retu?= =?UTF-8?q?rn=20anything;=20rely=20on=20asserts=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sixel.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/sixel.c b/sixel.c index 76b42b25..2ae0c042 100644 --- a/sixel.c +++ b/sixel.c @@ -109,7 +109,7 @@ rebase_row(const struct terminal *term, int abs_row) return rebased_row; } -static bool +static void verify_list_order(const struct terminal *term) { #if defined(_DEBUG) @@ -126,8 +126,6 @@ verify_list_order(const struct terminal *term) int col_count = it->item.cols; assert(row <= prev_row); - if (row > prev_row) - return false; if (row == prev_row) { /* Allowed to be on the same row only if their columns @@ -135,10 +133,6 @@ verify_list_order(const struct terminal *term) assert(col + col_count <= prev_col || prev_col + prev_col_count <= col); - - if (!(col + col_count <= prev_col || - prev_col + prev_col_count <= col)) - return false; } prev_row = row; @@ -147,10 +141,9 @@ verify_list_order(const struct terminal *term) idx++; } #endif - return true; } -static bool +static void verify_no_wraparound_crossover(const struct terminal *term) { #if defined(_DEBUG) @@ -164,12 +157,9 @@ verify_no_wraparound_crossover(const struct terminal *term) assert(end >= six->pos.row); } #endif - return true; } -#include - -static bool +static void verify_no_overlap(const struct terminal *term) { #if defined(_DEBUG) @@ -204,15 +194,14 @@ verify_no_overlap(const struct terminal *term) pixman_region32_fini(&rect1); } #endif - return true; } -static bool +static void verify_sixels(const struct terminal *term) { - return (verify_no_wraparound_crossover(term) && - verify_no_overlap(term) && - verify_list_order(term)); + verify_no_wraparound_crossover(term); + verify_no_overlap(term); + verify_list_order(term); } static void From cc54c1bea7737c7456cef87d9fe05aafbb5fe057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Oct 2020 18:28:53 +0200 Subject: [PATCH 51/70] sixel: add comments to verify_*() functions --- sixel.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sixel.c b/sixel.c index 2ae0c042..e55b52b0 100644 --- a/sixel.c +++ b/sixel.c @@ -99,6 +99,15 @@ sixel_erase(struct terminal *term, struct sixel *sixel) sixel_destroy(sixel); } +/* + * Calculates the scrollback relative row number, given an absolute row number. + * + * The scrollback relative row number 0 is the *first*, and *oldest* + * row in the scrollback history (and thus the *first* row to be + * scrolled out). Thus, a higher number means further *down* in the + * scrollback, with the *highest* number being at the bottom of the + * screen, where new input appears. + */ static int rebase_row(const struct terminal *term, int abs_row) { @@ -109,6 +118,12 @@ rebase_row(const struct terminal *term, int abs_row) return rebased_row; } +/* + * Verify the sixels are sorted correctly. + * + * The sixels are sorted on their *end* row, in descending order. This + * invariant means the most recent sixels appear first in the list. + */ static void verify_list_order(const struct terminal *term) { @@ -143,6 +158,11 @@ verify_list_order(const struct terminal *term) #endif } +/* + * Verifies there aren't any sixels that cross the scrollback + * wrap-around. This invariant means a sixel's absolute row numbers + * are strictly increasing. + */ static void verify_no_wraparound_crossover(const struct terminal *term) { @@ -159,6 +179,9 @@ verify_no_wraparound_crossover(const struct terminal *term) #endif } +/* + * Verifies no sixel overlap with any other sixels. + */ static void verify_no_overlap(const struct terminal *term) { From 09e8a5b11d044ed6c6c133e25a99fe86c2f76f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Oct 2020 18:29:24 +0200 Subject: [PATCH 52/70] sixel: verify scrollback consistency: new verify function Verifies sixels have been scrolled out correctly --- sixel.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sixel.c b/sixel.c index e55b52b0..6c378546 100644 --- a/sixel.c +++ b/sixel.c @@ -179,6 +179,31 @@ verify_no_wraparound_crossover(const struct terminal *term) #endif } +/* + * Verify there aren't any sixels that cross the scrollback end. This + * invariant means a sixel's rebased row numbers are strictly + * increasing. + */ +static void +verify_scrollback_consistency(const struct terminal *term) +{ +#if defined(_DEBUG) + tll_foreach(term->grid->sixel_images, it) { + const struct sixel *six = &it->item; + + int last_row = -1; + for (int i = 0; i < six->rows; i++) { + int row_no = rebase_row(term, six->pos.row + i); + + if (last_row != -1) + assert(last_row < row_no); + + last_row = row_no; + } + } +#endif +} + /* * Verifies no sixel overlap with any other sixels. */ @@ -223,6 +248,7 @@ static void verify_sixels(const struct terminal *term) { verify_no_wraparound_crossover(term); + verify_scrollback_consistency(term); verify_no_overlap(term); verify_list_order(term); } From 329a290f82c867859222862c77a44fff08c651e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Oct 2020 18:30:23 +0200 Subject: [PATCH 53/70] sixel: ovewrite-by-rectangle: in debug builds, cross-reference against pixman Use pixman to calculate the intersection of the rectangle being overwritten, and the sixel(s). Verify our code matches. --- sixel.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/sixel.c b/sixel.c index 6c378546..53bd3e75 100644 --- a/sixel.c +++ b/sixel.c @@ -427,6 +427,13 @@ static void _sixel_overwrite_by_rectangle( struct terminal *term, int row, int col, int height, int width) { + verify_sixels(term); + +#if defined(_DEBUG) + pixman_region32_t overwrite_rect; + pixman_region32_init_rect(&overwrite_rect, col, row, width, height); +#endif + const int start = row; const int end = row + height - 1; @@ -435,6 +442,8 @@ _sixel_overwrite_by_rectangle( const int scrollback_rel_start = rebase_row(term, start); + bool UNUSED would_have_breaked = false; + tll_foreach(term->grid->sixel_images, it) { struct sixel *six = &it->item; @@ -447,9 +456,23 @@ _sixel_overwrite_by_rectangle( if (six_scrollback_rel_end < scrollback_rel_start) { /* All remaining sixels are *before* our rectangle */ + would_have_breaked = true; break; } +#if defined(_DEBUG) + pixman_region32_t six_rect; + pixman_region32_init_rect(&six_rect, six->pos.col, six->pos.row, six->cols, six->rows); + + pixman_region32_t intersection; + pixman_region32_init(&intersection); + pixman_region32_intersect(&intersection, &six_rect, &overwrite_rect); + + const bool collides = pixman_region32_not_empty(&intersection); +#else + const bool UNUSED collides = false; +#endif + if ((start <= six_start && end >= six_start) || /* Crosses sixel start boundary */ (start <= six_end && end >= six_end) || /* Crosses sixel end boundary */ (start >= six_start && end <= six_end)) /* Fully within sixel range */ @@ -461,14 +484,27 @@ _sixel_overwrite_by_rectangle( (col <= col_end && col + width - 1 >= col_end) || (col >= col_start && col + width - 1 <= col_end)) { + assert(!would_have_breaked); + struct sixel to_be_erased = *six; tll_remove(term->grid->sixel_images, it); sixel_overwrite(term, &to_be_erased, start, col, height, width); sixel_erase(term, &to_be_erased); - } - } + } else + assert(!collides); + } else + assert(!collides); + +#if defined(_DEBUG) + pixman_region32_fini(&intersection); + pixman_region32_fini(&six_rect); +#endif } + +#if defined(_DEBUG) + pixman_region32_fini(&overwrite_rect); +#endif } void From 0e4b0fefc1bef0616eeb290dfb392065a5ea31d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Oct 2020 18:31:25 +0200 Subject: [PATCH 54/70] sixel: overwrite: use pixman to calculate new the sixel boundaries When punching a hole in a sixel (and thus splitting it up into up to four new sixels), use pixman to calculate the new sixel coordinates and sizes. --- sixel.c | 153 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 76 insertions(+), 77 deletions(-) diff --git a/sixel.c b/sixel.c index 53bd3e75..b7bcb65a 100644 --- a/sixel.c +++ b/sixel.c @@ -333,93 +333,92 @@ static void sixel_overwrite(struct terminal *term, struct sixel *six, int row, int col, int height, int width) { - int rel_above = min(max(row - six->pos.row, 0), six->rows); - int rel_below = max(min(row + height - six->pos.row, six->rows), 0); - int rel_left = min(max(col - six->pos.col, 0), six->cols); - int rel_right = max(min(col + width - six->pos.col, six->cols), 0); + pixman_region32_t six_rect; + pixman_region32_init_rect( + &six_rect, + six->pos.col * term->cell_width, six->pos.row * term->cell_height, + six->width, six->height); - assert(rel_above >= 0); - assert(rel_below >= 0); - assert(rel_left >= 0); - assert(rel_right >= 0); + pixman_region32_t overwrite_rect; + pixman_region32_init_rect( + &overwrite_rect, + col * term->cell_width, row * term->cell_height, + width * term->cell_width, height * term->cell_height); - LOG_DBG("SPLIT: six (%p): %dx%d-%dx%d, %dx%d-%dx%d, rel: above=%d, below=%d, left=%d, right=%d", - (void *)six, six->pos.row, six->pos.col, six->rows, six->cols, - row, col, height, width, - rel_above, rel_below, rel_left, rel_right); +#if defined(_DEBUG) + pixman_region32_t intersection; + pixman_region32_init(&intersection); + pixman_region32_intersect(&intersection, &six_rect, &overwrite_rect); + assert(pixman_region32_not_empty(&intersection)); + pixman_region32_fini(&intersection); +#endif - struct sixel imgs[4] = {0}; + pixman_region32_t diff; + pixman_region32_init(&diff); + pixman_region32_subtract(&diff, &six_rect, &overwrite_rect); - if (rel_above > 0) { - imgs[0] = (struct sixel){ - .width = six->width, - .height = rel_above * term->cell_height, - .pos = six->pos, - }; - imgs[0].data = xmalloc(imgs[0].width * imgs[0].height * sizeof(uint32_t)); - memcpy(imgs[0].data, six->data, imgs[0].width * imgs[0].height * sizeof(uint32_t)); - } + pixman_region32_fini(&six_rect); + pixman_region32_fini(&overwrite_rect); - if (rel_below < six->rows) { - imgs[1] = (struct sixel){ - .width = six->width, - .height = six->height - rel_below * term->cell_height, - .pos = (struct coord){ - six->pos.col, - (six->pos.row + rel_below) & (term->grid->num_rows - 1)}, - }; - imgs[1].data = xmalloc(imgs[1].width * imgs[1].height * sizeof(uint32_t)); - memcpy( - imgs[1].data, - &((const uint32_t *)six->data)[rel_below * term->cell_height * six->width], - imgs[1].width * imgs[1].height * sizeof(uint32_t)); - } + int n_rects = -1; + pixman_box32_t *boxes = pixman_region32_rectangles(&diff, &n_rects); - if (rel_left > 0) { - imgs[2] = (struct sixel){ - .width = rel_left * term->cell_width, - .height = min(term->cell_height, six->height - rel_above * term->cell_height), - .pos = (struct coord){ - six->pos.col, - (six->pos.row + rel_above) & (term->grid->num_rows - 1)}, - }; - imgs[2].data = xmalloc(imgs[2].width * imgs[2].height * sizeof(uint32_t)); - for (size_t i = 0; i < imgs[2].height; i++) + for (int i = 0; i < n_rects; i++) { + LOG_DBG("box #%d: x1=%d, y1=%d, x2=%d, y2=%d", i, + boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2); + + assert(boxes[i].x1 % term->cell_width == 0); + assert(boxes[i].y1 % term->cell_height == 0); + + /* New image's position, in cells */ + const int new_col = boxes[i].x1 / term->cell_width; + const int new_row = boxes[i].y1 / term->cell_height; + + assert(new_row < term->grid->num_rows); + + /* New image's width and height, in pixels */ + const int new_width = boxes[i].x2 - boxes[i].x1; + const int new_height = boxes[i].y2 - boxes[i].y1; + + uint32_t *new_data = xmalloc(new_width * new_height * sizeof(uint32_t)); + const uint32_t *old_data = six->data; + + /* Pixel offsets into old image backing memory */ + const int x_ofs = boxes[i].x1 - six->pos.col * term->cell_width; + const int y_ofs = boxes[i].y1 - six->pos.row * term->cell_height; + + /* Copy image data, one row at a time */ + for (size_t j = 0; j < new_height; j++) { memcpy( - &((uint32_t *)imgs[2].data)[i * imgs[2].width], - &((const uint32_t *)six->data)[(rel_above * term->cell_height + i) * six->width], - imgs[2].width * sizeof(uint32_t)); - } + &new_data[(0 + j) * new_width], + &old_data[(y_ofs + j) * six->width + x_ofs], + new_width * sizeof(uint32_t)); + } - if (rel_right < six->cols) { - imgs[3] = (struct sixel){ - .width = six->width - rel_right * term->cell_width, - .height = min(term->cell_height, six->height - rel_above * term->cell_height), - .pos = (struct coord){ - six->pos.col + rel_right, - (six->pos.row + rel_above) & (term->grid->num_rows - 1)}, - }; - imgs[3].data = xmalloc(imgs[3].width * imgs[3].height * sizeof(uint32_t)); - for (size_t i = 0; i < imgs[3].height; i++) - memcpy( - &((uint32_t *)imgs[3].data)[i * imgs[3].width], - &((const uint32_t *)six->data)[(rel_above * term->cell_height + i) * six->width + rel_right * term->cell_width], - imgs[3].width * sizeof(uint32_t)); - } - - for (size_t i = 0; i < sizeof(imgs) / sizeof(imgs[0]); i++) { - if (imgs[i].data == NULL) - continue; - - imgs[i].rows = (imgs[i].height + term->cell_height - 1) / term->cell_height; - imgs[i].cols = (imgs[i].width + term->cell_width - 1) / term->cell_width; - - imgs[i].pix = pixman_image_create_bits_no_clear( + pixman_image_t *new_pix = pixman_image_create_bits_no_clear( PIXMAN_a8r8g8b8, - imgs[i].width, imgs[i].height, - imgs[i].data, imgs[i].width * sizeof(uint32_t)); - sixel_insert(term, imgs[i]); + new_width, new_height, new_data, new_width * sizeof(uint32_t)); + + struct sixel new_six = { + .data = new_data, + .pix = new_pix, + .width = new_width, + .height = new_height, + .pos = {.col = new_col, .row = new_row}, + .cols = (new_width + term->cell_width - 1) / term->cell_width, + .rows = (new_height + term->cell_height - 1) / term->cell_height, + }; + +#if defined(_DEBUG) + /* Assert we don't cross the scrollback wrap-around */ + const int new_end = new_six.pos.row + new_six.rows - 1; + assert(new_end < term->grid->num_rows); +#endif + + sixel_insert(term, new_six); } + + pixman_region32_fini(&diff); } /* Row numbers are absolute */ From d54adc526334483ebe87b6f46589229d97f3ce5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Oct 2020 18:32:44 +0200 Subject: [PATCH 55/70] sixel: unhook: do overwrite *after* linefeeding This ensures the overwrite is done when the scrollback history is in the same state as when we then insert the new image. --- sixel.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sixel.c b/sixel.c index b7bcb65a..0b971a90 100644 --- a/sixel.c +++ b/sixel.c @@ -706,8 +706,8 @@ sixel_unhook(struct terminal *term) .pos = (struct coord){start_col, cur_row}, }; - sixel_overwrite_by_rectangle( - term, cursor->row, image.pos.col, image.rows, image.cols); + assert(image.rows < term->grid->num_rows); + assert(image.pos.row + image.rows - 1 < term->grid->num_rows); LOG_DBG("generating %dx%d pixman image at %d-%d", image.width, image.height, @@ -723,6 +723,9 @@ sixel_unhook(struct terminal *term) term_linefeed(term); term_carriage_return(term); + _sixel_overwrite_by_rectangle( + term, image.pos.row, image.pos.col, image.rows, image.cols); + sixel_insert(term, image); pixel_row_idx += height; From d0c5cf6e9fa3c7f85531cfc3d3166c2cf7b6707e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Oct 2020 18:33:50 +0200 Subject: [PATCH 56/70] =?UTF-8?q?sixel:=20reflow:=20drop=20sixels=20that?= =?UTF-8?q?=20crosses=20the=20scrollback=20history=E2=80=99s=20end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes various crashes that occurred after a reflow due to the sixel image list invariants no longer being true. --- sixel.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sixel.c b/sixel.c index 0b971a90..898b8713 100644 --- a/sixel.c +++ b/sixel.c @@ -643,6 +643,29 @@ sixel_reflow(struct terminal *term) continue; } + /* Drop sixels that now cross the current scrollback end + * border. This is similar to a sixel that have been + * scrolled out */ + /* TODO: should be possible to optimize this */ + bool sixel_destroyed = false; + int last_row = -1; + + for (int j = 0; j < six->rows; j++) { + int row_no = rebase_row(term, six->pos.row + j); + if (last_row != -1 && last_row >= row_no) { + sixel_destroy(six); + sixel_destroyed = true; + break; + } + + last_row = row_no; + } + + if (sixel_destroyed) { + LOG_WARN("destroyed sixel that now crossed history"); + continue; + } + /* Sixels that didn’t overlap may now do so, which isn’t * allowed of course */ _sixel_overwrite_by_rectangle( From 98c316556f9fba1591e307bb4d25eb4e02f45026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Oct 2020 18:46:11 +0200 Subject: [PATCH 57/70] =?UTF-8?q?changelog:=20we=E2=80=99ve=20fixed=20seve?= =?UTF-8?q?ral=20sixel+reflow=20related=20bugs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64e94377..2b972b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,8 @@ * Sixel image at non-zero column positions getting sheared at seemingly random occasions (https://codeberg.org/dnkl/foot/issues/151). +* Crash after either resizing a window or changing the font size if + there were sixels present in the scrollback while doing so. ### Security From 0fa4a189384cef057d46f83296041e2220b7bcfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 9 Oct 2020 18:52:05 +0200 Subject: [PATCH 58/70] term: remove unused bit in xtsave struct --- terminal.h | 1 - 1 file changed, 1 deletion(-) diff --git a/terminal.h b/terminal.h index 60a4aba4..2d199fcb 100644 --- a/terminal.h +++ b/terminal.h @@ -258,7 +258,6 @@ struct terminal { uint32_t show_cursor:1; uint32_t auto_margin:1; uint32_t cursor_blink:1; - uint32_t insert_mode:1; uint32_t bracketed_paste:1; uint32_t focus_events:1; uint32_t alt_scrolling:1; From 5daaaa03c27aeeaa64063825f9a93915aeea9ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 9 Oct 2020 18:52:28 +0200 Subject: [PATCH 59/70] readme: clearer descriptions of secondary and tertiary DA responses --- README.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 773d6a7f..aa8d9ae1 100644 --- a/README.md +++ b/README.md @@ -322,16 +322,12 @@ chosen to use a different terminfo). You can instead use the escape sequences to read the _Secondary_ and _Tertiary Device Attributes_ (secondary/tertiary DA, for short). -The tertiary DA response is always `\EP!|464f4f54\E\\`. The `\EP!|` is -the standard tertiary DA response prefix, `DCS ! |`. The trailing -`\E\\` is of course the standard string terminator, `ST`. +The tertiary DA response is always `\EP!|464f4f54\E\\`, where +`464f4f54` if `FOOT` in hex. -In the response above, the interesting part is `464f4f54`; this is -the string _FOOT_ in hex. - -The secondary DA response is `\E[>1;XXYYZZ;0c`, where XXYYZZ is foot's -major, minor and patch version numbers, in decimal, using two digits -for each number. For example, foot-1.4.2 would respond with +The secondary DA response is `\E[>1;XXYYZZ;0c`, where `XXYYZZ` is +foot's major, minor and patch version numbers, in decimal, using two +digits for each number. For example, foot-1.4.2 would respond with `\E[>1;010402;0c`. **Note**: not all terminal emulators implement tertiary DA. Most From 5477ee88948166f76c9ac69bc28bf8af8d8bd869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 9 Oct 2020 18:53:00 +0200 Subject: [PATCH 60/70] csi: only respond to Primary DA when Ps == 0 --- CHANGELOG.md | 1 + csi.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b972b6b..2ab0f56e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ (https://codeberg.org/dnkl/foot/issues/151). * Crash after either resizing a window or changing the font size if there were sixels present in the scrollback while doing so. +* _Send Device Attributes_ to only send a response if `Ps == 0`. ### Security diff --git a/csi.c b/csi.c index 53a90805..7c4d5077 100644 --- a/csi.c +++ b/csi.c @@ -653,6 +653,11 @@ csi_dispatch(struct terminal *term, uint8_t final) break; case 'c': { + if (vt_param_get(term, 0, 0) != 0) { + UNHANDLED(); + break; + } + /* Send Device Attributes (Primary DA) */ /* From 5540e3a0e2209f9614dbb8a299192f0ea24f4d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 9 Oct 2020 18:54:54 +0200 Subject: [PATCH 61/70] readme: minor rewrite of server/daemon section --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index aa8d9ae1..7e2f17cd 100644 --- a/README.md +++ b/README.md @@ -201,14 +201,12 @@ When run normally, **foot** is a single-window application; if you want another window, start another foot process. However, foot can also be run in a _server_ mode. In this mode, one -process hosts multiple windows. Note that this is **nothing** like -tabs. When first started in server mode, **no** windows are available. +process hosts multiple windows. All Wayland communication, VT parsing +and rendering is done in the server process. -You open new windows by running `footclient`. This is a small process -that instructs the foot server to open a new terminal window. The -client process remains running until the terminal window is -closed. The exit value of the client process is that of the shell that -was running in the terminal window. +New windows are opened by running `footclient`, which remains running +until the terminal window is closed, at which point it exits with the +exit value of the client process (typically the shell). The point of this mode is **a)** reduced memory footprint - all terminal windows will share fonts and glyph cache, and **b)** reduced From f1752c76423af24b5e60eab737e37d398ff40f60 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Fri, 9 Oct 2020 08:31:55 +0100 Subject: [PATCH 62/70] config: fix "-Wformat-nonliteral" warnings --- config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.c b/config.c index ff5d6c59..e984ea25 100644 --- a/config.c +++ b/config.c @@ -464,7 +464,7 @@ parse_section_main(const char *key, const char *value, struct config *conf, if (strcmp(key, "geometry") == 0) { LOG_WARN("deprecated: %s:%d: [default]: geometry: use 'initial-window-size-pixels' instead'", path, lineno); - const char *fmt = "%s:%d: \033[1mgeometry\033[21m, use \033[1minitial-window-size-pixels\033[21m instead"; + const char fmt[] = "%s:%d: \033[1mgeometry\033[21m, use \033[1minitial-window-size-pixels\033[21m instead"; char *text = xasprintf(fmt, path, lineno); struct user_notification deprecation = { @@ -559,7 +559,7 @@ parse_section_main(const char *key, const char *value, struct config *conf, else if (strcmp(key, "scrollback") == 0) { LOG_WARN("deprecated: %s:%d: [default]: scrollback: use 'scrollback.lines' instead'", path, lineno); - const char *fmt = "%s:%d: \033[1mdefault.scrollback\033[21m, use \033[1mscrollback.lines\033[21m instead"; + const char fmt[] = "%s:%d: \033[1mdefault.scrollback\033[21m, use \033[1mscrollback.lines\033[21m instead"; char *text = xasprintf(fmt, path, lineno); struct user_notification deprecation = { @@ -1066,7 +1066,7 @@ maybe_deprecated_key_binding(struct config *conf, path, lineno, section, binding_action_map[action], binding_action_map[replacement]); - const char *fmt = "%s:%d: [%s]: \033[1m%s\033[21m, use \033[1m%s\033[21m instead"; + const char fmt[] = "%s:%d: [%s]: \033[1m%s\033[21m, use \033[1m%s\033[21m instead"; char *text = xasprintf( fmt, path, lineno, section, binding_action_map[action], binding_action_map[replacement]); From 4bf61fe2f11536c98edb8a2859f762abd5d66c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 9 Oct 2020 19:19:40 +0200 Subject: [PATCH 63/70] changelog: add contributor --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ab0f56e..76c08a10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,8 @@ ### Security ### Contributors +* [craigbarnes](https://codeberg.org/craigbarnes) + ## 1.5.0 From 282af4478413d3c9390a5332e386bd6dc049946b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 10 Oct 2020 10:27:42 +0200 Subject: [PATCH 64/70] config: bind shift+insert to primary-paste by default --- CHANGELOG.md | 2 ++ config.c | 1 + doc/foot.ini.5.scd | 4 ++-- foot.ini | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76c08a10..5747cf99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ * Default value of the **scrollback.multiplier** option in `foot.ini` from `1.0` to `3.0`. +* `shift`+`insert` now pastes from the primary selection by + default. This is in addition to middle-clicking with the mouse. ### Deprecated diff --git a/config.c b/config.c index e984ea25..437bd5d8 100644 --- a/config.c +++ b/config.c @@ -1766,6 +1766,7 @@ add_default_key_bindings(struct config *conf) add_binding(BIND_ACTION_SCROLLBACK_DOWN, shift, XKB_KEY_Page_Down); add_binding(BIND_ACTION_CLIPBOARD_COPY, ctrl_shift, XKB_KEY_C); add_binding(BIND_ACTION_CLIPBOARD_PASTE, ctrl_shift, XKB_KEY_V); + add_binding(BIND_ACTION_PRIMARY_PASTE, shift, XKB_KEY_Insert); add_binding(BIND_ACTION_SEARCH_START, ctrl_shift, XKB_KEY_R); add_binding(BIND_ACTION_FONT_SIZE_UP, ctrl, XKB_KEY_plus); add_binding(BIND_ACTION_FONT_SIZE_UP, ctrl, XKB_KEY_equal); diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 60da2d67..191c54e3 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -291,8 +291,8 @@ e.g. *search-start=none*. Pastes from the _clipboard_. Default: _Control+Shift+V_. *primary-paste* - Pastes from the _primary selection_. Default: not bound (to a - _key_, see *mouse-bindings*). + Pastes from the _primary selection_. Default: _Shift+Insert_ (also + defined in *mouse-bindings*). *search-start* Starts a scrollback/history search. Default: _Control+Shift+R_. diff --git a/foot.ini b/foot.ini index 952bf00c..aa0fda50 100644 --- a/foot.ini +++ b/foot.ini @@ -66,6 +66,7 @@ # scrollback-down-line=none # clipboard-copy=Control+Shift+C # clipboard-paste=Control+Shift+V +# primary-paste=Shift+Insert # search-start=Control+Shift+R # font-increase=Control+plus Control+equal Control+KP_Add # font-decrease=Control+minus Control+KP_Subtract From e842f4936740477a28357e8238455253aa2f02de Mon Sep 17 00:00:00 2001 From: Sergey Nazaryev Date: Sat, 10 Oct 2020 21:13:08 +0300 Subject: [PATCH 65/70] selection: use appropriate check for PRIMARY paste Assume it could be a copy-paste typo. We should check PRIMARY, not CLIPBOARD. Without this fix, we can't use PRIMARY until we copy anything to CLIPBOARD. --- CHANGELOG.md | 1 + selection.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5747cf99..7142cbe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ * Crash after either resizing a window or changing the font size if there were sixels present in the scrollback while doing so. * _Send Device Attributes_ to only send a response if `Ps == 0`. +* Paste from primary when clipboard is empty. ### Security diff --git a/selection.c b/selection.c index 6cfacc02..7c814467 100644 --- a/selection.c +++ b/selection.c @@ -1381,8 +1381,8 @@ selection_from_primary(struct seat *seat, struct terminal *term) return; } - struct wl_clipboard *clipboard = &seat->clipboard; - if (clipboard->data_offer == NULL) + struct wl_primary *primary = &seat->primary; + if (primary->data_offer == NULL) return; term->is_sending_paste_data = true; From 70a6f8882358751ad0376929353c9a31d9811700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 10 Oct 2020 23:34:21 +0200 Subject: [PATCH 66/70] =?UTF-8?q?changelog:=20update=20=E2=80=98contributo?= =?UTF-8?q?rs=E2=80=99=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7142cbe2..a34b5b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ ### Contributors * [craigbarnes](https://codeberg.org/craigbarnes) +* [zar](https://codeberg.org/zar) ## 1.5.0 From 16a525f8e2548d12f52827e563c8775628c18ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 10 Oct 2020 23:36:41 +0200 Subject: [PATCH 67/70] readme/doc: add shift+insert to list of default key bindings --- README.md | 3 +++ doc/foot.1.scd | 3 +++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 7e2f17cd..0d4ce17c 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,9 @@ These are the default shortcuts. See `man foot.ini` and the example ctrl+shift+v : Paste from _clipboard_ +shift+insert +: Paste from the _primary selection_ + ctrl+shift+r : Start a scrollback search diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 601c23f8..20ac9ebc 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -149,6 +149,9 @@ Note that these are just the defaults; they can be changed in *ctrl*+*shift*+*v* Paste from _clipboard_ +*shift*+*insert* + Paste from the _primary selection_. + *ctrl*+*shift*+*r* Start a scrollback search From a32464e296dbedd623cf444aae5b44c44e0011f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 11 Oct 2020 19:20:24 +0200 Subject: [PATCH 68/70] changelog: remove duplicate entry --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a34b5b6b..d6fbc2d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,10 +36,6 @@ (https://codeberg.org/dnkl/foot/issues/141). * Scrollback position is now retained when resizing the window (https://codeberg.org/dnkl/foot/issues/142). -* Trackpad scrolling speed. Note that it is much slower compared to - previous foot versions. Use the **multiplier** option in `foot.ini` - if you find the new speed too slow - (https://codeberg.org/dnkl/foot/issues/144). * Trackpad scrolling speed to better match the mouse scrolling speed, and to be consistent with other (Wayland) terminal emulators. Note that it is (much) slower compared to previous foot versions. Use the From 77a87b30ffd424a57c0da5563586107f3e6944ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 11 Oct 2020 19:31:01 +0200 Subject: [PATCH 69/70] changelog: prepare for 1.5.1 --- CHANGELOG.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6fbc2d0..7497e499 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -* [Unreleased](#Unreleased) +* [1.5.1](#1-5-1) * [1.5.0](#1-5-0) * [1.4.4](#1-4-4) * [1.4.3](#1-4-3) @@ -14,8 +14,8 @@ * [1.2.0](#1-2-0) -## Unreleased -### Added +## 1.5.1 + ### Changed * Default value of the **scrollback.multiplier** option in `foot.ini` @@ -24,8 +24,6 @@ default. This is in addition to middle-clicking with the mouse. -### Deprecated -### Removed ### Fixed * Mouse bindings now match even if the actual click count is larger @@ -55,7 +53,6 @@ * Paste from primary when clipboard is empty. -### Security ### Contributors * [craigbarnes](https://codeberg.org/craigbarnes) From 2f20550893e32755ffba147248b6598eba22accc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 11 Oct 2020 19:31:25 +0200 Subject: [PATCH 70/70] meson/pkgbuild: bump version to 1.5.1 --- PKGBUILD | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index eb0e16ec..cc42ced2 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,5 +1,5 @@ pkgname=('foot-git' 'foot-terminfo-git') -pkgver=1.5.0 +pkgver=1.5.1 pkgrel=1 arch=('x86_64' 'aarch64') url=https://codeberg.org/dnkl/foot diff --git a/meson.build b/meson.build index fc79f8a8..613c388b 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('foot', 'c', - version: '1.5.0', + version: '1.5.1', license: 'MIT', meson_version: '>=0.53.0', default_options: [