mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
apprt/gtk: forward window key events to the focused surface
This commit is contained in:
@ -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),
|
||||||
|
@ -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(
|
||||||
|
Reference in New Issue
Block a user