mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
Merge pull request #1267 from mitchellh/keypad
input: manage application keypad state with mode 1035
This commit is contained in:
@ -1322,6 +1322,7 @@ pub fn keyCallback(
|
||||
.alt_esc_prefix = t.modes.get(.alt_esc_prefix),
|
||||
.cursor_key_application = t.modes.get(.cursor_keys),
|
||||
.keypad_key_application = t.modes.get(.keypad_keys),
|
||||
.ignore_keypad_with_numlock = t.modes.get(.ignore_keypad_with_numlock),
|
||||
.modify_other_keys_state_2 = t.flags.modify_other_keys_2,
|
||||
.kitty_flags = t.screen.kitty_keyboard.current(),
|
||||
};
|
||||
|
@ -26,6 +26,7 @@ macos_option_as_alt: config.OptionAsAlt = .false,
|
||||
alt_esc_prefix: bool = false,
|
||||
cursor_key_application: bool = false,
|
||||
keypad_key_application: bool = false,
|
||||
ignore_keypad_with_numlock: bool = false,
|
||||
modify_other_keys_state_2: bool = false,
|
||||
kitty_flags: KittyFlags = .{},
|
||||
|
||||
@ -245,6 +246,7 @@ fn legacy(
|
||||
all_mods,
|
||||
self.cursor_key_application,
|
||||
self.keypad_key_application,
|
||||
self.ignore_keypad_with_numlock,
|
||||
self.modify_other_keys_state_2,
|
||||
)) |sequence| pc_style: {
|
||||
// If we're pressing enter and have UTF-8 text, we probably are
|
||||
@ -416,7 +418,8 @@ fn pcStyleFunctionKey(
|
||||
keyval: key.Key,
|
||||
mods: key.Mods,
|
||||
cursor_key_application: bool,
|
||||
keypad_key_application: bool,
|
||||
keypad_key_application_req: bool,
|
||||
ignore_keypad_with_numlock: bool,
|
||||
modify_other_keys: bool, // True if state 2
|
||||
) ?[]const u8 {
|
||||
// We only want binding-sensitive mods because lock keys
|
||||
@ -424,6 +427,24 @@ fn pcStyleFunctionKey(
|
||||
// pc-style function keys.
|
||||
const mods_int = mods.binding().int();
|
||||
|
||||
// Keypad application keymode isn't super straightforward.
|
||||
// On xterm, in VT220 mode, numlock alone is enough to trigger
|
||||
// application mode. But in more modern modes, numlock is
|
||||
// ignored by default via mode 1035 (default true). If mode
|
||||
// 1035 is on, we always are in numerical keypad mode. If
|
||||
// mode 1035 is off, we are in application mode if the
|
||||
// proper numlock state is pressed. The numlock state is implicitly
|
||||
// determined based on the keycode sent (i.e. 1 with numlock
|
||||
// on will be kp_end).
|
||||
const keypad_key_application = keypad: {
|
||||
// If we're ignoring keypad then this is always false.
|
||||
// In other words, we're always in numerical keypad mode.
|
||||
if (ignore_keypad_with_numlock) break :keypad false;
|
||||
|
||||
// If we're not ignoring then we enable the desired state.
|
||||
break :keypad keypad_key_application_req;
|
||||
};
|
||||
|
||||
for (function_keys.keys.get(keyval)) |entry| {
|
||||
switch (entry.cursor) {
|
||||
.any => {},
|
||||
@ -1677,6 +1698,70 @@ test "legacy: keypad enter" {
|
||||
try testing.expectEqualStrings("\r", actual);
|
||||
}
|
||||
|
||||
test "legacy: keypad 1" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var enc: KeyEncoder = .{
|
||||
.event = .{
|
||||
.key = .kp_1,
|
||||
.mods = .{},
|
||||
.consumed_mods = .{},
|
||||
.utf8 = "1",
|
||||
},
|
||||
};
|
||||
|
||||
const actual = try enc.legacy(&buf);
|
||||
try testing.expectEqualStrings("1", actual);
|
||||
}
|
||||
|
||||
test "legacy: keypad 1 with application keypad" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var enc: KeyEncoder = .{
|
||||
.event = .{
|
||||
.key = .kp_1,
|
||||
.mods = .{},
|
||||
.consumed_mods = .{},
|
||||
.utf8 = "1",
|
||||
},
|
||||
.keypad_key_application = true,
|
||||
};
|
||||
|
||||
const actual = try enc.legacy(&buf);
|
||||
try testing.expectEqualStrings("\x1bOq", actual);
|
||||
}
|
||||
|
||||
test "legacy: keypad 1 with application keypad and numlock" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var enc: KeyEncoder = .{
|
||||
.event = .{
|
||||
.key = .kp_1,
|
||||
.mods = .{ .num_lock = true },
|
||||
.consumed_mods = .{},
|
||||
.utf8 = "1",
|
||||
},
|
||||
.keypad_key_application = true,
|
||||
};
|
||||
|
||||
const actual = try enc.legacy(&buf);
|
||||
try testing.expectEqualStrings("\x1bOq", actual);
|
||||
}
|
||||
|
||||
test "legacy: keypad 1 with application keypad and numlock ignore" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var enc: KeyEncoder = .{
|
||||
.event = .{
|
||||
.key = .kp_1,
|
||||
.mods = .{ .num_lock = false },
|
||||
.consumed_mods = .{},
|
||||
.utf8 = "1",
|
||||
},
|
||||
.keypad_key_application = true,
|
||||
.ignore_keypad_with_numlock = true,
|
||||
};
|
||||
|
||||
const actual = try enc.legacy(&buf);
|
||||
try testing.expectEqualStrings("1", actual);
|
||||
}
|
||||
|
||||
test "legacy: f1" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var enc: KeyEncoder = .{
|
||||
|
@ -121,6 +121,7 @@ pub const keys = keys: {
|
||||
result.set(.kp_down, pcStyle("\x1b[1;{}B") ++ cursorKey("\x1b[B", "\x1bOB"));
|
||||
result.set(.kp_right, pcStyle("\x1b[1;{}C") ++ cursorKey("\x1b[C", "\x1bOC"));
|
||||
result.set(.kp_left, pcStyle("\x1b[1;{}D") ++ cursorKey("\x1b[D", "\x1bOD"));
|
||||
result.set(.kp_begin, pcStyle("\x1b[1;{}E") ++ cursorKey("\x1b[E", "\x1bOE"));
|
||||
result.set(.kp_home, pcStyle("\x1b[1;{}H") ++ cursorKey("\x1b[H", "\x1bOH"));
|
||||
result.set(.kp_end, pcStyle("\x1b[1;{}F") ++ cursorKey("\x1b[F", "\x1bOF"));
|
||||
result.set(.kp_insert, pcStyle("\x1b[2;{}~") ++ .{.{ .sequence = "\x1B[2~" }});
|
||||
|
@ -206,6 +206,7 @@ const entries: []const ModeEntry = &.{
|
||||
.{ .name = "mouse_alternate_scroll", .value = 1007, .default = true },
|
||||
.{ .name = "mouse_format_urxvt", .value = 1015 },
|
||||
.{ .name = "mouse_format_sgr_pixels", .value = 1016 },
|
||||
.{ .name = "ignore_keypad_with_numlock", .value = 1035, .default = true },
|
||||
.{ .name = "alt_esc_prefix", .value = 1036, .default = true },
|
||||
.{ .name = "alt_sends_escape", .value = 1039 },
|
||||
.{ .name = "reverse_wrap_extended", .value = 1045 },
|
||||
|
Reference in New Issue
Block a user