diff --git a/CHANGELOG.md b/CHANGELOG.md index 468f897d..365eb7f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,9 @@ * Blinking text now uses the foreground color, but dimmed down in its off state, instead of the background color. +* Num Lock by default overrides the keypad mode. See + **foot.ini**(5)::KEYPAD, or [README.md](README.md#keypad) for + details (https://codeberg.org/dnkl/foot/issues/194). ### Deprecated diff --git a/README.md b/README.md index bcbddecd..8bf12bf8 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ The fast, lightweight and minimalistic Wayland terminal emulator. 1. [Server (daemon) mode](#server-daemon-mode) 1. [Alt/meta](#alt-meta) 1. [Backspace](#backspace) +1. [Keypad](#keypad) 1. [DPI and font size](#dpi-and-font-size) 1. [Supported OSCs](#supported-oscs) 1. [Programmatically checking if running in foot](#programmatically-checking-if-running-in-foot) @@ -270,6 +271,25 @@ Finally, pressing alt will prefix the transmitted byte with ESC. +## KEYPAD + +By default, Num Lock overrides the run-time configuration +keypad mode; when active, the keypad is always considered to be in +_numerical_ mode. This corresponds to XTerm's `numLock` option set to +`true`. + +In this mode, the keypad keys always sends either numbers (Num +Lock is **active**) or cursor movement keys (Up, +Down, Left, Right, Page +Up, Page Down etc). + +This can be disabled programmatically with `\E[?1035l` (and enabled +again with `\E[?1035h`). + +When disabled, the keypad sends custom escape sequences instead of +numbers, when in _application_ mode. + + ## DPI and font size Font sizes are apparently a complex thing. Many applications use a diff --git a/csi.c b/csi.c index c1982275..80f2bfd0 100644 --- a/csi.c +++ b/csi.c @@ -470,6 +470,12 @@ decset_decrst(struct terminal *term, unsigned param, bool enable) term->meta.eight_bit = enable; break; + case 1035: + /* numLock */ + LOG_DBG("%s Num Lock modifier", enable ? "enabling" : "disabling"); + term->num_lock_modifier = enable; + break; + case 1036: /* metaSendsEscape */ LOG_DBG("%s meta-sends-escape", enable ? "enabling" : "disabling"); @@ -592,6 +598,7 @@ xtsave(struct terminal *term, unsigned param) case 1007: term->xtsave.alt_scrolling = term->alt_scrolling; break; case 1015: term->xtsave.mouse_urxvt = term->mouse_reporting == MOUSE_URXVT; break; case 1034: term->xtsave.meta_eight_bit = term->meta.eight_bit; break; + case 1035: term->xtsave.num_lock_modifier = term->num_lock_modifier; break; case 1036: term->xtsave.meta_esc_prefix = term->meta.esc_prefix; break; case 1042: term->xtsave.bell_is_urgent = term->bell_is_urgent; break; case 1049: term->xtsave.alt_screen = term->grid == &term->alt; break; @@ -624,6 +631,7 @@ xtrestore(struct terminal *term, unsigned param) case 1007: enable = term->xtsave.alt_scrolling; break; case 1015: enable = term->xtsave.mouse_urxvt; break; case 1034: enable = term->xtsave.meta_eight_bit; break; + case 1035: enable = term->xtsave.num_lock_modifier; break; case 1036: enable = term->xtsave.meta_esc_prefix; break; case 1042: enable = term->xtsave.bell_is_urgent; break; case 1049: enable = term->xtsave.alt_screen; break; diff --git a/doc/foot.1.scd b/doc/foot.1.scd index e8460cc7..e3be3013 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -267,6 +267,23 @@ described above *cannot* be changed. Finally, pressing *alt* will prefix the transmitted byte with ESC. +# KEYPAD + +By default, *Num Lock* overrides the run-time configuration keypad +mode; when active, the keypad is always considered to be in +_numerical_ mode. This corresponds to XTerm's *numLock* option set to +*true*. + +In this mode, the keypad keys always sends either numbers (Num Lock is +active) or cursor movement keys (up, down, left, right, page up, page +down etc). + +This can be disabled programmatically with *\E[?1035l* (and enabled +again with *\E[?1035h*). + +When disabled, the keypad sends custom escape sequences instead of +numbers, when in _application_ mode. + # CONFIGURATION See *foot.ini*(5) diff --git a/foot.ini b/foot.ini index 8f8d4493..b22ed049 100644 --- a/foot.ini +++ b/foot.ini @@ -84,7 +84,6 @@ # pipe-scrollback=[sh -c "xurls | bemenu | xargs -r firefox"] none # pipe-selected=[xargs -r firefox] none - [search-bindings] # cancel=Control+g Escape # commit=Return diff --git a/input.c b/input.c index 5d21a3bc..d455a473 100644 --- a/input.c +++ b/input.c @@ -526,10 +526,11 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, if (seat->kbd.xkb_keymap != NULL) { seat->kbd.xkb_state = xkb_state_new(seat->kbd.xkb_keymap); - seat->kbd.mod_shift = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Shift"); - seat->kbd.mod_alt = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Mod1") ; - seat->kbd.mod_ctrl = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Control"); - seat->kbd.mod_meta = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, "Mod4"); + seat->kbd.mod_shift = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, XKB_MOD_NAME_SHIFT); + seat->kbd.mod_alt = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, XKB_MOD_NAME_ALT) ; + seat->kbd.mod_ctrl = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, XKB_MOD_NAME_CTRL); + seat->kbd.mod_meta = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, XKB_MOD_NAME_LOGO); + seat->kbd.mod_num = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, XKB_MOD_NAME_NUM); seat->kbd.key_arrow_up = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "UP"); seat->kbd.key_arrow_down = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "DOWN"); @@ -632,6 +633,7 @@ keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, seat->kbd.alt = false; seat->kbd.ctrl = false; seat->kbd.meta = false; + seat->kbd.num = false; if (seat->kbd.xkb_compose_state != NULL) xkb_compose_state_reset(seat->kbd.xkb_compose_state); @@ -739,7 +741,8 @@ keymap_data_for_sym(xkb_keysym_t sym, size_t *count) } static const struct key_data * -keymap_lookup(struct terminal *term, xkb_keysym_t sym, enum modifier mods) +keymap_lookup(struct seat *seat, struct terminal *term, + xkb_keysym_t sym, enum modifier mods) { size_t count; const struct key_data *info = keymap_data_for_sym(sym, &count); @@ -747,16 +750,22 @@ keymap_lookup(struct terminal *term, xkb_keysym_t sym, enum modifier mods) if (info == NULL) return NULL; + const enum cursor_keys cursor_keys_mode = term->cursor_keys_mode; + const enum keypad_keys keypad_keys_mode + = (term->num_lock_modifier && seat->kbd.num + ? KEYPAD_NUMERICAL + : term->keypad_keys_mode); + for (size_t j = 0; j < count; j++) { if (info[j].modifiers != MOD_ANY && info[j].modifiers != mods) continue; if (info[j].cursor_keys_mode != CURSOR_KEYS_DONTCARE && - info[j].cursor_keys_mode != term->cursor_keys_mode) + info[j].cursor_keys_mode != cursor_keys_mode) continue; if (info[j].keypad_keys_mode != KEYPAD_DONTCARE && - info[j].keypad_keys_mode != term->keypad_keys_mode) + info[j].keypad_keys_mode != keypad_keys_mode) continue; return &info[j]; @@ -882,7 +891,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, keymap_mods |= seat->kbd.ctrl ? MOD_CTRL : MOD_NONE; keymap_mods |= seat->kbd.meta ? MOD_META : MOD_NONE; - const struct key_data *keymap = keymap_lookup(term, sym, keymap_mods); + const struct key_data *keymap = keymap_lookup(seat, term, sym, keymap_mods); if (keymap != NULL) { term_to_slave(term, keymap->seq, strlen(keymap->seq)); @@ -1047,6 +1056,8 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, seat->kbd.xkb_state, seat->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED); seat->kbd.meta = xkb_state_mod_index_is_active( seat->kbd.xkb_state, seat->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED); + seat->kbd.num = xkb_state_mod_index_is_active( + seat->kbd.xkb_state, seat->kbd.mod_num, XKB_STATE_MODS_LOCKED); } if (seat->kbd_focus && seat->kbd_focus->active_surface == TERM_SURF_GRID) diff --git a/terminal.c b/terminal.c index b9e4528a..d117bf9c 100644 --- a/terminal.c +++ b/terminal.c @@ -1047,6 +1047,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .esc_prefix = true, .eight_bit = true, }, + .num_lock_modifier = true, .bell_is_urgent = conf->bell_is_urgent, .tab_stops = tll_init(), .wl = wayl, diff --git a/terminal.h b/terminal.h index 6a8e340b..5c7a9501 100644 --- a/terminal.h +++ b/terminal.h @@ -252,6 +252,7 @@ struct terminal { bool eight_bit; } meta; + bool num_lock_modifier; bool bell_is_urgent; /* Saved DECSET modes - we save the SET state */ @@ -275,6 +276,7 @@ struct terminal { uint32_t mouse_urxvt:1; uint32_t meta_eight_bit:1; uint32_t meta_esc_prefix:1; + uint32_t num_lock_modifier:1; uint32_t bell_is_urgent:1; uint32_t alt_screen:1; } xtsave; diff --git a/wayland.h b/wayland.h index ac6dd9a7..7bf5eb80 100644 --- a/wayland.h +++ b/wayland.h @@ -163,6 +163,7 @@ struct seat { xkb_mod_index_t mod_alt; xkb_mod_index_t mod_ctrl; xkb_mod_index_t mod_meta; + xkb_mod_index_t mod_num; xkb_keycode_t key_arrow_up; xkb_keycode_t key_arrow_down; @@ -172,6 +173,7 @@ struct seat { bool alt; bool ctrl; bool meta; + bool num; struct { tll(struct key_binding_normal) key;