From d28ac267d251f8f3f7aeba95d1b4099a5e6bb755 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 15 May 2026 15:51:01 +1000 Subject: [PATCH] Add an optional build-time switch to disable scrollback support This change introduces a new `scrollback` Meson build option (enabled by default) that lets foot be compiled without scrollback history. When the option is off, `FOOT_HAVE_SCROLLBACK` is left undefined and the relevant code is excluded from the build, producing a slimmer terminal for use cases that do not need it. With scrollback disabled: - The `[scrollback]` section in `foot.ini` and its key bindings become no-ops. - In-terminal search is removed, along with the "pipe scrollback" action, the scrollback indicator, and their colors/overlays. - IME hooks for the search box, mouse-wheel scrollback handling, and related `terminal` state are compiled out. - Selection auto-scroll (the timer that scrolls the viewport while a drag-selection extends past the visible area) is removed, since with no scrollback there is nowhere to scroll to. The associated function declarations, `enum selection_scroll_direction`, the `auto_scroll` field on `terminal::selection`, and their init/teardown sites are all excluded from the build. To keep action enumerations stable across build configurations, two range markers (`BIND_ACTION_PIPE_FIRST` / `BIND_ACTION_PIPE_LAST`) are introduced so that pipe-action handling does not depend on `PIPE_SCROLLBACK` being present. The build summary and `foot --version` now report `+scrollback` or `-scrollback`, and the config tests have been updated to account for optional section. --- CHANGELOG.md | 8 +++++++ commands.c | 2 ++ commands.h | 2 ++ config.c | 56 +++++++++++++++++++++++++++++++++++++++++++-- config.h | 12 +++++++++- csi.c | 2 ++ foot-features.c | 6 +++++ ime.c | 22 ++++++++++++++---- input.c | 32 +++++++++++++++++++++++++- key-binding.c | 10 ++++++++ key-binding.h | 18 ++++++++++++++- meson.build | 4 ++++ meson_options.txt | 3 +++ render.c | 49 +++++++++++++++++++++++++++++++++++---- render.h | 2 ++ search.c | 4 ++++ search.h | 2 ++ selection.c | 8 +++++++ selection.h | 2 ++ terminal.c | 35 ++++++++++++++++++++++++---- terminal.h | 22 ++++++++++++++++++ tests/test-config.c | 14 +++++++++++- unicode-mode.c | 16 +++++++++---- wayland.c | 6 +++++ wayland.h | 2 ++ 25 files changed, 317 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5792c240..7017ed75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,14 @@ ## Unreleased ### Added + +* New `scrollback` Meson build option (enabled by default). When + disabled, scrollback history, in-terminal search, the scrollback + indicator, the "pipe scrollback" action, and selection auto-scroll + are excluded from the build, producing a smaller binary. `foot + --version` reports `+scrollback` or `-scrollback`. + + ### Changed ### Deprecated ### Removed diff --git a/commands.c b/commands.c index a3e48458..da01c18f 100644 --- a/commands.c +++ b/commands.c @@ -10,6 +10,7 @@ #include "url-mode.h" #include "util.h" +#if defined(FOOT_HAVE_SCROLLBACK) void cmd_scrollback_up(struct terminal *term, int rows) { @@ -113,3 +114,4 @@ cmd_scrollback_down(struct terminal *term, int rows) render_refresh_urls(term); render_refresh(term); } +#endif /* FOOT_HAVE_SCROLLBACK */ diff --git a/commands.h b/commands.h index 644523b0..7d428550 100644 --- a/commands.h +++ b/commands.h @@ -2,5 +2,7 @@ #include "terminal.h" +#if defined(FOOT_HAVE_SCROLLBACK) void cmd_scrollback_up(struct terminal *term, int rows); void cmd_scrollback_down(struct terminal *term, int rows); +#endif /* FOOT_HAVE_SCROLLBACK */ diff --git a/config.c b/config.c index 481d4c4f..3dd9a0e4 100644 --- a/config.c +++ b/config.c @@ -109,6 +109,7 @@ static const uint32_t default_sixel_colors[16] = { static const char *const binding_action_map[] = { [BIND_ACTION_NONE] = NULL, [BIND_ACTION_NOOP] = "noop", +#if defined(FOOT_HAVE_SCROLLBACK) [BIND_ACTION_SCROLLBACK_UP_PAGE] = "scrollback-up-page", [BIND_ACTION_SCROLLBACK_UP_HALF_PAGE] = "scrollback-up-half-page", [BIND_ACTION_SCROLLBACK_UP_LINE] = "scrollback-up-line", @@ -117,10 +118,13 @@ static const char *const binding_action_map[] = { [BIND_ACTION_SCROLLBACK_DOWN_LINE] = "scrollback-down-line", [BIND_ACTION_SCROLLBACK_HOME] = "scrollback-home", [BIND_ACTION_SCROLLBACK_END] = "scrollback-end", +#endif /* FOOT_HAVE_SCROLLBACK */ [BIND_ACTION_CLIPBOARD_COPY] = "clipboard-copy", [BIND_ACTION_CLIPBOARD_PASTE] = "clipboard-paste", [BIND_ACTION_PRIMARY_PASTE] = "primary-paste", +#if defined(FOOT_HAVE_SCROLLBACK) [BIND_ACTION_SEARCH_START] = "search-start", +#endif [BIND_ACTION_FONT_SIZE_UP] = "font-increase", [BIND_ACTION_FONT_SIZE_DOWN] = "font-decrease", [BIND_ACTION_FONT_SIZE_RESET] = "font-reset", @@ -128,7 +132,9 @@ static const char *const binding_action_map[] = { [BIND_ACTION_MINIMIZE] = "minimize", [BIND_ACTION_MAXIMIZE] = "maximize", [BIND_ACTION_FULLSCREEN] = "fullscreen", +#if defined(FOOT_HAVE_SCROLLBACK) [BIND_ACTION_PIPE_SCROLLBACK] = "pipe-scrollback", +#endif [BIND_ACTION_PIPE_VIEW] = "pipe-visible", [BIND_ACTION_PIPE_SELECTED] = "pipe-selected", [BIND_ACTION_PIPE_COMMAND_OUTPUT] = "pipe-command-output", @@ -149,8 +155,10 @@ static const char *const binding_action_map[] = { [BIND_ACTION_THEME_TOGGLE] = "color-theme-toggle", /* Mouse-specific actions */ +#if defined(FOOT_HAVE_SCROLLBACK) [BIND_ACTION_SCROLLBACK_UP_MOUSE] = "scrollback-up-mouse", [BIND_ACTION_SCROLLBACK_DOWN_MOUSE] = "scrollback-down-mouse", +#endif /* FOOT_HAVE_SCROLLBACK */ [BIND_ACTION_SELECT_BEGIN] = "select-begin", [BIND_ACTION_SELECT_BEGIN_BLOCK] = "select-begin-block", [BIND_ACTION_SELECT_EXTEND] = "select-extend", @@ -161,6 +169,7 @@ static const char *const binding_action_map[] = { [BIND_ACTION_SELECT_ROW] = "select-row", }; +#if defined(FOOT_HAVE_SCROLLBACK) static const char *const search_binding_action_map[] = { [BIND_ACTION_SEARCH_NONE] = NULL, [BIND_ACTION_SEARCH_SCROLLBACK_UP_PAGE] = "scrollback-up-page", @@ -199,6 +208,7 @@ static const char *const search_binding_action_map[] = { [BIND_ACTION_SEARCH_PRIMARY_PASTE] = "primary-paste", [BIND_ACTION_SEARCH_UNICODE_INPUT] = "unicode-input", }; +#endif /* FOOT_HAVE_SCROLLBACK */ static const char *const url_binding_action_map[] = { [BIND_ACTION_URL_NONE] = NULL, @@ -208,8 +218,10 @@ static const char *const url_binding_action_map[] = { static_assert(ALEN(binding_action_map) == BIND_ACTION_COUNT, "binding action map size mismatch"); +#if defined(FOOT_HAVE_SCROLLBACK) static_assert(ALEN(search_binding_action_map) == BIND_ACTION_SEARCH_COUNT, "search binding action map size mismatch"); +#endif static_assert(ALEN(url_binding_action_map) == BIND_ACTION_URL_COUNT, "URL binding action map size mismatch"); @@ -1249,6 +1261,7 @@ parse_section_desktop_notifications(struct context *ctx) } } +#if defined(FOOT_HAVE_SCROLLBACK) static bool parse_section_scrollback(struct context *ctx) { @@ -1291,6 +1304,7 @@ parse_section_scrollback(struct context *ctx) return false; } } +#endif /* FOOT_HAVE_SCROLLBACK */ static bool parse_section_url(struct context *ctx) @@ -1489,6 +1503,7 @@ parse_color_theme(struct context *ctx, struct color_theme *theme) return true; } +#if defined(FOOT_HAVE_SCROLLBACK) else if (streq(key, "scrollback-indicator")) { if (!value_to_two_colors( ctx, @@ -1530,6 +1545,7 @@ parse_color_theme(struct context *ctx, struct color_theme *theme) theme->use_custom.search_box_match = true; return true; } +#endif /* FOOT_HAVE_SCROLLBACK */ else if (streq(key, "cursor")) { if (!value_to_two_colors( @@ -2313,8 +2329,8 @@ parse_key_binding_section(struct context *ctx, /* TODO: this is ugly... */ if (action_map == binding_action_map && - action >= BIND_ACTION_PIPE_SCROLLBACK && - action <= BIND_ACTION_PIPE_COMMAND_OUTPUT) + action >= BIND_ACTION_PIPE_FIRST && + action <= BIND_ACTION_PIPE_LAST) { ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &aux.pipe); if (pipe_remove_len <= 0) @@ -2478,6 +2494,7 @@ parse_section_key_bindings(struct context *ctx) &ctx->conf->bindings.key); } +#if defined(FOOT_HAVE_SCROLLBACK) static bool parse_section_search_bindings(struct context *ctx) { @@ -2486,6 +2503,7 @@ parse_section_search_bindings(struct context *ctx) BIND_ACTION_SEARCH_COUNT, search_binding_action_map, &ctx->conf->bindings.search); } +#endif /* FOOT_HAVE_SCROLLBACK */ static bool parse_section_url_bindings(struct context *ctx) @@ -3046,7 +3064,9 @@ enum section { SECTION_SECURITY, SECTION_BELL, SECTION_DESKTOP_NOTIFICATIONS, +#if defined(FOOT_HAVE_SCROLLBACK) SECTION_SCROLLBACK, +#endif SECTION_URL, SECTION_REGEX, SECTION_COLORS_DARK, @@ -3055,7 +3075,9 @@ enum section { SECTION_MOUSE, SECTION_CSD, SECTION_KEY_BINDINGS, +#if defined(FOOT_HAVE_SCROLLBACK) SECTION_SEARCH_BINDINGS, +#endif SECTION_URL_BINDINGS, SECTION_MOUSE_BINDINGS, SECTION_TEXT_BINDINGS, @@ -3082,7 +3104,9 @@ static const struct { [SECTION_SECURITY] = {&parse_section_security, "security"}, [SECTION_BELL] = {&parse_section_bell, "bell"}, [SECTION_DESKTOP_NOTIFICATIONS] = {&parse_section_desktop_notifications, "desktop-notifications"}, +#if defined(FOOT_HAVE_SCROLLBACK) [SECTION_SCROLLBACK] = {&parse_section_scrollback, "scrollback"}, +#endif [SECTION_URL] = {&parse_section_url, "url"}, [SECTION_REGEX] = {&parse_section_regex, "regex", true}, [SECTION_COLORS_DARK] = {&parse_section_colors_dark, "colors-dark"}, @@ -3091,7 +3115,9 @@ static const struct { [SECTION_MOUSE] = {&parse_section_mouse, "mouse"}, [SECTION_CSD] = {&parse_section_csd, "csd"}, [SECTION_KEY_BINDINGS] = {&parse_section_key_bindings, "key-bindings"}, +#if defined(FOOT_HAVE_SCROLLBACK) [SECTION_SEARCH_BINDINGS] = {&parse_section_search_bindings, "search-bindings"}, +#endif [SECTION_URL_BINDINGS] = {&parse_section_url_bindings, "url-bindings"}, [SECTION_MOUSE_BINDINGS] = {&parse_section_mouse_bindings, "mouse-bindings"}, [SECTION_TEXT_BINDINGS] = {&parse_section_text_bindings, "text-bindings"}, @@ -3325,16 +3351,20 @@ static void add_default_key_bindings(struct config *conf) { const struct config_key_binding bindings[] = { +#if defined(FOOT_HAVE_SCROLLBACK) {BIND_ACTION_SCROLLBACK_UP_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Prior}}}, {BIND_ACTION_SCROLLBACK_UP_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_KP_Prior}}}, {BIND_ACTION_SCROLLBACK_DOWN_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Next}}}, {BIND_ACTION_SCROLLBACK_DOWN_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_KP_Next}}}, +#endif /* FOOT_HAVE_SCROLLBACK */ {BIND_ACTION_CLIPBOARD_COPY, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_c}}}, {BIND_ACTION_CLIPBOARD_COPY, m("none"), {{XKB_KEY_XF86Copy}}}, {BIND_ACTION_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_v}}}, {BIND_ACTION_CLIPBOARD_PASTE, m("none"), {{XKB_KEY_XF86Paste}}}, {BIND_ACTION_PRIMARY_PASTE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Insert}}}, +#if defined(FOOT_HAVE_SCROLLBACK) {BIND_ACTION_SEARCH_START, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_r}}}, +#endif {BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_plus}}}, {BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_equal}}}, {BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_KP_Add}}}, @@ -3354,6 +3384,7 @@ add_default_key_bindings(struct config *conf) } +#if defined(FOOT_HAVE_SCROLLBACK) static void add_default_search_bindings(struct config *conf) { @@ -3407,6 +3438,7 @@ add_default_search_bindings(struct config *conf) conf->bindings.search.count = ALEN(bindings); conf->bindings.search.arr = xmemdup(bindings, sizeof(bindings)); } +#endif /* FOOT_HAVE_SCROLLBACK */ static void add_default_url_bindings(struct config *conf) @@ -3427,8 +3459,10 @@ static void add_default_mouse_bindings(struct config *conf) { const struct config_key_binding bindings[] = { +#if defined(FOOT_HAVE_SCROLLBACK) {BIND_ACTION_SCROLLBACK_UP_MOUSE, m("none"), {.m = {BTN_WHEEL_BACK, 1}}}, {BIND_ACTION_SCROLLBACK_DOWN_MOUSE, m("none"), {.m = {BTN_WHEEL_FORWARD, 1}}}, +#endif /* FOOT_HAVE_SCROLLBACK */ {BIND_ACTION_PRIMARY_PASTE, m("none"), {.m = {BTN_MIDDLE, 1}}}, {BIND_ACTION_SELECT_BEGIN, m("none"), {.m = {BTN_LEFT, 1}}}, {BIND_ACTION_SELECT_BEGIN_BLOCK, m(XKB_MOD_NAME_CTRL), {.m = {BTN_LEFT, 1}}}, @@ -3530,6 +3564,7 @@ config_load(struct config *conf, const char *conf_path, }, .custom_regexes = tll_init(), .can_shape_grapheme = fcft_caps & FCFT_CAPABILITY_GRAPHEME_SHAPING, +#if defined(FOOT_HAVE_SCROLLBACK) .scrollback = { .lines = 1000, .indicator = { @@ -3539,6 +3574,7 @@ config_load(struct config *conf, const char *conf_path, }, .multiplier = 3., }, +#endif /* FOOT_HAVE_SCROLLBACK */ .colors_dark = { .fg = default_foreground, .bg = default_background, @@ -3555,7 +3591,9 @@ config_load(struct config *conf, const char *conf_path, }, .use_custom = { .jump_label = false, +#if defined(FOOT_HAVE_SCROLLBACK) .scrollback_indicator = false, +#endif .url = false, }, .blur = false, @@ -3707,7 +3745,9 @@ config_load(struct config *conf, const char *conf_path, } add_default_key_bindings(conf); +#if defined(FOOT_HAVE_SCROLLBACK) add_default_search_bindings(conf); +#endif add_default_url_bindings(conf); add_default_mouse_bindings(conf); @@ -3766,8 +3806,10 @@ config_load(struct config *conf, const char *conf_path, #if defined(_DEBUG) for (size_t i = 0; i < conf->bindings.key.count; i++) xassert(conf->bindings.key.arr[i].action != BIND_ACTION_NONE); +#if defined(FOOT_HAVE_SCROLLBACK) for (size_t i = 0; i < conf->bindings.search.count; i++) xassert(conf->bindings.search.arr[i].action != BIND_ACTION_SEARCH_NONE); +#endif /* FOOT_HAVE_SCROLLBACK */ for (size_t i = 0; i < conf->bindings.url.count; i++) xassert(conf->bindings.url.arr[i].action != BIND_ACTION_URL_NONE); #endif @@ -3842,9 +3884,11 @@ config_override_apply(struct config *conf, config_override_t *overrides, resolve_key_binding_collisions( conf, section_info[SECTION_KEY_BINDINGS].name, binding_action_map, &conf->bindings.key, KEY_BINDING) && +#if defined(FOOT_HAVE_SCROLLBACK) resolve_key_binding_collisions( conf, section_info[SECTION_SEARCH_BINDINGS].name, search_binding_action_map, &conf->bindings.search, KEY_BINDING) && +#endif /* FOOT_HAVE_SCROLLBACK */ resolve_key_binding_collisions( conf, section_info[SECTION_URL_BINDINGS].name, url_binding_action_map, &conf->bindings.url, KEY_BINDING) && @@ -3935,7 +3979,9 @@ config_clone(const struct config *old) conf->app_id = xstrdup(old->app_id); conf->toplevel_tag = xstrdup(old->toplevel_tag); conf->word_delimiters = xc32dup(old->word_delimiters); +#if defined(FOOT_HAVE_SCROLLBACK) conf->scrollback.indicator.text = xc32dup(old->scrollback.indicator.text); +#endif conf->server_socket_path = xstrdup(old->server_socket_path); spawn_template_clone(&conf->bell.command, &old->bell.command); spawn_template_clone(&conf->desktop_notifications.command, @@ -3969,7 +4015,9 @@ config_clone(const struct config *old) } key_binding_list_clone(&conf->bindings.key, &old->bindings.key); +#if defined(FOOT_HAVE_SCROLLBACK) key_binding_list_clone(&conf->bindings.search, &old->bindings.search); +#endif key_binding_list_clone(&conf->bindings.url, &old->bindings.url); key_binding_list_clone(&conf->bindings.mouse, &old->bindings.mouse); @@ -4037,7 +4085,9 @@ config_free(struct config *conf) free(conf->toplevel_tag); free(conf->word_delimiters); spawn_template_free(&conf->bell.command); +#if defined(FOOT_HAVE_SCROLLBACK) free(conf->scrollback.indicator.text); +#endif spawn_template_free(&conf->desktop_notifications.command); spawn_template_free(&conf->desktop_notifications.command_action_arg); spawn_template_free(&conf->desktop_notifications.close); @@ -4062,7 +4112,9 @@ config_free(struct config *conf) } free_key_binding_list(&conf->bindings.key); +#if defined(FOOT_HAVE_SCROLLBACK) free_key_binding_list(&conf->bindings.search); +#endif free_key_binding_list(&conf->bindings.url); free_key_binding_list(&conf->bindings.mouse); tll_free_and_free(conf->mouse.selection_override_modifiers, free); diff --git a/config.h b/config.h index f8e99df3..d9fdeacf 100644 --- a/config.h +++ b/config.h @@ -166,11 +166,14 @@ struct color_theme { uint32_t bg; } jump_label; +#if defined(FOOT_HAVE_SCROLLBACK) struct { uint32_t fg; uint32_t bg; } scrollback_indicator; +#endif /* FOOT_HAVE_SCROLLBACK */ +#if defined(FOOT_HAVE_SCROLLBACK) struct { struct { uint32_t fg; @@ -182,14 +185,17 @@ struct color_theme { uint32_t bg; } match; } search_box; +#endif /* FOOT_HAVE_SCROLLBACK */ struct { bool cursor:1; bool jump_label:1; - bool scrollback_indicator:1; bool url:1; +#if defined(FOOT_HAVE_SCROLLBACK) + bool scrollback_indicator:1; bool search_box_no_match:1; bool search_box_match:1; +#endif /* FOOT_HAVE_SCROLLBACK */ uint8_t dim; } use_custom; @@ -308,6 +314,7 @@ struct config { bool command_focused; } bell; +#if defined(FOOT_HAVE_SCROLLBACK) struct { uint32_t lines; @@ -328,6 +335,7 @@ struct config { } indicator; float multiplier; } scrollback; +#endif /* FOOT_HAVE_SCROLLBACK */ struct { char32_t *label_letters; @@ -375,9 +383,11 @@ struct config { * Special modes */ +#if defined(FOOT_HAVE_SCROLLBACK) /* While searching (not - action to *start* a search is in the * 'key' bindings above */ struct config_key_binding_list search; +#endif /* FOOT_HAVE_SCROLLBACK */ /* While showing URL jump labels */ struct config_key_binding_list url; diff --git a/csi.c b/csi.c index 87af215e..1e0469e2 100644 --- a/csi.c +++ b/csi.c @@ -991,11 +991,13 @@ csi_dispatch(struct terminal *term, uint8_t final) term->grid->cursor.lcf = false; break; +#if defined(FOOT_HAVE_SCROLLBACK) case 3: { /* Erase scrollback */ term_erase_scrollback(term); break; } +#endif default: UNHANDLED(); diff --git a/foot-features.c b/foot-features.c index 8e332517..40b188a6 100644 --- a/foot-features.c +++ b/foot-features.c @@ -16,6 +16,12 @@ const char version_and_features[] = " -ime" #endif +#if defined(FOOT_HAVE_SCROLLBACK) + " +scrollback" +#else + " -scrollback" +#endif + #if defined(FOOT_GRAPHEME_CLUSTERING) && FOOT_GRAPHEME_CLUSTERING " +graphemes" #else diff --git a/ime.c b/ime.c index c6ccb479..d2e0e74f 100644 --- a/ime.c +++ b/ime.c @@ -177,10 +177,14 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, ime_reset_preedit(seat); if (term != NULL) { - if (term->is_searching) +#if defined(FOOT_HAVE_SCROLLBACK) + if (term->is_searching) { render_refresh_search(term); - else + } else +#endif + { render_refresh(term); + } } } @@ -198,11 +202,15 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, size_t len = strlen(text); if (term != NULL) { +#if defined(FOOT_HAVE_SCROLLBACK) if (term->is_searching) { search_add_chars(term, text, len); render_refresh_search(term); } else +#endif + { term_to_slave(term, text, len); + } } ime_reset_pending_commit(seat); } @@ -367,10 +375,14 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, ime_reset_pending_preedit(seat); if (term != NULL) { - if (term->is_searching) +#if defined(FOOT_HAVE_SCROLLBACK) + if (term->is_searching) { render_refresh_search(term); - else + } else +#endif + { render_refresh(term); + } } } @@ -473,9 +485,11 @@ ime_update_cursor_rect(struct seat *seat) if (seat->ime.preedit.cells != NULL) goto update; +#if defined(FOOT_HAVE_SCROLLBACK) /* Set in render_search_box() */ if (term->is_searching) goto update; +#endif int x, y, width, height; int col = term->grid->cursor.point.col; diff --git a/input.c b/input.c index 6a829a70..62004d7c 100644 --- a/input.c +++ b/input.c @@ -82,7 +82,9 @@ pipe_closed: return true; } +#if defined(FOOT_HAVE_SCROLLBACK) static void alternate_scroll(struct seat *seat, int amount, int button); +#endif static bool execute_binding(struct seat *seat, struct terminal *term, @@ -97,6 +99,7 @@ execute_binding(struct seat *seat, struct terminal *term, case BIND_ACTION_NOOP: return true; +#if defined(FOOT_HAVE_SCROLLBACK) case BIND_ACTION_SCROLLBACK_UP_PAGE: if (term->grid == &term->normal) { cmd_scrollback_up(term, term->rows); @@ -176,6 +179,7 @@ execute_binding(struct seat *seat, struct terminal *term, return true; } break; +#endif /* FOOT_HAVE_SCROLLBACK */ case BIND_ACTION_CLIPBOARD_COPY: selection_to_clipboard(seat, term, serial); @@ -191,9 +195,11 @@ execute_binding(struct seat *seat, struct terminal *term, term_reset_view(term); return true; +#if defined(FOOT_HAVE_SCROLLBACK) case BIND_ACTION_SEARCH_START: search_begin(term); return true; +#endif /* FOOT_HAVE_SCROLLBACK */ case BIND_ACTION_FONT_SIZE_UP: term_font_size_increase(term); @@ -231,10 +237,12 @@ execute_binding(struct seat *seat, struct terminal *term, xdg_toplevel_set_fullscreen(term->window->xdg_toplevel, NULL); return true; +#if defined(FOOT_HAVE_SCROLLBACK) case BIND_ACTION_PIPE_SCROLLBACK: if (term->grid == &term->alt) break; /* FALLTHROUGH */ +#endif /* FOOT_HAVE_SCROLLBACK */ case BIND_ACTION_PIPE_VIEW: case BIND_ACTION_PIPE_SELECTED: case BIND_ACTION_PIPE_COMMAND_OUTPUT: { @@ -265,9 +273,11 @@ execute_binding(struct seat *seat, struct terminal *term, bool success; switch (action) { +#if defined(FOOT_HAVE_SCROLLBACK) case BIND_ACTION_PIPE_SCROLLBACK: success = term_scrollback_to_text(term, &text, &len); break; +#endif /* FOOT_HAVE_SCROLLBACK */ case BIND_ACTION_PIPE_VIEW: success = term_view_to_text(term, &text, &len); @@ -1649,6 +1659,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, return; } +#if defined(FOOT_HAVE_SCROLLBACK) else if (term->is_searching) { if (pressed) { if (should_repeat) @@ -1660,6 +1671,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, } return; } +#endif /* FOOT_HAVE_SCROLLBACK */ else if (urls_mode_is_active(term)) { if (pressed) { @@ -1931,9 +1943,11 @@ UNITTEST .start = {-1, -1}, .end = {-1, -1}, }, +#if defined(FOOT_HAVE_SCROLLBACK) .auto_scroll = { .fd = -1, }, +#endif }, }; @@ -2768,6 +2782,7 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, /* Cursor is inside the grid, i.e. *not* in the margins */ const bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0; +#if defined(FOOT_HAVE_SCROLLBACK) enum selection_scroll_direction auto_scroll_direction = term->selection.coords.end.row < 0 ? SELECTION_SCROLL_NOT @@ -2779,9 +2794,14 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, if (auto_scroll_direction == SELECTION_SCROLL_NOT) selection_stop_scroll_timer(term); +#endif /* FOOT_HAVE_SCROLLBACK */ /* Update selection */ - if (!term->is_searching) { +#if defined(FOOT_HAVE_SCROLLBACK) + if (!term->is_searching) +#endif + { +#if defined(FOOT_HAVE_SCROLLBACK) if (auto_scroll_direction != SELECTION_SCROLL_NOT) { /* * Start 'selection auto-scrolling' @@ -2809,6 +2829,7 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, term, 400000000 / (divisor > 0 ? divisor : 1), auto_scroll_direction, seat->mouse.col); } +#endif /* FOOT_HAVE_SCROLLBACK */ if (term->selection.ongoing && (cursor_is_on_new_cell || @@ -3244,7 +3265,9 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, break; case TERM_SURF_GRID: { +#if defined(FOOT_HAVE_SCROLLBACK) search_cancel(term); +#endif urls_reset(term); bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0; @@ -3301,6 +3324,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } } +#if defined(FOOT_HAVE_SCROLLBACK) static void alternate_scroll(struct seat *seat, int amount, int button) { @@ -3320,6 +3344,7 @@ alternate_scroll(struct seat *seat, int amount, int button) key_press_release(seat, term, seat->kbd.serial, key, XKB_KEY_DOWN); key_press_release(seat, term, seat->kbd.serial, key, XKB_KEY_UP); } +#endif /* FOOT_HAVE_SCROLLBACK */ static void mouse_scroll(struct seat *seat, int amount, enum wl_pointer_axis axis) @@ -3367,10 +3392,15 @@ mouse_scroll(struct seat *seat, int amount, enum wl_pointer_axis axis) static double mouse_scroll_multiplier(const struct terminal *term, const struct seat *seat) { +#if defined(FOOT_HAVE_SCROLLBACK) return (term->grid == &term->normal || (term_mouse_grabbed(term, seat) && term->alt_scrolling)) ? term->conf->scrollback.multiplier : 1.0; +#else + (void)term; (void)seat; + return 1.0; +#endif /* FOOT_HAVE_SCROLLBACK */ } static void diff --git a/key-binding.c b/key-binding.c index a2883ed5..99c13952 100644 --- a/key-binding.c +++ b/key-binding.c @@ -111,7 +111,9 @@ key_binding_new_for_seat(struct key_binding_manager *mgr, struct key_set set = { .public = { .key = tll_init(), +#if defined(FOOT_HAVE_SCROLLBACK) .search = tll_init(), +#endif .url = tll_init(), .mouse = tll_init(), }, @@ -152,7 +154,9 @@ key_binding_new_for_conf(struct key_binding_manager *mgr, struct key_set set = { .public = { .key = tll_init(), +#if defined(FOOT_HAVE_SCROLLBACK) .search = tll_init(), +#endif .url = tll_init(), .mouse = tll_init(), }, @@ -531,6 +535,7 @@ convert_key_bindings(struct key_set *set) } } +#if defined(FOOT_HAVE_SCROLLBACK) static void convert_search_bindings(struct key_set *set) { @@ -541,6 +546,7 @@ convert_search_bindings(struct key_set *set) convert_key_binding(set, binding, &set->public.search); } } +#endif /* FOOT_HAVE_SCROLLBACK */ static void convert_url_bindings(struct key_set *set) @@ -597,7 +603,9 @@ load_keymap(struct key_set *set) } convert_key_bindings(set); +#if defined(FOOT_HAVE_SCROLLBACK) convert_search_bindings(set); +#endif convert_url_bindings(set); convert_mouse_bindings(set); @@ -638,7 +646,9 @@ static void NOINLINE unload_keymap(struct key_set *set) { key_bindings_destroy(&set->public.key); +#if defined(FOOT_HAVE_SCROLLBACK) key_bindings_destroy(&set->public.search); +#endif key_bindings_destroy(&set->public.url); key_bindings_destroy(&set->public.mouse); set->public.selection_overrides = 0; diff --git a/key-binding.h b/key-binding.h index c4a04e99..e5e6b4fe 100644 --- a/key-binding.h +++ b/key-binding.h @@ -10,6 +10,7 @@ enum bind_action_normal { BIND_ACTION_NONE, BIND_ACTION_NOOP, +#if defined(FOOT_HAVE_SCROLLBACK) BIND_ACTION_SCROLLBACK_UP_PAGE, BIND_ACTION_SCROLLBACK_UP_HALF_PAGE, BIND_ACTION_SCROLLBACK_UP_LINE, @@ -18,10 +19,13 @@ enum bind_action_normal { BIND_ACTION_SCROLLBACK_DOWN_LINE, BIND_ACTION_SCROLLBACK_HOME, BIND_ACTION_SCROLLBACK_END, +#endif /* FOOT_HAVE_SCROLLBACK */ BIND_ACTION_CLIPBOARD_COPY, BIND_ACTION_CLIPBOARD_PASTE, BIND_ACTION_PRIMARY_PASTE, +#if defined(FOOT_HAVE_SCROLLBACK) BIND_ACTION_SEARCH_START, +#endif BIND_ACTION_FONT_SIZE_UP, BIND_ACTION_FONT_SIZE_DOWN, BIND_ACTION_FONT_SIZE_RESET, @@ -29,8 +33,10 @@ enum bind_action_normal { BIND_ACTION_MINIMIZE, BIND_ACTION_MAXIMIZE, BIND_ACTION_FULLSCREEN, - BIND_ACTION_PIPE_SCROLLBACK, BIND_ACTION_PIPE_VIEW, +#if defined(FOOT_HAVE_SCROLLBACK) + BIND_ACTION_PIPE_SCROLLBACK, +#endif BIND_ACTION_PIPE_SELECTED, BIND_ACTION_PIPE_COMMAND_OUTPUT, BIND_ACTION_SHOW_URLS_COPY, @@ -50,8 +56,10 @@ enum bind_action_normal { BIND_ACTION_THEME_TOGGLE, /* Mouse specific actions - i.e. they require a mouse coordinate */ +#if defined(FOOT_HAVE_SCROLLBACK) BIND_ACTION_SCROLLBACK_UP_MOUSE, BIND_ACTION_SCROLLBACK_DOWN_MOUSE, +#endif /* FOOT_HAVE_SCROLLBACK */ BIND_ACTION_SELECT_BEGIN, BIND_ACTION_SELECT_BEGIN_BLOCK, BIND_ACTION_SELECT_EXTEND, @@ -63,8 +71,13 @@ enum bind_action_normal { BIND_ACTION_KEY_COUNT = BIND_ACTION_THEME_TOGGLE + 1, BIND_ACTION_COUNT = BIND_ACTION_SELECT_ROW + 1, + + /* Range markers (aliases) - stable regardless of FOOT_HAVE_SCROLLBACK */ + BIND_ACTION_PIPE_FIRST = BIND_ACTION_PIPE_VIEW, + BIND_ACTION_PIPE_LAST = BIND_ACTION_PIPE_COMMAND_OUTPUT, }; +#if defined(FOOT_HAVE_SCROLLBACK) enum bind_action_search { BIND_ACTION_SEARCH_NONE, BIND_ACTION_SEARCH_SCROLLBACK_UP_PAGE, @@ -104,6 +117,7 @@ enum bind_action_search { BIND_ACTION_SEARCH_UNICODE_INPUT, BIND_ACTION_SEARCH_COUNT, }; +#endif /* FOOT_HAVE_SCROLLBACK */ enum bind_action_url { BIND_ACTION_URL_NONE, @@ -142,7 +156,9 @@ struct wayland; struct key_binding_set { key_binding_list_t key; +#if defined(FOOT_HAVE_SCROLLBACK) key_binding_list_t search; +#endif key_binding_list_t url; key_binding_list_t mouse; xkb_mod_mask_t selection_overrides; diff --git a/meson.build b/meson.build index e4e83302..b34780ce 100644 --- a/meson.build +++ b/meson.build @@ -90,6 +90,9 @@ add_project_arguments( (get_option('ime') ? ['-DFOOT_IME_ENABLED=1'] : []) + + (get_option('scrollback') + ? ['-DFOOT_HAVE_SCROLLBACK'] + : []) + (get_option('b_pgo') == 'use' ? ['-DFOOT_PGO_ENABLED=1'] : []) + @@ -443,6 +446,7 @@ summary( 'Documentation': scdoc.found(), 'Themes': get_option('themes'), 'IME': get_option('ime'), + 'Scrollback': get_option('scrollback'), 'Grapheme clustering': utf8proc.found(), 'utmp backend': utmp_backend, 'utmp helper default path': utmp_default_helper_path, diff --git a/meson_options.txt b/meson_options.txt index e3356074..b1602485 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -7,6 +7,9 @@ option('themes', type: 'boolean', value: true, option('ime', type: 'boolean', value: true, description: 'IME (Input Method Editor) support') +option('scrollback', type: 'boolean', value: true, + description: 'Enable scrollback history. When disabled, the [scrollback] section in foot.ini and the corresponding key bindings become no-ops.') + option('grapheme-clustering', type: 'feature', description: 'Enables grapheme clustering using libutf8proc. Requires fcft with harfbuzz support to be useful.') diff --git a/render.c b/render.c index cf5f969a..88778410 100644 --- a/render.c +++ b/render.c @@ -1732,8 +1732,10 @@ render_ime_preedit_for_seat(struct terminal *term, struct seat *seat, if (likely(seat->ime.preedit.cells == NULL)) return; +#if defined(FOOT_HAVE_SCROLLBACK) if (unlikely(term->is_searching)) return; +#endif const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf); @@ -1975,7 +1977,9 @@ render_overlay(struct terminal *term) const bool unicode_mode_active = term->unicode_mode.active; const enum overlay_style style = +#if defined(FOOT_HAVE_SCROLLBACK) term->is_searching ? OVERLAY_SEARCH : +#endif term->flash.active ? OVERLAY_FLASH : unicode_mode_active ? OVERLAY_UNICODE_MODE : OVERLAY_NONE; @@ -1994,7 +1998,9 @@ render_overlay(struct terminal *term) pixman_color_t color; switch (style) { +#if defined(FOOT_HAVE_SCROLLBACK) case OVERLAY_SEARCH: +#endif case OVERLAY_UNICODE_MODE: color = (pixman_color_t){0, 0, 0, 0x7fff}; break; @@ -2028,6 +2034,7 @@ render_overlay(struct terminal *term) /* Bounding rectangle of damaged areas - for wl_surface_damage_buffer() */ pixman_box32_t damage_bounds; +#if defined(FOOT_HAVE_SCROLLBACK) if (style == OVERLAY_SEARCH) { /* * When possible, we only update the areas that have *changed* @@ -2143,9 +2150,10 @@ render_overlay(struct terminal *term) pixman_region32_fini(&new_dimmed); pixman_region32_fini(&damage); } - - else if (buf == term->render.last_overlay_buf && - style == term->render.last_overlay_style) + else +#endif /* FOOT_HAVE_SCROLLBACK */ + if (buf == term->render.last_overlay_buf && + style == term->render.last_overlay_style) { xassert(style == OVERLAY_FLASH || style == OVERLAY_UNICODE_MODE); shm_did_not_use_buf(buf); @@ -2989,6 +2997,7 @@ render_csd(struct terminal *term) render_csd_title(term, &infos[CSD_SURF_TITLE], bufs[CSD_SURF_TITLE]); } +#if defined(FOOT_HAVE_SCROLLBACK) static void render_scrollback_position(struct terminal *term) { @@ -3139,6 +3148,7 @@ render_scrollback_position(struct terminal *term) fg, 0xffu << 24 | bg, width - margin - c32len(text) * term->cell_width); } +#endif /* FOOT_HAVE_SCROLLBACK */ static void render_render_timer(struct terminal *term, struct timespec render_time) @@ -3612,7 +3622,9 @@ grid_render(struct terminal *term) render_overlay(term); render_ime_preedit(term, buf); +#if defined(FOOT_HAVE_SCROLLBACK) render_scrollback_position(term); +#endif if (term->conf->tweak.render_timer != RENDER_TIMER_NONE) { struct timespec end_time; @@ -3716,6 +3728,7 @@ grid_render(struct terminal *term) wl_surface_commit(term->window->surface.surf); } +#if defined(FOOT_HAVE_SCROLLBACK) static void render_search_box(struct terminal *term) { @@ -4061,6 +4074,7 @@ render_search_box(struct terminal *term) #undef WINDOW_X #undef WINDOW_Y } +#endif /* FOOT_HAVE_SCROLLBACK */ static void render_urls(struct terminal *term) @@ -4319,12 +4333,18 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da bool grid = term->render.pending.grid; bool csd = term->render.pending.csd; +#if defined(FOOT_HAVE_SCROLLBACK) bool search = term->is_searching && term->render.pending.search; +#else + bool search = false; +#endif bool urls = urls_mode_is_active(term) > 0 && term->render.pending.urls; term->render.pending.grid = false; term->render.pending.csd = false; +#if defined(FOOT_HAVE_SCROLLBACK) term->render.pending.search = false; +#endif term->render.pending.urls = false; struct grid *original_grid = term->grid; @@ -4339,8 +4359,10 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da quirk_weston_csd_off(term); } +#if defined(FOOT_HAVE_SCROLLBACK) if (search) render_search_box(term); +#endif if (urls) render_urls(term); @@ -4689,8 +4711,13 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts) * the grid array. */ const unsigned max_scrollback = (INT_MAX >> 1) + 1; +#if defined(FOOT_HAVE_SCROLLBACK) + const uint64_t scrollback_lines = term->render.scrollback_lines; +#else + const uint64_t scrollback_lines = 0; +#endif const unsigned scrollback_lines_not_yet_power_of_two = - min((uint64_t)term->render.scrollback_lines + new_rows - 1, max_scrollback); + min(scrollback_lines + new_rows - 1, max_scrollback); /* Grid rows/cols after resize */ const int new_normal_grid_rows = @@ -4997,7 +5024,9 @@ damage_view: term->render.last_buf = NULL; term_damage_view(term); render_refresh_csd(term); +#if defined(FOOT_HAVE_SCROLLBACK) render_refresh_search(term); +#endif render_refresh(term); return true; @@ -5144,7 +5173,11 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) bool grid = term->render.refresh.grid; bool csd = term->render.refresh.csd; +#if defined(FOOT_HAVE_SCROLLBACK) bool search = term->is_searching && term->render.refresh.search; +#else + bool search = false; +#endif bool urls = urls_mode_is_active(term) && term->render.refresh.urls; if (!(grid | csd | search | urls)) @@ -5155,7 +5188,9 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) term->render.refresh.grid = false; term->render.refresh.csd = false; +#if defined(FOOT_HAVE_SCROLLBACK) term->render.refresh.search = false; +#endif term->render.refresh.urls = false; if (term->window->frame_callback == NULL) { @@ -5170,8 +5205,10 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) render_csd(term); quirk_weston_csd_off(term); } +#if defined(FOOT_HAVE_SCROLLBACK) if (search) render_search_box(term); +#endif if (urls) render_urls(term); if (grid | csd | search | urls) @@ -5187,7 +5224,9 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) /* Tells the frame callback to render again */ term->render.pending.grid |= grid; term->render.pending.csd |= csd; +#if defined(FOOT_HAVE_SCROLLBACK) term->render.pending.search |= search; +#endif term->render.pending.urls |= urls; } } @@ -5305,12 +5344,14 @@ render_refresh_csd(struct terminal *term) term->render.refresh.csd = true; } +#if defined(FOOT_HAVE_SCROLLBACK) void render_refresh_search(struct terminal *term) { if (term->is_searching) term->render.refresh.search = true; } +#endif /* FOOT_HAVE_SCROLLBACK */ void render_refresh_urls(struct terminal *term) diff --git a/render.h b/render.h index e6674ab2..01f277c3 100644 --- a/render.h +++ b/render.h @@ -24,7 +24,9 @@ void render_refresh(struct terminal *term); void render_refresh_app_id(struct terminal *term); void render_refresh_icon(struct terminal *term); void render_refresh_csd(struct terminal *term); +#if defined(FOOT_HAVE_SCROLLBACK) void render_refresh_search(struct terminal *term); +#endif void render_refresh_title(struct terminal *term); void render_refresh_urls(struct terminal *term); bool render_xcursor_set( diff --git a/search.c b/search.c index ef0a15bb..1652719b 100644 --- a/search.c +++ b/search.c @@ -1,5 +1,7 @@ #include "search.h" +#if defined(FOOT_HAVE_SCROLLBACK) + #include #include @@ -1510,3 +1512,5 @@ update_search: if (redraw) render_refresh_search(term); } + +#endif /* FOOT_HAVE_SCROLLBACK */ diff --git a/search.h b/search.h index ee8ecd76..35be9edd 100644 --- a/search.h +++ b/search.h @@ -5,6 +5,7 @@ #include "key-binding.h" #include "terminal.h" +#if defined(FOOT_HAVE_SCROLLBACK) void search_begin(struct terminal *term); void search_cancel(struct terminal *term); void search_input( @@ -24,3 +25,4 @@ struct search_match_iterator { struct search_match_iterator search_matches_new_iter(struct terminal *term); struct range search_matches_next(struct search_match_iterator *iter); +#endif /* FOOT_HAVE_SCROLLBACK */ diff --git a/selection.c b/selection.c index 0a479ee8..30e3e271 100644 --- a/selection.c +++ b/selection.c @@ -1549,7 +1549,9 @@ selection_finalize(struct seat *seat, struct terminal *term, uint32_t serial) LOG_DBG("selection finalize"); +#if defined(FOOT_HAVE_SCROLLBACK) selection_stop_scroll_timer(term); +#endif term->selection.ongoing = false; if (term->selection.coords.start.row < 0 || term->selection.coords.end.row < 0) @@ -1599,7 +1601,9 @@ selection_cancel(struct terminal *term) term->selection.coords.start.row, term->selection.coords.start.col, term->selection.coords.end.row, term->selection.coords.end.col); +#if defined(FOOT_HAVE_SCROLLBACK) selection_stop_scroll_timer(term); +#endif if (term->selection.coords.start.row >= 0 && term->selection.coords.end.row >= 0) { foreach_selected( @@ -1616,7 +1620,9 @@ selection_cancel(struct terminal *term) term->selection.direction = SELECTION_UNDIR; term->selection.ongoing = false; +#if defined(FOOT_HAVE_SCROLLBACK) search_selection_cancelled(term); +#endif } bool @@ -1671,6 +1677,7 @@ selection_primary_unset(struct seat *seat) primary->text = NULL; } +#if defined(FOOT_HAVE_SCROLLBACK) static bool fdm_scroll_timer(struct fdm *fdm, int fd, int events, void *data) { @@ -1773,6 +1780,7 @@ selection_stop_scroll_timer(struct terminal *term) term->selection.auto_scroll.fd = -1; term->selection.auto_scroll.direction = SELECTION_SCROLL_NOT; } +#endif /* FOOT_HAVE_SCROLLBACK */ static void target(void *data, struct wl_data_source *wl_data_source, const char *mime_type) diff --git a/selection.h b/selection.h index b6ad099a..dfbe3572 100644 --- a/selection.h +++ b/selection.h @@ -72,10 +72,12 @@ void text_from_primary( void (*cb)(char *data, size_t size, void *user), void (*dont)(void *user), void *user); +#if defined(FOOT_HAVE_SCROLLBACK) void selection_start_scroll_timer( struct terminal *term, int interval_ns, enum selection_scroll_direction direction, int col); void selection_stop_scroll_timer(struct terminal *term); +#endif void selection_find_word_boundary_left( const struct terminal *term, struct coord *pos, bool spaces_only); diff --git a/terminal.c b/terminal.c index 8eafbcbe..e3d681c5 100644 --- a/terminal.c +++ b/terminal.c @@ -1344,9 +1344,11 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .start = {-1, -1}, .end = {-1, -1}, }, +#if defined(FOOT_HAVE_SCROLLBACK) .auto_scroll = { .fd = -1, }, +#endif }, .normal = {.scroll_damage = tll_init(), .sixel_images = tll_init()}, .alt = {.scroll_damage = tll_init(), .sixel_images = tll_init()}, @@ -1365,14 +1367,18 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .chains = { .grid = shm_chain_new(wayl, true, 1 + conf->render_worker_count, desired_bit_depth, &render_buffer_release_callback, term), +#if defined(FOOT_HAVE_SCROLLBACK) .search = shm_chain_new(wayl, false, 1 ,desired_bit_depth, NULL, NULL), .scrollback_indicator = shm_chain_new(wayl, false, 1, desired_bit_depth, NULL, NULL), +#endif .render_timer = shm_chain_new(wayl, false, 1, desired_bit_depth, NULL, NULL), .url = shm_chain_new(wayl, false, 1, desired_bit_depth, NULL, NULL), .csd = shm_chain_new(wayl, false, 1, desired_bit_depth, NULL, NULL), .overlay = shm_chain_new(wayl, false, 1, desired_bit_depth, NULL, NULL), }, +#if defined(FOOT_HAVE_SCROLLBACK) .scrollback_lines = conf->scrollback.lines, +#endif .app_sync_updates.timer_fd = app_sync_updates_fd, .title = { .timer_fd = title_update_fd, @@ -1718,7 +1724,9 @@ term_shutdown(struct terminal *term) term_cursor_blink_update(term); xassert(term->cursor_blink.fd < 0); +#if defined(FOOT_HAVE_SCROLLBACK) fdm_del(term->fdm, term->selection.auto_scroll.fd); +#endif fdm_del(term->fdm, term->render.app_sync_updates.timer_fd); fdm_del(term->fdm, term->render.app_id.timer_fd); fdm_del(term->fdm, term->render.icon.timer_fd); @@ -1770,7 +1778,9 @@ term_shutdown(struct terminal *term) } } +#if defined(FOOT_HAVE_SCROLLBACK) term->selection.auto_scroll.fd = -1; +#endif term->render.app_sync_updates.timer_fd = -1; term->render.app_id.timer_fd = -1; term->render.icon.timer_fd = -1; @@ -1825,7 +1835,9 @@ term_destroy(struct terminal *term) del_utmp_record(term->conf, term->reaper, term->ptmx); +#if defined(FOOT_HAVE_SCROLLBACK) fdm_del(term->fdm, term->selection.auto_scroll.fd); +#endif fdm_del(term->fdm, term->render.app_sync_updates.timer_fd); fdm_del(term->fdm, term->render.app_id.timer_fd); fdm_del(term->fdm, term->render.icon.timer_fd); @@ -1891,8 +1903,10 @@ term_destroy(struct terminal *term) free_custom_glyphs( &term->custom_glyphs.octants, GLYPH_OCTANTS_COUNT); +#if defined(FOOT_HAVE_SCROLLBACK) free(term->search.buf); free(term->search.last.buf); +#endif if (term->render.workers.threads != NULL) { for (size_t i = 0; i < term->render.workers.count; i++) { @@ -1911,8 +1925,10 @@ term_destroy(struct terminal *term) shm_unref(term->render.last_buf); shm_chain_free(term->render.chains.grid); +#if defined(FOOT_HAVE_SCROLLBACK) shm_chain_free(term->render.chains.search); shm_chain_free(term->render.chains.scrollback_indicator); +#endif shm_chain_free(term->render.chains.render_timer); shm_chain_free(term->render.chains.url); shm_chain_free(term->render.chains.csd); @@ -2680,6 +2696,7 @@ term_erase(struct terminal *term, int start_row, int start_col, sixel_overwrite_by_row(term, end_row, 0, end_col + 1); } +#if defined(FOOT_HAVE_SCROLLBACK) void term_erase_scrollback(struct terminal *term) { @@ -2766,7 +2783,6 @@ term_erase_scrollback(struct terminal *term) term_damage_view(term); } - UNITTEST { const int scrollback_rows = 16; @@ -2893,6 +2909,7 @@ UNITTEST free(term.normal.rows); fdm_destroy(fdm); } +#endif /* FOOT_HAVE_SCROLLBACK */ int term_row_rel_to_abs(const struct terminal *term, int row) @@ -3086,9 +3103,11 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows sixel_scroll_up(term, rows); +#if defined(FOOT_HAVE_SCROLLBACK) /* How many lines from the scrollback start is the current viewport? */ int view_sb_start_distance = grid_row_abs_to_sb( term->grid, term->rows, term->grid->view); +#endif bool view_follows = term->grid->view == term->grid->offset; term->grid->offset += rows; @@ -3098,12 +3117,15 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows term_damage_scroll(term, DAMAGE_SCROLL, region, rows); selection_view_down(term, term->grid->offset); term->grid->view = term->grid->offset; - } else if (unlikely(rows > view_sb_start_distance)) { + } +#if defined(FOOT_HAVE_SCROLLBACK) + else if (unlikely(rows > view_sb_start_distance)) { /* Part of current view is being scrolled out */ int new_view = grid_row_sb_to_abs(term->grid, term->rows, 0); selection_view_down(term, new_view); cmd_scrollback_down(term, rows - view_sb_start_distance); } +#endif /* FOOT_HAVE_SCROLLBACK */ /* Top non-scrolling region. */ for (int i = region.start - 1; i >= 0; i--) @@ -3834,8 +3856,11 @@ term_enable_app_sync_updates(struct terminal *term) /* Disable pending refresh *iff* the grid is the *only* thing * scheduled to be re-rendered */ - if (!term->render.refresh.csd && !term->render.refresh.search && - !term->render.pending.csd && !term->render.pending.search) + if (!term->render.refresh.csd && +#if defined(FOOT_HAVE_SCROLLBACK) + !term->render.refresh.search && !term->render.pending.search && +#endif + !term->render.pending.csd) { term->render.refresh.grid = false; term->render.pending.grid = false; @@ -4487,6 +4512,7 @@ out: return extract_finish(ctx, text, len); } +#if defined(FOOT_HAVE_SCROLLBACK) bool term_scrollback_to_text(const struct terminal *term, char **text, size_t *len) { @@ -4514,6 +4540,7 @@ term_scrollback_to_text(const struct terminal *term, char **text, size_t *len) return rows_to_text(term, start, end, 0, term->cols, text, len); } +#endif /* FOOT_HAVE_SCROLLBACK */ bool term_view_to_text(const struct terminal *term, char **text, size_t *len) diff --git a/terminal.h b/terminal.h index 446d5f23..e29d6431 100644 --- a/terminal.h +++ b/terminal.h @@ -341,8 +341,10 @@ enum selection_kind { SELECTION_BLOCK }; enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT}; +#if defined(FOOT_HAVE_SCROLLBACK) enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN}; enum search_direction { SEARCH_BACKWARD_SAME_POSITION, SEARCH_BACKWARD, SEARCH_FORWARD }; +#endif struct ptmx_buffer { void *data; @@ -365,7 +367,9 @@ enum term_surface { enum overlay_style { OVERLAY_NONE, +#if defined(FOOT_HAVE_SCROLLBACK) OVERLAY_SEARCH, +#endif OVERLAY_FLASH, OVERLAY_UNICODE_MODE, }; @@ -605,13 +609,16 @@ struct terminal { struct range pivot; +#if defined(FOOT_HAVE_SCROLLBACK) struct { int fd; int col; enum selection_scroll_direction direction; } auto_scroll; +#endif } selection; +#if defined(FOOT_HAVE_SCROLLBACK) bool is_searching; struct { char32_t *buf; @@ -629,6 +636,7 @@ struct terminal { size_t len; } last; } search; +#endif /* FOOT_HAVE_SCROLLBACK */ struct wayland *wl; struct wl_window *window; @@ -639,8 +647,10 @@ struct terminal { struct { struct { struct buffer_chain *grid; +#if defined(FOOT_HAVE_SCROLLBACK) struct buffer_chain *search; struct buffer_chain *scrollback_indicator; +#endif struct buffer_chain *render_timer; struct buffer_chain *url; struct buffer_chain *csd; @@ -651,7 +661,9 @@ struct terminal { struct { bool grid; bool csd; +#if defined(FOOT_HAVE_SCROLLBACK) bool search; +#endif bool urls; } refresh; @@ -659,7 +671,9 @@ struct terminal { struct { bool grid; bool csd; +#if defined(FOOT_HAVE_SCROLLBACK) bool search; +#endif bool urls; } pending; @@ -681,7 +695,9 @@ struct terminal { int timer_fd; } app_id; +#if defined(FOOT_HAVE_SCROLLBACK) uint32_t scrollback_lines; /* Number of scrollback lines, from conf (TODO: move out from render struct?) */ +#endif struct { bool enabled; @@ -722,7 +738,9 @@ struct terminal { struct buffer *last_overlay_buf; pixman_region32_t last_overlay_clip; +#if defined(FOOT_HAVE_SCROLLBACK) size_t search_glyph_offset; +#endif struct timespec input_time; } render; @@ -889,7 +907,9 @@ void term_erase( struct terminal *term, int start_row, int start_col, int end_row, int end_col); +#if defined(FOOT_HAVE_SCROLLBACK) void term_erase_scrollback(struct terminal *term); +#endif int term_row_rel_to_abs(const struct terminal *term, int row); void term_cursor_home(struct terminal *term); @@ -958,8 +978,10 @@ void term_disable_app_sync_updates(struct terminal *term); enum term_surface term_surface_kind( const struct terminal *term, const struct wl_surface *surface); +#if defined(FOOT_HAVE_SCROLLBACK) bool term_scrollback_to_text( const struct terminal *term, char **text, size_t *len); +#endif bool term_view_to_text( const struct terminal *term, char **text, size_t *len); bool term_command_output_to_text( diff --git a/tests/test-config.c b/tests/test-config.c index 16cfb2b0..6d651cc4 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -590,6 +590,7 @@ test_section_desktop_notifications(void) config_free(&conf); } +#if defined(FOOT_HAVE_SCROLLBACK) static void test_section_scrollback(void) { @@ -616,6 +617,7 @@ test_section_scrollback(void) config_free(&conf); } +#endif /* FOOT_HAVE_SCROLLBACK */ static void test_section_url(void) @@ -747,6 +749,7 @@ test_section_colors_dark(void) test_two_colors(&ctx, &parse_section_colors_dark, "jump-labels", false, &conf.colors_dark.jump_label.fg, &conf.colors_dark.jump_label.bg); +#if defined(FOOT_HAVE_SCROLLBACK) test_two_colors(&ctx, &parse_section_colors_dark, "scrollback-indicator", false, &conf.colors_dark.scrollback_indicator.fg, &conf.colors_dark.scrollback_indicator.bg); @@ -756,6 +759,7 @@ test_section_colors_dark(void) test_two_colors(&ctx, &parse_section_colors_dark, "search-box-match", false, &conf.colors_dark.search_box.match.fg, &conf.colors_dark.search_box.match.bg); +#endif /* FOOT_HAVE_SCROLLBACK */ test_two_colors(&ctx, &parse_section_colors_dark, "cursor", false, &conf.colors_dark.cursor.text, @@ -828,6 +832,7 @@ test_section_colors_light(void) test_two_colors(&ctx, &parse_section_colors_light, "jump-labels", false, &conf.colors_light.jump_label.fg, &conf.colors_light.jump_label.bg); +#if defined(FOOT_HAVE_SCROLLBACK) test_two_colors(&ctx, &parse_section_colors_light, "scrollback-indicator", false, &conf.colors_light.scrollback_indicator.fg, &conf.colors_light.scrollback_indicator.bg); @@ -837,6 +842,7 @@ test_section_colors_light(void) test_two_colors(&ctx, &parse_section_colors_light, "search-box-match", false, &conf.colors_light.search_box.match.fg, &conf.colors_light.search_box.match.bg); +#endif /* FOOT_HAVE_SCROLLBACK */ test_two_colors(&ctx, &parse_section_colors_light, "cursor", false, &conf.colors_light.cursor.text, @@ -1239,7 +1245,7 @@ test_section_key_bindings(void) &ctx, &parse_section_key_bindings, action, BIND_ACTION_KEY_COUNT - 1, binding_action_map, &conf.bindings.key, KEY_BINDING, - action >= BIND_ACTION_PIPE_SCROLLBACK && action <= BIND_ACTION_PIPE_COMMAND_OUTPUT, + action >= BIND_ACTION_PIPE_FIRST && action <= BIND_ACTION_PIPE_LAST, action >= BIND_ACTION_REGEX_LAUNCH && action <= BIND_ACTION_REGEX_COPY); } @@ -1259,6 +1265,7 @@ test_section_key_bindings_collisions(void) config_free(&conf); } +#if defined(FOOT_HAVE_SCROLLBACK) static void test_section_search_bindings(void) { @@ -1295,6 +1302,7 @@ test_section_search_bindings_collisions(void) config_free(&conf); } +#endif /* FOOT_HAVE_SCROLLBACK */ static void test_section_url_bindings(void) @@ -1534,7 +1542,9 @@ main(int argc, const char *const *argv) test_section_security(); test_section_bell(); test_section_desktop_notifications(); +#if defined(FOOT_HAVE_SCROLLBACK) test_section_scrollback(); +#endif test_section_url(); test_section_cursor(); test_section_mouse(); @@ -1544,8 +1554,10 @@ main(int argc, const char *const *argv) test_section_csd(); test_section_key_bindings(); test_section_key_bindings_collisions(); +#if defined(FOOT_HAVE_SCROLLBACK) test_section_search_bindings(); test_section_search_bindings_collisions(); +#endif test_section_url_bindings(); test_section_url_bindings_collisions(); test_section_mouse_bindings(); diff --git a/unicode-mode.c b/unicode-mode.c index 99a7293d..f3fb138d 100644 --- a/unicode-mode.c +++ b/unicode-mode.c @@ -34,10 +34,14 @@ unicode_mode_updated(struct terminal *term) if (term == NULL) return; - if (term->is_searching) +#if defined(FOOT_HAVE_SCROLLBACK) + if (term->is_searching) { render_refresh_search(term); - else + } else +#endif + { render_refresh(term); + } } void @@ -57,10 +61,14 @@ unicode_mode_input(struct seat *seat, struct terminal *term, term->unicode_mode.character, (int)chars, utf8); if (chars != (size_t)-1) { - if (term->is_searching) +#if defined(FOOT_HAVE_SCROLLBACK) + if (term->is_searching) { search_add_chars(term, utf8, chars); - else + } else +#endif + { term_to_slave(term, utf8, chars); + } } seat->kbd.last_shortcut_sym = sym; diff --git a/wayland.c b/wayland.c index f5737c1e..062b6231 100644 --- a/wayland.c +++ b/wayland.c @@ -2210,6 +2210,7 @@ wayl_win_destroy(struct wl_window *win) wl_surface_commit(win->render_timer.surface.surf); } +#if defined(FOOT_HAVE_SCROLLBACK) if (win->scrollback_indicator.surface.surf != NULL) { wl_surface_attach(win->scrollback_indicator.surface.surf, NULL, 0, 0); wl_surface_commit(win->scrollback_indicator.surface.surf); @@ -2220,6 +2221,7 @@ wayl_win_destroy(struct wl_window *win) wl_surface_attach(win->search.surface.surf, NULL, 0, 0); wl_surface_commit(win->search.surface.surf); } +#endif /* FOOT_HAVE_SCROLLBACK */ /* URLs */ tll_foreach(win->urls, it) { @@ -2253,13 +2255,17 @@ wayl_win_destroy(struct wl_window *win) render_wait_for_preapply_damage(term); csd_destroy(win); +#if defined(FOOT_HAVE_SCROLLBACK) wayl_win_subsurface_destroy(&win->search); wayl_win_subsurface_destroy(&win->scrollback_indicator); +#endif wayl_win_subsurface_destroy(&win->render_timer); wayl_win_subsurface_destroy(&win->overlay); +#if defined(FOOT_HAVE_SCROLLBACK) shm_purge(term->render.chains.search); shm_purge(term->render.chains.scrollback_indicator); +#endif shm_purge(term->render.chains.render_timer); shm_purge(term->render.chains.grid); shm_purge(term->render.chains.url); diff --git a/wayland.h b/wayland.h index 9cbd1023..18994878 100644 --- a/wayland.h +++ b/wayland.h @@ -397,8 +397,10 @@ struct wl_window { bool minimize:1; } wm_capabilities; +#if defined(FOOT_HAVE_SCROLLBACK) struct wayl_sub_surface search; struct wayl_sub_surface scrollback_indicator; +#endif struct wayl_sub_surface render_timer; struct wayl_sub_surface overlay;