mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
apprt/embedded: keycallback should use nomod text to determine key
To determine the logical key that was pressed, we previously just trusted that the translated text would have the right value. But if modifiers are pressed, the text may not translate. For example on macOS, Ctrl+C does not produce any text. As a result, we would fall back to the physical key. On layouts like Dvorak, the physical key for "C" is "I". This means "Ctrl+C" sequences weren't working. Instead, if there is no text or the text doesn't map to a key, we translate again using no modifiers to try to get the raw text of the input and then base the key on that.
This commit is contained in:
@ -1134,6 +1134,13 @@ pub fn keyCallback(
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
// log.warn("KEY CALLBACK action={} key={} physical_key={} mods={}", .{
|
||||
// action,
|
||||
// key,
|
||||
// physical_key,
|
||||
// mods,
|
||||
// });
|
||||
|
||||
// Dev Mode
|
||||
if (DevMode.enabled and DevMode.instance.visible) {
|
||||
// If the event was handled by imgui, ignore it.
|
||||
|
@ -422,10 +422,11 @@ pub const Surface = struct {
|
||||
self.core_surface.preeditCallback(null) catch {};
|
||||
}
|
||||
|
||||
// log.warn("TRANSLATE: action={} keycode={x} dead={} key={any} key_str={s} mods={}", .{
|
||||
// log.warn("TRANSLATE: action={} keycode={x} dead={} key_len={} key={any} key_str={s} mods={}", .{
|
||||
// action,
|
||||
// keycode,
|
||||
// result.composing,
|
||||
// result.text.len,
|
||||
// result.text,
|
||||
// result.text,
|
||||
// mods,
|
||||
@ -444,8 +445,29 @@ pub const Surface = struct {
|
||||
// We also only do key translation if this is not a dead key.
|
||||
const key = if (!result.composing and 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;
|
||||
// attempt to translate it to a key enum and call the key
|
||||
// callback. First try plain ASCII.
|
||||
if (input.Key.fromASCII(result.text[0])) |key| {
|
||||
break :key key;
|
||||
}
|
||||
|
||||
// If that doesn't work then we try to translate without
|
||||
// any modifiers and convert that.
|
||||
var nomod_buf: [128]u8 = undefined;
|
||||
var nomod_state: input.Keymap.State = undefined;
|
||||
const nomod = try self.app.keymap.translate(
|
||||
&nomod_buf,
|
||||
&nomod_state,
|
||||
@intCast(keycode),
|
||||
.{},
|
||||
);
|
||||
if (nomod.text.len == 1) {
|
||||
if (input.Key.fromASCII(nomod.text[0])) |key| {
|
||||
break :key key;
|
||||
}
|
||||
}
|
||||
|
||||
break :key physical_key;
|
||||
} else .invalid;
|
||||
|
||||
// If both keys are invalid then we won't call the key callback. But
|
||||
|
Reference in New Issue
Block a user