Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package foot for openSUSE:Factory checked in at 2022-09-01 22:11:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/foot (Old) and /work/SRC/openSUSE:Factory/.foot.new.2083 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "foot" Thu Sep 1 22:11:06 2022 rev:18 rq:1000508 version:1.13.1 Changes: -------- --- /work/SRC/openSUSE:Factory/foot/foot.changes 2022-08-08 08:45:23.918488735 +0200 +++ /work/SRC/openSUSE:Factory/.foot.new.2083/foot.changes 2022-09-01 22:12:06.768398674 +0200 @@ -1,0 +2,10 @@ +Wed Aug 31 17:38:33 UTC 2022 - Arnav Singh <opens...@arnavion.dev> + +- Update to v1.13.1: + * Window is now dimmed while in Unicode input mode. + * Fix crash on some compositors like GNOME. + * Fix crash when resizing the window or scrolling in scrollback history. + * Fix empty cells being highlighted as selected when they shouldn't be. + * Fix separate URLs being connected in URL mode if they have the same ID. + +------------------------------------------------------------------- Old: ---- foot-1.13.0.tar.gz New: ---- foot-1.13.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ foot.spec ++++++ --- /var/tmp/diff_new_pack.rP9Rft/_old 2022-09-01 22:12:07.300400129 +0200 +++ /var/tmp/diff_new_pack.rP9Rft/_new 2022-09-01 22:12:07.308400151 +0200 @@ -17,7 +17,7 @@ Name: foot -Version: 1.13.0 +Version: 1.13.1 Release: 0 Summary: A Wayland terminal emulator License: MIT ++++++ foot-1.13.0.tar.gz -> foot-1.13.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/.builds/alpine-x64.yml new/foot/.builds/alpine-x64.yml --- old/foot/.builds/alpine-x64.yml 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/.builds/alpine-x64.yml 2022-08-31 19:19:15.000000000 +0200 @@ -24,7 +24,7 @@ - font-noto-emoji sources: - - https://codeberg.org/dnkl/foot + - https://git.sr.ht/~dnkl/foot # triggers: # - action: email @@ -49,4 +49,4 @@ - codespell: | pip install codespell cd foot - ~/.local/bin/codespell -Lser,doas README.md INSTALL.md CHANGELOG.md *.c *.h doc/*.scd + ~/.local/bin/codespell -Lser,doas,zar README.md INSTALL.md CHANGELOG.md *.c *.h doc/*.scd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/.builds/alpine-x86.yml.disabled new/foot/.builds/alpine-x86.yml.disabled --- old/foot/.builds/alpine-x86.yml.disabled 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/.builds/alpine-x86.yml.disabled 2022-08-31 19:19:15.000000000 +0200 @@ -23,7 +23,7 @@ - font-noto-emoji sources: - - https://codeberg.org/dnkl/foot + - https://git.sr.ht/~dnkl/foot # triggers: # - action: email diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/.builds/freebsd-x64.yml new/foot/.builds/freebsd-x64.yml --- old/foot/.builds/freebsd-x64.yml 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/.builds/freebsd-x64.yml 2022-08-31 19:19:15.000000000 +0200 @@ -19,7 +19,7 @@ - noto-emoji sources: - - https://codeberg.org/dnkl/foot + - https://git.sr.ht/~dnkl/foot # triggers: # - action: email diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/.gitlab-ci.yml new/foot/.gitlab-ci.yml --- old/foot/.gitlab-ci.yml 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/.gitlab-ci.yml 2022-08-31 19:19:15.000000000 +0200 @@ -109,4 +109,4 @@ - apk add python3 - apk add py3-pip - pip install codespell - - codespell -Lser,doas README.md INSTALL.md CHANGELOG.md *.c *.h doc/*.scd + - codespell -Lser,doas,zar README.md INSTALL.md CHANGELOG.md *.c *.h doc/*.scd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/.woodpecker.yml new/foot/.woodpecker.yml --- old/foot/.woodpecker.yml 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/.woodpecker.yml 2022-08-31 19:19:15.000000000 +0200 @@ -9,7 +9,7 @@ - apk add python3 - apk add py3-pip - pip install codespell - - codespell -Lser,doas README.md INSTALL.md CHANGELOG.md *.c *.h doc/*.scd + - codespell -Lser,doas,zar README.md INSTALL.md CHANGELOG.md *.c *.h doc/*.scd subprojects: when: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/CHANGELOG.md new/foot/CHANGELOG.md --- old/foot/CHANGELOG.md 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/CHANGELOG.md 2022-08-31 19:19:15.000000000 +0200 @@ -1,5 +1,6 @@ # Changelog +* [1.13.1](#1-13-1) * [1.13.0](#1-13-0) * [1.12.1](#1-12-1) * [1.12.0](#1-12-0) @@ -39,6 +40,29 @@ * [1.2.0](#1-2-0) +## 1.13.1 + +### Changed + +* Window is now dimmed while in Unicode input mode. + + +### Fixed + +* Compiling against wayland-protocols < 1.25 +* Crash on buggy compositors (GNOME) that sometimes send pointer-enter + events with a NULL surface. Foot now ignores these events, and the + subsequent motion and leave events. +* Regression: ???random??? selected empty cells being highlighted as + selected when they should not. +* Crash when either resizing the terminal window, or scrolling in the + scrollback history ([#1074][1074]) +* OSC-8 URLs with matching IDs, but mismatching URIs being incorrectly + connected. + +[1074]: https://codeberg.org/dnkl/foot/pulls/1074 + + ## 1.13.0 ### Added diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/grid.c new/foot/grid.c --- old/foot/grid.c 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/grid.c 2022-08-31 19:19:15.000000000 +0200 @@ -935,13 +935,29 @@ start += cols; } - if (old_row->linebreak) { /* Erase the remaining cells */ memset(&new_row->cells[new_col_idx], 0, (new_cols - new_col_idx) * sizeof(new_row->cells[0])); new_row->linebreak = true; - line_wrap(); + + if (r + 1 < old_rows) + line_wrap(); + else if (new_row->extra != NULL && + new_row->extra->uri_ranges.count > 0) + { + /* + * line_wrap() "closes" still-open URIs. Since this is + * the *last* row, and since we???re line-breaking due + * to a hard line-break (rather than running out of + * cells in the "new_row"), there shouldn???t be an open + * URI (it would have been closed when we reached the + * end of the URI while reflowing the last "old" + * row). + */ + uint32_t last_idx = new_row->extra->uri_ranges.count - 1; + xassert(new_row->extra->uri_ranges.v[last_idx].end >= 0); + } } grid_row_free(old_grid[old_row_idx]); @@ -985,25 +1001,6 @@ /* Set offset such that the last reflowed row is at the bottom */ grid->offset = new_row_idx - new_screen_rows + 1; - if (new_col_idx == 0) { - int next_to_last_new_row_idx = new_row_idx - 1; - next_to_last_new_row_idx += new_rows; - next_to_last_new_row_idx &= new_rows - 1; - - const struct row *next_to_last_row = new_grid[next_to_last_new_row_idx]; - if (next_to_last_row != NULL && next_to_last_row->linebreak) { - /* - * The next to last row is actually the *last* row. But we - * ended the reflow with a line-break, causing an empty - * row to be inserted at the bottom. Undo this. - */ - /* TODO: can we detect this in the reflow loop above instead? */ - grid->offset--; - grid_row_free(new_grid[new_row_idx]); - new_grid[new_row_idx] = NULL; - } - } - while (grid->offset < 0) grid->offset += new_rows; while (new_grid[grid->offset] == NULL) @@ -1016,23 +1013,6 @@ 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 UNUSED idx = (grid->view + r) & (new_rows - 1); - xassert(new_grid[idx] != NULL); - } - /* Free old grid (rows already free:d) */ free(grid->rows); @@ -1040,6 +1020,17 @@ grid->num_rows = new_rows; grid->num_cols = new_cols; + /* + * Set new viewport, making sure it???s not too far down. + * + * This is done by using scrollback-start relative cooardinates, + * and bounding the new viewport to (grid_rows - screen_rows). + */ + int sb_view = grid_row_abs_to_sb( + grid, new_screen_rows, view_follows ? grid->offset : viewport.row); + grid->view = grid_row_sb_to_abs( + grid, new_screen_rows, min(sb_view, new_rows - new_screen_rows)); + /* Convert absolute coordinates to screen relative */ cursor.row -= grid->offset; while (cursor.row < 0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/input.c new/foot/input.c --- old/foot/input.c 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/input.c 2022-08-31 19:19:15.000000000 +0200 @@ -1709,11 +1709,9 @@ uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { - xassert(surface != NULL); - xassert(serial != 0); - - if (surface == NULL) { + if (unlikely(surface == NULL)) { /* Seen on mutter-3.38 */ + LOG_WARN("compositor sent pointer_enter event with a NULL surface"); return; } @@ -1866,6 +1864,16 @@ struct seat *seat = data; struct wayland *wayl = seat->wayl; struct terminal *term = seat->mouse_focus; + + if (unlikely(term == NULL)) { + /* Typically happens when the compositor sent a pointer enter + * event with a NULL surface - see wl_pointer_enter(). + * + * In this case, we never set seat->mouse_focus (since we + * can???t map the enter event to a specific window). */ + return; + } + struct wl_window *win = term->window; LOG_DBG("pointer_motion: pointer=%p, x=%d, y=%d", (void *)wl_pointer, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/meson.build new/foot/meson.build --- old/foot/meson.build 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/meson.build 2022-08-31 19:19:15.000000000 +0200 @@ -1,5 +1,5 @@ project('foot', 'c', - version: '1.13.0', + version: '1.13.1', license: 'MIT', meson_version: '>=0.58.0', default_options: [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/render.c new/foot/render.c --- old/foot/render.c 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/render.c 2022-08-31 19:19:15.000000000 +0200 @@ -1466,10 +1466,21 @@ render_overlay(struct terminal *term) { struct wl_surf_subsurf *overlay = &term->window->overlay; + bool unicode_mode_active = false; + + /* Check if unicode mode is active on at least one seat focusing + * this terminal instance */ + tll_foreach(term->wl->seats, it) { + if (it->item.unicode_mode.active) { + unicode_mode_active = true; + break; + } + } const enum overlay_style style = term->is_searching ? OVERLAY_SEARCH : term->flash.active ? OVERLAY_FLASH : + unicode_mode_active ? OVERLAY_UNICODE_MODE : OVERLAY_NONE; if (likely(style == OVERLAY_NONE)) { @@ -1488,9 +1499,21 @@ pixman_image_set_clip_region32(buf->pix[0], NULL); - pixman_color_t color = style == OVERLAY_SEARCH - ? (pixman_color_t){0, 0, 0, 0x7fff} - : (pixman_color_t){.red=0x7fff, .green=0x7fff, .blue=0, .alpha=0x7fff}; + pixman_color_t color; + + switch (style) { + case OVERLAY_NONE: + break; + + case OVERLAY_SEARCH: + case OVERLAY_UNICODE_MODE: + color = (pixman_color_t){0, 0, 0, 0x7fff}; + break; + + case OVERLAY_FLASH: + color = (pixman_color_t){.red=0x7fff, .green=0x7fff, .blue=0, .alpha=0x7fff}; + break; + } /* Bounding rectangle of damaged areas - for wl_surface_damage_buffer() */ pixman_box32_t damage_bounds; @@ -1517,7 +1540,7 @@ * region that needs to be *cleared* in this frame. * * Finally, the union of the two ???diff??? regions above, gives - * us the total region affecte by a change, in either way. We + * us the total region affected by a change, in either way. We * use this as the bounding box for the * wl_surface_damage_buffer() call. */ @@ -1605,7 +1628,7 @@ else if (buf == term->render.last_overlay_buf && style == term->render.last_overlay_style) { - xassert(style == OVERLAY_FLASH); + xassert(style == OVERLAY_FLASH || style == OVERLAY_UNICODE_MODE); shm_did_not_use_buf(buf); return; } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/selection.c new/foot/selection.c --- old/foot/selection.c 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/selection.c 2022-08-31 19:19:15.000000000 +0200 @@ -711,10 +711,26 @@ } } +enum mark_selection_variant { + MARK_SELECTION_MARK_AND_DIRTY, + MARK_SELECTION_UNMARK_AND_DIRTY, + MARK_SELECTION_MARK_FOR_RENDER, +}; + static void mark_selected_region(struct terminal *term, pixman_box32_t *boxes, - size_t count, bool selected, bool dirty_cells) + size_t count, enum mark_selection_variant mark_variant) { + const bool selected = + mark_variant == MARK_SELECTION_MARK_AND_DIRTY || + mark_variant == MARK_SELECTION_MARK_FOR_RENDER; + const bool dirty_cells = + mark_variant == MARK_SELECTION_MARK_AND_DIRTY || + mark_variant == MARK_SELECTION_UNMARK_AND_DIRTY; + const bool highlight_empty = + mark_variant != MARK_SELECTION_MARK_FOR_RENDER || + term->selection.kind == SELECTION_BLOCK; + for (size_t i = 0; i < count; i++) { const pixman_box32_t *box = &boxes[i]; @@ -737,8 +753,58 @@ row->dirty = true; for (int c = box->x1, empty_count = 0; c < box->x2; c++) { - if (selected && row->cells[c].wc == 0) { + struct cell *cell = &row->cells[c]; + + if (cell->wc == 0 && !highlight_empty) { + /* + * We used to highlight empty cells *if* they were + * followed by non-empty cell(s), since this + * corresponds to what gets extracted when the + * selection is copied (that is, empty cells + * ???between??? non-empty cells are converted to + * spaces). + * + * However, they way we handle selection updates + * (diffing the ???old??? selection area against the + * ???new??? one, using pixman regions), means we + * can???t correctly update the state of empty + * cells. The result is ???random??? empty cells being + * rendered as selected when they shouldn???t. + * + * ???Fix??? by *never* highlighting selected empty + * cells (they still get converted to spaces when + * copied, if followed by non-empty cells). + */ empty_count++; + + /* + * When the selection is *modified*, empty cells + * are treated just like non-empty cells; they are + * marked as selected, and dirtied. + * + * This is due to how the algorithm for updating + * the selection works; it uses regions to + * calculate the difference between the ???old??? and + * the ???new??? selection. This makes it impossible + * to tell if an empty cell is a *trailing* empty + * cell (that should not be highlighted), or an + * empty cells between non-empty cells (that + * *should* be highlighted). + * + * Then, when a frame is rendered, we loop the + * *visibible* cells that belong to the + * selection. At this point, we *can* tell if an + * empty cell is trailing or not. + * + * So, what we need to do is check if a + * ???selected???, and empty cell has been marked as + * selected, temporarily unmark (forcing it dirty, + * to ensure it gets re-rendered). If it is *not* + * a trailing empty cell, it will get re-tagged as + * selected in the for-loop below. + */ + cell->attrs.clean = false; + cell->attrs.selected = false; continue; } @@ -791,10 +857,10 @@ pixman_box32_t *boxes = NULL; boxes = pixman_region32_rectangles(&no_longer_selected, &n_rects); - mark_selected_region(term, boxes, n_rects, false, true); + mark_selected_region(term, boxes, n_rects, MARK_SELECTION_UNMARK_AND_DIRTY); boxes = pixman_region32_rectangles(&newly_selected, &n_rects); - mark_selected_region(term, boxes, n_rects, true, true); + mark_selected_region(term, boxes, n_rects, MARK_SELECTION_MARK_AND_DIRTY); pixman_region32_fini(&newly_selected); pixman_region32_fini(&no_longer_selected); @@ -1059,7 +1125,7 @@ int n_rects = -1; pixman_box32_t *boxes = pixman_region32_rectangles(&visible_and_selected, &n_rects); - mark_selected_region(term, boxes, n_rects, true, false); + mark_selected_region(term, boxes, n_rects, MARK_SELECTION_MARK_FOR_RENDER); pixman_region32_fini(&visible_and_selected); pixman_region32_fini(&view); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/terminal.h new/foot/terminal.h --- old/foot/terminal.h 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/terminal.h 2022-08-31 19:19:15.000000000 +0200 @@ -289,9 +289,10 @@ }; enum overlay_style { - OVERLAY_NONE = 0, - OVERLAY_SEARCH = 1, - OVERLAY_FLASH = 2, + OVERLAY_NONE, + OVERLAY_SEARCH, + OVERLAY_FLASH, + OVERLAY_UNICODE_MODE, }; typedef tll(struct ptmx_buffer) ptmx_buffer_list_t; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/url-mode.c new/foot/url-mode.c --- old/foot/url-mode.c 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/url-mode.c 2022-08-31 19:19:15.000000000 +0200 @@ -677,18 +677,23 @@ if (count == 0) return; - uint64_t seen_ids[count]; char32_t *combos[count]; generate_key_combos(conf, count, combos); size_t combo_idx = 0; - size_t id_idx = 0; tll_foreach(*urls, it) { bool id_already_seen = false; - for (size_t i = 0; i < id_idx; i++) { - if (it->item.id == seen_ids[i]) { + /* Look for already processed URLs where both the URI and the + * ID matches */ + tll_foreach(*urls, it2) { + if (&it->item == &it2->item) + break; + + if (it->item.id == it2->item.id && + strcmp(it->item.url, it2->item.url) == 0) + { id_already_seen = true; break; } @@ -696,7 +701,6 @@ if (id_already_seen) continue; - seen_ids[id_idx++] = it->item.id; /* * Scan previous URLs, and check if *this* URL matches any of @@ -730,7 +734,7 @@ char *key = ac32tombs(it->item.key); xassert(key != NULL); - LOG_DBG("URL: %s (%s)", it->item.url, key); + LOG_DBG("URL: %s (key=%s, id=%"PRIu64")", it->item.url, key, it->item.id); free(key); } #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot/wayland.c new/foot/wayland.c --- old/foot/wayland.c 2022-08-07 09:32:02.000000000 +0200 +++ new/foot/wayland.c 2022-08-31 19:19:15.000000000 +0200 @@ -706,6 +706,7 @@ term_shutdown(term); } +#if defined(XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION) static void xdg_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, @@ -713,6 +714,7 @@ { /* TODO: ensure we don't pick a bigger size */ } +#endif #if defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) static void @@ -742,7 +744,9 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = { .configure = &xdg_toplevel_configure, /*.close = */&xdg_toplevel_close, /* epoll-shim defines a macro ???close???... */ +#if defined(XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION) .configure_bounds = &xdg_toplevel_configure_bounds, +#endif #if defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) .wm_capabilities = xdg_toplevel_wm_capabilities, #endif