diff --git a/native/libmacbridge/bridge.h b/native/libmacbridge/bridge.h index 4a0f1d8..169c3cf 100644 --- a/native/libmacbridge/bridge.h +++ b/native/libmacbridge/bridge.h @@ -76,6 +76,11 @@ void send_multi_vkey(int32_t vk, int32_t count); */ void delete_string(int32_t count); +/* + * Check whether keyboard modifiers (CTRL, CMD, SHIFT, ecc) are pressed + */ +int32_t are_modifiers_pressed(); + /* * Trigger normal paste ( Pressing CMD+V ) */ diff --git a/native/libmacbridge/bridge.mm b/native/libmacbridge/bridge.mm index 1ddd549..bafe1ae 100644 --- a/native/libmacbridge/bridge.mm +++ b/native/libmacbridge/bridge.mm @@ -235,6 +235,14 @@ void trigger_copy() { }); } +int32_t are_modifiers_pressed() { + if ((NSEventModifierFlagControl | NSEventModifierFlagOption | + NSEventModifierFlagCommand | NSEventModifierFlagShift) & [NSEvent modifierFlags]) { + return 1; + } + return 0; +} + int32_t get_active_app_bundle(char * buffer, int32_t size) { NSRunningApplication *frontApp = [[NSWorkspace sharedWorkspace] frontmostApplication]; NSString *bundlePath = [frontApp bundleURL].path; diff --git a/src/bridge/macos.rs b/src/bridge/macos.rs index cb87675..c9f8c9f 100644 --- a/src/bridge/macos.rs +++ b/src/bridge/macos.rs @@ -63,4 +63,5 @@ extern "C" { pub fn delete_string(count: i32); pub fn trigger_paste(); pub fn trigger_copy(); + pub fn are_modifiers_pressed() -> i32; } diff --git a/src/extension/form.rs b/src/extension/form.rs index b5b8e83..6a2e2d2 100644 --- a/src/extension/form.rs +++ b/src/extension/form.rs @@ -20,7 +20,7 @@ use serde_yaml::{Mapping, Value}; use std::collections::HashMap; use crate::{ui::modulo::ModuloManager, extension::ExtensionResult, config::Configs}; -use log::error; +use log::{error, warn}; pub struct FormExtension { manager: ModuloManager, @@ -59,6 +59,10 @@ impl super::Extension for FormExtension { let serialized_config: String = serde_yaml::to_string(&form_config).expect("unable to serialize form config"); let output = self.manager.invoke(&["form", "-i", "-"], &serialized_config); + + // On macOS, after the form closes we have to wait until the user releases the modifier keys + on_form_close(); + if let Some(output) = output { let json: Result, _> = serde_json::from_str(&output); match json { @@ -76,3 +80,16 @@ impl super::Extension for FormExtension { } } } + +#[cfg(not(target_os = "macos"))] +fn on_form_close() { + // NOOP on Windows and Linux +} + +#[cfg(target_os = "macos")] +fn on_form_close() { + let released = crate::keyboard::macos::wait_for_modifiers_release(); + if !released { + warn!("Wait for modifiers release timed out! Please after closing the form, release your modifiers keys (CTRL, CMD, ALT, SHIFT)"); + } +} \ No newline at end of file diff --git a/src/keyboard/macos.rs b/src/keyboard/macos.rs index a5ea03e..284091a 100644 --- a/src/keyboard/macos.rs +++ b/src/keyboard/macos.rs @@ -20,7 +20,7 @@ use super::PasteShortcut; use crate::bridge::macos::*; use crate::config::Configs; -use log::error; +use log::{error}; use std::ffi::CString; pub struct MacKeyboardManager {} @@ -75,3 +75,15 @@ impl super::KeyboardManager for MacKeyboardManager { } } } + +pub fn wait_for_modifiers_release() -> bool { + let start = std::time::SystemTime::now(); + while start.elapsed().unwrap_or_default().as_millis() < 3000 { + let pressed = unsafe { crate::bridge::macos::are_modifiers_pressed() }; + if pressed == 0 { + return true + } + std::thread::sleep(std::time::Duration::from_millis(100)); + } + false +} \ No newline at end of file diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index add9499..dece480 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -27,7 +27,7 @@ mod windows; mod linux; #[cfg(target_os = "macos")] -mod macos; +pub mod macos; pub trait KeyboardManager { fn send_string(&self, active_config: &Configs, s: &str);