1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-20 11:17:15 +03:00

window: adjust xkb handling for future RawKeyEvent support

This moves the event dispatching into the keyboard processor,
which will allow for the processor to skip feeding an event
into the dead key/composition stuff if a key assignment is
handled.

It doesn't actually do that bit yet though, as the wayland
key repeat processing was a bit more involved and I wanted
to constrain the scope of this commit.

refs: #877
This commit is contained in:
Wez Furlong 2022-01-02 15:33:42 -07:00
parent d5726ba91a
commit 6feabb8178
4 changed files with 71 additions and 41 deletions

View File

@ -116,6 +116,12 @@ impl WindowState {
}
}
#[derive(Debug, Clone)]
pub enum WindowKeyEvent {
RawKeyEvent(RawKeyEvent),
KeyEvent(KeyEvent),
}
#[derive(Debug)]
pub enum WindowEvent {
/// Called when the window close button is clicked.

View File

@ -6,7 +6,7 @@ use crate::os::wayland::connection::WaylandConnection;
use crate::os::x11::keyboard::Keyboard;
use crate::{
Clipboard, Connection, Dimensions, MouseCursor, Point, ScreenPoint, Window, WindowEvent,
WindowEventSender, WindowOps, WindowState,
WindowEventSender, WindowKeyEvent, WindowOps, WindowState,
};
use anyhow::{anyhow, bail, Context};
use async_io::Timer;
@ -41,7 +41,7 @@ use wezterm_input_types::*;
#[derive(Debug)]
struct KeyRepeatState {
when: Instant,
key: KeyEvent,
event: WindowKeyEvent,
}
impl KeyRepeatState {
@ -82,9 +82,8 @@ impl KeyRepeatState {
}
let mut st = state.lock().unwrap();
let mut event = st.key.clone();
event.repeat_count = 1;
let mut repeat_count = 1;
let mut elapsed = st.when.elapsed();
if initial {
@ -96,10 +95,22 @@ impl KeyRepeatState {
// gap, we need to inflate the repeat count to match
// the intended rate
while elapsed >= gap {
event.repeat_count += 1;
repeat_count += 1;
elapsed -= gap;
}
inner.events.dispatch(WindowEvent::KeyEvent(event));
let event = match st.event.clone() {
WindowKeyEvent::KeyEvent(mut key) => {
key.repeat_count = repeat_count;
WindowEvent::KeyEvent(key)
}
WindowKeyEvent::RawKeyEvent(mut raw) => {
raw.repeat_count = repeat_count;
WindowEvent::RawKeyEvent(raw)
}
};
inner.events.dispatch(event);
st.when = Instant::now();
}
@ -400,18 +411,15 @@ impl WaylandWindowInner {
self.emit_focus(mapper, false);
}
WlKeyboardEvent::Key { key, state, .. } => {
if let Some(event) = mapper.process_wayland_key(key, state == KeyState::Pressed) {
if event.key_is_down && mapper.wayland_key_repeats(key) {
let rep = Arc::new(Mutex::new(KeyRepeatState {
when: Instant::now(),
key: event.clone(),
}));
self.key_repeat.replace(Arc::clone(&rep));
KeyRepeatState::schedule(rep, self.window_id);
} else {
self.key_repeat.take();
}
self.events.dispatch(WindowEvent::KeyEvent(event));
if let Some(event) =
mapper.process_wayland_key(key, state == KeyState::Pressed, &mut self.events)
{
let rep = Arc::new(Mutex::new(KeyRepeatState {
when: Instant::now(),
event,
}));
self.key_repeat.replace(Arc::clone(&rep));
KeyRepeatState::schedule(rep, self.window_id);
} else {
self.key_repeat.take();
}

View File

@ -1,5 +1,5 @@
use crate::os::xkeysyms::keysym_to_keycode;
use crate::{KeyEvent, Modifiers};
use crate::{KeyEvent, Modifiers, WindowEvent, WindowEventSender, WindowKeyEvent};
use anyhow::{anyhow, ensure};
use libc;
use std::cell::RefCell;
@ -146,18 +146,30 @@ impl Keyboard {
self.keymap.borrow().key_repeats(code + 8)
}
pub fn process_wayland_key(&self, code: u32, pressed: bool) -> Option<KeyEvent> {
self.process_key_event_impl(code + 8, pressed)
pub fn process_wayland_key(
&self,
code: u32,
pressed: bool,
events: &mut WindowEventSender,
) -> Option<WindowKeyEvent> {
let want_repeat = self.wayland_key_repeats(code);
self.process_key_event_impl(code + 8, pressed, events, want_repeat)
}
pub fn process_key_event(&self, xcb_ev: &xcb::KeyPressEvent) -> Option<KeyEvent> {
pub fn process_key_event(&self, xcb_ev: &xcb::KeyPressEvent, events: &mut WindowEventSender) {
let pressed = (xcb_ev.response_type() & !0x80) == xcb::KEY_PRESS;
let xcode = xkb::Keycode::from(xcb_ev.detail());
self.process_key_event_impl(xcode, pressed)
self.process_key_event_impl(xcode, pressed, events, false);
}
fn process_key_event_impl(&self, xcode: xkb::Keycode, pressed: bool) -> Option<KeyEvent> {
fn process_key_event_impl(
&self,
xcode: xkb::Keycode,
pressed: bool,
events: &mut WindowEventSender,
want_repeat: bool,
) -> Option<WindowKeyEvent> {
let xsym = self.state.borrow().key_get_one_sym(xcode);
let mut kc = None;
@ -216,19 +228,26 @@ impl Keyboard {
(_, mods) => mods,
};
Some(
KeyEvent {
key: kc,
modifiers,
raw_key: None,
raw_modifiers,
raw_code: Some(xcode),
phys_code: self.phys_code_map.borrow().get(&xcode).copied(),
repeat_count: 1,
key_is_down: pressed,
}
.normalize_ctrl(),
)
let event = KeyEvent {
key: kc,
modifiers,
raw_key: None,
raw_modifiers,
raw_code: Some(xcode),
phys_code: self.phys_code_map.borrow().get(&xcode).copied(),
repeat_count: 1,
key_is_down: pressed,
}
.normalize_ctrl();
if pressed && want_repeat {
events.dispatch(WindowEvent::KeyEvent(event.clone()));
// Returns the event that should be repeated later
Some(WindowKeyEvent::KeyEvent(event))
} else {
events.dispatch(WindowEvent::KeyEvent(event));
None
}
}
fn mod_is_active(&self, modifier: &str) -> bool {

View File

@ -269,10 +269,7 @@ impl XWindowInner {
xcb::KEY_PRESS | xcb::KEY_RELEASE => {
let key_press: &xcb::KeyPressEvent = unsafe { xcb::cast_event(event) };
self.copy_and_paste.time = key_press.time();
if let Some(key) = conn.keyboard.process_key_event(key_press) {
let key = key.normalize_shift();
self.events.dispatch(WindowEvent::KeyEvent(key));
}
conn.keyboard.process_key_event(key_press, &mut self.events);
}
xcb::MOTION_NOTIFY => {