Implement filter bindings for Windows and moved extern in bridge. Fix #13

This commit is contained in:
Federico Terzi 2019-09-07 22:23:04 +02:00
parent d04bd9d7f6
commit cd2c159696
12 changed files with 206 additions and 16 deletions

View File

@ -247,4 +247,29 @@ void send_vkey(int32_t vk) {
vec.push_back(input);
SendInput(vec.size(), vec.data(), sizeof(INPUT));
}
// SYSTEM
int32_t get_active_window_name(wchar_t * buffer, int32_t size) {
HWND hwnd = GetForegroundWindow();
return GetWindowText(hwnd, buffer, size);
}
int32_t get_active_window_executable(wchar_t * buffer, int32_t size) {
HWND hwnd = GetForegroundWindow();
// Extract the window PID
DWORD windowPid;
GetWindowThreadProcessId(hwnd, &windowPid);
DWORD dsize = (DWORD) size;
// Extract the process executable file path
HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, windowPid);
int res = QueryFullProcessImageNameW(process, 0, buffer, &dsize);
CloseHandle(process);
return res;
}

View File

@ -44,4 +44,14 @@ extern "C" void send_vkey(int32_t vk);
*/
extern "C" void delete_string(int32_t count);
/*
* Return the active windows's title
*/
extern "C" int32_t get_active_window_name(wchar_t * buffer, int32_t size);
/*
* Return the active windows's executable path
*/
extern "C" int32_t get_active_window_executable(wchar_t * buffer, int32_t size);
#endif //ESPANSO_BRIDGE_H

17
src/bridge/windows.rs Normal file
View File

@ -0,0 +1,17 @@
use std::os::raw::{c_void};
#[allow(improper_ctypes)]
#[link(name="winbridge", kind="static")]
extern {
pub fn get_active_window_name(buffer: *mut u16, size: i32) -> i32;
pub fn get_active_window_executable(buffer: *mut u16, size: i32) -> i32;
pub fn register_keypress_callback(s: *const c_void,
cb: extern fn(_self: *mut c_void, *const i32,
i32, i32, i32));
pub fn initialize_window();
pub fn eventloop();
pub fn send_string(string: *const u16);
pub fn send_vkey(vk: i32);
pub fn delete_string(count: i32);
}

View File

@ -19,4 +19,12 @@ pub fn get_manager() -> impl ClipboardManager {
let manager = linux::LinuxClipboardManager{};
manager.initialize();
manager
}
// WINDOWS IMPLEMENTATION
#[cfg(target_os = "windows")]
pub fn get_manager() -> impl ClipboardManager {
let manager = windows::WindowsClipboardManager{};
manager.initialize();
manager
}

24
src/clipboard/windows.rs Normal file
View File

@ -0,0 +1,24 @@
use std::process::{Command, Stdio};
use std::io::{Write};
pub struct WindowsClipboardManager {
}
impl super::ClipboardManager for WindowsClipboardManager {
fn initialize(&self) {
// TODO: check if xclip is present and log an error otherwise.
}
fn get_clipboard(&self) -> Option<String> {
unimplemented!();
}
fn set_clipboard(&self, payload: &str) {
unimplemented!();
}
}
impl WindowsClipboardManager {
}

View File

@ -203,9 +203,13 @@ impl <S: SystemManager> ConfigManager for RuntimeConfigManager<S> {
fn active_config(&self) -> &Configs {
// TODO: optimize performance by avoiding some of these checks if no Configs use the filters
debug!("Requested config for window:");
let active_title = self.system_manager.get_current_window_title();
if let Some(title) = active_title {
debug!("=> Title: '{}'", title);
for (i, regex) in self.title_regexps.iter().enumerate() {
if let Some(regex) = regex {
if regex.is_match(&title) {
@ -218,6 +222,24 @@ impl <S: SystemManager> ConfigManager for RuntimeConfigManager<S> {
}
}
let active_executable = self.system_manager.get_current_window_executable();
if let Some(executable) = active_executable {
debug!("=> Executable: '{}'", executable);
// TODO
/*for (i, regex) in self.title_regexps.iter().enumerate() {
if let Some(regex) = regex {
if regex.is_match(&title) {
debug!("Matched 'filter_title' for '{}' config, using custom settings.",
self.set.specific[i].name);
return &self.set.specific[i]
}
}
}*/
}
// No matches, return the default mapping
debug!("No matches for custom configs, using default settings.");
&self.set.default

View File

@ -3,7 +3,6 @@ use std::os::raw::{c_void};
use std::ffi::CString;
use crate::keyboard::{KeyEvent, KeyModifier};
use crate::keyboard::KeyModifier::*;
use crate::bridge::linux::*;
#[repr(C)]

View File

@ -1,7 +1,9 @@
use std::sync::mpsc;
use std::os::raw::{c_void};
use widestring::{U16CString};
use crate::keyboard::{KeyEvent, KeyModifier};
use crate::keyboard::KeyModifier::*;
use crate::bridge::windows::*;
#[repr(C)]
pub struct WindowsKeyboardInterceptor {
@ -11,7 +13,8 @@ pub struct WindowsKeyboardInterceptor {
impl super::KeyboardInterceptor for WindowsKeyboardInterceptor {
fn initialize(&self) {
unsafe {
register_keypress_callback(self,keypress_callback);
let self_ptr = self as *const WindowsKeyboardInterceptor as *const c_void;
register_keypress_callback(self_ptr,keypress_callback);
initialize_window();
}
}
@ -47,6 +50,10 @@ impl super::KeyboardSender for WindowsKeyboardSender {
}
}
fn trigger_paste(&self) {
unimplemented!()
}
fn delete_string(&self, count: i32) {
unsafe {
delete_string(count)
@ -56,9 +63,11 @@ impl super::KeyboardSender for WindowsKeyboardSender {
// Native bridge code
extern fn keypress_callback(_self: *mut WindowsKeyboardInterceptor, raw_buffer: *const i32, len: i32,
extern fn keypress_callback(_self: *mut c_void, raw_buffer: *const i32, len: i32,
is_modifier: i32, key_code: i32) {
unsafe {
let _self = _self as *mut WindowsKeyboardInterceptor;
if is_modifier == 0 { // Char event
// Convert the received buffer to a character
let buffer = std::slice::from_raw_parts(raw_buffer, len as usize);
@ -83,17 +92,4 @@ extern fn keypress_callback(_self: *mut WindowsKeyboardInterceptor, raw_buffer:
}
}
}
}
#[allow(improper_ctypes)]
#[link(name="winbridge", kind="static")]
extern {
fn register_keypress_callback(s: *const WindowsKeyboardInterceptor,
cb: extern fn(_self: *mut WindowsKeyboardInterceptor, *const i32,
i32, i32, i32));
fn initialize_window();
fn eventloop();
fn send_string(string: *const u16);
fn send_vkey(vk: i32);
fn delete_string(count: i32);
}

View File

@ -20,4 +20,12 @@ pub fn get_manager() -> impl SystemManager {
let manager = linux::LinuxSystemManager{};
manager.initialize();
manager
}
// WINDOWS IMPLEMENTATION
#[cfg(target_os = "windows")]
pub fn get_manager() -> impl SystemManager {
let manager = windows::WindowsSystemManager{};
manager.initialize();
manager
}

54
src/system/windows.rs Normal file
View File

@ -0,0 +1,54 @@
use widestring::U16CString;
use crate::bridge::windows::*;
pub struct WindowsSystemManager {
}
impl super::SystemManager for WindowsSystemManager {
fn initialize(&self) {
}
fn get_current_window_title(&self) -> Option<String> {
unsafe {
let mut buffer : [u16; 100] = [0; 100];
let res = get_active_window_name(buffer.as_mut_ptr(), buffer.len() as i32);
if res > 0 {
let c_string = U16CString::from_ptr_str(buffer.as_ptr());
let string = c_string.to_string_lossy();
return Some((*string).to_owned());
}
}
None
}
fn get_current_window_class(&self) -> Option<String> {
self.get_current_window_executable()
}
fn get_current_window_executable(&self) -> Option<String> {
unsafe {
let mut buffer : [u16; 250] = [0; 250];
let res = get_active_window_executable(buffer.as_mut_ptr(), buffer.len() as i32);
if res > 0 {
let c_string = U16CString::from_ptr_str(buffer.as_ptr());
let string = c_string.to_string_lossy();
return Some((*string).to_owned());
}
}
None
}
}
unsafe impl Send for WindowsSystemManager {}
impl WindowsSystemManager {
}

View File

@ -26,4 +26,12 @@ pub fn get_uimanager() -> impl UIManager {
let manager = linux::LinuxUIManager{};
manager.initialize();
manager
}
// WINDOWS IMPLEMENTATION
#[cfg(target_os = "windows")]
pub fn get_uimanager() -> impl UIManager {
let manager = windows::WindowsUIManager{};
manager.initialize();
manager
}

19
src/ui/windows.rs Normal file
View File

@ -0,0 +1,19 @@
use std::process::Command;
pub struct WindowsUIManager {
}
impl super::UIManager for WindowsUIManager {
fn initialize(&self) {
// TODO: check if notify-send is present and log an error otherwise.
}
fn notify(&self, message: &str) {
}
}
impl WindowsUIManager {
}