core: start on key2Callback for the new callback that uses KeyEncoder

This commit is contained in:
Mitchell Hashimoto
2023-08-16 10:12:40 -07:00
parent a2d4e7ce29
commit 9b90692fc7
2 changed files with 68 additions and 29 deletions

View File

@ -1139,40 +1139,79 @@ pub fn charCallback(
try self.io_thread.wakeup.notify(); try self.io_thread.wakeup.notify();
} }
/// A key input event. pub fn key2Callback(
pub const KeyEvent = struct { self: *Surface,
/// The action: press, release, etc. event: input.KeyEvent,
action: input.Action, ) !bool {
// Before encoding, we see if we have any keybindings for this
/// "key" is the logical key that was pressed. For example, if // key. Those always intercept before any encoding tasks.
/// a Dvorak keyboard layout is being used on a US keyboard, if (event.action == .press or event.action == .repeat) {
/// the "i" physical key will be reported as "c". The physical const binding_mods = event.mods.effectiveMods().binding();
/// key is the key that was physically pressed on the keyboard. const binding_action_: ?input.Binding.Action = action: {
key: input.Key, var trigger: input.Binding.Trigger = .{
physical_key: input.Key, .mods = binding_mods,
.key = event.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,
}; };
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. /// Called for a single key event.
/// ///
/// This will return true if the key was handled/consumed. In that case, /// This will return true if the key was handled/consumed. In that case,

View File

@ -25,7 +25,7 @@ modify_other_keys_state_2: bool = false,
/// These together combine the legacy protocol because they're all /// These together combine the legacy protocol because they're all
/// meant to be extensions that do not change any existing behavior /// meant to be extensions that do not change any existing behavior
/// and therefore safe to combine. /// and therefore safe to combine.
fn legacy( pub fn legacy(
self: *const KeyEncoder, self: *const KeyEncoder,
buf: []u8, buf: []u8,
) ![]const u8 { ) ![]const u8 {