From c05652618f2240fd856f7a337fd1f3053a4c3865 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Fri, 30 Aug 2019 19:45:27 +0200 Subject: [PATCH] First windows sender channel implementation --- Cargo.lock | 23 ------------------ Cargo.toml | 3 --- native/libwinbridge/bridge.cpp | 8 ++++--- native/libwinbridge/bridge.h | 7 +++--- src/keyboard/mod.rs | 14 +++++++++++ src/keyboard/windows.rs | 44 ++++++++++++++++++++++++++++++++++ src/main.rs | 35 +++++++++++++-------------- 7 files changed, 84 insertions(+), 50 deletions(-) create mode 100644 src/keyboard/mod.rs create mode 100644 src/keyboard/windows.rs diff --git a/Cargo.lock b/Cargo.lock index 4ce39df..e37f192 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,31 +16,8 @@ name = "espanso" version = "0.1.0" dependencies = [ "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -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 winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 85a9141..53e62c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,9 +5,6 @@ authors = ["Federico Terzi "] edition = "2018" build="build.rs" -[target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["winuser"] } - [dependencies] [build-dependencies] diff --git a/native/libwinbridge/bridge.cpp b/native/libwinbridge/bridge.cpp index 6443040..9e8f644 100644 --- a/native/libwinbridge/bridge.cpp +++ b/native/libwinbridge/bridge.cpp @@ -18,9 +18,11 @@ HWND window; const wchar_t* const winclass = L"Espanso"; keypress_callback keypressCallback; +void * backend_instance; -void register_keypress_callback(keypress_callback callback) { +void register_keypress_callback(void * self, keypress_callback callback) { keypressCallback = callback; + backend_instance = self; } /* @@ -93,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(reinterpret_cast(buffer.data()), buffer.size()); + keypressCallback(backend_instance, reinterpret_cast(buffer.data()), buffer.size()); } } } @@ -105,7 +107,7 @@ LRESULT CALLBACK window_worker_procedure(HWND window, unsigned int msg, WPARAM w } } -int32_t initialize() { +int32_t initialize_window() { // Initialize the default keyboard layout currentKeyboardLayout = GetKeyboardLayout(0); diff --git a/native/libwinbridge/bridge.h b/native/libwinbridge/bridge.h index 48f5c73..37975a5 100644 --- a/native/libwinbridge/bridge.h +++ b/native/libwinbridge/bridge.h @@ -8,20 +8,21 @@ * Called when a new keypress is made, the first argument is an int array, * while the second is the size of the array. */ -typedef void (*keypress_callback)(int32_t *buffer, int32_t len); +typedef void (*keypress_callback)(void * self, int32_t *buffer, int32_t len); extern keypress_callback keypressCallback; +extern void * backend_instance; /* * Register the callback that will be called when a keypress was made */ -extern "C" void register_keypress_callback(keypress_callback callback); +extern "C" void register_keypress_callback(void *self, keypress_callback callback); /* * Initialize the Windows worker's parameters * return: 1 if OK, -1 otherwise. */ -extern "C" int32_t initialize(); +extern "C" int32_t initialize_window(); /* * Start the event loop indefinitely. Blocking call. diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs new file mode 100644 index 0000000..cc925bf --- /dev/null +++ b/src/keyboard/mod.rs @@ -0,0 +1,14 @@ +#[cfg(target_os = "windows")] +mod windows; + +use std::sync::mpsc; + +pub trait KeyboardBackend { + fn initialize(&self); + fn start(&self); +} + +#[cfg(target_os = "windows")] +pub fn get_backend(sender: mpsc::Sender) -> impl KeyboardBackend{ + windows::WindowsKeyboardBackend{sender } +} \ No newline at end of file diff --git a/src/keyboard/windows.rs b/src/keyboard/windows.rs new file mode 100644 index 0000000..0c7ee65 --- /dev/null +++ b/src/keyboard/windows.rs @@ -0,0 +1,44 @@ +use std::thread; +use std::sync::mpsc; + +#[repr(C)] +pub struct WindowsKeyboardBackend { + pub sender: mpsc::Sender +} + +impl super::KeyboardBackend for WindowsKeyboardBackend { + fn initialize(&self) { + unsafe { + register_keypress_callback(self,keypress_callback); + } + } + + fn start(&self) { + thread::spawn(|| { + unsafe { + initialize_window(); + eventloop(); + } + }); + } +} + +// Native bridge code + +extern fn keypress_callback(_self: *mut WindowsKeyboardBackend, 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); + let r = std::char::from_u32(buffer[0] as u32).unwrap(); + + // Send the char through the channel + (*_self).sender.send(r).unwrap(); + } +} + +#[link(name="winbridge", kind="static")] +extern { + fn register_keypress_callback(s: *const WindowsKeyboardBackend, cb: extern fn(_self: *mut WindowsKeyboardBackend, *const i32, i32)); + fn initialize_window(); + fn eventloop(); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 07884dc..71b97f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,25 @@ -extern fn keypress_callback(raw_buffer: *const i32, len: i32) { - unsafe { - let buffer = std::slice::from_raw_parts(raw_buffer, len as usize); - println!("{}", std::char::from_u32(buffer[0] as u32).unwrap()); - } -} +use std::thread::sleep; +use std::time::Duration; +use crate::keyboard::KeyboardBackend; +use std::sync::mpsc; -#[link(name="winbridge", kind="static")] -extern { - fn initialize(); - fn eventloop(); - fn register_keypress_callback(cb: extern fn(*const i32, i32)); -} +mod keyboard; fn main() { println!("Hello, world from Rust!"); - // calling the function from foo library - unsafe { - initialize(); + let (sender, receiver) = mpsc::channel(); - register_keypress_callback(keypress_callback); + let keyboard = keyboard::get_backend(sender); + keyboard.initialize(); + keyboard.start(); - eventloop(); - }; + loop { + match receiver.recv() { + Ok(c) => { + println!("Yeah {}",c); + }, + Err(_) => panic!("Worker threads disconnected before the solution was found!"), + } + } } \ No newline at end of file