From 75bd780f0296b7a9b73068a05fc367c435455cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 11 Nov 2020 18:25:54 +0100 Subject: [PATCH 1/5] input: use XKB_MOD_NAME_* macros instead of hard-coded strings --- input.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/input.c b/input.c index 5d21a3bc..913b68dc 100644 --- a/input.c +++ b/input.c @@ -526,10 +526,10 @@ 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.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"); From 2382d6b4487cc9d599578034db8117eb3f1cc75f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 11 Nov 2020 18:26:47 +0100 Subject: [PATCH 2/5] =?UTF-8?q?csi:=20implement=20=E2=80=9CCSI=20=3F=20103?= =?UTF-8?q?5=E2=80=9D=20-=20toggle=20Num=20Lock=20override?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a num_lock_modifier state to the terminal, and hooks up “CSI?1035h/l” to toggle it. --- csi.c | 8 ++++++++ terminal.c | 1 + terminal.h | 2 ++ 3 files changed, 11 insertions(+) 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/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; From bdaf20ba71fe9ae5222f259e286f627c36603732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 11 Nov 2020 18:28:13 +0100 Subject: [PATCH 3/5] input: track num lock state --- input.c | 4 ++++ wayland.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/input.c b/input.c index 913b68dc..4c59a555 100644 --- a/input.c +++ b/input.c @@ -530,6 +530,7 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, 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); @@ -1047,6 +1049,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/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; From deb2c2db6d153c6f9e89a3180180edda5bc6786c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 11 Nov 2020 18:28:37 +0100 Subject: [PATCH 4/5] =?UTF-8?q?input:=20enforce=20=E2=80=98numerical?= =?UTF-8?q?=E2=80=99=20keypad=20mode=20when=20Num=20Lock=20override=20is?= =?UTF-8?q?=20enabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When num lock override has been enabled via “CSI?1035h” (the default), keypad is always considered to be in ‘numerical’ mode. This affects how keypad keys are translated to escape sequences when Num Lock is active. The keypad has four modes: * Num Lock off, numerical mode * Num Lock off, application mode * Num Lock on, numerical mode * Num Lock on, application mode The keymap is identical for numerical and application mode when Num Lock is off, meaning the keypad effectively has three different modes. In XTerm, numerical and application mode _can_ be the same, **if** the ‘numLock’ resource is set to true (the default). It is only when ‘numLock’ is false that the application mode is actually used. This patch changes foot to do the same. We don’t expose an option, but do implement “CSI ? 1035”. Closes #194 --- input.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/input.c b/input.c index 4c59a555..d455a473 100644 --- a/input.c +++ b/input.c @@ -741,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); @@ -749,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]; @@ -884,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)); From 2af65471a6a575c3de6c124a520e3bb22a823a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 11 Nov 2020 18:37:28 +0100 Subject: [PATCH 5/5] readme/doc:foot.1: document the (new) keypad behavior --- CHANGELOG.md | 3 +++ README.md | 20 ++++++++++++++++++++ doc/foot.1.scd | 17 +++++++++++++++++ foot.ini | 1 - 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 645b6eeb..c66a98b1 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/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