diff --git a/CHANGELOG.md b/CHANGELOG.md index 30a73369..78803ea3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog * [Unreleased](#unreleased) +* [1.26.1](#1-26-1) * [1.26.0](#1-26-0) * [1.25.0](#1-25-0) * [1.24.0](#1-24-0) @@ -75,16 +76,39 @@ ### Removed ### Fixed -* Wrong documented default value for `initial-color-theme` in - `foot.ini(5)` ([#2292][2292]). +* Other output (key presses, query replies etc) being mixed with paste + data, both interactive pastes and OSC-52 ([#2307][2307]). +* Scrollback search not working correctly when the terminal + application has enabled the kitty keyboard protocol with release + event reporting ([#2316][2316]). -[2292]: https://codeberg.org/dnkl/foot/issues/2292 +[2307]: https://codeberg.org/dnkl/foot/issues/2307 +[2316]: https://codeberg.org/dnkl/foot/issues/2316 ### Security ### Contributors +## 1.26.1 + +### Fixed + +* Wrong documented default value for `initial-color-theme` in + `foot.ini(5)` ([#2292][2292]). +* Occasional crashes when closing a window and + `tweak.pre-apply-damage=yes` (the default) ([#2288][2288]). + +[2292]: https://codeberg.org/dnkl/foot/issues/2292 +[2288]: https://codeberg.org/dnkl/foot/issues/2288 + + +### Contributors + +* Roshless +* vlkrs + + ## 1.26.0 ### Added diff --git a/char32.c b/char32.c index 3d6c2c78..be5bf229 100644 --- a/char32.c +++ b/char32.c @@ -34,7 +34,7 @@ _Static_assert( #if !defined(__STDC_UTF_32__) || !__STDC_UTF_32__ #error "char32_t does not use UTF-32" #endif -#if (!defined(__STDC_ISO_10646__) || !__STDC_ISO_10646__) && !defined(__FreeBSD__) +#if (!defined(__STDC_ISO_10646__) || !__STDC_ISO_10646__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #error "wchar_t does not use UTF-32" #endif diff --git a/input.c b/input.c index aa6b7f1d..6a829a70 100644 --- a/input.c +++ b/input.c @@ -1643,31 +1643,34 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, seat->wayl->key_binding_manager, term->conf, seat); xassert(bindings != NULL); - if (pressed) { - if (term->unicode_mode.active) { + if (term->unicode_mode.active) { + if (pressed) unicode_mode_input(seat, term, sym); - return; - } + return; + } - else if (term->is_searching) { + else if (term->is_searching) { + if (pressed) { if (should_repeat) start_repeater(seat, key); search_input( seat, term, bindings, key, sym, mods, consumed, raw_syms, raw_count, serial); - return; } + return; + } - else if (urls_mode_is_active(term)) { + else if (urls_mode_is_active(term)) { + if (pressed) { if (should_repeat) start_repeater(seat, key); urls_input( seat, term, bindings, key, sym, mods, consumed, raw_syms, raw_count, serial); - return; } + return; } #if defined(_DEBUG) && defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG diff --git a/meson.build b/meson.build index 66b3d6bc..a0e602bb 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('foot', 'c', - version: '1.26.0', + version: '1.26.1', license: 'MIT', meson_version: '>=0.59.0', default_options: [ @@ -12,6 +12,11 @@ is_debug_build = get_option('buildtype').startswith('debug') cc = meson.get_compiler('c') +# Newer clang versions warns when using __COUNTER__ without -std=c2y +if cc.has_argument('-Wc2y-extensions') + add_project_arguments('-Wno-c2y-extensions', language: 'c') +endif + if cc.has_function('memfd_create', args: ['-D_GNU_SOURCE'], prefix: '#include ') diff --git a/osc.c b/osc.c index 4dc47172..82793fb5 100644 --- a/osc.c +++ b/osc.c @@ -261,12 +261,12 @@ osc_from_clipboard(struct terminal *term, const char *source) if (from_clipboard) { text_from_clipboard( - seat, term, &from_clipboard_cb, &from_clipboard_done, ctx); + seat, term, true, &from_clipboard_cb, &from_clipboard_done, ctx); } if (from_primary) { text_from_primary( - seat, term, &from_clipboard_cb, &from_clipboard_done, ctx); + seat, term, true, &from_clipboard_cb, &from_clipboard_done, ctx); } } diff --git a/search.c b/search.c index 5228bf61..5386ffd3 100644 --- a/search.c +++ b/search.c @@ -1375,13 +1375,13 @@ execute_binding(struct seat *seat, struct terminal *term, case BIND_ACTION_SEARCH_CLIPBOARD_PASTE: text_from_clipboard( - seat, term, &from_clipboard_cb, &from_clipboard_done, term); + seat, term, false, &from_clipboard_cb, &from_clipboard_done, term); *update_search_result = *redraw = true; return true; case BIND_ACTION_SEARCH_PRIMARY_PASTE: text_from_primary( - seat, term, &from_clipboard_cb, &from_clipboard_done, term); + seat, term, false, &from_clipboard_cb, &from_clipboard_done, term); *update_search_result = *redraw = true; return true; diff --git a/selection.c b/selection.c index f07396a5..0a479ee8 100644 --- a/selection.c +++ b/selection.c @@ -2006,6 +2006,7 @@ struct clipboard_receive { int timeout_fd; struct itimerspec timeout; bool bracketed; + bool no_strip; bool quote_paths; void (*decoder)(struct clipboard_receive *ctx, char *data, size_t size); @@ -2153,6 +2154,8 @@ static bool fdm_receive(struct fdm *fdm, int fd, int events, void *data) { struct clipboard_receive *ctx = data; + const bool no_strip = ctx->no_strip; + const bool bracketed = ctx->bracketed; if ((events & EPOLLHUP) && !(events & EPOLLIN)) goto done; @@ -2204,13 +2207,14 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data) break; case '\n': - if (!ctx->bracketed) + if (!no_strip && !bracketed) { p[i] = '\r'; + } break; case '\r': /* Convert \r\n -> \r */ - if (!ctx->bracketed && i + 1 < left && p[i + 1] == '\n') { + if (!no_strip && !bracketed && i + 1 < left && p[i + 1] == '\n') { i++; skip_one(); goto again; @@ -2223,8 +2227,11 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data) case '\x11': case '\x12': case '\x13': case '\x14': case '\x15': case '\x16': case '\x17': case '\x18': case '\x19': case '\x1a': case '\x1b': case '\x1c': case '\x1d': case '\x1e': case '\x1f': - skip_one(); - goto again; + if (!no_strip) { + skip_one(); + goto again; + } + break; /* * In addition to stripping non-formatting C0 controls, @@ -2242,7 +2249,7 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data) * handled above. */ case '\b': case '\x7f': case '\x00': - if (!ctx->bracketed) { + if (!no_strip && !bracketed) { skip_one(); goto again; } @@ -2263,8 +2270,8 @@ done: } static void -begin_receive_clipboard(struct terminal *term, int read_fd, - enum data_offer_mime_type mime_type, +begin_receive_clipboard(struct terminal *term, bool no_strip, + int read_fd, enum data_offer_mime_type mime_type, void (*cb)(char *data, size_t size, void *user), void (*done)(void *user), void *user) { @@ -2297,6 +2304,7 @@ begin_receive_clipboard(struct terminal *term, int read_fd, .timeout_fd = timeout_fd, .timeout = timeout, .bracketed = term->bracketed_paste, + .no_strip = no_strip, .quote_paths = term->grid == &term->normal, .decoder = (mime_type == DATA_OFFER_MIME_URI_LIST ? &fdm_receive_decoder_uri @@ -2326,6 +2334,7 @@ err: void text_from_clipboard(struct seat *seat, struct terminal *term, + bool no_strip, void (*cb)(char *data, size_t size, void *user), void (*done)(void *user), void *user) { @@ -2358,7 +2367,8 @@ text_from_clipboard(struct seat *seat, struct terminal *term, /* Don't keep our copy of the write-end open (or we'll never get EOF) */ close(write_fd); - begin_receive_clipboard(term, read_fd, clipboard->mime_type, cb, done, user); + begin_receive_clipboard( + term, no_strip, read_fd, clipboard->mime_type, cb, done, user); } static void @@ -2401,7 +2411,8 @@ selection_from_clipboard(struct seat *seat, struct terminal *term, uint32_t seri if (term->bracketed_paste) term_paste_data_to_slave(term, "\033[200~", 6); - text_from_clipboard(seat, term, &receive_offer, &receive_offer_done, term); + text_from_clipboard( + seat, term, false, &receive_offer, &receive_offer_done, term); } bool @@ -2470,7 +2481,7 @@ selection_to_primary(struct seat *seat, struct terminal *term, uint32_t serial) void text_from_primary( - struct seat *seat, struct terminal *term, + struct seat *seat, struct terminal *term, bool no_strip, void (*cb)(char *data, size_t size, void *user), void (*done)(void *user), void *user) { @@ -2508,7 +2519,8 @@ text_from_primary( /* Don't keep our copy of the write-end open (or we'll never get EOF) */ close(write_fd); - begin_receive_clipboard(term, read_fd, primary->mime_type, cb, done, user); + begin_receive_clipboard( + term, no_strip, read_fd, primary->mime_type, cb, done, user); } void @@ -2530,7 +2542,8 @@ selection_from_primary(struct seat *seat, struct terminal *term) if (term->bracketed_paste) term_paste_data_to_slave(term, "\033[200~", 6); - text_from_primary(seat, term, &receive_offer, &receive_offer_done, term); + text_from_primary( + seat, term, false, &receive_offer, &receive_offer_done, term); } static void @@ -2819,7 +2832,7 @@ drop(void *data, struct wl_data_device *wl_data_device) term_paste_data_to_slave(term, "\033[200~", 6); begin_receive_clipboard( - term, read_fd, clipboard->mime_type, + term, false, read_fd, clipboard->mime_type, &receive_dnd, &receive_dnd_done, ctx); /* data offer is now "owned" by the receive context */ diff --git a/selection.h b/selection.h index 26298457..b6ad099a 100644 --- a/selection.h +++ b/selection.h @@ -63,12 +63,12 @@ bool text_to_primary( * point). */ void text_from_clipboard( - struct seat *seat, struct terminal *term, + struct seat *seat, struct terminal *term, bool no_strip, void (*cb)(char *data, size_t size, void *user), void (*done)(void *user), void *user); void text_from_primary( - struct seat *seat, struct terminal *term, + struct seat *seat, struct terminal *term, bool no_strip, void (*cb)(char *data, size_t size, void *user), void (*dont)(void *user), void *user); diff --git a/terminal.c b/terminal.c index ac7922a7..8eafbcbe 100644 --- a/terminal.c +++ b/terminal.c @@ -120,7 +120,10 @@ term_to_slave(struct terminal *term, const void *data, size_t len) return false; } - if (tll_length(term->ptmx_buffers) > 0 || term->is_sending_paste_data) { + if (unlikely(tll_length(term->ptmx_buffers) > 0 || + term->is_sending_paste_data || + tll_length(term->ptmx_paste_buffers) > 0)) + { /* * Don't even try to send data *now* if there's queued up * data, since that would result in events arriving out of diff --git a/wayland.c b/wayland.c index 1d258213..f5737c1e 100644 --- a/wayland.c +++ b/wayland.c @@ -1,5 +1,6 @@ #include "wayland.h" +#include #include #include #include @@ -245,19 +246,34 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) case WL_SHM_FORMAT_ABGR16161616: wayl->shm_have_abgr161616 = true; break; } -#if defined(_DEBUG) +#if defined(_DEBUG) && LOG_ENABLE_DBG == 1 bool have_description = false; + const char c4 = (format >> 24) & 0xff; + const char c3 = (format >> 16) & 0xff; + const char c2 = (format >> 8) & 0xff; + const char c1 = (format >> 0) & 0xff; for (size_t i = 0; i < ALEN(shm_formats); i++) { if (shm_formats[i].format == format) { - LOG_DBG("shm: 0x%08x: %s", format, shm_formats[i].description); + LOG_DBG("shm: 0x%08x: %c%c%c%c - %s", + format, + isprint(c1) ? c1 : ' ', + isprint(c2) ? c2 : ' ', + isprint(c3) ? c3 : ' ', + isprint(c4) ? c4 : ' ', + shm_formats[i].description); have_description = true; break; } } if (!have_description) - LOG_DBG("shm: 0x%08x: unknown", format); + LOG_DBG("shm: 0x%08x: %c%c%c%c - unknown", + format, + isprint(c1) ? c1 : ' ', + isprint(c2) ? c2 : ' ', + isprint(c3) ? c3 : ' ', + isprint(c4) ? c4 : ' '); #endif } @@ -2177,8 +2193,6 @@ wayl_win_destroy(struct wl_window *win) struct terminal *term = win->term; - render_wait_for_preapply_damage(term); - if (win->csd.move_timeout_fd != -1) close(win->csd.move_timeout_fd); @@ -2236,6 +2250,8 @@ wayl_win_destroy(struct wl_window *win) tll_remove(win->urls, it); } + render_wait_for_preapply_damage(term); + csd_destroy(win); wayl_win_subsurface_destroy(&win->search); wayl_win_subsurface_destroy(&win->scrollback_indicator);