From c0cd826b45bd42c8f2afd590431f6e82f1e98327 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Fri, 30 Aug 2019 21:24:03 +0200 Subject: [PATCH] Add windows send keys --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + native/libwinbridge/bridge.cpp | 27 ++++++++++++++++++++++++--- native/libwinbridge/bridge.h | 7 ++++++- src/engine.rs | 0 src/keyboard/mod.rs | 10 +++++++--- src/keyboard/windows.rs | 22 ++++++++++++++++++---- src/main.rs | 21 +++++++++------------ src/matcher/mod.rs | 25 +++++++++++++++++++++++++ src/matcher/scrolling.rs | 0 10 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 src/engine.rs create mode 100644 src/matcher/mod.rs create mode 100644 src/matcher/scrolling.rs diff --git a/Cargo.lock b/Cargo.lock index e37f192..4743738 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,8 +16,15 @@ name = "espanso" version = "0.1.0" dependencies = [ "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "widestring" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] "checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" "checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" +"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" diff --git a/Cargo.toml b/Cargo.toml index 53e62c4..aab72fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" build="build.rs" [dependencies] +widestring = "0.4.0" [build-dependencies] cmake = "0.1.31" \ No newline at end of file diff --git a/native/libwinbridge/bridge.cpp b/native/libwinbridge/bridge.cpp index 9e8f644..a9b3069 100644 --- a/native/libwinbridge/bridge.cpp +++ b/native/libwinbridge/bridge.cpp @@ -18,11 +18,11 @@ HWND window; const wchar_t* const winclass = L"Espanso"; keypress_callback keypressCallback; -void * backend_instance; +void * interceptor_instance; void register_keypress_callback(void * self, keypress_callback callback) { keypressCallback = callback; - backend_instance = self; + interceptor_instance = self; } /* @@ -95,7 +95,7 @@ LRESULT CALLBACK window_worker_procedure(HWND window, unsigned int msg, WPARAM w // If a result is available, invoke the callback if (result >= 1) { //std::cout << buffer[0] << " " << buffer[1] << " res=" << result << " vk=" << raw->data.keyboard.VKey << " rsc=" << raw->data.keyboard.MakeCode << std::endl; - keypressCallback(backend_instance, reinterpret_cast(buffer.data()), buffer.size()); + keypressCallback(interceptor_instance, reinterpret_cast(buffer.data()), buffer.size()); } } } @@ -180,3 +180,24 @@ void eventloop() { // Something went wrong, this should have been an infinite loop. } +/* + * Type the given string simulating keyboard presses. + */ +void send_string(const wchar_t * string) { + std::wstring msg = string; + + std::vector vec; + for (auto ch : msg) + { + INPUT input = { 0 }; + input.type = INPUT_KEYBOARD; + input.ki.dwFlags = KEYEVENTF_UNICODE; + input.ki.wScan = ch; + vec.push_back(input); + + input.ki.dwFlags |= KEYEVENTF_KEYUP; + vec.push_back(input); + } + + SendInput(vec.size(), vec.data(), sizeof(INPUT)); +} \ No newline at end of file diff --git a/native/libwinbridge/bridge.h b/native/libwinbridge/bridge.h index 37975a5..dba6259 100644 --- a/native/libwinbridge/bridge.h +++ b/native/libwinbridge/bridge.h @@ -11,7 +11,7 @@ typedef void (*keypress_callback)(void * self, int32_t *buffer, int32_t len); extern keypress_callback keypressCallback; -extern void * backend_instance; +extern void * interceptor_instance; /* * Register the callback that will be called when a keypress was made @@ -29,4 +29,9 @@ extern "C" int32_t initialize_window(); */ extern "C" void eventloop(); +/* + * Type the given string by simulating Key Presses + */ +extern "C" void send_string(const wchar_t * string); + #endif //ESPANSO_BRIDGE_H diff --git a/src/engine.rs b/src/engine.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index cc925bf..0ecfd9f 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -3,12 +3,16 @@ mod windows; use std::sync::mpsc; -pub trait KeyboardBackend { +pub trait KeyboardInterceptor { fn initialize(&self); fn start(&self); } +pub trait KeyboardSender { + fn send_string(&self, s: &str); +} + #[cfg(target_os = "windows")] -pub fn get_backend(sender: mpsc::Sender) -> impl KeyboardBackend{ - windows::WindowsKeyboardBackend{sender } +pub fn get_backend(sender: mpsc::Sender) -> (impl KeyboardInterceptor, impl KeyboardSender) { + (windows::WindowsKeyboardInterceptor {sender}, windows::WindowsKeyboardSender{}) } \ No newline at end of file diff --git a/src/keyboard/windows.rs b/src/keyboard/windows.rs index 0c7ee65..5490324 100644 --- a/src/keyboard/windows.rs +++ b/src/keyboard/windows.rs @@ -1,12 +1,13 @@ use std::thread; use std::sync::mpsc; +use widestring::{WideString, WideStr}; #[repr(C)] -pub struct WindowsKeyboardBackend { +pub struct WindowsKeyboardInterceptor { pub sender: mpsc::Sender } -impl super::KeyboardBackend for WindowsKeyboardBackend { +impl super::KeyboardInterceptor for WindowsKeyboardInterceptor { fn initialize(&self) { unsafe { register_keypress_callback(self,keypress_callback); @@ -23,9 +24,21 @@ impl super::KeyboardBackend for WindowsKeyboardBackend { } } +pub struct WindowsKeyboardSender { +} + +impl super::KeyboardSender for WindowsKeyboardSender { + fn send_string(&self, s: &str) { + let s = WideString::from(s.to_owned()); + unsafe { + send_string(s.as_ptr()); + } + } +} + // Native bridge code -extern fn keypress_callback(_self: *mut WindowsKeyboardBackend, raw_buffer: *const i32, len: i32) { +extern fn keypress_callback(_self: *mut WindowsKeyboardInterceptor, raw_buffer: *const i32, len: i32) { unsafe { // Convert the received buffer to a character let buffer = std::slice::from_raw_parts(raw_buffer, len as usize); @@ -38,7 +51,8 @@ extern fn keypress_callback(_self: *mut WindowsKeyboardBackend, raw_buffer: *con #[link(name="winbridge", kind="static")] extern { - fn register_keypress_callback(s: *const WindowsKeyboardBackend, cb: extern fn(_self: *mut WindowsKeyboardBackend, *const i32, i32)); + fn register_keypress_callback(s: *const WindowsKeyboardInterceptor, cb: extern fn(_self: *mut WindowsKeyboardInterceptor, *const i32, i32)); fn initialize_window(); fn eventloop(); + fn send_string(string: *const u16); } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 71b97f5..59e8bff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,22 @@ use std::thread::sleep; use std::time::Duration; -use crate::keyboard::KeyboardBackend; use std::sync::mpsc; +use crate::keyboard::KeyboardInterceptor; +use crate::keyboard::KeyboardSender; +use crate::matcher::Matcher; mod keyboard; +mod matcher; fn main() { println!("Hello, world from Rust!"); let (sender, receiver) = mpsc::channel(); - let keyboard = keyboard::get_backend(sender); - keyboard.initialize(); - keyboard.start(); + let (interceptor, sender) = keyboard::get_backend(sender); + interceptor.initialize(); + interceptor.start(); - loop { - match receiver.recv() { - Ok(c) => { - println!("Yeah {}",c); - }, - Err(_) => panic!("Worker threads disconnected before the solution was found!"), - } - } + let matcher = Matcher{receiver}; + matcher.watch(); } \ No newline at end of file diff --git a/src/matcher/mod.rs b/src/matcher/mod.rs new file mode 100644 index 0000000..9aa9235 --- /dev/null +++ b/src/matcher/mod.rs @@ -0,0 +1,25 @@ +use std::sync::mpsc::Receiver; + +pub struct Match { + pub trigger: String, + pub result: String +} + + + +pub struct Matcher { + pub receiver: Receiver +} + +impl Matcher { + pub fn watch(&self) { + loop { + match self.receiver.recv() { + Ok(c) => { + println!("Yeah {}",c); + }, + Err(_) => panic!("Worker threads disconnected before the solution was found!"), + } + } + } +} \ No newline at end of file diff --git a/src/matcher/scrolling.rs b/src/matcher/scrolling.rs new file mode 100644 index 0000000..e69de29