use std::sync::atomic::{AtomicU32, Ordering};
static MODIFIER_MASK: AtomicU32 = AtomicU32::new(0);
pub const MASK_BUTTON1: u32 = 1 << 8;
pub const MASK_BUTTON2: u32 = 1 << 9;
pub const MASK_BUTTON3: u32 = 1 << 10;
pub const MASK_BUTTON4: u32 = 1 << 11;
pub const MASK_BUTTON5: u32 = 1 << 12;
pub const MASK_SHIFT: u32 = 1 << 0;
pub const MASK_CTRL: u32 = 1 << 1;
pub const MASK_ALT: u32 = 1 << 2;
pub const MASK_META: u32 = 1 << 3;
pub const MASK_CAPS_LOCK: u32 = 1 << 4;
pub const MASK_NUM_LOCK: u32 = 1 << 5;
pub const MASK_SCROLL_LOCK: u32 = 1 << 6;
pub const MASK_ALL_BUTTONS: u32 =
MASK_BUTTON1 | MASK_BUTTON2 | MASK_BUTTON3 | MASK_BUTTON4 | MASK_BUTTON5;
pub const MASK_ALL_MODIFIERS: u32 = MASK_SHIFT
| MASK_CTRL
| MASK_ALT
| MASK_META
| MASK_CAPS_LOCK
| MASK_NUM_LOCK
| MASK_SCROLL_LOCK;
#[inline]
pub fn set_mask(mask: u32) {
MODIFIER_MASK.fetch_or(mask, Ordering::SeqCst);
}
#[inline]
pub fn unset_mask(mask: u32) {
MODIFIER_MASK.fetch_and(!mask, Ordering::SeqCst);
}
#[inline]
pub fn get_mask() -> u32 {
MODIFIER_MASK.load(Ordering::SeqCst)
}
#[inline]
pub fn reset_mask() {
MODIFIER_MASK.store(0, Ordering::SeqCst);
}
#[inline]
pub fn is_button_held() -> bool {
(get_mask() & MASK_ALL_BUTTONS) != 0
}
#[inline]
pub fn is_button_pressed(button_mask: u32) -> bool {
(get_mask() & button_mask) != 0
}
#[inline]
pub fn is_shift_held() -> bool {
is_button_pressed(MASK_SHIFT)
}
#[inline]
pub fn is_ctrl_held() -> bool {
is_button_pressed(MASK_CTRL)
}
#[inline]
pub fn is_alt_held() -> bool {
is_button_pressed(MASK_ALT)
}
#[inline]
pub fn is_meta_held() -> bool {
is_button_pressed(MASK_META)
}
pub fn button_to_mask(button_num: u8) -> u32 {
match button_num {
1 => MASK_BUTTON1,
2 => MASK_BUTTON2,
3 => MASK_BUTTON3,
4 => MASK_BUTTON4,
5 => MASK_BUTTON5,
_ => 0,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_button_mask_operations() {
reset_mask();
assert!(!is_button_held());
set_mask(MASK_BUTTON1);
assert!(is_button_held());
assert!(is_button_pressed(MASK_BUTTON1));
assert!(!is_button_pressed(MASK_BUTTON2));
set_mask(MASK_BUTTON2);
assert!(is_button_pressed(MASK_BUTTON1));
assert!(is_button_pressed(MASK_BUTTON2));
unset_mask(MASK_BUTTON1);
assert!(!is_button_pressed(MASK_BUTTON1));
assert!(is_button_pressed(MASK_BUTTON2));
assert!(is_button_held());
unset_mask(MASK_BUTTON2);
assert!(!is_button_held());
}
#[test]
fn test_modifier_mask_operations() {
reset_mask();
set_mask(MASK_SHIFT);
assert!(is_shift_held());
assert!(!is_ctrl_held());
set_mask(MASK_CTRL);
assert!(is_shift_held());
assert!(is_ctrl_held());
reset_mask();
assert!(!is_shift_held());
assert!(!is_ctrl_held());
}
#[test]
fn test_button_to_mask() {
assert_eq!(button_to_mask(1), MASK_BUTTON1);
assert_eq!(button_to_mask(2), MASK_BUTTON2);
assert_eq!(button_to_mask(3), MASK_BUTTON3);
assert_eq!(button_to_mask(4), MASK_BUTTON4);
assert_eq!(button_to_mask(5), MASK_BUTTON5);
assert_eq!(button_to_mask(6), 0);
}
}