Add support for application keypad mode (DECKPAM) #21022

Open
opened 2026-01-31 07:30:55 +00:00 by claunia · 0 comments
Owner

Originally created by @j4james on GitHub (Dec 30, 2023).

Description of the new feature/enhancement

Looking through the old issues, I see I already noted back in #159 that DECKPAM didn't appear to be working. I assumed at the time that it was a configuration issue, or possibly a minor bug in the implementation, but I've only realised now that this mode doesn't do anything at all.

We do already parse the DECKPAM and DECKPNM escape sequences, and I even recently added support for DECNKM, which is an alias of that functionality, but the mode doesn't actually have any effect. It switches between two key mapping tables in the TerminalInput class, but they're essentially identical.

This mode is useful because it provides a way for applications to distinguish the keypad keys from the top row numeric keys and arithmetic keys, as well as distinguishing the two Return keys.

Proposed technical implementation details (optional)

If we just want a simple solution, we can probably just update the existing mapping table, although it might be a little more complicated than that to handle the modifiers.

My preferred approach, though, is essentially a rewrite of the TerminalInput class, which is something I've been working on for a while. In addition to the application keypad support, it also prepares the way for future VT enhancements, and fixes a bunch of other keyboard issue.

The way it works is there's a single keyboard map, that takes a virtual key code combined with Ctrl, Alt, and Shift modifier bits as the key, and the appropiate VT sequence as the value. This map is initially built at startup, and then regenerated whenever a keyboard mode is changed.

That takes care of the "functional" keys (cursor keys, editing keys, function keys, and things like BkSp, Tab, and Return). But if the key-modifier combination is not in that map, I do the following:

  1. If the active keyboard layout has given us a UnicodeChar value, that takes priority. Although that can often still need to be "extended" with a Ctrl modifier that converts the value into a C0 control, and/or an Alt modifier that add an ESC prefix.

  2. If there isn't a UnicodeChar value, we need to calculate what value the would have been without any Ctrl or Alt modifiers applied (you can do this with the ToUnicodeEx API). And once we have that value, we can then manually apply the Ctrl and Alt modifiers as described above.

There are a whole lot of edge cases that also need to be dealt with, but that's the main gist of my proposal.

Originally created by @j4james on GitHub (Dec 30, 2023). # Description of the new feature/enhancement Looking through the old issues, I see I already noted back in #159 that `DECKPAM` didn't appear to be working. I assumed at the time that it was a configuration issue, or possibly a minor bug in the implementation, but I've only realised now that this mode doesn't do anything at all. We do already parse the `DECKPAM` and `DECKPNM` escape sequences, and I even recently added support for `DECNKM`, which is an alias of that functionality, but the mode doesn't actually have any effect. It switches between two key mapping tables in the `TerminalInput` class, but they're essentially identical. This mode is useful because it provides a way for applications to distinguish the keypad keys from the top row numeric keys and arithmetic keys, as well as distinguishing the two <kbd>Return</kbd> keys. # Proposed technical implementation details (optional) If we just want a simple solution, we can probably just update the existing mapping table, although it might be a little more complicated than that to handle the modifiers. My preferred approach, though, is essentially a rewrite of the `TerminalInput` class, which is something I've been working on for a while. In addition to the application keypad support, it also prepares the way for future VT enhancements, and fixes a bunch of other keyboard issue. The way it works is there's a single keyboard map, that takes a virtual key code combined with <kbd>Ctrl</kbd>, <kbd>Alt</kbd>, and <kbd>Shift</kbd> modifier bits as the key, and the appropiate VT sequence as the value. This map is initially built at startup, and then regenerated whenever a keyboard mode is changed. That takes care of the "functional" keys (cursor keys, editing keys, function keys, and things like <kbd>BkSp</kbd>, <kbd>Tab</kbd>, and <kbd>Return</kbd>). But if the key-modifier combination is not in that map, I do the following: 1. If the active keyboard layout has given us a `UnicodeChar` value, that takes priority. Although that can often still need to be "extended" with a <kbd>Ctrl</kbd> modifier that converts the value into a C0 control, and/or an <kbd>Alt</kbd> modifier that add an `ESC` prefix. 2. If there isn't a `UnicodeChar` value, we need to calculate what value the would have been _without_ any <kbd>Ctrl</kbd> or <kbd>Alt</kbd> modifiers applied (you can do this with the `ToUnicodeEx` API). And once we have that value, we can then manually apply the <kbd>Ctrl</kbd> and <kbd>Alt</kbd> modifiers as described above. There are a whole lot of edge cases that also need to be dealt with, but that's the main gist of my proposal.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#21022