core: get rid of ignore_char, apprt must handle this now

This commit is contained in:
Mitchell Hashimoto
2023-08-11 09:42:16 -07:00
parent 38477ed547
commit ce4eb2112c
4 changed files with 26 additions and 55 deletions

View File

@ -90,12 +90,6 @@ padding: renderer.Padding,
/// the lifetime of. This makes updating config at runtime easier. /// the lifetime of. This makes updating config at runtime easier.
config: DerivedConfig, config: DerivedConfig,
/// Set to true for a single GLFW key/char callback cycle to cause the
/// char callback to ignore. GLFW seems to always do key followed by char
/// callbacks so we abuse that here. This is to solve an issue where commands
/// like such as "control-v" will write a "v" even if they're intercepted.
ignore_char: bool = false,
/// This is set to true if our IO thread notifies us our child exited. /// This is set to true if our IO thread notifies us our child exited.
/// This is used to determine if we need to confirm, hold open, etc. /// This is used to determine if we need to confirm, hold open, etc.
child_exited: bool = false, child_exited: bool = false,
@ -986,12 +980,6 @@ pub fn charCallback(self: *Surface, codepoint: u21) !void {
} else |_| {} } else |_| {}
} }
// Ignore if requested. See field docs for more information.
if (self.ignore_char) {
self.ignore_char = false;
return;
}
// Critical area // Critical area
{ {
self.renderer_state.mutex.lock(); self.renderer_state.mutex.lock();
@ -1048,10 +1036,6 @@ pub fn keyCallback(
} else |_| {} } else |_| {}
} }
// Reset the ignore char setting. If we didn't handle the char
// by here, we aren't going to get it so we just reset this.
self.ignore_char = false;
if (action == .press or action == .repeat) { if (action == .press or action == .repeat) {
// Mods for bindings never include caps/num lock. // Mods for bindings never include caps/num lock.
const binding_mods = mods: { const binding_mods = mods: {
@ -1080,12 +1064,7 @@ pub fn keyCallback(
if (binding_action_) |binding_action| { if (binding_action_) |binding_action| {
//log.warn("BINDING ACTION={}", .{binding_action}); //log.warn("BINDING ACTION={}", .{binding_action});
try self.performBindingAction(binding_action); try self.performBindingAction(binding_action);
return true;
// Bindings always result in us ignoring the char if printable
self.ignore_char = true;
// No matter what, if there is a binding then we are done.
return self.ignore_char;
} }
// Handle non-printables // Handle non-printables
@ -1143,18 +1122,6 @@ pub fn keyCallback(
}; };
}; };
if (char > 0) { if (char > 0) {
// We are handling this char so don't allow charCallback to do
// anything. Normally it shouldn't because charCallback should not
// be called for control characters. But, we found a scenario where
// it does: https://github.com/mitchellh/ghostty/issues/267
//
// In case that URL goes away: on macOS, after typing a dead
// key sequence, macOS would call `insertText` with control
// characters. Prior to calling a dead key sequence, it would
// not. I don't know. It doesn't matter, this is more correct
// anyways.
self.ignore_char = true;
// Ask our IO thread to write the data // Ask our IO thread to write the data
var data: termio.Message.WriteReq.Small.Array = undefined; var data: termio.Message.WriteReq.Small.Array = undefined;
data[0] = @intCast(char); data[0] = @intCast(char);
@ -1176,10 +1143,12 @@ pub fn keyCallback(
log.warn("error scrolling to bottom err={}", .{err}); log.warn("error scrolling to bottom err={}", .{err});
}; };
} }
return true;
} }
} }
return self.ignore_char; return false;
} }
pub fn focusCallback(self: *Surface, focused: bool) !void { pub fn focusCallback(self: *Surface, focused: bool) !void {

View File

@ -441,15 +441,6 @@ pub const Surface = struct {
// If we consume the key then we want to reset the dead key state. // If we consume the key then we want to reset the dead key state.
if (consumed) { if (consumed) {
self.keymap_state = .{}; self.keymap_state = .{};
// This is kloodge right now to reset the surface ignore_char
// state. We should refactor the API contract with the surface
// to be that if we consume a key then we don't call the char
// callback.
//
// If you don't do this, then after a consumed char a pure
// char event will be ignored. i.e. an emoji keyboard entry.
self.core_surface.charCallback(0) catch {};
return; return;
} }
} }

View File

@ -282,6 +282,10 @@ pub const Surface = struct {
/// A core surface /// A core surface
core_surface: CoreSurface, core_surface: CoreSurface,
/// This is set to true when keyCallback consumes the input, suppressing
/// the charCallback from being fired.
key_consumed: bool = false,
pub const Options = struct {}; pub const Options = struct {};
/// Initialize the surface into the given self pointer. This gives a /// Initialize the surface into the given self pointer. This gives a
@ -586,6 +590,13 @@ pub const Surface = struct {
defer tracy.end(); defer tracy.end();
const core_win = window.getUserPointer(CoreSurface) orelse return; const core_win = window.getUserPointer(CoreSurface) orelse return;
// If our keyCallback consumed the key input, don't emit a char.
if (core_win.rt_surface.key_consumed) {
core_win.rt_surface.key_consumed = false;
return;
}
core_win.charCallback(codepoint) catch |err| { core_win.charCallback(codepoint) catch |err| {
log.err("error in char callback err={}", .{err}); log.err("error in char callback err={}", .{err});
return; return;
@ -601,6 +612,11 @@ pub const Surface = struct {
) void { ) void {
_ = scancode; _ = scancode;
const core_win = window.getUserPointer(CoreSurface) orelse return;
// Reset our consumption state
core_win.rt_surface.key_consumed = false;
const tracy = trace(@src()); const tracy = trace(@src());
defer tracy.end(); defer tracy.end();
@ -739,8 +755,12 @@ pub const Surface = struct {
// TODO: we need to do mapped keybindings // TODO: we need to do mapped keybindings
const core_win = window.getUserPointer(CoreSurface) orelse return; core_win.rt_surface.key_consumed = core_win.keyCallback(
_ = core_win.keyCallback(action, key, key, mods) catch |err| { action,
key,
key,
mods,
) catch |err| {
log.err("error in key callback err={}", .{err}); log.err("error in key callback err={}", .{err});
return; return;
}; };

View File

@ -1214,15 +1214,6 @@ pub const Surface = struct {
// If we consume the key then we want to reset the dead key state. // If we consume the key then we want to reset the dead key state.
if (consumed) { if (consumed) {
c.gtk_im_context_reset(self.im_context); c.gtk_im_context_reset(self.im_context);
// This is kloodge right now to reset the surface ignore_char
// state. We should refactor the API contract with the surface
// to be that if we consume a key then we don't call the char
// callback.
//
// If you don't do this, then after a consumed char a pure
// char event will be ignored. i.e. an emoji keyboard entry.
self.core_surface.charCallback(0) catch {};
return 1; return 1;
} }
} }