From b1950ac222f525f6763908ad57ff6d6399e061a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 24 Jul 2020 17:51:40 +0200 Subject: [PATCH 01/41] render: add code that calculates current position in scrollback --- render.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/render.c b/render.c index 80611d22..da6c2610 100644 --- a/render.c +++ b/render.c @@ -1287,6 +1287,50 @@ render_csd(struct terminal *term) render_csd_title(term); } +static void +render_scrollback_position(struct terminal *term) +{ +#if 0 + if (!term->conf->show_scrollback_position) + return; +#endif + + /* Find absolute row number of the scrollback start */ + int scrollback_start = term->grid->offset + term->rows; + while (term->grid->rows[scrollback_start & (term->grid->num_rows - 1)] == NULL) + scrollback_start++; + + /* Rebase viewport against scrollback start (so that 0 is at + * the beginning of the scrollback) */ + int rebased_view = term->grid->view - scrollback_start + term->grid->num_rows; + rebased_view &= term->grid->num_rows - 1; + + /* + * How far down in the scrollback we are. + * + * 0% -> at the beginning of the scrollback + * 100% -> at the bottom, i.e. where new lines are inserted + */ + int percentage __attribute__((unused)) = + rebased_view + term->rows == term->grid->num_rows + ? 100 + : 100 * rebased_view / term->grid->num_rows; + + int next_row_no = term->grid->view + term->rows; + next_row_no &= term->grid->num_rows - 1; + + /* Are we at the end of the scrollback? */ + bool at_bottom = rebased_view + term->rows == term->grid->num_rows || + term->grid->rows[next_row_no] == NULL; + + LOG_DBG("scrollback position: %d/%d (%d%%), at-bottom: %d", + rebased_view, term->grid->num_rows, percentage, at_bottom); + + if (!at_bottom) { + /* TODO: insert rendering code here */ + } +} + static void frame_callback( void *data, struct wl_callback *wl_callback, uint32_t callback_data); @@ -1498,6 +1542,8 @@ grid_render(struct terminal *term) term->window->surface, 0, 0, term->width, term->height); } + render_scrollback_position(term); + assert(term->grid->offset >= 0 && term->grid->offset < term->grid->num_rows); assert(term->grid->view >= 0 && term->grid->view < term->grid->num_rows); From 2c6f7adc17832c77b2353338b0c76c8a19f4112b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 24 Jul 2020 18:20:26 +0200 Subject: [PATCH 02/41] config: add 'show-scrollback-position' option to footrc --- config.c | 4 ++++ config.h | 1 + doc/foot.5.scd | 4 ++++ render.c | 2 -- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/config.c b/config.c index 283a72ea..9666da61 100644 --- a/config.c +++ b/config.c @@ -291,6 +291,9 @@ parse_section_main(const char *key, const char *value, struct config *conf, conf->scrollback_lines = lines; } + else if (strcmp(key, "show-scrollback-position") == 0) + conf->show_scrollback_position = str_to_bool(value); + else { LOG_ERR("%s:%u: invalid key: %s", path, lineno, key); return false; @@ -918,6 +921,7 @@ config_load(struct config *conf, const char *conf_path) .startup_mode = STARTUP_WINDOWED, .fonts = tll_init(), .scrollback_lines = 1000, + .show_scrollback_position = true, .colors = { .fg = default_foreground, diff --git a/config.h b/config.h index 2b43b806..c21e1160 100644 --- a/config.h +++ b/config.h @@ -40,6 +40,7 @@ struct config { tll(struct config_font) fonts; int scrollback_lines; + bool show_scrollback_position; struct { uint32_t fg; diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 92ac7c01..fd5a5d42 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -68,6 +68,10 @@ in this order: *scrollback* Number of scrollback lines. Default: _1000_. +*show-scrollback-position* + Boolean. Enables a position indicator when the viewport is not at + the bottom of the scrollback history. Default: _yes_. + *workers* Number of threads to use for rendering. Set to 0 to disable multithreading. Default: the number of available logical CPUs diff --git a/render.c b/render.c index da6c2610..6611fbb9 100644 --- a/render.c +++ b/render.c @@ -1290,10 +1290,8 @@ render_csd(struct terminal *term) static void render_scrollback_position(struct terminal *term) { -#if 0 if (!term->conf->show_scrollback_position) return; -#endif /* Find absolute row number of the scrollback start */ int scrollback_start = term->grid->offset + term->rows; From e94506362028b57fa5d2c77f73a152a47cc06768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 24 Jul 2020 18:26:44 +0200 Subject: [PATCH 03/41] config: rename show-scrollback-position to scrollback-indicator --- config.c | 6 +++--- config.h | 2 +- doc/foot.5.scd | 2 +- render.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config.c b/config.c index 9666da61..e7ba74b2 100644 --- a/config.c +++ b/config.c @@ -291,8 +291,8 @@ parse_section_main(const char *key, const char *value, struct config *conf, conf->scrollback_lines = lines; } - else if (strcmp(key, "show-scrollback-position") == 0) - conf->show_scrollback_position = str_to_bool(value); + else if (strcmp(key, "scrollback-indicator") == 0) + conf->scrollback_indicator = str_to_bool(value); else { LOG_ERR("%s:%u: invalid key: %s", path, lineno, key); @@ -921,7 +921,7 @@ config_load(struct config *conf, const char *conf_path) .startup_mode = STARTUP_WINDOWED, .fonts = tll_init(), .scrollback_lines = 1000, - .show_scrollback_position = true, + .scrollback_indicator = true, .colors = { .fg = default_foreground, diff --git a/config.h b/config.h index c21e1160..f0f077be 100644 --- a/config.h +++ b/config.h @@ -40,7 +40,7 @@ struct config { tll(struct config_font) fonts; int scrollback_lines; - bool show_scrollback_position; + bool scrollback_indicator; struct { uint32_t fg; diff --git a/doc/foot.5.scd b/doc/foot.5.scd index fd5a5d42..1f71a8d3 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -68,7 +68,7 @@ in this order: *scrollback* Number of scrollback lines. Default: _1000_. -*show-scrollback-position* +*scrollback-indicator* Boolean. Enables a position indicator when the viewport is not at the bottom of the scrollback history. Default: _yes_. diff --git a/render.c b/render.c index 6611fbb9..d5cdb8dc 100644 --- a/render.c +++ b/render.c @@ -1290,7 +1290,7 @@ render_csd(struct terminal *term) static void render_scrollback_position(struct terminal *term) { - if (!term->conf->show_scrollback_position) + if (!term->conf->scrollback_indicator) return; /* Find absolute row number of the scrollback start */ From 5b868fd0c94af61e62a28a80a4bd337f9cbb25b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 24 Jul 2020 18:34:19 +0200 Subject: [PATCH 04/41] config: add 'scrollback-indicator-format' option The value of this option must be either 'percent', or 'line', and determines _how_ we render the scrollback indicator. --- config.c | 14 ++++++++++++++ config.h | 1 + doc/foot.5.scd | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/config.c b/config.c index e7ba74b2..332fd11a 100644 --- a/config.c +++ b/config.c @@ -294,6 +294,19 @@ parse_section_main(const char *key, const char *value, struct config *conf, else if (strcmp(key, "scrollback-indicator") == 0) conf->scrollback_indicator = str_to_bool(value); + else if (strcmp(key, "scrollback-indicator-format") == 0) { + if (strcmp(value, "percent") == 0) + conf->scrollback_indicator_format = SCROLLBACK_INDICATOR_PERCENT; + else if (strcmp(value, "line") == 0) + conf->scrollback_indicator_format = SCROLLBACK_INDICATOR_LINENO; + else { + LOG_ERR("%s:%d: 'scrollback-indicator-format must be one " + "of 'percent' or 'line', not %s", + path, lineno, value); + return false; + } + } + else { LOG_ERR("%s:%u: invalid key: %s", path, lineno, key); return false; @@ -922,6 +935,7 @@ config_load(struct config *conf, const char *conf_path) .fonts = tll_init(), .scrollback_lines = 1000, .scrollback_indicator = true, + .scrollback_indicator_format = SCROLLBACK_INDICATOR_PERCENT, .colors = { .fg = default_foreground, diff --git a/config.h b/config.h index f0f077be..109eecb8 100644 --- a/config.h +++ b/config.h @@ -41,6 +41,7 @@ struct config { int scrollback_lines; bool scrollback_indicator; + enum {SCROLLBACK_INDICATOR_PERCENT, SCROLLBACK_INDICATOR_LINENO} scrollback_indicator_format; struct { uint32_t fg; diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 1f71a8d3..485886fa 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -72,6 +72,11 @@ in this order: Boolean. Enables a position indicator when the viewport is not at the bottom of the scrollback history. Default: _yes_. +*scrollback-indicator-format* + Which format to use when displaying the scrollback position + indicator. Either _percent_ or _line_. This option is ignored if + *scrollback-indicator=no*. Default: _percent_. + *workers* Number of threads to use for rendering. Set to 0 to disable multithreading. Default: the number of available logical CPUs From c4679e474e0546ee8dad6e122c226ece85bdb134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 14:31:45 +0200 Subject: [PATCH 05/41] config: rename scrollback-indicator to scrollback-indicator-style And turn it from a boolean to an enum. It can be set to: * `none` - disables the indicator * `static` - always rendered near the top of the window * `moving` - position reflects the scrollback position --- config.c | 37 ++++++++++++++++++++++++++----------- config.h | 19 ++++++++++++++++--- doc/foot.5.scd | 12 ++++++++---- footrc | 2 ++ render.c | 2 +- terminal.c | 2 +- 6 files changed, 54 insertions(+), 20 deletions(-) diff --git a/config.c b/config.c index 332fd11a..7c4c9d9f 100644 --- a/config.c +++ b/config.c @@ -288,21 +288,33 @@ parse_section_main(const char *key, const char *value, struct config *conf, LOG_ERR("%s:%d: expected an integer: %s", path, lineno, value); return false; } - conf->scrollback_lines = lines; + conf->scrollback.lines = lines; } - else if (strcmp(key, "scrollback-indicator") == 0) - conf->scrollback_indicator = str_to_bool(value); + else if (strcmp(key, "scrollback-indicator") == 0) { + if (strcmp(value, "none") == 0) + conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_NONE; + else if (strcmp(value, "static") == 0) + conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_STATIC; + else if (strcmp(value, "moving") == 0) + conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_MOVING; + else { + LOG_ERR("%s:%d: scrollback-indicator-style must be one of " + "'none', 'static' or 'moving'", + path, lineno); + return false; + } + } else if (strcmp(key, "scrollback-indicator-format") == 0) { if (strcmp(value, "percent") == 0) - conf->scrollback_indicator_format = SCROLLBACK_INDICATOR_PERCENT; + conf->scrollback.indicator.format = SCROLLBACK_INDICATOR_FORMAT_PERCENT; else if (strcmp(value, "line") == 0) - conf->scrollback_indicator_format = SCROLLBACK_INDICATOR_LINENO; + conf->scrollback.indicator.format = SCROLLBACK_INDICATOR_FORMAT_LINENO; else { LOG_ERR("%s:%d: 'scrollback-indicator-format must be one " - "of 'percent' or 'line', not %s", - path, lineno, value); + "of 'percent' or 'line'", + path, lineno); return false; } } @@ -933,10 +945,13 @@ config_load(struct config *conf, const char *conf_path) .pad_y = 2, .startup_mode = STARTUP_WINDOWED, .fonts = tll_init(), - .scrollback_lines = 1000, - .scrollback_indicator = true, - .scrollback_indicator_format = SCROLLBACK_INDICATOR_PERCENT, - + .scrollback = { + .lines = 1000, + .indicator = { + .style = SCROLLBACK_INDICATOR_STYLE_MOVING, + .format = SCROLLBACK_INDICATOR_FORMAT_PERCENT, + }, + }, .colors = { .fg = default_foreground, .bg = default_background, diff --git a/config.h b/config.h index 109eecb8..9ff83b77 100644 --- a/config.h +++ b/config.h @@ -39,9 +39,22 @@ struct config { tll(struct config_font) fonts; - int scrollback_lines; - bool scrollback_indicator; - enum {SCROLLBACK_INDICATOR_PERCENT, SCROLLBACK_INDICATOR_LINENO} scrollback_indicator_format; + struct { + int lines; + + struct { + enum { + SCROLLBACK_INDICATOR_STYLE_NONE, + SCROLLBACK_INDICATOR_STYLE_STATIC, + SCROLLBACK_INDICATOR_STYLE_MOVING + } style; + + enum { + SCROLLBACK_INDICATOR_FORMAT_PERCENT, + SCROLLBACK_INDICATOR_FORMAT_LINENO + } format; + } indicator; + } scrollback; struct { uint32_t fg; diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 485886fa..9813741c 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -68,14 +68,18 @@ in this order: *scrollback* Number of scrollback lines. Default: _1000_. -*scrollback-indicator* - Boolean. Enables a position indicator when the viewport is not at - the bottom of the scrollback history. Default: _yes_. +*scrollback-indicator-style* + Configures the style of the scrollback position indicator. One of + *none*, *static* or *moving*. *none* disables the indicator + completely. *static* always renders the indicator near the top at + the window, and *moving* renders the indicator at the position + corresponding to the current scrollback position. Default: + _moving_. *scrollback-indicator-format* Which format to use when displaying the scrollback position indicator. Either _percent_ or _line_. This option is ignored if - *scrollback-indicator=no*. Default: _percent_. + *scrollback-indicator-style=none*. Default: _percent_. *workers* Number of threads to use for rendering. Set to 0 to disable diff --git a/footrc b/footrc index 624c688b..911ebb28 100644 --- a/footrc +++ b/footrc @@ -2,6 +2,8 @@ # font=monospace # scrollback=1000 +# scrollback-indicator-style=moving +# scrollback-indicator-format=percent # geometry=700x500 # pad=2x2 # initial-window-mode=windowed diff --git a/render.c b/render.c index d5cdb8dc..bab87cf4 100644 --- a/render.c +++ b/render.c @@ -1290,7 +1290,7 @@ render_csd(struct terminal *term) static void render_scrollback_position(struct terminal *term) { - if (!term->conf->scrollback_indicator) + if (term->conf->scrollback.indicator.style == SCROLLBACK_INDICATOR_STYLE_NONE) return; /* Find absolute row number of the scrollback start */ diff --git a/terminal.c b/terminal.c index 86672f06..1e355fe3 100644 --- a/terminal.c +++ b/terminal.c @@ -909,7 +909,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .tab_stops = tll_init(), .wl = wayl, .render = { - .scrollback_lines = conf->scrollback_lines, + .scrollback_lines = conf->scrollback.lines, .app_sync_updates.timer_fd = app_sync_updates_fd, .workers = { .count = conf->render_worker_count, From e3be2cbd6f62baaa81dcae62b24731668ac764b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 14:38:36 +0200 Subject: [PATCH 06/41] config: rename scrollback-indicator-style value 'moving' to 'relative' --- config.c | 4 ++-- config.h | 2 +- doc/foot.5.scd | 6 +++--- footrc | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/config.c b/config.c index 7c4c9d9f..59b824b8 100644 --- a/config.c +++ b/config.c @@ -297,7 +297,7 @@ parse_section_main(const char *key, const char *value, struct config *conf, else if (strcmp(value, "static") == 0) conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_STATIC; else if (strcmp(value, "moving") == 0) - conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_MOVING; + conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_RELATIVE; else { LOG_ERR("%s:%d: scrollback-indicator-style must be one of " "'none', 'static' or 'moving'", @@ -948,7 +948,7 @@ config_load(struct config *conf, const char *conf_path) .scrollback = { .lines = 1000, .indicator = { - .style = SCROLLBACK_INDICATOR_STYLE_MOVING, + .style = SCROLLBACK_INDICATOR_STYLE_RELATIVE, .format = SCROLLBACK_INDICATOR_FORMAT_PERCENT, }, }, diff --git a/config.h b/config.h index 9ff83b77..030bfc88 100644 --- a/config.h +++ b/config.h @@ -46,7 +46,7 @@ struct config { enum { SCROLLBACK_INDICATOR_STYLE_NONE, SCROLLBACK_INDICATOR_STYLE_STATIC, - SCROLLBACK_INDICATOR_STYLE_MOVING + SCROLLBACK_INDICATOR_STYLE_RELATIVE } style; enum { diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 9813741c..496042b3 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -70,11 +70,11 @@ in this order: *scrollback-indicator-style* Configures the style of the scrollback position indicator. One of - *none*, *static* or *moving*. *none* disables the indicator + *none*, *static* or *relative*. *none* disables the indicator completely. *static* always renders the indicator near the top at - the window, and *moving* renders the indicator at the position + the window, and *relative* renders the indicator at the position corresponding to the current scrollback position. Default: - _moving_. + _relative_. *scrollback-indicator-format* Which format to use when displaying the scrollback position diff --git a/footrc b/footrc index 911ebb28..c2ee52e7 100644 --- a/footrc +++ b/footrc @@ -2,7 +2,7 @@ # font=monospace # scrollback=1000 -# scrollback-indicator-style=moving +# scrollback-indicator-style=relative # scrollback-indicator-format=percent # geometry=700x500 # pad=2x2 From 9edd71a741a3aeff89fe04f51582214d69bbde5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 14:40:46 +0200 Subject: [PATCH 07/41] config: rename scrollback-indicator-style value 'static' to 'fixed' --- config.c | 6 +++--- config.h | 2 +- doc/foot.5.scd | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config.c b/config.c index 59b824b8..b6af1d26 100644 --- a/config.c +++ b/config.c @@ -294,9 +294,9 @@ parse_section_main(const char *key, const char *value, struct config *conf, else if (strcmp(key, "scrollback-indicator") == 0) { if (strcmp(value, "none") == 0) conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_NONE; - else if (strcmp(value, "static") == 0) - conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_STATIC; - else if (strcmp(value, "moving") == 0) + else if (strcmp(value, "fixed") == 0) + conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_FIXED; + else if (strcmp(value, "relative") == 0) conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_RELATIVE; else { LOG_ERR("%s:%d: scrollback-indicator-style must be one of " diff --git a/config.h b/config.h index 030bfc88..57701606 100644 --- a/config.h +++ b/config.h @@ -45,7 +45,7 @@ struct config { struct { enum { SCROLLBACK_INDICATOR_STYLE_NONE, - SCROLLBACK_INDICATOR_STYLE_STATIC, + SCROLLBACK_INDICATOR_STYLE_FIXED, SCROLLBACK_INDICATOR_STYLE_RELATIVE } style; diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 496042b3..573eb313 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -70,8 +70,8 @@ in this order: *scrollback-indicator-style* Configures the style of the scrollback position indicator. One of - *none*, *static* or *relative*. *none* disables the indicator - completely. *static* always renders the indicator near the top at + *none*, *fixed* or *relative*. *none* disables the indicator + completely. *fixed* always renders the indicator near the top at the window, and *relative* renders the indicator at the position corresponding to the current scrollback position. Default: _relative_. From be7d0a5615fafc81a0f88c45bc2e670339960e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 09:43:58 +0200 Subject: [PATCH 08/41] config: fix key check for 'scrollback-indicator-style' --- config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.c b/config.c index b6af1d26..18c88228 100644 --- a/config.c +++ b/config.c @@ -291,7 +291,7 @@ parse_section_main(const char *key, const char *value, struct config *conf, conf->scrollback.lines = lines; } - else if (strcmp(key, "scrollback-indicator") == 0) { + else if (strcmp(key, "scrollback-indicator-style") == 0) { if (strcmp(value, "none") == 0) conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_NONE; else if (strcmp(value, "fixed") == 0) From d180de00a9dab2ea2a8dbd9b48ab0e98f5595b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 09:44:16 +0200 Subject: [PATCH 09/41] config: fix error message for 'scrollback-indicator-style' --- config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.c b/config.c index 18c88228..f87eb67f 100644 --- a/config.c +++ b/config.c @@ -300,7 +300,7 @@ parse_section_main(const char *key, const char *value, struct config *conf, conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_RELATIVE; else { LOG_ERR("%s:%d: scrollback-indicator-style must be one of " - "'none', 'static' or 'moving'", + "'none', 'fixed' or 'moving'", path, lineno); return false; } From a39c490d9b1d82700dcd48cc9ac28d58051197f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 10:00:21 +0200 Subject: [PATCH 10/41] shm: add shm_cookie_scrollback_indicator() --- shm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shm.h b/shm.h index 4c8e9506..0bfb3839 100644 --- a/shm.h +++ b/shm.h @@ -49,4 +49,5 @@ void shm_purge(struct wl_shm *shm, unsigned long cookie); struct terminal; static inline unsigned long shm_cookie_grid(const struct terminal *term) { return (unsigned long)((uintptr_t)term + 0); } static inline unsigned long shm_cookie_search(const struct terminal *term) { return (unsigned long)((uintptr_t)term + 1); } -static inline unsigned long shm_cookie_csd(const struct terminal *term, int n) { return (unsigned long)((uintptr_t)term + 2 + (n)); } +static inline unsigned long shm_cookie_scrollback_indicator(const struct terminal *term) { return (unsigned long)(uintptr_t)term + 2; } +static inline unsigned long shm_cookie_csd(const struct terminal *term, int n) { return (unsigned long)((uintptr_t)term + 3 + (n)); } From 2815c1c0764cbc79625aa9c6623601d2188e0500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 10:00:50 +0200 Subject: [PATCH 11/41] wayland: add scrollback indicator surface + sub-surface to wl_window --- wayland.c | 9 +++++++++ wayland.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/wayland.c b/wayland.c index 70d5e0f1..66f2c3b3 100644 --- a/wayland.c +++ b/wayland.c @@ -1203,6 +1203,11 @@ wayl_win_destroy(struct wl_window *win) * nor mouse focus). */ + if (win->scrollback_indicator_surface != NULL) { + wl_surface_attach(win->scrollback_indicator_surface, NULL, 0, 0); + wl_surface_commit(win->scrollback_indicator_surface); + } + /* Scrollback search */ if (win->search_surface != NULL) { wl_surface_attach(win->search_surface, NULL, 0, 0); @@ -1227,6 +1232,10 @@ wayl_win_destroy(struct wl_window *win) tll_free(win->on_outputs); csd_destroy(win); + if (win->scrollback_indicator_sub_surface != NULL) + wl_subsurface_destroy(win->scrollback_indicator_sub_surface); + if (win->scrollback_indicator_surface != NULL) + wl_surface_destroy(win->scrollback_indicator_surface); if (win->search_sub_surface != NULL) wl_subsurface_destroy(win->search_sub_surface); if (win->search_surface != NULL) diff --git a/wayland.h b/wayland.h index dbf63c1b..e67d514a 100644 --- a/wayland.h +++ b/wayland.h @@ -273,6 +273,9 @@ struct wl_window { struct wl_surface *search_surface; struct wl_subsurface *search_sub_surface; + struct wl_surface *scrollback_indicator_surface; + struct wl_subsurface *scrollback_indicator_sub_surface; + struct wl_callback *frame_callback; tll(const struct monitor *) on_outputs; /* Outputs we're mapped on */ From c2362c10f133c707101302249763e5c66d5c8653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 10:01:05 +0200 Subject: [PATCH 12/41] render: search: fix subpixel argument to fcft_glyph_rasterize() --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index bab87cf4..ffab85ab 100644 --- a/render.c +++ b/render.c @@ -1660,7 +1660,7 @@ render_search_box(struct terminal *term) draw_bar(term, buf->pix[0], font, &fg, x, y); const struct fcft_glyph *glyph = fcft_glyph_rasterize( - font, term->search.buf[i], true); + font, term->search.buf[i], term->font_subpixel); if (glyph == NULL) continue; From 67758a7cb7207582671d223730123a63c0231642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 10:01:26 +0200 Subject: [PATCH 13/41] render: scrollback indicator: wip: implement 'fixed:percent' indicator When scrollback indicator has been enabled, and the viewport isn't at the bottom, we now render a *static* indicator with the position in percent. We use the color scheme's blue color as background, and it's white color as foreground. This is subject to change... Should maybe be configurable as well. The Wayland surface + sub-surface are instantiated on-demand, and automatically destroyed when no longer used. --- render.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 10 deletions(-) diff --git a/render.c b/render.c index ffab85ab..a64654f2 100644 --- a/render.c +++ b/render.c @@ -1293,6 +1293,53 @@ render_scrollback_position(struct terminal *term) if (term->conf->scrollback.indicator.style == SCROLLBACK_INDICATOR_STYLE_NONE) return; + struct wayland *wayl = term->wl; + struct wl_window *win = term->window; + + if (term->grid->view == term->grid->offset) { + if (win->scrollback_indicator_surface != NULL) { + wl_subsurface_destroy(win->scrollback_indicator_sub_surface); + wl_surface_destroy(win->scrollback_indicator_surface); + + win->scrollback_indicator_surface = NULL; + win->scrollback_indicator_sub_surface = NULL; + + LOG_INFO("destroyed indicator surfaces"); + } + return; + } + + if (win->scrollback_indicator_surface == NULL) { + win->scrollback_indicator_surface + = wl_compositor_create_surface(wayl->compositor); + + if (win->scrollback_indicator_surface == NULL) { + LOG_ERR("failed to create scrollback indicator surface"); + return; + } + + wl_surface_set_user_data(win->scrollback_indicator_surface, win); + + term->window->scrollback_indicator_sub_surface + = wl_subcompositor_get_subsurface( + wayl->sub_compositor, + win->scrollback_indicator_surface, + win->surface); + + if (win->scrollback_indicator_sub_surface == NULL) { + LOG_ERR("failed to create scrollback indicator sub-surface"); + wl_surface_destroy(win->scrollback_indicator_surface); + win->scrollback_indicator_surface = NULL; + return; + } + + wl_subsurface_set_sync(win->scrollback_indicator_sub_surface); + LOG_INFO("instantiated indicator surfaces"); + } + + assert(win->scrollback_indicator_surface != NULL); + assert(win->scrollback_indicator_sub_surface != NULL); + /* Find absolute row number of the scrollback start */ int scrollback_start = term->grid->offset + term->rows; while (term->grid->rows[scrollback_start & (term->grid->num_rows - 1)] == NULL) @@ -1309,24 +1356,67 @@ render_scrollback_position(struct terminal *term) * 0% -> at the beginning of the scrollback * 100% -> at the bottom, i.e. where new lines are inserted */ - int percentage __attribute__((unused)) = + int percentage = rebased_view + term->rows == term->grid->num_rows ? 100 : 100 * rebased_view / term->grid->num_rows; - int next_row_no = term->grid->view + term->rows; - next_row_no &= term->grid->num_rows - 1; + const int scale = term->scale; + const int margin = 3 * scale; + const int width = 2 * margin + 3 * term->cell_width; /* TODO: this is percent only */ + const int height = 2 * margin + term->cell_height; - /* Are we at the end of the scrollback? */ - bool at_bottom = rebased_view + term->rows == term->grid->num_rows || - term->grid->rows[next_row_no] == NULL; + unsigned long cookie = shm_cookie_scrollback_indicator(term); + struct buffer *buf = shm_get_buffer( + term->wl->shm, width, height, cookie, false, 1); - LOG_DBG("scrollback position: %d/%d (%d%%), at-bottom: %d", - rebased_view, term->grid->num_rows, percentage, at_bottom); + pixman_color_t bg = color_hex_to_pixman(term->colors.table[4]); + pixman_image_fill_rectangles( + PIXMAN_OP_SRC, buf->pix[0], &bg, 1, + &(pixman_rectangle16_t){0, 0, width, height}); - if (!at_bottom) { - /* TODO: insert rendering code here */ + struct fcft_font *font = term->fonts[0]; + pixman_color_t fg = color_hex_to_pixman(term->colors.table[7]); + + wchar_t text[64]; + swprintf(text, sizeof(text) / sizeof(text[0]), L"%d%%", percentage); + + unsigned x = width - margin - wcslen(text) * term->cell_width; + const unsigned y = margin; + + for (size_t i = 0; i < wcslen(text); i++) { + const struct fcft_glyph *glyph = fcft_glyph_rasterize( + font, text[i], term->font_subpixel); + + if (glyph == NULL) + continue; + + pixman_image_t *src = pixman_image_create_solid_fill(&fg); + pixman_image_composite32( + PIXMAN_OP_OVER, src, glyph->pix, buf->pix[0], 0, 0, 0, 0, + x + glyph->x, y + font_baseline(term) - glyph->y, + glyph->width, glyph->height); + pixman_image_unref(src); + + x += term->cell_width; } + + wl_subsurface_set_position( + win->scrollback_indicator_sub_surface, + (term->width - term->margins.right - width) / scale, + term->margins.top / scale + term->cell_height); + wl_surface_attach(win->scrollback_indicator_surface, buf->wl_buf, 0, 0); + wl_surface_damage_buffer(win->scrollback_indicator_surface, 0, 0, width, height); + wl_surface_set_buffer_scale(win->scrollback_indicator_surface, scale); + + struct wl_region *region = wl_compositor_create_region(wayl->compositor); + if (region != NULL) { + wl_region_add(region, 0, 0, width, height); + wl_surface_set_opaque_region(win->scrollback_indicator_surface, region); + wl_region_destroy(region); + } + + wl_surface_commit(win->scrollback_indicator_surface); } static void frame_callback( From 2e519ed5b6f94940f7c70b7eba42b68ccf5c18a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 10:18:05 +0200 Subject: [PATCH 14/41] render: scrollback indicator: implement 'relative' and 'line' variants We now implement all combinations of 'scrollback-indicator-style' and 'scrollback-indicator-format'. --- render.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/render.c b/render.c index a64654f2..1d21a615 100644 --- a/render.c +++ b/render.c @@ -1303,8 +1303,6 @@ render_scrollback_position(struct terminal *term) win->scrollback_indicator_surface = NULL; win->scrollback_indicator_sub_surface = NULL; - - LOG_INFO("destroyed indicator surfaces"); } return; } @@ -1334,7 +1332,6 @@ render_scrollback_position(struct terminal *term) } wl_subsurface_set_sync(win->scrollback_indicator_sub_surface); - LOG_INFO("instantiated indicator surfaces"); } assert(win->scrollback_indicator_surface != NULL); @@ -1356,14 +1353,30 @@ render_scrollback_position(struct terminal *term) * 0% -> at the beginning of the scrollback * 100% -> at the bottom, i.e. where new lines are inserted */ - int percentage = + unsigned percent = rebased_view + term->rows == term->grid->num_rows ? 100 : 100 * rebased_view / term->grid->num_rows; + wchar_t text[64]; + int cell_count; + + /* *What* to render */ + switch (term->conf->scrollback.indicator.format) { + case SCROLLBACK_INDICATOR_FORMAT_PERCENT: + swprintf(text, sizeof(text) / sizeof(text[0]), L"%u%%", percent); + cell_count = 3; + break; + + case SCROLLBACK_INDICATOR_FORMAT_LINENO: + swprintf(text, sizeof(text) / sizeof(text[0]), L"%d", rebased_view + 1); + cell_count = 1 + (int)log10(term->grid->num_rows); + break; + } + const int scale = term->scale; const int margin = 3 * scale; - const int width = 2 * margin + 3 * term->cell_width; /* TODO: this is percent only */ + const int width = 2 * margin + cell_count * term->cell_width; const int height = 2 * margin + term->cell_height; unsigned long cookie = shm_cookie_scrollback_indicator(term); @@ -1378,9 +1391,7 @@ render_scrollback_position(struct terminal *term) struct fcft_font *font = term->fonts[0]; pixman_color_t fg = color_hex_to_pixman(term->colors.table[7]); - wchar_t text[64]; - swprintf(text, sizeof(text) / sizeof(text[0]), L"%d%%", percentage); - + /* Sub-surface relative coordinates */ unsigned x = width - margin - wcslen(text) * term->cell_width; const unsigned y = margin; @@ -1401,10 +1412,31 @@ render_scrollback_position(struct terminal *term) x += term->cell_width; } + /* *Where* to render - parent relative coordinates */ + int surf_top = 0; + switch (term->conf->scrollback.indicator.style) { + case SCROLLBACK_INDICATOR_STYLE_NONE: + assert(false); + return; + + case SCROLLBACK_INDICATOR_STYLE_FIXED: + surf_top = margin + term->cell_height; + break; + + case SCROLLBACK_INDICATOR_STYLE_RELATIVE: { + int lines = term->rows - 2; /* Avoid using first and last row */ + assert(lines > 0); + + int on_line = 1 + percent * lines / 100; + surf_top = margin + on_line * term->cell_height; + break; + } + } + wl_subsurface_set_position( win->scrollback_indicator_sub_surface, (term->width - term->margins.right - width) / scale, - term->margins.top / scale + term->cell_height); + surf_top / scale); wl_surface_attach(win->scrollback_indicator_surface, buf->wl_buf, 0, 0); wl_surface_damage_buffer(win->scrollback_indicator_surface, 0, 0, width, height); wl_surface_set_buffer_scale(win->scrollback_indicator_surface, scale); From 9a9e876d6e41da21eb3fdfc385135c8a94ce1183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 10:42:38 +0200 Subject: [PATCH 15/41] render: scrollback indicator: use black on bright blue --- render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render.c b/render.c index 1d21a615..55213408 100644 --- a/render.c +++ b/render.c @@ -1383,13 +1383,13 @@ render_scrollback_position(struct terminal *term) struct buffer *buf = shm_get_buffer( term->wl->shm, width, height, cookie, false, 1); - pixman_color_t bg = color_hex_to_pixman(term->colors.table[4]); + pixman_color_t bg = color_hex_to_pixman(term->colors.table[8 + 4]); pixman_image_fill_rectangles( PIXMAN_OP_SRC, buf->pix[0], &bg, 1, &(pixman_rectangle16_t){0, 0, width, height}); struct fcft_font *font = term->fonts[0]; - pixman_color_t fg = color_hex_to_pixman(term->colors.table[7]); + pixman_color_t fg = color_hex_to_pixman(term->colors.table[0]); /* Sub-surface relative coordinates */ unsigned x = width - margin - wcslen(text) * term->cell_width; From 50d116dcb9183047899d93095117632c669d5f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 11:39:02 +0200 Subject: [PATCH 16/41] config: scrollback-indicator-format: percent -> percentage --- config.c | 14 ++++++++------ config.h | 2 +- doc/foot.5.scd | 4 ++-- footrc | 2 +- render.c | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/config.c b/config.c index f87eb67f..2b989d62 100644 --- a/config.c +++ b/config.c @@ -307,11 +307,13 @@ parse_section_main(const char *key, const char *value, struct config *conf, } else if (strcmp(key, "scrollback-indicator-format") == 0) { - if (strcmp(value, "percent") == 0) - conf->scrollback.indicator.format = SCROLLBACK_INDICATOR_FORMAT_PERCENT; - else if (strcmp(value, "line") == 0) - conf->scrollback.indicator.format = SCROLLBACK_INDICATOR_FORMAT_LINENO; - else { + if (strcmp(value, "percent") == 0) { + conf->scrollback.indicator.format + = SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE; + } else if (strcmp(value, "line") == 0) { + conf->scrollback.indicator.format + = SCROLLBACK_INDICATOR_FORMAT_LINENO; + } else { LOG_ERR("%s:%d: 'scrollback-indicator-format must be one " "of 'percent' or 'line'", path, lineno); @@ -949,7 +951,7 @@ config_load(struct config *conf, const char *conf_path) .lines = 1000, .indicator = { .style = SCROLLBACK_INDICATOR_STYLE_RELATIVE, - .format = SCROLLBACK_INDICATOR_FORMAT_PERCENT, + .format = SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE, }, }, .colors = { diff --git a/config.h b/config.h index 57701606..456019b5 100644 --- a/config.h +++ b/config.h @@ -50,7 +50,7 @@ struct config { } style; enum { - SCROLLBACK_INDICATOR_FORMAT_PERCENT, + SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE, SCROLLBACK_INDICATOR_FORMAT_LINENO } format; } indicator; diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 573eb313..c348391b 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -78,8 +78,8 @@ in this order: *scrollback-indicator-format* Which format to use when displaying the scrollback position - indicator. Either _percent_ or _line_. This option is ignored if - *scrollback-indicator-style=none*. Default: _percent_. + indicator. Either _percentage_ or _line_. This option is ignored + if *scrollback-indicator-style=none*. Default: _percentage_. *workers* Number of threads to use for rendering. Set to 0 to disable diff --git a/footrc b/footrc index c2ee52e7..3ab2e6c1 100644 --- a/footrc +++ b/footrc @@ -3,7 +3,7 @@ # font=monospace # scrollback=1000 # scrollback-indicator-style=relative -# scrollback-indicator-format=percent +# scrollback-indicator-format=percentage # geometry=700x500 # pad=2x2 # initial-window-mode=windowed diff --git a/render.c b/render.c index 55213408..6e8a56d4 100644 --- a/render.c +++ b/render.c @@ -1363,7 +1363,7 @@ render_scrollback_position(struct terminal *term) /* *What* to render */ switch (term->conf->scrollback.indicator.format) { - case SCROLLBACK_INDICATOR_FORMAT_PERCENT: + case SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE: swprintf(text, sizeof(text) / sizeof(text[0]), L"%u%%", percent); cell_count = 3; break; From c1f35731e0a98344b605d5b07caa77c2f00e3791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 12:31:13 +0200 Subject: [PATCH 17/41] input: margins are not selectable * Fix col/row calculation in pointer-enter event; we did not take the margins into account. * seat->mouse.col,row are now set to -1 if the cursor is inside the margins. That is, col/row are only ever valid when the mouse is actually over the grid, and not in the margins. * Use regular 'left-ptr' mouse cursor when mouse is inside the margins, to not make the user think he/she can start a selection. Besides making things clearer, this also fixes a crash that occurred if you started a selection in e.g. the right margin. --- CHANGELOG.md | 6 ++++++ input.c | 40 ++++++++++++++++++++++++++-------------- selection.c | 7 ++++--- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea392a60..22da9175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,11 +32,17 @@ outside it. * Scrollback search to focus match, that requires a viewport change, roughly in the center of the screen. +* Mouse cursor is now always a `left_ptr` when inside the margins, to + indicate it is not possible to start a selection. ### Deprecated ### Removed ### Fixed + +* Crash when starting a selection inside the margins. + + ### Security diff --git a/input.c b/input.c index 442cd322..4dd8cf39 100644 --- a/input.c +++ b/input.c @@ -1023,11 +1023,16 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, int y = wl_fixed_to_int(surface_y) * term->scale; switch ((term->active_surface = term_surface_kind(term, surface))) { - case TERM_SURF_GRID: - seat->mouse.col = x / term->cell_width; - seat->mouse.row = y / term->cell_height; + case TERM_SURF_GRID: { + int col = (x - term->margins.left) / term->cell_width; + int row = (y - term->margins.top) / term->cell_height; + + seat->mouse.col = col >= 0 && col < term->cols ? col : -1; + seat->mouse.row = row >= 0 && row < term->rows ? row : -1; + term_xcursor_update(term); break; + } case TERM_SURF_SEARCH: case TERM_SURF_TITLE: @@ -1165,26 +1170,31 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, break; case TERM_SURF_GRID: { + term_xcursor_update(term); + int col = (x - term->margins.left) / term->cell_width; int row = (y - term->margins.top) / term->cell_height; - if (col < 0 || row < 0 || col >= term->cols || row >= term->rows) - return; + int old_col = seat->mouse.col; + int old_row = seat->mouse.row; + + seat->mouse.col = col >= 0 && col < term->cols ? col : -1; + seat->mouse.row = row >= 0 && row < term->rows ? row : -1; + + if (seat->mouse.col < 0 || seat->mouse.row < 0) + break; bool update_selection = seat->mouse.button == BTN_LEFT; bool update_selection_early = term->selection.end.row == -1; if (update_selection && update_selection_early) - selection_update(term, col, row); + selection_update(term, seat->mouse.col, seat->mouse.row); - if (col == seat->mouse.col && row == seat->mouse.row) + if (old_col == seat->mouse.col && old_row == seat->mouse.row) break; - seat->mouse.col = col; - seat->mouse.row = row; - if (update_selection && !update_selection_early) - selection_update(term, col, row); + selection_update(term, seat->mouse.col, seat->mouse.row); if (!term_mouse_grabbed(term, seat)) { term_mouse_motion( @@ -1360,9 +1370,11 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (selection_enabled(term, seat)) { switch (seat->mouse.count) { case 1: - selection_start( - term, seat->mouse.col, seat->mouse.row, - seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); + if (seat->mouse.col >= 0 && seat->mouse.row >= 0) { + selection_start( + term, seat->mouse.col, seat->mouse.row, + seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); + } break; case 2: diff --git a/selection.c b/selection.c index d5add464..3b8c1969 100644 --- a/selection.c +++ b/selection.c @@ -25,9 +25,10 @@ bool selection_enabled(const struct terminal *term, struct seat *seat) { return - term->mouse_tracking == MOUSE_NONE || - term_mouse_grabbed(term, seat) || - term->is_searching; + seat->mouse.col >= 0 && seat->mouse.row >= 0 && + (term->mouse_tracking == MOUSE_NONE || + term_mouse_grabbed(term, seat) || + term->is_searching); } bool From 76350c568e6a64dd0f8cea1138348ea97cf93aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 12:37:12 +0200 Subject: [PATCH 18/41] term: term_surface_kind(): recognize the scrollback indicator sub-surface --- terminal.c | 2 ++ terminal.h | 1 + 2 files changed, 3 insertions(+) diff --git a/terminal.c b/terminal.c index 1e355fe3..f1b528fb 100644 --- a/terminal.c +++ b/terminal.c @@ -2407,6 +2407,8 @@ term_surface_kind(const struct terminal *term, const struct wl_surface *surface) return TERM_SURF_GRID; else if (surface == term->window->search_surface) return TERM_SURF_SEARCH; + else if (surface == term->window->scrollback_indicator_surface) + return TERM_SURF_SCROLLBACK_INDICATOR; else if (surface == term->window->csd.surface[CSD_SURF_TITLE]) return TERM_SURF_TITLE; else if (surface == term->window->csd.surface[CSD_SURF_LEFT]) diff --git a/terminal.h b/terminal.h index 85f89abf..eae636cc 100644 --- a/terminal.h +++ b/terminal.h @@ -195,6 +195,7 @@ enum term_surface { TERM_SURF_NONE, TERM_SURF_GRID, TERM_SURF_SEARCH, + TERM_SURF_SCROLLBACK_INDICATOR, TERM_SURF_TITLE, TERM_SURF_BORDER_LEFT, TERM_SURF_BORDER_RIGHT, From 1a65b161dc03bb1ab42913866a111be16abc7e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 12:37:35 +0200 Subject: [PATCH 19/41] input: handle the scrollback indicator surface in pointer events --- input.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/input.c b/input.c index 4dd8cf39..fbf6b517 100644 --- a/input.c +++ b/input.c @@ -1035,6 +1035,7 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, } case TERM_SURF_SEARCH: + case TERM_SURF_SCROLLBACK_INDICATOR: case TERM_SURF_TITLE: render_xcursor_set(seat, term, XCURSOR_LEFT_PTR); break; @@ -1112,6 +1113,7 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, case TERM_SURF_NONE: case TERM_SURF_GRID: case TERM_SURF_SEARCH: + case TERM_SURF_SCROLLBACK_INDICATOR: case TERM_SURF_TITLE: case TERM_SURF_BORDER_LEFT: case TERM_SURF_BORDER_RIGHT: @@ -1146,6 +1148,7 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, switch (term->active_surface) { case TERM_SURF_NONE: case TERM_SURF_SEARCH: + case TERM_SURF_SCROLLBACK_INDICATOR: case TERM_SURF_BUTTON_MINIMIZE: case TERM_SURF_BUTTON_MAXIMIZE: case TERM_SURF_BUTTON_CLOSE: @@ -1357,6 +1360,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, break; case TERM_SURF_SEARCH: + case TERM_SURF_SCROLLBACK_INDICATOR: break; case TERM_SURF_GRID: { From a98484c6ebb2aa7f0ba1f99bb1f03e2d6a251b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 12:37:57 +0200 Subject: [PATCH 20/41] render: scrollback indicator: add top margin --- render.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/render.c b/render.c index 6e8a56d4..d9999bf0 100644 --- a/render.c +++ b/render.c @@ -1420,7 +1420,7 @@ render_scrollback_position(struct terminal *term) return; case SCROLLBACK_INDICATOR_STYLE_FIXED: - surf_top = margin + term->cell_height; + surf_top = term->cell_height - margin; break; case SCROLLBACK_INDICATOR_STYLE_RELATIVE: { @@ -1428,15 +1428,15 @@ render_scrollback_position(struct terminal *term) assert(lines > 0); int on_line = 1 + percent * lines / 100; - surf_top = margin + on_line * term->cell_height; + surf_top = on_line * term->cell_height - margin; break; } } wl_subsurface_set_position( win->scrollback_indicator_sub_surface, - (term->width - term->margins.right - width) / scale, - surf_top / scale); + (term->width - margin - width) / scale, + (term->margins.top + surf_top) / scale); wl_surface_attach(win->scrollback_indicator_surface, buf->wl_buf, 0, 0); wl_surface_damage_buffer(win->scrollback_indicator_surface, 0, 0, width, height); wl_surface_set_buffer_scale(win->scrollback_indicator_surface, scale); From ee5c9d714a31b0bdf2b46188c30c30eb1bb27e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 12:41:32 +0200 Subject: [PATCH 21/41] changelog: scrollback position indicator --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 638609a9..fd2b1d79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ roughly in the center of the screen. * Mouse cursor is now always a `left_ptr` when inside the margins, to indicate it is not possible to start a selection. +* Scrollback position indicator. This feature is optional and + controlled by the **scrollback-indicator-style** and + **scrollback-indicator-format** options in `footrc`. ### Deprecated From 22cd25d36059c784ea0da3ebeed063414aad44d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 06:03:30 +0200 Subject: [PATCH 22/41] tokenize: reset *argv = NULL on error This allows the caller to call free() without having to worry about whether it has already been free:d or not. Closes #49. --- tokenize.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tokenize.c b/tokenize.c index b4aab6b5..703ecb07 100644 --- a/tokenize.c +++ b/tokenize.c @@ -46,6 +46,7 @@ tokenize_cmdline(char *cmdline, char ***argv) if (delim != ' ') { LOG_ERR("unterminated %s quote\n", delim == '"' ? "double" : "single"); free(*argv); + *argv = NULL; return false; } From a9eeeedc90224cb74b6d265c91c1a60fa884254c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 06:04:29 +0200 Subject: [PATCH 23/41] tokenize: remove newline from log message (LOG_ERR appends one for us) --- tokenize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokenize.c b/tokenize.c index 703ecb07..2671e23b 100644 --- a/tokenize.c +++ b/tokenize.c @@ -44,7 +44,7 @@ tokenize_cmdline(char *cmdline, char ***argv) char *end = strchr(p, delim); if (end == NULL) { if (delim != ' ') { - LOG_ERR("unterminated %s quote\n", delim == '"' ? "double" : "single"); + LOG_ERR("unterminated %s quote", delim == '"' ? "double" : "single"); free(*argv); *argv = NULL; return false; From 9bc10cdb01056fc22f6eef601a7113c8efefc195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:39:08 +0200 Subject: [PATCH 24/41] render: scrollback indicator: render relative indicator "smoothly" That is, don't require it to be placed on a grid row. --- render.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/render.c b/render.c index d9999bf0..2f95e5b3 100644 --- a/render.c +++ b/render.c @@ -1353,10 +1353,10 @@ render_scrollback_position(struct terminal *term) * 0% -> at the beginning of the scrollback * 100% -> at the bottom, i.e. where new lines are inserted */ - unsigned percent = + double percent = rebased_view + term->rows == term->grid->num_rows - ? 100 - : 100 * rebased_view / term->grid->num_rows; + ? 1.0 + : (double)rebased_view / term->grid->num_rows; wchar_t text[64]; int cell_count; @@ -1364,7 +1364,7 @@ render_scrollback_position(struct terminal *term) /* *What* to render */ switch (term->conf->scrollback.indicator.format) { case SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE: - swprintf(text, sizeof(text) / sizeof(text[0]), L"%u%%", percent); + swprintf(text, sizeof(text) / sizeof(text[0]), L"%u%%", (int)(100 * percent)); cell_count = 3; break; @@ -1424,11 +1424,11 @@ render_scrollback_position(struct terminal *term) break; case SCROLLBACK_INDICATOR_STYLE_RELATIVE: { - int lines = term->rows - 2; /* Avoid using first and last row */ + int lines = term->rows - 3; /* Avoid using first and two last rows */ assert(lines > 0); - int on_line = 1 + percent * lines / 100; - surf_top = on_line * term->cell_height - margin; + int pixels = lines * term->cell_height - height + 2 * margin; + surf_top = term->cell_height - margin + (int)(percent * pixels); break; } } From faad0936270171467546c920e8cb629c0aa69efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:41:35 +0200 Subject: [PATCH 25/41] changelog: mention fix for crash on unclosed quote in tokenizer --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df304262..d4836891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,9 @@ ### Fixed * Crash in scrollback search +* Crash when a **pipe-visible** or **pipe-scrollback** command + contained an unclosed quote + (https://codeberg.org/dnkl/foot/issues/49). ### Security From 50bd51c4d43931418c5b8c706841b46b67c1a947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:43:41 +0200 Subject: [PATCH 26/41] tokenize: handle escaped quotes We only support escaping quotes inside a quote, and only of the same type as the enclosing quote. I.e. "double quote \"escaped double quote\"" But not "double quote \'invalid escaped single quote\'" --- CHANGELOG.md | 2 ++ tokenize.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4836891..764e8f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ * [LICENSE](LICENSE), [README.md](README.md) and [CHANGELOG.md](CHANGELOG.md) are now installed to `${datadir}/doc/foot`. +* Support for escaping quotes in **pipe-visible** and + **pipe-scrollback** commands. ### Changed diff --git a/tokenize.c b/tokenize.c index 2671e23b..35d52345 100644 --- a/tokenize.c +++ b/tokenize.c @@ -38,10 +38,11 @@ tokenize_cmdline(char *cmdline, char ***argv) char delim = first_token_is_quoted ? cmdline[0] : ' '; char *p = first_token_is_quoted ? &cmdline[1] : &cmdline[0]; + char *search_start = p; size_t idx = 0; while (*p != '\0') { - char *end = strchr(p, delim); + char *end = strchr(search_start, delim); if (end == NULL) { if (delim != ' ') { LOG_ERR("unterminated %s quote", delim == '"' ? "double" : "single"); @@ -58,6 +59,15 @@ tokenize_cmdline(char *cmdline, char ***argv) return true; } + if (end > p && *(end - 1) == '\\') { + /* Escaped quote, remove one level of escaping and + * continue searching for "our" closing quote */ + memmove(end - 1, end, strlen(end)); + end[strlen(end) - 1] = '\0'; + search_start = end; + continue; + } + *end = '\0'; if (!push_argv(argv, &argv_size, p, &idx)) @@ -75,6 +85,7 @@ tokenize_cmdline(char *cmdline, char ***argv) p++; } else delim = ' '; + search_start = p; } if (!push_argv(argv, &argv_size, NULL, &idx)) From 7127a0a6c393ee888a7b640c5481e191e0744519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:44:41 +0200 Subject: [PATCH 27/41] selection: extending a selection is now interactive That is, a selection extension can be resized just like an ordinary extension. --- CHANGELOG.md | 4 +++- input.c | 2 +- selection.c | 16 ++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 764e8f46..53c2462a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,13 +37,15 @@ outside it. * Scrollback search to focus match, that requires a viewport change, roughly in the center of the screen. +* Extending a selection with the right mouse button now works while + dragging the mouse. ### Deprecated ### Removed ### Fixed -* Crash in scrollback search +* Crash in scrollback search. * Crash when a **pipe-visible** or **pipe-scrollback** command contained an unclosed quote (https://codeberg.org/dnkl/foot/issues/49). diff --git a/input.c b/input.c index 442cd322..c7f4b073 100644 --- a/input.c +++ b/input.c @@ -1171,7 +1171,7 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, if (col < 0 || row < 0 || col >= term->cols || row >= term->rows) return; - bool update_selection = seat->mouse.button == BTN_LEFT; + bool update_selection = seat->mouse.button == BTN_LEFT || seat->mouse.button == BTN_RIGHT; bool update_selection_early = term->selection.end.row == -1; if (update_selection && update_selection_early) diff --git a/selection.c b/selection.c index d5add464..354f6f53 100644 --- a/selection.c +++ b/selection.c @@ -372,8 +372,8 @@ selection_extend_normal(struct terminal *term, int col, int row, uint32_t serial if (row < start->row || (row == start->row && col < start->col)) { /* Extend selection to start *before* current start */ - new_start = (struct coord){col, row}; - new_end = *end; + new_start = *end; + new_end = (struct coord){col, row}; } else if (row > end->row || (row == end->row && col > end->col)) { @@ -391,8 +391,8 @@ selection_extend_normal(struct terminal *term, int col, int row, uint32_t serial abs(linear - (end->row * term->cols + end->col))) { /* Move start point */ - new_start = (struct coord){col, row}; - new_end = *end; + new_start = *end; + new_end = (struct coord){col, row}; } else { @@ -440,13 +440,13 @@ selection_extend_block(struct terminal *term, int col, int row, uint32_t serial) /* Move one of the top corners */ if (abs(col - top_left.col) < abs(col - top_right.col)) { - new_start = (struct coord){col, row}; - new_end = bottom_right; + new_start = bottom_right; + new_end = (struct coord){col, row}; } else { - new_start = (struct coord){col, row}; - new_end = bottom_left; + new_start = bottom_left; + new_end = (struct coord){col, row}; } } From 77afd615251ebff7b090454c180a5f5470cb97e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:45:34 +0200 Subject: [PATCH 28/41] doc: foot.5: modifiers+keys are plural --- doc/foot.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 7c3ab283..d837cd1a 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -176,7 +176,7 @@ This section lets you override the default key bindings. The general format is _action=combo1...comboN_. That is, each action may have one or more key combinations, space separated. Each combination is on the form _mod1+mod2+key_. The names of the modifiers -and the key *must* be a valid XKB key name. +and the key *must* be valid XKB key names. Note that if *Shift* is one of the modifiers, the _key_ *must* be in upper case. For example, *Control+Shift+v* will never trigger - From 4143f331ff4fc97856e0fdcbeef98a9c65921a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 18:55:12 +0200 Subject: [PATCH 29/41] changelog: prepare for 1.4.3 --- CHANGELOG.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53c2462a..910944c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -* [Unreleased](#unreleased) -* [1.4.2](#1.4.2) +* [1.4.3](#1-4-3) +* [1.4.2](#1-4-2) * [1.4.1](#1-4-1) * [1.4.0](#1-4-0) * [1.3.0](#1-3-0) @@ -10,7 +10,7 @@ * [1.2.1](#1-2-1) * [1.2.0](#1-2-0) -## Unreleased +## 1.4.3 ### Added * Section to [README.md](README.md) describing how to programmatically @@ -41,8 +41,6 @@ dragging the mouse. -### Deprecated -### Removed ### Fixed * Crash in scrollback search. @@ -51,7 +49,6 @@ (https://codeberg.org/dnkl/foot/issues/49). -### Security ### Contributors * [birger](https://codeberg.org/birger) From e71108d7c37c838beddc7e05367a20b8cd769ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 18:55:28 +0200 Subject: [PATCH 30/41] meson/pkgbuild: bump version to 1.4.3 --- PKGBUILD | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index ae70f263..36d020d4 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,5 +1,5 @@ pkgname=('foot-git' 'foot-terminfo-git') -pkgver=1.4.2 +pkgver=1.4.3 pkgrel=1 arch=('x86_64' 'aarch64') url=https://codeberg.org/dnkl/foot diff --git a/meson.build b/meson.build index 493b4392..1a75a151 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('foot', 'c', - version: '1.4.2', + version: '1.4.3', license: 'MIT', meson_version: '>=0.53.0', default_options: [ From ddbca7ca55de7ac22e93ab99a73bcd5f8e3affb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 19:00:25 +0200 Subject: [PATCH 31/41] changelog: add new 'unreleased' section --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 910944c8..a9529ba9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +* [Unreleased](#unreleased) * [1.4.3](#1-4-3) * [1.4.2](#1-4-2) * [1.4.1](#1-4-1) @@ -10,6 +11,15 @@ * [1.2.1](#1-2-1) * [1.2.0](#1-2-0) +## Unreleased +### Added +### Deprecated +### Removed +### Fixed +### Security +### Contributors + + ## 1.4.3 ### Added From 0c8b44ab67bdcffee6fe7f16c400c254a37b1d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 19:07:00 +0200 Subject: [PATCH 32/41] changelog: add link to issue --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd38f103..4f57df94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,7 +53,8 @@ indicate it is not possible to start a selection. * Scrollback position indicator. This feature is optional and controlled by the **scrollback-indicator-style** and - **scrollback-indicator-format** options in `footrc`. + **scrollback-indicator-format** options in `footrc` + (https://codeberg.org/dnkl/foot/issues/42). ### Fixed From 9d859131367cea63ac4d604dd269db35a9a0bdb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 19:08:28 +0200 Subject: [PATCH 33/41] changelog: move scrollback indicator entries from 1.4.3 to 'unreleased' --- CHANGELOG.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f57df94..35669232 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,21 @@ ### Added ### Deprecated ### Removed +### Changed + +* Mouse cursor is now always a `left_ptr` when inside the margins, to + indicate it is not possible to start a selection. +* Scrollback position indicator. This feature is optional and + controlled by the **scrollback-indicator-style** and + **scrollback-indicator-format** options in `footrc` + (https://codeberg.org/dnkl/foot/issues/42). + + ### Fixed + +* Crash when starting a selection inside the margins. + + ### Security ### Contributors @@ -49,12 +63,6 @@ roughly in the center of the screen. * Extending a selection with the right mouse button now works while dragging the mouse. -* Mouse cursor is now always a `left_ptr` when inside the margins, to - indicate it is not possible to start a selection. -* Scrollback position indicator. This feature is optional and - controlled by the **scrollback-indicator-style** and - **scrollback-indicator-format** options in `footrc` - (https://codeberg.org/dnkl/foot/issues/42). ### Fixed @@ -63,7 +71,6 @@ * Crash when a **pipe-visible** or **pipe-scrollback** command contained an unclosed quote (https://codeberg.org/dnkl/foot/issues/49). -* Crash when starting a selection inside the margins. ### Contributors From aca5a64954ee736373d3f125632807582498c772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 20:00:42 +0200 Subject: [PATCH 34/41] render: scrollback indicator: apply weston sub-surface quirk --- render.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/render.c b/render.c index 2f95e5b3..59601c05 100644 --- a/render.c +++ b/render.c @@ -1433,6 +1433,7 @@ render_scrollback_position(struct terminal *term) } } + quirk_weston_subsurface_desync_on(win->scrollback_indicator_sub_surface); wl_subsurface_set_position( win->scrollback_indicator_sub_surface, (term->width - margin - width) / scale, @@ -1449,6 +1450,7 @@ render_scrollback_position(struct terminal *term) } wl_surface_commit(win->scrollback_indicator_surface); + quirk_weston_subsurface_desync_off(win->scrollback_indicator_sub_surface); } static void frame_callback( From 718e5b4a7787cc9d68b9c422b8b6703f3b7c5c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 20:02:51 +0200 Subject: [PATCH 35/41] config: rename scrollback-indicator-style to scrollback-indicator-position --- CHANGELOG.md | 2 +- config.c | 12 ++++++------ config.h | 8 ++++---- doc/foot.5.scd | 4 ++-- footrc | 2 +- render.c | 10 +++++----- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35669232..dc6fc301 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ * Mouse cursor is now always a `left_ptr` when inside the margins, to indicate it is not possible to start a selection. * Scrollback position indicator. This feature is optional and - controlled by the **scrollback-indicator-style** and + controlled by the **scrollback-indicator-position** and **scrollback-indicator-format** options in `footrc` (https://codeberg.org/dnkl/foot/issues/42). diff --git a/config.c b/config.c index 2b989d62..169b2b40 100644 --- a/config.c +++ b/config.c @@ -291,15 +291,15 @@ parse_section_main(const char *key, const char *value, struct config *conf, conf->scrollback.lines = lines; } - else if (strcmp(key, "scrollback-indicator-style") == 0) { + else if (strcmp(key, "scrollback-indicator-position") == 0) { if (strcmp(value, "none") == 0) - conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_NONE; + conf->scrollback.indicator.position = SCROLLBACK_INDICATOR_POSITION_NONE; else if (strcmp(value, "fixed") == 0) - conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_FIXED; + conf->scrollback.indicator.position = SCROLLBACK_INDICATOR_POSITION_FIXED; else if (strcmp(value, "relative") == 0) - conf->scrollback.indicator.style = SCROLLBACK_INDICATOR_STYLE_RELATIVE; + conf->scrollback.indicator.position = SCROLLBACK_INDICATOR_POSITION_RELATIVE; else { - LOG_ERR("%s:%d: scrollback-indicator-style must be one of " + LOG_ERR("%s:%d: scrollback-indicator-position must be one of " "'none', 'fixed' or 'moving'", path, lineno); return false; @@ -950,7 +950,7 @@ config_load(struct config *conf, const char *conf_path) .scrollback = { .lines = 1000, .indicator = { - .style = SCROLLBACK_INDICATOR_STYLE_RELATIVE, + .position = SCROLLBACK_INDICATOR_POSITION_RELATIVE, .format = SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE, }, }, diff --git a/config.h b/config.h index 456019b5..eee01e65 100644 --- a/config.h +++ b/config.h @@ -44,10 +44,10 @@ struct config { struct { enum { - SCROLLBACK_INDICATOR_STYLE_NONE, - SCROLLBACK_INDICATOR_STYLE_FIXED, - SCROLLBACK_INDICATOR_STYLE_RELATIVE - } style; + SCROLLBACK_INDICATOR_POSITION_NONE, + SCROLLBACK_INDICATOR_POSITION_FIXED, + SCROLLBACK_INDICATOR_POSITION_RELATIVE + } position; enum { SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE, diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 188e8edf..949e2751 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -68,7 +68,7 @@ in this order: *scrollback* Number of scrollback lines. Default: _1000_. -*scrollback-indicator-style* +*scrollback-indicator-position* Configures the style of the scrollback position indicator. One of *none*, *fixed* or *relative*. *none* disables the indicator completely. *fixed* always renders the indicator near the top at @@ -79,7 +79,7 @@ in this order: *scrollback-indicator-format* Which format to use when displaying the scrollback position indicator. Either _percentage_ or _line_. This option is ignored - if *scrollback-indicator-style=none*. Default: _percentage_. + if *scrollback-indicator-position=none*. Default: _percentage_. *workers* Number of threads to use for rendering. Set to 0 to disable diff --git a/footrc b/footrc index 117b73fe..900ce149 100644 --- a/footrc +++ b/footrc @@ -2,7 +2,7 @@ # font=monospace # scrollback=1000 -# scrollback-indicator-style=relative +# scrollback-indicator-position=relative # scrollback-indicator-format=percentage # geometry=700x500 # pad=2x2 diff --git a/render.c b/render.c index 59601c05..195839fb 100644 --- a/render.c +++ b/render.c @@ -1290,7 +1290,7 @@ render_csd(struct terminal *term) static void render_scrollback_position(struct terminal *term) { - if (term->conf->scrollback.indicator.style == SCROLLBACK_INDICATOR_STYLE_NONE) + if (term->conf->scrollback.indicator.position == SCROLLBACK_INDICATOR_POSITION_NONE) return; struct wayland *wayl = term->wl; @@ -1414,16 +1414,16 @@ render_scrollback_position(struct terminal *term) /* *Where* to render - parent relative coordinates */ int surf_top = 0; - switch (term->conf->scrollback.indicator.style) { - case SCROLLBACK_INDICATOR_STYLE_NONE: + switch (term->conf->scrollback.indicator.position) { + case SCROLLBACK_INDICATOR_POSITION_NONE: assert(false); return; - case SCROLLBACK_INDICATOR_STYLE_FIXED: + case SCROLLBACK_INDICATOR_POSITION_FIXED: surf_top = term->cell_height - margin; break; - case SCROLLBACK_INDICATOR_STYLE_RELATIVE: { + case SCROLLBACK_INDICATOR_POSITION_RELATIVE: { int lines = term->rows - 3; /* Avoid using first and two last rows */ assert(lines > 0); From 62c4f1e5b428306b479235592d3cabb84eb7f130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 20:04:56 +0200 Subject: [PATCH 36/41] doc: rename foot.5 -> footrc.5 --- CHANGELOG.md | 1 + README.md | 7 ++++--- doc/foot.1.scd | 6 +++--- doc/{foot.5.scd => footrc.5.scd} | 4 ++-- doc/meson.build | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) rename doc/{foot.5.scd => footrc.5.scd} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc6fc301..57c01110 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### Removed ### Changed +* Renamed man page for `footrc` from **foot**(5) to **footrc**(5). * Mouse cursor is now always a `left_ptr` when inside the margins, to indicate it is not possible to start a selection. * Scrollback position indicator. This feature is optional and diff --git a/README.md b/README.md index 233703d1..d784b4fc 100644 --- a/README.md +++ b/README.md @@ -55,11 +55,12 @@ The fast, lightweight and minimalistic Wayland terminal emulator. ## Configuration -**foot** can be configured by creating a file `$XDG_CONFIG_HOME/footrc` (defaulting to `~/.config/footrc`). -A template for that can usually be found in `/usr/share/foot/footrc` or +**foot** can be configured by creating a file +`$XDG_CONFIG_HOME/footrc` (defaulting to `~/.config/footrc`). A +template for that can usually be found in `/usr/share/foot/footrc` or [here](https://codeberg.org/dnkl/foot/src/branch/master/footrc). -Further information can be found in foot's manpage `foot(5)`. +Further information can be found in foot's man page `footrc(5)`. ## Troubleshooting diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 883ae8b1..c22eea70 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -119,7 +119,7 @@ The following keyboard shortcuts are available. ## NORMAL MODE Note that these are just the defaults; they can be changed in the -*footrc*, see *foot*(5). +*footrc*, see *footrc*(5). *shift*+*page up*/*page down* Scroll up/down in history @@ -239,7 +239,7 @@ Finally, pressing *alt* will prefix the transmitted byte with ESC. # CONFIGURATION -See *foot*(5) +See *footrc*(5) # BUGS @@ -256,4 +256,4 @@ The report should contain the following: # SEE ALSO -*foot*(5), *footclient*(1) +*footrc*(5), *footclient*(1) diff --git a/doc/foot.5.scd b/doc/footrc.5.scd similarity index 99% rename from doc/foot.5.scd rename to doc/footrc.5.scd index 949e2751..97545886 100644 --- a/doc/foot.5.scd +++ b/doc/footrc.5.scd @@ -1,7 +1,7 @@ -foot(5) +footrc(5) # NAME -foot - configuration file +footrc - configuration file # DESCRIPTION diff --git a/doc/meson.build b/doc/meson.build index 6d3219dc..39697496 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -3,7 +3,7 @@ sh = find_program('sh', native: true) scdoc = dependency('scdoc', native: true) scdoc_prog = find_program(scdoc.get_pkgconfig_variable('scdoc'), native: true) -foreach man_src : ['foot.1.scd', 'foot.5.scd', 'footclient.1.scd'] +foreach man_src : ['foot.1.scd', 'footrc.5.scd', 'footclient.1.scd'] parts = man_src.split('.') name = parts[-3] section = parts[-2] From c3f01bda23461df48829e4c9816d96f657170217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 20:06:54 +0200 Subject: [PATCH 37/41] doc: footrc.5: add references to foot.1 and footclient.1 --- doc/footrc.5.scd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/footrc.5.scd b/doc/footrc.5.scd index 97545886..f23d7a36 100644 --- a/doc/footrc.5.scd +++ b/doc/footrc.5.scd @@ -411,3 +411,7 @@ any of these options. Note: this feature is always disabled in 32-bit. Default: _512_. Maximum allowed: _2048_ (2GB). + +# SEE ALSO + +*foot*(1), *footclient*(1) From 698c9b240ffe45b5609f449399ae61feb8b5c6d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Jul 2020 19:53:32 +0200 Subject: [PATCH 38/41] readme: add link to license --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index d784b4fc..b131d2f2 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ The fast, lightweight and minimalistic Wayland terminal emulator. 1. [Credits](#Credits) 1. [Bugs](#bugs) 1. [Mastodon](#mastodon) +1. [License](#license) + ## Features @@ -591,3 +593,8 @@ The report should contain the following: Every now and then I post foot related updates on [@dnkl@linuxrocks.online](https://linuxrocks.online/@dnkl) + + +# License + +Foot is released under the [MIT](LICENSE). From eadb5a4a88243098ddc8348b42c93be0553777dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Jul 2020 19:55:09 +0200 Subject: [PATCH 39/41] config: handle trailing comments and empty values --- CHANGELOG.md | 1 + config.c | 48 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57c01110..9c98fdba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ ### Fixed * Crash when starting a selection inside the margins. +* Handle trailing comments in `footrc` ### Security diff --git a/config.c b/config.c index 169b2b40..8da9c258 100644 --- a/config.c +++ b/config.c @@ -822,7 +822,7 @@ parse_config_file(FILE *f, struct config *conf, const char *path) break; } - /* Strip whitespace */ + /* Strip leading whitespace */ char *line = _line; { while (isspace(*line)) @@ -839,11 +839,15 @@ parse_config_file(FILE *f, struct config *conf, const char *path) if (line[0] == '\0' || line[0] == '#') continue; + /* Split up into key/value pair + trailing comment */ + char *key_value = strtok(line, "#"); + char *comment __attribute__((unused)) = strtok(NULL, "\n"); + /* Check for new section */ - if (line[0] == '[') { - char *end = strchr(line, ']'); + if (key_value[0] == '[') { + char *end = strchr(key_value, ']'); if (end == NULL) { - LOG_ERR("%s:%d: syntax error: %s", path, lineno, line); + LOG_ERR("%s:%d: syntax error: %s", path, lineno, key_value); goto err; } @@ -851,13 +855,13 @@ parse_config_file(FILE *f, struct config *conf, const char *path) section = SECTION_COUNT; for (enum section i = 0; i < SECTION_COUNT; i++) { - if (strcmp(&line[1], section_info[i].name) == 0) { + if (strcmp(&key_value[1], section_info[i].name) == 0) { section = i; } } if (section == SECTION_COUNT) { - LOG_ERR("%s:%d: invalid section name: %s", path, lineno, &line[1]); + LOG_ERR("%s:%d: invalid section name: %s", path, lineno, &key_value[1]); goto err; } @@ -865,11 +869,20 @@ parse_config_file(FILE *f, struct config *conf, const char *path) continue; } - char *key = strtok(line, "="); + char *key = strtok(key_value, "="); + if (key == NULL) { + LOG_ERR("%s:%d: syntax error: no key specified", path, lineno); + goto err; + } + char *value = strtok(NULL, "\n"); + if (value == NULL) { + /* Empty value, i.e. "key=" */ + value = key + strlen(key); + } /* Strip trailing whitespace from key (leading stripped earlier) */ - { + if (key[0] != '\0') { assert(!isspace(*key)); char *end = key + strlen(key) - 1; @@ -880,25 +893,28 @@ parse_config_file(FILE *f, struct config *conf, const char *path) if (value == NULL) { if (key != NULL && strlen(key) > 0 && key[0] != '#') { - LOG_ERR("%s:%d: syntax error: %s", path, lineno, line); + LOG_ERR("%s:%d: syntax error: %s", path, lineno, key_value); goto err; } continue; } - /* Strip leading whitespace from value (trailing stripped earlier) */ + /* Strip leading+trailing whitespace from value */ { while (isspace(*value)) value++; - assert(!isspace(*(value + strlen(value) - 1))); + + if (value[0] != '\0') { + char *end = value + strlen(value) - 1; + while (isspace(*end)) + end--; + *(end + 1) = '\0'; + } } - if (key[0] == '#') - continue; - - LOG_DBG("section=%s, key='%s', value='%s'", - section_names[section], key, value); + LOG_DBG("section=%s, key='%s', value='%s', comment='%s'", + section_info[section].name, key, value, comment); parser_fun_t section_parser = section_info[section].fun; assert(section_parser != NULL); From 2882fbb537f53feb33d407c3aac103d0189af725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Jul 2020 19:56:53 +0200 Subject: [PATCH 40/41] config: add free-form text variant to 'scrollback-indicator-format' And make the empty string the new default. --- config.c | 19 ++++++++++++++----- config.h | 5 ++++- doc/footrc.5.scd | 5 +++-- footrc | 2 +- render.c | 12 +++++++++--- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/config.c b/config.c index 8da9c258..19e2a2ca 100644 --- a/config.c +++ b/config.c @@ -314,10 +314,17 @@ parse_section_main(const char *key, const char *value, struct config *conf, conf->scrollback.indicator.format = SCROLLBACK_INDICATOR_FORMAT_LINENO; } else { - LOG_ERR("%s:%d: 'scrollback-indicator-format must be one " - "of 'percent' or 'line'", - path, lineno); - return false; + free(conf->scrollback.indicator.text); + conf->scrollback.indicator.text = NULL; + + size_t len = mbstowcs(NULL, value, -1); + if (len < 0) { + LOG_ERRNO("%s:%d: invalid scrollback-indicator-format value", path, lineno); + return false; + } + + conf->scrollback.indicator.text = calloc(len + 1, sizeof(wchar_t)); + mbstowcs(conf->scrollback.indicator.text, value, len); } } @@ -967,7 +974,8 @@ config_load(struct config *conf, const char *conf_path) .lines = 1000, .indicator = { .position = SCROLLBACK_INDICATOR_POSITION_RELATIVE, - .format = SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE, + .format = SCROLLBACK_INDICATOR_FORMAT_TEXT, + .text = wcsdup(L""), }, }, .colors = { @@ -1119,6 +1127,7 @@ config_free(struct config conf) free(conf.shell); free(conf.title); free(conf.app_id); + free(conf.scrollback.indicator.text); tll_foreach(conf.fonts, it) config_font_destroy(&it->item); tll_free(conf.fonts); diff --git a/config.h b/config.h index eee01e65..9de282a0 100644 --- a/config.h +++ b/config.h @@ -51,8 +51,11 @@ struct config { enum { SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE, - SCROLLBACK_INDICATOR_FORMAT_LINENO + SCROLLBACK_INDICATOR_FORMAT_LINENO, + SCROLLBACK_INDICATOR_FORMAT_TEXT, } format; + + wchar_t *text; } indicator; } scrollback; diff --git a/doc/footrc.5.scd b/doc/footrc.5.scd index f23d7a36..6bba164f 100644 --- a/doc/footrc.5.scd +++ b/doc/footrc.5.scd @@ -78,8 +78,9 @@ in this order: *scrollback-indicator-format* Which format to use when displaying the scrollback position - indicator. Either _percentage_ or _line_. This option is ignored - if *scrollback-indicator-position=none*. Default: _percentage_. + indicator. Either _percentage_, _line_, or a custom fixed + string. This option is ignored if + *scrollback-indicator-position=none*. Default: _empty string_. *workers* Number of threads to use for rendering. Set to 0 to disable diff --git a/footrc b/footrc index 900ce149..30eeee39 100644 --- a/footrc +++ b/footrc @@ -3,7 +3,7 @@ # font=monospace # scrollback=1000 # scrollback-indicator-position=relative -# scrollback-indicator-format=percentage +# scrollback-indicator-format= # geometry=700x500 # pad=2x2 # initial-window-mode=windowed diff --git a/render.c b/render.c index 195839fb..92b546ed 100644 --- a/render.c +++ b/render.c @@ -1358,20 +1358,26 @@ render_scrollback_position(struct terminal *term) ? 1.0 : (double)rebased_view / term->grid->num_rows; - wchar_t text[64]; + wchar_t _text[64]; + const wchar_t *text = _text; int cell_count; /* *What* to render */ switch (term->conf->scrollback.indicator.format) { case SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE: - swprintf(text, sizeof(text) / sizeof(text[0]), L"%u%%", (int)(100 * percent)); + swprintf(_text, sizeof(_text) / sizeof(_text[0]), L"%u%%", (int)(100 * percent)); cell_count = 3; break; case SCROLLBACK_INDICATOR_FORMAT_LINENO: - swprintf(text, sizeof(text) / sizeof(text[0]), L"%d", rebased_view + 1); + swprintf(_text, sizeof(_text) / sizeof(_text[0]), L"%d", rebased_view + 1); cell_count = 1 + (int)log10(term->grid->num_rows); break; + + case SCROLLBACK_INDICATOR_FORMAT_TEXT: + text = term->conf->scrollback.indicator.text; + cell_count = wcslen(text); + break; } const int scale = term->scale; From 47d9b947f0a7ae0eb3d87e291c06f1a66784a3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Jul 2020 19:57:26 +0200 Subject: [PATCH 41/41] config: fix check for scrollback-indicator-format=percentage --- config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.c b/config.c index 19e2a2ca..5a1bc282 100644 --- a/config.c +++ b/config.c @@ -307,7 +307,7 @@ parse_section_main(const char *key, const char *value, struct config *conf, } else if (strcmp(key, "scrollback-indicator-format") == 0) { - if (strcmp(value, "percent") == 0) { + if (strcmp(value, "percentage") == 0) { conf->scrollback.indicator.format = SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE; } else if (strcmp(value, "line") == 0) {