seat: implement key repeat
This commit is contained in:
parent
0e1be7544f
commit
4b4f05d153
10 changed files with 153 additions and 19 deletions
|
|
@ -902,6 +902,7 @@ impl WlSeatGlobal {
|
|||
match key_state {
|
||||
KeyState::Released => pk.remove(&kc.to_evdev()),
|
||||
KeyState::Pressed => pk.insert(kc.to_evdev()),
|
||||
KeyState::Repeated => unreachable!(),
|
||||
}
|
||||
};
|
||||
if key_state == KeyState::Pressed
|
||||
|
|
@ -922,6 +923,7 @@ impl WlSeatGlobal {
|
|||
continue;
|
||||
}
|
||||
shortcuts.clear();
|
||||
let repeats;
|
||||
{
|
||||
let mut mods = kbvm_state.kb_state.mods.mods.0 & !(CAPS.0 | NUM.0);
|
||||
if key_state == KeyState::Released {
|
||||
|
|
@ -933,6 +935,7 @@ impl WlSeatGlobal {
|
|||
ModifierMask::default(),
|
||||
kc,
|
||||
);
|
||||
repeats = keysyms.repeats();
|
||||
let mut revert_pointer_to_default = false;
|
||||
for props in keysyms {
|
||||
let sym = props.keysym().0;
|
||||
|
|
@ -982,28 +985,44 @@ impl WlSeatGlobal {
|
|||
}
|
||||
}
|
||||
self.send_components(&mut components_changed, &kbvm_state);
|
||||
let mut forward_to_node = true;
|
||||
if let Some(g) = self.input_method_grab.get() {
|
||||
forward_to_node =
|
||||
g.on_key(time_usec, kc.to_evdev(), key_state, &kbvm_state.kb_state);
|
||||
}
|
||||
if forward_to_node {
|
||||
self.keyboard_node.get().node_on_key(
|
||||
self,
|
||||
time_usec,
|
||||
kc.to_evdev(),
|
||||
key_state,
|
||||
&kbvm_state.kb_state,
|
||||
)
|
||||
}
|
||||
self.send_key(time_usec, kc, key_state, &kbvm_state.kb_state);
|
||||
self.for_each_ei_seat(|ei_seat| {
|
||||
ei_seat.handle_key(time_usec, kc.to_evdev(), key_state, &kbvm_state.kb_state);
|
||||
});
|
||||
update_pressed_keys(&mut kbvm_state);
|
||||
match key_state {
|
||||
KeyState::Released => {
|
||||
if self.repeat_key.get() == Some(kc) {
|
||||
self.clear_repeat_key();
|
||||
}
|
||||
}
|
||||
KeyState::Pressed => {
|
||||
if repeats {
|
||||
self.set_repeat_key(kc, kbvm_state_rc);
|
||||
}
|
||||
}
|
||||
KeyState::Repeated => {}
|
||||
}
|
||||
}
|
||||
self.send_components(&mut components_changed, &kbvm_state);
|
||||
}
|
||||
|
||||
fn send_key(&self, time_usec: u64, kc: Keycode, key_state: KeyState, kb_state: &KeyboardState) {
|
||||
let mut forward_to_node = true;
|
||||
if let Some(g) = self.input_method_grab.get() {
|
||||
forward_to_node = g.on_key(time_usec, kc.to_evdev(), key_state, kb_state);
|
||||
}
|
||||
if forward_to_node {
|
||||
self.keyboard_node.get().node_on_key(
|
||||
self,
|
||||
time_usec,
|
||||
kc.to_evdev(),
|
||||
key_state,
|
||||
kb_state,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_mark_interactive(&self) {
|
||||
self.mark_mode.set(Some(MarkMode::Mark));
|
||||
}
|
||||
|
|
@ -1306,6 +1325,82 @@ impl WlSeatGlobal {
|
|||
}
|
||||
self.changes.set(0);
|
||||
}
|
||||
|
||||
pub(super) fn set_repeat_key(&self, key: Keycode, state: &Rc<RefCell<KbvmState>>) {
|
||||
self.repeat_key_version.fetch_add(1);
|
||||
self.repeat_key_start_ns.set(self.state.now_nsec());
|
||||
self.repeat_key_state.set(Some(state.clone()));
|
||||
let old = self.repeat_key.replace(Some(key));
|
||||
if old.is_none() {
|
||||
self.have_repeat_key.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn clear_repeat_key(&self) {
|
||||
self.repeat_key_version.fetch_add(1);
|
||||
self.repeat_key_state.take();
|
||||
self.repeat_key.take();
|
||||
}
|
||||
|
||||
pub(super) fn create_repeat_handler(self: &Rc<Self>) {
|
||||
self.clear_repeat_key();
|
||||
let (rate, delay_ms) = self.repeat_rate.get();
|
||||
self.key_repeater.take();
|
||||
if rate == 0 {
|
||||
return;
|
||||
}
|
||||
let delay_first_repeat_ns = delay_ms as u64 * 1_000_000;
|
||||
let delay_subsequent_repeat_ns = 1_000_000_000 / rate as u64;
|
||||
let slf = self.clone();
|
||||
let handle = self.state.eng.spawn("key repeat", async move {
|
||||
'outer: loop {
|
||||
let Some(key) = slf.repeat_key.get() else {
|
||||
slf.have_repeat_key.triggered().await;
|
||||
continue;
|
||||
};
|
||||
let mut base_ns = slf.repeat_key_start_ns.get();
|
||||
let kbvm_state = slf.repeat_key_state.get().unwrap();
|
||||
let version = slf.repeat_key_version.get();
|
||||
macro_rules! check_version {
|
||||
() => {
|
||||
if slf.repeat_key_version.get() != version {
|
||||
continue 'outer;
|
||||
}
|
||||
};
|
||||
}
|
||||
let target_ns = base_ns + delay_first_repeat_ns;
|
||||
slf.state.ring.timeout(target_ns).await.unwrap();
|
||||
check_version!();
|
||||
let send_key = |now_ns: u64| {
|
||||
slf.send_key(
|
||||
now_ns / 1_000,
|
||||
key,
|
||||
KeyState::Repeated,
|
||||
&kbvm_state.borrow().kb_state,
|
||||
);
|
||||
};
|
||||
send_key(target_ns);
|
||||
base_ns = target_ns;
|
||||
let mut now_ns = slf.state.now_nsec();
|
||||
loop {
|
||||
let max_sleep_ns = now_ns + delay_first_repeat_ns;
|
||||
let target_ns = base_ns + delay_subsequent_repeat_ns;
|
||||
slf.state
|
||||
.ring
|
||||
.timeout(target_ns.min(max_sleep_ns))
|
||||
.await
|
||||
.unwrap();
|
||||
check_version!();
|
||||
now_ns = slf.state.now_nsec();
|
||||
if now_ns >= target_ns {
|
||||
send_key(target_ns);
|
||||
base_ns = target_ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
self.key_repeater.set(Some(handle));
|
||||
}
|
||||
}
|
||||
|
||||
// Button callbacks
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ impl UnicodeInput {
|
|||
|
||||
impl InputMethodKeyboardGrab for SimpleIm {
|
||||
fn on_key(&self, _time_usec: u64, key: u32, state: KeyState, kb_state: &KeyboardState) -> bool {
|
||||
if state != KeyState::Pressed {
|
||||
if state == KeyState::Released {
|
||||
return true;
|
||||
}
|
||||
let Some(con) = self.con.get() else {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ impl ZwpInputMethodKeyboardGrabV2 {
|
|||
state: match state {
|
||||
KeyState::Released => wl_keyboard::RELEASED,
|
||||
KeyState::Pressed => wl_keyboard::PRESSED,
|
||||
KeyState::Repeated => return,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use {
|
|||
};
|
||||
|
||||
pub const REPEAT_INFO_SINCE: Version = Version(4);
|
||||
pub const REPEATED_SINCE: Version = Version(10);
|
||||
|
||||
#[expect(dead_code)]
|
||||
const NO_KEYMAP: u32 = 0;
|
||||
|
|
@ -25,6 +26,7 @@ pub const XKB_V1: u32 = 1;
|
|||
|
||||
pub const RELEASED: u32 = 0;
|
||||
pub const PRESSED: u32 = 1;
|
||||
pub const REPEATED: u32 = 2;
|
||||
|
||||
pub struct WlKeyboard {
|
||||
id: WlKeyboardId,
|
||||
|
|
@ -132,6 +134,9 @@ impl WlKeyboard {
|
|||
}
|
||||
|
||||
fn send_key(&self, serial: u64, time: u32, key: u32, state: KeyState) {
|
||||
if state == KeyState::Repeated && self.seat.version < REPEATED_SINCE {
|
||||
return;
|
||||
}
|
||||
{
|
||||
let pk = &mut self.pressed_keys.borrow_mut();
|
||||
match state {
|
||||
|
|
@ -145,6 +150,11 @@ impl WlKeyboard {
|
|||
return;
|
||||
}
|
||||
}
|
||||
KeyState::Repeated => {
|
||||
if !pk.contains(&key) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.seat.client.event(Key {
|
||||
|
|
@ -155,6 +165,7 @@ impl WlKeyboard {
|
|||
state: match state {
|
||||
KeyState::Released => RELEASED,
|
||||
KeyState::Pressed => PRESSED,
|
||||
KeyState::Repeated => REPEATED,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -178,7 +189,11 @@ impl WlKeyboard {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn send_repeat_info(self: &Rc<Self>, rate: i32, delay: i32) {
|
||||
pub fn send_repeat_info(self: &Rc<Self>, mut rate: i32, mut delay: i32) {
|
||||
if self.seat.version >= REPEATED_SINCE {
|
||||
rate = 0;
|
||||
delay = 0;
|
||||
}
|
||||
self.seat.client.event(RepeatInfo {
|
||||
self_id: self.id,
|
||||
rate,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue