From 15d78dc13f6e35e52ed247a208e4aa26d387dfac Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Sat, 20 Mar 2021 22:04:47 +0100 Subject: [PATCH] feat(info): implement app info provider on Windows --- espanso-info/build.rs | 4 +- espanso-info/src/lib.rs | 6 +-- espanso-info/src/win32/ffi.rs | 24 ++++++++++ espanso-info/src/win32/mod.rs | 76 +++++++++++++++++++++++++++++++ espanso-info/src/win32/native.cpp | 65 ++++++++++++++++++++++++++ espanso-info/src/win32/native.h | 28 ++++++++++++ 6 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 espanso-info/src/win32/ffi.rs create mode 100644 espanso-info/src/win32/mod.rs create mode 100644 espanso-info/src/win32/native.cpp create mode 100644 espanso-info/src/win32/native.h diff --git a/espanso-info/build.rs b/espanso-info/build.rs index 28a331e..c67b678 100644 --- a/espanso-info/build.rs +++ b/espanso-info/build.rs @@ -25,9 +25,9 @@ fn cc_config() { .cpp(true) .include("src/win32/native.h") .file("src/win32/native.cpp") - .compile("espansoclipboard"); + .compile("espansoinfo"); - println!("cargo:rustc-link-lib=static=espansoclipboard"); + println!("cargo:rustc-link-lib=static=espansoinfo"); println!("cargo:rustc-link-lib=dylib=user32"); #[cfg(target_env = "gnu")] println!("cargo:rustc-link-lib=dylib=stdc++"); diff --git a/espanso-info/src/lib.rs b/espanso-info/src/lib.rs index 4f94cac..c65643f 100644 --- a/espanso-info/src/lib.rs +++ b/espanso-info/src/lib.rs @@ -46,9 +46,9 @@ pub struct AppInfo { } #[cfg(target_os = "windows")] -pub fn get_clipboard(_: ClipboardOptions) -> Result> { - info!("using Win32Clipboard"); - Ok(Box::new(win32::Win32Clipboard::new()?)) +pub fn get_provider() -> Result> { + info!("using Win32AppInfoProvider"); + Ok(Box::new(win32::WinAppInfoProvider::new())) } #[cfg(target_os = "macos")] diff --git a/espanso-info/src/win32/ffi.rs b/espanso-info/src/win32/ffi.rs new file mode 100644 index 0000000..9d8b964 --- /dev/null +++ b/espanso-info/src/win32/ffi.rs @@ -0,0 +1,24 @@ +/* + * 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 . + */ + +#[link(name = "espansoinfo", kind = "static")] +extern "C" { + pub fn info_get_title(buffer: *mut u16, buffer_size: i32) -> i32; + pub fn info_get_exec(buffer: *mut u16, buffer_size: i32) -> i32; +} diff --git a/espanso-info/src/win32/mod.rs b/espanso-info/src/win32/mod.rs new file mode 100644 index 0000000..cb40ece --- /dev/null +++ b/espanso-info/src/win32/mod.rs @@ -0,0 +1,76 @@ +/* + * 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 . + */ + +use widestring::U16CStr; + +use crate::{AppInfo, AppInfoProvider}; + +use self::ffi::{info_get_exec, info_get_title}; + +mod ffi; + +pub struct WinAppInfoProvider {} + +impl WinAppInfoProvider { + pub fn new() -> Self { + Self {} + } +} + +impl AppInfoProvider for WinAppInfoProvider { + fn get_info(&self) -> AppInfo { + AppInfo { + title: self.get_title(), + class: None, + exec: self.get_exec(), + } + } +} + +impl WinAppInfoProvider { + fn get_exec(&self) -> Option { + let mut buffer: [u16; 2048] = [0; 2048]; + if unsafe { info_get_exec(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } != 0 { + let string = unsafe { U16CStr::from_ptr_str(buffer.as_ptr()) }; + let string = string.to_string_lossy(); + if !string.is_empty() { + Some(string) + } else { + None + } + } else { + None + } + } + + fn get_title(&self) -> Option { + let mut buffer: [u16; 2048] = [0; 2048]; + if unsafe { info_get_title(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 { + let string = unsafe { U16CStr::from_ptr_str(buffer.as_ptr()) }; + let string = string.to_string_lossy(); + if !string.is_empty() { + Some(string) + } else { + None + } + } else { + None + } + } +} diff --git a/espanso-info/src/win32/native.cpp b/espanso-info/src/win32/native.cpp new file mode 100644 index 0000000..ef00d63 --- /dev/null +++ b/espanso-info/src/win32/native.cpp @@ -0,0 +1,65 @@ +/* + * 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 . + */ + +#include "native.h" +#include +#include +#include +#include +#include +#include + +#define UNICODE + +#ifdef __MINGW32__ +#ifndef WINVER +#define WINVER 0x0606 +#endif +#define STRSAFE_NO_DEPRECATE +#endif + +#include +#include +#include + +#include + +int32_t info_get_title(wchar_t *buffer, int32_t buffer_size) +{ + HWND hwnd = GetForegroundWindow(); + return GetWindowText(hwnd, buffer, buffer_size); +} + +int32_t info_get_exec(wchar_t *buffer, int32_t buffer_size) +{ + HWND hwnd = GetForegroundWindow(); + + // Extract the window PID + DWORD windowPid; + GetWindowThreadProcessId(hwnd, &windowPid); + + DWORD dsize = (DWORD)buffer_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; +} \ No newline at end of file diff --git a/espanso-info/src/win32/native.h b/espanso-info/src/win32/native.h new file mode 100644 index 0000000..6f6dd02 --- /dev/null +++ b/espanso-info/src/win32/native.h @@ -0,0 +1,28 @@ +/* + * 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 . + */ + +#ifndef ESPANSO_INFO_H +#define ESPANSO_INFO_H + +#include + +extern "C" int32_t info_get_title(wchar_t * buffer, int32_t buffer_size); +extern "C" int32_t info_get_exec(wchar_t * buffer, int32_t buffer_size); + +#endif //ESPANSO_INFO_H \ No newline at end of file