core: note when keyCallback processed the input

This commit is contained in:
Mitchell Hashimoto
2023-08-10 15:29:46 -07:00
parent d5df8aea9a
commit 4fe739cae0
4 changed files with 40 additions and 31 deletions

View File

@ -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 {

View File

@ -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.

View File

@ -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;
};

View File

@ -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(