propagate event tap creation error (#218)

This commit is contained in:
Ferdinand Schober
2024-10-25 16:31:15 +02:00
committed by GitHub
parent 9f52a2ac93
commit 75b790ec2e
2 changed files with 48 additions and 18 deletions

View File

@@ -93,7 +93,7 @@ pub enum CaptureCreationError {
#[error("error creating windows capture backend")] #[error("error creating windows capture backend")]
Windows, Windows,
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
#[error("error creating macos capture backend")] #[error("error creating macos capture backend: `{0}`")]
MacOS(#[from] MacosCaptureCreationError), MacOS(#[from] MacosCaptureCreationError),
} }
@@ -165,6 +165,9 @@ pub enum X11InputCaptureCreationError {
pub enum MacosCaptureCreationError { pub enum MacosCaptureCreationError {
#[error("event source creation failed!")] #[error("event source creation failed!")]
EventSourceCreation, EventSourceCreation,
#[cfg(target_os = "macos")]
#[error("event tap creation failed")]
EventTapCreation,
#[error("failed to set CG Cursor property")] #[error("failed to set CG Cursor property")]
CGCursorProperty, CGCursorProperty,
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]

View File

@@ -24,8 +24,8 @@ use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use std::task::{ready, Context, Poll}; use std::task::{ready, Context, Poll};
use std::thread::{self}; use std::thread::{self};
use tokio::sync::mpsc::{Receiver, Sender}; use tokio::sync::mpsc::{self, Receiver, Sender};
use tokio::sync::Mutex; use tokio::sync::{oneshot, Mutex};
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct Bounds { struct Bounds {
@@ -322,12 +322,11 @@ fn get_events(
Ok(()) Ok(())
} }
fn event_tap_thread( fn create_event_tap<'a>(
client_state: Arc<Mutex<InputCaptureState>>, client_state: Arc<Mutex<InputCaptureState>>,
event_tx: Sender<(Position, CaptureEvent)>,
notify_tx: Sender<ProducerEvent>, notify_tx: Sender<ProducerEvent>,
exit: tokio::sync::oneshot::Sender<Result<(), &'static str>>, event_tx: Sender<(Position, CaptureEvent)>,
) { ) -> Result<CGEventTap<'a>, MacosCaptureCreationError> {
let cg_events_of_interest: Vec<CGEventType> = vec![ let cg_events_of_interest: Vec<CGEventType> = vec![
CGEventType::LeftMouseDown, CGEventType::LeftMouseDown,
CGEventType::LeftMouseUp, CGEventType::LeftMouseUp,
@@ -345,12 +344,8 @@ fn event_tap_thread(
CGEventType::FlagsChanged, CGEventType::FlagsChanged,
]; ];
let tap = CGEventTap::new( let event_tap_callback =
CGEventTapLocation::Session, move |_proxy: CGEventTapProxy, event_type: CGEventType, cg_ev: &CGEvent| {
CGEventTapPlacement::HeadInsertEventTap,
CGEventTapOptions::Default,
cg_events_of_interest,
|_proxy: CGEventTapProxy, event_type: CGEventType, cg_ev: &CGEvent| {
log::trace!("Got event from tap: {event_type:?}"); log::trace!("Got event from tap: {event_type:?}");
let mut state = client_state.blocking_lock(); let mut state = client_state.blocking_lock();
let mut pos = None; let mut pos = None;
@@ -404,9 +399,16 @@ fn event_tap_thread(
cg_ev.set_type(CGEventType::Null); cg_ev.set_type(CGEventType::Null);
} }
Some(cg_ev.to_owned()) Some(cg_ev.to_owned())
}, };
let tap = CGEventTap::new(
CGEventTapLocation::Session,
CGEventTapPlacement::HeadInsertEventTap,
CGEventTapOptions::Default,
cg_events_of_interest,
event_tap_callback,
) )
.expect("Failed creating tap"); .map_err(|_| MacosCaptureCreationError::EventTapCreation)?;
let tap_source: CFRunLoopSource = tap let tap_source: CFRunLoopSource = tap
.mach_port .mach_port
@@ -417,6 +419,26 @@ fn event_tap_thread(
CFRunLoop::get_current().add_source(&tap_source, kCFRunLoopCommonModes); CFRunLoop::get_current().add_source(&tap_source, kCFRunLoopCommonModes);
} }
Ok(tap)
}
fn event_tap_thread(
client_state: Arc<Mutex<InputCaptureState>>,
event_tx: Sender<(Position, CaptureEvent)>,
notify_tx: Sender<ProducerEvent>,
ready: std::sync::mpsc::Sender<Result<(), MacosCaptureCreationError>>,
exit: oneshot::Sender<Result<(), &'static str>>,
) {
let _tap = match create_event_tap(client_state, notify_tx, event_tx) {
Err(e) => {
ready.send(Err(e)).expect("channel closed");
return;
}
Ok(tap) => {
ready.send(Ok(())).expect("channel closed");
tap
}
};
CFRunLoop::run_current(); CFRunLoop::run_current();
let _ = exit.send(Err("tap thread exited")); let _ = exit.send(Err("tap thread exited"));
@@ -430,9 +452,10 @@ pub struct MacOSInputCapture {
impl MacOSInputCapture { impl MacOSInputCapture {
pub async fn new() -> Result<Self, MacosCaptureCreationError> { pub async fn new() -> Result<Self, MacosCaptureCreationError> {
let state = Arc::new(Mutex::new(InputCaptureState::new()?)); let state = Arc::new(Mutex::new(InputCaptureState::new()?));
let (event_tx, event_rx) = tokio::sync::mpsc::channel(32); let (event_tx, event_rx) = mpsc::channel(32);
let (notify_tx, mut notify_rx) = tokio::sync::mpsc::channel(32); let (notify_tx, mut notify_rx) = mpsc::channel(32);
let (tap_exit_tx, mut tap_exit_rx) = tokio::sync::oneshot::channel(); let (ready_tx, ready_rx) = std::sync::mpsc::channel();
let (tap_exit_tx, mut tap_exit_rx) = oneshot::channel();
unsafe { unsafe {
configure_cf_settings()?; configure_cf_settings()?;
@@ -446,10 +469,14 @@ impl MacOSInputCapture {
event_tap_thread_state, event_tap_thread_state,
event_tx, event_tx,
event_tap_notify, event_tap_notify,
ready_tx,
tap_exit_tx, tap_exit_tx,
) )
}); });
// wait for event tap creation result
ready_rx.recv().expect("channel closed")?;
let _tap_task: tokio::task::JoinHandle<()> = tokio::task::spawn_local(async move { let _tap_task: tokio::task::JoinHandle<()> = tokio::task::spawn_local(async move {
loop { loop {
tokio::select! { tokio::select! {