apprt/gtk: forward window key events to the focused surface

This commit is contained in:
Mitchell Hashimoto
2024-10-07 13:06:25 -07:00
parent 9e435f050e
commit 9c547dd8cd
2 changed files with 25 additions and 88 deletions

View File

@ -1395,7 +1395,14 @@ fn gtkKeyPressed(
gtk_mods: c.GdkModifierType, gtk_mods: c.GdkModifierType,
ud: ?*anyopaque, ud: ?*anyopaque,
) callconv(.C) c.gboolean { ) callconv(.C) c.gboolean {
return if (keyEvent(.press, ec_key, keyval, keycode, gtk_mods, ud)) 1 else 0; const self = userdataSelf(ud.?);
return if (self.keyEvent(
.press,
ec_key,
keyval,
keycode,
gtk_mods,
)) 1 else 0;
} }
fn gtkKeyReleased( fn gtkKeyReleased(
@ -1405,7 +1412,14 @@ fn gtkKeyReleased(
state: c.GdkModifierType, state: c.GdkModifierType,
ud: ?*anyopaque, ud: ?*anyopaque,
) callconv(.C) c.gboolean { ) callconv(.C) c.gboolean {
return if (keyEvent(.release, ec_key, keyval, keycode, state, ud)) 1 else 0; const self = userdataSelf(ud.?);
return if (self.keyEvent(
.release,
ec_key,
keyval,
keycode,
state,
)) 1 else 0;
} }
/// Key press event. This is where we do ALL of our key handling, /// Key press event. This is where we do ALL of our key handling,
@ -1432,15 +1446,14 @@ fn gtkKeyReleased(
/// Note we ALSO have an IMContext attached directly to the widget /// Note we ALSO have an IMContext attached directly to the widget
/// which can emit preedit and commit callbacks. But, if we're not /// which can emit preedit and commit callbacks. But, if we're not
/// in a keypress, we let those automatically work. /// in a keypress, we let those automatically work.
fn keyEvent( pub fn keyEvent(
self: *Surface,
action: input.Action, action: input.Action,
ec_key: *c.GtkEventControllerKey, ec_key: *c.GtkEventControllerKey,
keyval: c.guint, keyval: c.guint,
keycode: c.guint, keycode: c.guint,
gtk_mods: c.GdkModifierType, gtk_mods: c.GdkModifierType,
ud: ?*anyopaque,
) bool { ) bool {
const self = userdataSelf(ud.?);
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( const event = c.gtk_event_controller_get_current_event(
@ptrCast(ec_key), @ptrCast(ec_key),

View File

@ -679,90 +679,14 @@ fn gtkKeyPressed(
ud: ?*anyopaque, ud: ?*anyopaque,
) callconv(.C) c.gboolean { ) callconv(.C) c.gboolean {
const self = userdataSelf(ud.?); const self = userdataSelf(ud.?);
const keyval_unicode = c.gdk_keyval_to_unicode(keyval); const surface = self.app.core_app.focusedSurface() orelse return 0;
const event = c.gtk_event_controller_get_current_event(@ptrCast(ec_key)) orelse return 0; return if (surface.rt_surface.keyEvent(
.press,
// We want to get the physical unmapped key to process physical keybinds. ec_key,
// (These are keybinds explicitly marked as requesting physical mapping). keyval,
const physical_key = keycode: for (input.keycodes.entries) |entry| {
if (entry.native == keycode) break :keycode entry.key;
} else .invalid;
// Get our modifier for the event
const mods: input.Mods = gtk_key.eventMods(
@ptrCast(self.window),
event,
physical_key,
gtk_mods,
if (self.app.x11_xkb) |*xkb| xkb else null,
);
// Get our consumed modifiers
const consumed_mods: input.Mods = consumed: {
const raw = c.gdk_key_event_get_consumed_modifiers(event);
const masked = raw & c.GDK_MODIFIER_MASK;
break :consumed gtk_key.translateMods(masked);
};
// Get the unshifted unicode value of the keyval.
const keyval_unicode_unshifted: u21 = gtk_key.keyvalUnicodeUnshifted(
@ptrCast(self.window),
event,
keycode, keycode,
); gtk_mods,
)) 1 else 0;
// If we're not in a dead key state, we want to translate our text
// to some input.Key.
const key: input.Key = key: {
// First, try to convert the keyval directly to a key. This allows the
// use of key remapping and identification of keypad numerics (as
// opposed to their ASCII counterparts)
if (gtk_key.keyFromKeyval(keyval)) |key| {
break :key key;
}
// If that doesn't work then we try to translate the kevval..
if (keyval_unicode != 0) {
if (std.math.cast(u8, keyval_unicode)) |byte| {
if (input.Key.fromASCII(byte)) |key| {
break :key key;
}
}
}
// If that doesn't work we use the unshifted value...
if (std.math.cast(u8, keyval_unicode_unshifted)) |ascii| {
if (input.Key.fromASCII(ascii)) |key| {
break :key key;
}
}
if (keyval_unicode_unshifted != 0) break :key .invalid;
break :key physical_key;
};
// Build our final key event
const core_event: input.KeyEvent = .{
.action = .press,
.key = key,
.physical_key = physical_key,
.mods = mods,
.consumed_mods = consumed_mods,
.composing = false,
.utf8 = "",
.unshifted_codepoint = keyval_unicode_unshifted,
};
// log.debug("attempting app-scoped key event={}", .{core_event});
// Invoke the core Ghostty logic to handle this input.
const consumed = self.app.core_app.keyEvent(self.app, core_event);
if (consumed) {
log.info("app-scoped key consumed event={}", .{core_event});
return 1;
}
return 0;
} }
fn gtkActionAbout( fn gtkActionAbout(