mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-22 19:56:08 +03:00
apprt/gtk: call new key2callback using the all-in-one key event
This commit is contained in:
@ -1143,10 +1143,12 @@ pub fn key2Callback(
|
|||||||
self: *Surface,
|
self: *Surface,
|
||||||
event: input.KeyEvent,
|
event: input.KeyEvent,
|
||||||
) !bool {
|
) !bool {
|
||||||
|
// log.debug("keyCallback event={}", .{event});
|
||||||
|
|
||||||
// Before encoding, we see if we have any keybindings for this
|
// Before encoding, we see if we have any keybindings for this
|
||||||
// key. Those always intercept before any encoding tasks.
|
// key. Those always intercept before any encoding tasks.
|
||||||
if (event.action == .press or event.action == .repeat) {
|
if (event.action == .press or event.action == .repeat) {
|
||||||
const binding_mods = event.mods.effectiveMods().binding();
|
const binding_mods = event.effectiveMods().binding();
|
||||||
const binding_action_: ?input.Binding.Action = action: {
|
const binding_action_: ?input.Binding.Action = action: {
|
||||||
var trigger: input.Binding.Trigger = .{
|
var trigger: input.Binding.Trigger = .{
|
||||||
.mods = binding_mods,
|
.mods = binding_mods,
|
||||||
@ -1194,7 +1196,7 @@ pub fn key2Callback(
|
|||||||
_ = self.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_small = .{
|
.write_small = .{
|
||||||
.data = data,
|
.data = data,
|
||||||
.len = seq.len,
|
.len = @intCast(seq.len),
|
||||||
},
|
},
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
try self.io_thread.wakeup.notify();
|
try self.io_thread.wakeup.notify();
|
||||||
|
@ -1213,10 +1213,12 @@ pub const Surface = struct {
|
|||||||
const event = c.gtk_event_controller_get_current_event(@ptrCast(ec_key));
|
const event = c.gtk_event_controller_get_current_event(@ptrCast(ec_key));
|
||||||
_ = c.gtk_im_context_filter_keypress(self.im_context, event) != 0;
|
_ = c.gtk_im_context_filter_keypress(self.im_context, event) != 0;
|
||||||
|
|
||||||
// If we aren't composing, then we set our preedit to empty no matter what.
|
// Get our consumed modifiers
|
||||||
if (!self.im_composing) {
|
const consumed_mods: input.Mods = consumed: {
|
||||||
self.core_surface.preeditCallback(null) catch {};
|
const raw = c.gdk_key_event_get_consumed_modifiers(event);
|
||||||
}
|
const masked = raw & c.GDK_MODIFIER_MASK;
|
||||||
|
break :consumed translateMods(masked);
|
||||||
|
};
|
||||||
|
|
||||||
// If we're not in a dead key state, we want to translate our text
|
// If we're not in a dead key state, we want to translate our text
|
||||||
// to some input.Key.
|
// to some input.Key.
|
||||||
@ -1252,48 +1254,29 @@ pub const Surface = struct {
|
|||||||
// mods,
|
// mods,
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// 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) {
|
|
||||||
const consumed = self.core_surface.keyCallback(
|
|
||||||
.press,
|
|
||||||
key,
|
|
||||||
physical_key,
|
|
||||||
mods,
|
|
||||||
) catch |err| {
|
|
||||||
log.err("error in key callback err={}", .{err});
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we consume the key then we want to reset the dead key state.
|
|
||||||
if (consumed) {
|
|
||||||
c.gtk_im_context_reset(self.im_context);
|
|
||||||
self.core_surface.preeditCallback(null) catch {};
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is a dead key, then we're composing a character and
|
// 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.
|
// we need to set our proper preedit state.
|
||||||
if (self.im_composing) {
|
if (self.im_composing) preedit: {
|
||||||
const text = self.im_buf[0..self.im_len];
|
const text = self.im_buf[0..self.im_len];
|
||||||
const view = std.unicode.Utf8View.init(text) catch |err| {
|
const view = std.unicode.Utf8View.init(text) catch |err| {
|
||||||
log.warn("cannot build utf8 view over input: {}", .{err});
|
log.warn("cannot build utf8 view over input: {}", .{err});
|
||||||
return 0;
|
break :preedit;
|
||||||
};
|
};
|
||||||
var it = view.iterator();
|
var it = view.iterator();
|
||||||
|
|
||||||
const cp: u21 = it.nextCodepoint() orelse 0;
|
const cp: u21 = it.nextCodepoint() orelse 0;
|
||||||
self.core_surface.preeditCallback(cp) catch |err| {
|
self.core_surface.preeditCallback(cp) catch |err| {
|
||||||
log.err("error in preedit callback err={}", .{err});
|
log.err("error in preedit callback err={}", .{err});
|
||||||
return 0;
|
break :preedit;
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
return 0;
|
// If we aren't composing, then we set our preedit to
|
||||||
|
// empty no matter what.
|
||||||
|
self.core_surface.preeditCallback(null) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we aren't composing and have no text, we try to convert the keyval
|
// If we have no UTF-8 text, we try to convert our keyval to
|
||||||
// to a text value. We have to do this because GTK will not process
|
// a text value. We have to do this because GTK will not process
|
||||||
// "Ctrl+Shift+1" (on US keyboards) as "Ctrl+!" but instead as "".
|
// "Ctrl+Shift+1" (on US keyboards) as "Ctrl+!" but instead as "".
|
||||||
// But the keyval is set correctly so we can at least extract that.
|
// But the keyval is set correctly so we can at least extract that.
|
||||||
if (self.im_len == 0) {
|
if (self.im_len == 0) {
|
||||||
@ -1307,21 +1290,24 @@ pub const Surface = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next, we want to call the char callback with each codepoint.
|
// Invoke the core Ghostty logic to handle this input.
|
||||||
if (self.im_len > 0) {
|
const consumed = self.core_surface.key2Callback(.{
|
||||||
const text = self.im_buf[0..self.im_len];
|
.action = .press,
|
||||||
const view = std.unicode.Utf8View.init(text) catch |err| {
|
.key = key,
|
||||||
log.warn("cannot build utf8 view over input: {}", .{err});
|
.physical_key = physical_key,
|
||||||
return 0;
|
.mods = mods,
|
||||||
};
|
.consumed_mods = consumed_mods,
|
||||||
var it = view.iterator();
|
.composing = self.im_composing,
|
||||||
while (it.nextCodepoint()) |cp| {
|
.utf8 = self.im_buf[0..self.im_len],
|
||||||
self.core_surface.charCallback(cp, mods) catch |err| {
|
}) catch |err| {
|
||||||
log.err("error in char callback err={}", .{err});
|
log.err("error in key callback err={}", .{err});
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
// If we consume the key then we want to reset the dead key state.
|
||||||
|
if (consumed) {
|
||||||
|
c.gtk_im_context_reset(self.im_context);
|
||||||
|
self.core_surface.preeditCallback(null) catch {};
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user