mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-17 07:16:12 +00:00
macos: use the new self-hosted translation
This commit is contained in:
@@ -395,6 +395,81 @@ pub const Surface = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn key2Callback(
|
||||
self: *Surface,
|
||||
action: input.Action,
|
||||
keycode: u32,
|
||||
mods: input.Mods,
|
||||
) !void {
|
||||
if (action != .press) return;
|
||||
|
||||
// Translate our key using the keymap for our localized keyboard layout.
|
||||
var buf: [128]u8 = undefined;
|
||||
const result = try self.app.keymap.translate(
|
||||
&buf,
|
||||
&self.keymap_state,
|
||||
@intCast(keycode),
|
||||
mods,
|
||||
);
|
||||
|
||||
log.warn("TRANSLATE: action={} keycode={x} dead={} key={any} key_str={s} mods={}", .{
|
||||
action,
|
||||
keycode,
|
||||
result.composing,
|
||||
result.text,
|
||||
result.text,
|
||||
mods,
|
||||
});
|
||||
|
||||
// If this is a dead key, then we're composing a character and
|
||||
// we end processing here. We don't process keybinds for dead keys.
|
||||
if (result.composing) {
|
||||
// TODO: we ultimately want to update some surface state so that
|
||||
// we can show the user that we're in dead key mode and the
|
||||
// precomposed character. For now, we can just ignore and that
|
||||
// is not incorrect behavior.
|
||||
log.warn("dead key mode, currently composing", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
// We want to get the physical unmapped key to process keybinds.
|
||||
const physical_key = keycode: for (input.keycodes.entries) |entry| {
|
||||
if (entry.native == keycode) break :keycode entry.key;
|
||||
} else .invalid;
|
||||
|
||||
// If the resulting text has length 1 then we can take its key
|
||||
// and attempt to translate it to a key enum and call the key callback.
|
||||
// If the length is greater than 1 then we're going to call the
|
||||
// charCallback.
|
||||
const key = if (result.text.len == 1) key: {
|
||||
// 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 callback.
|
||||
break :key input.Key.fromASCII(result.text[0]) orelse physical_key;
|
||||
} else .invalid;
|
||||
|
||||
// If both keys are invalid then we won't call the key callback. But
|
||||
// if either one is valid, we want to give it a chance.
|
||||
if (key != .invalid or physical_key != .invalid) {
|
||||
self.core_surface.keyCallback(action, key, physical_key, mods) catch |err| {
|
||||
log.err("error in key callback err={}", .{err});
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
// Next, we want to call the char callback with each codepoint.
|
||||
const view = std.unicode.Utf8View.init(result.text) catch |err| {
|
||||
log.warn("cannot build utf8 view over input: {}", .{err});
|
||||
return;
|
||||
};
|
||||
var it = view.iterator();
|
||||
while (it.nextCodepoint()) |cp| {
|
||||
self.core_surface.charCallback(cp) catch |err| {
|
||||
log.err("error in char callback err={}", .{err});
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn charCallback(self: *Surface, cp_: u32) void {
|
||||
const cp = std.math.cast(u21, cp_) orelse return;
|
||||
self.core_surface.charCallback(cp) catch |err| {
|
||||
@@ -573,27 +648,14 @@ pub const CAPI = struct {
|
||||
keycode: u32,
|
||||
c_mods: c_int,
|
||||
) void {
|
||||
if (action != .press) return;
|
||||
|
||||
var buf: [128]u8 = undefined;
|
||||
const mods: input.Mods = @bitCast(@as(u8, @truncate(@as(c_uint, @bitCast(c_mods)))));
|
||||
const result = surface.app.keymap.translate(
|
||||
&buf,
|
||||
&surface.keymap_state,
|
||||
@intCast(keycode),
|
||||
mods,
|
||||
) catch |err| {
|
||||
log.err("TRANSLATE error translating key err={}", .{err});
|
||||
return;
|
||||
};
|
||||
|
||||
log.warn("TRANSLATE: action={} keycode={x} dead={} key={any} key_str={s}", .{
|
||||
surface.key2Callback(
|
||||
action,
|
||||
keycode,
|
||||
result.composing,
|
||||
result.text,
|
||||
result.text,
|
||||
});
|
||||
@bitCast(@as(u8, @truncate(@as(c_uint, @bitCast(c_mods))))),
|
||||
) catch |err| {
|
||||
log.err("error processing key event err={}", .{err});
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
/// Tell the surface that it needs to schedule a render
|
||||
|
@@ -2,6 +2,7 @@ const std = @import("std");
|
||||
|
||||
pub usingnamespace @import("input/mouse.zig");
|
||||
pub usingnamespace @import("input/key.zig");
|
||||
pub const keycodes = @import("input/keycodes.zig");
|
||||
pub const Binding = @import("input/Binding.zig");
|
||||
pub const Keymap = @import("input/Keymap.zig");
|
||||
pub const SplitDirection = Binding.Action.SplitDirection;
|
||||
|
@@ -180,4 +180,67 @@ pub const Key = enum(c_int) {
|
||||
|
||||
// To support more keys (there are obviously more!) add them here
|
||||
// and ensure the mapping is up to date in the Window key handler.
|
||||
|
||||
/// Converts an ASCII character to a key, if possible. This returns
|
||||
/// null if the character is unknown.
|
||||
///
|
||||
/// Note that this can't distinguish between physical keys, i.e. '0'
|
||||
/// may be from the number row or the keypad, but it always maps
|
||||
/// to '.zero'.
|
||||
///
|
||||
/// This is what we want, we awnt people to create keybindings that
|
||||
/// are independent of the physical key.
|
||||
pub fn fromASCII(ch: u8) ?Key {
|
||||
return switch (ch) {
|
||||
'a' => .a,
|
||||
'b' => .b,
|
||||
'c' => .c,
|
||||
'd' => .d,
|
||||
'e' => .e,
|
||||
'f' => .f,
|
||||
'g' => .g,
|
||||
'h' => .h,
|
||||
'i' => .i,
|
||||
'j' => .j,
|
||||
'k' => .k,
|
||||
'l' => .l,
|
||||
'm' => .m,
|
||||
'n' => .n,
|
||||
'o' => .o,
|
||||
'p' => .p,
|
||||
'q' => .q,
|
||||
'r' => .r,
|
||||
's' => .s,
|
||||
't' => .t,
|
||||
'u' => .u,
|
||||
'v' => .v,
|
||||
'w' => .w,
|
||||
'x' => .x,
|
||||
'y' => .y,
|
||||
'z' => .z,
|
||||
'0' => .zero,
|
||||
'1' => .one,
|
||||
'2' => .two,
|
||||
'3' => .three,
|
||||
'4' => .four,
|
||||
'5' => .five,
|
||||
'6' => .six,
|
||||
'7' => .seven,
|
||||
'8' => .eight,
|
||||
'9' => .nine,
|
||||
';' => .semicolon,
|
||||
' ' => .space,
|
||||
'\'' => .apostrophe,
|
||||
',' => .comma,
|
||||
'`' => .grave_accent,
|
||||
'.' => .period,
|
||||
'/' => .slash,
|
||||
'-' => .minus,
|
||||
'=' => .equal,
|
||||
'[' => .left_bracket,
|
||||
']' => .right_bracket,
|
||||
'\\' => .backslash,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user