Improve macOS form handling

This commit is contained in:
Federico Terzi 2020-08-12 22:04:02 +02:00
parent f17898bfd7
commit 97d11fd34e
6 changed files with 46 additions and 3 deletions

View File

@ -76,6 +76,11 @@ void send_multi_vkey(int32_t vk, int32_t count);
*/ */
void delete_string(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 ) * Trigger normal paste ( Pressing CMD+V )
*/ */

View File

@ -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) { int32_t get_active_app_bundle(char * buffer, int32_t size) {
NSRunningApplication *frontApp = [[NSWorkspace sharedWorkspace] frontmostApplication]; NSRunningApplication *frontApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
NSString *bundlePath = [frontApp bundleURL].path; NSString *bundlePath = [frontApp bundleURL].path;

View File

@ -63,4 +63,5 @@ extern "C" {
pub fn delete_string(count: i32); pub fn delete_string(count: i32);
pub fn trigger_paste(); pub fn trigger_paste();
pub fn trigger_copy(); pub fn trigger_copy();
pub fn are_modifiers_pressed() -> i32;
} }

View File

@ -20,7 +20,7 @@
use serde_yaml::{Mapping, Value}; use serde_yaml::{Mapping, Value};
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ui::modulo::ModuloManager, extension::ExtensionResult, config::Configs}; use crate::{ui::modulo::ModuloManager, extension::ExtensionResult, config::Configs};
use log::error; use log::{error, warn};
pub struct FormExtension { pub struct FormExtension {
manager: ModuloManager, 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 serialized_config: String = serde_yaml::to_string(&form_config).expect("unable to serialize form config");
let output = self.manager.invoke(&["form", "-i", "-"], &serialized_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 { if let Some(output) = output {
let json: Result<HashMap<String, String>, _> = serde_json::from_str(&output); let json: Result<HashMap<String, String>, _> = serde_json::from_str(&output);
match json { 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)");
}
}

View File

@ -20,7 +20,7 @@
use super::PasteShortcut; use super::PasteShortcut;
use crate::bridge::macos::*; use crate::bridge::macos::*;
use crate::config::Configs; use crate::config::Configs;
use log::error; use log::{error};
use std::ffi::CString; use std::ffi::CString;
pub struct MacKeyboardManager {} 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
}

View File

@ -27,7 +27,7 @@ mod windows;
mod linux; mod linux;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
mod macos; pub mod macos;
pub trait KeyboardManager { pub trait KeyboardManager {
fn send_string(&self, active_config: &Configs, s: &str); fn send_string(&self, active_config: &Configs, s: &str);