Skip to content

Commit

Permalink
macos: handle key repeat
Browse files Browse the repository at this point in the history
  • Loading branch information
kiwiz committed Jan 25, 2024
1 parent 52f2354 commit 78c6cc5
Showing 1 changed file with 51 additions and 15 deletions.
66 changes: 51 additions & 15 deletions src/backend/consumer/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@ use core_graphics::event::{
use core_graphics::event_source::{CGEventSource, CGEventSourceStateID};
use keycode::{KeyMap, KeyMapping};
use std::ops::{Index, IndexMut};
use std::time::Duration;
use tokio::task::AbortHandle;

const DEFAULT_REPEAT_DELAY: Duration = Duration::from_millis(500);
const DEFAULT_REPEAT_INTERVAL: Duration = Duration::from_millis(32);

pub struct MacOSConsumer {
pub event_source: CGEventSource,
repeat_task: Option<AbortHandle>,
button_state: ButtonState,
}

Expand Down Expand Up @@ -60,13 +66,52 @@ impl MacOSConsumer {
Ok(Self {
event_source,
button_state,
repeat_task: None
})
}

fn get_mouse_location(&self) -> Option<CGPoint> {
let event: CGEvent = CGEvent::new(self.event_source.clone()).ok()?;
Some(event.location())
}

async fn spawn_repeat_task(&mut self, key: u16) {
// there can only be one repeating key and it's
// always the last to be pressed
self.kill_repeat_task();
let event_source = self.event_source.clone();
let repeat_task = tokio::task::spawn_local(async move {
tokio::time::sleep(DEFAULT_REPEAT_DELAY).await;
loop {
key_event(event_source.clone(), key, 1);
tokio::time::sleep(DEFAULT_REPEAT_INTERVAL).await;
}
});
self.repeat_task = Some(repeat_task.abort_handle());
}
fn kill_repeat_task(&mut self) {
if let Some(task) = self.repeat_task.take() {
task.abort();
}
}
}

fn key_event(event_source: CGEventSource, key: u16, state: u8) {
let event = match CGEvent::new_keyboard_event(
event_source,
key,
match state {
1 => true,
_ => false,
},
) {
Ok(e) => e,
Err(_) => {
log::warn!("unable to create key event");
return;
}
};
event.post(CGEventTapLocation::HID);
}

#[async_trait]
Expand Down Expand Up @@ -222,21 +267,12 @@ impl EventConsumer for MacOSConsumer {
return;
}
};
let event = match CGEvent::new_keyboard_event(
self.event_source.clone(),
code,
match state {
1 => true,
_ => false,
},
) {
Ok(e) => e,
Err(_) => {
log::warn!("unable to create key event");
return;
}
};
event.post(CGEventTapLocation::HID);
match state {
// pressed
1 => self.spawn_repeat_task(code).await,
_ => self.kill_repeat_task(),
}
key_event(self.event_source.clone(), code, state)
}
KeyboardEvent::Modifiers { .. } => {}
},
Expand Down

0 comments on commit 78c6cc5

Please sign in to comment.