diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 658bc5c..4df1b18 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -623,7 +623,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -837,6 +837,19 @@ dependencies = [ "libc", ] +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.8.0", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", + "foreign-types 0.5.0", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.1.3" @@ -1253,6 +1266,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +[[package]] +name = "enigo" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71744ff36f35a4276e8827add8102d0e792378c574fd93cb4e1c8e0505f96b7c" +dependencies = [ + "core-foundation 0.10.0", + "core-graphics 0.25.0", + "foreign-types-shared 0.3.1", + "libc", + "log", + "nom 8.0.0", + "objc2 0.6.1", + "objc2-app-kit 0.3.1", + "objc2-foundation 0.3.1", + "windows 0.61.3", + "x11rb", + "xkbcommon", + "xkeysym", +] + [[package]] name = "enum-map" version = "2.7.3" @@ -1956,6 +1990,7 @@ version = "0.1.2" dependencies = [ "anyhow", "cpal", + "enigo", "env_logger", "log", "once_cell", @@ -2753,6 +2788,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.9.1" @@ -2937,6 +2981,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + [[package]] name = "num-complex" version = "0.4.6" @@ -6751,6 +6804,23 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "xkbcommon" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d66ca9352cbd4eecbbc40871d8a11b4ac8107cfc528a6e14d7c19c69d0e1ac9" +dependencies = [ + "libc", + "memmap2", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + [[package]] name = "yoke" version = "0.7.5" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3a7aec7..fcbbe22 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -40,6 +40,7 @@ tokio = "1.43.0" vad-rs = "0.1.5" tauri-plugin-store = "2" tauri-plugin-os = "2" +enigo = "0.5.0" [target.'cfg(target_os = "macos")'.dependencies] whisper-rs = { version = "0.13.2", features = ["metal"] } diff --git a/src-tauri/src/actions.rs b/src-tauri/src/actions.rs index 2045db4..ef6a976 100644 --- a/src-tauri/src/actions.rs +++ b/src-tauri/src/actions.rs @@ -43,7 +43,17 @@ impl ShortcutAction for TranscribeAction { Ok(transcription) => { println!("Transcription Result: {}", transcription); if !transcription.is_empty() { - utils::paste(transcription, ah); + let transcription_clone = transcription.clone(); + let ah_clone = ah.clone(); + ah.run_on_main_thread(move || { + match utils::paste(transcription_clone, ah_clone) { + Ok(()) => println!("Text pasted successfully"), + Err(e) => eprintln!("Failed to paste transcription: {}", e), + } + }) + .unwrap_or_else(|e| { + eprintln!("Failed to run paste on main thread: {:?}", e); + }); } } Err(err) => println!("Global Shortcut Transcription error: {}", err), diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 17aa2cf..c312f07 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -1,51 +1,61 @@ -use rdev::{simulate, EventType, Key, SimulateError}; -use std::thread; -use std::time; +use enigo::Enigo; +use enigo::Key; +use enigo::Keyboard; +use enigo::Settings; + use tauri::image::Image; use tauri::tray::TrayIcon; use tauri::AppHandle; use tauri::Manager; use tauri_plugin_clipboard_manager::ClipboardExt; -fn try_send_event(event: &EventType) { - if let Err(SimulateError) = simulate(event) { - println!("We could not send {:?}", event); - } -} - -fn send_with_delay(event: EventType, delay_ms: u64) { - try_send_event(&event); - thread::sleep(time::Duration::from_millis(delay_ms)); -} - -// TODO: use enigo for paste not on macos? -fn send_paste() { +fn send_paste() -> Result<(), String> { // Determine the modifier key based on the OS #[cfg(target_os = "macos")] - let modifier_key = Key::MetaLeft; // Command key on macOS + let modifier_key = Key::Meta; // Command key on macOS #[cfg(not(target_os = "macos"))] - let modifier_key = Key::ControlLeft; // Control key on other systems + let modifier_key = Key::Control; // Control key on other systems + + let mut enigo = Enigo::new(&Settings::default()) + .map_err(|e| format!("Failed to initialize Enigo: {}", e))?; // Press both keys - send_with_delay(EventType::KeyPress(modifier_key), 100); - send_with_delay(EventType::KeyPress(Key::KeyV), 100); + enigo + .key(modifier_key, enigo::Direction::Press) + .map_err(|e| format!("Failed to press modifier key: {}", e))?; + enigo + .key(Key::Unicode('v'), enigo::Direction::Press) + .map_err(|e| format!("Failed to press V key: {}", e))?; // Release both keys - send_with_delay(EventType::KeyRelease(Key::KeyV), 100); - send_with_delay(EventType::KeyRelease(modifier_key), 0); + enigo + .key(Key::Unicode('v'), enigo::Direction::Release) + .map_err(|e| format!("Failed to release V key: {}", e))?; + enigo + .key(modifier_key, enigo::Direction::Release) + .map_err(|e| format!("Failed to release modifier key: {}", e))?; + + Ok(()) } -pub fn paste(text: String, app_handle: AppHandle) { +pub fn paste(text: String, app_handle: AppHandle) -> Result<(), String> { let clipboard = app_handle.clipboard(); // get the current clipboard content let clipboard_content = clipboard.read_text().unwrap_or_default(); - clipboard.write_text(&text).unwrap(); - send_paste(); + clipboard + .write_text(&text) + .map_err(|e| format!("Failed to write to clipboard: {}", e))?; + + send_paste()?; // restore the clipboard - clipboard.write_text(&clipboard_content).unwrap(); + clipboard + .write_text(&clipboard_content) + .map_err(|e| format!("Failed to restore clipboard: {}", e))?; + + Ok(()) } pub enum TrayIconState {