apprt/embedded: only call new key2callback

This commit is contained in:
Mitchell Hashimoto
2023-08-16 13:26:22 -07:00
parent 896d0e8fcf
commit cd90b2a716

View File

@ -387,8 +387,8 @@ pub const Surface = struct {
keycode: u32, keycode: u32,
mods: input.Mods, mods: input.Mods,
) !void { ) !void {
// We don't handle release events because we don't use them yet. // True if this is a key down event
if (action != .press and action != .repeat) return; const is_down = action == .press or action == .repeat;
// If we're on macOS and we have macos-option-as-alt enabled, // If we're on macOS and we have macos-option-as-alt enabled,
// then we strip the alt modifier from the mods for translation. // then we strip the alt modifier from the mods for translation.
@ -420,18 +420,43 @@ pub const Surface = struct {
}; };
// Translate our key using the keymap for our localized keyboard layout. // Translate our key using the keymap for our localized keyboard layout.
// We only translate for keydown events. Otherwise, we only care about
// the raw keycode.
var buf: [128]u8 = undefined; var buf: [128]u8 = undefined;
const result = try self.app.keymap.translate( const result: input.Keymap.Translation = if (is_down) translate: {
&buf, const result = try self.app.keymap.translate(
&self.keymap_state, &buf,
@intCast(keycode), &self.keymap_state,
translate_mods, @intCast(keycode),
); translate_mods,
);
// If we aren't composing, then we set our preedit to empty no matter what. // If this is a dead key, then we're composing a character and
if (!result.composing) { // we need to set our proper preedit state.
self.core_surface.preeditCallback(null) catch {}; if (result.composing) {
} const view = std.unicode.Utf8View.init(result.text) catch |err| {
log.warn("cannot build utf8 view over input: {}", .{err});
return;
};
var it = view.iterator();
const cp: u21 = it.nextCodepoint() orelse 0;
self.core_surface.preeditCallback(cp) catch |err| {
log.err("error in preedit callback err={}", .{err});
return;
};
} else {
// If we aren't composing, then we set our preedit to
// empty no matter what.
self.core_surface.preeditCallback(null) catch {};
}
break :translate result;
} else .{ .composing = false, .text = "" };
// UCKeyTranslate always consumes all mods, so if we have any output
// then we've consumed our translate mods.
const consumed_mods: input.Mods = if (result.text.len > 0) translate_mods else .{};
// log.warn("TRANSLATE: action={} keycode={x} dead={} key_len={} key={any} key_str={s} mods={}", .{ // log.warn("TRANSLATE: action={} keycode={x} dead={} key_len={} key={any} key_str={s} mods={}", .{
// action, // action,
@ -454,12 +479,14 @@ pub const Surface = struct {
// charCallback. // charCallback.
// //
// We also only do key translation if this is not a dead key. // We also only do key translation if this is not a dead key.
const key = if (!result.composing and result.text.len == 1) key: { const key = if (!result.composing) 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.
if (input.Key.fromASCII(result.text[0])) |key| { if (result.text.len > 0) {
break :key key; if (input.Key.fromASCII(result.text[0])) |key| {
break :key key;
}
} }
// If that doesn't work then we try to translate without // If that doesn't work then we try to translate without
@ -481,53 +508,26 @@ pub const Surface = struct {
break :key physical_key; break :key physical_key;
} else .invalid; } else .invalid;
// If both keys are invalid then we won't call the key callback. But // Invoke the core Ghostty logic to handle this input.
// if either one is valid, we want to give it a chance. const consumed = self.core_surface.key2Callback(.{
if (key != .invalid or physical_key != .invalid) { .action = action,
const consumed = self.core_surface.keyCallback( .key = key,
action, .physical_key = physical_key,
key, .mods = mods,
physical_key, .consumed_mods = consumed_mods,
mods, .composing = result.composing,
) catch |err| { .utf8 = result.text,
log.err("error in key callback err={}", .{err}); }) catch |err| {
return; log.err("error in key callback err={}", .{err});
};
// If we consume the key then we want to reset the dead key state.
if (consumed) {
self.keymap_state = .{};
self.core_surface.preeditCallback(null) catch {};
return;
}
}
// No matter what happens next we'll want a utf8 view.
const view = std.unicode.Utf8View.init(result.text) catch |err| {
log.warn("cannot build utf8 view over input: {}", .{err});
return; return;
}; };
var it = view.iterator();
// 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) {
const cp: u21 = it.nextCodepoint() orelse 0;
self.core_surface.preeditCallback(cp) catch |err| {
log.err("error in preedit callback err={}", .{err});
return;
};
// If we consume the key then we want to reset the dead key state.
if (consumed and is_down) {
self.keymap_state = .{};
self.core_surface.preeditCallback(null) catch {};
return; return;
} }
// Next, we want to call the char callback with each codepoint.
while (it.nextCodepoint()) |cp| {
self.core_surface.charCallback(cp, mods) catch |err| {
log.err("error in char callback err={}", .{err});
return;
};
}
} }
pub fn charCallback(self: *Surface, cp_: u32) void { pub fn charCallback(self: *Surface, cp_: u32) void {