Skip to content

Commit 4b4f05d

Browse files
committed
seat: implement key repeat
1 parent 0e1be75 commit 4b4f05d

File tree

10 files changed

+153
-19
lines changed

10 files changed

+153
-19
lines changed

docs/features.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ Jay supports the following wayland protocols:
170170
| wl_drm | 2 | |
171171
| wl_fixes | 1 | |
172172
| wl_output | 4 | |
173-
| wl_seat | 9 | |
173+
| wl_seat | 10 | |
174174
| wl_shm | 2 | |
175175
| wl_subcompositor | 1 | |
176176
| wp_alpha_modifier_v1 | 1 | |

src/backend.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ pub enum BackendEvent {
315315
pub enum KeyState {
316316
Released,
317317
Pressed,
318+
Repeated,
318319
}
319320

320321
#[derive(Debug, Copy, Clone, Eq, PartialEq)]

src/ei/ei_ifs/ei_keyboard.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ impl EiKeyboard {
5959
state: match state {
6060
KeyState::Released => 0,
6161
KeyState::Pressed => 1,
62+
KeyState::Repeated => return,
6263
},
6364
});
6465
}

src/ifs/wl_seat.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ pub struct WlSeatGlobal {
188188
>,
189189
data_control_devices: CopyHashMap<DataControlDeviceId, Rc<dyn DynDataControlDevice>>,
190190
repeat_rate: Cell<(i32, i32)>,
191+
key_repeater: Cell<Option<SpawnedFuture<()>>>,
192+
repeat_key: Cell<Option<Keycode>>,
193+
repeat_key_state: CloneCell<Option<Rc<RefCell<KbvmState>>>>,
194+
repeat_key_version: NumCell<u64>,
195+
repeat_key_start_ns: Cell<u64>,
196+
have_repeat_key: AsyncEvent,
191197
seat_kb_map: CloneCell<Rc<KbvmMap>>,
192198
seat_kb_state: CloneCell<Rc<RefCell<KbvmState>>>,
193199
latest_kb_state: CloneCell<Rc<dyn DynKeyboardState>>,
@@ -280,6 +286,12 @@ impl WlSeatGlobal {
280286
data_devices: RefCell::new(Default::default()),
281287
primary_selection_devices: RefCell::new(Default::default()),
282288
repeat_rate: Cell::new((25, 250)),
289+
key_repeater: Default::default(),
290+
repeat_key: Default::default(),
291+
repeat_key_state: Default::default(),
292+
repeat_key_version: Default::default(),
293+
repeat_key_start_ns: Default::default(),
294+
have_repeat_key: Default::default(),
283295
seat_kb_map: CloneCell::new(state.default_keymap.clone()),
284296
seat_kb_state: CloneCell::new(seat_kb_state.clone()),
285297
latest_kb_state: CloneCell::new(seat_kb_state.clone()),
@@ -336,6 +348,7 @@ impl WlSeatGlobal {
336348
slf.pointer_cursor.set_owner(slf.clone());
337349
slf.modifiers_listener
338350
.attach(&seat_kb_state.borrow().kb_state.leds_changed);
351+
slf.create_repeat_handler();
339352
let seat = slf.clone();
340353
let future = state.eng.spawn("seat handler", async move {
341354
loop {
@@ -684,8 +697,9 @@ impl WlSeatGlobal {
684697
self.repeat_rate.get()
685698
}
686699

687-
pub fn set_rate(&self, rate: i32, delay: i32) {
700+
pub fn set_rate(self: &Rc<Self>, rate: i32, delay: i32) {
688701
self.repeat_rate.set((rate, delay));
702+
self.create_repeat_handler();
689703
let bindings = self.bindings.borrow_mut();
690704
for client in bindings.values() {
691705
for seat in client.values() {
@@ -1252,6 +1266,8 @@ impl WlSeatGlobal {
12521266
self.tablet_clear();
12531267
self.ei_seats.clear();
12541268
self.marks.clear();
1269+
self.key_repeater.take();
1270+
self.repeat_key_state.take();
12551271
}
12561272

12571273
pub fn id(&self) -> SeatId {
@@ -1482,7 +1498,7 @@ impl Global for WlSeatGlobal {
14821498
}
14831499

14841500
fn version(&self) -> u32 {
1485-
9
1501+
10
14861502
}
14871503
}
14881504

src/ifs/wl_seat/event_handling.rs

Lines changed: 109 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,7 @@ impl WlSeatGlobal {
902902
match key_state {
903903
KeyState::Released => pk.remove(&kc.to_evdev()),
904904
KeyState::Pressed => pk.insert(kc.to_evdev()),
905+
KeyState::Repeated => unreachable!(),
905906
}
906907
};
907908
if key_state == KeyState::Pressed
@@ -922,6 +923,7 @@ impl WlSeatGlobal {
922923
continue;
923924
}
924925
shortcuts.clear();
926+
let repeats;
925927
{
926928
let mut mods = kbvm_state.kb_state.mods.mods.0 & !(CAPS.0 | NUM.0);
927929
if key_state == KeyState::Released {
@@ -933,6 +935,7 @@ impl WlSeatGlobal {
933935
ModifierMask::default(),
934936
kc,
935937
);
938+
repeats = keysyms.repeats();
936939
let mut revert_pointer_to_default = false;
937940
for props in keysyms {
938941
let sym = props.keysym().0;
@@ -982,28 +985,44 @@ impl WlSeatGlobal {
982985
}
983986
}
984987
self.send_components(&mut components_changed, &kbvm_state);
985-
let mut forward_to_node = true;
986-
if let Some(g) = self.input_method_grab.get() {
987-
forward_to_node =
988-
g.on_key(time_usec, kc.to_evdev(), key_state, &kbvm_state.kb_state);
989-
}
990-
if forward_to_node {
991-
self.keyboard_node.get().node_on_key(
992-
self,
993-
time_usec,
994-
kc.to_evdev(),
995-
key_state,
996-
&kbvm_state.kb_state,
997-
)
998-
}
988+
self.send_key(time_usec, kc, key_state, &kbvm_state.kb_state);
999989
self.for_each_ei_seat(|ei_seat| {
1000990
ei_seat.handle_key(time_usec, kc.to_evdev(), key_state, &kbvm_state.kb_state);
1001991
});
1002992
update_pressed_keys(&mut kbvm_state);
993+
match key_state {
994+
KeyState::Released => {
995+
if self.repeat_key.get() == Some(kc) {
996+
self.clear_repeat_key();
997+
}
998+
}
999+
KeyState::Pressed => {
1000+
if repeats {
1001+
self.set_repeat_key(kc, kbvm_state_rc);
1002+
}
1003+
}
1004+
KeyState::Repeated => {}
1005+
}
10031006
}
10041007
self.send_components(&mut components_changed, &kbvm_state);
10051008
}
10061009

1010+
fn send_key(&self, time_usec: u64, kc: Keycode, key_state: KeyState, kb_state: &KeyboardState) {
1011+
let mut forward_to_node = true;
1012+
if let Some(g) = self.input_method_grab.get() {
1013+
forward_to_node = g.on_key(time_usec, kc.to_evdev(), key_state, kb_state);
1014+
}
1015+
if forward_to_node {
1016+
self.keyboard_node.get().node_on_key(
1017+
self,
1018+
time_usec,
1019+
kc.to_evdev(),
1020+
key_state,
1021+
kb_state,
1022+
)
1023+
}
1024+
}
1025+
10071026
pub fn create_mark_interactive(&self) {
10081027
self.mark_mode.set(Some(MarkMode::Mark));
10091028
}
@@ -1306,6 +1325,82 @@ impl WlSeatGlobal {
13061325
}
13071326
self.changes.set(0);
13081327
}
1328+
1329+
pub(super) fn set_repeat_key(&self, key: Keycode, state: &Rc<RefCell<KbvmState>>) {
1330+
self.repeat_key_version.fetch_add(1);
1331+
self.repeat_key_start_ns.set(self.state.now_nsec());
1332+
self.repeat_key_state.set(Some(state.clone()));
1333+
let old = self.repeat_key.replace(Some(key));
1334+
if old.is_none() {
1335+
self.have_repeat_key.trigger();
1336+
}
1337+
}
1338+
1339+
pub(super) fn clear_repeat_key(&self) {
1340+
self.repeat_key_version.fetch_add(1);
1341+
self.repeat_key_state.take();
1342+
self.repeat_key.take();
1343+
}
1344+
1345+
pub(super) fn create_repeat_handler(self: &Rc<Self>) {
1346+
self.clear_repeat_key();
1347+
let (rate, delay_ms) = self.repeat_rate.get();
1348+
self.key_repeater.take();
1349+
if rate == 0 {
1350+
return;
1351+
}
1352+
let delay_first_repeat_ns = delay_ms as u64 * 1_000_000;
1353+
let delay_subsequent_repeat_ns = 1_000_000_000 / rate as u64;
1354+
let slf = self.clone();
1355+
let handle = self.state.eng.spawn("key repeat", async move {
1356+
'outer: loop {
1357+
let Some(key) = slf.repeat_key.get() else {
1358+
slf.have_repeat_key.triggered().await;
1359+
continue;
1360+
};
1361+
let mut base_ns = slf.repeat_key_start_ns.get();
1362+
let kbvm_state = slf.repeat_key_state.get().unwrap();
1363+
let version = slf.repeat_key_version.get();
1364+
macro_rules! check_version {
1365+
() => {
1366+
if slf.repeat_key_version.get() != version {
1367+
continue 'outer;
1368+
}
1369+
};
1370+
}
1371+
let target_ns = base_ns + delay_first_repeat_ns;
1372+
slf.state.ring.timeout(target_ns).await.unwrap();
1373+
check_version!();
1374+
let send_key = |now_ns: u64| {
1375+
slf.send_key(
1376+
now_ns / 1_000,
1377+
key,
1378+
KeyState::Repeated,
1379+
&kbvm_state.borrow().kb_state,
1380+
);
1381+
};
1382+
send_key(target_ns);
1383+
base_ns = target_ns;
1384+
let mut now_ns = slf.state.now_nsec();
1385+
loop {
1386+
let max_sleep_ns = now_ns + delay_first_repeat_ns;
1387+
let target_ns = base_ns + delay_subsequent_repeat_ns;
1388+
slf.state
1389+
.ring
1390+
.timeout(target_ns.min(max_sleep_ns))
1391+
.await
1392+
.unwrap();
1393+
check_version!();
1394+
now_ns = slf.state.now_nsec();
1395+
if now_ns >= target_ns {
1396+
send_key(target_ns);
1397+
base_ns = target_ns;
1398+
}
1399+
}
1400+
}
1401+
});
1402+
self.key_repeater.set(Some(handle));
1403+
}
13091404
}
13101405

13111406
// Button callbacks

src/ifs/wl_seat/text_input/simple_im.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl UnicodeInput {
168168

169169
impl InputMethodKeyboardGrab for SimpleIm {
170170
fn on_key(&self, _time_usec: u64, key: u32, state: KeyState, kb_state: &KeyboardState) -> bool {
171-
if state != KeyState::Pressed {
171+
if state == KeyState::Released {
172172
return true;
173173
}
174174
let Some(con) = self.con.get() else {

src/ifs/wl_seat/text_input/zwp_input_method_keyboard_grab_v2.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl ZwpInputMethodKeyboardGrabV2 {
6969
state: match state {
7070
KeyState::Released => wl_keyboard::RELEASED,
7171
KeyState::Pressed => wl_keyboard::PRESSED,
72+
KeyState::Repeated => return,
7273
},
7374
})
7475
}

src/ifs/wl_seat/wl_keyboard.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ use {
1818
};
1919

2020
pub const REPEAT_INFO_SINCE: Version = Version(4);
21+
pub const REPEATED_SINCE: Version = Version(10);
2122

2223
#[expect(dead_code)]
2324
const NO_KEYMAP: u32 = 0;
2425
pub const XKB_V1: u32 = 1;
2526

2627
pub const RELEASED: u32 = 0;
2728
pub const PRESSED: u32 = 1;
29+
pub const REPEATED: u32 = 2;
2830

2931
pub struct WlKeyboard {
3032
id: WlKeyboardId,
@@ -132,6 +134,9 @@ impl WlKeyboard {
132134
}
133135

134136
fn send_key(&self, serial: u64, time: u32, key: u32, state: KeyState) {
137+
if state == KeyState::Repeated && self.seat.version < REPEATED_SINCE {
138+
return;
139+
}
135140
{
136141
let pk = &mut self.pressed_keys.borrow_mut();
137142
match state {
@@ -145,6 +150,11 @@ impl WlKeyboard {
145150
return;
146151
}
147152
}
153+
KeyState::Repeated => {
154+
if !pk.contains(&key) {
155+
return;
156+
}
157+
}
148158
}
149159
}
150160
self.seat.client.event(Key {
@@ -155,6 +165,7 @@ impl WlKeyboard {
155165
state: match state {
156166
KeyState::Released => RELEASED,
157167
KeyState::Pressed => PRESSED,
168+
KeyState::Repeated => REPEATED,
158169
},
159170
})
160171
}
@@ -178,7 +189,11 @@ impl WlKeyboard {
178189
})
179190
}
180191

181-
pub fn send_repeat_info(self: &Rc<Self>, rate: i32, delay: i32) {
192+
pub fn send_repeat_info(self: &Rc<Self>, mut rate: i32, mut delay: i32) {
193+
if self.seat.version >= REPEATED_SINCE {
194+
rate = 0;
195+
delay = 0;
196+
}
182197
self.seat.client.event(RepeatInfo {
183198
self_id: self.id,
184199
rate,

src/it/test_ifs/test_virtual_keyboard.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ impl TestVirtualKeyboard {
4646
let state = match state {
4747
KeyState::Released => wl_keyboard::RELEASED,
4848
KeyState::Pressed => wl_keyboard::PRESSED,
49+
KeyState::Repeated => wl_keyboard::REPEATED,
4950
};
5051
self.tran.send(Key {
5152
self_id: self.id,

src/kbvm.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ impl PhysicalKeyboardState {
213213
return;
214214
}
215215
}
216+
KeyState::Repeated => {
217+
return;
218+
}
216219
}
217220
let state = &mut *self.state.borrow_mut();
218221
state.map.state_machine.handle_key(
@@ -222,6 +225,7 @@ impl PhysicalKeyboardState {
222225
match key_state {
223226
KeyState::Released => Direction::Up,
224227
KeyState::Pressed => Direction::Down,
228+
KeyState::Repeated => unreachable!(),
225229
},
226230
);
227231
self.events.append(&mut inner.event_stash);

0 commit comments

Comments
 (0)