From d90d82a4b74e37c531e64ea723fe1dfb52c7d9eb Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Tue, 7 Jan 2025 00:44:20 -0700 Subject: [PATCH] win32 gui: remove bespoke/incorrect key translation I played around with the API a bit and I tried out the other approach where instead of trying to implement our own keyboard translation, instead I just clear the "control key" before calling ToUnicode. This fixes any weird translation the OS was doing. With this change, we no longer need to skip calling ToUnicode if the control or alt keys are down, so keys will always work the same way whether or not these modifiers are down. --- src/keybind/builtin/emacs.json | 10 ++++--- src/keybind/parse_flow.zig | 1 + src/win32/gui.zig | 54 ++++++++++++---------------------- 3 files changed, 25 insertions(+), 40 deletions(-) diff --git a/src/keybind/builtin/emacs.json b/src/keybind/builtin/emacs.json index 72b1e57..089b453 100644 --- a/src/keybind/builtin/emacs.json +++ b/src/keybind/builtin/emacs.json @@ -2,7 +2,7 @@ "normal": { "press": [ ["ctrl+g", "cancel"], - ["ctrl+shift+-", "undo"], + ["ctrl+shift+_", "undo"], ["ctrl+k", ["select_end"], ["cut"]], ["ctrl+w", "cut"], @@ -14,8 +14,10 @@ ["alt+f", "move_word_right"], ["ctrl+a", "move_begin"], ["ctrl+e", "move_end"], - ["alt+shift+,", "move_buffer_begin"], - ["alt+shift+.", "move_buffer_end"], + ["alt+<" , "move_buffer_begin"], + ["alt+shift+<" , "move_buffer_begin"], + ["alt+gt" , "move_buffer_begin"], + ["alt+shift+gt", "move_buffer_end"], ["alt+v", "move_page_up"], ["ctrl+v", "move_page_down"], @@ -23,7 +25,7 @@ ["ctrl+d", "delete_forward"], ["alt+d", ["select_word_right"], ["cut"]], ["ctrl+y", "system_paste"], - ["ctrl+x>ctrl+f", "open_recent"], + ["ctrl+x>ctrl+f", "open_file"], ["ctrl+x>k", "close_file"], ["ctrl+x>ctrl+c", "quit"], ["ctrl+x>ctrl+s", "save_file"], diff --git a/src/keybind/parse_flow.zig b/src/keybind/parse_flow.zig index 577a3b1..2cbd6db 100644 --- a/src/keybind/parse_flow.zig +++ b/src/keybind/parse_flow.zig @@ -80,5 +80,6 @@ pub const name_map = blk: { .{ "escape", input.key.escape }, .{ "space", input.key.space }, .{ "backspace", input.key.backspace }, + .{ "gt", '>' }, }); }; diff --git a/src/win32/gui.zig b/src/win32/gui.zig index 3d24c94..5e5047b 100644 --- a/src/win32/gui.zig +++ b/src/win32/gui.zig @@ -747,17 +747,25 @@ fn sendKey( .vk = @intCast(0xffff & wparam), .extended = win_key_flags.extended, }; + if (winkey.skipToUnicode()) |codepoint| { + state.pid.send(.{ + "RDR", + "I", + event, + @as(u21, codepoint), + @as(u21, codepoint), + "", + @as(u8, @bitCast(mods)), + }) catch |e| onexit(e); + return; + } const max_char_count = 20; var char_buf: [max_char_count + 1]u16 = undefined; - // don't call ToUnicode if control is down as it does some weird - // translation (i.e. ctrl+a becomes virtual keycode 1) - const skip_unicode = mods.ctrl or mods.alt or switch (winkey.vk) { - @intFromEnum(win32.VK_BACK) => true, - else => false, - }; - const unicode_result = if (skip_unicode) 0 else win32.ToUnicode( + // release control key when getting the unicode character of this key + keyboard_state[@intFromEnum(win32.VK_CONTROL)] = 0; + const unicode_result = win32.ToUnicode( winkey.vk, win_key_flags.scan_code, &keyboard_state, @@ -779,19 +787,8 @@ fn sendKey( } if (unicode_result == 0) { - const codepoint = winkey.toCodepoint() orelse { - std.log.warn("unknown virtual key {} 0x{0x}", .{winkey}); - return; - }; - state.pid.send(.{ - "RDR", - "I", - event, - @as(u21, codepoint), - @as(u21, codepoint), - "", - @as(u8, @bitCast(mods)), - }) catch |e| onexit(e); + std.log.warn("unknown virtual key {} (0x{x})", .{ winkey, winkey.vk }); + return; } for (char_buf[0..@intCast(unicode_result)]) |codepoint| { var utf8_buf: [6]u8 = undefined; @@ -829,7 +826,7 @@ const WinKey = struct { const e_suffix: []const u8 = if (self.extended) "e" else ""; try writer.print("{}{s}", .{ self.vk, e_suffix }); } - pub fn toCodepoint(self: WinKey) ?u21 { + pub fn skipToUnicode(self: WinKey) ?u21 { if (self.extended) return switch (self.vk) { @intFromEnum(win32.VK_RETURN) => input.key.kp_enter, @intFromEnum(win32.VK_CONTROL) => input.key.right_control, @@ -875,9 +872,6 @@ const WinKey = struct { @intFromEnum(win32.VK_INSERT) => input.key.kp_insert, @intFromEnum(win32.VK_DELETE) => input.key.kp_delete, - '0'...'9' => |ascii| ascii, - 'A'...'Z' => |ascii| ascii + ('a' - 'A'), - @intFromEnum(win32.VK_LWIN) => input.key.left_super, @intFromEnum(win32.VK_RWIN) => input.key.right_super, @intFromEnum(win32.VK_NUMPAD0) => input.key.kp_0, @@ -936,18 +930,6 @@ const WinKey = struct { @intFromEnum(win32.VK_MEDIA_PREV_TRACK) => input.key.media_track_previous, @intFromEnum(win32.VK_MEDIA_STOP) => input.key.media_stop, @intFromEnum(win32.VK_MEDIA_PLAY_PAUSE) => input.key.media_play_pause, - @intFromEnum(win32.VK_OEM_1) => ';', - @intFromEnum(win32.VK_OEM_PLUS) => '+', - @intFromEnum(win32.VK_OEM_COMMA) => ',', - @intFromEnum(win32.VK_OEM_MINUS) => '-', - @intFromEnum(win32.VK_OEM_PERIOD) => '.', - @intFromEnum(win32.VK_OEM_2) => '/', - @intFromEnum(win32.VK_OEM_3) => '`', - @intFromEnum(win32.VK_OEM_4) => '[', - @intFromEnum(win32.VK_OEM_5) => '\\', - @intFromEnum(win32.VK_OEM_6) => ']', - @intFromEnum(win32.VK_OEM_7) => '\'', - @intFromEnum(win32.VK_OEM_102) => '\\', else => null, }; }