Skip to content

Commit 196d01f

Browse files
committed
macos: fix key-release with repeat logic
1 parent b071201 commit 196d01f

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

input-emulation/src/macos.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ use core_graphics::event_source::{CGEventSource, CGEventSourceStateID};
1111
use input_event::{Event, KeyboardEvent, PointerEvent};
1212
use keycode::{KeyMap, KeyMapping};
1313
use std::ops::{Index, IndexMut};
14+
use std::sync::Arc;
1415
use std::time::Duration;
15-
use tokio::task::AbortHandle;
16+
use tokio::{sync::Notify, task::JoinHandle};
1617

1718
use super::error::MacOSEmulationCreationError;
1819

@@ -21,8 +22,9 @@ const DEFAULT_REPEAT_INTERVAL: Duration = Duration::from_millis(32);
2122

2223
pub(crate) struct MacOSEmulation {
2324
event_source: CGEventSource,
24-
repeat_task: Option<AbortHandle>,
25+
repeat_task: Option<JoinHandle<()>>,
2526
button_state: ButtonState,
27+
notify_repeat_task: Arc<Notify>,
2628
}
2729

2830
struct ButtonState {
@@ -68,6 +70,7 @@ impl MacOSEmulation {
6870
event_source,
6971
button_state,
7072
repeat_task: None,
73+
notify_repeat_task: Arc::new(Notify::new()),
7174
})
7275
}
7376

@@ -79,20 +82,33 @@ impl MacOSEmulation {
7982
async fn spawn_repeat_task(&mut self, key: u16) {
8083
// there can only be one repeating key and it's
8184
// always the last to be pressed
82-
self.kill_repeat_task();
85+
self.cancel_repeat_task().await;
8386
let event_source = self.event_source.clone();
87+
let notify = self.notify_repeat_task.clone();
8488
let repeat_task = tokio::task::spawn_local(async move {
85-
tokio::time::sleep(DEFAULT_REPEAT_DELAY).await;
86-
loop {
87-
key_event(event_source.clone(), key, 1);
88-
tokio::time::sleep(DEFAULT_REPEAT_INTERVAL).await;
89+
let stop = tokio::select! {
90+
_ = tokio::time::sleep(DEFAULT_REPEAT_DELAY) => false,
91+
_ = notify.notified() => true,
92+
};
93+
if !stop {
94+
loop {
95+
key_event(event_source.clone(), key, 1);
96+
tokio::select! {
97+
_ = tokio::time::sleep(DEFAULT_REPEAT_INTERVAL) => {},
98+
_ = notify.notified() => break,
99+
}
100+
}
89101
}
102+
// release key when cancelled
103+
key_event(event_source.clone(), key, 0);
90104
});
91-
self.repeat_task = Some(repeat_task.abort_handle());
105+
self.repeat_task = Some(repeat_task);
92106
}
93-
fn kill_repeat_task(&mut self) {
107+
108+
async fn cancel_repeat_task(&mut self) {
94109
if let Some(task) = self.repeat_task.take() {
95-
task.abort();
110+
self.notify_repeat_task.notify_waiters();
111+
let _ = task.await;
96112
}
97113
}
98114
}
@@ -346,7 +362,7 @@ impl Emulation for MacOSEmulation {
346362
match state {
347363
// pressed
348364
1 => self.spawn_repeat_task(code).await,
349-
_ => self.kill_repeat_task(),
365+
_ => self.cancel_repeat_task().await,
350366
}
351367
key_event(self.event_source.clone(), code, state)
352368
}

0 commit comments

Comments
 (0)