Fix bug on Windows that prevented ALT key from being registered correctly

This commit is contained in:
Federico Terzi 2019-09-18 10:28:34 +02:00
parent b8d9cf77c1
commit 78451d122a
5 changed files with 51 additions and 32 deletions

View File

@ -205,8 +205,15 @@ LRESULT CALLBACK window_procedure(HWND window, unsigned int msg, WPARAM wp, LPAR
RAWINPUT* raw = reinterpret_cast<RAWINPUT*>(lpb.data()); RAWINPUT* raw = reinterpret_cast<RAWINPUT*>(lpb.data());
// Make sure it's a keyboard type event, relative to a key press. // Make sure it's a keyboard type event, relative to a key press.
if (raw->header.dwType == RIM_TYPEKEYBOARD && raw->data.keyboard.Message == WM_KEYDOWN) if (raw->header.dwType == RIM_TYPEKEYBOARD)
{ {
// We only want KEY UP AND KEY DOWN events
if (raw->data.keyboard.Message != WM_KEYDOWN && raw->data.keyboard.Message != WM_KEYUP) {
return 0;
}
int is_key_down = raw->data.keyboard.Message == WM_KEYDOWN;
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
@ -241,9 +248,9 @@ LRESULT CALLBACK window_procedure(HWND window, unsigned int msg, WPARAM wp, LPAR
// We need to call the callback in two different ways based on the type of key // We need to call the callback in two different ways based on the type of key
// The only modifier we use that has a result > 0 is the BACKSPACE, so we have to consider it. // The only modifier we use that has a result > 0 is the BACKSPACE, so we have to consider it.
if (result >= 1 && raw->data.keyboard.VKey != VK_BACK) { if (result >= 1 && raw->data.keyboard.VKey != VK_BACK) {
keypress_callback(manager_instance, reinterpret_cast<int32_t*>(buffer.data()), buffer.size(), 0, raw->data.keyboard.VKey); keypress_callback(manager_instance, reinterpret_cast<int32_t*>(buffer.data()), buffer.size(), 0, raw->data.keyboard.VKey, is_key_down);
}else{ }else{
keypress_callback(manager_instance, nullptr, 0, 1, raw->data.keyboard.VKey); keypress_callback(manager_instance, nullptr, 0, 1, raw->data.keyboard.VKey, is_key_down);
} }
} }
} }

View File

@ -39,7 +39,7 @@ extern "C" int32_t initialize(void * self, wchar_t * ico_path, wchar_t * bmp_pat
* Called when a new keypress is made, the first argument is an int array, * Called when a new keypress is made, the first argument is an int array,
* while the second is the size of the array. * while the second is the size of the array.
*/ */
typedef void (*KeypressCallback)(void * self, int32_t *buffer, int32_t len, int32_t is_modifier, int32_t key_code); typedef void (*KeypressCallback)(void * self, int32_t *buffer, int32_t len, int32_t is_modifier, int32_t key_code, int32_t is_key_down);
extern KeypressCallback keypress_callback; extern KeypressCallback keypress_callback;
/* /*

View File

@ -50,7 +50,7 @@ extern {
// KEYBOARD // KEYBOARD
pub fn register_keypress_callback(cb: extern fn(_self: *mut c_void, *const i32, pub fn register_keypress_callback(cb: extern fn(_self: *mut c_void, *const i32,
i32, i32, i32)); i32, i32, i32, i32));
pub fn eventloop(); pub fn eventloop();
pub fn send_string(string: *const u16); pub fn send_string(string: *const u16);

View File

@ -103,33 +103,36 @@ impl super::Context for WindowsContext {
// Native bridge code // Native bridge code
extern fn keypress_callback(_self: *mut c_void, 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) { is_modifier: i32, key_code: i32, is_key_down: i32) {
unsafe { unsafe {
let _self = _self as *mut WindowsContext; let _self = _self as *mut WindowsContext;
if is_key_down != 0 { // KEY DOWN EVENT
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);
let r = std::char::from_u32(buffer[0] as u32);
if is_modifier == 0 { // Char event // Send the char through the channel
// Convert the received buffer to a character if let Some(c) = r {
let buffer = std::slice::from_raw_parts(raw_buffer, len as usize); let event = Event::Key(KeyEvent::Char(c));
let r = std::char::from_u32(buffer[0] as u32); (*_self).send_channel.send(event).unwrap();
}
// Send the char through the channel
if let Some(c) = r {
let event = Event::Key(KeyEvent::Char(c));
(*_self).send_channel.send(event).unwrap();
} }
}else{ // Modifier event }else{ // KEY UP event
let modifier: Option<KeyModifier> = match key_code { if is_modifier != 0 { // Modifier event
0x5B | 0x5C => Some(META), let modifier: Option<KeyModifier> = match key_code {
0x10 => Some(SHIFT), 0x5B | 0x5C => Some(META),
0x12 => Some(ALT), 0x10 => Some(SHIFT),
0x11 => Some(CTRL), 0x12 => Some(ALT),
0x08 => Some(BACKSPACE), 0x11 => Some(CTRL),
_ => None, 0x08 => Some(BACKSPACE),
}; _ => None,
};
if let Some(modifier) = modifier { if let Some(modifier) = modifier {
let event = Event::Key(KeyEvent::Modifier(modifier)); let event = Event::Key(KeyEvent::Modifier(modifier));
(*_self).send_channel.send(event).unwrap(); (*_self).send_channel.send(event).unwrap();
}
} }
} }
} }

View File

@ -20,8 +20,6 @@
// This functions are used to register/unregister espanso from the system daemon manager. // This functions are used to register/unregister espanso from the system daemon manager.
use crate::config::ConfigSet; use crate::config::ConfigSet;
use std::fs::create_dir_all;
use std::process::{Command, ExitStatus};
// INSTALLATION // INSTALLATION
@ -36,7 +34,10 @@ const MAC_PLIST_CONTENT : &str = include_str!("res/mac/com.federicoterzi.espanso
const MAC_PLIST_FILENAME : &str = "com.federicoterzi.espanso.plist"; const MAC_PLIST_FILENAME : &str = "com.federicoterzi.espanso.plist";
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn install(config_set: ConfigSet) { pub fn install(_config_set: ConfigSet) {
use std::fs::create_dir_all;
use std::process::{Command, ExitStatus};
let home_dir = dirs::home_dir().expect("Could not get user home directory"); let home_dir = dirs::home_dir().expect("Could not get user home directory");
let library_dir = home_dir.join("Library"); let library_dir = home_dir.join("Library");
let agents_dir = library_dir.join("LaunchAgents"); let agents_dir = library_dir.join("LaunchAgents");
@ -81,7 +82,10 @@ pub fn install(config_set: ConfigSet) {
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn uninstall(config_set: ConfigSet) { pub fn uninstall(_config_set: ConfigSet) {
use std::fs::create_dir_all;
use std::process::{Command, ExitStatus};
let home_dir = dirs::home_dir().expect("Could not get user home directory"); let home_dir = dirs::home_dir().expect("Could not get user home directory");
let library_dir = home_dir.join("Library"); let library_dir = home_dir.join("Library");
let agents_dir = library_dir.join("LaunchAgents"); let agents_dir = library_dir.join("LaunchAgents");
@ -101,6 +105,11 @@ pub fn uninstall(config_set: ConfigSet) {
} }
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn install(config_set: ConfigSet) { pub fn install(_config_set: ConfigSet) {
println!("Windows does not support system daemon integration.")
}
#[cfg(target_os = "windows")]
pub fn uninstall(_config_set: ConfigSet) {
println!("Windows does not support system daemon integration.") println!("Windows does not support system daemon integration.")
} }