From cbebafbfe8d43415fa6baeb59d44bd3be0b593bf Mon Sep 17 00:00:00 2001 From: Nick Hastings Date: Tue, 4 Oct 2022 13:04:03 +0900 Subject: [PATCH 001/118] doc: fix tiny typo --- doc/footclient.1.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/footclient.1.scd b/doc/footclient.1.scd index 967a4f1b..93bddd61 100644 --- a/doc/footclient.1.scd +++ b/doc/footclient.1.scd @@ -89,7 +89,7 @@ terminal has terminated. # EXIT STATUS -Footlient will exit with code 220 if there is a failure in footclient +Footclient will exit with code 220 if there is a failure in footclient itself (for example, the server socket does not exist). If *-N*,*--no-wait* is used, footclient exits with code 0 as soon as From 2d4f0535c6507dfb7b7444f6aaff9bfe854cf5a8 Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Tue, 4 Oct 2022 20:50:44 +0200 Subject: [PATCH 002/118] Add zenburn theme This is the one included by default in previous releases. --- themes/zenburn | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 themes/zenburn diff --git a/themes/zenburn b/themes/zenburn new file mode 100644 index 00000000..3867826f --- /dev/null +++ b/themes/zenburn @@ -0,0 +1,23 @@ +[colors] +foreground=dcdccc +background=111111 + +## Normal/regular colors (color palette 0-7) +regular0=222222 # black +regular1=cc9393 # red +regular2=7f9f7f # green +regular3=d0bf8f # yellow +regular4=6ca0a3 # blue +regular5=dc8cc3 # magenta +regular6=93e0e3 # cyan +regular7=dcdccc # white + +## Bright colors (color palette 8-15) +bright0=666666 # bright black +bright1=dca3a3 # bright red +bright2=bfebbf # bright green +bright3=f0dfaf # bright yellow +bright4=8cd0d3 # bright blue +bright5=fcace3 # bright magenta +bright6=b3ffff # bright cyan +bright7=ffffff # bright white From 37218be64853dccd5574a7f5de7193c0e1a7b5e6 Mon Sep 17 00:00:00 2001 From: Alexey Sakovets Date: Mon, 3 Oct 2022 19:41:13 +0300 Subject: [PATCH 003/118] render: fix nanosec "overflow" when calculating timeout value --- CHANGELOG.md | 2 ++ render.c | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a6efd08..52d5b7be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,8 @@ * Scrollback search matches not being highlighted correctly, on compositors that does now allow Wayland buffer re-use (e.g. KDE/plasma). +* Nanosecs "overflow" when calculating timeout value for + `resize-delay-ms` option. [1173]: https://codeberg.org/dnkl/foot/issues/1173 diff --git a/render.c b/render.c index b285b120..f14911d4 100644 --- a/render.c +++ b/render.c @@ -3716,7 +3716,10 @@ send_dimensions_to_client(struct terminal *term) if (fd >= 0) { /* Reset timeout */ const struct itimerspec timeout = { - .it_value = {.tv_sec = 0, .tv_nsec = delay_ms * 1000000}, + .it_value = { + .tv_sec = delay_ms / 1000, + .tv_nsec = (delay_ms % 1000) * 1000000, + }, }; if (timerfd_settime(fd, 0, &timeout, NULL) < 0) { From fd743b51736e99a097063c1f52c242e5592c298e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 27 Sep 2022 19:05:56 +0200 Subject: [PATCH 004/118] scripts: generate-builtin-terminfo: double-escape backslash in ST Fixes an issue with XTGETTCAP, where escape sequences terminated with ST, and containing parameters were missing a trailing backslash. --- CHANGELOG.md | 2 ++ scripts/generate-builtin-terminfo.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52d5b7be..1606f3b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,8 @@ (e.g. KDE/plasma). * Nanosecs "overflow" when calculating timeout value for `resize-delay-ms` option. +* Missing backslash in ST terminator in escape sequences in the + built-in terminfo (accessed via XTGETTCAP). [1173]: https://codeberg.org/dnkl/foot/issues/1173 diff --git a/scripts/generate-builtin-terminfo.py b/scripts/generate-builtin-terminfo.py index 906e2be0..035fa1cc 100755 --- a/scripts/generate-builtin-terminfo.py +++ b/scripts/generate-builtin-terminfo.py @@ -55,6 +55,10 @@ class StringCapability(Capability): value = re.sub(r'\\E([0-7])', r'\\033" "\1', value) value = re.sub(r'\\E', r'\\033', value) else: + # Need to double-escape backslashes. These only occur in + # ‘\E\’ combos. Note that \E itself is updated below + value = value.replace('\\E\\\\', '\\E\\\\\\\\') + # Need to double-escape \E in C string literals value = value.replace('\\E', '\\\\E') From f359a8d6bcad8c7f12c6f707caa7480fd193c92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 4 Oct 2022 21:42:13 +0200 Subject: [PATCH 005/118] scripts: generate-builtin-terminfo: escape fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove ‘:’ escaping only in raw (non-parameterized) sequences * Double-escape *all* escape characters in parameterized sequences --- scripts/generate-builtin-terminfo.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/scripts/generate-builtin-terminfo.py b/scripts/generate-builtin-terminfo.py index 035fa1cc..acbf5279 100755 --- a/scripts/generate-builtin-terminfo.py +++ b/scripts/generate-builtin-terminfo.py @@ -52,18 +52,25 @@ class StringCapability(Capability): def __init__(self, name: str, value: str): # Expand \E to literal ESC in non-parameterized capabilities if '%' not in value: + # Ensure e.g. \E7 doesn’t get translated to “\0337”, which + # would be interpreted as octal 337 by the C compiler value = re.sub(r'\\E([0-7])', r'\\033" "\1', value) + + # Replace \E with an actual escape value = re.sub(r'\\E', r'\\033', value) + + # Don’t escape ‘:’ + value = value.replace('\\:', ':') + else: - # Need to double-escape backslashes. These only occur in - # ‘\E\’ combos. Note that \E itself is updated below - value = value.replace('\\E\\\\', '\\E\\\\\\\\') + value = value.replace("\\", "\\\\") + # # Need to double-escape backslashes. These only occur in + # # ‘\E\’ combos. Note that \E itself is updated below + # value = value.replace('\\E\\\\', '\\E\\\\\\\\') - # Need to double-escape \E in C string literals - value = value.replace('\\E', '\\\\E') + # # Need to double-escape \E in C string literals + # value = value.replace('\\E', '\\\\E') - # Don’t escape ‘:’ - value = value.replace('\\:', ':') super().__init__(name, value) From 9937d92c85b5e113c57abae7b74ad55972eaffab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 7 Oct 2022 14:40:22 +0200 Subject: [PATCH 006/118] utils: xtgettcap: new utility, to send XTGETTCAP queries --- meson.build | 1 + utils/meson.build | 1 + utils/xtgettcap.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 utils/meson.build create mode 100644 utils/xtgettcap.c diff --git a/meson.build b/meson.build index 4d3b6213..68c3bf19 100644 --- a/meson.build +++ b/meson.build @@ -331,6 +331,7 @@ endif subdir('completions') subdir('icons') +subdir('utils') if (get_option('tests')) subdir('tests') diff --git a/utils/meson.build b/utils/meson.build new file mode 100644 index 00000000..2836788c --- /dev/null +++ b/utils/meson.build @@ -0,0 +1 @@ +executable('xtgettcap', 'xtgettcap.c') diff --git a/utils/xtgettcap.c b/utils/xtgettcap.c new file mode 100644 index 00000000..e21de7c0 --- /dev/null +++ b/utils/xtgettcap.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct termios orig_termios; + +static void +disable_raw_mode(void) +{ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) < 0) + exit(__LINE__); +} + +static void +enable_raw_mode(void) +{ + if (tcgetattr(STDIN_FILENO, &orig_termios) < 0) + exit(__LINE__); + + atexit(disable_raw_mode); + + struct termios raw = orig_termios; + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_oflag &= ~(OPOST); + raw.c_cflag |= (CS8); + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 1; + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) < 0) + exit(__LINE__); +} + +static const char * +hexlify(const char *s) +{ + static char buf[1024]; + + const size_t len = strlen(s); + for (size_t i = 0; i < len; i++) + sprintf(&buf[i * 2], "%02x", s[i]); + buf[len * 2 + 1] = '\0'; + + return buf; +} + +static size_t +unhexlify(char *dst, const char *src) +{ + size_t count = 0; + for (const char *p = src; *p != '\0'; p += 2, dst++, count++) + sscanf(p, "%02hhx", (unsigned char *)dst); + + *dst = '\0'; + return count; +} + +int +main(int argc, const char *const *argv) +{ + enable_raw_mode(); + + const size_t query_count = argc - 1; + + printf("\x1bP+q"); + for (int i = 1; i < argc; i++) + printf("%s%s", i > 1 ? ";" : "", hexlify(argv[i])); + printf("\033\\"); + + fflush(NULL); + + size_t replies = 0; + while (replies < query_count) { + struct pollfd fds[] = {{.fd = STDIN_FILENO, .events = POLLIN}}; + int r = poll(fds, sizeof(fds) / sizeof(fds[0]), -1); + if (r < 0) + exit(__LINE__); + + char buf[1024] = {0}; + ssize_t count = read(STDIN_FILENO, buf, sizeof(buf)); + + if (count < 0) + exit(__LINE__); + + if (count == 1 && buf[0] == 'q') + break; + + printf("reply: (%zd chars): ", count); + + for (size_t i = 0; i < (size_t)count; i++) { + if (isprint(buf[i])) + printf("%c", buf[i]); + else if (buf[i] == '\033') + printf("\033[1;31m\\E\033[m"); + else + printf("%02x", (uint8_t)buf[i]); + } + printf("\r\n"); + + const char *p = buf; + const char *end = buf + count; + + while (p < end) { + + const char *ST = strstr(p, "\033\\"); + if (ST == NULL) + break; + + if (count < 5 || + (strncmp(p, "\033P1+r", 5) != 00 && + strncmp(p, "\033P0+r", 5) != 0)) + { + break; + } + + const bool success = p[2] == '1'; + + char decoded[1024]; + char copy[ST - &p[5] + 1]; + strncpy(copy, &p[5], ST - &p[5]); + copy[ST - &p[5]] = '\0'; + + char *saveptr = NULL; + for (char *key_value = strtok_r(copy, "; ", &saveptr); + key_value != NULL; + key_value = strtok_r(NULL, "; ", &saveptr)) + { + // printf("key-value=%s\n", key_value); + const char *key = strtok(key_value, "="); + const char *value = strtok(NULL, "="); + +#if 0 + assert((success && value != NULL) || + (!success && value == NULL)); +#endif + + //printf("key=%s, value=%s\n", key, value); + size_t len = unhexlify(decoded, key); + + if (value != NULL) { + decoded[len++] = '='; + len += unhexlify(&decoded[len], value); + } + + const int color = success ? 39 : 31; + + printf(" \033[%dm", color); + for (size_t i = 0 ; i < len; i++) { + if (isprint(decoded[i])) + printf("%c", decoded[i]); + else if (decoded[i] == '\033') + printf("\033[1;31m\\E\033[22;%dm", color); + else + printf("\033[1m%02x\033[22m", (uint8_t)decoded[i]); + } + printf("\033[m\r\n"); + replies++; + } + + p = ST + 2; + } + + } + + return 0; +} From 503740f8365aa67197a8ef6f710852b5caec362c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 7 Oct 2022 21:47:56 +0200 Subject: [PATCH 007/118] pgo: execute xtgettcap utility, to get profiling data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: ../utils/xtgettcap.c:175:1: error: ‘/home/daniel/src/foot/src/utils/xtgettcap.p/xtgettcap.c.gcda’ profile count data file not found [-Werror=missing-profile] --- pgo/full-inner.sh | 1 + pgo/partial.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/pgo/full-inner.sh b/pgo/full-inner.sh index 599d6aad..425d1ff0 100755 --- a/pgo/full-inner.sh +++ b/pgo/full-inner.sh @@ -15,6 +15,7 @@ rm -f "${blddir}"/pgo-ok # To ensure profiling data is generated in the build directory cd "${blddir}" +"${blddir}"/utils/xtgettcap name "${blddir}"/footclient --version "${blddir}"/foot \ --config=/dev/null \ diff --git a/pgo/partial.sh b/pgo/partial.sh index c16de324..17de7175 100755 --- a/pgo/partial.sh +++ b/pgo/partial.sh @@ -21,6 +21,7 @@ rm -f "${blddir}"/pgo-ok # To ensure profiling data is generated in the build directory cd "${blddir}" +"${blddir}"/utils/xtgettcap name "${blddir}"/footclient --version "${blddir}"/foot --version "${blddir}"/pgo "${pgo_data}" From f747650b770140d7ddf87dcf507157f9681e443e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 8 Oct 2022 16:56:28 +0200 Subject: [PATCH 008/118] install.md: add xtgettcap to PGO build instructions --- INSTALL.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index da3a667e..86280079 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -327,6 +327,7 @@ We will use the `pgo` binary along with input corpus generated by `scripts/generate-alt-random-writes.py`: ```sh +./utils/xtgettcap name ./footclient --version ./foot --version tmp_file=$(mktemp) @@ -349,9 +350,10 @@ rm ${tmp_file} ``` The first step, running `./foot --version` and `./footclient ---version` might seem unnecessary, but is needed to ensure we have -_some_ profiling data for functions not covered by the PGO helper -binary. Without this, the final link phase will fail. +--version` etc, might seem unnecessary, but is needed to ensure we +have _some_ profiling data for functions not covered by the PGO helper +binary, for **all** binaries. Without this, the final link phase will +fail. The snippet above then creates an (empty) temporary file. Then, it runs a script that generates random escape sequences (if you cat From 4fca380585b0ccddcef3082b08cbe9e5c3131e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:27:10 +0200 Subject: [PATCH 009/118] install.md: add `./utils/xtgettcap name` to "full PGO" instructions too --- INSTALL.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 86280079..d2f4e3d4 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -373,6 +373,7 @@ This method requires a running Wayland session. We will use the script `scripts/generate-alt-random-writes.py`: ```sh +./utils/xtgettcap name ./footclient --version foot_tmp_file=$(mktemp) ./foot \ @@ -386,9 +387,10 @@ rm ${foot_tmp_file} You should see a foot window open up, with random colored text. The window should close after ~1-2s. -The first step, `./footclient --version` might seem unnecessary, but -is needed to ensure we have _some_ profiling data for -`footclient`. Without this, the final link phase will fail. +The first step, `./utils/xtgettcap name && ./footclient --version` +might seem unnecessary, but is needed to ensure we have _some_ +profiling data for **all** binaries we build. Without this, the final +link phase will fail. ##### Use the generated PGO data From 807e19385480696ce9fbd8dbdee946df224eaddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 10 Oct 2022 17:17:38 +0200 Subject: [PATCH 010/118] xtgettcap: exit immediately when there are no capabilities to query for --- utils/xtgettcap.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/utils/xtgettcap.c b/utils/xtgettcap.c index e21de7c0..b3ab712a 100644 --- a/utils/xtgettcap.c +++ b/utils/xtgettcap.c @@ -67,10 +67,13 @@ unhexlify(char *dst, const char *src) int main(int argc, const char *const *argv) { - enable_raw_mode(); - const size_t query_count = argc - 1; + if (query_count == 0) + return 0; + + enable_raw_mode(); + printf("\x1bP+q"); for (int i = 1; i < argc; i++) printf("%s%s", i > 1 ? ";" : "", hexlify(argv[i])); From a9fc7ce1806d92779da9931c804a88ac444344ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 10 Oct 2022 17:18:04 +0200 Subject: [PATCH 011/118] pgo: run xtgettcap without any arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We execute xtgettcap in the parent terminal. Thus we don’t know if it implements XTGETTCAP, and thus it’s not guaranteed to exit - it may hang indefinitely waiting for a reply. Fix by not actually quering anything. --- INSTALL.md | 6 +++--- pgo/full-inner.sh | 2 +- pgo/partial.sh | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index d2f4e3d4..4c15b7b4 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -327,7 +327,7 @@ We will use the `pgo` binary along with input corpus generated by `scripts/generate-alt-random-writes.py`: ```sh -./utils/xtgettcap name +./utils/xtgettcap ./footclient --version ./foot --version tmp_file=$(mktemp) @@ -373,7 +373,7 @@ This method requires a running Wayland session. We will use the script `scripts/generate-alt-random-writes.py`: ```sh -./utils/xtgettcap name +./utils/xtgettcap ./footclient --version foot_tmp_file=$(mktemp) ./foot \ @@ -387,7 +387,7 @@ rm ${foot_tmp_file} You should see a foot window open up, with random colored text. The window should close after ~1-2s. -The first step, `./utils/xtgettcap name && ./footclient --version` +The first step, `./utils/xtgettcap && ./footclient --version` might seem unnecessary, but is needed to ensure we have _some_ profiling data for **all** binaries we build. Without this, the final link phase will fail. diff --git a/pgo/full-inner.sh b/pgo/full-inner.sh index 425d1ff0..c2205e5e 100755 --- a/pgo/full-inner.sh +++ b/pgo/full-inner.sh @@ -15,7 +15,7 @@ rm -f "${blddir}"/pgo-ok # To ensure profiling data is generated in the build directory cd "${blddir}" -"${blddir}"/utils/xtgettcap name +"${blddir}"/utils/xtgettcap "${blddir}"/footclient --version "${blddir}"/foot \ --config=/dev/null \ diff --git a/pgo/partial.sh b/pgo/partial.sh index 17de7175..6d6fdffe 100755 --- a/pgo/partial.sh +++ b/pgo/partial.sh @@ -21,7 +21,7 @@ rm -f "${blddir}"/pgo-ok # To ensure profiling data is generated in the build directory cd "${blddir}" -"${blddir}"/utils/xtgettcap name +"${blddir}"/utils/xtgettcap "${blddir}"/footclient --version "${blddir}"/foot --version "${blddir}"/pgo "${pgo_data}" From 8179d73daa95dc3b3bdd76eaecc78e456bb4686a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 5 Oct 2022 17:05:44 +0200 Subject: [PATCH 012/118] =?UTF-8?q?render:=20delay=20reflow=20for=20?= =?UTF-8?q?=E2=80=98resize-delay-ms=E2=80=99=20milliseconds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reflowing a large scrollback is *slow*. During an interactive resize, it can easily take long enough that the compositor fills the Wayland socket with configure events. Eventually, the socket becomes full and the compositor terminates the connection, causing foot to exit. This patch is work-in-progress, and the first step towards alleviating this. It delays the reflow by: * Snapshotting (copying) the original grid when an interactive resize is started. * While resizing, we apply a simple truncation resize of the grid (like we handle the alt screen). * When the resize is done, or paused for ‘resize-delay-ms’, the grid is reflowed. TODO: we *must* not allow any changes to the temporary (truncated) grid during the resize. Any changes to the grid would be lost when the final reflow is applied. That is, we must completely pause the ptmx pipe while a resize is in progress. Future improvements: The initial copy can be slow. We should be able to avoid it by rewriting the reflow algorithm to not free anything. This is complicated by the fact that some resources (e.g. sixel images) are currently *moved* to the new grid. They’d instead have to be copied. --- doc/foot.ini.5.scd | 18 ++++--- grid.c | 2 + render.c | 118 ++++++++++++++++++++++++++++++++++++++++----- terminal.h | 5 ++ 4 files changed, 123 insertions(+), 20 deletions(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 46a6d33e..6fe97c09 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -213,15 +213,19 @@ commented out will usually be installed to */etc/xdg/foot/foot.ini*. Default: _0x0_. *resize-delay-ms* - Time, in milliseconds, of "idle time" before foot sends the new - window dimensions to the client application while doing an - interactive resize of a foot window. Idle time in this context is - a period of time where the window size is not changing. + + Time, in milliseconds, of "idle time" before foot performs text + reflow, and sends the new window dimensions to the client + application while doing an interactive resize of a foot + window. Idle time in this context is a period of time where the + window size is not changing. In other words, while you are fiddling with the window size, foot - does not send the updated dimensions to the client. Only when you - pause the fiddling for *resize-delay-ms* milliseconds is the - client updated. + does not send the updated dimensions to the client. It also does a + fast "truncating" resize of the grid, instead of actually + reflowing the contents. Only when you pause the fiddling for + *resize-delay-ms* milliseconds is the client updated, and the + contents properly reflowed. Emphasis is on _while_ here; as soon as the interactive resize ends (i.e. when you let go of the window border), the final diff --git a/grid.c b/grid.c index 7bfef5cb..bccac529 100644 --- a/grid.c +++ b/grid.c @@ -210,6 +210,8 @@ grid_snapshot(const struct grid *grid) clone->offset = grid->offset; clone->view = grid->view; clone->cursor = grid->cursor; + clone->saved_cursor = grid->saved_cursor; + clone->kitty_kbd = grid->kitty_kbd; clone->rows = xcalloc(grid->num_rows, sizeof(clone->rows[0])); memset(&clone->scroll_damage, 0, sizeof(clone->scroll_damage)); memset(&clone->sixel_images, 0, sizeof(clone->sixel_images)); diff --git a/render.c b/render.c index f14911d4..034c9946 100644 --- a/render.c +++ b/render.c @@ -3663,13 +3663,54 @@ tiocswinsz(struct terminal *term) } } +static void +delayed_reflow_of_normal_grid(struct terminal *term) +{ + if (term->render.resizing.grid == NULL) + return; + + struct coord *const tracking_points[] = { + &term->selection.coords.start, + &term->selection.coords.end, + }; + + /* Reflow the original (since before the resize was started) grid, + * to the *current* dimensions */ + grid_resize_and_reflow( + term->render.resizing.grid, + term->grid->num_rows, term->grid->num_cols, + term->render.resizing.screen_rows, term->rows, + term->selection.coords.end.row >= 0 ? ALEN(tracking_points) : 0, + tracking_points); + + /* Replace the current, truncated, “normal” grid with the + * correctly reflowed one */ + grid_free(&term->normal); + term->normal = *term->render.resizing.grid; + free(term->render.resizing.grid); + + /* Reset */ + term->render.resizing.grid = NULL; + term->render.resizing.screen_rows = 0; + + /* Invalidate render pointers */ + shm_unref(term->render.last_buf); + term->render.last_buf = NULL; + term->render.last_cursor.row = NULL; + + if (term->grid == &term->normal) + term_damage_view(term); +} + static bool fdm_tiocswinsz(struct fdm *fdm, int fd, int events, void *data) { struct terminal *term = data; - if (events & EPOLLIN) + if (events & EPOLLIN) { tiocswinsz(term); + delayed_reflow_of_normal_grid(term); + } if (term->window->resize_timeout_fd >= 0) { fdm_del(fdm, term->window->resize_timeout_fd); @@ -3686,6 +3727,7 @@ send_dimensions_to_client(struct terminal *term) if (!win->is_resizing || term->conf->resize_delay_ms == 0) { /* Send new dimensions to client immediately */ tiocswinsz(term); + delayed_reflow_of_normal_grid(term); /* And make sure to reset and deallocate a lingering timer */ if (win->resize_timeout_fd >= 0) { @@ -3846,9 +3888,30 @@ maybe_resize(struct terminal *term, int width, int height, bool force) const uint32_t scrollback_lines = term->render.scrollback_lines; + /* + * Snapshot the “normal” grid. + * + * Since text reflow is slow, don’t do it *while* resizing. Only + * do it when done, or after “pausing” the resize for sufficiently + * long. We re-use the TIOCSWINSZ timer to handle this. See + * send_dimensions_to_client() and fdm_tiocswinsz(). + * + * To be able to do the final reflow correctly, we need a copy of + * the original grid, before the resize started. + */ + if (term->window->is_resizing && term->render.resizing.grid == NULL) { + /* + * TODO: snapshotting a large grid is slow. To improve, move + * normal -> resizing.grid, and instantiate a small (screen + * sized) new “normal” + */ + term->render.resizing.grid = grid_snapshot(&term->normal); + term->render.resizing.screen_rows = term->rows; + } + /* Screen rows/cols before resize */ - const int old_cols = term->cols; - const int old_rows = term->rows; + int old_cols = term->cols; + int old_rows = term->rows; /* Screen rows/cols after resize */ const int new_cols = (term->width - 2 * pad_x) / term->cell_width; @@ -3882,7 +3945,9 @@ maybe_resize(struct terminal *term, int width, int height, bool force) xassert(term->margins.top >= pad_y); xassert(term->margins.bottom >= pad_y); - if (new_cols == old_cols && new_rows == old_rows) { + if (new_cols == old_cols && new_rows == old_rows && + (term->render.resizing.grid == NULL || term->window->is_resizing)) + { LOG_DBG("grid layout unaffected; skipping reflow"); goto damage_view; } @@ -3906,16 +3971,43 @@ maybe_resize(struct terminal *term, int width, int height, bool force) * selection’s pivot point coordinates *must* be added to the * tracking points list. */ - struct coord *const tracking_points[] = { - &term->selection.coords.start, - &term->selection.coords.end, - }; - /* Resize grids */ - grid_resize_and_reflow( - &term->normal, new_normal_grid_rows, new_cols, old_rows, new_rows, - term->selection.coords.end.row >= 0 ? ALEN(tracking_points) : 0, - tracking_points); + if (term->window->is_resizing) { + /* Simple truncating resize, *while* an interactive resize is + * ongoing. */ + xassert(term->render.resizing.grid != NULL); + grid_resize_without_reflow( + &term->normal, + new_normal_grid_rows, new_cols, + old_rows, + new_rows); + } else { + /* Full text reflow */ + + if (term->render.resizing.grid != NULL) { + /* Throw away the current, truncated, “normal” grid, and + * use the original grid instead (from before the resize + * started) */ + grid_free(&term->normal); + term->normal = *term->render.resizing.grid; + free(term->render.resizing.grid); + + old_rows = term->render.resizing.screen_rows; + + term->render.resizing.grid = NULL; + term->render.resizing.screen_rows = 0; + } + + struct coord *const tracking_points[] = { + &term->selection.coords.start, + &term->selection.coords.end, + }; + + grid_resize_and_reflow( + &term->normal, new_normal_grid_rows, new_cols, old_rows, new_rows, + term->selection.coords.end.row >= 0 ? ALEN(tracking_points) : 0, + tracking_points); + } grid_resize_without_reflow( &term->alt, new_alt_grid_rows, new_cols, old_rows, new_rows); diff --git a/terminal.h b/terminal.h index 0dde6330..3afd101d 100644 --- a/terminal.h +++ b/terminal.h @@ -595,6 +595,11 @@ struct terminal { size_t search_glyph_offset; + struct { + struct grid *grid; + int screen_rows; + } resizing; + struct timespec input_time; } render; From 3565cbd636dacf15049504d686219b787783733c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 6 Oct 2022 17:09:32 +0200 Subject: [PATCH 013/118] render: performance improvements during interactive resize Instead of copying the entire grid when an interactive resize is started, stash the complete grid (to be used in the final reflow). Copy the current viewport only, to be used during the interactive resize. This gets rid of the initial "pause" when snapshotting the grid when an interactive resize is started. --- render.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/render.c b/render.c index 034c9946..d2fce8b0 100644 --- a/render.c +++ b/render.c @@ -3900,13 +3900,45 @@ maybe_resize(struct terminal *term, int width, int height, bool force) * the original grid, before the resize started. */ if (term->window->is_resizing && term->render.resizing.grid == NULL) { - /* - * TODO: snapshotting a large grid is slow. To improve, move - * normal -> resizing.grid, and instantiate a small (screen - * sized) new “normal” - */ - term->render.resizing.grid = grid_snapshot(&term->normal); + /* Stash the current ‘normal’ grid, as-is, to be used when + * doing the final reflow */ term->render.resizing.screen_rows = term->rows; + term->render.resizing.grid = xmalloc(sizeof(*term->render.resizing.grid)); + *term->render.resizing.grid = term->normal; + + + /* + * Copy the current viewport to a new grid that will be used + * during the resize. For now, throw away sixels and OSC-8 + * URLs. They’ll be "restored" when we do the final reflow. + * + * TODO: + * - sixels? + * - OSC-8? + */ + struct grid g = { + .num_rows = 1 << (32 - __builtin_clz(term->rows - 1)), + .num_cols = term->cols, + .offset = 0, + .view = 0, + .cursor = term->normal.cursor, + .saved_cursor = term->normal.saved_cursor, + .rows = xcalloc(g.num_rows, sizeof(g.rows[0])), + .cur_row = NULL, + .scroll_damage = tll_init(), + .sixel_images = tll_init(), + .kitty_kbd = term->normal.kitty_kbd, + }; + + for (size_t i = 0, j = term->normal.view; i < term->rows; + i++, j = (j + 1) & (term->normal.num_rows - 1)) + { + g.rows[i] = grid_row_alloc(term->cols, false); + memcpy(g.rows[i]->cells, term->normal.rows[j]->cells, + term->cols * sizeof(g.rows[i]->cells[0])); + } + + term->normal = g; } /* Screen rows/cols before resize */ From f4f1989b6ef341557cc90a6805d745fef2a7a815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 6 Oct 2022 17:23:56 +0200 Subject: [PATCH 014/118] render: resize: ignore ptmx read events during interactive resize --- render.c | 4 ++++ terminal.c | 12 ++++++++++++ terminal.h | 3 +++ 3 files changed, 19 insertions(+) diff --git a/render.c b/render.c index d2fce8b0..3cb544cd 100644 --- a/render.c +++ b/render.c @@ -3700,6 +3700,8 @@ delayed_reflow_of_normal_grid(struct terminal *term) if (term->grid == &term->normal) term_damage_view(term); + + term_ptmx_resume(term); } static bool @@ -3939,6 +3941,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) } term->normal = g; + term_ptmx_pause(term); } /* Screen rows/cols before resize */ @@ -4028,6 +4031,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) term->render.resizing.grid = NULL; term->render.resizing.screen_rows = 0; + term_ptmx_resume(term); } struct coord *const tracking_points[] = { diff --git a/terminal.c b/terminal.c index df17201b..ee12ae32 100644 --- a/terminal.c +++ b/terminal.c @@ -233,6 +233,18 @@ static struct timespec last = {0}; static bool cursor_blink_rearm_timer(struct terminal *term); +void +term_ptmx_pause(struct terminal *term) +{ + fdm_event_del(term->fdm, term->ptmx, EPOLLIN); +} + +void +term_ptmx_resume(struct terminal *term) +{ + fdm_event_add(term->fdm, term->ptmx, EPOLLIN); +} + /* Externally visible, but not declared in terminal.h, to enable pgo * to call this function directly */ bool diff --git a/terminal.h b/terminal.h index 3afd101d..7a281e72 100644 --- a/terminal.h +++ b/terminal.h @@ -810,6 +810,9 @@ void term_collect_urls(struct terminal *term); void term_osc8_open(struct terminal *term, uint64_t id, const char *uri); void term_osc8_close(struct terminal *term); +void term_ptmx_pause(struct terminal *term); +void term_ptmx_resume(struct terminal *term); + static inline void term_reset_grapheme_state(struct terminal *term) { #if defined(FOOT_GRAPHEME_CLUSTERING) From b52262da8e422a9b3b62a642bf7108ab03fa4cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 6 Oct 2022 17:26:38 +0200 Subject: [PATCH 015/118] changelog: fixed crash when resizing window with a very large scrollback --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1606f3b4..f97cb252 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,8 @@ `resize-delay-ms` option. * Missing backslash in ST terminator in escape sequences in the built-in terminfo (accessed via XTGETTCAP). +* Crash when interactively resizing the window with a very large + scrollback. [1173]: https://codeberg.org/dnkl/foot/issues/1173 From f70c34c5a8c6e89f6591e08fe3e26b9f0f44e6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:01:11 +0200 Subject: [PATCH 016/118] sixel: add sixel_reflow_grid() This function reflows all sixels in the specified grid. The pre-existing sixel_reflow() function is a shortcut for sixel_reflow_grid(term, &term->normal) sixel_reflow_grid(term, &term->alt); --- sixel.c | 146 +++++++++++++++++++++++++++++--------------------------- sixel.h | 4 ++ 2 files changed, 79 insertions(+), 71 deletions(-) diff --git a/sixel.c b/sixel.c index 0c94117f..c80a92a3 100644 --- a/sixel.c +++ b/sixel.c @@ -838,85 +838,89 @@ sixel_cell_size_changed(struct terminal *term) } void -sixel_reflow(struct terminal *term) +sixel_reflow_grid(struct terminal *term, struct grid *grid) { - struct grid *g = term->grid; + /* Meh - the sixel functions we call use term->grid... */ + struct grid *active_grid = term->grid; + term->grid = grid; - for (size_t i = 0; i < 2; i++) { - struct grid *grid = i == 0 ? &term->normal : &term->alt; + /* 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); - term->grid = grid; + tll_rforeach(copy, it) { + struct sixel *six = &it->item; + int start = six->pos.row; + int end = (start + six->rows - 1) & (grid->num_rows - 1); - /* 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 */ - /* TODO: split image */ - sixel_destroy(six); - continue; - } - - if (six->rows > grid->num_rows) { - /* Image too large */ - /* TODO: keep bottom part? */ - sixel_destroy(six); - 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 = grid_row_abs_to_sb( - term->grid, term->rows, 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( - term, six->pos.row, six->pos.col, six->rows, six->cols, - &it->item.pix, &it->item.opaque); - - if (it->item.data != pixman_image_get_data(it->item.pix)) { - it->item.data = pixman_image_get_data(it->item.pix); - it->item.width = pixman_image_get_width(it->item.pix); - it->item.height = pixman_image_get_height(it->item.pix); - it->item.cols = (it->item.width + term->cell_width - 1) / term->cell_width; - it->item.rows = (it->item.height + term->cell_height - 1) / term->cell_height; - } - - sixel_insert(term, it->item); + if (end < start) { + /* Crosses scrollback wrap-around */ + /* TODO: split image */ + sixel_destroy(six); + continue; } - tll_free(copy); + if (six->rows > grid->num_rows) { + /* Image too large */ + /* TODO: keep bottom part? */ + sixel_destroy(six); + 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 = grid_row_abs_to_sb( + term->grid, term->rows, 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( + term, six->pos.row, six->pos.col, six->rows, six->cols, + &it->item.pix, &it->item.opaque); + + if (it->item.data != pixman_image_get_data(it->item.pix)) { + it->item.data = pixman_image_get_data(it->item.pix); + it->item.width = pixman_image_get_width(it->item.pix); + it->item.height = pixman_image_get_height(it->item.pix); + it->item.cols = (it->item.width + term->cell_width - 1) / term->cell_width; + it->item.rows = (it->item.height + term->cell_height - 1) / term->cell_height; + } + + sixel_insert(term, it->item); } - term->grid = g; + tll_free(copy); + term->grid = active_grid; +} + +void +sixel_reflow(struct terminal *term) +{ + for (size_t i = 0; i < 2; i++) { + struct grid *grid = i == 0 ? &term->normal : &term->alt; + sixel_reflow_grid(term, grid); + } } void diff --git a/sixel.h b/sixel.h index a57957c3..f72b4dc4 100644 --- a/sixel.h +++ b/sixel.h @@ -19,6 +19,10 @@ 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_grid(struct terminal *term, struct grid *grid); + +/* Shortcut for sixel_reflow_grid(normal) + sixel_reflow_grid(alt) */ void sixel_reflow(struct terminal *term); /* From d4b0b0887e73c80cf5ff22fdbac82947897b2b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:11:49 +0200 Subject: [PATCH 017/118] render: delayed reflow: not enough to damage current view; need to refresh too --- render.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/render.c b/render.c index 3cb544cd..c7174228 100644 --- a/render.c +++ b/render.c @@ -3698,8 +3698,10 @@ delayed_reflow_of_normal_grid(struct terminal *term) term->render.last_buf = NULL; term->render.last_cursor.row = NULL; - if (term->grid == &term->normal) + if (term->grid == &term->normal) { term_damage_view(term); + render_refresh(term); + } term_ptmx_resume(term); } From 18ef36523f55cb8c8a6a9a9c3269274cc08c0a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:12:18 +0200 Subject: [PATCH 018/118] grid: resize: assert grid->cur_row is not NULL after a grid resize --- grid.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/grid.c b/grid.c index bccac529..3bcc8a55 100644 --- a/grid.c +++ b/grid.c @@ -485,6 +485,8 @@ grid_resize_without_reflow( grid->saved_cursor.point = saved_cursor; grid->cur_row = new_grid[(grid->offset + cursor.row) & (new_rows - 1)]; + xassert(grid->cur_row != NULL); + grid->cursor.lcf = false; grid->saved_cursor.lcf = false; @@ -1047,6 +1049,8 @@ grid_resize_and_reflow( saved_cursor.col = min(saved_cursor.col, new_cols - 1); grid->cur_row = new_grid[(grid->offset + cursor.row) & (new_rows - 1)]; + xassert(grid->cur_row != NULL); + grid->cursor.point = cursor; grid->saved_cursor.point = saved_cursor; From 66e4592d91312568c8948ddda850ba8b1c31c87d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:14:49 +0200 Subject: [PATCH 019/118] term: use SIZE_MAX instead of (size_t)-1ll --- terminal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/terminal.c b/terminal.c index ee12ae32..5dd261bb 100644 --- a/terminal.c +++ b/terminal.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -268,7 +269,7 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) } uint8_t buf[24 * 1024]; - const size_t max_iterations = !hup ? 10 : (size_t)-1ll; + const size_t max_iterations = !hup ? 10 : SIZE_MAX; for (size_t i = 0; i < max_iterations && pollin; i++) { xassert(pollin); From 54d637e2b47fd55e4abde1e28f7f665e69c2a995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:15:29 +0200 Subject: [PATCH 020/118] =?UTF-8?q?term:=20ptmx:=20don=E2=80=99t=20consume?= =?UTF-8?q?=20anything=20while=20doing=20an=20interactive=20resize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ‘normal’ grid in use during an interactive resize is temporary; all changes done to it will be lost when the resize is finished. --- terminal.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/terminal.c b/terminal.c index 5dd261bb..4fb13f44 100644 --- a/terminal.c +++ b/terminal.c @@ -268,6 +268,16 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) cursor_blink_rearm_timer(term); } + if (unlikely(term->interactive_resizing.grid != NULL)) { + /* + * Don’t consume PTMX while we’re doing an interactive resize, + * since the ‘normal’ grid we’re currently using is a + * temporary one - all changes done to it will be lost when + * the interactive resize ends. + */ + return 0; + } + uint8_t buf[24 * 1024]; const size_t max_iterations = !hup ? 10 : SIZE_MAX; @@ -291,6 +301,7 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) break; } + xassert(term->interactive_resizing.grid == NULL); vt_from_slave(term, buf, count); } From c5c97c2fd4a674d0fcce16d40e0e56994195e9b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:16:23 +0200 Subject: [PATCH 021/118] term_ptmx_{pause,resume}: return success/fail --- terminal.c | 24 ++++++++++++------------ terminal.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/terminal.c b/terminal.c index 4fb13f44..16486d82 100644 --- a/terminal.c +++ b/terminal.c @@ -234,18 +234,6 @@ static struct timespec last = {0}; static bool cursor_blink_rearm_timer(struct terminal *term); -void -term_ptmx_pause(struct terminal *term) -{ - fdm_event_del(term->fdm, term->ptmx, EPOLLIN); -} - -void -term_ptmx_resume(struct terminal *term) -{ - fdm_event_add(term->fdm, term->ptmx, EPOLLIN); -} - /* Externally visible, but not declared in terminal.h, to enable pgo * to call this function directly */ bool @@ -382,6 +370,18 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) return true; } +bool +term_ptmx_pause(struct terminal *term) +{ + return fdm_event_del(term->fdm, term->ptmx, EPOLLIN); +} + +bool +term_ptmx_resume(struct terminal *term) +{ + return fdm_event_add(term->fdm, term->ptmx, EPOLLIN); +} + static bool fdm_flash(struct fdm *fdm, int fd, int events, void *data) { diff --git a/terminal.h b/terminal.h index 7a281e72..16c8e776 100644 --- a/terminal.h +++ b/terminal.h @@ -810,8 +810,8 @@ void term_collect_urls(struct terminal *term); void term_osc8_open(struct terminal *term, uint64_t id, const char *uri); void term_osc8_close(struct terminal *term); -void term_ptmx_pause(struct terminal *term); -void term_ptmx_resume(struct terminal *term); +bool term_ptmx_pause(struct terminal *term); +bool term_ptmx_resume(struct terminal *term); static inline void term_reset_grapheme_state(struct terminal *term) { From c550d67cd856ba806c616ac2f15bdbca283e0a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:16:50 +0200 Subject: [PATCH 022/118] render: resize: do delayed reflow immediately when failing to arm tiocswinsz timer --- render.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/render.c b/render.c index c7174228..2f79c6c1 100644 --- a/render.c +++ b/render.c @@ -3776,8 +3776,10 @@ send_dimensions_to_client(struct terminal *term) successfully_scheduled = true; } - if (!successfully_scheduled) + if (!successfully_scheduled) { tiocswinsz(term); + delayed_reflow_of_normal_grid(term); + } } } From 298f210ed93a83a531a44f772172da7f64510217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Oct 2022 16:17:22 +0200 Subject: [PATCH 023/118] render: rename term->render.resizing -> term->interactive_resizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit But also, more importantly, logical fixes: * Stash the number of new scrollback lines the stashed ‘normal’ grid should be resized *to*. There’s also a couple of performance changes here: * When doing a delayed reflow (tiocswinsz timer), call sixel_reflow_grid(term, &term->normal) - there’s no need to reflow sixels in the ‘alt’ screen. * When doing a delayed reflow, free all scroll damage. It’s not needed, since we’re damaging the entire window anyway. * Use minimum size for the temporary ‘normal’ grid (that contains the current viewport). We just need it to be large enough to fit the current viewport, and be a valid grid row count (power of 2). This just so happens to be the current ‘alt’ grid’s row count... --- render.c | 68 +++++++++++++++++++++++++++++++----------------------- terminal.h | 11 +++++---- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/render.c b/render.c index 2f79c6c1..d50606cb 100644 --- a/render.c +++ b/render.c @@ -3666,9 +3666,11 @@ tiocswinsz(struct terminal *term) static void delayed_reflow_of_normal_grid(struct terminal *term) { - if (term->render.resizing.grid == NULL) + if (term->interactive_resizing.grid == NULL) return; + xassert(term->interactive_resizing.new_rows > 0); + struct coord *const tracking_points[] = { &term->selection.coords.start, &term->selection.coords.end, @@ -3677,27 +3679,31 @@ delayed_reflow_of_normal_grid(struct terminal *term) /* Reflow the original (since before the resize was started) grid, * to the *current* dimensions */ grid_resize_and_reflow( - term->render.resizing.grid, - term->grid->num_rows, term->grid->num_cols, - term->render.resizing.screen_rows, term->rows, + term->interactive_resizing.grid, + term->interactive_resizing.new_rows, term->normal.num_cols, + term->interactive_resizing.old_screen_rows, term->rows, term->selection.coords.end.row >= 0 ? ALEN(tracking_points) : 0, tracking_points); /* Replace the current, truncated, “normal” grid with the * correctly reflowed one */ grid_free(&term->normal); - term->normal = *term->render.resizing.grid; - free(term->render.resizing.grid); + term->normal = *term->interactive_resizing.grid; + free(term->interactive_resizing.grid); /* Reset */ - term->render.resizing.grid = NULL; - term->render.resizing.screen_rows = 0; + term->interactive_resizing.grid = NULL; + term->interactive_resizing.old_screen_rows = 0; + term->interactive_resizing.new_rows = 0; /* Invalidate render pointers */ shm_unref(term->render.last_buf); term->render.last_buf = NULL; term->render.last_cursor.row = NULL; + tll_free(term->normal.scroll_damage); + sixel_reflow_grid(term, &term->normal); + if (term->grid == &term->normal) { term_damage_view(term); render_refresh(term); @@ -3895,8 +3901,6 @@ maybe_resize(struct terminal *term, int width, int height, bool force) const uint32_t scrollback_lines = term->render.scrollback_lines; /* - * Snapshot the “normal” grid. - * * Since text reflow is slow, don’t do it *while* resizing. Only * do it when done, or after “pausing” the resize for sufficiently * long. We re-use the TIOCSWINSZ timer to handle this. See @@ -3905,25 +3909,30 @@ maybe_resize(struct terminal *term, int width, int height, bool force) * To be able to do the final reflow correctly, we need a copy of * the original grid, before the resize started. */ - if (term->window->is_resizing && term->render.resizing.grid == NULL) { + if (term->window->is_resizing && term->interactive_resizing.grid == NULL) { + term_ptmx_pause(term); + /* Stash the current ‘normal’ grid, as-is, to be used when * doing the final reflow */ - term->render.resizing.screen_rows = term->rows; - term->render.resizing.grid = xmalloc(sizeof(*term->render.resizing.grid)); - *term->render.resizing.grid = term->normal; - + term->interactive_resizing.old_screen_rows = term->rows; + term->interactive_resizing.grid = xmalloc(sizeof(*term->interactive_resizing.grid)); + *term->interactive_resizing.grid = term->normal; /* * Copy the current viewport to a new grid that will be used * during the resize. For now, throw away sixels and OSC-8 * URLs. They’ll be "restored" when we do the final reflow. * + * We use the ‘alt’ screen’s row count, since we don’t want to + * instantiate an unnecessarily large grid. + * * TODO: * - sixels? * - OSC-8? */ + xassert(1 << (32 - __builtin_clz(term->rows)) == term->alt.num_rows); struct grid g = { - .num_rows = 1 << (32 - __builtin_clz(term->rows - 1)), + .num_rows = term->alt.num_rows, .num_cols = term->cols, .offset = 0, .view = 0, @@ -3945,7 +3954,6 @@ maybe_resize(struct terminal *term, int width, int height, bool force) } term->normal = g; - term_ptmx_pause(term); } /* Screen rows/cols before resize */ @@ -3985,9 +3993,10 @@ maybe_resize(struct terminal *term, int width, int height, bool force) xassert(term->margins.bottom >= pad_y); if (new_cols == old_cols && new_rows == old_rows && - (term->render.resizing.grid == NULL || term->window->is_resizing)) + (term->interactive_resizing.grid == NULL || term->window->is_resizing)) { LOG_DBG("grid layout unaffected; skipping reflow"); + term->interactive_resizing.new_rows = new_normal_grid_rows; goto damage_view; } @@ -4014,27 +4023,28 @@ maybe_resize(struct terminal *term, int width, int height, bool force) if (term->window->is_resizing) { /* Simple truncating resize, *while* an interactive resize is * ongoing. */ - xassert(term->render.resizing.grid != NULL); + xassert(term->interactive_resizing.grid != NULL); + xassert(new_normal_grid_rows > 0); + term->interactive_resizing.new_rows = new_normal_grid_rows; + grid_resize_without_reflow( - &term->normal, - new_normal_grid_rows, new_cols, - old_rows, - new_rows); + &term->normal, new_alt_grid_rows, new_cols, old_rows, new_rows); } else { /* Full text reflow */ - if (term->render.resizing.grid != NULL) { + if (term->interactive_resizing.grid != NULL) { /* Throw away the current, truncated, “normal” grid, and * use the original grid instead (from before the resize * started) */ grid_free(&term->normal); - term->normal = *term->render.resizing.grid; - free(term->render.resizing.grid); + term->normal = *term->interactive_resizing.grid; + free(term->interactive_resizing.grid); - old_rows = term->render.resizing.screen_rows; + old_rows = term->interactive_resizing.old_screen_rows; - term->render.resizing.grid = NULL; - term->render.resizing.screen_rows = 0; + term->interactive_resizing.grid = NULL; + term->interactive_resizing.old_screen_rows = 0; + term->interactive_resizing.new_rows = 0; term_ptmx_resume(term); } diff --git a/terminal.h b/terminal.h index 16c8e776..d5ed1ba2 100644 --- a/terminal.h +++ b/terminal.h @@ -595,14 +595,15 @@ struct terminal { size_t search_glyph_offset; - struct { - struct grid *grid; - int screen_rows; - } resizing; - struct timespec input_time; } render; + struct { + struct grid *grid; /* Original ‘normal’ grid, before resize started */ + int old_screen_rows; /* term->rows before resize started */ + int new_rows; /* New number of scrollback rows */ + } interactive_resizing; + struct { enum { SIXEL_DECSIXEL, /* DECSIXEL body part ", $, -, ? ... ~ */ From 43a48f53d42a5de21e0a6eb6783863051ad8862a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 13 Oct 2022 17:52:34 +0200 Subject: [PATCH 024/118] =?UTF-8?q?sixel:=20don=E2=80=99t=20crash=20when?= =?UTF-8?q?=20sixel=20image=20exceeds=20current=20sixel=20max=20height?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we try to resize a sixel past the current max height, we set col > image-width to signal this. This means ‘width’ could be smaller than ‘col’. When calculating how many sixels to emit in sixel_add_many(), we didnt’ account for this. The resulting value was -1, converted to ‘unsigned’. I.e. a very large value. This resulted in an assert triggering in sixel_add() in debug builds, and a crash in release builds. --- CHANGELOG.md | 1 + sixel.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f97cb252..cf6a2104 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,7 @@ built-in terminfo (accessed via XTGETTCAP). * Crash when interactively resizing the window with a very large scrollback. +* Crash when a sixel image exceeds the current sixel max height. [1173]: https://codeberg.org/dnkl/foot/issues/1173 diff --git a/sixel.c b/sixel.c index c80a92a3..a824c405 100644 --- a/sixel.c +++ b/sixel.c @@ -1295,7 +1295,7 @@ sixel_add_many(struct terminal *term, uint8_t c, unsigned count) if (unlikely(col + count - 1 >= width)) { resize_horizontally(term, col + count); width = term->sixel.image.width; - count = min(count, width - col); + count = min(count, max(width - col, 0)); } uint32_t color = term->sixel.color; From 3d9a429499841cca83b5c8359ea7e2b78509601f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 14 Oct 2022 18:00:48 +0200 Subject: [PATCH 025/118] term: reverse scroll: free scrolled out lines This ensures *everything* in the circular scrollback history, after the bottom of the screen, is either NULL rows, or belong to the scrollback *history* (as opposed to the future history). This fixes an issue when calculating the scrollback start, which for example would trigger a crash when moving the viewport (i.e. scrolling with the mouse, or PgUp/PgDown). Closes #1190 --- terminal.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/terminal.c b/terminal.c index 16486d82..380f0d4a 100644 --- a/terminal.c +++ b/terminal.c @@ -2676,6 +2676,18 @@ term_scroll_reverse_partial(struct terminal *term, selection_scroll_down(term, rows); } + /* Unallocate scrolled out lines */ + for (int r = region.end - rows; r < region.end; r++) { + const int abs_r = grid_row_absolute(term->grid, r); + struct row *row = term->grid->rows[abs_r]; + + grid_row_free(row); + term->grid->rows[abs_r] = NULL; + + if (term->render.last_cursor.row == row) + term->render.last_cursor.row = NULL; + } + sixel_scroll_down(term, rows); bool view_follows = term->grid->view == term->grid->offset; From 89744f8123aadd58b74ea7b5038c3302c1ed75ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 14 Oct 2022 18:03:00 +0200 Subject: [PATCH 026/118] selection: scroll down: handle non-full scrollback correctly When determining whether or not to cancel a selection (due to it, or part of it, being "scrolled out"), we assumed the scrollback was full. This patch changes the implementation to compare the scrollback relative selection coordinates with the scrollback relative end-of-the-scrollback coordinates. --- selection.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/selection.c b/selection.c index c94686e1..92f1f85f 100644 --- a/selection.c +++ b/selection.c @@ -133,13 +133,18 @@ selection_scroll_down(struct terminal *term, int rows) { xassert(term->selection.coords.end.row >= 0); + const struct grid *grid = term->grid; + const struct range *sel = &term->selection.coords; + + const int screen_end = + grid_row_abs_to_sb(grid, term->rows, grid->offset + term->rows - 1); const int rel_row_start = - grid_row_abs_to_sb(term->grid, term->rows, term->selection.coords.start.row); + grid_row_abs_to_sb(term->grid, term->rows, sel->start.row); const int rel_row_end = - grid_row_abs_to_sb(term->grid, term->rows, term->selection.coords.end.row); + grid_row_abs_to_sb(term->grid, term->rows, sel->end.row); const int actual_end = max(rel_row_start, rel_row_end); - if (actual_end + rows <= term->grid->num_rows) { + if (actual_end > screen_end - rows) { /* Part of the selection will be scrolled out, cancel it */ selection_cancel(term); } From 3c9a51afa69370efb73e0b8208415fac11a41a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 14 Oct 2022 18:05:12 +0200 Subject: [PATCH 027/118] changelog: crash after reverse-scrolling in the normal screen --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf6a2104..3022836d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,8 +89,11 @@ * Crash when interactively resizing the window with a very large scrollback. * Crash when a sixel image exceeds the current sixel max height. +* Crash after reverse-scrolling (`CSI Ps T`) in the ‘normal’ + (non-alternate) screen ([#1190][1190]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 +[1190]: https://codeberg.org/dnkl/foot/issues/1190 ### Security From 0ac0d0647ae996bcef119d885cbd2d22a9940d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Oct 2022 18:49:57 +0200 Subject: [PATCH 028/118] interactive resize: improve user experience MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-initialize the temporary ‘normal’ grid instance each time we receive a configure event while doing an interactive resize. This way, window content will not be "erased" when the window is first made smaller, then larger again. And, if the viewport is up in the scrollback history, increasing the window size will reveal more of the scrollback, instead of just being black. The last issue is the cursor; it’s currently not "stuck" where it should be. Instead, it follows the window around. This is due to two things: 1) the temporary grid we create is large enough to contain the current viewport, but not more than that. That means we can’t "scroll up", to hide the cursor. 2) grid_resize_without_reflow() doesn’t know anything about "interactive resizing". As such, it will ensure the cursor is bound to the new grid dimensions. I don’t yet have a solution for this. This patch implements a workaround to at least reduce the impact, by simply hiding the cursor while we’re doing an interactive resize. --- render.c | 141 ++++++++++++++++++++++++++++++----------------------- terminal.h | 2 + 2 files changed, 83 insertions(+), 60 deletions(-) diff --git a/render.c b/render.c index d50606cb..19ab5ef8 100644 --- a/render.c +++ b/render.c @@ -3691,10 +3691,13 @@ delayed_reflow_of_normal_grid(struct terminal *term) term->normal = *term->interactive_resizing.grid; free(term->interactive_resizing.grid); + term->hide_cursor = term->interactive_resizing.old_hide_cursor; + /* Reset */ term->interactive_resizing.grid = NULL; term->interactive_resizing.old_screen_rows = 0; term->interactive_resizing.new_rows = 0; + term->interactive_resizing.old_hide_cursor = false; /* Invalidate render pointers */ shm_unref(term->render.last_buf); @@ -3900,62 +3903,6 @@ maybe_resize(struct terminal *term, int width, int height, bool force) const uint32_t scrollback_lines = term->render.scrollback_lines; - /* - * Since text reflow is slow, don’t do it *while* resizing. Only - * do it when done, or after “pausing” the resize for sufficiently - * long. We re-use the TIOCSWINSZ timer to handle this. See - * send_dimensions_to_client() and fdm_tiocswinsz(). - * - * To be able to do the final reflow correctly, we need a copy of - * the original grid, before the resize started. - */ - if (term->window->is_resizing && term->interactive_resizing.grid == NULL) { - term_ptmx_pause(term); - - /* Stash the current ‘normal’ grid, as-is, to be used when - * doing the final reflow */ - term->interactive_resizing.old_screen_rows = term->rows; - term->interactive_resizing.grid = xmalloc(sizeof(*term->interactive_resizing.grid)); - *term->interactive_resizing.grid = term->normal; - - /* - * Copy the current viewport to a new grid that will be used - * during the resize. For now, throw away sixels and OSC-8 - * URLs. They’ll be "restored" when we do the final reflow. - * - * We use the ‘alt’ screen’s row count, since we don’t want to - * instantiate an unnecessarily large grid. - * - * TODO: - * - sixels? - * - OSC-8? - */ - xassert(1 << (32 - __builtin_clz(term->rows)) == term->alt.num_rows); - struct grid g = { - .num_rows = term->alt.num_rows, - .num_cols = term->cols, - .offset = 0, - .view = 0, - .cursor = term->normal.cursor, - .saved_cursor = term->normal.saved_cursor, - .rows = xcalloc(g.num_rows, sizeof(g.rows[0])), - .cur_row = NULL, - .scroll_damage = tll_init(), - .sixel_images = tll_init(), - .kitty_kbd = term->normal.kitty_kbd, - }; - - for (size_t i = 0, j = term->normal.view; i < term->rows; - i++, j = (j + 1) & (term->normal.num_rows - 1)) - { - g.rows[i] = grid_row_alloc(term->cols, false); - memcpy(g.rows[i]->cells, term->normal.rows[j]->cells, - term->cols * sizeof(g.rows[i]->cells[0])); - } - - term->normal = g; - } - /* Screen rows/cols before resize */ int old_cols = term->cols; int old_rows = term->rows; @@ -3992,14 +3939,84 @@ maybe_resize(struct terminal *term, int width, int height, bool force) xassert(term->margins.top >= pad_y); xassert(term->margins.bottom >= pad_y); - if (new_cols == old_cols && new_rows == old_rows && - (term->interactive_resizing.grid == NULL || term->window->is_resizing)) - { + if (new_cols == old_cols && new_rows == old_rows) { LOG_DBG("grid layout unaffected; skipping reflow"); term->interactive_resizing.new_rows = new_normal_grid_rows; goto damage_view; } + + /* + * Since text reflow is slow, don’t do it *while* resizing. Only + * do it when done, or after “pausing” the resize for sufficiently + * long. We re-use the TIOCSWINSZ timer to handle this. See + * send_dimensions_to_client() and fdm_tiocswinsz(). + * + * To be able to do the final reflow correctly, we need a copy of + * the original grid, before the resize started. + */ + if (term->window->is_resizing) { + if (term->interactive_resizing.grid == NULL) { + term_ptmx_pause(term); + + /* Stash the current ‘normal’ grid, as-is, to be used when + * doing the final reflow */ + term->interactive_resizing.old_screen_rows = term->rows; + term->interactive_resizing.old_cols = term->cols; + term->interactive_resizing.old_hide_cursor = term->hide_cursor; + term->interactive_resizing.grid = xmalloc(sizeof(*term->interactive_resizing.grid)); + *term->interactive_resizing.grid = term->normal; + } else { + /* We’ll replace the current temporary grid, with a new + * one (again based on the original grid) */ + grid_free(&term->normal); + } + + struct grid *orig = term->interactive_resizing.grid; + + /* + * Copy the current viewport (of the original grid) to a new + * grid that will be used during the resize. For now, throw + * away sixels and OSC-8 URLs. They’ll be "restored" when we + * do the final reflow. + * + * Note that OSC-8 URLs are perfectly ok to throw away; they + * cannot be interacted with during the resize. And, even if + * url.osc8-underline=always, the “underline” attribute is + * part of the cell, not the URI struct (and thus our faked + * grid will still render OSC-8 links underlined). + * + * TODO: + * - sixels? + */ + struct grid g = { + .num_rows = 1 << (32 - __builtin_clz(term->interactive_resizing.old_screen_rows)), + .num_cols = term->interactive_resizing.old_cols, + .offset = 0, + .view = 0, + .cursor = orig->cursor, + .saved_cursor = orig->saved_cursor, + .rows = xcalloc(g.num_rows, sizeof(g.rows[0])), + .cur_row = NULL, + .scroll_damage = tll_init(), + .sixel_images = tll_init(), + .kitty_kbd = orig->kitty_kbd, + }; + + for (size_t i = 0, j = orig->view; + i < term->interactive_resizing.old_screen_rows; + i++, j = (j + 1) & (orig->num_rows - 1)) + { + g.rows[i] = grid_row_alloc(g.num_cols, false); + memcpy(g.rows[i]->cells, + orig->rows[j]->cells, + g.num_cols * sizeof(g.rows[i]->cells[0])); + } + + term->normal = g; + term->hide_cursor = true; + } + if (term->grid == &term->alt) selection_cancel(term); else { @@ -4028,7 +4045,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force) term->interactive_resizing.new_rows = new_normal_grid_rows; grid_resize_without_reflow( - &term->normal, new_alt_grid_rows, new_cols, old_rows, new_rows); + &term->normal, new_alt_grid_rows, new_cols, + term->interactive_resizing.old_screen_rows, new_rows); } else { /* Full text reflow */ @@ -4040,11 +4058,14 @@ maybe_resize(struct terminal *term, int width, int height, bool force) term->normal = *term->interactive_resizing.grid; free(term->interactive_resizing.grid); + term->hide_cursor = term->interactive_resizing.old_hide_cursor; + old_rows = term->interactive_resizing.old_screen_rows; term->interactive_resizing.grid = NULL; term->interactive_resizing.old_screen_rows = 0; term->interactive_resizing.new_rows = 0; + term->interactive_resizing.old_hide_cursor = false; term_ptmx_resume(term); } diff --git a/terminal.h b/terminal.h index d5ed1ba2..ec5560cd 100644 --- a/terminal.h +++ b/terminal.h @@ -601,6 +601,8 @@ struct terminal { struct { struct grid *grid; /* Original ‘normal’ grid, before resize started */ int old_screen_rows; /* term->rows before resize started */ + int old_cols; /* term->cols before resize started */ + int old_hide_cursor; /* term->hide_cursor before resize started */ int new_rows; /* New number of scrollback rows */ } interactive_resizing; From b0c30c7ed22acbf4033db18949ea43f50edd1382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Oct 2022 20:16:53 +0200 Subject: [PATCH 029/118] doc: foot.ini: improve documentation of cursor.color --- doc/foot.ini.5.scd | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 6fe97c09..ee6aa94c 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -452,14 +452,13 @@ applications can change these at runtime. by applications. Default: _no_. *color* - Two RRGGBB values (i.e. plain old 6-digit hex values, without - prefix) specifying the foreground (text) and background (cursor) - colors for the cursor. + Two space separated RRGGBB values (i.e. plain old 6-digit hex + values, without prefix) specifying the foreground (text) and + background (cursor) colors for the cursor. - Default: _inverse foreground/background colors_. - - Note that this value only applies to the block cursor. The other - cursor styles are always rendered with the foreground color. + Example: *ff0000 00ff00* (green cursor, red text) + + Default: the regular foreground and background colors, reversed. *beam-thickness* Thickness (width) of the beam styled cursor. The value is in From 2e9b3ceb95597e2612b048f20fa006d123090e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 18 Oct 2022 18:28:51 +0200 Subject: [PATCH 030/118] =?UTF-8?q?fdm=5Fptmx():=20regression:=20don?= =?UTF-8?q?=E2=80=99t=20return=20false=20when=20an=20interactive=20resize?= =?UTF-8?q?=20is=20in=20progress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terminal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terminal.c b/terminal.c index 380f0d4a..b17731d3 100644 --- a/terminal.c +++ b/terminal.c @@ -263,7 +263,7 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) * temporary one - all changes done to it will be lost when * the interactive resize ends. */ - return 0; + return true; } uint8_t buf[24 * 1024]; From 09d52d5db6175c272b43d6e132922e14a0c57d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 18 Oct 2022 18:29:20 +0200 Subject: [PATCH 031/118] term_destroy(): free interactive_resizing.grid This grid is normally unallocated, but may be allocated if we are exiting (for whatever reason) in the middle of an interactive resize. --- terminal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/terminal.c b/terminal.c index b17731d3..6cb419be 100644 --- a/terminal.c +++ b/terminal.c @@ -1752,6 +1752,8 @@ term_destroy(struct terminal *term) grid_free(&term->normal); grid_free(&term->alt); + grid_free(term->interactive_resizing.grid); + free(term->interactive_resizing.grid); free(term->foot_exe); free(term->cwd); From c4f08a3b9a7c6d6fc27f68e5a5c273975d42de76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 18 Oct 2022 18:30:02 +0200 Subject: [PATCH 032/118] grid_free(): allow being called with grid == NULL --- grid.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grid.c b/grid.c index 3bcc8a55..7b86e2c1 100644 --- a/grid.c +++ b/grid.c @@ -287,6 +287,9 @@ grid_snapshot(const struct grid *grid) void grid_free(struct grid *grid) { + if (grid == NULL) + return; + for (int r = 0; r < grid->num_rows; r++) grid_row_free(grid->rows[r]); From 3ba03901b893abcdb4433d71d0b6568abceba770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 18 Oct 2022 18:31:18 +0200 Subject: [PATCH 033/118] =?UTF-8?q?pgo:=20don=E2=80=99t=20re-use=20the=20r?= =?UTF-8?q?ows=20between=20the=20=E2=80=98normal=E2=80=99=20and=20?= =?UTF-8?q?=E2=80=98alt=E2=80=99=20grids?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This used to work because we never free:d any of the rows. Now however, we do free (some of) them when reverse scrolling. This means we can no longer re-use the rows between the two screens. Closes #1196 --- pgo/pgo.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/pgo/pgo.c b/pgo/pgo.c index 7f6f758b..b41b5850 100644 --- a/pgo/pgo.c +++ b/pgo/pgo.c @@ -228,10 +228,14 @@ main(int argc, const char *const *argv) return EXIT_FAILURE; } - struct row **rows = calloc(grid_row_count, sizeof(rows[0])); + struct row **normal_rows = calloc(grid_row_count, sizeof(normal_rows[0])); + struct row **alt_rows = calloc(grid_row_count, sizeof(alt_rows[0])); + for (int i = 0; i < grid_row_count; i++) { - rows[i] = calloc(1, sizeof(*rows[i])); - rows[i]->cells = calloc(col_count, sizeof(rows[i]->cells[0])); + normal_rows[i] = calloc(1, sizeof(*normal_rows[i])); + normal_rows[i]->cells = calloc(col_count, sizeof(normal_rows[i]->cells[0])); + alt_rows[i] = calloc(1, sizeof(*alt_rows[i])); + alt_rows[i]->cells = calloc(col_count, sizeof(alt_rows[i]->cells[0])); } struct config conf = { @@ -254,14 +258,14 @@ main(int argc, const char *const *argv) .normal = { .num_rows = grid_row_count, .num_cols = col_count, - .rows = rows, - .cur_row = rows[0], + .rows = normal_rows, + .cur_row = normal_rows[0], }, .alt = { .num_rows = grid_row_count, .num_cols = col_count, - .rows = rows, - .cur_row = rows[0], + .rows = alt_rows, + .cur_row = alt_rows[0], }, .scale = 1, .width = col_count * 8, @@ -371,11 +375,17 @@ out: tll_free(wayl.terms); for (int i = 0; i < grid_row_count; i++) { - free(rows[i]->cells); - free(rows[i]); + if (normal_rows[i] != NULL) + free(normal_rows[i]->cells); + free(normal_rows[i]); + + if (alt_rows[i] != NULL) + free(alt_rows[i]->cells); + free(alt_rows[i]); } - free(rows); + free(normal_rows); + free(alt_rows); close(lower_fd); close(upper_fd); return ret; From 59c9dfe109f9045b583299d934ac54b8a07749d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 23 Oct 2022 10:34:18 +0200 Subject: [PATCH 034/118] render: resize: do full text reflow immediately if resize-delay-ms == 0 That is, skip all custom grid handling when doing an interactive resize, if resize-delay-ms == 0. --- render.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/render.c b/render.c index 19ab5ef8..76f4b7c6 100644 --- a/render.c +++ b/render.c @@ -3955,9 +3955,10 @@ maybe_resize(struct terminal *term, int width, int height, bool force) * To be able to do the final reflow correctly, we need a copy of * the original grid, before the resize started. */ - if (term->window->is_resizing) { + if (term->window->is_resizing && term->conf->resize_delay_ms > 0) { if (term->interactive_resizing.grid == NULL) { term_ptmx_pause(term); + xassert(false); /* Stash the current ‘normal’ grid, as-is, to be used when * doing the final reflow */ @@ -4037,7 +4038,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) * tracking points list. */ /* Resize grids */ - if (term->window->is_resizing) { + if (term->window->is_resizing && term->conf->resize_delay_ms > 0) { /* Simple truncating resize, *while* an interactive resize is * ongoing. */ xassert(term->interactive_resizing.grid != NULL); From 1313e6352a442bfd7483f7b6e14308f2cabdc684 Mon Sep 17 00:00:00 2001 From: Andrea Pappacoda Date: Sun, 23 Oct 2022 23:56:34 +0200 Subject: [PATCH 035/118] build: fix GCC detection in pgo.sh On my system, GCC doesn't output its name when passing the --version flag: $ cc --version cc (Debian 12.2.0-3) 12.2.0 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. As the Free Software Foundation is unlikely to write another compiler, I think that searching for the foundation's name instead of GCC is a good enough fix (and I'm almost sure we wouldn't be the first ones to do so). --- pgo/pgo.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgo/pgo.sh b/pgo/pgo.sh index b2ce7fe5..2f409268 100755 --- a/pgo/pgo.sh +++ b/pgo/pgo.sh @@ -30,7 +30,7 @@ do_pgo=no CFLAGS="${CFLAGS-} -O3" case $(${CC-cc} --version) in - *GCC*) + *Free\ Software\ Foundation*) compiler=gcc do_pgo=yes ;; From 49fa75195322e47114d2f5effb0e87f433c275f4 Mon Sep 17 00:00:00 2001 From: Andrea Pappacoda Date: Sun, 23 Oct 2022 21:32:11 +0200 Subject: [PATCH 036/118] chore: use MIT license for appstream metadata The Appstream metadata file introduced in commit 335612cfa4ea090874354c7080f492b2b28a136b has been submitted as licensed under the CC0-1.0 license. People generally use the CC0-1.0 to put the file in the "public domain", but this isn't actually possible in lots of countries, so the file ends up being licensed under CC0's fallback permissive license; unfortunately, the fallback license contains some terms that are seen as problematic to some (notably, Fedora has recently decided to consider the license pretty much non-free). As foot is already MIT-licensed, and since this license is in the list of allowed [metadata licenses], this patch changes the license of the metadata file from CC0-1.0 to MIT. [metadata licenses]: https://freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-metadata_license --- org.codeberg.dnkl.foot.metainfo.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.codeberg.dnkl.foot.metainfo.xml b/org.codeberg.dnkl.foot.metainfo.xml index 22512ce8..1c0b7985 100644 --- a/org.codeberg.dnkl.foot.metainfo.xml +++ b/org.codeberg.dnkl.foot.metainfo.xml @@ -1,7 +1,7 @@ org.codeberg.dnkl.foot - CC0-1.0 + MIT MIT dnkl foot From 2c2a39317be3df4ff9899896067684408526fb29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 30 Oct 2022 19:39:09 +0100 Subject: [PATCH 037/118] render: never apply alpha to text color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When drawing a block cursor using inversed fg/bg colors, we didn’t strip the alpha from the background color. This meant that the text "behind" the cursor was rendered with transparency. If alpha was set to 0, the text was completely invisible. We should never apply alpha to the text color. So, detect this, and force alpha to 1.0. Normally, when selecting the cursor’s color, we don’t really know _where_ the background color is coming from (or more accurately, _what_ it is). However, the *only* background color that can have a non-1.0 alpha is the *default* background color. This is why we can ignore the bg parameter, and use term->colors.fg/bg instead. Closes #1205 --- CHANGELOG.md | 4 ++++ render.c | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3022836d..3546d92e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,9 +91,13 @@ * Crash when a sixel image exceeds the current sixel max height. * Crash after reverse-scrolling (`CSI Ps T`) in the ‘normal’ (non-alternate) screen ([#1190][1190]). +* Background transparency being applied to the text "behind" the + cursor. Only applies to block cursor using inversed fg/bg + colors. ([#1205][1205]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 +[1205]: https://codeberg.org/dnkl/foot/issues/1205 ### Security diff --git a/render.c b/render.c index 76f4b7c6..822667ae 100644 --- a/render.c +++ b/render.c @@ -419,7 +419,14 @@ cursor_colors_for_cell(const struct terminal *term, const struct cell *cell, } } else { *cursor_color = *fg; - *text_color = *bg; + + if (unlikely(text_color->alpha != 0xffff)) { + /* We *know* this only happens when bg is the default bg + * color */ + *text_color = color_hex_to_pixman( + term->reverse ? term->colors.fg : term->colors.bg); + } else + *text_color = *bg; } } From 30d088376cf8f5c44f393ce876f9a3a10f1dcd82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 1 Nov 2022 17:12:16 +0100 Subject: [PATCH 038/118] render: maybe_resize(): remove debug assert This, depending on which compiler being used, caused issues not only in debug builds, but release builds as well (with NDEBUG defined). --- render.c | 1 - 1 file changed, 1 deletion(-) diff --git a/render.c b/render.c index 822667ae..f5e7f627 100644 --- a/render.c +++ b/render.c @@ -3965,7 +3965,6 @@ maybe_resize(struct terminal *term, int width, int height, bool force) if (term->window->is_resizing && term->conf->resize_delay_ms > 0) { if (term->interactive_resizing.grid == NULL) { term_ptmx_pause(term); - xassert(false); /* Stash the current ‘normal’ grid, as-is, to be used when * doing the final reflow */ From 8f2bda67034b1db89be28db1d1f3bfe33cfeb37b Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Tue, 1 Nov 2022 21:04:22 +0000 Subject: [PATCH 039/118] wayland: use BUG() instead of xassert(false) The latter will expand to the former anyway, so we may as well provide an explicit error message instead of "assertion failed: 'false'". --- wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wayland.c b/wayland.c index cd052532..fb103ad1 100644 --- a/wayland.c +++ b/wayland.c @@ -1915,7 +1915,7 @@ activation_token_done(void *data, struct xdg_activation_token_v1 *xdg_token, return; } - xassert(false); + BUG("activation token not found in list"); } static const struct From fa9beae3a69ad1f84e26a5c7528651d7563c0a45 Mon Sep 17 00:00:00 2001 From: Soren A D Date: Tue, 1 Nov 2022 11:32:49 +0530 Subject: [PATCH 040/118] added modus themes --- themes/modus-operandi | 24 ++++++++++++++++++++++++ themes/modus-vivendi | 25 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 themes/modus-operandi create mode 100644 themes/modus-vivendi diff --git a/themes/modus-operandi b/themes/modus-operandi new file mode 100644 index 00000000..ca6c9493 --- /dev/null +++ b/themes/modus-operandi @@ -0,0 +1,24 @@ +# +# modus-operandi +# See: https://protesilaos.com/emacs/modus-themes +# +[colors] +alpha=1.0 +background=ffffff +foreground=000000 +regular0=000000 +regular1=a60000 +regular2=005e00 +regular3=813e00 +regular4=0031a9 +regular5=721045 +regular6=00538b +regular7=bfbfbf +bright0=595959 +bright1=972500 +bright2=315b00 +bright3=70480f +bright4=2544bb +bright5=5317ac +bright6=005a5f +bright7=ffffff diff --git a/themes/modus-vivendi b/themes/modus-vivendi new file mode 100644 index 00000000..a95bcec0 --- /dev/null +++ b/themes/modus-vivendi @@ -0,0 +1,25 @@ +# +# modus-vivendi +# See: https://protesilaos.com/emacs/modus-themes +# + +[colors] +alpha=1.0 +background=000000 +foreground=ffffff +regular0=000000 +regular1=ff8059 +regular2=44bc44 +regular3=d0bc00 +regular4=2fafff +regular5=feacd0 +regular6=00d3d0 +regular7=bfbfbf +bright0=595959 +bright1=ef8b50 +bright2=70b900 +bright3=c0c530 +bright4=79a8ff +bright5=b6a0ff +bright6=6ae4b9 +bright7=ffffff From 2910ca354c741cded6656bf15b4d5216d4417ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 4 Nov 2022 17:42:52 +0100 Subject: [PATCH 041/118] wayland: use fp math all the way when calculating DPI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes an FPE when the monitor’s physical width/height is so small that the conversion from mm to inch resulted in inches being zero. --- CHANGELOG.md | 2 ++ wayland.c | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3546d92e..9c41f21a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,10 +94,12 @@ * Background transparency being applied to the text "behind" the cursor. Only applies to block cursor using inversed fg/bg colors. ([#1205][1205]). +* Crash when monitor’s physical size is "too small" ([#1209][1209]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 [1205]: https://codeberg.org/dnkl/foot/issues/1205 +[1209]: https://codeberg.org/dnkl/foot/issues/1209 ### Security diff --git a/wayland.c b/wayland.c index fb103ad1..974dfb39 100644 --- a/wayland.c +++ b/wayland.c @@ -370,8 +370,8 @@ output_update_ppi(struct monitor *mon) if (mon->dim.mm.width <= 0 || mon->dim.mm.height <= 0) return; - int x_inches = mon->dim.mm.width * 0.03937008; - int y_inches = mon->dim.mm.height * 0.03937008; + double x_inches = mon->dim.mm.width * 0.03937008; + double y_inches = mon->dim.mm.height * 0.03937008; mon->ppi.real.x = mon->dim.px_real.width / x_inches; mon->ppi.real.y = mon->dim.px_real.height / y_inches; @@ -407,7 +407,7 @@ output_update_ppi(struct monitor *mon) mon->ppi.scaled.x = scaled_width / x_inches; mon->ppi.scaled.y = scaled_height / y_inches; - float px_diag = sqrt(pow(scaled_width, 2) + pow(scaled_height, 2)); + double px_diag = sqrt(pow(scaled_width, 2) + pow(scaled_height, 2)); mon->dpi = px_diag / mon->inch * mon->scale; } From 42c6af091440e89be9c0d8895a1c5ff1caac5427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 4 Nov 2022 17:45:43 +0100 Subject: [PATCH 042/118] =?UTF-8?q?wayland:=20force=20monitor=20DPI=20to?= =?UTF-8?q?=2096=20when=20it=E2=80=99s=20unreasonably=20high?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an output has a bogus physical width or height, the DPI can become so high that the cell width/height is too large for pixman_image_fill_rectangles(), resulting in a crash in pixman_fill(). Since it doesn’t make any sense to use a DPI that is obviously bogus, don’t. Force it 96 instead. --- CHANGELOG.md | 1 + wayland.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c41f21a..f4089b37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ ("permanently reset") instead of `2` ("reset") for DEC private modes that are known but unsupported. * Set `PWD` environment variable in the slave process ([#1179][1179]). +* DPI is now forced to 96 when found to be unreasonably high. [1166]: https://codeberg.org/dnkl/foot/issues/1166 [1179]: https://codeberg.org/dnkl/foot/issues/1179 diff --git a/wayland.c b/wayland.c index 974dfb39..e48d59aa 100644 --- a/wayland.c +++ b/wayland.c @@ -409,6 +409,14 @@ output_update_ppi(struct monitor *mon) double px_diag = sqrt(pow(scaled_width, 2) + pow(scaled_height, 2)); mon->dpi = px_diag / mon->inch * mon->scale; + + if (mon->dpi > 1000) { + if (mon->name != NULL) { + LOG_WARN("%s: DPI=%f is unreasonable, using 96 instead", + mon->name, mon->dpi); + } + mon->dpi = 96; + } } static void From b80c7f75fea0c1a69471d1f67aa97b584d3e48b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Fri, 18 Nov 2022 11:07:16 -0500 Subject: [PATCH 043/118] change default log level to WARNING The default foot output looks like this, in Debian testing "bookworm" at the time of writing: anarcat@angela:pubpaste$ foot true info: main.c:421: version: 1.13.1 +pgo +ime +graphemes -assertions info: main.c:428: arch: Linux x86_64/64-bit info: main.c:440: locale: fr_CA.UTF-8 info: config.c:3003: loading configuration from /home/anarcat/.config/foot/foot.ini info: fcft.c:338: fcft: 3.1.5 +graphemes -runs +svg(nanosvg) -assertions info: fcft.c:377: fontconfig: 2.13.1, freetype: 2.12.1, harfbuzz: 5.2.0 info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=8.00pt/8px, dpi=75.00 info: wayland.c:1353: eDP-1: 2256x1504+0x0@60Hz 0x095F 13.32" scale=2 PPI=205x214 (physical) PPI=136x143 (logical), DPI=271.31 info: wayland.c:1509: requesting SSD decorations info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Bold.otf: size=24.00pt/32px, dpi=96.00 info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=24.00pt/32px, dpi=96.00 info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Bold.otf: size=24.00pt/32px, dpi=96.00 info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=24.00pt/32px, dpi=96.00 info: terminal.c:700: cell width=19, height=39 info: terminal.c:588: using 16 rendering threads info: wayland.c:859: using SSD decorations info: main.c:680: goodbye anarcat@angela:pubpaste$ That's 17 lines of output that are *mostly* useless for most use cases. I might understand having this output during the project's startup, when it's helpful for diagnostics, but now Foot just mostly works everywhere, and I've never had a use for any of that stuff in the (arguably short) time I've been using Foot so far. And if I do, there's the `--log-level` commandline option to tweak this. At first, I looked at tweaking the log level through the config file. But as explained in this issue: https://codeberg.org/dnkl/foot/issues/1142 ... there's a chicken and egg problem there that makes it hard to implement and possibly confusing for users as well. There's also the possibility for users to change the shortcut with which they start foot, for example a `.desktop` file so that menu systems that support those start foot properly. But that only works in that environment, and not through the so many things that will just call `foot` and hope it will do the right thing. In my case, I have `foot` hardcoded in a lot of places now, between sway and waybar, and this is only going to grow. Others have suggested adding the flag to a $TERMINAL global variable, but that won't help .desktop users. So, instead of playing whack-a-mole with the log levels, just make it so that, by default, foot is silent. This is actually one of the [basics of UNIX philosophy][1]: > Rule of Silence: When a program has nothing surprising to say, it > should say nothing. And yes, I am aware I am severely violating that principle by writing a way too long commit log for a one-line patch, but there you go, I figured it was good to document the why of this properly. [1]: https://web.archive.org/web/20031102053334/http://www.faqs.org/docs/artu/ch01s06.html --- CHANGELOG.md | 2 ++ client.c | 4 ++-- completions/fish/foot.fish | 2 +- completions/zsh/_foot | 2 +- completions/zsh/_footclient | 2 +- doc/foot.1.scd | 2 +- doc/footclient.1.scd | 2 +- main.c | 4 ++-- 8 files changed, 11 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4089b37..ba339100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,9 +65,11 @@ modes that are known but unsupported. * Set `PWD` environment variable in the slave process ([#1179][1179]). * DPI is now forced to 96 when found to be unreasonably high. +* Set default log level to warning ([#1215][1215]). [1166]: https://codeberg.org/dnkl/foot/issues/1166 [1179]: https://codeberg.org/dnkl/foot/issues/1179 +[1215]: https://codeberg.org/dnkl/foot/pulls/1215 ### Deprecated diff --git a/client.c b/client.c index 2a802d16..6954d17e 100644 --- a/client.c +++ b/client.c @@ -94,7 +94,7 @@ print_usage(const char *prog_name) " -N,--no-wait detach the client process from the running terminal, exiting immediately\n" " -o,--override=[section.]key=value override configuration option\n" " -E, --client-environment exec shell using footclient's environment, instead of the server's\n" - " -d,--log-level={info|warning|error|none} log level (info)\n" + " -d,--log-level={info|warning|error|none} log level (warning)\n" " -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n" " -v,--version show the version number and quit\n" " -e ignored (for compatibility with xterm -e)\n"; @@ -178,7 +178,7 @@ main(int argc, char *const *argv) const char *custom_cwd = NULL; const char *server_socket_path = NULL; - enum log_class log_level = LOG_CLASS_INFO; + enum log_class log_level = LOG_CLASS_WARNING; enum log_colorize log_colorize = LOG_COLORIZE_AUTO; bool hold = false; bool client_environment = false; diff --git a/completions/fish/foot.fish b/completions/fish/foot.fish index 81c7da61..86f6616d 100644 --- a/completions/fish/foot.fish +++ b/completions/fish/foot.fish @@ -15,7 +15,7 @@ complete -c foot -x -s W -l window-size-chars complete -c foot -F -s s -l server -d "run as server; open terminals by running footclient" complete -c foot -s H -l hold -d "remain open after child process exits" complete -c foot -r -s p -l print-pid -d "print PID to this file or FD when up and running (server mode only)" -complete -c foot -x -s d -l log-level -a "info warning error none" -d "log-level (info)" +complete -c foot -x -s d -l log-level -a "info warning error none" -d "log-level (warning)" complete -c foot -x -s l -l log-colorize -a "always never auto" -d "enable or disable colorization of log output on stderr" complete -c foot -s S -l log-no-syslog -d "disable syslog logging (server mode only)" complete -c foot -s v -l version -d "show the version number and quit" diff --git a/completions/zsh/_foot b/completions/zsh/_foot index 0f184cc0..b9f46cdc 100644 --- a/completions/zsh/_foot +++ b/completions/zsh/_foot @@ -18,7 +18,7 @@ _arguments \ '(-s --server)'{-s,--server}'[run as server; open terminals by running footclient]:server:_files' \ '(-H --hold)'{-H,--hold}'[remain open after child process exits]' \ '(-p --print-pid)'{-p,--print-pid}'[print PID to this file or FD when up and running (server mode only)]:pidfile:_files' \ - '(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error none)' \ + '(-d --log-level)'{-d,--log-level}'[log level (warning)]:loglevel:(info warning error none)' \ '(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \ '(-S --log-no-syslog)'{-s,--log-no-syslog}'[disable syslog logging (server mode only)]' \ '(-v --version)'{-v,--version}'[show the version number and quit]' \ diff --git a/completions/zsh/_footclient b/completions/zsh/_footclient index b36644c6..c14d65d5 100644 --- a/completions/zsh/_footclient +++ b/completions/zsh/_footclient @@ -16,7 +16,7 @@ _arguments \ '(-N --no-wait)'{-N,--no-wait}'[detach the client process from the running terminal, exiting immediately]' \ '(-o --override)'{-o,--override}'[configuration option to override, in form SECTION.KEY=VALUE]:()' \ '(-E --client-environment)'{-E,--client-environment}"[child process inherits footclient's environment, instead of the server's]" \ - '(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error none)' \ + '(-d --log-level)'{-d,--log-level}'[log level (warning)]:loglevel:(info warning error none)' \ '(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \ '(-v --version)'{-v,--version}'[show the version number and quit]' \ '(-h --help)'{-h,--help}'[show help message and quit]' \ diff --git a/doc/foot.1.scd b/doc/foot.1.scd index afb8faf5..4ee5df57 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -142,7 +142,7 @@ the foot command line *-d*,*--log-level*={*info*,*warning*,*error*,*none*} Log level, used both for log output on stderr as well as - syslog. Default: _info_. + syslog. Default: _warning_. *-l*,*--log-colorize*=[{*never*,*always*,*auto*}] Enables or disables colorization of log output on stderr. Default: diff --git a/doc/footclient.1.scd b/doc/footclient.1.scd index 93bddd61..63235134 100644 --- a/doc/footclient.1.scd +++ b/doc/footclient.1.scd @@ -75,7 +75,7 @@ terminal has terminated. *-d*,*--log-level*={*info*,*warning*,*error*,*none*} Log level, used both for log output on stderr as well as - syslog. Default: _info_. + syslog. Default: _warning_. *-l*,*--log-colorize*=[{*never*,*always*,*auto*}] Enables or disables colorization of log output on stderr. diff --git a/main.c b/main.c index a3ae579d..c882c825 100644 --- a/main.c +++ b/main.c @@ -83,7 +83,7 @@ print_usage(const char *prog_name) " Without PATH, $XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock will be used.\n" " -H,--hold remain open after child process exits\n" " -p,--print-pid=FILE|FD print PID to file or FD (only applicable in server mode)\n" - " -d,--log-level={info|warning|error|none} log level (info)\n" + " -d,--log-level={info|warning|error|none} log level (warning)\n" " -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n" " -s,--log-no-syslog disable syslog logging (only applicable in server mode)\n" " -v,--version show the version number and quit\n" @@ -236,7 +236,7 @@ main(int argc, char *const *argv) bool fullscreen = false; bool unlink_pid_file = false; const char *pid_file = NULL; - enum log_class log_level = LOG_CLASS_INFO; + enum log_class log_level = LOG_CLASS_WARNING; enum log_colorize log_colorize = LOG_COLORIZE_AUTO; bool log_syslog = true; user_notifications_t user_notifications = tll_init(); From dfabc5d75423c863a7e9a930b9a8aac593784e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 23 Nov 2022 16:27:50 +0100 Subject: [PATCH 044/118] =?UTF-8?q?readme/foot.1:=20mention=20that=20we=20?= =?UTF-8?q?now=20need=20=E2=80=9C-d=20info=E2=80=9D=20to=20get=20log=20out?= =?UTF-8?q?put?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- doc/foot.1.scd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 348f2e18..8d037af3 100644 --- a/README.md +++ b/README.md @@ -565,7 +565,7 @@ reported the same issue. The report should contain the following: - Foot version (`foot --version`). -- Log output from foot (start foot from another terminal). +- Log output from foot (run `foot -d info` from another terminal). - Which Wayland compositor (and version) you are running. - If reporting a crash, please try to provide a `bt full` backtrace with symbols. diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 4ee5df57..e20e7805 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -557,7 +557,7 @@ the same issue. The report should contain the following: - Foot version (*foot --version*). -- Log output from foot (start foot from another terminal). +- Log output from foot (run *foot -d info* from another terminal). - Which Wayland compositor (and version) you are running. - If reporting a crash, please try to provide a *bt full* backtrace with symbols. From 5a54423000ad0cffec0178a6091c87d75110eee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 23 Nov 2022 16:15:32 +0100 Subject: [PATCH 045/118] term: adjust user-set line-height by the same percentage as the primary font MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch, a user-set line-height was increased/decreased by the exact same amount of pt’s as the font(s). This means, that when there’s a large discrepancy between the line-height and the font size, the proportion between the line’s height and the font size will change as we increase or decrease the font size. This patch changes how the line height is adjusted when the font size is incremented or decremented. We calculate the difference, in percent, between the primary font’s original (default) size, and its current size, and then apply that to the configured line-height. Closes #1218 --- terminal.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/terminal.c b/terminal.c index 6cb419be..ea934df9 100644 --- a/terminal.c +++ b/terminal.c @@ -2031,12 +2031,20 @@ term_font_size_adjust(struct terminal *term, double amount) } if (term->font_line_height.px >= 0) { - float old_pt_size = term->font_line_height.px > 0 - ? term->font_line_height.px * 72. / dpi - : term->font_line_height.pt; + const struct config *conf = term->conf; + + const float font_original_pt_size = + conf->fonts[0].arr[0].px_size > 0 + ? conf->fonts[0].arr[0].px_size * 72. / dpi + : conf->fonts[0].arr[0].pt_size; + + const float change = term->font_sizes[0][0].pt_size / font_original_pt_size; + const float line_original_pt_size = conf->line_height.px > 0 + ? conf->line_height.px * 72. / dpi + : conf->line_height.pt; term->font_line_height.px = 0; - term->font_line_height.pt = fmaxf(old_pt_size + amount, 0.); + term->font_line_height.pt = fmaxf(line_original_pt_size * change, 0.); } return reload_fonts(term); From f31ea4f56d6ff560ad16f9c18528881ee8077dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 23 Nov 2022 16:23:01 +0100 Subject: [PATCH 046/118] changelog: line-height adjustment with user-set line-height --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba339100..499b4275 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,11 +98,14 @@ cursor. Only applies to block cursor using inversed fg/bg colors. ([#1205][1205]). * Crash when monitor’s physical size is "too small" ([#1209][1209]). +* Line-height adjustment when incrementing/decrementing the font size + with a user-set line-height ([#1218][1218]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 [1205]: https://codeberg.org/dnkl/foot/issues/1205 [1209]: https://codeberg.org/dnkl/foot/issues/1209 +[1218]: https://codeberg.org/dnkl/foot/issues/1218 ### Security From 94bac0513ab3ca78464d8e79c153c8ee4bac835f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Nov 2022 14:34:31 +0100 Subject: [PATCH 047/118] term: update user-set line-height just before calculating the cell dimensions This ensures *all* font-size affecting changes (DPI, output scaling, font size increment/decrement) also updates the line-height. --- terminal.c | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/terminal.c b/terminal.c index ea934df9..3af436a4 100644 --- a/terminal.c +++ b/terminal.c @@ -704,6 +704,34 @@ free_custom_glyphs(struct fcft_glyph ***glyphs, size_t count) *glyphs = NULL; } +static void +term_line_height_update(struct terminal *term) +{ + const struct config *conf = term->conf; + + if (term->conf->line_height.px < 0) + return; + + const float dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.; + + const float font_original_pt_size = + conf->fonts[0].arr[0].px_size > 0 + ? conf->fonts[0].arr[0].px_size * 72. / dpi + : conf->fonts[0].arr[0].pt_size; + const float font_current_pt_size = + term->font_sizes[0][0].px_size > 0 + ? term->font_sizes[0][0].px_size * 72. / dpi + : term->font_sizes[0][0].pt_size; + + const float change = font_current_pt_size / font_original_pt_size; + const float line_original_pt_size = conf->line_height.px > 0 + ? conf->line_height.px * 72. / dpi + : conf->line_height.pt; + + term->font_line_height.px = 0; + term->font_line_height.pt = fmaxf(line_original_pt_size * change, 0.); +} + static bool term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) { @@ -730,6 +758,8 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) fonts[0], U'M', term->font_subpixel); int advance = M != NULL ? M->advance.x : term->fonts[0]->max_advance.x; + term_line_height_update(term); + term->cell_width = advance + term_pt_or_px_as_pixels(term, &conf->letter_spacing); @@ -1078,7 +1108,6 @@ load_fonts_from_conf(struct terminal *term) } } - term->font_line_height = term->conf->line_height; return reload_fonts(term); } @@ -1298,7 +1327,6 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .pt_size = font->pt_size, .px_size = font->px_size}; } } - term->font_line_height = conf->line_height; add_utmp_record(conf, reaper, ptmx); @@ -2030,23 +2058,6 @@ term_font_size_adjust(struct terminal *term, double amount) } } - if (term->font_line_height.px >= 0) { - const struct config *conf = term->conf; - - const float font_original_pt_size = - conf->fonts[0].arr[0].px_size > 0 - ? conf->fonts[0].arr[0].px_size * 72. / dpi - : conf->fonts[0].arr[0].pt_size; - - const float change = term->font_sizes[0][0].pt_size / font_original_pt_size; - const float line_original_pt_size = conf->line_height.px > 0 - ? conf->line_height.px * 72. / dpi - : conf->line_height.pt; - - term->font_line_height.px = 0; - term->font_line_height.pt = fmaxf(line_original_pt_size * change, 0.); - } - return reload_fonts(term); } From e85257bcae116f5e6148e38690e2ec95b586d451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Nov 2022 17:09:31 +0100 Subject: [PATCH 048/118] =?UTF-8?q?term:=20initialize=20term->font=5Fline?= =?UTF-8?q?=5Fheight=20when=20there=E2=80=99s=20no=20user-set=20line-heigh?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terminal.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/terminal.c b/terminal.c index 3af436a4..429a4cc3 100644 --- a/terminal.c +++ b/terminal.c @@ -709,8 +709,11 @@ term_line_height_update(struct terminal *term) { const struct config *conf = term->conf; - if (term->conf->line_height.px < 0) + if (term->conf->line_height.px < 0) { + term->font_line_height.pt = 0; + term->font_line_height.px = -1; return; + } const float dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.; From fa6b07abeacfb5b8a70bc762e9c8ff64470c4d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Nov 2022 17:20:05 +0100 Subject: [PATCH 049/118] term: apply scale factor when converting a px value to pt --- terminal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terminal.c b/terminal.c index 429a4cc3..1914a229 100644 --- a/terminal.c +++ b/terminal.c @@ -946,7 +946,7 @@ term_pt_or_px_as_pixels(const struct terminal *term, return pt_or_px->px == 0 ? round(pt_or_px->pt * scale * dpi / 72) - : pt_or_px->px; + : pt_or_px->px * scale; } struct font_load_data { From db2627ea26564fc1b8bfc890e42c90a2cde48a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Nov 2022 17:21:53 +0100 Subject: [PATCH 050/118] changelog: scaling factor not being applied when converting px-to-pt --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 499b4275..c5584b45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -100,6 +100,8 @@ * Crash when monitor’s physical size is "too small" ([#1209][1209]). * Line-height adjustment when incrementing/decrementing the font size with a user-set line-height ([#1218][1218]). +* Scaling factor not being correctly applied when converting pt-or-px + config values (e.g. letter offsets, line height etc). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 From 0fc8b65a2b77a5c4dd066e4d49be470ee1d1f70a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Nov 2022 17:05:27 +0100 Subject: [PATCH 051/118] selection: selection_on_rows(): typo: row_start -> row_end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes an issue where selections in the scroll margins were not detected correctly. This meant they weren’t canceled as they should have been, which in turn caused a visual glitch where text appeared to be selected, but were in fact not. --- CHANGELOG.md | 1 + csi.c | 4 ++-- selection.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5584b45..1f7d033b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,6 +102,7 @@ with a user-set line-height ([#1218][1218]). * Scaling factor not being correctly applied when converting pt-or-px config values (e.g. letter offsets, line height etc). +* Selection being stuck visually when `IL` and `DL`.` [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 diff --git a/csi.c b/csi.c index 2eacaaa9..e77ae971 100644 --- a/csi.c +++ b/csi.c @@ -933,7 +933,7 @@ csi_dispatch(struct terminal *term, uint8_t final) break; } - case 'L': { + case 'L': { /* IL */ if (term->grid->cursor.point.row < term->scroll_region.start || term->grid->cursor.point.row >= term->scroll_region.end) break; @@ -953,7 +953,7 @@ csi_dispatch(struct terminal *term, uint8_t final) break; } - case 'M': { + case 'M': { /* DL */ if (term->grid->cursor.point.row < term->scroll_region.start || term->grid->cursor.point.row >= term->scroll_region.end) break; diff --git a/selection.c b/selection.c index 92f1f85f..f6349d7f 100644 --- a/selection.c +++ b/selection.c @@ -86,7 +86,7 @@ selection_on_rows(const struct terminal *term, int row_start, int row_end) const int rel_row_start = grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, row_start); const int rel_row_end = - grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, row_start); + grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, row_end); int rel_sel_start = grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, start->row); int rel_sel_end = From 1b24cf4fcb8a32a9c20eb607c2015542eb2753d4 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Thu, 24 Nov 2022 20:34:41 +0000 Subject: [PATCH 052/118] doc: ctlseq: add trailing space to fix XTGETTCAP entry in DCS table Without the trailing space, both the sequence and the description were getting packed into a single table column. --- doc/foot-ctlseqs.7.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index 1d94219f..e2d66982 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -703,7 +703,7 @@ and are terminated by *\\E\\* (ST). : Begin (_C_=*1*) or end (_C_=*2*) application synchronized updates. This sequence is supported for compatibility reasons, but it's recommended to use private mode 2026 (see above) instead. -| \\EP + q \\E\\ +| \\EP + q \\E\\ : Query builtin terminfo database (XTGETTCAP) From 76d494484f0b26f7785c0964cc412609d09607ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 30 Nov 2022 10:51:45 +0100 Subject: [PATCH 053/118] url-mode: tag cells after snapshot:ing the grid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch, hyperlinked cells were tagged with the “URL” attribute (thus instructing the renderer to draw an underline) *before* the grid was snapshot. When exiting URL mode, the cells were once again updated, this time removing the URL attribute. But what if an escape sequence had modified the grid _while we were in URL mode_? Depending on the sequence, it could move cells around in such a way, that when exiting URL mode, the affected cells weren’t updated correctly. I.e. we left some cells with the URL attribute still set. The fix is simple: tag cells in the snapshot:ed grid only (which isn’t affected by any escape sequence received while in URL mode). Not in the *actual* grid (which _is_ affected). --- CHANGELOG.md | 1 + url-mode.c | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f7d033b..13b87f4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,6 +103,7 @@ * Scaling factor not being correctly applied when converting pt-or-px config values (e.g. letter offsets, line height etc). * Selection being stuck visually when `IL` and `DL`.` +* URL underlines sometimes still being visible after exiting URL mode. [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 diff --git a/url-mode.c b/url-mode.c index 6fa16623..7d7ffd81 100644 --- a/url-mode.c +++ b/url-mode.c @@ -746,15 +746,18 @@ tag_cells_for_url(struct terminal *term, const struct url *url, bool value) if (url->url_mode_dont_change_url_attr) return; + struct grid *grid = term->url_grid_snapshot; + xassert(grid != NULL); + const struct coord *start = &url->range.start; const struct coord *end = &url->range.end; - size_t end_r = end->row & (term->grid->num_rows - 1); + size_t end_r = end->row & (grid->num_rows - 1); - size_t r = start->row & (term->grid->num_rows - 1); + size_t r = start->row & (grid->num_rows - 1); size_t c = start->col; - struct row *row = term->grid->rows[r]; + struct row *row = grid->rows[r]; row->dirty = true; while (true) { @@ -766,10 +769,10 @@ tag_cells_for_url(struct terminal *term, const struct url *url, bool value) break; if (++c >= term->cols) { - r = (r + 1) & (term->grid->num_rows - 1); + r = (r + 1) & (grid->num_rows - 1); c = 0; - row = term->grid->rows[r]; + row = grid->rows[r]; if (row == NULL) { /* Un-allocated scrollback. This most likely means a * runaway OSC-8 URL. */ @@ -788,15 +791,6 @@ urls_render(struct terminal *term) if (tll_length(win->term->urls) == 0) return; - xassert(tll_length(win->urls) == 0); - tll_foreach(win->term->urls, it) { - struct wl_url url = {.url = &it->item}; - wayl_win_subsurface_new(win, &url.surf, false); - - tll_push_back(win->urls, url); - tag_cells_for_url(term, &it->item, true); - } - /* Dirty the last cursor, to ensure it is erased */ { struct row *cursor_row = term->render.last_cursor.row; @@ -819,6 +813,15 @@ urls_render(struct terminal *term) /* Snapshot the current grid */ term->url_grid_snapshot = grid_snapshot(term->grid); + xassert(tll_length(win->urls) == 0); + tll_foreach(win->term->urls, it) { + struct wl_url url = {.url = &it->item}; + wayl_win_subsurface_new(win, &url.surf, false); + + tll_push_back(win->urls, url); + tag_cells_for_url(term, &it->item, true); + } + render_refresh_urls(term); render_refresh(term); } @@ -860,7 +863,6 @@ urls_reset(struct terminal *term) } tll_foreach(term->urls, it) { - tag_cells_for_url(term, &it->item, false); url_destroy(&it->item); tll_remove(term->urls, it); } From b43a41df6a5a72b22b6c16d5ac45d0d66a9d5207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 2 Dec 2022 11:45:10 +0100 Subject: [PATCH 054/118] =?UTF-8?q?log:=20don=E2=80=99t=20default=20to=20s?= =?UTF-8?q?yslog=20enabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize the global ‘do_syslog’ variable to false. This ensures any log calls done before log_init() has been called (e.g. unit tests) doesn’t syslog anything. As a side effect, such log calls no longer open an implicit syslog file descriptor; this is how this “bug” was found: valgrind detected an unclosed file descriptor at exit. Finally, completely disable syslogging if log-level is “none”. --- log.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/log.c b/log.c index b93b2cde..360ca1c0 100644 --- a/log.c +++ b/log.c @@ -15,7 +15,7 @@ #include "xsnprintf.h" static bool colorize = false; -static bool do_syslog = true; +static bool do_syslog = false; static enum log_class log_level = LOG_CLASS_NONE; static const struct { @@ -45,8 +45,13 @@ log_init(enum log_colorize _colorize, bool _do_syslog, log_level = _log_level; int slvl = log_level_map[_log_level].syslog_equivalent; - if (do_syslog && slvl != -1) { + if (slvl < 0) + do_syslog = false; + + if (do_syslog) { openlog(NULL, /*LOG_PID*/0, facility_map[syslog_facility]); + + xassert(slvl >= 0); setlogmask(LOG_UPTO(slvl)); } } From 1486c57bdb084e5c41f917fd542a3605dcaa90a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 4 Dec 2022 19:49:02 +0100 Subject: [PATCH 055/118] doc: foot: add PWD to list of env vars set in child process --- doc/foot.1.scd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index e20e7805..6f63d4c8 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -539,6 +539,9 @@ In all other cases, the exit code is that of the client application set according to either the *--term* command-line option or the *term* config option in *foot.ini*(5). +*PWD* + Current working directory (at the time of launching foot) + *COLORTERM* This variable is set to *truecolor*, to indicate to client applications that 24-bit RGB colors are supported. From 051e86242043cd10dee186343e3f7b661ee30219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 1 Dec 2022 15:00:44 +0100 Subject: [PATCH 056/118] config: allow string values to be quoted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Both double and single quotes are recognized. There’s no difference in how they are handled. * The entire string must be quoted: - “a quoted string” - OK - quotes “in the middle” of a string - NOT ok * Two escape characters are regonized: - Backslash - The quote character itself --- CHANGELOG.md | 2 ++ config.c | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13b87f4b..bffe4e11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,8 @@ * Support (optional) for utmp logging with libutempter. * `kxIN` and `kxOUT` (focus in/out events) to terminfo. * `name` capability to `XTGETTCAP`. +* String values in `foot.ini` may now be quoted. This can be used to + set a value to the empty string, for example. [1136]: https://codeberg.org/dnkl/foot/issues/1136 diff --git a/config.c b/config.c index e2c007d2..cbf64abc 100644 --- a/config.c +++ b/config.c @@ -502,8 +502,48 @@ value_to_double(struct context *ctx, float *res) static bool NOINLINE value_to_str(struct context *ctx, char **res) { + char *copy = xstrdup(ctx->value); + char *end = copy + strlen(copy) - 1; + + /* Un-quote + * + * Note: this is very simple; we only support the *entire* value + * being quoted. That is, no mid-value quotes. Both double and + * single quotes are supported. + * + * - key="value" OK + * - key=abc "quote" def NOT OK + * - key=’value’ OK + * + * Finally, we support escaping the quote character, and the + * escape character itself: + * + * - key="value \"quotes\"" + * - key="backslash: \\" + * + * ONLY the "current" quote character can be escaped: + * + * key="value \'" NOt OK (both backslash and single quote is kept) + */ + + if ((copy[0] == '"' && *end == '"') || + (copy[0] == '\'' && *end == '\'')) + { + const char quote = copy[0]; + *end = '\0'; + + memmove(copy, copy + 1, end - copy); + + /* Un-escape */ + for (char *p = copy; *p != '\0'; p++) { + if (p[0] == '\\' && (p[1] == '\\' || p[1] == quote)) { + memmove(p, p + 1, end - p); + } + } + } + free(*res); - *res = xstrdup(ctx->value); + *res = copy; return true; } From 57d9a7451faa62381058575a7dbf11fdb73903d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 1 Dec 2022 15:06:13 +0100 Subject: [PATCH 057/118] =?UTF-8?q?foot.ini:=20use=20a=20quoted,=20empty?= =?UTF-8?q?=20string=20for=20=E2=80=9Cindicator-format=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don’t allow empty values, but we do allow quoted, empty values. --- foot.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foot.ini b/foot.ini index 62f853fa..d0c93519 100644 --- a/foot.ini +++ b/foot.ini @@ -48,7 +48,7 @@ # lines=1000 # multiplier=3.0 # indicator-position=relative -# indicator-format= +# indicator-format="" [url] # launch=xdg-open ${url} From 646314469afd96eda346b6a296037d5430e5f121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 2 Dec 2022 15:03:07 +0100 Subject: [PATCH 058/118] doc: foot.ini: add example, and mention string options can be quoted --- doc/foot.ini.5.scd | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index ee6aa94c..e18a6208 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -22,6 +22,15 @@ in this order: An example configuration file containing all options with their default value commented out will usually be installed to */etc/xdg/foot/foot.ini*. +Options are set using KEY=VALUE pairs: + + *\[colors\]*++ +*background=000000*++ +*foreground=ffffff* + +Empty values (*KEY=*) are not supported. String options do allow the +empty string to be set, but it must be quoted: *KEY=""*) + # SECTION: main *shell* From ccfb953bb020a1d229490b8a3e7790ed5c7e1752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 1 Dec 2022 19:43:38 +0100 Subject: [PATCH 059/118] slave: unsetenv() env vars that have been set to the empty string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is, users can now *clear* environment variables by doing: [environment] VAR=”” Note that the quotes are required. Closes #1225 --- CHANGELOG.md | 3 +++ config.c | 23 ++++++++++++----------- slave.c | 11 +++++++++-- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bffe4e11..ead014cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,8 +51,11 @@ * `name` capability to `XTGETTCAP`. * String values in `foot.ini` may now be quoted. This can be used to set a value to the empty string, for example. +* Environment variables can now be **unset**, by setting + `[environment].=""` (quotes are required) ([#1225][1225]) [1136]: https://codeberg.org/dnkl/foot/issues/1136 +[1225]: https://codeberg.org/dnkl/foot/issues/1225 ### Changed diff --git a/config.c b/config.c index cbf64abc..68641647 100644 --- a/config.c +++ b/config.c @@ -2295,21 +2295,22 @@ parse_section_environment(struct context *ctx) { struct config *conf = ctx->conf; const char *key = ctx->key; - const char *value = ctx->value; + /* Check for pre-existing env variable */ tll_foreach(conf->env_vars, it) { - if (strcmp(it->item.name, key) == 0) { - free(it->item.value); - it->item.value = xstrdup(value); - return true; - } + if (strcmp(it->item.name, key) == 0) + return value_to_str(ctx, &it->item.value); } - struct env_var var = { - .name = xstrdup(key), - .value = xstrdup(value), - }; - tll_push_back(conf->env_vars, var); + /* + * No pre-existing variable - allocate a new one + */ + + char *value = NULL; + if (!value_to_str(ctx, &value)) + return false; + + tll_push_back(conf->env_vars, ((struct env_var){xstrdup(key), value})); return true; } diff --git a/slave.c b/slave.c index 4dd80e6f..d4861ad0 100644 --- a/slave.c +++ b/slave.c @@ -359,8 +359,15 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv, #endif if (extra_env_vars != NULL) { - tll_foreach(*extra_env_vars, it) - setenv(it->item.name, it->item.value, 1); + tll_foreach(*extra_env_vars, it) { + const char *name = it->item.name; + const char *value = it->item.value; + + if (strlen(value) == 0) + unsetenv(name); + else + setenv(name, value, 1); + } } char **_shell_argv = NULL; From 3b9aca6a3d0caef3c0a5070f7684687e8c5d0c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 14 Dec 2022 12:20:52 +0100 Subject: [PATCH 060/118] doc: foot-ctlseq: expand last column to fill screen in all tables --- doc/foot-ctlseqs.7.scd | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index e2d66982..f06a9418 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -22,7 +22,7 @@ This document describes all the control sequences supported by foot. [[ *Sequence* :[ *Name* -:[ *Description* +:< *Description* | \\a : BEL : Depends on what *bell* in *foot.ini*(5) is set to. @@ -60,7 +60,7 @@ equivalent to 8-bit C1 controls. [[ *Sequence* :[ *Name* :[ *Origin* -:[ *Description* +:< *Description* | \\E 7 : DECSC : VT100 @@ -140,7 +140,7 @@ single CSI sequence by separating them with semicolons: *\\E[ 1;2;3 m*. [[ *Parameter* -:[ *Description* +:< *Description* | 0 : Reset all attributes | 1 @@ -223,7 +223,7 @@ following 4 escape sequences: [[ *Sequence* :[ *Name* -:[ *Description* +:< *Description* | \\E[ ? _Pm_ h : DECSET : Enable private mode @@ -243,7 +243,7 @@ that corresponds to one of the following modes: [[ *Parameter* :[ *Origin* -:[ *Description* +:< *Description* | 1 : VT100 : Cursor keys mode (DECCKM) @@ -344,7 +344,7 @@ manipulation sequences. The generic format is: [[ *Parameter 1* :[ *Parameter 2* -:[ *Description* +:< *Description* | 11 : - : Report if window is iconified. Foot always reports *1* - not iconified. @@ -394,7 +394,7 @@ manipulation sequences. The generic format is: [[ *Parameter* :[ *Name* :[ *Origin* -:[ *Description* +:< *Description* | \\E[ _Ps_ c : DA : VT100 @@ -595,7 +595,7 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_. [[ *Sequence* :[ *Origin* -:[ *Description* +:< *Description* | \\E] 0 ; _Pt_ \\E\\ : xterm : Set window icon and title to _Pt_ (foot does not support setting the @@ -693,7 +693,7 @@ All _DCS_ sequences begin with *\\EP* (sometimes abbreviated _DCS_), and are terminated by *\\E\\* (ST). [[ *Sequence* -:[ *Description* +:< *Description* | \\EP q \\E\\ : Emit a sixel image at the current cursor position | \\P $ q \\E\\ From 7bb5c80d04be5e5297fb6259e487fe0105e85935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Fri, 16 Dec 2022 08:38:37 +0100 Subject: [PATCH 061/118] main: Graceful fallback if user has configured an invalid locale --- main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index c882c825..4af200fd 100644 --- a/main.c +++ b/main.c @@ -433,8 +433,13 @@ main(int argc, char *const *argv) const char *locale = setlocale(LC_CTYPE, ""); if (locale == NULL) { - LOG_ERR("setlocale() failed"); - return ret; + /* + * If the user has configured an invalid locale, or a name of a locale + * 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_INFO("locale: %s", locale); From f6ca8c90e11d9b1ecdfe8a5bf69b1b793376a91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 15 Dec 2022 11:10:32 +0100 Subject: [PATCH 062/118] =?UTF-8?q?config:=20add=20=E2=80=98font-size-adju?= =?UTF-8?q?stment=3DN[px|%]=E2=80=99=20option?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new config option, font-size-adjustment. It lets you configure how much the font size should be incremented/decremented when zooming in or out (ctrl-+, ctrl+-). Values can be specified in points, pixels or percent. Closes #1188 --- CHANGELOG.md | 6 +++- config.c | 26 ++++++++++++++ config.h | 6 ++++ doc/foot.ini.5.scd | 13 +++++++ terminal.c | 87 +++++++++++++++++++++++++++++++++++---------- tests/test-config.c | 1 + 6 files changed, 120 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ead014cf..9538ccca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,10 +52,14 @@ * String values in `foot.ini` may now be quoted. This can be used to set a value to the empty string, for example. * Environment variables can now be **unset**, by setting - `[environment].=""` (quotes are required) ([#1225][1225]) + `[environment].=""` (quotes are required) ([#1225][1225]). +* `font-size-adjustment=N[px]` option, letting you configure how much + to increment/decrement the font size when zooming in or out + ([#1188][1188]). [1136]: https://codeberg.org/dnkl/foot/issues/1136 [1225]: https://codeberg.org/dnkl/foot/issues/1225 +[1188]: https://codeberg.org/dnkl/foot/issues/1188 ### Changed diff --git a/config.c b/config.c index 68641647..b10f42b2 100644 --- a/config.c +++ b/config.c @@ -925,6 +925,31 @@ parse_section_main(struct context *ctx) return true; } + else if (strcmp(key, "font-size-adjustment") == 0) { + const size_t len = strlen(ctx->value); + if (len >= 1 && ctx->value[len - 1] == '%') { + errno = 0; + char *end = NULL; + + float percent = strtof(ctx->value, &end); + if (!(errno == 0 && end == ctx->value + len - 1)) { + LOG_CONTEXTUAL_ERR( + "invalid percent value (must be in the form 10.5%%)"); + return false; + } + + conf->font_size_adjustment.percent = percent / 100.; + conf->font_size_adjustment.pt_or_px.pt = 0; + conf->font_size_adjustment.pt_or_px.px = 0; + return true; + } else { + bool ret = value_to_pt_or_px(ctx, &conf->font_size_adjustment.pt_or_px); + if (ret) + conf->font_size_adjustment.percent = 0.; + return ret; + } + } + else if (strcmp(key, "line-height") == 0) return value_to_pt_or_px(ctx, &conf->line_height); @@ -2886,6 +2911,7 @@ config_load(struct config *conf, const char *conf_path, }, .startup_mode = STARTUP_WINDOWED, .fonts = {{0}}, + .font_size_adjustment = {.percent = 0., .pt_or_px = {.pt = 0.5, .px = 0}}, .line_height = {.pt = 0, .px = -1}, .letter_spacing = {.pt = 0, .px = 0}, .horizontal_letter_offset = {.pt = 0, .px = 0}, diff --git a/config.h b/config.h index d35abbb2..648d92e4 100644 --- a/config.h +++ b/config.h @@ -22,6 +22,11 @@ struct pt_or_px { float pt; }; +struct font_size_adjustment { + struct pt_or_px pt_or_px; + float percent; +}; + enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BEAM }; enum conf_size_type {CONF_SIZE_PX, CONF_SIZE_CELLS}; @@ -139,6 +144,7 @@ struct config { enum {DPI_AWARE_AUTO, DPI_AWARE_YES, DPI_AWARE_NO} dpi_aware; struct config_font_list fonts[4]; + struct font_size_adjustment font_size_adjustment; /* Custom font metrics (-1 = use real font metrics) */ struct pt_or_px line_height; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index e18a6208..6443d2ba 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -80,6 +80,19 @@ empty string to be set, but it must be quoted: *KEY=""*) Default: _monospace:size=8_ (*font*), _not set_ (*font-bold*, *font-italic*, *font-bold-italic*). +*font-size-adjustment* + Amount, in _points_, _pixels_ or _percent_, to increment/decrement + the font size when zooming in our out. + + Examples: + ``` + font-size-adjustment=0.5 # Adjust by 0.5 points + font-size-adjustment=10xp # Adjust by 10 pixels + font-size-adjustment=7.5% # Adjust by 7.5 percent + ``` + + Default: _0.5_ + *include* Absolute path to configuration file to import. diff --git a/terminal.c b/terminal.c index 1914a229..78ce4bc3 100644 --- a/terminal.c +++ b/terminal.c @@ -2035,29 +2035,70 @@ term_reset(struct terminal *term, bool hard) } static bool -term_font_size_adjust(struct terminal *term, double amount) +term_font_size_adjust_by_points(struct terminal *term, float amount) { const struct config *conf = term->conf; - const float dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.; for (size_t i = 0; i < 4; i++) { const struct config_font_list *font_list = &conf->fonts[i]; for (size_t j = 0; j < font_list->count; j++) { - float old_pt_size = term->font_sizes[i][j].pt_size; + struct config_font *font = &term->font_sizes[i][j]; + float old_pt_size = font->pt_size; - /* - * To ensure primary and user-configured fallback fonts are - * resizes by the same amount, convert pixel sizes to point - * sizes, and to the adjustment on point sizes only. - */ + if (font->px_size > 0) + old_pt_size = font->px_size * 72. / dpi; - if (term->font_sizes[i][j].px_size > 0) - old_pt_size = term->font_sizes[i][j].px_size * 72. / dpi; + font->pt_size = fmaxf(old_pt_size + amount, 0.); + font->px_size = -1; + } + } - term->font_sizes[i][j].pt_size = fmaxf(old_pt_size + amount, 0.); - term->font_sizes[i][j].px_size = -1; + return reload_fonts(term); +} + +static bool +term_font_size_adjust_by_pixels(struct terminal *term, int amount) +{ + const struct config *conf = term->conf; + const float dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.; + + for (size_t i = 0; i < 4; i++) { + const struct config_font_list *font_list = &conf->fonts[i]; + + for (size_t j = 0; j < font_list->count; j++) { + struct config_font *font = &term->font_sizes[i][j]; + int old_px_size = font->px_size; + + if (font->px_size <= 0) + old_px_size = font->pt_size * dpi / 72.; + + font->px_size = max(old_px_size + amount, 1); + } + } + + return reload_fonts(term); +} + +static bool +term_font_size_adjust_by_percent(struct terminal *term, bool increment, float percent) +{ + const struct config *conf = term->conf; + const float multiplier = increment + ? 1. + percent + : 1. / (1. + percent); + + for (size_t i = 0; i < 4; i++) { + const struct config_font_list *font_list = &conf->fonts[i]; + + for (size_t j = 0; j < font_list->count; j++) { + struct config_font *font = &term->font_sizes[i][j]; + + if (font->px_size > 0) + font->px_size = max(font->px_size * multiplier, 1); + else + font->pt_size = fmax(font->pt_size * multiplier, 0); } } @@ -2067,19 +2108,29 @@ term_font_size_adjust(struct terminal *term, double amount) bool term_font_size_increase(struct terminal *term) { - if (!term_font_size_adjust(term, 0.5)) - return false; + const struct config *conf = term->conf; + const struct font_size_adjustment *inc_dec = &conf->font_size_adjustment; - return true; + if (inc_dec->percent > 0.) + return term_font_size_adjust_by_percent(term, true, inc_dec->percent); + else if (inc_dec->pt_or_px.px > 0) + return term_font_size_adjust_by_pixels(term, inc_dec->pt_or_px.px); + else + return term_font_size_adjust_by_points(term, inc_dec->pt_or_px.pt); } bool term_font_size_decrease(struct terminal *term) { - if (!term_font_size_adjust(term, -0.5)) - return false; + const struct config *conf = term->conf; + const struct font_size_adjustment *inc_dec = &conf->font_size_adjustment; - return true; + if (inc_dec->percent > 0.) + return term_font_size_adjust_by_percent(term, false, inc_dec->percent); + else if (inc_dec->pt_or_px.px > 0) + return term_font_size_adjust_by_pixels(term, -inc_dec->pt_or_px.px); + else + return term_font_size_adjust_by_points(term, -inc_dec->pt_or_px.pt); } bool diff --git a/tests/test-config.c b/tests/test-config.c index ae7969dc..4f8b0c3b 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -467,6 +467,7 @@ test_section_main(void) test_boolean(&ctx, &parse_section_main, "locked-title", &conf.locked_title); test_boolean(&ctx, &parse_section_main, "notify-focus-inhibit", &conf.notify_focus_inhibit); + test_pt_or_px(&ctx, &parse_section_main, "font-size-adjustment", &conf.font_size_adjustment.pt_or_px); /* TODO: test ‘N%’ values too */ test_pt_or_px(&ctx, &parse_section_main, "line-height", &conf.line_height); test_pt_or_px(&ctx, &parse_section_main, "letter-spacing", &conf.letter_spacing); test_pt_or_px(&ctx, &parse_section_main, "horizontal-letter-offset", &conf.horizontal_letter_offset); From 59018446fd8ff616aa80a81dea581c935372b605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 17 Dec 2022 10:18:55 +0100 Subject: [PATCH 063/118] foot.ini: add font-size-adjustment --- foot.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/foot.ini b/foot.ini index d0c93519..8266b01b 100644 --- a/foot.ini +++ b/foot.ini @@ -12,6 +12,7 @@ # font-bold= # font-italic= # font-bold-italic= +# font-size-adjustment=0.5 # line-height= # letter-spacing=0 # horizontal-letter-offset=0 From 7bf150c11a6d3b8145b7a3d8b7d0ae2349e0c094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 17 Dec 2022 10:25:16 +0100 Subject: [PATCH 064/118] =?UTF-8?q?config:=20value=5Fto=5Fpt=5For=5Fpx():?= =?UTF-8?q?=20don=E2=80=99t=20allow=20empty=20px=20values=20(key=3Dpx)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.c b/config.c index b10f42b2..af93f419 100644 --- a/config.c +++ b/config.c @@ -651,7 +651,7 @@ value_to_pt_or_px(struct context *ctx, struct pt_or_px *res) char *end = NULL; long value = strtol(s, &end, 10); - if (!(errno == 0 && end == s + len - 2)) { + if (!(len > 2 && errno == 0 && end == s + len - 2)) { LOG_CONTEXTUAL_ERR("invalid px value (must be in the form 12px)"); return false; } From 4ee0b28b02a4633a4f4e6b41b9da57e41bcf9356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 17 Dec 2022 10:25:48 +0100 Subject: [PATCH 065/118] =?UTF-8?q?config:=20font-size-adjustment:=20don?= =?UTF-8?q?=E2=80=99t=20allow=20empty=20%-values=20(key=3D%)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.c b/config.c index af93f419..7d849d5c 100644 --- a/config.c +++ b/config.c @@ -932,7 +932,7 @@ parse_section_main(struct context *ctx) char *end = NULL; float percent = strtof(ctx->value, &end); - if (!(errno == 0 && end == ctx->value + len - 1)) { + if (!(len > 1 && errno == 0 && end == ctx->value + len - 1)) { LOG_CONTEXTUAL_ERR( "invalid percent value (must be in the form 10.5%%)"); return false; From 6ebe5cf62115f34d4f9ec1bbf17d3f30447c28f6 Mon Sep 17 00:00:00 2001 From: argosatcore Date: Sun, 25 Dec 2022 05:34:56 +0000 Subject: [PATCH 066/118] Add Deus theme. New color palette based on: https://github.com/ajmwagar/vim-deus --- themes/deus | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 themes/deus diff --git a/themes/deus b/themes/deus new file mode 100644 index 00000000..5f863b76 --- /dev/null +++ b/themes/deus @@ -0,0 +1,32 @@ +# Deus +# Color palette based on: https://github.com/ajmwagar/vim-deus + +[cursor] +color=2c323b eaeaea + +[colors] +alpha=1.0 +background=2c323b +foreground=eaeaea +regular0=242a32 +regular1=d54e53 +regular2=98c379 +regular3=e5c07b +regular4=83a598 +regular5=c678dd +regular6=70c0ba +regular7=eaeaea +bright0=666666 +bright1=ec3e45 +bright2=90c966 +bright3=edbf69 +bright4=73ba9f +bright5=c858e9 +bright6=2bcec2 +bright7=ffffff + +## Enable if prefer Deus colors instead of inverterd fg/bg for +## highlighting (mouse selection) +# selection-foreground=2c323b +# selection-background=eaeaea + From da7b393a034dfb36dac8afc9b8d0698e8d37fea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Dec 2022 10:54:02 +0100 Subject: [PATCH 067/118] themes: remove alpha MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alpha isn’t really part of the theme. Leave it up to the user to set alpha. --- themes/catppuccin | 1 - themes/deus | 8 +++----- themes/dracula | 1 - themes/jetbrains-darcula | 1 - themes/modus-operandi | 1 - themes/modus-vivendi | 1 - themes/paper-color-dark | 43 ++++++++++++++++++++-------------------- themes/paper-color-light | 43 ++++++++++++++++++++-------------------- 8 files changed, 45 insertions(+), 54 deletions(-) diff --git a/themes/catppuccin b/themes/catppuccin index f873aa3f..9e46aeed 100644 --- a/themes/catppuccin +++ b/themes/catppuccin @@ -4,7 +4,6 @@ color=1A1826 D9E0EE [colors] -alpha=1.0 foreground=D9E0EE background=1E1D2F regular0=6E6C7E # black diff --git a/themes/deus b/themes/deus index 5f863b76..d9cd82af 100644 --- a/themes/deus +++ b/themes/deus @@ -5,7 +5,6 @@ color=2c323b eaeaea [colors] -alpha=1.0 background=2c323b foreground=eaeaea regular0=242a32 @@ -24,9 +23,8 @@ bright4=73ba9f bright5=c858e9 bright6=2bcec2 bright7=ffffff - -## Enable if prefer Deus colors instead of inverterd fg/bg for -## highlighting (mouse selection) + +# Enable if prefer Deus colors instead of inverterd fg/bg for +# highlighting (mouse selection) # selection-foreground=2c323b # selection-background=eaeaea - diff --git a/themes/dracula b/themes/dracula index cd60e2e6..e116a694 100644 --- a/themes/dracula +++ b/themes/dracula @@ -4,7 +4,6 @@ color=282a36 f8f8f2 [colors] -alpha=1.0 foreground=f8f8f2 background=282a36 regular0=000000 # black diff --git a/themes/jetbrains-darcula b/themes/jetbrains-darcula index a4c811c5..ef4f1ece 100644 --- a/themes/jetbrains-darcula +++ b/themes/jetbrains-darcula @@ -5,7 +5,6 @@ color=202020 ffffff [colors] -#alpha=0.80 background=202020 foreground=adadad regular0=000000 # black diff --git a/themes/modus-operandi b/themes/modus-operandi index ca6c9493..12d884d8 100644 --- a/themes/modus-operandi +++ b/themes/modus-operandi @@ -3,7 +3,6 @@ # See: https://protesilaos.com/emacs/modus-themes # [colors] -alpha=1.0 background=ffffff foreground=000000 regular0=000000 diff --git a/themes/modus-vivendi b/themes/modus-vivendi index a95bcec0..b8176c8e 100644 --- a/themes/modus-vivendi +++ b/themes/modus-vivendi @@ -4,7 +4,6 @@ # [colors] -alpha=1.0 background=000000 foreground=ffffff regular0=000000 diff --git a/themes/paper-color-dark b/themes/paper-color-dark index 17d569ac..7cb1f903 100644 --- a/themes/paper-color-dark +++ b/themes/paper-color-dark @@ -2,27 +2,26 @@ # Palette based on https://github.com/NLKNguyen/papercolor-theme [cursor] - color=1c1c1c eeeeee +color=1c1c1c eeeeee [colors] - alpha=0.80 - background=1c1c1c - foreground=eeeeee - regular0=1c1c1c # black - regular1=af005f # red - regular2=5faf00 # green - regular3=d7af5f # yellow - regular4=5fafd7 # blue - regular5=808080 # magenta - regular6=d7875f # cyan - regular7=d0d0d0 # white - bright0=bcbcbc # bright black - bright1=5faf5f # bright red - bright2=afd700 # bright green - bright3=af87d7 # bright yellow - bright4=ffaf00 # bright blue - bright5=ff5faf # bright magenta - bright6=00afaf # bright cyan - bright7=5f8787 # bright white - #selection-foreground=1c1c1c - #selection-background=af87d7 +background=1c1c1c +foreground=eeeeee +regular0=1c1c1c # black +regular1=af005f # red +regular2=5faf00 # green +regular3=d7af5f # yellow +regular4=5fafd7 # blue +regular5=808080 # magenta +regular6=d7875f # cyan +regular7=d0d0d0 # white +bright0=bcbcbc # bright black +bright1=5faf5f # bright red +bright2=afd700 # bright green +bright3=af87d7 # bright yellow +bright4=ffaf00 # bright blue +bright5=ff5faf # bright magenta +bright6=00afaf # bright cyan +bright7=5f8787 # bright white +# selection-foreground=1c1c1c +# selection-background=af87d7 diff --git a/themes/paper-color-light b/themes/paper-color-light index 6e9f59f6..714ff022 100644 --- a/themes/paper-color-light +++ b/themes/paper-color-light @@ -2,27 +2,26 @@ # Palette based on https://github.com/NLKNguyen/papercolor-theme [cursor] - color=eeeeee 444444 +color=eeeeee 444444 [colors] - alpha=1.0 - background=eeeeee - foreground=444444 - regular0=eeeeee # black - regular1=af0000 # red - regular2=008700 # green - regular3=5f8700 # yellow - regular4=0087af # blue - regular5=878787 # magenta - regular6=005f87 # cyan - regular7=764e37 # white - bright0=bcbcbc # bright black - bright1=d70000 # bright red - bright2=d70087 # bright green - bright3=8700af # bright yellow - bright4=d75f00 # bright blue - bright5=d75f00 # bright magenta - bright6=4c7a5d # bright cyan - bright7=005faf # bright white - #selection-foreground=eeeeee - #selection-background=0087af +background=eeeeee +foreground=444444 +regular0=eeeeee # black +regular1=af0000 # red +regular2=008700 # green +regular3=5f8700 # yellow +regular4=0087af # blue +regular5=878787 # magenta +regular6=005f87 # cyan +regular7=764e37 # white +bright0=bcbcbc # bright black +bright1=d70000 # bright red +bright2=d70087 # bright green +bright3=8700af # bright yellow +bright4=d75f00 # bright blue +bright5=d75f00 # bright magenta +bright6=4c7a5d # bright cyan +bright7=005faf # bright white +# selection-foreground=eeeeee +# selection-background=0087af From 135d4478a156ce2264afd0ee5203510132986381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Dec 2022 10:59:37 +0100 Subject: [PATCH 068/118] =?UTF-8?q?themes:=20add=20=E2=80=98conf=E2=80=99?= =?UTF-8?q?=20modeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- themes/apprentice | 1 + themes/catppuccin | 1 + themes/derp | 1 + themes/deus | 1 + themes/dracula | 1 + themes/gruvbox-dark | 1 + themes/gruvbox-light | 1 + themes/hacktober | 1 + themes/jetbrains-darcula | 1 + themes/kitty | 2 ++ themes/material-design | 1 + themes/modus-operandi | 1 + themes/modus-vivendi | 1 + themes/monokai-pro | 1 + themes/moonfly | 1 + themes/nightfly | 1 + themes/nord | 1 + themes/nordiq | 1 + themes/paper-color-dark | 1 + themes/paper-color-light | 1 + themes/rezza | 1 + themes/selenized-black | 1 + themes/selenized-dark | 1 + themes/selenized-light | 1 + themes/selenized-white | 1 + themes/solarized-dark | 1 + themes/solarized-dark-normal-brights | 1 + themes/solarized-light | 1 + themes/tango | 1 + themes/tempus-autumn | 1 + themes/tempus-classic | 1 + themes/tempus-dawn | 1 + themes/tempus-day | 1 + themes/tempus-dusk | 1 + themes/tempus-fugit | 1 + themes/tempus-future | 1 + themes/tempus-night | 1 + themes/tempus-past | 1 + themes/tempus-rift | 1 + themes/tempus-spring | 1 + themes/tempus-summer | 1 + themes/tempus-tempest | 1 + themes/tempus-totus | 1 + themes/tempus-warp | 1 + themes/tempus-winter | 1 + themes/tokyonight-day | 2 ++ themes/tokyonight-night | 2 ++ themes/tokyonight-storm | 2 ++ themes/visibone | 1 + themes/zenburn | 2 ++ 50 files changed, 55 insertions(+) diff --git a/themes/apprentice b/themes/apprentice index 06d26315..941a27b4 100644 --- a/themes/apprentice +++ b/themes/apprentice @@ -1,3 +1,4 @@ +# -*- conf -*- # https://github.com/romainl/Apprentice [cursor] diff --git a/themes/catppuccin b/themes/catppuccin index 9e46aeed..4ccfabec 100644 --- a/themes/catppuccin +++ b/themes/catppuccin @@ -1,3 +1,4 @@ +# -*- conf -*- # Catppuccin [cursor] diff --git a/themes/derp b/themes/derp index 1d1afcd5..0925d2c2 100644 --- a/themes/derp +++ b/themes/derp @@ -1,3 +1,4 @@ +# -*- conf -*- # Derp [cursor] diff --git a/themes/deus b/themes/deus index d9cd82af..8fb37f75 100644 --- a/themes/deus +++ b/themes/deus @@ -1,3 +1,4 @@ +# -*- conf -*- # Deus # Color palette based on: https://github.com/ajmwagar/vim-deus diff --git a/themes/dracula b/themes/dracula index e116a694..8b6ab542 100644 --- a/themes/dracula +++ b/themes/dracula @@ -1,3 +1,4 @@ +# -*- conf -*- # Dracula [cursor] diff --git a/themes/gruvbox-dark b/themes/gruvbox-dark index 1716647d..73207199 100644 --- a/themes/gruvbox-dark +++ b/themes/gruvbox-dark @@ -1,3 +1,4 @@ +# -*- conf -*- # Gruvbox [colors] diff --git a/themes/gruvbox-light b/themes/gruvbox-light index a0788d0c..6a7a2416 100644 --- a/themes/gruvbox-light +++ b/themes/gruvbox-light @@ -1,3 +1,4 @@ +# -*- conf -*- # Gruvbox - Light [colors] diff --git a/themes/hacktober b/themes/hacktober index 4c7c6233..acb6c0b1 100644 --- a/themes/hacktober +++ b/themes/hacktober @@ -1,3 +1,4 @@ +# -*- conf -*- [cursor] color=141414 c9c9c9 diff --git a/themes/jetbrains-darcula b/themes/jetbrains-darcula index ef4f1ece..306b1e9d 100644 --- a/themes/jetbrains-darcula +++ b/themes/jetbrains-darcula @@ -1,3 +1,4 @@ +# -*- conf -*- # JetBrains Darcula # Palette based on the same theme from https://github.com/dexpota/kitty-themes diff --git a/themes/kitty b/themes/kitty index 670a4559..b5b813cc 100644 --- a/themes/kitty +++ b/themes/kitty @@ -1,3 +1,5 @@ +# -*- conf -*- + [cursor] color=111111 cccccc diff --git a/themes/material-design b/themes/material-design index 4b017391..6d81e339 100644 --- a/themes/material-design +++ b/themes/material-design @@ -1,3 +1,4 @@ +# -*- conf -*- # Material # From https://github.com/MartinSeeler/iterm2-material-design diff --git a/themes/modus-operandi b/themes/modus-operandi index 12d884d8..5e3a9fd6 100644 --- a/themes/modus-operandi +++ b/themes/modus-operandi @@ -1,3 +1,4 @@ +# -*- conf -*- # # modus-operandi # See: https://protesilaos.com/emacs/modus-themes diff --git a/themes/modus-vivendi b/themes/modus-vivendi index b8176c8e..82b1075d 100644 --- a/themes/modus-vivendi +++ b/themes/modus-vivendi @@ -1,3 +1,4 @@ +# -*- conf -*- # # modus-vivendi # See: https://protesilaos.com/emacs/modus-themes diff --git a/themes/monokai-pro b/themes/monokai-pro index eecdd3f7..5d9f31a9 100644 --- a/themes/monokai-pro +++ b/themes/monokai-pro @@ -1,3 +1,4 @@ +# -*- conf -*- # Monokai Pro [colors] diff --git a/themes/moonfly b/themes/moonfly index 54d9203b..c622ab45 100644 --- a/themes/moonfly +++ b/themes/moonfly @@ -1,3 +1,4 @@ +# -*- conf -*- # moonfly # Based on https://github.com/bluz71/vim-moonfly-colors diff --git a/themes/nightfly b/themes/nightfly index 3815b42e..50f95125 100644 --- a/themes/nightfly +++ b/themes/nightfly @@ -1,3 +1,4 @@ +# -*- conf -*- # nightfly # Based on https://github.com/bluz71/vim-nightfly-guicolors diff --git a/themes/nord b/themes/nord index 4f6d8c2b..af09f727 100644 --- a/themes/nord +++ b/themes/nord @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Nord # author: Arctic Ice Studio , Sven Greb # description: „Nord“ — An arctic, north-bluish color palette diff --git a/themes/nordiq b/themes/nordiq index df45e80a..f309de23 100644 --- a/themes/nordiq +++ b/themes/nordiq @@ -1,3 +1,4 @@ +# -*- conf -*- # Nordiq [cursor] diff --git a/themes/paper-color-dark b/themes/paper-color-dark index 7cb1f903..18cd7f17 100644 --- a/themes/paper-color-dark +++ b/themes/paper-color-dark @@ -1,3 +1,4 @@ +# -*- conf -*- # PaperColorDark # Palette based on https://github.com/NLKNguyen/papercolor-theme diff --git a/themes/paper-color-light b/themes/paper-color-light index 714ff022..b08ea707 100644 --- a/themes/paper-color-light +++ b/themes/paper-color-light @@ -1,3 +1,4 @@ +# -*- conf -*- # PaperColor Light # Palette based on https://github.com/NLKNguyen/papercolor-theme diff --git a/themes/rezza b/themes/rezza index b9ef4a1f..56814a77 100644 --- a/themes/rezza +++ b/themes/rezza @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: rezza # author: Doug Whiteley (rezza) # original URL: http://metawire.org/~rezza/index.php diff --git a/themes/selenized-black b/themes/selenized-black index a75891f9..28392add 100644 --- a/themes/selenized-black +++ b/themes/selenized-black @@ -1,3 +1,4 @@ +# -*- conf -*- # Selenized black [cursor] diff --git a/themes/selenized-dark b/themes/selenized-dark index e3a7b7b4..ed74cdfc 100644 --- a/themes/selenized-dark +++ b/themes/selenized-dark @@ -1,3 +1,4 @@ +# -*- conf -*- # Selenized dark [cursor] diff --git a/themes/selenized-light b/themes/selenized-light index 5f2b7c08..7e599d8e 100644 --- a/themes/selenized-light +++ b/themes/selenized-light @@ -1,3 +1,4 @@ +# -*- conf -*- # Selenized light [cursor] diff --git a/themes/selenized-white b/themes/selenized-white index 492c01f6..b4d25315 100644 --- a/themes/selenized-white +++ b/themes/selenized-white @@ -1,3 +1,4 @@ +# -*- conf -*- # Selenized white [cursor] diff --git a/themes/solarized-dark b/themes/solarized-dark index 0d0a233f..e2395bdc 100644 --- a/themes/solarized-dark +++ b/themes/solarized-dark @@ -1,3 +1,4 @@ +# -*- conf -*- # Solarized dark [cursor] diff --git a/themes/solarized-dark-normal-brights b/themes/solarized-dark-normal-brights index 484e5dc2..405a6e49 100644 --- a/themes/solarized-dark-normal-brights +++ b/themes/solarized-dark-normal-brights @@ -1,3 +1,4 @@ +# -*- conf -*- # Solarized dark [cursor] diff --git a/themes/solarized-light b/themes/solarized-light index fb4b762a..74474573 100644 --- a/themes/solarized-light +++ b/themes/solarized-light @@ -1,3 +1,4 @@ +# -*- conf -*- # Solarized light [cursor] diff --git a/themes/tango b/themes/tango index 3b5c93c4..a326f8ad 100644 --- a/themes/tango +++ b/themes/tango @@ -1,3 +1,4 @@ +# -*- conf -*- # Tango [cursor] diff --git a/themes/tempus-autumn b/themes/tempus-autumn index 9fafb5a2..3f706d0e 100644 --- a/themes/tempus-autumn +++ b/themes/tempus-autumn @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Autumn # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with a palette inspired by earthly colours (WCAG AA compliant) diff --git a/themes/tempus-classic b/themes/tempus-classic index af86b024..66fb886a 100644 --- a/themes/tempus-classic +++ b/themes/tempus-classic @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Classic # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with warm hues (WCAG AA compliant) diff --git a/themes/tempus-dawn b/themes/tempus-dawn index ef599373..fa368b13 100644 --- a/themes/tempus-dawn +++ b/themes/tempus-dawn @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Dawn # author: Protesilaos Stavrou (https://protesilaos.com) # description: Light theme with a soft, slightly desaturated palette (WCAG AA compliant) diff --git a/themes/tempus-day b/themes/tempus-day index 2e4cfdc9..6002a8e2 100644 --- a/themes/tempus-day +++ b/themes/tempus-day @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Day # author: Protesilaos Stavrou (https://protesilaos.com) # description: Light theme with warm colours (WCAG AA compliant) diff --git a/themes/tempus-dusk b/themes/tempus-dusk index 07907efc..e9f94725 100644 --- a/themes/tempus-dusk +++ b/themes/tempus-dusk @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Dusk # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with a deep blue-ish, slightly desaturated palette (WCAG AA compliant) diff --git a/themes/tempus-fugit b/themes/tempus-fugit index 37484f4c..1a6ae9e7 100644 --- a/themes/tempus-fugit +++ b/themes/tempus-fugit @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Fugit # author: Protesilaos Stavrou (https://protesilaos.com) # description: Light, pleasant theme optimised for long writing/coding sessions (WCAG AA compliant) diff --git a/themes/tempus-future b/themes/tempus-future index 462e53dc..c0cdaad9 100644 --- a/themes/tempus-future +++ b/themes/tempus-future @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Future # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with colours inspired by concept art of outer space (WCAG AAA compliant) diff --git a/themes/tempus-night b/themes/tempus-night index 72e46bce..a431fbc6 100644 --- a/themes/tempus-night +++ b/themes/tempus-night @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Night # author: Protesilaos Stavrou (https://protesilaos.com) # description: High contrast dark theme with bright colours (WCAG AAA compliant) diff --git a/themes/tempus-past b/themes/tempus-past index 5dcee1c2..8f8ddcb1 100644 --- a/themes/tempus-past +++ b/themes/tempus-past @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Past # author: Protesilaos Stavrou (https://protesilaos.com) # description: Light theme inspired by old vaporwave concept art (WCAG AA compliant) diff --git a/themes/tempus-rift b/themes/tempus-rift index b60409e7..6d1ed3a2 100644 --- a/themes/tempus-rift +++ b/themes/tempus-rift @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Rift # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with a subdued palette on the green side of the spectrum (WCAG AA compliant) diff --git a/themes/tempus-spring b/themes/tempus-spring index dcee15f7..207434e9 100644 --- a/themes/tempus-spring +++ b/themes/tempus-spring @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Spring # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with a palette inspired by early spring colours (WCAG AA compliant) diff --git a/themes/tempus-summer b/themes/tempus-summer index 3662c04a..3a852e46 100644 --- a/themes/tempus-summer +++ b/themes/tempus-summer @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Summer # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with colours inspired by summer evenings by the sea (WCAG AA compliant) diff --git a/themes/tempus-tempest b/themes/tempus-tempest index aab3c44e..15b3d881 100644 --- a/themes/tempus-tempest +++ b/themes/tempus-tempest @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Tempest # author: Protesilaos Stavrou (https://protesilaos.com) # description: A green-scale, subtle theme for late night hackers (WCAG AAA compliant) diff --git a/themes/tempus-totus b/themes/tempus-totus index 2673a70c..5ccac91d 100644 --- a/themes/tempus-totus +++ b/themes/tempus-totus @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Totus # author: Protesilaos Stavrou (https://protesilaos.com) # description: Light theme for prose or for coding in an open space (WCAG AAA compliant) diff --git a/themes/tempus-warp b/themes/tempus-warp index 48fd47bc..d4c7a94b 100644 --- a/themes/tempus-warp +++ b/themes/tempus-warp @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Warp # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with a vibrant palette (WCAG AA compliant) diff --git a/themes/tempus-winter b/themes/tempus-winter index 69c8b867..22cdd6d9 100644 --- a/themes/tempus-winter +++ b/themes/tempus-winter @@ -1,3 +1,4 @@ +# -*- conf -*- # theme: Tempus Winter # author: Protesilaos Stavrou (https://protesilaos.com) # description: Dark theme with a palette inspired by winter nights at the city (WCAG AA compliant) diff --git a/themes/tokyonight-day b/themes/tokyonight-day index 744ef351..5143aa07 100644 --- a/themes/tokyonight-day +++ b/themes/tokyonight-day @@ -1,3 +1,5 @@ +# -*- conf -*- + [colors] background=e1e2e7 foreground=3760bf diff --git a/themes/tokyonight-night b/themes/tokyonight-night index e48d7cd6..f789e1bd 100644 --- a/themes/tokyonight-night +++ b/themes/tokyonight-night @@ -1,3 +1,5 @@ +# -*- conf -*- + [colors] background=1a1b26 foreground=c0caf5 diff --git a/themes/tokyonight-storm b/themes/tokyonight-storm index 96b90eb8..074b4697 100644 --- a/themes/tokyonight-storm +++ b/themes/tokyonight-storm @@ -1,3 +1,5 @@ +# -*- conf -*- + [colors] background=24283b foreground=c0caf5 diff --git a/themes/visibone b/themes/visibone index a27c815f..3ee665d0 100644 --- a/themes/visibone +++ b/themes/visibone @@ -1,3 +1,4 @@ +# -*- conf -*- # VisiBone [cursor] diff --git a/themes/zenburn b/themes/zenburn index 3867826f..bace080c 100644 --- a/themes/zenburn +++ b/themes/zenburn @@ -1,3 +1,5 @@ +# -*- conf -*- + [colors] foreground=dcdccc background=111111 From 9e4270cd482398361061423de13d7412eecb9f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Dec 2022 11:03:17 +0100 Subject: [PATCH 069/118] themes: comment out selection-{foreground,background} That is, mouse selections should default to inverse fg/bg --- themes/jetbrains-darcula | 4 ++-- themes/material-design | 4 ++-- themes/moonfly | 5 +++-- themes/nightfly | 5 +++-- themes/nord | 5 +++-- themes/solarized-dark | 4 ++-- themes/solarized-dark-normal-brights | 4 ++-- themes/tempus-autumn | 4 ++-- themes/tempus-classic | 4 ++-- themes/tempus-dawn | 4 ++-- themes/tempus-day | 4 ++-- themes/tempus-dusk | 4 ++-- themes/tempus-fugit | 4 ++-- themes/tempus-future | 4 ++-- themes/tempus-night | 4 ++-- themes/tempus-past | 4 ++-- themes/tempus-rift | 4 ++-- themes/tempus-spring | 4 ++-- themes/tempus-summer | 4 ++-- themes/tempus-tempest | 4 ++-- themes/tempus-totus | 4 ++-- themes/tempus-warp | 4 ++-- themes/tempus-winter | 4 ++-- 23 files changed, 49 insertions(+), 46 deletions(-) diff --git a/themes/jetbrains-darcula b/themes/jetbrains-darcula index 306b1e9d..82528498 100644 --- a/themes/jetbrains-darcula +++ b/themes/jetbrains-darcula @@ -24,5 +24,5 @@ bright4=6d9df1 # bright blue bright5=fb82ff # bright magenta bright6=60d3d1 # bright cyan bright7=eeeeee # bright white -selection-foreground=202020 -selection-background=1a3272 +# selection-foreground=202020 +# selection-background=1a3272 diff --git a/themes/material-design b/themes/material-design index 6d81e339..4a9e008a 100644 --- a/themes/material-design +++ b/themes/material-design @@ -5,8 +5,6 @@ [colors] foreground=ECEFF1 background=263238 -selection-foreground=ECEFF1 -selection-background=607D8B regular0=546E7A # black regular1=FF5252 # red regular2=5CF19E # green @@ -23,3 +21,5 @@ bright4=80D8FF # bright blue bright5=FF80AB # bright magenta bright6=A7FDEB # bright cyan bright7=FFFFFF # bright white +# selection-foreground=ECEFF1 +# selection-background=607D8B diff --git a/themes/moonfly b/themes/moonfly index c622ab45..870de9d0 100644 --- a/themes/moonfly +++ b/themes/moonfly @@ -8,8 +8,9 @@ color = 080808 9e9e9e [colors] foreground = b2b2b2 background = 080808 -selection-foreground = 080808 -selection-background = b2ceee + +# selection-foreground = 080808 +# selection-background = b2ceee regular0 = 323437 regular1 = ff5454 diff --git a/themes/nightfly b/themes/nightfly index 50f95125..2a27fb2d 100644 --- a/themes/nightfly +++ b/themes/nightfly @@ -8,8 +8,9 @@ color = 080808 9ca1aa [colors] foreground = acb4c2 background = 011627 -selection-foreground = 080808 -selection-background = b2ceee + +# selection-foreground = 080808 +# selection-background = b2ceee regular0 = 1d3b53 regular1 = fc514e diff --git a/themes/nord b/themes/nord index af09f727..4ce3a53e 100644 --- a/themes/nord +++ b/themes/nord @@ -12,8 +12,9 @@ color = 2e3440 d8dee9 [colors] foreground = d8dee9 background = 2e3440 -#selection-foreground = d8dee9 -#selection-background = 4c566a + +# selection-foreground = d8dee9 +# selection-background = 4c566a regular0 = 3b4252 regular1 = bf616a diff --git a/themes/solarized-dark b/themes/solarized-dark index e2395bdc..cad2945e 100644 --- a/themes/solarized-dark +++ b/themes/solarized-dark @@ -24,7 +24,7 @@ bright5= 6c71c4 bright6= 93a1a1 bright7= fdf6e3 -## Enable if prefer solarized colors instead of inverterd fg/bg for -## highlighting (mouse selection) +# Enable if prefer solarized colors instead of inverterd fg/bg for +# highlighting (mouse selection) # selection-foreground=93a1a1 # selection-background=073642 diff --git a/themes/solarized-dark-normal-brights b/themes/solarized-dark-normal-brights index 405a6e49..1ab7d375 100644 --- a/themes/solarized-dark-normal-brights +++ b/themes/solarized-dark-normal-brights @@ -26,7 +26,7 @@ bright5= dc619d bright6= 32c1b6 bright7= ffffff -## Enable if prefer solarized colors instead of inverterd fg/bg for -## highlighting (mouse selection) +# Enable if prefer solarized colors instead of inverterd fg/bg for +# highlighting (mouse selection) # selection-foreground=93a1a1 # selection-background=073642 diff --git a/themes/tempus-autumn b/themes/tempus-autumn index 3f706d0e..9c1f8797 100644 --- a/themes/tempus-autumn +++ b/themes/tempus-autumn @@ -25,5 +25,5 @@ bright4 = 958fdf bright5 = ce7dc4 bright6 = 2fa6b7 bright7 = a9a2a6 -#selection-foreground = a8948a -#selection-background = 36302a +# selection-foreground = a8948a +# selection-background = 36302a diff --git a/themes/tempus-classic b/themes/tempus-classic index 66fb886a..0164605b 100644 --- a/themes/tempus-classic +++ b/themes/tempus-classic @@ -25,5 +25,5 @@ bright4 = 8e9cc0 bright5 = d58888 bright6 = 7aa880 bright7 = aeadaf -#selection-foreground = 949d9f -#selection-background = 312e30 +# selection-foreground = 949d9f +# selection-background = 312e30 diff --git a/themes/tempus-dawn b/themes/tempus-dawn index fa368b13..cf143fba 100644 --- a/themes/tempus-dawn +++ b/themes/tempus-dawn @@ -25,5 +25,5 @@ bright4 = 5c59b2 bright5 = 8e45a8 bright6 = 3f649c bright7 = eff0f2 -#selection-foreground = 676364 -#selection-background = dee2e0 +# selection-foreground = 676364 +# selection-background = dee2e0 diff --git a/themes/tempus-day b/themes/tempus-day index 6002a8e2..b287d45c 100644 --- a/themes/tempus-day +++ b/themes/tempus-day @@ -25,5 +25,5 @@ bright4 = 0f64c4 bright5 = 8050a7 bright6 = 336c87 bright7 = f8f2e5 -#selection-foreground = 68607d -#selection-background = e7e3d7 +# selection-foreground = 68607d +# selection-background = e7e3d7 diff --git a/themes/tempus-dusk b/themes/tempus-dusk index e9f94725..2c0308e1 100644 --- a/themes/tempus-dusk +++ b/themes/tempus-dusk @@ -25,5 +25,5 @@ bright4 = 9ca5de bright5 = c69ac6 bright6 = 8caeb6 bright7 = a2a8ba -#selection-foreground = a29899 -#selection-background = 2c3150 +# selection-foreground = a29899 +# selection-background = 2c3150 diff --git a/themes/tempus-fugit b/themes/tempus-fugit index 1a6ae9e7..9ebbcee7 100644 --- a/themes/tempus-fugit +++ b/themes/tempus-fugit @@ -25,5 +25,5 @@ bright4 = 485adf bright5 = a234c0 bright6 = 00756a bright7 = fff5f3 -#selection-foreground = 796271 -#selection-background = efe6e4 +# selection-foreground = 796271 +# selection-background = efe6e4 diff --git a/themes/tempus-future b/themes/tempus-future index c0cdaad9..3dd8c7a6 100644 --- a/themes/tempus-future +++ b/themes/tempus-future @@ -25,5 +25,5 @@ bright4 = 8ba7ea bright5 = e08bd6 bright6 = 2cbab6 bright7 = b4abac -#selection-foreground = a7a2c4 -#selection-background = 2b1329 +# selection-foreground = a7a2c4 +# selection-background = 2b1329 diff --git a/themes/tempus-night b/themes/tempus-night index a431fbc6..de7be5ff 100644 --- a/themes/tempus-night +++ b/themes/tempus-night @@ -25,5 +25,5 @@ bright4 = 8cb4f0 bright5 = de99f0 bright6 = 00ca9a bright7 = e0e0e0 -#selection-foreground = c4bdaf -#selection-background = 242536 +# selection-foreground = c4bdaf +# selection-background = 242536 diff --git a/themes/tempus-past b/themes/tempus-past index 8f8ddcb1..8c66f54d 100644 --- a/themes/tempus-past +++ b/themes/tempus-past @@ -25,5 +25,5 @@ bright4 = 5559bb bright5 = b022a7 bright6 = 07707a bright7 = f3f2f4 -#selection-foreground = 80565d -#selection-background = eae2de +# selection-foreground = 80565d +# selection-background = eae2de diff --git a/themes/tempus-rift b/themes/tempus-rift index 6d1ed3a2..3657a7fe 100644 --- a/themes/tempus-rift +++ b/themes/tempus-rift @@ -25,5 +25,5 @@ bright4 = 56bdad bright5 = cca0ba bright6 = 10c480 bright7 = bbbcbc -#selection-foreground = ab9aa9 -#selection-background = 283431 +# selection-foreground = ab9aa9 +# selection-background = 283431 diff --git a/themes/tempus-spring b/themes/tempus-spring index 207434e9..d50e6d06 100644 --- a/themes/tempus-spring +++ b/themes/tempus-spring @@ -25,5 +25,5 @@ bright4 = 70afef bright5 = d095e2 bright6 = 3cbfaf bright7 = b5b8b7 -#selection-foreground = 99afae -#selection-background = 2a453d +# selection-foreground = 99afae +# selection-background = 2a453d diff --git a/themes/tempus-summer b/themes/tempus-summer index 3a852e46..7da1d8c4 100644 --- a/themes/tempus-summer +++ b/themes/tempus-summer @@ -25,5 +25,5 @@ bright4 = 8599ef bright5 = cc82d7 bright6 = 2aacbf bright7 = a0abae -#selection-foreground = 949cbf -#selection-background = 39304f +# selection-foreground = 949cbf +# selection-background = 39304f diff --git a/themes/tempus-tempest b/themes/tempus-tempest index 15b3d881..57c300aa 100644 --- a/themes/tempus-tempest +++ b/themes/tempus-tempest @@ -25,5 +25,5 @@ bright4 = 74e4cd bright5 = d2d4aa bright6 = 9bdfc4 bright7 = b6e0ca -#selection-foreground = b0c8ca -#selection-background = 323535 +# selection-foreground = b0c8ca +# selection-background = 323535 diff --git a/themes/tempus-totus b/themes/tempus-totus index 5ccac91d..01e84692 100644 --- a/themes/tempus-totus +++ b/themes/tempus-totus @@ -25,5 +25,5 @@ bright4 = 2d45b0 bright5 = 700dc9 bright6 = 005289 bright7 = ffffff -#selection-foreground = 5e4b4f -#selection-background = efefef +# selection-foreground = 5e4b4f +# selection-background = efefef diff --git a/themes/tempus-warp b/themes/tempus-warp index d4c7a94b..fa8c21c2 100644 --- a/themes/tempus-warp +++ b/themes/tempus-warp @@ -25,5 +25,5 @@ bright4 = 8887f0 bright5 = d85cf2 bright6 = 1da1af bright7 = a29fa0 -#selection-foreground = 968282 -#selection-background = 261c2c +# selection-foreground = 968282 +# selection-background = 261c2c diff --git a/themes/tempus-winter b/themes/tempus-winter index 22cdd6d9..8db97057 100644 --- a/themes/tempus-winter +++ b/themes/tempus-winter @@ -25,5 +25,5 @@ bright4 = 329fcb bright5 = ca77c5 bright6 = 1ba6a4 bright7 = 8da3b8 -#selection-foreground = 91959b -#selection-background = 2a2e38 +# selection-foreground = 91959b +# selection-background = 2a2e38 From 6259d59b4d82b0e8b7705759e04262130a3426c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 16 Dec 2022 16:56:43 +0100 Subject: [PATCH 070/118] config: change default grapheme-width-method from wcswidth to double-width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old default, wcswidth, simply calls wcswidth() on the grapheme cluster. This was supposedly the implementation with the highest application compatibility. Except we never even tried to measure it. It was just assumed. A lot of modern applications have better implementations. Let’s try to push support for better emoji support by changing our default method from wcswith to double-width. While far from correct (it’s not based on the Unicode tables), the ‘double-width’ method produces accurate results anyway. double-width is like wcswidth(), in that it adds together the individual wcwidths of all codepoints in the grapheme cluster. But, it limits the maximum width to 2. --- CHANGELOG.md | 1 + config.c | 2 +- doc/foot.ini.5.scd | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9538ccca..4aadd7bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ * Set `PWD` environment variable in the slave process ([#1179][1179]). * DPI is now forced to 96 when found to be unreasonably high. * Set default log level to warning ([#1215][1215]). +* Default `grapheme-width-method` from `wcswidth` to `double-width`. [1166]: https://codeberg.org/dnkl/foot/issues/1166 [1179]: https://codeberg.org/dnkl/foot/issues/1179 diff --git a/config.c b/config.c index 7d849d5c..ea8d062f 100644 --- a/config.c +++ b/config.c @@ -3003,7 +3003,7 @@ config_load(struct config *conf, const char *conf_path, #if defined(FOOT_GRAPHEME_CLUSTERING) && FOOT_GRAPHEME_CLUSTERING .grapheme_shaping = fcft_caps & FCFT_CAPABILITY_GRAPHEME_SHAPING, #endif - .grapheme_width_method = GRAPHEME_WIDTH_WCSWIDTH, + .grapheme_width_method = GRAPHEME_WIDTH_DOUBLE, .delayed_render_lower_ns = 500000, /* 0.5ms */ .delayed_render_upper_ns = 16666666 / 2, /* half a frame period (60Hz) */ .max_shm_pool_size = 512 * 1024 * 1024, diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 6443d2ba..6cdb7db8 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -1256,7 +1256,7 @@ any of these options. *max* uses the width of the largest codepoint in the cluster. - Default: _wcswidth_ + Default: _double-width_ *font-monospace-warn* Boolean. When enabled, foot will use heuristics to try to verify From e7c1a93d29f6e6d3962d8444834a8b90f367170d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 1 Jan 2023 10:22:54 +0100 Subject: [PATCH 071/118] terminfo: add entries for bracketed paste Ncurses added these in 2022-12-24, but they have been used/supported by vim since 2017. * BE - Bracketed paste Enable * BD - Bracketed paste Disable * PE - Paste Enable (i.e. "begin") * PD - Paste Disable (i.e. "end") --- CHANGELOG.md | 2 ++ foot.info | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aadd7bc..f10f2b75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,8 @@ * `font-size-adjustment=N[px]` option, letting you configure how much to increment/decrement the font size when zooming in or out ([#1188][1188]). +* Bracketed paste terminfo entries (`BD`, `BE`, `PD` and `PE`, added + to ncurses in 2022-12-24). Vim makes use of these. [1136]: https://codeberg.org/dnkl/foot/issues/1136 [1225]: https://codeberg.org/dnkl/foot/issues/1225 diff --git a/foot.info b/foot.info index f4030b22..33769278 100644 --- a/foot.info +++ b/foot.info @@ -28,10 +28,14 @@ it#8, lines#24, pairs#0x10000, + BD=\E[?2004l, + BE=\E[?2004h, Cr=\E]112\E\\, Cs=\E]12;%p1%s\E\\, E3=\E[3J, Ms=\E]52;%p1%s;%p2%s\E\\, + PD=\E[201~, + PE=\E[200~, Se=\E[ q, Ss=\E[%p1%d q, Sync=\E[?2026%?%p1%{1}%-%tl%eh, From 88641005fef7cc72db898ca4baccbca789d09f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 1 Jan 2023 15:21:05 +0100 Subject: [PATCH 072/118] terminfo: PD/PE -> PE/PS Ncurses 2022-12-24 had the names wrong. It was corrected on 2022-12-29. --- foot.info | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/foot.info b/foot.info index 33769278..271a00f5 100644 --- a/foot.info +++ b/foot.info @@ -34,8 +34,8 @@ Cs=\E]12;%p1%s\E\\, E3=\E[3J, Ms=\E]52;%p1%s;%p2%s\E\\, - PD=\E[201~, - PE=\E[200~, + PE=\E[201~, + PS=\E[200~, Se=\E[ q, Ss=\E[%p1%d q, Sync=\E[?2026%?%p1%{1}%-%tl%eh, From 1d3023ec5e3a996ab3b0b031292e0fb101ce5900 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Sun, 1 Jan 2023 15:21:17 +0000 Subject: [PATCH 073/118] changelog: amend terminfo names, in accordance with previous commit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f10f2b75..ac18a97e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,7 +56,7 @@ * `font-size-adjustment=N[px]` option, letting you configure how much to increment/decrement the font size when zooming in or out ([#1188][1188]). -* Bracketed paste terminfo entries (`BD`, `BE`, `PD` and `PE`, added +* Bracketed paste terminfo entries (`BD`, `BE`, `PE` and `PS`, added to ncurses in 2022-12-24). Vim makes use of these. [1136]: https://codeberg.org/dnkl/foot/issues/1136 From 63bef0dc8cf68e957eeb1f286d813b294c229ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 2 Jan 2023 13:52:49 +0100 Subject: [PATCH 074/118] ci: drop gitlab CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We’re no longer mirroring to gitlab. --- .gitlab-ci.yml | 112 ------------------------------------------------- 1 file changed, 112 deletions(-) delete mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 28df1ccb..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,112 +0,0 @@ -stages: - - build - -variables: - GIT_SUBMODULE_STRATEGY: normal - -before_script: - - apk update - - apk add musl-dev linux-headers meson ninja gcc scdoc ncurses - - apk add libxkbcommon-dev pixman-dev freetype-dev fontconfig-dev harfbuzz-dev utf8proc-dev - - apk add wayland-dev wayland-protocols - - apk add git - - apk add check-dev - - apk add ttf-hack font-noto-emoji - -debug-x64: - image: alpine:edge - stage: build - script: - - cd subprojects - - git clone https://codeberg.org/dnkl/fcft.git - - cd .. - - mkdir -p bld/debug - - cd bld/debug - - meson --buildtype=debug -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../../ - - ninja -v -k0 - - ninja -v test - artifacts: - reports: - junit: bld/debug/meson-logs/testlog.junit.xml - -debug-x64-no-grapheme-clustering: - image: alpine:edge - stage: build - script: - - apk del harfbuzz harfbuzz-dev utf8proc utf8proc-dev - - cd subprojects - - git clone https://codeberg.org/dnkl/fcft.git - - cd .. - - mkdir -p bld/debug - - cd bld/debug - - meson --buildtype=debug -Dgrapheme-clustering=disabled -Dfcft:grapheme-shaping=disabled -Dfcft:run-shaping=disabled -Dfcft:test-text-shaping=false ../../ - - ninja -v -k0 - - ninja -v test - - ./foot --version - - ./footclient --version - artifacts: - reports: - junit: bld/debug/meson-logs/testlog.junit.xml - -release-x64: - image: alpine:edge - stage: build - script: - - cd subprojects - - git clone https://codeberg.org/dnkl/fcft.git - - cd .. - - mkdir -p bld/release - - cd bld/release - - meson --buildtype=release -Db_pgo=generate -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../../ - - ninja -v -k0 - - ninja -v test - - ./foot --version - - ./footclient --version - artifacts: - reports: - junit: bld/release/meson-logs/testlog.junit.xml - -debug-x86: - image: i386/alpine:edge - stage: build - script: - - cd subprojects - - git clone https://codeberg.org/dnkl/fcft.git - - cd .. - - mkdir -p bld/debug - - cd bld/debug - - meson --buildtype=debug -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../../ - - ninja -v -k0 - - ninja -v test - - ./foot --version - - ./footclient --version - artifacts: - reports: - junit: bld/debug/meson-logs/testlog.junit.xml - -release-x86: - image: i386/alpine:edge - stage: build - script: - - cd subprojects - - git clone https://codeberg.org/dnkl/fcft.git - - cd .. - - mkdir -p bld/release - - cd bld/release - - meson --buildtype=release -Db_pgo=generate -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../../ - - ninja -v -k0 - - ninja -v test - - ./foot --version - - ./footclient --version - artifacts: - reports: - junit: bld/release/meson-logs/testlog.junit.xml - -codespell: - image: alpine:edge - stage: build - script: - - apk add python3 - - apk add py3-pip - - pip install codespell - - codespell -Lser,doas,zar README.md INSTALL.md CHANGELOG.md *.c *.h doc/*.scd From c9465e4c5c81c9bb33886441e266c843b9425752 Mon Sep 17 00:00:00 2001 From: woojiq Date: Wed, 4 Jan 2023 12:35:53 +0200 Subject: [PATCH 075/118] themes: add Onedark --- themes/onedark | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 themes/onedark diff --git a/themes/onedark b/themes/onedark new file mode 100644 index 00000000..d7f78a66 --- /dev/null +++ b/themes/onedark @@ -0,0 +1,27 @@ +# OneDark +# Pallete based on the same theme from https://github.com/dexpota/kitty-themes + +[cursor] +color=111111 cccccc + +[colors] +foreground=979eab +background=282c34 +regular0=282c34 # black +regular1=e06c75 # red +regular2=98c379 # green +regular3=e5c07b # yellow +regular4=61afef # blue +regular5=be5046 # magenta +regular6=56b6c2 # cyan +regular7=979eab # white +bright0=393e48 # bright black +bright1=d19a66 # bright red +bright2=56b6c2 # bright green +bright3=e5c07b # bright yellow +bright4=61afef # bright blue +bright5=be5046 # bright magenta +bright6=56b6c2 # bright cyan +bright7=abb2bf # bright white +# selection-foreground=282c34 +# selection-background=979eab From f19768e30406ad154ebdb7f75ce8a656a130db4c Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Fri, 6 Jan 2023 23:43:51 +0000 Subject: [PATCH 076/118] wayland: avoid passing NULL to log_msg() in wayl_reload_xcursor_theme() This pointer ends up being passed to various printf-family functions, where passing a NULL pointer for an "%s" format specifier invokes undefined behaviour. --- wayland.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wayland.c b/wayland.c index e48d59aa..55d45da7 100644 --- a/wayland.c +++ b/wayland.c @@ -1704,7 +1704,8 @@ wayl_reload_xcursor_theme(struct seat *seat, int new_scale) const char *xcursor_theme = getenv("XCURSOR_THEME"); LOG_INFO("cursor theme: %s, size: %d, scale: %d", - xcursor_theme, xcursor_size, new_scale); + xcursor_theme ? xcursor_theme : "(null)", + xcursor_size, new_scale); seat->pointer.theme = wl_cursor_theme_load( xcursor_theme, xcursor_size * new_scale, seat->wayl->shm); From a38b8d02227f13ce1da5125905a262e298875a0d Mon Sep 17 00:00:00 2001 From: Grigory Kirillov Date: Sun, 8 Jan 2023 00:55:01 +0300 Subject: [PATCH 077/118] doc: fix a typo --- 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 6cdb7db8..07a3cb94 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -576,7 +576,7 @@ can configure the background transparency with the _alpha_ option. options are unconfigured). 24-bit RGB colors will typically fall into this category. - Note that applications can change the *regularN* and *brighN* + Note that applications can change the *regularN* and *brightN* colors at runtime. However, they have no way of changing the *dimN* colors. If an application has changed the *regularN* colors, foot will still use the corresponding *dimN* color, as From 7d28da50066601807b6790bbd77e2d8785e46884 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Tue, 10 Jan 2023 18:34:25 +0000 Subject: [PATCH 078/118] Use "command -v" instead of "which" in bash completion scripts The former is a built-in command in bash, whereas the latter is an external command and isn't always necessarily available. --- completions/bash/foot | 4 ++-- completions/bash/footclient | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/completions/bash/foot b/completions/bash/foot index 1fdab062..b427bc58 100644 --- a/completions/bash/foot +++ b/completions/bash/foot @@ -61,11 +61,11 @@ _foot() compopt -o dirnames elif [[ ${prev} == '--term' ]] ; then # check if toe is available - which toe > /dev/null || return 1 + command -v toe > /dev/null || return 1 COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) elif [[ ${prev} == '--font' ]] ; then # check if fc-list is available - which fc-list > /dev/null || return 1 + command -v fc-list > /dev/null || return 1 COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) ) elif [[ ${prev} == '--log-level' ]] ; then COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) diff --git a/completions/bash/footclient b/completions/bash/footclient index b672c247..0381e8a0 100644 --- a/completions/bash/footclient +++ b/completions/bash/footclient @@ -57,7 +57,7 @@ _footclient() compopt -o dirnames elif [[ ${prev} == '--term' ]] ; then # check if toe is available - which toe > /dev/null || return 1 + command -v toe > /dev/null || return 1 COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) elif [[ ${prev} == '--log-level' ]] ; then COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) From 8acc10b9d4bc1d4c245475e1812093bf8c9e3d78 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Tue, 10 Jan 2023 19:44:24 +0000 Subject: [PATCH 079/118] completions: bash: use "case" instead of long if/elif/else chain --- completions/bash/foot | 52 ++++++++++++++++++++----------------- completions/bash/footclient | 45 ++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/completions/bash/foot b/completions/bash/foot index b427bc58..c1bb20fa 100644 --- a/completions/bash/foot +++ b/completions/bash/foot @@ -31,7 +31,7 @@ _foot() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} - # check if positional argument is completed + # Check if positional argument is completed previous_words=( "${COMP_WORDS[@]}" ) unset previous_words[-1] commands=$(compgen -c | grep -vFx "$(compgen -k)" | grep -vE '^([.:[]|foot)$' | sort -u) @@ -43,41 +43,45 @@ _foot() (( i++ )) continue fi - # positional argument found + # Positional argument found offset=$i fi (( i++ )) done if [[ ! -z "$offset" ]] ; then - # depends on bash_completion being available + # Depends on bash_completion being available declare -F _command_offset >/dev/null || return 1 _command_offset $offset + return 0 elif [[ ${cur} == --* ]] ; then COMPREPLY=( $(compgen -W "${flags}" -- ${cur}) ) - elif [[ ${prev} =~ ^(--config|--print-pid|--server)$ ]] ; then - compopt -o default - elif [[ ${prev} == '--working-directory' ]] ; then - compopt -o dirnames - elif [[ ${prev} == '--term' ]] ; then - # check if toe is available - command -v toe > /dev/null || return 1 - COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) - elif [[ ${prev} == '--font' ]] ; then - # check if fc-list is available - command -v fc-list > /dev/null || return 1 - COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) ) - elif [[ ${prev} == '--log-level' ]] ; then - COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) - elif [[ ${prev} == '--log-colorize' ]] ; then - COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) - elif [[ ${prev} =~ ^(--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|--check-config)$ ]] ; then - : # don't autocomplete for these flags - else - # complete commands from $PATH - COMPREPLY=( $(compgen -c -- ${cur}) ) + return 0 fi + case "$prev" in + --config|--print-pid|--server) + compopt -o default ;; + --working-directory) + compopt -o dirnames ;; + --term) + command -v toe > /dev/null || return 1 + COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) ;; + --font) + command -v fc-list > /dev/null || return 1 + COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) ) ;; + --log-level) + COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) ;; + --log-colorize) + COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) ;; + --app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|--check-config) + # Don't autocomplete for these flags + : ;; + *) + # Complete commands from $PATH + COMPREPLY=( $(compgen -c -- ${cur}) ) ;; + esac + return 0 } diff --git a/completions/bash/footclient b/completions/bash/footclient index 0381e8a0..39cb070e 100644 --- a/completions/bash/footclient +++ b/completions/bash/footclient @@ -27,7 +27,7 @@ _footclient() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} - # check if positional argument is completed + # Check if positional argument is completed previous_words=( "${COMP_WORDS[@]}" ) unset previous_words[-1] commands=$(compgen -c | grep -vFx "$(compgen -k)" | grep -vE '^([.:[]|footclient)$' | sort -u) @@ -39,37 +39,42 @@ _footclient() (( i++ )) continue fi - # positional argument found + # Positional argument found offset=$i fi (( i++ )) done if [[ ! -z "$offset" ]] ; then - # depends on bash_completion being available + # Depends on bash_completion being available declare -F _command_offset >/dev/null || return 1 _command_offset $offset + return 0 elif [[ ${cur} == --* ]] ; then COMPREPLY=( $(compgen -W "${flags}" -- ${cur}) ) - elif [[ ${prev} == '--server-socket' ]] ; then - compopt -o default - elif [[ ${prev} == '--working-directory' ]] ; then - compopt -o dirnames - elif [[ ${prev} == '--term' ]] ; then - # check if toe is available - command -v toe > /dev/null || return 1 - COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) - elif [[ ${prev} == '--log-level' ]] ; then - COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) - elif [[ ${prev} == '--log-colorize' ]] ; then - COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) - elif [[ ${prev} =~ ^(--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|)$ ]] ; then - : # don't autocomplete for these flags - else - # complete commands from $PATH - COMPREPLY=( $(compgen -c -- ${cur}) ) + return 0 fi + case "$prev" in + --server-socket) + compopt -o default ;; + --working-directory) + compopt -o dirnames ;; + --term) + command -v toe > /dev/null || return 1 + COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) ;; + --log-level) + COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) ;; + --log-colorize) + COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) ;; + --app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels) + # Don't autocomplete for these flags + : ;; + *) + # Complete commands from $PATH + COMPREPLY=( $(compgen -c -- ${cur}) ) ;; + esac + return 0 } From becdcd9bb78a552e65f90d3ebb79d286f9496229 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Tue, 10 Jan 2023 19:56:12 +0000 Subject: [PATCH 080/118] completions: bash: complete option arguments for short options --- completions/bash/foot | 14 +++++++------- completions/bash/footclient | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/completions/bash/foot b/completions/bash/foot index c1bb20fa..71aea97c 100644 --- a/completions/bash/foot +++ b/completions/bash/foot @@ -60,21 +60,21 @@ _foot() fi case "$prev" in - --config|--print-pid|--server) + --config|--print-pid|--server|-[cps]) compopt -o default ;; - --working-directory) + --working-directory|-D) compopt -o dirnames ;; - --term) + --term|-t) command -v toe > /dev/null || return 1 COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) ;; - --font) + --font|-f) command -v fc-list > /dev/null || return 1 COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) ) ;; - --log-level) + --log-level|-d) COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) ;; - --log-colorize) + --log-colorize|-l) COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) ;; - --app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|--check-config) + --app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|--check-config|-[ahoTvWwC]) # Don't autocomplete for these flags : ;; *) diff --git a/completions/bash/footclient b/completions/bash/footclient index 39cb070e..62abdd65 100644 --- a/completions/bash/footclient +++ b/completions/bash/footclient @@ -56,18 +56,18 @@ _footclient() fi case "$prev" in - --server-socket) + --server-socket|-s) compopt -o default ;; - --working-directory) + --working-directory|-D) compopt -o dirnames ;; - --term) + --term|-t) command -v toe > /dev/null || return 1 COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) ;; - --log-level) + --log-level|-d) COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) ;; - --log-colorize) + --log-colorize|-l) COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) ;; - --app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels) + --app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|-[ahoTvWw]) # Don't autocomplete for these flags : ;; *) From 3f57afbf60aa622f0ae57ca9aa997b99623d3678 Mon Sep 17 00:00:00 2001 From: EuCaue Date: Mon, 9 Jan 2023 01:17:45 +0000 Subject: [PATCH 081/118] add rose-pine theme --- themes/rose-pine | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 themes/rose-pine diff --git a/themes/rose-pine b/themes/rose-pine new file mode 100644 index 00000000..6b58a66c --- /dev/null +++ b/themes/rose-pine @@ -0,0 +1,26 @@ +# -*- conf -*- +# Rose-Piné + +[cursor] +color=191724 e0def4 + +[colors] +background=191724 +foreground=e0def4 +regular0=26233a # black +regular1=eb6f92 # red +regular2=31748f # green +regular3=f6c177 # yellow +regular4=9ccfd8 # blue +regular5=c4a7e7 # magenta +regular6=ebbcba # cyan +regular7=e0def4 # white + +bright0=6e6a86 # bright black +bright1=eb6f92 # bright red +bright2=31748f # bright green +bright3=f6c177 # bright yellow +bright4=9ccfd8 # bright blue +bright5=c4a7e7 # bright magenta +bright6=ebbcba # bright cyan +bright7=e0def4 # bright white \ No newline at end of file From ffaf08e07c37a7fc02040efd4fcbda51b1cf5b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 15 Jan 2023 10:23:44 +0100 Subject: [PATCH 082/118] config: remove unused struct --- config.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/config.h b/config.h index 648d92e4..31dddc64 100644 --- a/config.h +++ b/config.h @@ -74,11 +74,6 @@ enum key_binding_type { MOUSE_BINDING, }; -struct config_key_binding_text { - char *text; - bool master_copy; -}; - struct config_key_binding { int action; /* One of the varios bind_action_* enums from wayland.h */ struct config_key_modifiers modifiers; From 09f3475ad19753c5ca9dc8693b6937a7f75f7c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 15 Jan 2023 10:24:01 +0100 Subject: [PATCH 083/118] =?UTF-8?q?config:=20don=E2=80=99t=20double-free?= =?UTF-8?q?=20key=20binding=20auxiliary=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Key bindings with multiple key mappings share auxiliary data (e.g. the command to execute in pipe-* bindings, or the escape sequence in text-bindings). The first one is the designated “master” copy. Only that one should be freed. This fixed a double-free on exit, with e.g. [text-bindings] \x1b\x23=Mod4+space Mod4+equal Closes #1259 --- CHANGELOG.md | 3 +++ config.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac18a97e..593d0692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -116,12 +116,15 @@ config values (e.g. letter offsets, line height etc). * Selection being stuck visually when `IL` and `DL`.` * URL underlines sometimes still being visible after exiting URL mode. +* Text-bindings, and pipe-* bindings, with multiple key mappings + causing a crash (double-free) on exit ([#1259][1259]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 [1205]: https://codeberg.org/dnkl/foot/issues/1205 [1209]: https://codeberg.org/dnkl/foot/issues/1209 [1218]: https://codeberg.org/dnkl/foot/issues/1218 +[1259]: https://codeberg.org/dnkl/foot/issues/1259 ### Security diff --git a/config.c b/config.c index ea8d062f..d77b50b8 100644 --- a/config.c +++ b/config.c @@ -1477,6 +1477,9 @@ parse_section_csd(struct context *ctx) static void free_binding_aux(struct binding_aux *aux) { + if (!aux->master_copy) + return; + switch (aux->type) { case BINDING_AUX_NONE: break; case BINDING_AUX_PIPE: free_argv(&aux->pipe); break; From d1220aebfd5814d53c49c814b8eaee456b5e9cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 15 Jan 2023 14:00:06 +0100 Subject: [PATCH 084/118] terminfo: sync with ncurses 2023-01-14 * RV/rv: report DA2 * XR/xr: report version (XTVERSION) * XF: boolean, focus in/out events available --- CHANGELOG.md | 3 +++ foot.info | 11 ++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 593d0692..2652f3ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,9 @@ ([#1188][1188]). * Bracketed paste terminfo entries (`BD`, `BE`, `PE` and `PS`, added to ncurses in 2022-12-24). Vim makes use of these. +* “Report version” terminfo entries (`XR`/`xr`). +* “Report DA2” terminfo entries (`RV`/`rv`). +* `XF` terminfo capability (focus in/out events available). [1136]: https://codeberg.org/dnkl/foot/issues/1136 [1225]: https://codeberg.org/dnkl/foot/issues/1225 diff --git a/foot.info b/foot.info index 271a00f5..34b05f23 100644 --- a/foot.info +++ b/foot.info @@ -12,6 +12,10 @@ setaf=\E[%?%p1%{8}%<%t3%p1%d%e38\:2\:\:%p1%{65536}%/%d\:%p1%{256}%/%{255}%&%d\:%p1%{255}%&%d%;m, @default_terminfo@+base|foot base fragment, + AX, + Tc, + XF, + XT, am, bce, bw, @@ -21,9 +25,6 @@ msgr, npc, xenl, - AX, - XT, - Tc, cols#80, it#8, lines#24, @@ -36,10 +37,12 @@ Ms=\E]52;%p1%s;%p2%s\E\\, PE=\E[201~, PS=\E[200~, + RV=\E[>c, Se=\E[ q, Ss=\E[%p1%d q, Sync=\E[?2026%?%p1%{1}%-%tl%eh, XM=\E[?1006;1000%?%p1%{1}%=%th%el%;, + XR=\E[>0q, acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, bel=^G, blink=\E[5m, @@ -242,6 +245,7 @@ rmxx=\E[29m, rs1=\Ec, rs2=\E[!p\E[?3;4l\E[4l\E>, + rv=\E\\[[0-9]+;[0-9]+;[0-9]+c, sc=\E7, setrgbb=\E[48\:2\:\:%p1%d\:%p2%d\:%p3%dm, setrgbf=\E[38\:2\:\:%p1%d\:%p2%d\:%p3%dm, @@ -264,6 +268,7 @@ u9=\E[c, vpa=\E[%i%p1%dd, xm=\E[<%i%p3%d;%p1%d;%p2%d;%?%p4%tM%em%;, + xr=\EP>\\|[ -~]+\E\\\\, # XT, # AX, From a9298959a188013530257a665d839a6343229b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 15 Jan 2023 14:42:48 +0100 Subject: [PATCH 085/118] render: fix double-width glyphs glitching when surrounding cells overflow into it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If cells overflowed (for example, by using an italic font that isn’t truly monospaced) into a double-width glyph (that itself is *not* overflowing), then the double-width glyph would glitch when being rendered; typically the second half of it would occasionally disappear. This happened because we tried to rasterize the second cell of the double-width glyph. This cell contains a special “spacer” value. Rasterizing that typically results the font’s “not available” glyph. If _that_ glyph overflows, things broke; we’d later end up forcing a re-render of it (thus erasing half the double-width glyph). But since the double-width glyph _itself_ doesn’t overflow, _it_ wouldn’t be re-rendered, leaving it half erased. Fix by recognizing spacer cells, and not trying to rasterize them (set glyph count to 0, and cell count to 1). Closes #1256 --- CHANGELOG.md | 3 +++ render.c | 16 ++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2652f3ce..95aaab07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -121,6 +121,8 @@ * URL underlines sometimes still being visible after exiting URL mode. * Text-bindings, and pipe-* bindings, with multiple key mappings causing a crash (double-free) on exit ([#1259][1259]). +* Double-width glyphs glitching when surrounded by glyphs overflowing + into the double-width glyph ([#1256][1256]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 @@ -128,6 +130,7 @@ [1209]: https://codeberg.org/dnkl/foot/issues/1209 [1218]: https://codeberg.org/dnkl/foot/issues/1218 [1259]: https://codeberg.org/dnkl/foot/issues/1259 +[1256]: https://codeberg.org/dnkl/foot/issues/1256 ### Security diff --git a/render.c b/render.c index f5e7f627..92a37d7c 100644 --- a/render.c +++ b/render.c @@ -646,17 +646,21 @@ render_cell(struct terminal *term, pixman_image_t *pix, } } - if (single == NULL && grapheme == NULL) { - xassert(base != 0); - single = fcft_rasterize_char_utf32(font, base, term->font_subpixel); - if (single == NULL) { + if (unlikely(base >= CELL_SPACER)) { glyph_count = 0; cell_cols = 1; } else { - glyph_count = 1; - glyphs = &single; + xassert(base != 0); + single = fcft_rasterize_char_utf32(font, base, term->font_subpixel); + if (single == NULL) { + glyph_count = 0; + cell_cols = 1; + } else { + glyph_count = 1; + glyphs = &single; cell_cols = single->cols; + } } } } From b81b98d47c9570f2ac7356b1ff68a284b03759b5 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Tue, 17 Jan 2023 23:49:32 +0000 Subject: [PATCH 086/118] render: fix incorrect indent introduced by previous commit --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 92a37d7c..1c9dcb16 100644 --- a/render.c +++ b/render.c @@ -659,7 +659,7 @@ render_cell(struct terminal *term, pixman_image_t *pix, } else { glyph_count = 1; glyphs = &single; - cell_cols = single->cols; + cell_cols = single->cols; } } } From 1823fa846ae8205c8bbe78204af599277a743896 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Fri, 27 Jan 2023 11:47:12 +0000 Subject: [PATCH 087/118] completions: bash: simplify awk command used to filter terminfo names --- completions/bash/foot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completions/bash/foot b/completions/bash/foot index 71aea97c..eb17dad1 100644 --- a/completions/bash/foot +++ b/completions/bash/foot @@ -66,7 +66,7 @@ _foot() compopt -o dirnames ;; --term|-t) command -v toe > /dev/null || return 1 - COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) ;; + COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 !~ /[+]/ {print $1}')" -- ${cur}) ) ;; --font|-f) command -v fc-list > /dev/null || return 1 COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) ) ;; From 1c16e4a575713581140b81198c0a57dbbf5c0cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 12 Feb 2023 19:09:48 +0100 Subject: [PATCH 088/118] Tag a couple variables with UNUSED, to fix warnings with clang-15 Closes #1278 --- sixel.c | 2 +- uri.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sixel.c b/sixel.c index a824c405..592f48f8 100644 --- a/sixel.c +++ b/sixel.c @@ -154,7 +154,7 @@ verify_list_order(const struct terminal *term) int prev_col_count = 0; /* To aid debugging */ - size_t idx = 0; + size_t UNUSED idx = 0; tll_foreach(term->grid->sixel_images, it) { int row = grid_row_abs_to_sb( diff --git a/uri.c b/uri.c index 39073bde..7214a479 100644 --- a/uri.c +++ b/uri.c @@ -159,7 +159,7 @@ uri_parse(const char *uri, size_t len, char *p = decoded; size_t encoded_len = path_len; - size_t decoded_len = 0; + size_t UNUSED decoded_len = 0; while (true) { /* Find next '%' */ From 25154a81509934074934bd71c986d9866103f293 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Thu, 16 Feb 2023 08:50:53 +0000 Subject: [PATCH 089/118] doc: ctlseq: fix capitalization in description of DA3 sequence --- doc/foot-ctlseqs.7.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index f06a9418..ec970127 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -504,7 +504,7 @@ manipulation sequences. The generic format is: | \\E[ = _Ps_ c : DA3 : VT510 -: send tertiary device attributes. Foot responds with "FOOT", in +: Send tertiary device attributes. Foot responds with "FOOT", in hexadecimal. | \\E[ _Pm_ d : VPA From f2356adee392edefa54009c9932a37e6c5a45b20 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Thu, 16 Feb 2023 09:09:51 +0000 Subject: [PATCH 090/118] doc: foot.ini: fix spelling mistake in [bell].urgent description --- 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 07a3cb94..1fbca27a 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -365,7 +365,7 @@ Note: do not set *TERM* here; use the *term* option in the main *urgent* When set to _yes_, foot will signal urgency to the compositor through the XDG activation protocol whenever *BEL* is received, - and the window does NOT have keyboard foccus. + and the window does NOT have keyboard focus. If the compositor does not implement this protocol, the margins will be painted in red instead. From 7f26914583a0114e102e4596763302a5bc6d1730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 29 Dec 2022 11:32:21 +0100 Subject: [PATCH 091/118] wayland: ignore configure events for unmapped surfaces Closes #1249 Note that it is still unclear whether ack:ing a configure event for an unmapped surface is a protocol violation, or something that should be handled by the compositor. According to https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/108, Kwin, Mutter and Weston handles it, while wlroots does not. --- CHANGELOG.md | 3 +++ wayland.c | 11 +++++++++++ wayland.h | 1 + 3 files changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95aaab07..0b11bbc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -123,6 +123,8 @@ causing a crash (double-free) on exit ([#1259][1259]). * Double-width glyphs glitching when surrounded by glyphs overflowing into the double-width glyph ([#1256][1256]). +* Wayland protocol violation when ack:ing a configure event for an + unmapped surface ([#1249][1249]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 @@ -131,6 +133,7 @@ [1218]: https://codeberg.org/dnkl/foot/issues/1218 [1259]: https://codeberg.org/dnkl/foot/issues/1259 [1256]: https://codeberg.org/dnkl/foot/issues/1256 +[1249]: https://codeberg.org/dnkl/foot/issues/1249 ### Security diff --git a/wayland.c b/wayland.c index 55d45da7..68a7a4f1 100644 --- a/wayland.c +++ b/wayland.c @@ -769,6 +769,16 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, struct wl_window *win = data; struct terminal *term = win->term; + if (win->unmapped) { + /* + * https://codeberg.org/dnkl/foot/issues/1249 + * https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3487 + * https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3719 + * https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/108 + */ + return; + } + bool wasnt_configured = !win->is_configured; bool was_resizing = win->is_resizing; bool csd_was_enabled = win->csd_mode == CSD_YES && !win->is_fullscreen; @@ -1619,6 +1629,7 @@ wayl_win_destroy(struct wl_window *win) wayl_roundtrip(win->term->wl); /* Main window */ + win->unmapped = true; wl_surface_attach(win->surface, NULL, 0, 0); wl_surface_commit(win->surface); wayl_roundtrip(win->term->wl); diff --git a/wayland.h b/wayland.h index e86c6a3d..4b6939ab 100644 --- a/wayland.h +++ b/wayland.h @@ -327,6 +327,7 @@ struct wl_window { tll(struct xdg_activation_token_context *) xdg_tokens; bool urgency_token_is_pending; #endif + bool unmapped; struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; From 7a43737745e5e6d8c5ef1cb29ade75b6ca2d6f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Feb 2023 17:51:29 +0100 Subject: [PATCH 092/118] =?UTF-8?q?render:=20fix=20selected=20cursor=20cel?= =?UTF-8?q?l=20being=20=E2=80=98invisble=E2=80=99=20when=20background=20al?= =?UTF-8?q?pha=20is=20used?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... by taking the cell ‘selected’ state into account when determining whether to use the default fg or bg as the ‘text’ color. --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 1c9dcb16..e85d669b 100644 --- a/render.c +++ b/render.c @@ -424,7 +424,7 @@ cursor_colors_for_cell(const struct terminal *term, const struct cell *cell, /* We *know* this only happens when bg is the default bg * color */ *text_color = color_hex_to_pixman( - term->reverse ? term->colors.fg : term->colors.bg); + term->reverse ^ is_selected ? term->colors.fg : term->colors.bg); } else *text_color = *bg; } From 8a849b4b08539766e8251fa9e7d56c557878617b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Feb 2023 17:49:57 +0100 Subject: [PATCH 093/118] render: fix inversed cursor fg color when alpha != 1.0, take #2 No need to check if terminal colors have been reversed - this is done by the cell rendering logic. This hopefully fixes all remaining issues with invisible text when background alpha < 1.0 --- render.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/render.c b/render.c index e85d669b..b1c56bbc 100644 --- a/render.c +++ b/render.c @@ -419,14 +419,13 @@ cursor_colors_for_cell(const struct terminal *term, const struct cell *cell, } } else { *cursor_color = *fg; + *text_color = *bg; if (unlikely(text_color->alpha != 0xffff)) { - /* We *know* this only happens when bg is the default bg - * color */ - *text_color = color_hex_to_pixman( - term->reverse ^ is_selected ? term->colors.fg : term->colors.bg); - } else - *text_color = *bg; + /* The *only* color that can have transparency is the + * default background color */ + *text_color = color_hex_to_pixman(term->colors.bg); + } } } From 514fcc20a73feec88f9a912a8dedf7eac40ca55b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 2 Mar 2023 17:22:27 +0100 Subject: [PATCH 094/118] render: resize: call xdg_toplevel_set_min_size() This is a hint to the compositor, not to set a smaller size than this. --- CHANGELOG.md | 1 + render.c | 17 ++++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b11bbc0..4fc80821 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -125,6 +125,7 @@ into the double-width glyph ([#1256][1256]). * Wayland protocol violation when ack:ing a configure event for an unmapped surface ([#1249][1249]). +* `xdg\_toplevel::set_min_size()` not being called. [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 diff --git a/render.c b/render.c index b1c56bbc..9c701000 100644 --- a/render.c +++ b/render.c @@ -3885,9 +3885,9 @@ maybe_resize(struct terminal *term, int width, int height, bool force) const int min_cols = 2; const int min_rows = 1; - /* Minimum window size */ - const int min_width = min_cols * term->cell_width; - const int min_height = min_rows * term->cell_height; + /* Minimum window size (must be divisible by the scaling factor)*/ + const int min_width = (min_cols * term->cell_width + scale - 1) / scale * scale; + const int min_height = (min_rows * term->cell_height + scale - 1) / scale * scale; width = max(width, min_width); height = max(height, min_height); @@ -4132,12 +4132,6 @@ damage_view: term->stashed_height = term->height; } -#if 0 - /* TODO: doesn't include CSD title bar */ - xdg_toplevel_set_min_size( - term->window->xdg_toplevel, min_width / scale, min_height / scale); -#endif - { const bool title_shown = wayl_win_csd_titlebar_visible(term->window); const bool border_shown = wayl_win_csd_borders_visible(term->window); @@ -4147,6 +4141,11 @@ damage_view: const int border_width = border_shown ? term->conf->csd.border_width_visible : 0; + xdg_toplevel_set_min_size( + term->window->xdg_toplevel, + min_width / scale + 2 * border_width, + min_height / scale + title_height + 2 * border_width); + xdg_surface_set_window_geometry( term->window->xdg_surface, -border_width, From 9a5a2d9957d8421b815d8ab07e867e73112b9591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Feb 2023 17:56:03 +0100 Subject: [PATCH 095/118] key-binding: sort binding lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sort bindings such that bindings with the same symbol are sorted with the binding having the most modifiers comes first. This fixes an issue where the “wrong” key binding are triggered when used with “consumed” modifiers. For example: if Control+BackSpace is bound before Control+Shift+BackSpace, then the latter binding is never triggered. Why? Because Shift is a consumed modifier. This means Control+BackSpace is “the same” as Control+Shift+BackSpace. By sorting bindings with more modifiers first, we work around the problem. But note that it is *just* a workaround, and I’m not confident there aren’t cases where it doesn’t work. Closes #1280 --- CHANGELOG.md | 3 +++ key-binding.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fc80821..40072182 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -126,6 +126,8 @@ * Wayland protocol violation when ack:ing a configure event for an unmapped surface ([#1249][1249]). * `xdg\_toplevel::set_min_size()` not being called. +* Key bindings with consumed modifiers masking other key bindings + ([#1280][1280]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 @@ -135,6 +137,7 @@ [1259]: https://codeberg.org/dnkl/foot/issues/1259 [1256]: https://codeberg.org/dnkl/foot/issues/1256 [1249]: https://codeberg.org/dnkl/foot/issues/1249 +[1280]: https://codeberg.org/dnkl/foot/issues/1280 ### Security diff --git a/key-binding.c b/key-binding.c index 1876a885..1dffd3ee 100644 --- a/key-binding.c +++ b/key-binding.c @@ -350,6 +350,60 @@ maybe_repair_key_combo(const struct seat *seat, return sym; } +static int +key_cmp(struct key_binding a, struct key_binding b) +{ + xassert(a.type == b.type); + + /* + * Sort bindings such that bindings with the same symbol are + * sorted with the binding having the most modifiers comes first. + * + * This fixes an issue where the “wrong” key binding are triggered + * when used with “consumed” modifiers. + * + * For example: if Control+BackSpace is bound before + * Control+Shift+BackSpace, then the latter binding is never + * triggered. + * + * Why? Because Shift is a consumed modifier. This means + * Control+BackSpace is “the same” as Control+Shift+BackSpace. + * + * By sorting bindings with more modifiers first, we work around + * the problem. But note that it is *just* a workaround, and I’m + * not confident there aren’t cases where it doesn’t work. + * + * See https://codeberg.org/dnkl/foot/issues/1280 + */ + + const int a_mod_count = __builtin_popcount(a.mods); + const int b_mod_count = __builtin_popcount(b.mods); + + switch (a.type) { + case KEY_BINDING: + if (a.k.sym != b.k.sym) + return b.k.sym - a.k.sym; + return b_mod_count - a_mod_count; + + case MOUSE_BINDING: { + if (a.m.button != b.m.button) + return b.m.button - a.m.button; + if (a_mod_count != b_mod_count) + return b_mod_count - a_mod_count; + return b.m.count - a.m.count; + } + } + + BUG("invalid key binding type"); + return 0; +} + +static void NOINLINE +sort_binding_list(key_binding_list_t *list) +{ + tll_sort(*list, key_cmp); +} + static void NOINLINE convert_key_binding(struct key_set *set, const struct config_key_binding *conf_binding, @@ -371,6 +425,7 @@ convert_key_binding(struct key_set *set, }, }; tll_push_back(*bindings, binding); + sort_binding_list(bindings); } static void @@ -421,6 +476,7 @@ convert_mouse_binding(struct key_set *set, }, }; tll_push_back(set->public.mouse, binding); + sort_binding_list(&set->public.mouse); } static void From 9da1b1cec33080890d12946b292511b1f2e17a24 Mon Sep 17 00:00:00 2001 From: jaroeichler Date: Mon, 27 Feb 2023 13:32:13 +0000 Subject: [PATCH 096/118] themes: add Material Amber --- themes/material-amber | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 themes/material-amber diff --git a/themes/material-amber b/themes/material-amber new file mode 100644 index 00000000..ee2c21b5 --- /dev/null +++ b/themes/material-amber @@ -0,0 +1,40 @@ +# -*- conf -*- +# Material Amber +# Based on material.io guidelines with Amber 50 background + +# [cursor] +# color=fff8e1 21201d + +[colors] +foreground = 21201d +background = fff8e1 + +regular0 = 21201d # black +regular1 = cd4340 # red +regular2 = 498d49 # green +regular3 = fab32d # yellow +regular4 = 3378c4 # blue +regular5 = b83269 # magenta +regular6 = 21929a # cyan +regular7 = ffd7d7 # white + +bright0 = 66635a # bright black +bright1 = dd7b72 # bright red +bright2 = 82ae78 # bright green +bright3 = fbc870 # bright yellow +bright4 = 73a0cd # bright blue +bright5 = ce6f8e # bright magenta +bright6 = 548c94 # bright cyan +bright7 = ffe1da # bright white + +dim0 = 9e9a8c # dim black +dim1 = e9a99b # dim red +dim2 = b0c99f # dim green +dim3 = fdda9a # dim yellow +dim4 = a6c0d4 # dim blue +dim5 = e0a1ad # dim magenta +dim6 = 3c6064 # dim cyan +dim7 = ffe9dd # dim white + +# selection-foreground=fff8e1 +# selection-background=21201d From 9f3ce9236f9818263437cb6a4f26b20c5506a218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Mar 2023 17:21:11 +0100 Subject: [PATCH 097/118] =?UTF-8?q?config:=20apply=20fontconfig=20rules=20?= =?UTF-8?q?if=20user=20didn=E2=80=99t=20set=20an=20explicit=20font=20size?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the user didn’t explicitly set the font size (e.g. font=monospace, instead of font=monospace:size=12), our initial attempt to read the FC_SIZE and FC_PIXEL_SIZE attributes will fail, and we used to fallback to setting the size to 8pt. Change this slightly, so that when we fail to read the FC_*_SIZE attributes, apply the fontconfig rules, but *without expanding* them (i.e. without calling FcDefaultSubstitute()). Then try reading FC_*_SIZE again. If that too fails, _then_ set size to 8pt. This allows us to pick up rules that set a default {pixel}size: 14 Closes #1287 --- CHANGELOG.md | 4 ++++ config.c | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40072182..08d7d69f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,10 +81,14 @@ * DPI is now forced to 96 when found to be unreasonably high. * Set default log level to warning ([#1215][1215]). * Default `grapheme-width-method` from `wcswidth` to `double-width`. +* When determining initial font size, do FontConfig config + substitution if the user-provided font pattern has no {pixel}size + option ([#1287][1287]). [1166]: https://codeberg.org/dnkl/foot/issues/1166 [1179]: https://codeberg.org/dnkl/foot/issues/1179 [1215]: https://codeberg.org/dnkl/foot/pulls/1215 +[1287]: https://codeberg.org/dnkl/foot/issues/1287 ### Deprecated diff --git a/config.c b/config.c index d77b50b8..2ede1aa5 100644 --- a/config.c +++ b/config.c @@ -3390,20 +3390,48 @@ config_font_parse(const char *pattern, struct config_font *font) if (pat == NULL) return false; + /* + * First look for user specified {pixel}size option + * e.g. “font-name:size=12” + */ + double pt_size = -1.0; - FcPatternGetDouble(pat, FC_SIZE, 0, &pt_size); - FcPatternRemove(pat, FC_SIZE, 0); + FcResult have_pt_size = FcPatternGetDouble(pat, FC_SIZE, 0, &pt_size); int px_size = -1; - FcPatternGetInteger(pat, FC_PIXEL_SIZE, 0, &px_size); - FcPatternRemove(pat, FC_PIXEL_SIZE, 0); + FcResult have_px_size = FcPatternGetInteger(pat, FC_PIXEL_SIZE, 0, &px_size); - if (pt_size == -1. && px_size == -1) - pt_size = 8.0; + if (have_pt_size != FcResultMatch && have_px_size != FcResultMatch) { + /* + * Apply fontconfig config. Can’t do that until we’ve first + * checked for a user provided size, since we may end up with + * both “size” and “pixelsize” being set, and we don’t know + * which one takes priority. + */ + FcPattern *pat_copy = FcPatternDuplicate(pat); + if (pat_copy == NULL || + !FcConfigSubstitute(NULL, pat_copy, FcMatchPattern)) + { + LOG_WARN("%s: failed to do config substitution", pattern); + } else { + have_pt_size = FcPatternGetDouble(pat_copy, FC_SIZE, 0, &pt_size); + have_px_size = FcPatternGetInteger(pat_copy, FC_PIXEL_SIZE, 0, &px_size); + } + + FcPatternDestroy(pat_copy); + + if (have_pt_size != FcResultMatch && have_px_size != FcResultMatch) + pt_size = 8.0; + } + + FcPatternRemove(pat, FC_SIZE, 0); + FcPatternRemove(pat, FC_PIXEL_SIZE, 0); char *stripped_pattern = (char *)FcNameUnparse(pat); FcPatternDestroy(pat); + LOG_DBG("%s: pt-size=%.2f, px-size=%d", stripped_pattern, pt_size, px_size); + *font = (struct config_font){ .pattern = stripped_pattern, .pt_size = pt_size, From 5b2f02d826d8043b6b89860c56802ea5fed0f3bd Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Mon, 20 Mar 2023 14:40:36 +0000 Subject: [PATCH 098/118] slave: set $TERM_PROGRAM and $TERM_PROGRAM_VERSION environment variables These are already being set by iTerm2, WezTerm, tmux and likely some others. Even though using yet more environment variables seems rather questionable, if we don't set these we run the risk of inheriting them from other terminals. See also: * https://gitlab.com/gnachman/iterm2/-/blob/97a6078df8e822da165e91737a01c0b9e115dd16/sources/PTYSession.m#L2568-2570 * https://github.com/tmux/tmux/blob/1d0f68dee9f71c504e03616fa472a408a6caa49b/environ.c#L263-L264 * https://github.com/search?q=TERM_PROGRAM&type=code --- CHANGELOG.md | 2 ++ doc/foot.1.scd | 11 +++++++++++ doc/footclient.1.scd | 11 +++++++++++ generate-version.sh | 1 + slave.c | 3 +++ 5 files changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08d7d69f..01d664fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,8 @@ * “Report version” terminfo entries (`XR`/`xr`). * “Report DA2” terminfo entries (`RV`/`rv`). * `XF` terminfo capability (focus in/out events available). +* `$TERM_PROGRAM` and `$TERM_PROGRAM_VERSION` environment variables + set in the slave process. [1136]: https://codeberg.org/dnkl/foot/issues/1136 [1225]: https://codeberg.org/dnkl/foot/issues/1225 diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 6f63d4c8..51c53130 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -546,6 +546,17 @@ In all other cases, the exit code is that of the client application This variable is set to *truecolor*, to indicate to client applications that 24-bit RGB colors are supported. +*TERM_PROGRAM* + Always set to *foot*. This can be used by client applications to + check which terminal is in use, but with the caveat that it may + have been inherited from a parent process in other terminals that + aren't known to set the variable. + +*TERM_PROGRAM_VERSION* + Set to the foot version string, in the format _major_*.*_minor_*.*_patch_ + or _major_*.*_minor_*.*_patch_*-*_revision_*-\g*_commit_ for inter-release + builds. The same caveat as for *TERM_PROGRAM* applies. + In addition to the variables listed above, custom environment variables may be defined in *foot.ini*(5). diff --git a/doc/footclient.1.scd b/doc/footclient.1.scd index 63235134..189d9e3c 100644 --- a/doc/footclient.1.scd +++ b/doc/footclient.1.scd @@ -158,6 +158,17 @@ terminfo entries manually, by copying *foot* and *foot-direct* to This variable is set to *truecolor*, to indicate to client applications that 24-bit RGB colors are supported. +*TERM_PROGRAM* + Always set to *foot*. This can be used by client applications to + check which terminal is in use, but with the caveat that it may + have been inherited from a parent process in other terminals that + aren't known to set the variable. + +*TERM_PROGRAM_VERSION* + Set to the foot version string, in the format _major_*.*_minor_*.*_patch_ + or _major_*.*_minor_*.*_patch_*-*_revision_*-\g*_commit_ for inter-release + builds. The same caveat as for *TERM_PROGRAM* applies. + In addition to the variables listed above, custom environment variables may be defined in *foot.ini*(5). diff --git a/generate-version.sh b/generate-version.sh index a030d512..3772008b 100755 --- a/generate-version.sh +++ b/generate-version.sh @@ -41,6 +41,7 @@ patch=$(echo "${new_version}" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\3/') extra=$(echo "${new_version}" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)(-([0-9]+-g[a-z0-9]+) .*)?.*/\5/') new_version="#define FOOT_VERSION \"${new_version}\" +#define FOOT_VERSION_SHORT \"${git_version:-${default_version}}\" #define FOOT_MAJOR ${major} #define FOOT_MINOR ${minor} #define FOOT_PATCH ${patch} diff --git a/slave.c b/slave.c index d4861ad0..2f23e996 100644 --- a/slave.c +++ b/slave.c @@ -21,6 +21,7 @@ #include "macros.h" #include "terminal.h" #include "tokenize.h" +#include "version.h" #include "xmalloc.h" extern char **environ; @@ -351,6 +352,8 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv, } setenv("TERM", term_env, 1); + setenv("TERM_PROGRAM", "foot", 1); + setenv("TERM_PROGRAM_VERSION", FOOT_VERSION_SHORT, 1); setenv("COLORTERM", "truecolor", 1); setenv("PWD", cwd, 1); From 296e75f4f54f56be7d36fcccb032dca9e5be959b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Mar 2023 16:53:41 +0200 Subject: [PATCH 099/118] =?UTF-8?q?render:=20fix=20glitchy=20selection=20w?= =?UTF-8?q?hile=20resizing=20the=20=E2=80=98normal=E2=80=99=20screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The selection coordinates are in absolute row numbers. As such, selection breaks when interactively resizing the normal grid, since we then instantiate a temporary grid mapping directly to the current viewport (for performance reason, to avoid reflowing the entire grid over and over again). Fix by stashing the actual selection coordinates, and ajusting the "active" ones to the temporary grid. --- render.c | 6 ++++++ terminal.h | 1 + 2 files changed, 7 insertions(+) diff --git a/render.c b/render.c index 9c701000..2aba3237 100644 --- a/render.c +++ b/render.c @@ -3976,6 +3976,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) term->interactive_resizing.old_hide_cursor = term->hide_cursor; term->interactive_resizing.grid = xmalloc(sizeof(*term->interactive_resizing.grid)); *term->interactive_resizing.grid = term->normal; + term->interactive_resizing.selection_coords = term->selection.coords; } else { /* We’ll replace the current temporary grid, with a new * one (again based on the original grid) */ @@ -4013,6 +4014,9 @@ maybe_resize(struct terminal *term, int width, int height, bool force) .kitty_kbd = orig->kitty_kbd, }; + term->selection.coords.start.row -= orig->view; + term->selection.coords.end.row -= orig->view; + for (size_t i = 0, j = orig->view; i < term->interactive_resizing.old_screen_rows; i++, j = (j + 1) & (orig->num_rows - 1)) @@ -4069,6 +4073,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) free(term->interactive_resizing.grid); term->hide_cursor = term->interactive_resizing.old_hide_cursor; + term->selection.coords = term->interactive_resizing.selection_coords; old_rows = term->interactive_resizing.old_screen_rows; @@ -4076,6 +4081,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) term->interactive_resizing.old_screen_rows = 0; term->interactive_resizing.new_rows = 0; term->interactive_resizing.old_hide_cursor = false; + term->interactive_resizing.selection_coords = (struct range){{-1, -1}, {-1, -1}}; term_ptmx_resume(term); } diff --git a/terminal.h b/terminal.h index ec5560cd..21236797 100644 --- a/terminal.h +++ b/terminal.h @@ -604,6 +604,7 @@ struct terminal { int old_cols; /* term->cols before resize started */ int old_hide_cursor; /* term->hide_cursor before resize started */ int new_rows; /* New number of scrollback rows */ + struct range selection_coords; } interactive_resizing; struct { From ae26915916731813edc2aefeb18a5754e8c79cd4 Mon Sep 17 00:00:00 2001 From: Harri Nieminen Date: Wed, 29 Mar 2023 00:31:49 +0300 Subject: [PATCH 100/118] fix typos --- INSTALL.md | 2 +- csi.c | 2 +- doc/foot.ini.5.scd | 2 +- grid.c | 2 +- tests/test-config.c | 10 +++++----- themes/onedark | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 4c15b7b4..6cc51750 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -440,7 +440,7 @@ sed 's/@default_terminfo@/foot/g' foot.info | \ Where _”output-directory”_ **must** match the value passed to `-Dcustom-terminfo-install-location` in the foot build. If `-Dcustom-terminfo-install-location` has not been set, `-o -` can simply be omitted. +` can simply be omitted. Or, if packaging: diff --git a/csi.c b/csi.c index e77ae971..cef48d43 100644 --- a/csi.c +++ b/csi.c @@ -1518,7 +1518,7 @@ csi_dispatch(struct terminal *term, uint8_t final) break; /* final == 'm' */ case 'n': { - int resource = vt_param_get(term, 0, 2); /* Default is modifyFuncionKeys */ + int resource = vt_param_get(term, 0, 2); /* Default is modifyFunctionKeys */ switch (resource) { case 0: /* modifyKeyboard */ case 1: /* modifyCursorKeys */ diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 1fbca27a..5ef62045 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -960,7 +960,7 @@ Be careful; do not use single-letter keys that are also used in original text. But with e.g. OSC-8 URLs (the terminal version of HTML anchors, - i.e. "links"), the text on the screen can be something completey + i.e. "links"), the text on the screen can be something completely different than the URL. This action toggles between showing and hiding the URL on the jump diff --git a/grid.c b/grid.c index 7b86e2c1..e1c4d28b 100644 --- a/grid.c +++ b/grid.c @@ -793,7 +793,7 @@ grid_resize_and_reflow( /* * Set end-coordinate for this chunk, by finding the next - * point-of-interrest on this row. + * point-of-interest on this row. * * If there are no more tracking points, or URI ranges, * the end-coordinate will be at the end of the row, diff --git a/tests/test-config.c b/tests/test-config.c index 4f8b0c3b..6b44e9c2 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -895,7 +895,7 @@ enum collision_test_mode { FAIL_DIFFERENT_ACTION, FAIL_DIFFERENT_ARGV, FAIL_MOUSE_OVERRIDE, - SUCCED_SAME_ACTION_AND_ARGV, + SUCCEED_SAME_ACTION_AND_ARGV, }; static void @@ -949,7 +949,7 @@ _test_binding_collisions(struct context *ctx, break; case FAIL_DIFFERENT_ARGV: - case SUCCED_SAME_ACTION_AND_ARGV: + case SUCCEED_SAME_ACTION_AND_ARGV: bindings.arr[0].aux.type = BINDING_AUX_PIPE; bindings.arr[0].aux.master_copy = true; bindings.arr[0].aux.pipe.args = xcalloc( @@ -965,13 +965,13 @@ _test_binding_collisions(struct context *ctx, bindings.arr[1].aux.pipe.args[0] = xstrdup("/usr/bin/foobar"); bindings.arr[1].aux.pipe.args[1] = xstrdup("hello"); - if (test_mode == SUCCED_SAME_ACTION_AND_ARGV) + if (test_mode == SUCCEED_SAME_ACTION_AND_ARGV) bindings.arr[1].aux.pipe.args[2] = xstrdup("world"); break; } bool expected_result = - test_mode == SUCCED_SAME_ACTION_AND_ARGV ? true : false; + test_mode == SUCCEED_SAME_ACTION_AND_ARGV ? true : false; if (resolve_key_binding_collisions( ctx->conf, ctx->section, map, &bindings, type) != expected_result) @@ -1004,7 +1004,7 @@ test_binding_collisions(struct context *ctx, { _test_binding_collisions(ctx, max_action, map, type, FAIL_DIFFERENT_ACTION); _test_binding_collisions(ctx, max_action, map, type, FAIL_DIFFERENT_ARGV); - _test_binding_collisions(ctx, max_action, map, type, SUCCED_SAME_ACTION_AND_ARGV); + _test_binding_collisions(ctx, max_action, map, type, SUCCEED_SAME_ACTION_AND_ARGV); if (type == MOUSE_BINDING) { _test_binding_collisions( diff --git a/themes/onedark b/themes/onedark index d7f78a66..ac5cc834 100644 --- a/themes/onedark +++ b/themes/onedark @@ -1,5 +1,5 @@ # OneDark -# Pallete based on the same theme from https://github.com/dexpota/kitty-themes +# Palette based on the same theme from https://github.com/dexpota/kitty-themes [cursor] color=111111 cccccc From 3215d54f31c9e339598a34c9fa43f3dc3c5d1e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Mar 2023 16:56:10 +0200 Subject: [PATCH 101/118] input: (kitty kbd): the resulting UTF-8 string may translate to multiple UTF-32 codepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When this happened (for example, by specifying a custom compose sequence), the kitty keyboard protocol didn’t emit any text at all. This was caused by the utf32 codepoint being -1. This in turned was caused by us trying to convert the utf8 sequence to a *single* utf32 codepoint. This patch replaces the use of mbrtoc32() with a call to ambstoc32(), and the utf32 codepoint with an utf32 string. The kitty keyboard protocol is updated: * When determining if we’re dealing with text, check *all* codepoints in the utf32 string. * Add support for multiple codepoints when reporting "associated text". The first codepoint is the actual parameter in the emitted sequence, and the remaining codepoints are sub-parameters. I.e. the codepoints are colon separated. Closes #1288 --- CHANGELOG.md | 3 +++ input.c | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01d664fc..a02b9346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -134,6 +134,8 @@ * `xdg\_toplevel::set_min_size()` not being called. * Key bindings with consumed modifiers masking other key bindings ([#1280][1280]). +* Multi-character compose sequences with the kitty keyboard protocol + ([#1288][1288]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 @@ -144,6 +146,7 @@ [1256]: https://codeberg.org/dnkl/foot/issues/1256 [1249]: https://codeberg.org/dnkl/foot/issues/1249 [1280]: https://codeberg.org/dnkl/foot/issues/1280 +[1288]: https://codeberg.org/dnkl/foot/issues/1288 ### Security diff --git a/input.c b/input.c index 0a3773bc..b7f25670 100644 --- a/input.c +++ b/input.c @@ -898,7 +898,7 @@ struct kbd_ctx { const uint8_t *buf; size_t count; } utf8; - uint32_t utf32; + uint32_t *utf32; enum xkb_compose_status compose_status; enum wl_keyboard_key_state key_state; @@ -1121,12 +1121,18 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term, (seat->kbd.mod_num != XKB_MOD_INVALID ? 1 << seat->kbd.mod_num : 0); const xkb_keysym_t sym = ctx->sym; - const uint32_t utf32 = ctx->utf32; + const uint32_t *utf32 = ctx->utf32; const uint8_t *const utf8 = ctx->utf8.buf; - - const bool is_text = iswprint(utf32) && (effective & ~caps_num) == 0; const size_t count = ctx->utf8.count; + bool is_text = utf32 != NULL && (effective & ~caps_num) == 0; + for (size_t i = 0; utf32[i] != U'\0'; i++) { + if (!iswprint(utf32[i])) { + is_text = false; + break; + } + } + const bool report_associated_text = (flags & KITTY_KBD_REPORT_ASSOCIATED) && is_text && !released; @@ -1245,7 +1251,7 @@ emit_escapes: : sym; if (composed) - key = utf32; + key = utf32[0]; /* TODO: what if there are multiple codepoints? */ else { key = xkb_keysym_to_utf32(sym_to_use); if (key == 0) @@ -1284,7 +1290,7 @@ emit_escapes: } else event[0] = '\0'; - char buf[64], *p = buf; + char buf[128], *p = buf; size_t left = sizeof(buf); size_t bytes; @@ -1316,8 +1322,16 @@ emit_escapes: } if (report_associated_text) { - bytes = snprintf(p, left, "%s;%u", !emit_mods ? ";" : "", utf32); + bytes = snprintf(p, left, "%s;%u", !emit_mods ? ";" : "", utf32[0]); p += bytes; left -= bytes; + + /* Additional text codepoints */ + if (utf32[0] != U'\0') { + for (size_t i = 1; utf32[i] != U'\0'; i++) { + bytes = snprintf(p, left, ":%u", utf32[i]); + p += bytes; left -= bytes; + } + } } bytes = snprintf(p, left, "%c", final); @@ -1514,19 +1528,20 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, * and use a malloc:ed buffer when necessary */ uint8_t buf[32]; uint8_t *utf8 = count < sizeof(buf) ? buf : xmalloc(count + 1); - uint32_t utf32 = (uint32_t)-1; + uint32_t *utf32 = NULL; if (composed) { xkb_compose_state_get_utf8( seat->kbd.xkb_compose_state, (char *)utf8, count + 1); - char32_t wc; - if (mbrtoc32(&wc, (const char *)utf8, count, &(mbstate_t){0}) == count) - utf32 = wc; + if (count > 0) + utf32 = ambstoc32((const char *)utf8); } else { xkb_state_key_get_utf8( seat->kbd.xkb_state, key, (char *)utf8, count + 1); - utf32 = xkb_state_key_get_utf32(seat->kbd.xkb_state, key); + + utf32 = xcalloc(2, sizeof(utf32[0])); + utf32[0] = xkb_state_key_get_utf32(seat->kbd.xkb_state, key); } struct kbd_ctx ctx = { @@ -1563,6 +1578,8 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, selection_cancel(term); } + free(utf32); + maybe_repeat: clock_gettime( term->wl->presentation_clock_id, &term->render.input_time); From 7bc22862fa9536cb2f18b030209a95306e57360d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Mar 2023 18:31:24 +0200 Subject: [PATCH 102/118] render: protect against integer underflow when calculating scroll area MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When applying scroll damage, we calculate the affected region’s height (in pixels), by subtracting the number of rows to scroll, from the scrolling region, and finally multiply by the cell height. If the number of rows to scroll is very large, the subtraction may underflow, resulting in a very large height value instead of a negative one. This caused the check for "scrolling too many lines" to fail. That in turn resulted in an integer overflow when calculating the source offset into the rendered surface buffer, which typically triggered a segfault. This bug happened when there was continuous output in the terminal without any new frames being rendered. This caused a buildup of scroll damage, that triggered the underflow+overflow when we finally did render a new frame. For example, a compositor that doesn’t send any frame callbacks (for example because the terminal window is minimized, or on a different workspace/tag) would cause this. Closes #1305 --- CHANGELOG.md | 3 +++ render.c | 22 ++++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a02b9346..df098c41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -136,6 +136,8 @@ ([#1280][1280]). * Multi-character compose sequences with the kitty keyboard protocol ([#1288][1288]). +* Crash when application output scrolls very fast, e.g. `yes` + ([#1305][1305]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 @@ -147,6 +149,7 @@ [1249]: https://codeberg.org/dnkl/foot/issues/1249 [1280]: https://codeberg.org/dnkl/foot/issues/1280 [1288]: https://codeberg.org/dnkl/foot/issues/1288 +[1305]: https://codeberg.org/dnkl/foot/issues/1305 ### Security diff --git a/render.c b/render.c index 2aba3237..f16898b4 100644 --- a/render.c +++ b/render.c @@ -929,14 +929,19 @@ static void grid_render_scroll(struct terminal *term, struct buffer *buf, const struct damage *dmg) { - int height = (dmg->region.end - dmg->region.start - dmg->lines) * term->cell_height; - LOG_DBG( "damage: SCROLL: %d-%d by %d lines", dmg->region.start, dmg->region.end, dmg->lines); - if (height <= 0) + const int region_size = dmg->region.end - dmg->region.start; + + if (dmg->lines >= region_size) { + /* The entire scroll region will be scrolled out (i.e. replaced) */ return; + } + + const int height = (region_size - dmg->lines) * term->cell_height; + xassert(height > 0); #if TIME_SCROLL_DAMAGE struct timespec start_time; @@ -1037,14 +1042,19 @@ static void grid_render_scroll_reverse(struct terminal *term, struct buffer *buf, const struct damage *dmg) { - int height = (dmg->region.end - dmg->region.start - dmg->lines) * term->cell_height; - LOG_DBG( "damage: SCROLL REVERSE: %d-%d by %d lines", dmg->region.start, dmg->region.end, dmg->lines); - if (height <= 0) + const int region_size = dmg->region.end - dmg->region.start; + + if (dmg->lines >= region_size) { + /* The entire scroll region will be scrolled out (i.e. replaced) */ return; + } + + const int height = (region_size - dmg->lines) * term->cell_height; + xassert(height > 0); #if TIME_SCROLL_DAMAGE struct timespec start_time; From 981e4b77cb96ab277ea3b7a1e8aebf0e4589c032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Mar 2023 18:37:41 +0200 Subject: [PATCH 103/118] term: protect against integer overflow when accumulating scroll damage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When accumulating scroll damage, we check if the last scroll damage’s scrolling region, and type, matches the new/current scroll damage. If so, the number of lines in the last scroll damage is increased, instead of adding a new scroll damage instance to the list. If the scroll damage list isn’t consumed, this build up of scroll damage would eventually overflow. And, even if it didn’t overflow, it could become large enough, that when later used to calculate e.g. the affected surface area, while rendering a frame, would cause an overflow there instead. This patch fixes both issues by: a) do an overflow check before increasing the line count b) limit the line count to UINT16_MAX --- CHANGELOG.md | 1 + terminal.c | 17 +++++++++++------ terminal.h | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df098c41..30a34f01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,6 +138,7 @@ ([#1288][1288]). * Crash when application output scrolls very fast, e.g. `yes` ([#1305][1305]). +* Crash when application scrolls **many** lines (> ~2³¹). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 diff --git a/terminal.c b/terminal.c index 78ce4bc3..04153513 100644 --- a/terminal.c +++ b/terminal.c @@ -2252,15 +2252,20 @@ void term_damage_scroll(struct terminal *term, enum damage_type damage_type, struct scroll_region region, int lines) { - if (tll_length(term->grid->scroll_damage) > 0) { + if (likely(tll_length(term->grid->scroll_damage) > 0)) { struct damage *dmg = &tll_back(term->grid->scroll_damage); - if (dmg->type == damage_type && - dmg->region.start == region.start && - dmg->region.end == region.end) + if (likely( + dmg->type == damage_type && + dmg->region.start == region.start && + dmg->region.end == region.end)) { - dmg->lines += lines; - return; + /* Make sure we don’t overflow... */ + int new_line_count = (int)dmg->lines + lines; + if (likely(new_line_count <= UINT16_MAX)) { + dmg->lines = new_line_count; + return; + } } } struct damage dmg = { diff --git a/terminal.h b/terminal.h index 21236797..d2762a5a 100644 --- a/terminal.h +++ b/terminal.h @@ -96,7 +96,7 @@ enum damage_type {DAMAGE_SCROLL, DAMAGE_SCROLL_REVERSE, struct damage { enum damage_type type; struct scroll_region region; - int lines; + uint16_t lines; }; struct row_uri_range { From 27c52fb4e38278c381a8d2e58f239cec57249a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 31 Mar 2023 10:30:58 +0200 Subject: [PATCH 104/118] test: config: call FcIni() + FcFini() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the config options we’re testing result in calls to FontConfig APIs. Without calling FcIni()+FcFini(), we leak memory: Direct leak of 768 byte(s) in 3 object(s) allocated from: #0 0x7f7e95cbfa89 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:69 #1 0x7f7e95bd1fe5 (/usr/lib/libfontconfig.so.1+0x20fe5) Indirect leak of 96 byte(s) in 3 object(s) allocated from: #0 0x7f7e95cbf411 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77 #1 0x7f7e95bd63fd (/usr/lib/libfontconfig.so.1+0x253fd) Indirect leak of 19 byte(s) in 2 object(s) allocated from: #0 0x7f7e95c72faa in __interceptor_strdup /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:439 #1 0x7f7e95bd1898 in FcValueSave (/usr/lib/libfontconfig.so.1+0x20898) --- tests/test-config.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test-config.c b/tests/test-config.c index 6b44e9c2..4736a46b 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -1304,6 +1304,7 @@ test_section_tweak(void) int main(int argc, const char *const *argv) { + FcInit(); log_init(LOG_COLORIZE_AUTO, false, 0, LOG_CLASS_ERROR); test_section_main(); test_section_bell(); @@ -1325,5 +1326,6 @@ main(int argc, const char *const *argv) test_section_environment(); test_section_tweak(); log_deinit(); + FcFini(); return 0; } From a5dd00362735693faef2c11e7349a42a1a3e3593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 31 Mar 2023 10:41:17 +0200 Subject: [PATCH 105/118] changelog: remove trailing back-tick --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30a34f01..bea5c363 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -123,7 +123,7 @@ with a user-set line-height ([#1218][1218]). * Scaling factor not being correctly applied when converting pt-or-px config values (e.g. letter offsets, line height etc). -* Selection being stuck visually when `IL` and `DL`.` +* Selection being stuck visually when `IL` and `DL`. * URL underlines sometimes still being visible after exiting URL mode. * Text-bindings, and pipe-* bindings, with multiple key mappings causing a crash (double-free) on exit ([#1259][1259]). From 03b23ed6e5bd3b9bd0735d577d9ad722e1e40ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 31 Mar 2023 10:42:50 +0200 Subject: [PATCH 106/118] changeloge: remove bad escape char --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bea5c363..5fd3acf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -131,7 +131,7 @@ into the double-width glyph ([#1256][1256]). * Wayland protocol violation when ack:ing a configure event for an unmapped surface ([#1249][1249]). -* `xdg\_toplevel::set_min_size()` not being called. +* `xdg_toplevel::set_min_size()` not being called. * Key bindings with consumed modifiers masking other key bindings ([#1280][1280]). * Multi-character compose sequences with the kitty keyboard protocol From deb43c8dc3930954537e8294805aaa71c199d7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 31 Mar 2023 10:43:39 +0200 Subject: [PATCH 107/118] changelog: typo: now -> not --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fd3acf1..4f1da5c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -104,7 +104,7 @@ that does not allow Wayland buffer re-use (e.g. KDE/plasma) ([#1173][1173]) * Scrollback search matches not being highlighted correctly, on - compositors that does now allow Wayland buffer re-use + compositors that does not allow Wayland buffer re-use (e.g. KDE/plasma). * Nanosecs "overflow" when calculating timeout value for `resize-delay-ms` option. From e71e7f5cf6452e9f14dd93a72ed9afca98ea13b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 31 Mar 2023 11:34:04 +0200 Subject: [PATCH 108/118] =?UTF-8?q?input:=20kitty:=20don=E2=80=99t=20treat?= =?UTF-8?q?=20zero-length=20utf8/utf32=20strings=20as=20text?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a regression introduced in 3215d54f31c9e339598a34c9fa43f3dc3c5d1e42 Symptoms: e.g. arrow keys not working in vim/neovim --- input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.c b/input.c index b7f25670..7e5d204d 100644 --- a/input.c +++ b/input.c @@ -1125,7 +1125,7 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term, const uint8_t *const utf8 = ctx->utf8.buf; const size_t count = ctx->utf8.count; - bool is_text = utf32 != NULL && (effective & ~caps_num) == 0; + bool is_text = count > 0 && utf32 != NULL && (effective & ~caps_num) == 0; for (size_t i = 0; utf32[i] != U'\0'; i++) { if (!iswprint(utf32[i])) { is_text = false; From 0bc934070c01474e1196ee1964f59cc1c74040b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 31 Mar 2023 13:02:41 +0200 Subject: [PATCH 109/118] ci (woodpecker): do a second release build, using clang instead of gcc --- .woodpecker.yml | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 284da761..06631f89 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -33,7 +33,7 @@ pipeline: image: alpine:latest commands: - apk update - - apk add musl-dev linux-headers meson ninja gcc scdoc ncurses + - apk add musl-dev linux-headers meson ninja gcc clang scdoc ncurses - apk add libxkbcommon-dev pixman-dev freetype-dev fontconfig-dev harfbuzz-dev utf8proc-dev - apk add wayland-dev wayland-protocols - apk add git @@ -50,7 +50,7 @@ pipeline: - ./footclient --version - cd ../.. - # Release + # Release (gcc) - mkdir -p bld/release-x64 - cd bld/release-x64 - meson --buildtype=release -Db_pgo=generate -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../.. @@ -60,6 +60,16 @@ pipeline: - ./footclient --version - cd ../.. + # Release (clang) + - mkdir -p bld/release-x64-clang + - cd bld/release-x64-clang + - CC=clang meson --buildtype=release -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../.. + - ninja -v -k0 + - ninja -v test + - ./foot --version + - ./footclient --version + - cd ../.. + # no grapheme clustering - apk del harfbuzz harfbuzz-dev utf8proc utf8proc-dev - mkdir -p bld/debug @@ -80,7 +90,7 @@ pipeline: image: i386/alpine:latest commands: - apk update - - apk add musl-dev linux-headers meson ninja gcc scdoc ncurses + - apk add musl-dev linux-headers meson ninja gcc clang scdoc ncurses - apk add libxkbcommon-dev pixman-dev freetype-dev fontconfig-dev harfbuzz-dev utf8proc-dev - apk add wayland-dev wayland-protocols - apk add git @@ -97,7 +107,7 @@ pipeline: - ./footclient --version - cd ../.. - # Release + # Release (gcc) - mkdir -p bld/release-x86 - cd bld/release-x86 - meson --buildtype=release -Db_pgo=generate -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../.. @@ -106,3 +116,13 @@ pipeline: - ./foot --version - ./footclient --version - cd ../.. + + # Release (clang) + - mkdir -p bld/release-x86-clang + - cd bld/release-x86-clang + - CC=clang meson --buildtype=release -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../.. + - ninja -v -k0 + - ninja -v test + - ./foot --version + - ./footclient --version + - cd ../.. From f114068a468f6d6d39603b4ed26049de7b701842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 19 Jan 2023 19:52:57 +0100 Subject: [PATCH 110/118] csi: DECCOLM+DECSCLM: remove all support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don’t support neither 132 column mode, nor smooth scrolling. Thus it makes little sense to recognize these control condes. Note that while XTerm does support 132 columns, it is disabled by default. In this mode, XTerm also doesn’t trigger the side-effects (i.e. clearing the screen). Closes #1265 --- CHANGELOG.md | 2 ++ csi.c | 21 --------------------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f1da5c1..d50eff6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -139,6 +139,7 @@ * Crash when application output scrolls very fast, e.g. `yes` ([#1305][1305]). * Crash when application scrolls **many** lines (> ~2³¹). +* DECCOLM erasing the screen ([#1265][1265]). [1173]: https://codeberg.org/dnkl/foot/issues/1173 [1190]: https://codeberg.org/dnkl/foot/issues/1190 @@ -151,6 +152,7 @@ [1280]: https://codeberg.org/dnkl/foot/issues/1280 [1288]: https://codeberg.org/dnkl/foot/issues/1288 [1305]: https://codeberg.org/dnkl/foot/issues/1305 +[1265]: https://codeberg.org/dnkl/foot/issues/1265 ### Security diff --git a/csi.c b/csi.c index cef48d43..d22c1da5 100644 --- a/csi.c +++ b/csi.c @@ -276,21 +276,6 @@ decset_decrst(struct terminal *term, unsigned param, bool enable) enable ? CURSOR_KEYS_APPLICATION : CURSOR_KEYS_NORMAL; break; - case 3: - /* DECCOLM */ - if (enable) - LOG_WARN("unimplemented: 132 column mode (DECCOLM)"); - - term_erase(term, 0, 0, term->rows - 1, term->cols - 1); - term_cursor_home(term); - break; - - case 4: - /* DECSCLM - Smooth scroll */ - if (enable) - LOG_WARN("unimplemented: Smooth (Slow) Scroll (DECSCLM)"); - break; - case 5: /* DECSCNM */ term->reverse = enable; @@ -558,8 +543,6 @@ decrqm(const struct terminal *term, unsigned param) { switch (param) { case 1: return decrpm(term->cursor_keys_mode == CURSOR_KEYS_APPLICATION); - case 3: return DECRPM_PERMANENTLY_RESET; - case 4: return DECRPM_PERMANENTLY_RESET; case 5: return decrpm(term->reverse); case 6: return decrpm(term->origin); case 7: return decrpm(term->auto_margin); @@ -601,8 +584,6 @@ xtsave(struct terminal *term, unsigned param) { switch (param) { case 1: term->xtsave.application_cursor_keys = term->cursor_keys_mode == CURSOR_KEYS_APPLICATION; break; - case 3: break; - case 4: break; case 5: term->xtsave.reverse = term->reverse; break; case 6: term->xtsave.origin = term->origin; break; case 7: term->xtsave.auto_margin = term->auto_margin; break; @@ -644,8 +625,6 @@ xtrestore(struct terminal *term, unsigned param) bool enable; switch (param) { case 1: enable = term->xtsave.application_cursor_keys; break; - case 3: return; - case 4: return; case 5: enable = term->xtsave.reverse; break; case 6: enable = term->xtsave.origin; break; case 7: enable = term->xtsave.auto_margin; break; From ae81f5af4caaa8bbad666e028f6fde9c23e58b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 31 Mar 2023 10:36:43 +0200 Subject: [PATCH 111/118] terminfo: remove DECRST of DECCOLM+DECSCLM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We’ve never supported neither 132-column mode, nor smooth scrolling. But we _did_ recognize the escape sequences. We don’t, anymore. Thus it makes very little sense to include these escapes in any of our terminfo capabilities. So, remove them. --- CHANGELOG.md | 1 + foot.info | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d50eff6b..8517d163 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,7 @@ * When determining initial font size, do FontConfig config substitution if the user-provided font pattern has no {pixel}size option ([#1287][1287]). +* DECRST of DECCOLM and DECSCLM removed from terminfo. [1166]: https://codeberg.org/dnkl/foot/issues/1166 [1179]: https://codeberg.org/dnkl/foot/issues/1179 diff --git a/foot.info b/foot.info index 34b05f23..cf81d721 100644 --- a/foot.info +++ b/foot.info @@ -86,7 +86,7 @@ indn=\E[%p1%dS, initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, invis=\E[8m, - is2=\E[!p\E[?3;4l\E[4l\E>, + is2=\E[!p\E[4l\E>, kDC3=\E[3;3~, kDC4=\E[3;4~, kDC5=\E[3;5~, @@ -244,7 +244,7 @@ rmul=\E[24m, rmxx=\E[29m, rs1=\Ec, - rs2=\E[!p\E[?3;4l\E[4l\E>, + rs2=\E[!p\E[4l\E>, rv=\E\\[[0-9]+;[0-9]+;[0-9]+c, sc=\E7, setrgbb=\E[48\:2\:\:%p1%d\:%p2%d\:%p3%dm, From 862a003b5b68a08d7ddfc653c3b36aaa21839d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 3 Apr 2023 18:52:22 +0200 Subject: [PATCH 112/118] changelog: prepare for 1.14.0 --- CHANGELOG.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8517d163..846735d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -* [Unreleased](#unreleased) +* [1.14.0](#1-14-0) * [1.13.1](#1-13-1) * [1.13.0](#1-13-0) * [1.12.1](#1-12-1) @@ -41,7 +41,7 @@ * [1.2.0](#1-2-0) -## Unreleased +## 1.14.0 ### Added @@ -94,8 +94,6 @@ [1287]: https://codeberg.org/dnkl/foot/issues/1287 -### Deprecated -### Removed ### Fixed * Crash in `foot --server` on key press, after another `footclient` @@ -156,10 +154,25 @@ [1265]: https://codeberg.org/dnkl/foot/issues/1265 -### Security ### Contributors +* Alexey Sakovets +* Andrea Pappacoda +* Antoine Beaupré +* argosatcore * Craig Barnes +* EuCaue +* Grigory Kirillov +* Harri Nieminen +* Hugo Osvaldo Barrera +* jaroeichler +* Joakim Nohlgård +* Nick Hastings +* Soren A D +* Torsten Trautwein +* Vladimír Magyar +* woojiq +* Yorick Peterse ## 1.13.1 From ae6bbce6c2527db40177585cc3c3d797d68c104a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 3 Apr 2023 18:52:42 +0200 Subject: [PATCH 113/118] meson: bump version to 1.14.0 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 68c3bf19..6e7e7fcf 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('foot', 'c', - version: '1.13.1', + version: '1.14.0', license: 'MIT', meson_version: '>=0.58.0', default_options: [ From a858934c042a364110c9e663871722acdfc48aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 3 Apr 2023 18:57:50 +0200 Subject: [PATCH 114/118] =?UTF-8?q?changelog:=20add=20a=20new=20=E2=80=98u?= =?UTF-8?q?nreleased=E2=80=99=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 846735d5..74be88cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +* [Unreleased](#unreleased) * [1.14.0](#1-14-0) * [1.13.1](#1-13-1) * [1.13.0](#1-13-0) @@ -41,6 +42,16 @@ * [1.2.0](#1-2-0) +## Unreleased +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security +### Contributors + + ## 1.14.0 ### Added From 479b3c8ee1816ac8019c202398de9fc93bf109ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 5 Apr 2023 14:39:02 +0200 Subject: [PATCH 115/118] *.desktop: add StartupWMClass=foot At least Gnome needs this in order to link running instances of foot to their corresponding .desktop file, used e.g. when determining which icon to display for running applications. Closes #1317 --- CHANGELOG.md | 6 ++++++ org.codeberg.dnkl.foot-server.desktop | 1 + org.codeberg.dnkl.foot.desktop | 1 + org.codeberg.dnkl.footclient.desktop | 1 + 4 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74be88cd..8500195b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,12 @@ ### Deprecated ### Removed ### Fixed + +* Incorrect icon in dock and window switcher on Gnome ([#1317][1317]) + +[1317]: https://codeberg.org/dnkl/foot/issues/1317 + + ### Security ### Contributors diff --git a/org.codeberg.dnkl.foot-server.desktop b/org.codeberg.dnkl.foot-server.desktop index 6e8891c0..a40117c7 100644 --- a/org.codeberg.dnkl.foot-server.desktop +++ b/org.codeberg.dnkl.foot-server.desktop @@ -9,3 +9,4 @@ Keywords=shell;prompt;command;commandline; Name=Foot Server GenericName=Terminal Comment=A wayland native terminal emulator (server) +StartupWMClass=foot diff --git a/org.codeberg.dnkl.foot.desktop b/org.codeberg.dnkl.foot.desktop index f072568d..720d35a9 100644 --- a/org.codeberg.dnkl.foot.desktop +++ b/org.codeberg.dnkl.foot.desktop @@ -9,3 +9,4 @@ Keywords=shell;prompt;command;commandline; Name=Foot GenericName=Terminal Comment=A wayland native terminal emulator +StartupWMClass=foot diff --git a/org.codeberg.dnkl.footclient.desktop b/org.codeberg.dnkl.footclient.desktop index f82f282b..dc8bc5dc 100644 --- a/org.codeberg.dnkl.footclient.desktop +++ b/org.codeberg.dnkl.footclient.desktop @@ -9,3 +9,4 @@ Keywords=shell;prompt;command;commandline; Name=Foot Client GenericName=Terminal Comment=A wayland native terminal emulator (client) +StartupWMClass=foot From 98528da5e5d3715b2778b3a1dd643fdd6dc051e3 Mon Sep 17 00:00:00 2001 From: Vivian Szczepanski Date: Sat, 8 Apr 2023 10:58:27 -0400 Subject: [PATCH 116/118] meson: bump tllist dependency version to 1.1.0 The tll_sort() macro was added to tllist in version 1.1.0, and so building with a previous version causes a linking error. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 6e7e7fcf..a6892cc4 100644 --- a/meson.build +++ b/meson.build @@ -110,7 +110,7 @@ if utf8proc.found() add_project_arguments('-DFOOT_GRAPHEME_CLUSTERING=1', language: 'c') endif -tllist = dependency('tllist', version: '>=1.0.4', fallback: 'tllist') +tllist = dependency('tllist', version: '>=1.1.0', fallback: 'tllist') fcft = dependency('fcft', version: ['>=3.0.1', '<4.0.0'], fallback: 'fcft') wayland_protocols_datadir = wayland_protocols.get_variable('pkgdatadir') From e2baa6523875aaa13b6b7db80b7985978b8ee492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 12 Apr 2023 16:39:54 +0200 Subject: [PATCH 117/118] =?UTF-8?q?render:=20ensure=20scroll=20region?= =?UTF-8?q?=E2=80=99s=20endpoint=20is=20valid=20after=20a=20window=20resiz?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we had a non-empty bottom scroll region, and the window was resized to a smaller size, the scroll region was not reset correctly. This led to a crash when scrolling the screen content. Fix by making sure the scroll region’s endpoint is within range. --- CHANGELOG.md | 2 ++ render.c | 3 +-- terminal.c | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8500195b..ca98ed5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,8 @@ ### Fixed * Incorrect icon in dock and window switcher on Gnome ([#1317][1317]) +* Crash when scrolling after resizing the window with non-zero + scrolling regions. [1317]: https://codeberg.org/dnkl/foot/issues/1317 diff --git a/render.c b/render.c index f16898b4..d39c9489 100644 --- a/render.c +++ b/render.c @@ -4128,8 +4128,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) if (term->scroll_region.start >= term->rows) term->scroll_region.start = 0; - - if (term->scroll_region.end >= old_rows) + if (term->scroll_region.end > term->rows) term->scroll_region.end = term->rows; term->render.last_cursor.row = NULL; diff --git a/terminal.c b/terminal.c index 04153513..2e62fbb7 100644 --- a/terminal.c +++ b/terminal.c @@ -2716,13 +2716,13 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows erase_line(term, row); } - term_damage_scroll(term, DAMAGE_SCROLL, region, rows); - term->grid->cur_row = grid_row(term->grid, term->grid->cursor.point.row); - #if defined(_DEBUG) for (int r = 0; r < term->rows; r++) xassert(grid_row(term->grid, r) != NULL); #endif + + term_damage_scroll(term, DAMAGE_SCROLL, region, rows); + term->grid->cur_row = grid_row(term->grid, term->grid->cursor.point.row); } void From a2db3cdd5b3b6ce0b782b5ee51d174f4b4890f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 12 Apr 2023 18:09:41 +0200 Subject: [PATCH 118/118] render: regression: keep empty bottom scroll margin empty after resize --- render.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/render.c b/render.c index d39c9489..521c8b7f 100644 --- a/render.c +++ b/render.c @@ -4128,8 +4128,11 @@ maybe_resize(struct terminal *term, int width, int height, bool force) if (term->scroll_region.start >= term->rows) term->scroll_region.start = 0; - if (term->scroll_region.end > term->rows) + if (term->scroll_region.end > term->rows || + term->scroll_region.end >= old_rows) + { term->scroll_region.end = term->rows; + } term->render.last_cursor.row = NULL;