mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Merge pull request #1031 from mitchellh/gtk-unshifted
apprt/gtk: use map_keycode to get the proper unshifted key for a layout
This commit is contained in:
@ -1210,13 +1210,48 @@ fn keyEvent(
|
|||||||
// Get the unshifted unicode value of the keyval. This is used
|
// Get the unshifted unicode value of the keyval. This is used
|
||||||
// by the Kitty keyboard protocol.
|
// by the Kitty keyboard protocol.
|
||||||
const keyval_unicode_unshifted: u21 = unshifted: {
|
const keyval_unicode_unshifted: u21 = unshifted: {
|
||||||
// Note: this can't possibly always be right, specifically in the
|
// We need to get the currently active keyboard layout so we know
|
||||||
// case of multi-level/group keyboards. But, this works for Dvorak,
|
// what group to look at.
|
||||||
// Norwegian, and French layouts and thats what we have real users for
|
const layout = c.gdk_key_event_get_layout(@ptrCast(event));
|
||||||
// right now.
|
|
||||||
const lower = c.gdk_keyval_to_lower(keyval);
|
// Get all the possible keyboard mappings for this keycode. A keycode
|
||||||
const lower_unicode = c.gdk_keyval_to_unicode(lower);
|
// is the physical key pressed.
|
||||||
break :unshifted std.math.cast(u21, lower_unicode) orelse 0;
|
const display = c.gtk_widget_get_display(@ptrCast(self.gl_area));
|
||||||
|
var keys: [*]c.GdkKeymapKey = undefined;
|
||||||
|
var keyvals: [*]c.guint = undefined;
|
||||||
|
var n_keys: c_int = 0;
|
||||||
|
if (c.gdk_display_map_keycode(
|
||||||
|
display,
|
||||||
|
keycode,
|
||||||
|
@ptrCast(&keys),
|
||||||
|
@ptrCast(&keyvals),
|
||||||
|
&n_keys,
|
||||||
|
) == 0) break :unshifted 0;
|
||||||
|
|
||||||
|
defer c.g_free(keys);
|
||||||
|
defer c.g_free(keyvals);
|
||||||
|
|
||||||
|
// debugging:
|
||||||
|
// log.debug("layout={}", .{layout});
|
||||||
|
// for (0..@intCast(n_keys)) |i| {
|
||||||
|
// log.debug("keymap key={} codepoint={x}", .{
|
||||||
|
// keys[i],
|
||||||
|
// c.gdk_keyval_to_unicode(keyvals[i]),
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (0..@intCast(n_keys)) |i| {
|
||||||
|
if (keys[i].group == layout and
|
||||||
|
keys[i].level == 0)
|
||||||
|
{
|
||||||
|
break :unshifted std.math.cast(
|
||||||
|
u21,
|
||||||
|
c.gdk_keyval_to_unicode(keyvals[i]),
|
||||||
|
) orelse 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break :unshifted 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// We always reset our committed text when ending a keypress so that
|
// We always reset our committed text when ending a keypress so that
|
||||||
@ -1369,6 +1404,14 @@ fn keyEvent(
|
|||||||
break :key key;
|
break :key key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have im text then this is invalid. This means that
|
||||||
|
// 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
|
||||||
|
// it can be simply wrong. For example on "Turkish Q" the "i" key
|
||||||
|
// on a US layout results in "ı" which is not the same as "i" so
|
||||||
|
// we shouldn't use the physical key.
|
||||||
|
if (self.im_len > 0 or keyval_unicode_unshifted != 0) break :key .invalid;
|
||||||
|
|
||||||
break :key physical_key;
|
break :key physical_key;
|
||||||
} else .invalid;
|
} else .invalid;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user