mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-17 01:06:08 +03:00
input: key must provide unshifted codepoint
This commit is contained in:
@ -458,6 +458,26 @@ pub const Surface = struct {
|
|||||||
// then we've consumed our translate mods.
|
// then we've consumed our translate mods.
|
||||||
const consumed_mods: input.Mods = if (result.text.len > 0) translate_mods else .{};
|
const consumed_mods: input.Mods = if (result.text.len > 0) translate_mods else .{};
|
||||||
|
|
||||||
|
// We need to always do a translation with no modifiers at all in
|
||||||
|
// order to get the "unshifted_codepoint" for the key event.
|
||||||
|
const unshifted_codepoint: u21 = unshifted: {
|
||||||
|
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),
|
||||||
|
.{},
|
||||||
|
);
|
||||||
|
|
||||||
|
const view = std.unicode.Utf8View.init(nomod.text) catch |err| {
|
||||||
|
log.warn("cannot build utf8 view over text: {}", .{err});
|
||||||
|
break :unshifted 0;
|
||||||
|
};
|
||||||
|
var it = view.iterator();
|
||||||
|
break :unshifted it.nextCodepoint() orelse 0;
|
||||||
|
};
|
||||||
|
|
||||||
// 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,
|
||||||
// keycode,
|
// keycode,
|
||||||
@ -489,18 +509,9 @@ pub const Surface = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If that doesn't work then we try to translate without
|
// If the above doesn't work, we use the unmodified value.
|
||||||
// any modifiers and convert that.
|
if (std.math.cast(u8, unshifted_codepoint)) |ascii| {
|
||||||
var nomod_buf: [128]u8 = undefined;
|
if (input.Key.fromASCII(ascii)) |key| {
|
||||||
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 key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -517,6 +528,7 @@ pub const Surface = struct {
|
|||||||
.consumed_mods = consumed_mods,
|
.consumed_mods = consumed_mods,
|
||||||
.composing = result.composing,
|
.composing = result.composing,
|
||||||
.utf8 = result.text,
|
.utf8 = result.text,
|
||||||
|
.unshifted_codepoint = unshifted_codepoint,
|
||||||
}) catch |err| {
|
}) catch |err| {
|
||||||
log.err("error in key callback err={}", .{err});
|
log.err("error in key callback err={}", .{err});
|
||||||
return;
|
return;
|
||||||
@ -549,6 +561,7 @@ pub const Surface = struct {
|
|||||||
.consumed_mods = .{},
|
.consumed_mods = .{},
|
||||||
.composing = false,
|
.composing = false,
|
||||||
.utf8 = buf[0..len],
|
.utf8 = buf[0..len],
|
||||||
|
.unshifted_codepoint = 0,
|
||||||
}) catch |err| {
|
}) catch |err| {
|
||||||
log.err("error in key callback err={}", .{err});
|
log.err("error in key callback err={}", .{err});
|
||||||
return;
|
return;
|
||||||
|
@ -1212,6 +1212,31 @@ pub const Surface = struct {
|
|||||||
const keyval_unicode = c.gdk_keyval_to_unicode(keyval);
|
const keyval_unicode = c.gdk_keyval_to_unicode(keyval);
|
||||||
const event = c.gtk_event_controller_get_current_event(@ptrCast(ec_key));
|
const event = c.gtk_event_controller_get_current_event(@ptrCast(ec_key));
|
||||||
|
|
||||||
|
// Get the unshifted unicode value of the keyval. This is used
|
||||||
|
// by the Kitty keyboard protocol.
|
||||||
|
const keyval_unicode_unshifted: u21 = unshifted: {
|
||||||
|
var n: c_int = undefined;
|
||||||
|
var keys: [*c]c.GdkKeymapKey = undefined;
|
||||||
|
var keyvals: [*c]c.guint = undefined;
|
||||||
|
if (c.gdk_display_map_keycode(
|
||||||
|
c.gdk_event_get_display(event),
|
||||||
|
keycode,
|
||||||
|
&keys,
|
||||||
|
&keyvals,
|
||||||
|
&n,
|
||||||
|
) == 0) break :unshifted 0;
|
||||||
|
|
||||||
|
defer c.g_free(keys);
|
||||||
|
defer c.g_free(keyvals);
|
||||||
|
for (keys[0..@intCast(n)], 0..) |key, i| {
|
||||||
|
if (key.group == 0 and key.level == 0) {
|
||||||
|
break :unshifted @intCast(c.gdk_keyval_to_unicode(keyvals[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
// future keypresses don't think we have a commit event.
|
// future keypresses don't think we have a commit event.
|
||||||
defer self.im_len = 0;
|
defer self.im_len = 0;
|
||||||
@ -1317,6 +1342,7 @@ pub const Surface = struct {
|
|||||||
.consumed_mods = consumed_mods,
|
.consumed_mods = consumed_mods,
|
||||||
.composing = self.im_composing,
|
.composing = self.im_composing,
|
||||||
.utf8 = self.im_buf[0..self.im_len],
|
.utf8 = self.im_buf[0..self.im_len],
|
||||||
|
.unshifted_codepoint = keyval_unicode_unshifted,
|
||||||
}) catch |err| {
|
}) catch |err| {
|
||||||
log.err("error in key callback err={}", .{err});
|
log.err("error in key callback err={}", .{err});
|
||||||
return false;
|
return false;
|
||||||
|
@ -41,6 +41,10 @@ pub const KeyEvent = struct {
|
|||||||
/// text.
|
/// text.
|
||||||
utf8: []const u8 = "",
|
utf8: []const u8 = "",
|
||||||
|
|
||||||
|
/// The codepoint for this key when it is unshifted. For example,
|
||||||
|
/// shift+a is "A" in UTF-8 but unshifted would provide 'a'.
|
||||||
|
unshifted_codepoint: u21 = 0,
|
||||||
|
|
||||||
/// Returns the effective modifiers for this event. The effective
|
/// Returns the effective modifiers for this event. The effective
|
||||||
/// modifiers are the mods that should be considered for keybindings.
|
/// modifiers are the mods that should be considered for keybindings.
|
||||||
pub fn effectiveMods(self: KeyEvent) Mods {
|
pub fn effectiveMods(self: KeyEvent) Mods {
|
||||||
|
Reference in New Issue
Block a user