mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
core: note when keyCallback processed the input
This commit is contained in:
@ -1022,13 +1022,19 @@ pub fn charCallback(self: *Surface, codepoint: u21) !void {
|
||||
try self.io_thread.wakeup.notify();
|
||||
}
|
||||
|
||||
/// Called for a single key event.
|
||||
///
|
||||
/// This will return true if the key was handled/consumed. In that case,
|
||||
/// the caller doesn't need to call a subsequent `charCallback` for the
|
||||
/// same event. However, the caller can call `charCallback` if they want,
|
||||
/// the surface will retain state to ensure the event is ignored.
|
||||
pub fn keyCallback(
|
||||
self: *Surface,
|
||||
action: input.Action,
|
||||
key: input.Key,
|
||||
unmapped_key: input.Key,
|
||||
mods: input.Mods,
|
||||
) !void {
|
||||
) !bool {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -1079,7 +1085,7 @@ pub fn keyCallback(
|
||||
self.ignore_char = true;
|
||||
|
||||
// No matter what, if there is a binding then we are done.
|
||||
return;
|
||||
return self.ignore_char;
|
||||
}
|
||||
|
||||
// Handle non-printables
|
||||
@ -1172,6 +1178,8 @@ pub fn keyCallback(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self.ignore_char;
|
||||
}
|
||||
|
||||
pub fn focusCallback(self: *Surface, focused: bool) !void {
|
||||
|
@ -408,17 +408,6 @@ pub const Surface = struct {
|
||||
// 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;
|
||||
@ -428,7 +417,9 @@ pub const Surface = struct {
|
||||
// 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: {
|
||||
//
|
||||
// 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;
|
||||
@ -437,10 +428,32 @@ pub const Surface = struct {
|
||||
// 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| {
|
||||
const consumed = self.core_surface.keyCallback(
|
||||
action,
|
||||
key,
|
||||
physical_key,
|
||||
mods,
|
||||
) catch |err| {
|
||||
log.err("error in key callback err={}", .{err});
|
||||
return;
|
||||
};
|
||||
|
||||
// If we consume the key then we want to reset the dead key state.
|
||||
if (consumed) {
|
||||
self.keymap_state = .{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Next, we want to call the char callback with each codepoint.
|
||||
|
@ -740,7 +740,7 @@ pub const Surface = struct {
|
||||
// TODO: we need to do mapped keybindings
|
||||
|
||||
const core_win = window.getUserPointer(CoreSurface) orelse return;
|
||||
core_win.keyCallback(action, key, key, mods) catch |err| {
|
||||
_ = core_win.keyCallback(action, key, key, mods) catch |err| {
|
||||
log.err("error in key callback err={}", .{err});
|
||||
return;
|
||||
};
|
||||
|
@ -1167,25 +1167,13 @@ pub const Surface = struct {
|
||||
const key = translateKey(keyval);
|
||||
const mods = translateMods(state);
|
||||
log.debug("key-press code={} key={} mods={}", .{ keycode, key, mods });
|
||||
self.core_surface.keyCallback(.press, key, key, mods) catch |err| {
|
||||
const processed = self.core_surface.keyCallback(.press, key, key, mods) catch |err| {
|
||||
log.err("error in key callback err={}", .{err});
|
||||
return 0;
|
||||
};
|
||||
|
||||
// We generally just say we didn't handle it. We control our
|
||||
// GTK environment so for any keys that matter we'll grab them.
|
||||
// One of the reasons we say we didn't handle it is so that the
|
||||
// IME can still work.
|
||||
return switch (keyval) {
|
||||
// If the key is tab, we say we handled it because we don't want
|
||||
// tab to move focus from our surface.
|
||||
c.GDK_KEY_Tab => 1,
|
||||
// We do the same for up, because that steals focus from the surface,
|
||||
// in case we have multiple tabs open.
|
||||
c.GDK_KEY_Up => 1,
|
||||
|
||||
else => 0,
|
||||
};
|
||||
// If we processed the key, we say we handled it.
|
||||
return if (processed) 1 else 0;
|
||||
}
|
||||
|
||||
fn gtkKeyReleased(
|
||||
|
Reference in New Issue
Block a user