diff --git a/src/check.rs b/src/check.rs index 146b170..daed087 100644 --- a/src/check.rs +++ b/src/check.rs @@ -17,11 +17,11 @@ * along with espanso. If not, see . */ -// This functions are used to check if the required dependencies are satisfied +// This functions are used to check if the required dependencies and conditions are satisfied // before starting espanso #[cfg(target_os = "linux")] -pub fn check_dependencies() -> bool { +pub fn check_preconditions() -> bool { use std::process::Command; let mut result = true; @@ -48,13 +48,26 @@ pub fn check_dependencies() -> bool { } #[cfg(target_os = "macos")] -pub fn check_dependencies() -> bool { - // Nothing to do here +pub fn check_preconditions() -> bool { + // Make sure no app is currently using secure input. + let secure_input_app = crate::system::macos::MacSystemManager::get_secure_input_application(); + + if let Some((app_name, process)) = secure_input_app { + eprintln!("WARNING: An application is currently using SecureInput and might prevent espanso from working correctly."); + eprintln!(); + eprintln!("APP: {}", app_name); + eprintln!("PROC: {}", process); + eprintln!(); + eprintln!("Please close it or disable SecureInput for that application (most apps that use it have a"); + eprintln!("setting to disable it)."); + eprintln!("Until then, espanso might not work as expected."); + } + true } #[cfg(target_os = "windows")] -pub fn check_dependencies() -> bool { +pub fn check_preconditions() -> bool { // Nothing needed on windows true } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index cc59337..ebc371d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1037,9 +1037,9 @@ fn release_lock(lock_file: File) { lock_file.unlock().unwrap() } -/// Used to make sure all the required dependencies are present before starting espanso. +/// Used to make sure all the required dependencies and conditions are satisfied before starting espanso. fn precheck_guard() { - let satisfied = check::check_dependencies(); + let satisfied = check::check_preconditions(); if !satisfied { println!(); println!("Pre-check was not successful, espanso could not be started."); diff --git a/src/system/macos.rs b/src/system/macos.rs index fc867d1..8a04e77 100644 --- a/src/system/macos.rs +++ b/src/system/macos.rs @@ -74,4 +74,71 @@ impl MacSystemManager { } } + + /// Check whether an application is currently holding the Secure Input. + /// Return None if no application has claimed SecureInput, Some((AppName, AppPath)) otherwise. + pub fn get_secure_input_application() -> Option<(String, String)> { + use std::process::Command; + use regex::Regex; + + let output = Command::new("ioreg") + .arg("-d") + .arg("1") + .arg("-k") + .arg("IOConsoleUsers") + .arg("-w") + .arg("0") + .output(); + + lazy_static! { + static ref PID_REGEX: Regex = Regex::new("\"kCGSSessionSecureInputPID\"=(\\d+)").unwrap(); + }; + + lazy_static! { + static ref APP_REGEX: Regex = Regex::new("/([^/]+).app/").unwrap(); + }; + + if let Ok(output) = output { + let output_str = String::from_utf8_lossy(output.stdout.as_slice()); + let caps = PID_REGEX.captures(&output_str); + + if let Some(caps) = caps { + // Get the PID of the process that is handling SecureInput + let pid_str = caps.get(1).map_or("", |m| m.as_str()); + let pid = pid_str.parse::().expect("Invalid pid value"); + + // Find the process that is handling the SecureInput + let output = Command::new("ps") + .arg("-p") + .arg(pid.to_string()) + .arg("-o") + .arg("command=") + .output(); + + if let Ok(output) = output { + let output_str = String::from_utf8_lossy(output.stdout.as_slice()); + + if !output_str.trim().is_empty() { + let process = output_str.trim().to_string(); + let caps = APP_REGEX.captures(&process); + let app_name = if let Some(caps) = caps { + caps.get(1).map_or("", |m| m.as_str()).to_owned() + }else{ + process.to_owned() + }; + + Some((app_name, process)) + }else{ + None + } + }else{ // Can't obtain process name + None + } + }else{ // No process is holding SecureInput + None + } + }else{ // Can't execute the query to the IOKit registry + None + } + } } \ No newline at end of file diff --git a/src/system/mod.rs b/src/system/mod.rs index fadcf5a..a0bd25a 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -24,7 +24,7 @@ mod windows; mod linux; #[cfg(target_os = "macos")] -mod macos; +pub mod macos; pub trait SystemManager { fn get_current_window_title(&self) -> Option;