mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 08:16:13 +03:00
core: start on key2Callback for the new callback that uses KeyEncoder
This commit is contained in:
103
src/Surface.zig
103
src/Surface.zig
@ -1139,40 +1139,79 @@ pub fn charCallback(
|
||||
try self.io_thread.wakeup.notify();
|
||||
}
|
||||
|
||||
/// A key input event.
|
||||
pub const KeyEvent = struct {
|
||||
/// The action: press, release, etc.
|
||||
action: input.Action,
|
||||
|
||||
/// "key" is the logical key that was pressed. For example, if
|
||||
/// a Dvorak keyboard layout is being used on a US keyboard,
|
||||
/// the "i" physical key will be reported as "c". The physical
|
||||
/// key is the key that was physically pressed on the keyboard.
|
||||
key: input.Key,
|
||||
physical_key: input.Key,
|
||||
|
||||
/// Mods are the modifiers that are pressed.
|
||||
mods: input.Mods,
|
||||
|
||||
/// The mods that were consumed in order to generate the text
|
||||
/// in utf8. This has the mods set that were consumed, so to
|
||||
/// get the set of mods that are effective you must negate
|
||||
/// mods with this.
|
||||
///
|
||||
/// This field is meaningless if utf8 is empty.
|
||||
consumed_mods: input.Mods,
|
||||
|
||||
/// Composing is true when this key event is part of a dead key
|
||||
/// composition sequence and we're in the middle of it.
|
||||
composing: bool,
|
||||
|
||||
/// The utf8 sequence that was generated by this key event.
|
||||
/// This will be an empty string if there is no text generated.
|
||||
/// If composing is true and this is non-empty, this is preedit
|
||||
/// text.
|
||||
utf8: []const u8,
|
||||
pub fn key2Callback(
|
||||
self: *Surface,
|
||||
event: input.KeyEvent,
|
||||
) !bool {
|
||||
// Before encoding, we see if we have any keybindings for this
|
||||
// key. Those always intercept before any encoding tasks.
|
||||
if (event.action == .press or event.action == .repeat) {
|
||||
const binding_mods = event.mods.effectiveMods().binding();
|
||||
const binding_action_: ?input.Binding.Action = action: {
|
||||
var trigger: input.Binding.Trigger = .{
|
||||
.mods = binding_mods,
|
||||
.key = event.key,
|
||||
};
|
||||
|
||||
const set = self.config.keybind.set;
|
||||
if (set.get(trigger)) |v| break :action v;
|
||||
|
||||
trigger.key = event.physical_key;
|
||||
trigger.physical = true;
|
||||
if (set.get(trigger)) |v| break :action v;
|
||||
|
||||
break :action null;
|
||||
};
|
||||
|
||||
if (binding_action_) |binding_action| {
|
||||
//log.warn("BINDING ACTION={}", .{binding_action});
|
||||
try self.performBindingAction(binding_action);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No binding, so we have to perform an encoding task. This
|
||||
// may still result in no encoding. Under different modes and
|
||||
// inputs there are many keybindings that result in no encoding
|
||||
// whatsoever.
|
||||
const enc: input.KeyEncoder = enc: {
|
||||
self.renderer_state.mutex.lock();
|
||||
defer self.renderer_state.mutex.unlock();
|
||||
const t = &self.io.terminal;
|
||||
break :enc .{
|
||||
.event = event,
|
||||
.alt_esc_prefix = t.modes.get(.alt_esc_prefix),
|
||||
.cursor_key_application = t.modes.get(.cursor_keys),
|
||||
.keypad_key_application = t.modes.get(.keypad_keys),
|
||||
.modify_other_keys_state_2 = t.flags.modify_other_keys_2,
|
||||
};
|
||||
};
|
||||
|
||||
var data: termio.Message.WriteReq.Small.Array = undefined;
|
||||
const seq = try enc.legacy(&data);
|
||||
if (seq.len == 0) return false;
|
||||
|
||||
_ = self.io_thread.mailbox.push(.{
|
||||
.write_small = .{
|
||||
.data = data,
|
||||
.len = seq.len,
|
||||
},
|
||||
}, .{ .forever = {} });
|
||||
try self.io_thread.wakeup.notify();
|
||||
|
||||
// If we have a sequence to emit then we always want to clear the
|
||||
// selection and scroll to the bottom.
|
||||
{
|
||||
self.renderer_state.mutex.lock();
|
||||
defer self.renderer_state.mutex.unlock();
|
||||
self.setSelection(null);
|
||||
try self.io.terminal.scrollViewport(.{ .bottom = {} });
|
||||
try self.queueRender();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Called for a single key event.
|
||||
///
|
||||
/// This will return true if the key was handled/consumed. In that case,
|
||||
|
@ -25,7 +25,7 @@ modify_other_keys_state_2: bool = false,
|
||||
/// These together combine the legacy protocol because they're all
|
||||
/// meant to be extensions that do not change any existing behavior
|
||||
/// and therefore safe to combine.
|
||||
fn legacy(
|
||||
pub fn legacy(
|
||||
self: *const KeyEncoder,
|
||||
buf: []u8,
|
||||
) ![]const u8 {
|
||||
|
Reference in New Issue
Block a user