KeyState uses flag to determine event type instead of seperate parameter
added is_down method to KeyState added more tests add get_flag and has_one_bit_set functions to lib.rs change main.rs to use is_down instead of w_param for checking event type
This commit is contained in:
parent
dde124e76a
commit
ee15231a47
3 changed files with 67 additions and 10 deletions
|
@ -1,7 +1,8 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
use winapi::um::winuser::{GetKeyNameTextW, KBDLLHOOKSTRUCT, LLKHF_EXTENDED};
|
||||
use winapi::um::winuser::{GetKeyNameTextW, KBDLLHOOKSTRUCT, LLKHF_EXTENDED, LLKHF_UP};
|
||||
use wio::wide::FromWide;
|
||||
use crate::get_flag;
|
||||
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct KeyState {
|
||||
|
@ -31,7 +32,8 @@ impl KeyState {
|
|||
}
|
||||
|
||||
/// `key_down` if the event was a keydown event, this should be true. if it was keyup it should be false
|
||||
pub fn update(&mut self, key: KBDLLHOOKSTRUCT, key_down: bool) {
|
||||
pub fn update(&mut self, key: KBDLLHOOKSTRUCT) {
|
||||
let key_down = !get_flag(key.flags, LLKHF_UP);
|
||||
self.kbdllstruct = key;
|
||||
|
||||
match key.vkCode {
|
||||
|
@ -40,7 +42,7 @@ impl KeyState {
|
|||
164 | 165 => self.alt_down = key_down,
|
||||
91 => self.win_down = key_down,
|
||||
_ => {},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// true if the key is an auxiliary key like shift, control or the windows key
|
||||
|
@ -48,22 +50,28 @@ impl KeyState {
|
|||
matches!(self.kbdllstruct.vkCode, 160..=165 | 91)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[no_mangle] //required to not get garbage from native call
|
||||
pub fn name(&self) -> String {
|
||||
unsafe {
|
||||
#[allow(clippy::if_not_else)] //clippy wrongfully assumes the != here is unecessary
|
||||
let flags = if self.kbdllstruct.flags & LLKHF_EXTENDED != 0 { 1 << 24 } else { 0 };
|
||||
let flags = if get_flag(self.kbdllstruct.flags, LLKHF_EXTENDED) { 1 << 24 } else { 0 };
|
||||
|
||||
let mut out = [0_u16; 128];
|
||||
GetKeyNameTextW((self.kbdllstruct.scanCode << 16 | flags /*this distinguishes special keys by setting a flag. yes only microsoft thinks that input and flags in 1 param is a good idea*/) as i32, (&mut out).as_mut_ptr(), 128);
|
||||
let null_pos = out.iter().position(|x| *x == b'\0' as u16).unwrap_or_else(|| out.len());
|
||||
OsString::from_wide(&out[..null_pos]).to_str().unwrap().to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
///true if this event is keydown, otherwise false
|
||||
pub fn is_down(&self) -> bool {
|
||||
!get_flag(self.kbdllstruct.flags, LLKHF_UP)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::key::keystate::KeyState;
|
||||
use winapi::um::winuser::LLKHF_UP;
|
||||
|
||||
#[test]
|
||||
fn is_aux_key() {
|
||||
|
@ -71,4 +79,17 @@ mod tests {
|
|||
k.kbdllstruct.vkCode = 160;
|
||||
assert!(k.is_aux_key());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_down() {
|
||||
let mut k = KeyState::new();
|
||||
|
||||
k.kbdllstruct.flags = LLKHF_UP;
|
||||
|
||||
assert!(!k.is_down());
|
||||
|
||||
k.kbdllstruct.flags = 0;
|
||||
|
||||
assert!(k.is_down());
|
||||
}
|
||||
}
|
||||
|
|
38
src/lib.rs
38
src/lib.rs
|
@ -4,10 +4,46 @@
|
|||
//disable silly rules
|
||||
#![allow(
|
||||
clippy::module_name_repetitions, //complains about function names which makes no sense, so disabled
|
||||
clippy::must_use_candidate, //no i dont wannt to add the must_use attribute to everything
|
||||
clippy::must_use_candidate, //no i dont want to add the must_use attribute to everything
|
||||
clippy::cast_lossless, clippy::cast_possible_wrap, //lossy casts are required to work with garbage WinApi
|
||||
)]
|
||||
//endregion
|
||||
|
||||
pub mod logging;
|
||||
pub mod key;
|
||||
|
||||
///gets the flag at the position of `flag`. `flag` must have exactly 1 bit set
|
||||
fn get_flag(val: u32, flag: u32) -> bool {
|
||||
if has_one_bit_set(flag) {
|
||||
val & flag != 0
|
||||
} else {
|
||||
panic!("flag must have 1 bit set")
|
||||
}
|
||||
}
|
||||
|
||||
///true if exactly 1 bit of the given number is set
|
||||
fn has_one_bit_set(n: u32) -> bool {
|
||||
//Dont ask me why this works! its mathgic!
|
||||
n > 0 && !(n & (n - 1) > 0)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn get_flag() {
|
||||
assert!(super::get_flag(5, 1 << 2));
|
||||
assert!(!super::get_flag(3, 1 << 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn get_flag_panic() {
|
||||
super::get_flag(0, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_one_bit_set() {
|
||||
assert!(super::has_one_bit_set(1));
|
||||
assert!(!super::has_one_bit_set(3));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,12 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe extern "system" fn hook_callback(_code: i32, w_param: usize, l_param: isize) -> isize {
|
||||
unsafe extern "system" fn hook_callback(_code: i32, _w_param: usize, l_param: isize) -> isize {
|
||||
let mut state = KEYSTATE.lock().unwrap();
|
||||
let key = *(l_param as PKBDLLHOOKSTRUCT);
|
||||
state.update(key, w_param == 256);
|
||||
state.update(key);
|
||||
//Check if keydown and not aux key
|
||||
if w_param != 256 || state.is_aux_key() { return 0; }
|
||||
if state.is_down() || state.is_aux_key() { return 0; }
|
||||
LOGGER.log(&state);
|
||||
0
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue