Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package foot for openSUSE:Factory checked in at 2024-08-16 12:23:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/foot (Old) and /work/SRC/openSUSE:Factory/.foot.new.2698 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "foot" Fri Aug 16 12:23:32 2024 rev:35 rq:1194032 version:1.18.1 Changes: -------- --- /work/SRC/openSUSE:Factory/foot/foot.changes 2024-08-03 20:05:05.420414787 +0200 +++ /work/SRC/openSUSE:Factory/.foot.new.2698/foot.changes 2024-08-16 12:24:03.040031251 +0200 @@ -1,0 +2,14 @@ +Wed Aug 14 16:27:10 UTC 2024 - Arnav Singh <opens...@arnavion.dev> + +- Update to v1.18.1: + * foot.ini options: + * desktop-notifications.command config can now also use "${muted}" + and "${sound-name}" in its template value. + * CSD buttons now activate on mouse button release, rather than press. + * Desktop notifications via OSC-99 sequence can now choose to play + a particular sound or mute the sound. + * Fixed bug in OSC-111 sequence used to reset background color not handling + alpha changes correctly, causing visual glitches. + * See https://codeberg.org/dnkl/foot/releases/tag/1.18.1 for more details. + +------------------------------------------------------------------- Old: ---- foot-1.18.0.tar.gz foot-1.18.0.tar.gz.sig New: ---- foot-1.18.1.tar.gz foot-1.18.1.tar.gz.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ foot.spec ++++++ --- /var/tmp/diff_new_pack.jOeSi3/_old 2024-08-16 12:24:03.676057684 +0200 +++ /var/tmp/diff_new_pack.jOeSi3/_new 2024-08-16 12:24:03.680057850 +0200 @@ -20,7 +20,7 @@ %define _distconfdir %{_sysconfdir} %endif Name: foot -Version: 1.18.0 +Version: 1.18.1 Release: 0 Summary: A Wayland terminal emulator License: MIT ++++++ foot-1.18.0.tar.gz -> foot-1.18.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/CHANGELOG.md new/foot-1.18.1/CHANGELOG.md --- old/foot-1.18.0/CHANGELOG.md 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/CHANGELOG.md 2024-08-14 12:00:20.000000000 +0200 @@ -1,5 +1,6 @@ # Changelog +* [1.18.1](#1-18-1) * [1.18.0](#1-18-0) * [1.17.2](#1-17-2) * [1.17.1](#1-17-1) @@ -52,6 +53,37 @@ * [1.2.0](#1-2-0) +## 1.18.1 + +### Added + +* OSC-99: support for the `s` parameter. Supported keywords are + `silent`, `system` and names from the freedesktop sound naming + specification. +* `${muted}` and `${sound-name}` added to the + `desktop-notifications.command` template. + + +### Changed + +* CSD buttons now activate on mouse button **release**, rather than + press ([#1787][1787]). + + +### Fixed + +* Regression: OSC-111 not handling alpha changes correctly, causing + visual glitches ([#1801][1801]). + +[1801]: https://codeberg.org/dnkl/foot/issues/1801 + + +### Contributors + +* Craig Barnes +* Shogo Yamazaki + + ## 1.18.0 ### Added diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/README.md new/foot-1.18.1/README.md --- old/foot-1.18.0/README.md 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/README.md 2024-08-14 12:00:20.000000000 +0200 @@ -3,10 +3,8 @@ The fast, lightweight and minimalistic Wayland terminal emulator. [](https://ci.codeberg.org/dnkl/foot) -[](https://gitlab.com/dnkl/foot/commits/master) -[](https://builds.sr.ht/~dnkl/foot?) -[](https://repology.org/project/foot/versions) +[](https://repology.org/project/foot/versions) ## Index diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/config.c new/foot-1.18.1/config.c --- old/foot-1.18.0/config.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/config.c 2024-08-14 12:00:20.000000000 +0200 @@ -356,9 +356,9 @@ /* First, check XDG_CONFIG_HOME (or .config, if unset) */ if (xdg_config_home != NULL && xdg_config_home[0] != '\0') - path = xstrjoin(xdg_config_home, "/foot/foot.ini", 0); + path = xstrjoin(xdg_config_home, "/foot/foot.ini"); else if (home_dir != NULL) - path = xstrjoin(home_dir, "/.config/foot/foot.ini", 0); + path = xstrjoin(home_dir, "/.config/foot/foot.ini"); if (path != NULL) { LOG_DBG("checking for %s", path); @@ -383,7 +383,7 @@ conf_dir = strtok(NULL, ":")) { free(path); - path = xstrjoin(conf_dir, "/foot/foot.ini", 0); + path = xstrjoin(conf_dir, "/foot/foot.ini"); LOG_DBG("checking for %s", path); int fd = open(path, O_RDONLY | O_CLOEXEC); @@ -843,7 +843,7 @@ return false; } - _include_path = xasprintf("%s/%s", home_dir, value + 2); + _include_path = xstrjoin3(home_dir, "/", value + 2); include_path = _include_path; } else include_path = value; @@ -2931,7 +2931,7 @@ const char *wayland_display = getenv("WAYLAND_DISPLAY"); if (wayland_display == NULL) { - return xstrjoin(xdg_runtime, "/foot.sock", 0); + return xstrjoin(xdg_runtime, "/foot.sock"); } return xasprintf("%s/foot-%s.sock", xdg_runtime, wayland_display); @@ -3242,7 +3242,7 @@ parse_modifiers(XKB_MOD_NAME_SHIFT, 5, &conf->mouse.selection_override_modifiers); tokenize_cmdline( - "notify-send --wait --app-name ${app-id} --icon ${app-id} --category ${category} --urgency ${urgency} --expire-time ${expire-time} --hint STRING:image-path:${icon} --replace-id ${replace-id} ${action-argument} --print-id -- ${title} ${body}", + "notify-send --wait --app-name ${app-id} --icon ${app-id} --category ${category} --urgency ${urgency} --expire-time ${expire-time} --hint STRING:image-path:${icon} --hint BOOLEAN:suppress-sound:${muted} --hint STRING:sound-name:${sound-name} --replace-id ${replace-id} ${action-argument} --print-id -- ${title} ${body}", &conf->desktop_notifications.command.argv.args); tokenize_cmdline("--action ${action-name}=${action-label}", &conf->desktop_notifications.command_action_arg.argv.args); tokenize_cmdline("xdg-open ${url}", &conf->url.launch.argv.args); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/doc/foot.ini.5.scd new/foot-1.18.1/doc/foot.ini.5.scd --- old/foot-1.18.0/doc/foot.ini.5.scd 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/doc/foot.ini.5.scd 2024-08-14 12:00:20.000000000 +0200 @@ -179,9 +179,10 @@ Default: _unset_ -*box-drawings-uses-font-glyphs* Boolean. When disabled, foot generates - box/line drawing characters itself. The are several advantages to - doing this instead of using font glyphs: +*box-drawings-uses-font-glyphs* + Boolean. When disabled, foot generates box/line drawing characters + itself. The are several advantages to doing this instead of using + font glyphs: - No antialiasing effects where e.g. line endpoints appear dimmed down, or blurred. @@ -195,6 +196,13 @@ When enabled, box/line drawing characters are rendered using font glyphs. This may result in a more uniform look, in some use cases. + When disabled, foot will render the following Unicode codepoints + by itself: + + - U+02500 - U+0259F + - U+02800 - U+028FF + - U+1Fb00 - U+1FB9B + Default: _no_. *dpi-aware* @@ -459,6 +467,17 @@ below. Can be used together with e.g. notify-send's *--replace-id* option. + _${muted}_ is replaced by either *true* or *false*, depending + on whether the notification has requested all notification + sounds be muted. It is intended to set the *suppress-sound* + hint (with e.g. notify-send's *--hint* option). + + _${sound-name}_ is replaced by sound-name requested by the + notification. This should be a name from the freedesktop sound + naming specification, but this is not something that foot + enforces. It is intended to set the *sound-name* hint (with + e.g. notify-send's *--hint* option). + _${action-argument}_ will be expanded to the *command-action-argument* option, for each notification action. There will always be at least one action, the @@ -568,6 +587,8 @@ --urgency ${urgency}++ --expire-time ${expire-time}++ --hint STRING:image-path:${icon}++ + --hint BOOLEAN:suppress-sound:${muted}++ + --hint STRING:sound-name:${sound-name}++ --replace-id ${replace-id}++ ${action-argument}++ --print-id++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/foot.ini new/foot-1.18.1/foot.ini --- old/foot-1.18.0/foot.ini 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/foot.ini 2024-08-14 12:00:20.000000000 +0200 @@ -47,7 +47,7 @@ # command-focused=no [desktop-notifications] -# command=notify-send --wait --app-name ${app-id} --icon ${app-id} --category ${category} --urgency ${urgency} --expire-time ${expire-time} --hint STRING:image-path:${icon} --replace-id ${replace-id} ${action-argument} --print-id -- ${title} ${body} +# command=notify-send --wait --app-name ${app-id} --icon ${app-id} --category ${category} --urgency ${urgency} --expire-time ${expire-time} --hint STRING:image-path:${icon} --hint BOOLEAN:suppress-sound:${muted} --hint STRING:sound-name:${sound-name} --replace-id ${replace-id} ${action-argument} --print-id -- ${title} ${body} # command-action-argument=--action ${action-name}=${action-label} # close="" # inhibit-when-focused=yes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/input.c new/foot-1.18.1/input.c --- old/foot-1.18.0/input.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/input.c 2024-08-14 12:00:20.000000000 +0200 @@ -2053,6 +2053,25 @@ } } +static bool +pointer_is_on_button(const struct terminal *term, const struct seat *seat, + enum csd_surface csd_surface) +{ + if (seat->mouse.x < 0) + return false; + if (seat->mouse.y < 0) + return false; + + struct csd_data info = get_csd_data(term, csd_surface); + if (seat->mouse.x > info.width) + return false; + + if (seat->mouse.y > info.height) + return false; + + return true; +} + static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) @@ -2085,16 +2104,42 @@ int x = wl_fixed_to_int(surface_x) * term->scale; int y = wl_fixed_to_int(surface_y) * term->scale; + enum term_surface surf_kind = term->active_surface; + int button = 0; + bool send_to_client = false; + bool is_on_button = false; + + /* If current surface is a button, check if pointer was on it + *before* the motion event */ + switch (surf_kind) { + case TERM_SURF_BUTTON_MINIMIZE: + is_on_button = pointer_is_on_button(term, seat, CSD_SURF_MINIMIZE); + break; + + case TERM_SURF_BUTTON_MAXIMIZE: + is_on_button = pointer_is_on_button(term, seat, CSD_SURF_MAXIMIZE); + break; + + case TERM_SURF_BUTTON_CLOSE: + is_on_button = pointer_is_on_button(term, seat, CSD_SURF_CLOSE); + break; + + case TERM_SURF_NONE: + case TERM_SURF_GRID: + case TERM_SURF_TITLE: + case TERM_SURF_BORDER_LEFT: + case TERM_SURF_BORDER_RIGHT: + case TERM_SURF_BORDER_TOP: + case TERM_SURF_BORDER_BOTTOM: + break; + } + seat->pointer.hidden = false; seat->mouse.x = x; seat->mouse.y = y; term_xcursor_update_for_seat(term, seat); - enum term_surface surf_kind = term->active_surface; - int button = 0; - bool send_to_client = false; - if (tll_length(seat->mouse.buttons) > 0) { const struct button_tracker *tracker = &tll_front(seat->mouse.buttons); surf_kind = tracker->surf_kind; @@ -2104,9 +2149,21 @@ switch (surf_kind) { case TERM_SURF_NONE: + break; + case TERM_SURF_BUTTON_MINIMIZE: + if (pointer_is_on_button(term, seat, CSD_SURF_MINIMIZE) != is_on_button) + render_refresh_csd(term); + break; + case TERM_SURF_BUTTON_MAXIMIZE: + if (pointer_is_on_button(term, seat, CSD_SURF_MAXIMIZE) != is_on_button) + render_refresh_csd(term); + break; + case TERM_SURF_BUTTON_CLOSE: + if (pointer_is_on_button(term, seat, CSD_SURF_CLOSE) != is_on_button) + render_refresh_csd(term); break; case TERM_SURF_TITLE: @@ -2246,8 +2303,8 @@ } static const struct key_binding * - match_mouse_binding(const struct seat *seat, const struct terminal *term, - int button) +match_mouse_binding(const struct seat *seat, const struct terminal *term, + int button) { if (seat->wl_keyboard != NULL && seat->kbd.xkb_state != NULL) { /* Seat has keyboard - use mouse bindings *with* modifiers */ @@ -2577,12 +2634,19 @@ } case TERM_SURF_BUTTON_MINIMIZE: - if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) + if (button == BTN_LEFT && + pointer_is_on_button(term, seat, CSD_SURF_MINIMIZE) && + state == WL_POINTER_BUTTON_STATE_RELEASED) + { xdg_toplevel_set_minimized(term->window->xdg_toplevel); + } break; case TERM_SURF_BUTTON_MAXIMIZE: - if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) { + if (button == BTN_LEFT && + pointer_is_on_button(term, seat, CSD_SURF_MAXIMIZE) && + state == WL_POINTER_BUTTON_STATE_RELEASED) + { if (term->window->is_maximized) xdg_toplevel_unset_maximized(term->window->xdg_toplevel); else @@ -2591,8 +2655,12 @@ break; case TERM_SURF_BUTTON_CLOSE: - if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) + if (button == BTN_LEFT && + pointer_is_on_button(term, seat, CSD_SURF_CLOSE) && + state == WL_POINTER_BUTTON_STATE_RELEASED) + { term_shutdown(term); + } break; case TERM_SURF_GRID: { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/main.c new/foot-1.18.1/main.c --- old/foot-1.18.0/main.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/main.c 2024-08-14 12:00:20.000000000 +0200 @@ -258,7 +258,7 @@ break; case 't': - tll_push_back(overrides, xstrjoin("term=", optarg, 0)); + tll_push_back(overrides, xstrjoin("term=", optarg)); break; case 'L': @@ -266,11 +266,11 @@ break; case 'T': - tll_push_back(overrides, xstrjoin("title=", optarg, 0)); + tll_push_back(overrides, xstrjoin("title=", optarg)); break; case 'a': - tll_push_back(overrides, xstrjoin("app-id=", optarg, 0)); + tll_push_back(overrides, xstrjoin("app-id=", optarg)); break; case 'D': { @@ -284,7 +284,7 @@ } case 'f': { - char *font_override = xstrjoin("font=", optarg, 0); + char *font_override = xstrjoin("font=", optarg); tll_push_back(overrides, font_override); break; } @@ -425,19 +425,19 @@ * that does not exist on this system, then the above call may return * NULL. We should just continue with the fallback method below. */ - LOG_WARN("setlocale() failed"); - locale = "C"; + LOG_ERR("setlocale() failed. The most common cause is that the " + "configured locale is not available, or has been misspelled"); } - LOG_INFO("locale: %s", locale); + LOG_INFO("locale: %s", locale != NULL ? locale : "<invalid>"); - bool bad_locale = !locale_is_utf8(); + bool bad_locale = locale == NULL || !locale_is_utf8(); if (bad_locale) { static const char fallback_locales[][12] = { "C.UTF-8", "en_US.UTF-8", }; - char *saved_locale = xstrdup(locale); + char *saved_locale = locale != NULL ? xstrdup(locale) : NULL; /* * Try to force an UTF-8 locale. If we succeed, launch the @@ -448,13 +448,23 @@ const char *const fallback_locale = fallback_locales[i]; if (setlocale(LC_CTYPE, fallback_locale) != NULL) { - LOG_WARN("'%s' is not a UTF-8 locale, using '%s' instead", - saved_locale, fallback_locale); - - user_notification_add_fmt( - &user_notifications, USER_NOTIFICATION_WARNING, - "'%s' is not a UTF-8 locale, using '%s' instead", - saved_locale, fallback_locale); + if (saved_locale != NULL) { + LOG_WARN( + "'%s' is not a UTF-8 locale, falling back to '%s'", + saved_locale, fallback_locale); + + user_notification_add_fmt( + &user_notifications, USER_NOTIFICATION_WARNING, + "'%s' is not a UTF-8 locale, falling back to '%s'", + saved_locale, fallback_locale); + + } else { + LOG_WARN( + "invalid locale, falling back to '%s'", fallback_locale); + user_notification_add_fmt( + &user_notifications, USER_NOTIFICATION_WARNING, + "invalid locale, falling back to '%s'", fallback_locale); + } bad_locale = false; break; @@ -462,14 +472,22 @@ } if (bad_locale) { - LOG_ERR( - "'%s' is not a UTF-8 locale, and failed to find a fallback", - saved_locale); - - user_notification_add_fmt( - &user_notifications, USER_NOTIFICATION_ERROR, - "'%s' is not a UTF-8 locale, and failed to find a fallback", - saved_locale); + if (saved_locale != NULL) { + LOG_ERR( + "'%s' is not a UTF-8 locale, and failed to find a fallback", + saved_locale); + + user_notification_add_fmt( + &user_notifications, USER_NOTIFICATION_ERROR, + "'%s' is not a UTF-8 locale, and failed to find a fallback", + saved_locale); + } else { + LOG_ERR("invalid locale, and failed to find a fallback"); + + user_notification_add_fmt( + &user_notifications, USER_NOTIFICATION_ERROR, + "invalid locale, and failed to find a fallback"); + } } free(saved_locale); } @@ -658,15 +676,19 @@ UNITTEST { - char *s = xstrjoin("foo", "bar", 0); + char *s = xstrjoin("foo", "bar"); xassert(streq(s, "foobar")); free(s); - s = xstrjoin("foo", "bar", ' '); + s = xstrjoin3("foo", " ", "bar"); xassert(streq(s, "foo bar")); free(s); - s = xstrjoin("foo", "bar", ','); + s = xstrjoin3("foo", ",", "bar"); xassert(streq(s, "foo,bar")); free(s); + + s = xstrjoin3("foo", "bar", "baz"); + xassert(streq(s, "foobarbaz")); + free(s); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/meson.build new/foot-1.18.1/meson.build --- old/foot-1.18.0/meson.build 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/meson.build 2024-08-14 12:00:20.000000000 +0200 @@ -1,5 +1,5 @@ project('foot', 'c', - version: '1.18.0', + version: '1.18.1', license: 'MIT', meson_version: '>=0.59.0', default_options: [ @@ -12,12 +12,16 @@ cc = meson.get_compiler('c') -if cc.has_function('memfd_create') +if cc.has_function('memfd_create', + args: ['-D_GNU_SOURCE'], + prefix: '#include <sys/mman.h>') add_project_arguments('-DMEMFD_CREATE', language: 'c') endif # Missing on DragonFly, FreeBSD < 14.1 -if cc.has_function('execvpe') +if cc.has_function('execvpe', + args: ['-D_GNU_SOURCE'], + prefix: '#include <unistd.h>') add_project_arguments('-DEXECVPE', language: 'c') endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/notify.c new/foot-1.18.1/notify.c --- old/foot-1.18.0/notify.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/notify.c 2024-08-14 12:00:20.000000000 +0200 @@ -34,6 +34,7 @@ free(notif->icon_cache_id); free(notif->icon_symbolic_name); free(notif->icon_data); + free(notif->sound_name); free(notif->xdg_token); free(notif->stdout_data); @@ -77,7 +78,7 @@ LOG_DBG("wrote icon data to %s", name); *filename = xstrdup(name); - *symbolic_name = xasprintf("file://%s", *filename); + *symbolic_name = xstrjoin("file://", *filename); return true; } @@ -421,9 +422,12 @@ ? "normal" : "critical"; LOG_DBG("notify: title=\"%s\", body=\"%s\", app-id=\"%s\", category=\"%s\", " - "urgency=\"%s\", icon=\"%s\", expires=%d, replaces=%u (tracking: %s)", + "urgency=\"%s\", icon=\"%s\", expires=%d, replaces=%u, muted=%s, " + "sound-name=%s (tracking: %s)", title, body, app_id, notif->category, urgency_str, icon_name_or_path, - notif->expire_time, replaces_id, track_notification ? "yes" : "no"); + notif->expire_time, replaces_id, + notif->muted ? "yes" : "no", notif->sound_name, + track_notification ? "yes" : "no"); xassert(title != NULL); if (title == NULL) @@ -463,13 +467,16 @@ } if (!spawn_expand_template( - &term->conf->desktop_notifications.command, 10, + &term->conf->desktop_notifications.command, 12, (const char *[]){ "app-id", "window-title", "icon", "title", "body", "category", - "urgency", "expire-time", "replace-id", "action-argument"}, + "urgency", "muted", "sound-name", "expire-time", "replace-id", + "action-argument"}, (const char *[]){ app_id, term->window_title, icon_name_or_path, title, body, notif->category != NULL ? notif->category : "", urgency_str, + notif->muted ? "true" : "false", + notif->sound_name != NULL ? notif->sound_name : "", expire_time, replaces_id_str, /* Custom expansion below, since we need to expand to multiple arguments */ @@ -542,6 +549,7 @@ notif->icon_data = NULL; notif->icon_data_sz = 0; notif->icon_path = NULL; + notif->sound_name = NULL; notif->icon_fd = -1; notif->stdout_fd = -1; struct notification *new_notif = &tll_back(term->active_notifications); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/notify.h new/foot-1.18.1/notify.h --- old/foot-1.18.0/notify.h 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/notify.h 2024-08-14 12:00:20.000000000 +0200 @@ -52,6 +52,9 @@ bool report_activated; /* OSC-99: report notification activation to client */ bool report_closed; /* OSC-99: report notification closed to client */ + bool muted; /* Explicitly mute the notification */ + char *sound_name; /* Should be set to NULL if muted == true */ + /* * Used internally by notify */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/osc.c new/foot-1.18.1/osc.c --- old/foot-1.18.0/osc.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/osc.c 2024-08-14 12:00:20.000000000 +0200 @@ -564,6 +564,33 @@ }); } +IGNORE_WARNING("-Wpedantic") +static bool +verify_kitty_id_is_valid(const char *id) +{ + const size_t len = strlen(id); + + for (size_t i = 0; i < len; i++) { + switch (id[i]) { + case 'a' ... 'z': + case 'A' ... 'Z': + case '0' ... '9': + case '_': + case '-': + case '+': + case '.': + break; + + default: + return false; + } + } + + return true; +} +UNIGNORE_WARNINGS + + static void kitty_notification(struct terminal *term, char *string) { @@ -582,6 +609,7 @@ char *icon_cache_id = NULL; /* The 'g' parameter */ char *symbolic_icon = NULL; /* The 'n' parameter */ char *category = NULL; /* The 't' parameter */ + char *sound_name = NULL; /* The 's' parameter */ char *payload = NULL; bool focus = true; /* The 'a' parameter */ @@ -672,8 +700,11 @@ case 'i': /* id */ - free(id); - id = xstrdup(value); + if (verify_kitty_id_is_valid(value)) { + free(id); + id = xstrdup(value); + } else + LOG_WARN("OSC-99: ignoring invalid 'i' identifier"); break; case 'p': @@ -709,7 +740,7 @@ char reply[128]; int n = xsnprintf( reply, sizeof(reply), - "\033]99;i=%s:p=?;p=%s:a=%s:o=%s:u=%s:c=1:w=1%s", + "\033]99;i=%s:p=?;p=%s:a=%s:o=%s:u=%s:c=1:w=1:s=system,silent,error,warn,warning,info,question%s", reply_id, p_caps, a_caps, when_caps, u_caps, terminator); xassert(n < sizeof(reply)); @@ -753,10 +784,15 @@ break; } - case 'f': - free(app_id); - app_id = base64_decode(value, NULL); + case 'f': { + /* App-name */ + char *decoded = base64_decode(value, NULL); + if (decoded != NULL) { + free(app_id); + app_id = decoded; + } break; + } case 't': { /* Type (category) */ @@ -767,7 +803,7 @@ else { /* Append, comma separated */ char *old_category = category; - category = xstrjoin(old_category, decoded, ','); + category = xstrjoin3(old_category, ",", decoded); free(decoded); free(old_category); } @@ -775,6 +811,32 @@ break; } + case 's': { + /* Sound */ + char *decoded = base64_decode(value, NULL); + if (decoded != NULL) { + free(sound_name); + sound_name = decoded; + + const char *translated_name = NULL; + + if (streq(decoded, "error")) + translated_name = "dialog-error"; + else if (streq(decoded, "warn") || streq(decoded, "warning")) + translated_name = "dialog-warning"; + else if (streq(decoded, "info")) + translated_name = "dialog-information"; + else if (streq(decoded, "question")) + translated_name = "dialog-question"; + + if (translated_name != NULL) { + free(sound_name); + sound_name = xstrdup(translated_name); + } + } + break; + } + case 'g': /* graphical ID (see 'n' and 'p=icon') */ free(icon_cache_id); @@ -910,12 +972,25 @@ category = NULL; /* Prevent double free */ } else { /* Append, comma separated */ - char *new_category = xstrjoin(notif->category, category, ','); + char *new_category = xstrjoin3(notif->category, ",", category); free(notif->category); notif->category = new_category; } } + if (sound_name != NULL) { + notif->muted = streq(sound_name, "silent"); + + if (notif->muted || streq(sound_name, "system")) { + free(notif->sound_name); + notif->sound_name = NULL; + } else { + free(notif->sound_name); + notif->sound_name = sound_name; + sound_name = NULL; /* Prevent double free */ + } + } + /* Handled chunked payload - append to existing metadata */ switch (payload_type) { case PAYLOAD_TITLE: @@ -929,7 +1004,7 @@ payload = NULL; } else { char *old = *ptr; - *ptr = xstrjoin(old, payload, 0); + *ptr = xstrjoin(old, payload); free(old); } break; @@ -963,7 +1038,7 @@ tll_push_back(notif->actions, xstrdup(button)); } } - + break; } } @@ -1002,7 +1077,7 @@ alive_ids = xstrdup(item_id); else { char *old_alive_ids = alive_ids; - alive_ids = xstrjoin(old_alive_ids, item_id, ','); + alive_ids = xstrjoin3(old_alive_ids, ",", item_id); free(old_alive_ids); } } @@ -1037,6 +1112,7 @@ free(symbolic_icon); free(payload); free(category); + free(sound_name); } void @@ -1305,13 +1381,22 @@ term_damage_color(term, COLOR_DEFAULT, 0); break; - case 111: /* Reset default text background color */ + case 111: { /* Reset default text background color */ LOG_DBG("resetting background color"); + bool alpha_changed = term->colors.alpha != term->conf->colors.alpha; + term->colors.bg = term->conf->colors.bg; term->colors.alpha = term->conf->colors.alpha; + + if (alpha_changed) { + wayl_win_alpha_changed(term->window); + term_font_subpixel_changed(term); + } + term_damage_color(term, COLOR_DEFAULT, 0); term_damage_margins(term); break; + } case 112: LOG_DBG("resetting cursor color"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/render.c new/foot-1.18.1/render.c --- old/foot-1.18.0/render.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/render.c 2024-08-14 12:00:20.000000000 +0200 @@ -2627,6 +2627,32 @@ pixman_image_unref(src); } +static bool +any_pointer_is_on_button(const struct terminal *term, enum csd_surface csd_surface) +{ + if (unlikely(tll_length(term->wl->seats) == 0)) + return false; + + tll_foreach(term->wl->seats, it) { + const struct seat *seat = &it->item; + + if (seat->mouse.x < 0) + continue; + if (seat->mouse.y < 0) + continue; + + struct csd_data info = get_csd_data(term, csd_surface); + if (seat->mouse.x > info.width) + continue; + + if (seat->mouse.y > info.height) + continue; + return true; + } + + return false; +} + static void render_csd_button(struct terminal *term, enum csd_surface surf_idx, const struct csd_data *info, struct buffer *buf) @@ -2650,21 +2676,24 @@ _color = term->conf->colors.table[4]; /* blue */ is_set = term->conf->csd.color.minimize_set; conf_color = &term->conf->csd.color.minimize; - is_active = term->active_surface == TERM_SURF_BUTTON_MINIMIZE; + is_active = term->active_surface == TERM_SURF_BUTTON_MINIMIZE && + any_pointer_is_on_button(term, CSD_SURF_MINIMIZE); break; case CSD_SURF_MAXIMIZE: _color = term->conf->colors.table[2]; /* green */ is_set = term->conf->csd.color.maximize_set; conf_color = &term->conf->csd.color.maximize; - is_active = term->active_surface == TERM_SURF_BUTTON_MAXIMIZE; + is_active = term->active_surface == TERM_SURF_BUTTON_MAXIMIZE && + any_pointer_is_on_button(term, CSD_SURF_MAXIMIZE); break; case CSD_SURF_CLOSE: _color = term->conf->colors.table[1]; /* red */ is_set = term->conf->csd.color.close_set; conf_color = &term->conf->csd.color.quit; - is_active = term->active_surface == TERM_SURF_BUTTON_CLOSE; + is_active = term->active_surface == TERM_SURF_BUTTON_CLOSE && + any_pointer_is_on_button(term, CSD_SURF_CLOSE); break; default: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/slave.c new/foot-1.18.1/slave.c --- old/foot-1.18.0/slave.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/slave.c 2024-08-14 12:00:20.000000000 +0200 @@ -55,7 +55,7 @@ path != NULL; path = strtok(NULL, ":")) { - char *full = xasprintf("%s/%s", path, file); + char *full = xstrjoin3(path, "/", file); if (access(full, F_OK) == 0) { free(path_list); return full; @@ -158,6 +158,7 @@ xassert(prefix != NULL); if (write(fd, prefix, strlen(prefix)) < 0 || + write(fd, "foot: ", 6) < 0 || write(fd, notif->text, strlen(notif->text)) < 0 || write(fd, postfix, strlen(postfix)) < 0) { @@ -180,7 +181,8 @@ } static bool -emit_notifications_of_kind(int fd, const user_notifications_t *notifications, +emit_notifications_of_kind(int fd, + const user_notifications_t *notifications, enum user_notification_kind kind) { tll_foreach(*notifications, it) { @@ -329,7 +331,7 @@ if (env->envp == NULL) setenv(name, value, 1); else { - char *e = xasprintf("%s=%s", name, value); + char *e = xstrjoin3(name, "=", value); /* Search for existing variable. If found, replace it with the new value */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/terminal.c new/foot-1.18.1/terminal.c --- old/foot-1.18.0/terminal.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/terminal.c 2024-08-14 12:00:20.000000000 +0200 @@ -994,7 +994,7 @@ snprintf(size, sizeof(size), ":size=%.2f", term->font_sizes[i][j].pt_size * scale); - names[i][j] = xstrjoin(font->pattern, size, 0); + names[i][j] = xstrjoin(font->pattern, size); } } @@ -1021,9 +1021,9 @@ char *attrs[4] = { [0] = dpi, /* Takes ownership */ - [1] = xstrjoin(dpi, !custom_bold ? ":weight=bold" : "", 0), - [2] = xstrjoin(dpi, !custom_italic ? ":slant=italic" : "", 0), - [3] = xstrjoin(dpi, !custom_bold_italic ? ":weight=bold:slant=italic" : "", 0), + [1] = xstrjoin(dpi, !custom_bold ? ":weight=bold" : ""), + [2] = xstrjoin(dpi, !custom_italic ? ":slant=italic" : ""), + [3] = xstrjoin(dpi, !custom_bold_italic ? ":weight=bold:slant=italic" : ""), }; struct fcft_font *fonts[4]; @@ -1048,8 +1048,10 @@ for (size_t i = 0; i < 4; i++) { if (tids[i] != 0) { int ret; - thrd_join(tids[i], &ret); - success = success && ret; + if (thrd_join(tids[i], &ret) != 0) + success = false; + else + success = success && ret; } else success = false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/utils/xtgettcap.c new/foot-1.18.1/utils/xtgettcap.c --- old/foot-1.18.0/utils/xtgettcap.c 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/utils/xtgettcap.c 2024-08-14 12:00:20.000000000 +0200 @@ -141,6 +141,9 @@ const char *key = strtok(key_value, "="); const char *value = strtok(NULL, "="); + if (key == NULL) + continue; + #if 0 assert((success && value != NULL) || (!success && value == NULL)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/foot-1.18.0/xmalloc.h new/foot-1.18.1/xmalloc.h --- old/foot-1.18.0/xmalloc.h 2024-08-02 14:28:16.000000000 +0200 +++ new/foot-1.18.1/xmalloc.h 2024-08-14 12:00:20.000000000 +0200 @@ -25,16 +25,25 @@ } static inline char * -xstrjoin(const char *s1, const char *s2, char delim) +xstrjoin(const char *s1, const char *s2) { size_t n1 = strlen(s1); - size_t n2 = delim > 0 ? 1 : 0; - size_t n3 = strlen(s2); + size_t n2 = strlen(s2); + char *joined = xmalloc(n1 + n2 + 1); + memcpy(joined, s1, n1); + memcpy(joined + n1, s2, n2 + 1); + return joined; +} +static inline char * +xstrjoin3(const char *s1, const char *s2, const char *s3) +{ + size_t n1 = strlen(s1); + size_t n2 = strlen(s2); + size_t n3 = strlen(s3); char *joined = xmalloc(n1 + n2 + n3 + 1); memcpy(joined, s1, n1); - if (delim > 0) - joined[n1] = delim; - memcpy(joined + n1 + n2, s2, n3 + 1); + memcpy(joined + n1, s2, n2); + memcpy(joined + n1 + n2, s3, n3 + 1); return joined; }