mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
Merge pull request #1075 from rockorager/keypad
fix: keypad key encoding on GTK
This commit is contained in:
@ -286,6 +286,18 @@ typedef enum {
|
|||||||
GHOSTTY_KEY_KP_ADD,
|
GHOSTTY_KEY_KP_ADD,
|
||||||
GHOSTTY_KEY_KP_ENTER,
|
GHOSTTY_KEY_KP_ENTER,
|
||||||
GHOSTTY_KEY_KP_EQUAL,
|
GHOSTTY_KEY_KP_EQUAL,
|
||||||
|
GHOSTTY_KEY_KP_SEPARATOR,
|
||||||
|
GHOSTTY_KEY_KP_LEFT,
|
||||||
|
GHOSTTY_KEY_KP_RIGHT,
|
||||||
|
GHOSTTY_KEY_KP_UP,
|
||||||
|
GHOSTTY_KEY_KP_DOWN,
|
||||||
|
GHOSTTY_KEY_KP_PAGE_UP,
|
||||||
|
GHOSTTY_KEY_KP_PAGE_DOWN,
|
||||||
|
GHOSTTY_KEY_KP_HOME,
|
||||||
|
GHOSTTY_KEY_KP_END,
|
||||||
|
GHOSTTY_KEY_KP_INSERT,
|
||||||
|
GHOSTTY_KEY_KP_DELETE,
|
||||||
|
GHOSTTY_KEY_KP_BEGIN,
|
||||||
|
|
||||||
// modifiers
|
// modifiers
|
||||||
GHOSTTY_KEY_LEFT_SHIFT,
|
GHOSTTY_KEY_LEFT_SHIFT,
|
||||||
|
@ -1333,6 +1333,10 @@ fn keyEvent(
|
|||||||
// event.
|
// event.
|
||||||
const mods = mods: {
|
const mods = mods: {
|
||||||
var mods = translateMods(gtk_mods);
|
var mods = translateMods(gtk_mods);
|
||||||
|
|
||||||
|
const device = c.gdk_event_get_device(event);
|
||||||
|
mods.num_lock = c.gdk_device_get_num_lock_state(device) == 1;
|
||||||
|
|
||||||
switch (physical_key) {
|
switch (physical_key) {
|
||||||
.left_shift => {
|
.left_shift => {
|
||||||
mods.shift = action == .press;
|
mods.shift = action == .press;
|
||||||
@ -1376,6 +1380,7 @@ fn keyEvent(
|
|||||||
|
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
break :mods mods;
|
break :mods mods;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1389,6 +1394,13 @@ fn keyEvent(
|
|||||||
// If we're not in a dead key state, we want to translate our text
|
// If we're not in a dead key state, we want to translate our text
|
||||||
// to some input.Key.
|
// to some input.Key.
|
||||||
const key = if (!self.im_composing) key: {
|
const key = if (!self.im_composing) key: {
|
||||||
|
// First, try to convert the keyval directly to a key. This allows the
|
||||||
|
// use of key remapping and identification of keypad numerics (as
|
||||||
|
// opposed to their ASCII counterparts)
|
||||||
|
if (gtk_key.keyFromKeyval(keyval)) |key| {
|
||||||
|
break :key key;
|
||||||
|
}
|
||||||
|
|
||||||
// A completed key. If the length of the key is one then we can
|
// A completed key. If the length of the key is one then we can
|
||||||
// attempt to translate it to a key enum and call the key
|
// attempt to translate it to a key enum and call the key
|
||||||
// callback. First try plain ASCII.
|
// callback. First try plain ASCII.
|
||||||
@ -1414,12 +1426,6 @@ fn keyEvent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before using the physical key, try to convert the keyval
|
|
||||||
// directly to a key. This allows the use of key remapping.
|
|
||||||
if (gtk_key.keyFromKeyval(keyval)) |key| {
|
|
||||||
break :key key;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have im text then this is invalid. This means that
|
// If we have im text then this is invalid. This means that
|
||||||
// the keypress generated some character that we don't know about
|
// the keypress generated some character that we don't know about
|
||||||
// in our key enum. We don't want to use the physical key because
|
// in our key enum. We don't want to use the physical key because
|
||||||
|
@ -190,16 +190,18 @@ const keymap: []const RawEntry = &.{
|
|||||||
.{ c.GDK_KEY_KP_Enter, .kp_enter },
|
.{ c.GDK_KEY_KP_Enter, .kp_enter },
|
||||||
.{ c.GDK_KEY_KP_Equal, .kp_equal },
|
.{ c.GDK_KEY_KP_Equal, .kp_equal },
|
||||||
|
|
||||||
// These are all just aliases to the non-kp variants because Ghostty
|
.{ c.GDK_KEY_KP_Separator, .kp_separator },
|
||||||
// core doesn't distinguish between them currently.
|
.{ c.GDK_KEY_KP_Left, .kp_left },
|
||||||
.{ c.GDK_KEY_KP_Home, .home },
|
.{ c.GDK_KEY_KP_Right, .kp_right },
|
||||||
.{ c.GDK_KEY_KP_End, .end },
|
.{ c.GDK_KEY_KP_Up, .kp_up },
|
||||||
.{ c.GDK_KEY_KP_Page_Up, .page_up },
|
.{ c.GDK_KEY_KP_Down, .kp_down },
|
||||||
.{ c.GDK_KEY_KP_Page_Down, .page_down },
|
.{ c.GDK_KEY_KP_Page_Up, .kp_page_up },
|
||||||
.{ c.GDK_KEY_KP_Up, .up },
|
.{ c.GDK_KEY_KP_Page_Down, .kp_page_down },
|
||||||
.{ c.GDK_KEY_KP_Down, .down },
|
.{ c.GDK_KEY_KP_Home, .kp_home },
|
||||||
.{ c.GDK_KEY_KP_Right, .right },
|
.{ c.GDK_KEY_KP_End, .kp_end },
|
||||||
.{ c.GDK_KEY_KP_Left, .left },
|
.{ c.GDK_KEY_KP_Insert, .kp_insert },
|
||||||
|
.{ c.GDK_KEY_KP_Delete, .kp_delete },
|
||||||
|
.{ c.GDK_KEY_KP_Begin, .kp_begin },
|
||||||
|
|
||||||
.{ c.GDK_KEY_Shift_L, .left_shift },
|
.{ c.GDK_KEY_Shift_L, .left_shift },
|
||||||
.{ c.GDK_KEY_Control_L, .left_control },
|
.{ c.GDK_KEY_Control_L, .left_control },
|
||||||
@ -209,4 +211,6 @@ const keymap: []const RawEntry = &.{
|
|||||||
.{ c.GDK_KEY_Control_R, .right_control },
|
.{ c.GDK_KEY_Control_R, .right_control },
|
||||||
.{ c.GDK_KEY_Alt_R, .right_alt },
|
.{ c.GDK_KEY_Alt_R, .right_alt },
|
||||||
.{ c.GDK_KEY_Super_R, .right_super },
|
.{ c.GDK_KEY_Super_R, .right_super },
|
||||||
|
|
||||||
|
// TODO: media keys
|
||||||
};
|
};
|
||||||
|
@ -117,6 +117,16 @@ pub const keys = keys: {
|
|||||||
result.set(.kp_subtract, kpDefault("m") ++ pcStyle("\x1bO{}m"));
|
result.set(.kp_subtract, kpDefault("m") ++ pcStyle("\x1bO{}m"));
|
||||||
result.set(.kp_add, kpDefault("k") ++ pcStyle("\x1bO{}k"));
|
result.set(.kp_add, kpDefault("k") ++ pcStyle("\x1bO{}k"));
|
||||||
result.set(.kp_enter, kpDefault("M") ++ pcStyle("\x1bO{}M") ++ .{.{ .sequence = "\r" }});
|
result.set(.kp_enter, kpDefault("M") ++ pcStyle("\x1bO{}M") ++ .{.{ .sequence = "\r" }});
|
||||||
|
result.set(.kp_up, pcStyle("\x1b[1;{}A") ++ cursorKey("\x1b[A", "\x1bOA"));
|
||||||
|
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_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~" }});
|
||||||
|
result.set(.kp_delete, pcStyle("\x1b[3;{}~") ++ .{.{ .sequence = "\x1B[3~" }});
|
||||||
|
result.set(.kp_page_up, pcStyle("\x1b[5;{}~") ++ .{.{ .sequence = "\x1B[5~" }});
|
||||||
|
result.set(.kp_page_down, pcStyle("\x1b[6;{}~") ++ .{.{ .sequence = "\x1B[6~" }});
|
||||||
|
|
||||||
result.set(.backspace, &.{
|
result.set(.backspace, &.{
|
||||||
// Modify Keys Normal
|
// Modify Keys Normal
|
||||||
|
@ -344,6 +344,20 @@ pub const Key = enum(c_int) {
|
|||||||
kp_add,
|
kp_add,
|
||||||
kp_enter,
|
kp_enter,
|
||||||
kp_equal,
|
kp_equal,
|
||||||
|
kp_separator,
|
||||||
|
kp_left,
|
||||||
|
kp_right,
|
||||||
|
kp_up,
|
||||||
|
kp_down,
|
||||||
|
kp_page_up,
|
||||||
|
kp_page_down,
|
||||||
|
kp_home,
|
||||||
|
kp_end,
|
||||||
|
kp_insert,
|
||||||
|
kp_delete,
|
||||||
|
kp_begin,
|
||||||
|
|
||||||
|
// TODO: media keys
|
||||||
|
|
||||||
// modifiers
|
// modifiers
|
||||||
left_shift,
|
left_shift,
|
||||||
@ -552,6 +566,20 @@ pub const Key = enum(c_int) {
|
|||||||
.kp_add => cimgui.c.ImGuiKey_KeypadAdd,
|
.kp_add => cimgui.c.ImGuiKey_KeypadAdd,
|
||||||
.kp_enter => cimgui.c.ImGuiKey_KeypadEnter,
|
.kp_enter => cimgui.c.ImGuiKey_KeypadEnter,
|
||||||
.kp_equal => cimgui.c.ImGuiKey_KeypadEqual,
|
.kp_equal => cimgui.c.ImGuiKey_KeypadEqual,
|
||||||
|
// We map KP_SEPARATOR to Comma because traditionally a numpad would
|
||||||
|
// have a numeric separator key. Most modern numpads do not
|
||||||
|
.kp_separator => cimgui.c.ImGuiKey_Comma,
|
||||||
|
.kp_left => cimgui.c.ImGuiKey_LeftArrow,
|
||||||
|
.kp_right => cimgui.c.ImGuiKey_RightArrow,
|
||||||
|
.kp_up => cimgui.c.ImGuiKey_UpArrow,
|
||||||
|
.kp_down => cimgui.c.ImGuiKey_DownArrow,
|
||||||
|
.kp_page_up => cimgui.c.ImGuiKey_PageUp,
|
||||||
|
.kp_page_down => cimgui.c.ImGuiKey_PageUp,
|
||||||
|
.kp_home => cimgui.c.ImGuiKey_Home,
|
||||||
|
.kp_end => cimgui.c.ImGuiKey_End,
|
||||||
|
.kp_insert => cimgui.c.ImGuiKey_Insert,
|
||||||
|
.kp_delete => cimgui.c.ImGuiKey_Delete,
|
||||||
|
.kp_begin => cimgui.c.ImGuiKey_NamedKey_BEGIN,
|
||||||
|
|
||||||
.left_shift => cimgui.c.ImGuiKey_LeftShift,
|
.left_shift => cimgui.c.ImGuiKey_LeftShift,
|
||||||
.left_control => cimgui.c.ImGuiKey_LeftCtrl,
|
.left_control => cimgui.c.ImGuiKey_LeftCtrl,
|
||||||
|
@ -328,18 +328,17 @@ pub const raw_entries: []const RawEntry = &.{
|
|||||||
.{ 0x070057, 0x004e, 0x0056, 0x004e, 0x0045, "NumpadAdd" },
|
.{ 0x070057, 0x004e, 0x0056, 0x004e, 0x0045, "NumpadAdd" },
|
||||||
|
|
||||||
.{ 0x070058, 0x0060, 0x0068, 0xe01c, 0x004c, "NumpadEnter" },
|
.{ 0x070058, 0x0060, 0x0068, 0xe01c, 0x004c, "NumpadEnter" },
|
||||||
.{ 0x070059, 0x004f, 0x0057, 0x004f, 0x0053, "Numpad1" },
|
.{ 0x070059, 0x004f, 0x0057, 0x004f, 0x0053, "Numpad1" }, // +End
|
||||||
.{ 0x07005a, 0x0050, 0x0058, 0x0050, 0x0054, "Numpad2" },
|
.{ 0x07005a, 0x0050, 0x0058, 0x0050, 0x0054, "Numpad2" }, // +Down
|
||||||
.{ 0x07005b, 0x0051, 0x0059, 0x0051, 0x0055, "Numpad3" },
|
.{ 0x07005b, 0x0051, 0x0059, 0x0051, 0x0055, "Numpad3" }, // +PageDown
|
||||||
.{ 0x07005c, 0x004b, 0x0053, 0x004b, 0x0056, "Numpad4" },
|
.{ 0x07005c, 0x004b, 0x0053, 0x004b, 0x0056, "Numpad4" }, // +Left
|
||||||
.{ 0x07005d, 0x004c, 0x0054, 0x004c, 0x0057, "Numpad5" },
|
.{ 0x07005d, 0x004c, 0x0054, 0x004c, 0x0057, "Numpad5" },
|
||||||
.{ 0x07005e, 0x004d, 0x0055, 0x004d, 0x0058, "Numpad6" },
|
.{ 0x07005e, 0x004d, 0x0055, 0x004d, 0x0058, "Numpad6" }, // +Right
|
||||||
.{ 0x07005f, 0x0047, 0x004f, 0x0047, 0x0059, "Numpad7" },
|
.{ 0x07005f, 0x0047, 0x004f, 0x0047, 0x0059, "Numpad7" }, // +Home
|
||||||
|
.{ 0x070060, 0x0048, 0x0050, 0x0048, 0x005b, "Numpad8" }, // +Up
|
||||||
.{ 0x070060, 0x0048, 0x0050, 0x0048, 0x005b, "Numpad8" },
|
.{ 0x070061, 0x0049, 0x0051, 0x0049, 0x005c, "Numpad9" }, // +PageUp
|
||||||
.{ 0x070061, 0x0049, 0x0051, 0x0049, 0x005c, "Numpad9" },
|
.{ 0x070062, 0x0052, 0x005a, 0x0052, 0x0052, "Numpad0" }, // +Insert
|
||||||
.{ 0x070062, 0x0052, 0x005a, 0x0052, 0x0052, "Numpad0" },
|
.{ 0x070063, 0x0053, 0x005b, 0x0053, 0x0041, "NumpadDecimal" }, // +Delete
|
||||||
.{ 0x070063, 0x0053, 0x005b, 0x0053, 0x0041, "NumpadDecimal" },
|
|
||||||
// USB#070064 is not present on US keyboard.
|
// USB#070064 is not present on US keyboard.
|
||||||
// This key is typically located near LeftShift key.
|
// This key is typically located near LeftShift key.
|
||||||
// The keycap varies on international keyboards:
|
// The keycap varies on international keyboards:
|
||||||
|
@ -104,6 +104,20 @@ const raw_entries: []const RawEntry = &.{
|
|||||||
.{ .kp_add, 57413, 'u', false },
|
.{ .kp_add, 57413, 'u', false },
|
||||||
.{ .kp_enter, 57414, 'u', false },
|
.{ .kp_enter, 57414, 'u', false },
|
||||||
.{ .kp_equal, 57415, 'u', false },
|
.{ .kp_equal, 57415, 'u', false },
|
||||||
|
.{ .kp_separator, 57416, 'u', false },
|
||||||
|
.{ .kp_left, 57417, 'u', false },
|
||||||
|
.{ .kp_right, 57418, 'u', false },
|
||||||
|
.{ .kp_up, 57419, 'u', false },
|
||||||
|
.{ .kp_down, 57420, 'u', false },
|
||||||
|
.{ .kp_page_up, 57421, 'u', false },
|
||||||
|
.{ .kp_page_down, 57422, 'u', false },
|
||||||
|
.{ .kp_home, 57423, 'u', false },
|
||||||
|
.{ .kp_end, 57424, 'u', false },
|
||||||
|
.{ .kp_insert, 57425, 'u', false },
|
||||||
|
.{ .kp_delete, 57426, 'u', false },
|
||||||
|
.{ .kp_begin, 57427, 'u', false },
|
||||||
|
|
||||||
|
// TODO: media keys
|
||||||
|
|
||||||
.{ .left_shift, 57441, 'u', true },
|
.{ .left_shift, 57441, 'u', true },
|
||||||
.{ .right_shift, 57447, 'u', true },
|
.{ .right_shift, 57447, 'u', true },
|
||||||
|
Reference in New Issue
Block a user