130 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| /*
 | |
|  * This file is part of espanso.
 | |
|  *
 | |
|  * Copyright (C) 2019-2021 Federico Terzi
 | |
|  *
 | |
|  * espanso is free software: you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License as published by
 | |
|  * the Free Software Foundation, either version 3 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * espanso is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
 | |
|  */
 | |
| 
 | |
| mod raw_keys;
 | |
| 
 | |
| use log::error;
 | |
| use raw_keys::convert_key_to_vkey;
 | |
| 
 | |
| use anyhow::Result;
 | |
| use thiserror::Error;
 | |
| 
 | |
| use crate::{keys, InjectionOptions, Injector};
 | |
| 
 | |
| #[allow(improper_ctypes)]
 | |
| #[link(name = "espansoinject", kind = "static")]
 | |
| extern "C" {
 | |
|   pub fn inject_string(string: *const u16);
 | |
|   pub fn inject_separate_vkeys(vkey_array: *const i32, vkey_count: i32);
 | |
|   pub fn inject_vkeys_combination(vkey_array: *const i32, vkey_count: i32);
 | |
|   pub fn inject_separate_vkeys_with_delay(vkey_array: *const i32, vkey_count: i32, delay: i32);
 | |
|   pub fn inject_vkeys_combination_with_delay(vkey_array: *const i32, vkey_count: i32, delay: i32);
 | |
| }
 | |
| 
 | |
| pub struct Win32Injector {}
 | |
| 
 | |
| #[allow(clippy::new_without_default)]
 | |
| impl Win32Injector {
 | |
|   pub fn new() -> Self {
 | |
|     Self {}
 | |
|   }
 | |
| 
 | |
|   pub fn convert_to_vk_array(keys: &[keys::Key]) -> Result<Vec<i32>> {
 | |
|     let mut virtual_keys: Vec<i32> = Vec::new();
 | |
|     for key in keys.iter() {
 | |
|       let vk = convert_key_to_vkey(key);
 | |
|       if let Some(vk) = vk {
 | |
|         virtual_keys.push(vk)
 | |
|       } else {
 | |
|         return Err(Win32InjectorError::MappingFailure(key.clone()).into());
 | |
|       }
 | |
|     }
 | |
|     Ok(virtual_keys)
 | |
|   }
 | |
| }
 | |
| 
 | |
| impl Injector for Win32Injector {
 | |
|   fn send_string(&self, string: &str, _: InjectionOptions) -> Result<()> {
 | |
|     let wide_string = widestring::WideCString::from_str(string)?;
 | |
|     unsafe {
 | |
|       inject_string(wide_string.as_ptr());
 | |
|     }
 | |
|     Ok(())
 | |
|   }
 | |
| 
 | |
|   fn send_keys(&self, keys: &[keys::Key], options: InjectionOptions) -> Result<()> {
 | |
|     let virtual_keys = Self::convert_to_vk_array(keys)?;
 | |
| 
 | |
|     if options.delay == 0 {
 | |
|       unsafe {
 | |
|         inject_separate_vkeys(virtual_keys.as_ptr(), virtual_keys.len() as i32);
 | |
|       }
 | |
|     } else {
 | |
|       unsafe {
 | |
|         inject_separate_vkeys_with_delay(
 | |
|           virtual_keys.as_ptr(),
 | |
|           virtual_keys.len() as i32,
 | |
|           options.delay,
 | |
|         );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Ok(())
 | |
|   }
 | |
| 
 | |
|   fn send_key_combination(&self, keys: &[keys::Key], options: InjectionOptions) -> Result<()> {
 | |
|     let virtual_keys = Self::convert_to_vk_array(keys)?;
 | |
| 
 | |
|     if options.delay == 0 {
 | |
|       unsafe {
 | |
|         inject_vkeys_combination(virtual_keys.as_ptr(), virtual_keys.len() as i32);
 | |
|       }
 | |
|     } else {
 | |
|       unsafe {
 | |
|         inject_vkeys_combination_with_delay(
 | |
|           virtual_keys.as_ptr(),
 | |
|           virtual_keys.len() as i32,
 | |
|           options.delay,
 | |
|         );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Ok(())
 | |
|   }
 | |
| }
 | |
| 
 | |
| #[derive(Error, Debug)]
 | |
| pub enum Win32InjectorError {
 | |
|   #[error("missing vkey mapping for key `{0}`")]
 | |
|   MappingFailure(keys::Key),
 | |
| }
 | |
| 
 | |
| #[cfg(test)]
 | |
| mod tests {
 | |
|   use super::*;
 | |
| 
 | |
|   #[test]
 | |
|   fn convert_raw_to_virtual_key_array() {
 | |
|     assert_eq!(
 | |
|       Win32Injector::convert_to_vk_array(&[keys::Key::Alt, keys::Key::V]).unwrap(),
 | |
|       vec![0x12, 0x56]
 | |
|     );
 | |
|   }
 | |
| }
 |