1 // Copyright 2023 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use windows::Win32::UI::Input::KeyboardAndMouse::GetKeyState; 6 7 /// Extracts the scancode (scancode set #1 / IBM PC XT) from the l_param of a WM_KEY/WM_SYSKEY 8 /// event. scancode_from_lparam(l_param: isize) -> u329pub fn scancode_from_lparam(l_param: isize) -> u32 { 10 // Bits 16 - 23 of l_param contain the lower 8 bits of the scancode. 11 // https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keyup 12 // 13 // Note: conversion from isize to u32 is safe because the bitwise &. 14 let lower_scancode = (l_param as u32 >> 16) & 0xFF; 15 16 let is_extended_key = (l_param as u32 >> 24) & 1 == 1; 17 if is_extended_key { 18 // Extended keys have 16 bit scancodes of the form 0xe0YY, where YY is the 19 // lower_scancode extracted above. 20 lower_scancode | 0xe000 21 } else { 22 // Regular keys only use the lower 8 bits of the scancode. 23 lower_scancode 24 } 25 } 26 27 /// Similar to keys_state, but returns false if any of the specified keys are up. 28 #[inline] keys_down(keys: &[i32]) -> bool29pub fn keys_down(keys: &[i32]) -> bool { 30 keys_state(keys).unwrap_or(false) 31 } 32 33 /// Returns whether a list of keys are all down or all up, or None if they do not match. 34 /// Note that this does NOT work for toggle keys like the caps lock. 35 #[inline] keys_state(keys: &[i32]) -> Option<bool>36fn keys_state(keys: &[i32]) -> Option<bool> { 37 let mut all_down: Option<bool> = None; 38 for key in keys { 39 // If the high order bit is set, the key is down 40 // SAFETY: Trivially safe (no pointers, return code is checked). 41 let key_down = unsafe { GetKeyState(*key) } >> 15 & 0x1 == 0x1; 42 match all_down { 43 Some(other_keys_down) => { 44 if other_keys_down != key_down { 45 return None; 46 } 47 } 48 None => all_down = Some(key_down), 49 } 50 } 51 all_down 52 } 53