Skip to content

Commit a143329

Browse files
authored
Merge pull request #307 from wash2/kbd_repeat
feat: keyboard repetition
2 parents 45a2ea5 + f8d8f04 commit a143329

File tree

3 files changed

+367
-7
lines changed

3 files changed

+367
-7
lines changed

examples/simple_window.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use std::convert::TryInto;
1+
use std::{convert::TryInto, time::Duration};
22

3+
use calloop::{EventLoop, LoopHandle};
34
use smithay_client_toolkit::{
45
compositor::{CompositorHandler, CompositorState},
56
delegate_compositor, delegate_keyboard, delegate_output, delegate_pointer, delegate_registry,
67
delegate_seat, delegate_shm, delegate_xdg_shell, delegate_xdg_window,
8+
event_loop::WaylandSource,
79
output::{OutputHandler, OutputState},
810
registry::{ProvidesRegistryState, RegistryState},
911
registry_handlers,
@@ -32,8 +34,12 @@ fn main() {
3234

3335
let conn = Connection::connect_to_env().unwrap();
3436

35-
let (globals, mut event_queue) = registry_queue_init(&conn).unwrap();
37+
let (globals, event_queue) = registry_queue_init(&conn).unwrap();
3638
let qh = event_queue.handle();
39+
let mut event_loop: EventLoop<SimpleWindow> =
40+
EventLoop::try_new().expect("Failed to initialize the event loop!");
41+
let loop_handle = event_loop.handle();
42+
WaylandSource::new(event_queue).unwrap().insert(loop_handle).unwrap();
3743

3844
let mut simple_window = SimpleWindow {
3945
registry_state: RegistryState::new(&globals),
@@ -56,6 +62,7 @@ fn main() {
5662
keyboard: None,
5763
keyboard_focus: false,
5864
pointer: None,
65+
loop_handle: event_loop.handle(),
5966
};
6067

6168
let pool = SlotPool::new(
@@ -80,7 +87,7 @@ fn main() {
8087
// We don't draw immediately, the configure will notify us when to first draw.
8188

8289
loop {
83-
event_queue.blocking_dispatch(&mut simple_window).unwrap();
90+
event_loop.dispatch(Duration::from_millis(16), &mut simple_window).unwrap();
8491

8592
if simple_window.exit {
8693
println!("exiting example");
@@ -109,6 +116,7 @@ struct SimpleWindow {
109116
keyboard: Option<wl_keyboard::WlKeyboard>,
110117
keyboard_focus: bool,
111118
pointer: Option<wl_pointer::WlPointer>,
119+
loop_handle: LoopHandle<'static, SimpleWindow>,
112120
}
113121

114122
impl CompositorHandler for SimpleWindow {
@@ -213,8 +221,15 @@ impl SeatHandler for SimpleWindow {
213221
) {
214222
if capability == Capability::Keyboard && self.keyboard.is_none() {
215223
println!("Set keyboard capability");
216-
let keyboard =
217-
self.seat_state.get_keyboard(qh, &seat, None).expect("Failed to create keyboard");
224+
let (keyboard, source) = self
225+
.seat_state
226+
.get_keyboard_with_repeat(qh, &seat, None)
227+
.expect("Failed to create keyboard");
228+
self.loop_handle
229+
.insert_source(source, |e, _, _state| {
230+
dbg!(e);
231+
})
232+
.expect("Failed to insert the repeating keyboard into the event loop");
218233
self.keyboard = Some(keyboard);
219234
}
220235

src/seat/keyboard/mod.rs

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ use xkbcommon::xkb;
2121

2222
use super::{Capability, SeatError, SeatHandler, SeatState};
2323

24+
#[cfg(feature = "calloop")]
25+
pub mod repeat;
26+
#[cfg(feature = "calloop")]
27+
use repeat::RepeatMessage;
28+
2429
/// Error when creating a keyboard.
30+
#[must_use]
2531
#[derive(Debug, thiserror::Error)]
2632
pub enum KeyboardError {
2733
/// Seat error.
@@ -210,7 +216,7 @@ pub trait KeyboardHandler: Sized {
210216
}
211217

212218
/// The rate at which a pressed key is repeated.
213-
#[derive(Debug)]
219+
#[derive(Debug, Clone, Copy)]
214220
pub enum RepeatInfo {
215221
/// Keys will be repeated at the specified rate and delay.
216222
Repeat {
@@ -308,6 +314,9 @@ pub struct KeyboardData {
308314
user_specified_rmlvo: bool,
309315
xkb_state: Mutex<Option<xkb::State>>,
310316
xkb_compose: Mutex<Option<xkb::compose::State>>,
317+
#[cfg(feature = "calloop")]
318+
repeat_sender: Option<calloop::channel::Sender<RepeatMessage>>,
319+
current_repeat: Mutex<Option<KeyEvent>>,
311320
}
312321

313322
impl Debug for KeyboardData {
@@ -350,6 +359,8 @@ impl Default for KeyboardData {
350359
xkb_state: Mutex::new(None),
351360
user_specified_rmlvo: false,
352361
xkb_compose: Mutex::new(None),
362+
repeat_sender: None,
363+
current_repeat: Mutex::new(None),
353364
};
354365

355366
udata.init_compose();
@@ -383,6 +394,8 @@ impl KeyboardData {
383394
xkb_state: Mutex::new(xkb_state),
384395
user_specified_rmlvo: true,
385396
xkb_compose: Mutex::new(None),
397+
repeat_sender: None,
398+
current_repeat: Mutex::new(None),
386399
};
387400

388401
udata.init_compose();
@@ -432,12 +445,17 @@ impl KeyboardData {
432445

433446
pub trait KeyboardDataExt: Send + Sync {
434447
fn keyboard_data(&self) -> &KeyboardData;
448+
fn keyboard_data_mut(&mut self) -> &mut KeyboardData;
435449
}
436450

437451
impl KeyboardDataExt for KeyboardData {
438452
fn keyboard_data(&self) -> &KeyboardData {
439453
self
440454
}
455+
456+
fn keyboard_data_mut(&mut self) -> &mut KeyboardData {
457+
self
458+
}
441459
}
442460

443461
impl<D, U> Dispatch<wl_keyboard::WlKeyboard, U, D> for SeatState
@@ -560,6 +578,13 @@ where
560578
wl_keyboard::Event::Leave { serial, surface } => {
561579
// We can send this event without any other checks in the protocol will guarantee a leave is
562580
// sent before entering a new surface.
581+
#[cfg(feature = "calloop")]
582+
{
583+
if let Some(repeat_sender) = &udata.repeat_sender {
584+
let _ = repeat_sender.send(RepeatMessage::StopRepeat);
585+
}
586+
}
587+
563588
data.leave(conn, qh, keyboard, &surface, serial);
564589
}
565590

@@ -598,10 +623,44 @@ where
598623

599624
match state {
600625
wl_keyboard::KeyState::Released => {
626+
#[cfg(feature = "calloop")]
627+
{
628+
if let Some(repeat_sender) = &udata.repeat_sender {
629+
let mut current_repeat =
630+
udata.current_repeat.lock().unwrap();
631+
if Some(event.raw_code)
632+
== current_repeat.as_ref().map(|r| r.raw_code)
633+
{
634+
current_repeat.take();
635+
let _ = repeat_sender.send(RepeatMessage::StopRepeat);
636+
}
637+
}
638+
}
601639
data.release_key(conn, qh, keyboard, serial, event);
602640
}
603641

604642
wl_keyboard::KeyState::Pressed => {
643+
#[cfg(feature = "calloop")]
644+
{
645+
if let Some(repeat_sender) = &udata.repeat_sender {
646+
let state_guard = udata.xkb_state.lock().unwrap();
647+
let key_repeats = state_guard
648+
.as_ref()
649+
.map(|guard| {
650+
guard.get_keymap().key_repeats(event.raw_code + 8)
651+
})
652+
.unwrap_or_default();
653+
if key_repeats {
654+
udata
655+
.current_repeat
656+
.lock()
657+
.unwrap()
658+
.replace(event.clone());
659+
let _ = repeat_sender
660+
.send(RepeatMessage::StartRepeat(event.clone()));
661+
}
662+
}
663+
}
605664
data.press_key(conn, qh, keyboard, serial, event);
606665
}
607666

@@ -626,7 +685,46 @@ where
626685

627686
let mask = match guard.as_mut() {
628687
Some(state) => {
629-
state.update_mask(mods_depressed, mods_latched, mods_locked, 0, 0, group)
688+
let mask = state.update_mask(
689+
mods_depressed,
690+
mods_latched,
691+
mods_locked,
692+
0,
693+
0,
694+
group,
695+
);
696+
697+
// update current repeating key
698+
let mut current_event = udata.current_repeat.lock().unwrap();
699+
if let Some(mut event) = current_event.take() {
700+
if let Some(repeat_sender) = &udata.repeat_sender {
701+
// apply new modifiers to get new utf8
702+
let utf8 = {
703+
let mut compose = udata.xkb_compose.lock().unwrap();
704+
705+
match compose.as_mut() {
706+
Some(compose) => match compose.feed(event.keysym) {
707+
xkb::FeedResult::Ignored => None,
708+
xkb::FeedResult::Accepted => match compose.status() {
709+
xkb::Status::Composed => compose.utf8(),
710+
xkb::Status::Nothing => {
711+
Some(state.key_get_utf8(event.raw_code + 8))
712+
}
713+
_ => None,
714+
},
715+
},
716+
717+
// No compose
718+
None => Some(state.key_get_utf8(event.raw_code + 8)),
719+
}
720+
};
721+
event.utf8 = utf8;
722+
723+
current_event.replace(event.clone());
724+
let _ = repeat_sender.send(RepeatMessage::StartRepeat(event));
725+
}
726+
}
727+
mask
630728
}
631729
None => return,
632730
};
@@ -650,6 +748,13 @@ where
650748
RepeatInfo::Disable
651749
};
652750

751+
#[cfg(feature = "calloop")]
752+
{
753+
if let Some(repeat_sender) = &udata.repeat_sender {
754+
let _ = repeat_sender.send(RepeatMessage::RepeatInfo(info));
755+
}
756+
}
757+
653758
data.update_repeat_info(conn, qh, keyboard, info);
654759
}
655760

0 commit comments

Comments
 (0)