feat(detect): add option to lower the windows keyboard layout cache interval, #745
This commit is contained in:
parent
21bc75bc31
commit
92645e0987
|
@ -66,6 +66,12 @@ pub struct SourceCreationOptions {
|
||||||
// those from espanso, but might need to be disabled when using some software-level keyboards.
|
// those from espanso, but might need to be disabled when using some software-level keyboards.
|
||||||
// Disabling this option might conflict with the undo feature.
|
// Disabling this option might conflict with the undo feature.
|
||||||
pub win32_exclude_orphan_events: bool,
|
pub win32_exclude_orphan_events: bool,
|
||||||
|
|
||||||
|
// The maximum interval (in milliseconds) for which a keyboard layout
|
||||||
|
// can be cached. If switching often between different layouts, you
|
||||||
|
// could lower this amount to avoid the "lost detection" effect described
|
||||||
|
// in this issue: https://github.com/federico-terzi/espanso/issues/745
|
||||||
|
pub win32_keyboard_layout_cache_interval: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This struct identifies the keyboard layout that
|
// This struct identifies the keyboard layout that
|
||||||
|
@ -87,6 +93,7 @@ impl Default for SourceCreationOptions {
|
||||||
evdev_keyboard_rmlvo: None,
|
evdev_keyboard_rmlvo: None,
|
||||||
hotkeys: Vec::new(),
|
hotkeys: Vec::new(),
|
||||||
win32_exclude_orphan_events: true,
|
win32_exclude_orphan_events: true,
|
||||||
|
win32_keyboard_layout_cache_interval: 2000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,6 +104,7 @@ pub fn get_source(options: SourceCreationOptions) -> Result<Box<dyn Source>> {
|
||||||
Ok(Box::new(win32::Win32Source::new(
|
Ok(Box::new(win32::Win32Source::new(
|
||||||
&options.hotkeys,
|
&options.hotkeys,
|
||||||
options.win32_exclude_orphan_events,
|
options.win32_exclude_orphan_events,
|
||||||
|
options.win32_keyboard_layout_cache_interval,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use std::os::raw::c_long;
|
||||||
use std::{convert::TryInto, ffi::c_void};
|
use std::{convert::TryInto, ffi::c_void};
|
||||||
|
|
||||||
use lazycell::LazyCell;
|
use lazycell::LazyCell;
|
||||||
|
@ -79,10 +80,19 @@ pub struct RawHotKey {
|
||||||
pub flags: u32,
|
pub flags: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct InitOptions {
|
||||||
|
pub keyboard_layout_cache_interval: c_long,
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
#[link(name = "espansodetect", kind = "static")]
|
#[link(name = "espansodetect", kind = "static")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn detect_initialize(_self: *const Win32Source, error_code: *mut i32) -> *mut c_void;
|
pub fn detect_initialize(
|
||||||
|
_self: *const Win32Source,
|
||||||
|
options: *const InitOptions,
|
||||||
|
error_code: *mut i32,
|
||||||
|
) -> *mut c_void;
|
||||||
pub fn detect_register_hotkey(window: *const c_void, hotkey: RawHotKey) -> i32;
|
pub fn detect_register_hotkey(window: *const c_void, hotkey: RawHotKey) -> i32;
|
||||||
|
|
||||||
pub fn detect_eventloop(
|
pub fn detect_eventloop(
|
||||||
|
@ -99,24 +109,35 @@ pub struct Win32Source {
|
||||||
hotkeys: Vec<HotKey>,
|
hotkeys: Vec<HotKey>,
|
||||||
|
|
||||||
exclude_orphan_events: bool,
|
exclude_orphan_events: bool,
|
||||||
|
keyboard_layout_cache_interval: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::new_without_default)]
|
#[allow(clippy::new_without_default)]
|
||||||
impl Win32Source {
|
impl Win32Source {
|
||||||
pub fn new(hotkeys: &[HotKey], exclude_orphan_events: bool) -> Win32Source {
|
pub fn new(
|
||||||
|
hotkeys: &[HotKey],
|
||||||
|
exclude_orphan_events: bool,
|
||||||
|
keyboard_layout_cache_interval: i64,
|
||||||
|
) -> Win32Source {
|
||||||
Self {
|
Self {
|
||||||
handle: std::ptr::null_mut(),
|
handle: std::ptr::null_mut(),
|
||||||
callback: LazyCell::new(),
|
callback: LazyCell::new(),
|
||||||
hotkeys: hotkeys.to_vec(),
|
hotkeys: hotkeys.to_vec(),
|
||||||
exclude_orphan_events,
|
exclude_orphan_events,
|
||||||
|
keyboard_layout_cache_interval,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Source for Win32Source {
|
impl Source for Win32Source {
|
||||||
fn initialize(&mut self) -> Result<()> {
|
fn initialize(&mut self) -> Result<()> {
|
||||||
|
let options = InitOptions {
|
||||||
|
keyboard_layout_cache_interval: self.keyboard_layout_cache_interval.try_into().unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut error_code = 0;
|
let mut error_code = 0;
|
||||||
let handle = unsafe { detect_initialize(self as *const Win32Source, &mut error_code) };
|
let handle =
|
||||||
|
unsafe { detect_initialize(self as *const Win32Source, &options, &mut error_code) };
|
||||||
|
|
||||||
if handle.is_null() {
|
if handle.is_null() {
|
||||||
let error = match error_code {
|
let error = match error_code {
|
||||||
|
|
|
@ -39,8 +39,6 @@
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
// How many milliseconds must pass between events before refreshing the keyboard layout
|
|
||||||
const long DETECT_REFRESH_KEYBOARD_LAYOUT_INTERVAL = 2000;
|
|
||||||
const wchar_t *const DETECT_WINCLASS = L"EspansoDetect";
|
const wchar_t *const DETECT_WINCLASS = L"EspansoDetect";
|
||||||
const USHORT MOUSE_DOWN_FLAGS = RI_MOUSE_LEFT_BUTTON_DOWN | RI_MOUSE_RIGHT_BUTTON_DOWN | RI_MOUSE_MIDDLE_BUTTON_DOWN |
|
const USHORT MOUSE_DOWN_FLAGS = RI_MOUSE_LEFT_BUTTON_DOWN | RI_MOUSE_RIGHT_BUTTON_DOWN | RI_MOUSE_MIDDLE_BUTTON_DOWN |
|
||||||
RI_MOUSE_BUTTON_1_DOWN | RI_MOUSE_BUTTON_2_DOWN | RI_MOUSE_BUTTON_3_DOWN |
|
RI_MOUSE_BUTTON_1_DOWN | RI_MOUSE_BUTTON_2_DOWN | RI_MOUSE_BUTTON_3_DOWN |
|
||||||
|
@ -52,6 +50,8 @@ const USHORT MOUSE_UP_FLAGS = RI_MOUSE_LEFT_BUTTON_UP | RI_MOUSE_RIGHT_BUTTON_UP
|
||||||
typedef struct {
|
typedef struct {
|
||||||
HKL current_keyboard_layout;
|
HKL current_keyboard_layout;
|
||||||
DWORD last_key_press_tick;
|
DWORD last_key_press_tick;
|
||||||
|
// How many milliseconds must pass between events before refreshing the keyboard layout
|
||||||
|
long keyboard_layout_cache_interval;
|
||||||
|
|
||||||
// Rust interop
|
// Rust interop
|
||||||
void * rust_instance;
|
void * rust_instance;
|
||||||
|
@ -130,7 +130,7 @@ LRESULT CALLBACK detect_window_procedure(HWND window, unsigned int msg, WPARAM w
|
||||||
DWORD currentTick = GetTickCount();
|
DWORD currentTick = GetTickCount();
|
||||||
|
|
||||||
// If enough time has passed between the last keypress and now, refresh the keyboard layout
|
// If enough time has passed between the last keypress and now, refresh the keyboard layout
|
||||||
if ((currentTick - variables->last_key_press_tick) > DETECT_REFRESH_KEYBOARD_LAYOUT_INTERVAL)
|
if ((currentTick - variables->last_key_press_tick) > variables->keyboard_layout_cache_interval)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Because keyboard layouts on windows are Window-specific, to get the current
|
// Because keyboard layouts on windows are Window-specific, to get the current
|
||||||
|
@ -269,7 +269,7 @@ LRESULT CALLBACK detect_window_procedure(HWND window, unsigned int msg, WPARAM w
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void * detect_initialize(void *_self, int32_t *error_code)
|
void * detect_initialize(void *_self, InitOptions * options, int32_t *error_code)
|
||||||
{
|
{
|
||||||
HWND window = NULL;
|
HWND window = NULL;
|
||||||
|
|
||||||
|
@ -297,6 +297,7 @@ void * detect_initialize(void *_self, int32_t *error_code)
|
||||||
|
|
||||||
// Initialize the default keyboard layout
|
// Initialize the default keyboard layout
|
||||||
variables->current_keyboard_layout = GetKeyboardLayout(0);
|
variables->current_keyboard_layout = GetKeyboardLayout(0);
|
||||||
|
variables->keyboard_layout_cache_interval = options->keyboard_layout_cache_interval;
|
||||||
|
|
||||||
// Docs: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw
|
// Docs: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw
|
||||||
window = CreateWindowEx(
|
window = CreateWindowEx(
|
||||||
|
|
|
@ -76,9 +76,12 @@ typedef struct {
|
||||||
|
|
||||||
typedef void (*EventCallback)(void * rust_istance, InputEvent data);
|
typedef void (*EventCallback)(void * rust_istance, InputEvent data);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long keyboard_layout_cache_interval;
|
||||||
|
} InitOptions;
|
||||||
|
|
||||||
// Initialize the Raw Input API and the Window.
|
// Initialize the Raw Input API and the Window.
|
||||||
extern "C" void * detect_initialize(void * rust_istance, int32_t *error_code);
|
extern "C" void * detect_initialize(void * rust_istance, InitOptions * options, int32_t *error_code);
|
||||||
|
|
||||||
// Register the given hotkey, return a non-zero code if successful
|
// Register the given hotkey, return a non-zero code if successful
|
||||||
extern "C" int32_t detect_register_hotkey(void * window, HotKey hotkey);
|
extern "C" int32_t detect_register_hotkey(void * window, HotKey hotkey);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user