Skip to content

Commit

Permalink
Add support for NumLock mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
j4james committed Feb 8, 2024
1 parent 71c35cf commit 32186f2
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/terminal/adapter/DispatchTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
UTF8_EXTENDED_MODE = DECPrivateMode(1005),
SGR_EXTENDED_MODE = DECPrivateMode(1006),
ALTERNATE_SCROLL = DECPrivateMode(1007),
XTERM_NumLockMode = DECPrivateMode(1035),
ASB_AlternateScreenBuffer = DECPrivateMode(1049),
XTERM_BracketedPasteMode = DECPrivateMode(2004),
W32IM_Win32InputMode = DECPrivateMode(9001),
Expand Down
6 changes: 6 additions & 0 deletions src/terminal/adapter/adaptDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1938,6 +1938,9 @@ bool AdaptDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param, con
case DispatchTypes::ModeParams::ALTERNATE_SCROLL:
_terminalInput.SetInputMode(TerminalInput::Mode::AlternateScroll, enable);
return !_PassThroughInputModes();
case DispatchTypes::ModeParams::XTERM_NumLockMode:
_terminalInput.SetInputMode(TerminalInput::Mode::NumLock, enable);
return true;
case DispatchTypes::ModeParams::ASB_AlternateScreenBuffer:
_SetAlternateScreenBufferMode(enable);
return true;
Expand Down Expand Up @@ -2076,6 +2079,9 @@ bool AdaptDispatch::RequestMode(const DispatchTypes::ModeParams param)
case DispatchTypes::ModeParams::ALTERNATE_SCROLL:
enabled = _terminalInput.GetInputMode(TerminalInput::Mode::AlternateScroll);
break;
case DispatchTypes::ModeParams::XTERM_NumLockMode:
enabled = _terminalInput.GetInputMode(TerminalInput::Mode::NumLock);
break;
case DispatchTypes::ModeParams::ASB_AlternateScreenBuffer:
enabled = _usingAltBuffer;
break;
Expand Down
35 changes: 23 additions & 12 deletions src/terminal/input/terminalInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ bool TerminalInput::GetInputMode(const Mode mode) const noexcept

void TerminalInput::ResetInputModes() noexcept
{
_inputMode = { Mode::Ansi, Mode::AutoRepeat, Mode::AlternateScroll };
_inputMode = { Mode::Ansi, Mode::AutoRepeat, Mode::NumLock, Mode::AlternateScroll };
_mouseInputState.lastPos = { -1, -1 };
_mouseInputState.lastButton = 0;
_initKeyboardMap();
Expand Down Expand Up @@ -211,23 +211,34 @@ TerminalInput::OutputType TerminalInput::HandleKey(const INPUT_RECORD& event)
return _makeNoOutput();
}

// NumLock mode is an XTerm extension that changes the behavior of keys on
// the numeric keypad, suppressing the effects of KeyPad mode when NumLock
// is on. This is for compatibility with Linux apps that have a tendency to
// set Keypad mode while not actually wanting the keys to change.
const auto numLockMode = _inputMode.test(Mode::NumLock) && WI_IsFlagSet(controlKeyState, NUMLOCK_ON);

// The only enhanced key we care about is the Return key, because that
// indicates that it's the key on the numeric keypad, which will transmit
// different escape sequences when the Keypad mode is enabled.
const auto enhancedReturnKey = WI_IsFlagSet(controlKeyState, ENHANCED_KEY) && virtualKeyCode == VK_RETURN;
// different escape sequences when the Keypad mode is enabled. But this
// doesn't apply when NumLock mode is active.
const auto enhancedReturnKey = WI_IsFlagSet(controlKeyState, ENHANCED_KEY) && virtualKeyCode == VK_RETURN && !numLockMode;

// Using the control key state that we calculated above, combined with the
// virtual key code, we've got a unique identifier for the key combination
// that we can lookup in our map of predefined key sequences.
auto keyCombo = virtualKeyCode;
WI_SetFlagIf(keyCombo, Ctrl, ctrlIsReallyPressed);
WI_SetFlagIf(keyCombo, Alt, altIsPressed);
WI_SetFlagIf(keyCombo, Shift, shiftIsPressed);
WI_SetFlagIf(keyCombo, Enhanced, enhancedReturnKey);
const auto keyMatch = _keyMap.find(keyCombo);
if (keyMatch != _keyMap.end())
// that we can lookup in our map of predefined key sequences. But this is
// bypassed for numeric keypad keys when NumLock mode is active.
if (!(virtualKeyCode >= VK_NUMPAD0 && virtualKeyCode <= VK_DIVIDE && numLockMode))
{
return keyMatch->second;
auto keyCombo = virtualKeyCode;
WI_SetFlagIf(keyCombo, Ctrl, ctrlIsReallyPressed);
WI_SetFlagIf(keyCombo, Alt, altIsPressed);
WI_SetFlagIf(keyCombo, Shift, shiftIsPressed);
WI_SetFlagIf(keyCombo, Enhanced, enhancedReturnKey);
const auto keyMatch = _keyMap.find(keyCombo);
if (keyMatch != _keyMap.end())
{
return keyMatch->second;
}
}

// If it's not in the key map, we'll use the UnicodeChar, if provided,
Expand Down
3 changes: 2 additions & 1 deletion src/terminal/input/terminalInput.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace Microsoft::Console::VirtualTerminal
Keypad,
CursorKey,
BackarrowKey,
NumLock,
Win32,

Utf8MouseEncoding,
Expand Down Expand Up @@ -77,7 +78,7 @@ namespace Microsoft::Console::VirtualTerminal
std::wstring _focusInSequence;
std::wstring _focusOutSequence;

til::enumset<Mode> _inputMode{ Mode::Ansi, Mode::AutoRepeat, Mode::AlternateScroll };
til::enumset<Mode> _inputMode{ Mode::Ansi, Mode::AutoRepeat, Mode::NumLock, Mode::AlternateScroll };
bool _forceDisableWin32InputMode{ false };

// In the future, if we add support for "8-bit" input mode, these prefixes
Expand Down

0 comments on commit 32186f2

Please sign in to comment.