use crate::*;
use windows::Win32::Foundation::{LPARAM, POINT, WPARAM};
use windows::Win32::Graphics::Gdi::{ClientToScreen, ScreenToClient};
use windows::Win32::System::{Ole::MK_ALT, SystemServices::*};
use windows::Win32::UI::WindowsAndMessaging::GetCursorPos;
use bitflags::bitflags;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
#[repr(u32)]
enum MouseStateVirtualKey {
Ctrl = 0x1,
Shift = 0x2,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MouseStateVirtualKeys(u32);
impl MouseStateVirtualKeys {
#[inline]
pub fn contains(&self, key: VirtualKey) -> bool {
if key == VirtualKey::Ctrl {
self.0 & MouseStateVirtualKey::Ctrl as u32 != 0
} else if key == VirtualKey::Shift {
self.0 & MouseStateVirtualKey::Shift as u32 != 0
} else {
false
}
}
#[inline]
pub fn to_vec(&self) -> Vec<VirtualKey> {
let mut v = vec![];
if self.0 & MouseStateVirtualKey::Ctrl as u32 != 0 {
v.push(VirtualKey::Ctrl);
}
if self.0 & MouseStateVirtualKey::Shift as u32 != 0 {
v.push(VirtualKey::Shift);
}
v
}
}
impl From<WPARAM> for MouseStateVirtualKeys {
#[inline]
fn from(value: WPARAM) -> Self {
let value = loword(value.0 as i32) as u32;
let mut ret = 0;
if value & MK_CONTROL.0 != 0 {
ret |= MouseStateVirtualKey::Ctrl as u32;
}
if value & MK_SHIFT.0 != 0 {
ret |= MouseStateVirtualKey::Shift as u32;
}
Self(ret)
}
}
impl std::fmt::Debug for MouseStateVirtualKeys {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let v = self.to_vec();
write!(f, "{v:?}")
}
}
impl std::fmt::Display for MouseStateVirtualKeys {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let v = self.to_vec();
write!(f, "{v:?}")
}
}
#[derive(Clone, Debug)]
pub struct MouseState {
pub position: PhysicalPosition<i32>,
pub buttons: MouseButtons,
pub keys: MouseStateVirtualKeys,
}
impl MouseState {
pub(crate) fn from_params(wparam: WPARAM, lparam: LPARAM) -> Self {
Self {
position: lparam_to_point(lparam),
buttons: wparam.into(),
keys: wparam.into(),
}
}
}
pub const WHEEL_DELTA: i32 = windows::Win32::UI::WindowsAndMessaging::WHEEL_DELTA as i32;
#[inline]
pub fn get_cursor_pos() -> ScreenPosition<i32> {
unsafe {
let mut pt = POINT::default();
let _ = GetCursorPos(&mut pt);
ScreenPosition::new(pt.x, pt.y)
}
}
#[inline]
pub fn client_to_screen(window: &impl IsWindow, src: PhysicalPosition<i32>) -> ScreenPosition<i32> {
unsafe {
let mut pt = POINT { x: src.x, y: src.y };
let _ = ClientToScreen(window.window_handle().as_hwnd(), &mut pt);
ScreenPosition::new(pt.x, pt.y)
}
}
#[inline]
pub fn screen_to_client(window: &impl IsWindow, src: ScreenPosition<i32>) -> PhysicalPosition<i32> {
unsafe {
let mut pt = POINT { x: src.x, y: src.y };
let _ = ScreenToClient(window.window_handle().as_hwnd(), &mut pt);
PhysicalPosition::new(pt.x, pt.y)
}
}
bitflags! {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct ModifierKey: u32 {
const CONTROL = MK_CONTROL.0;
const SHIFT = MK_SHIFT.0;
const ALT = MK_ALT;
const LBUTTON = MK_LBUTTON.0;
const RBUTTON = MK_RBUTTON.0;
const MBUTTON = MK_MBUTTON.0;
const XBUTTON1 = MK_XBUTTON1.0;
const XBUTTON2 = MK_XBUTTON2.0;
}
}
impl ModifierKey {
#[inline]
pub const fn as_raw(&self) -> MODIFIERKEYS_FLAGS {
MODIFIERKEYS_FLAGS(self.bits())
}
}
impl From<MODIFIERKEYS_FLAGS> for ModifierKey {
fn from(value: MODIFIERKEYS_FLAGS) -> Self {
Self::from_bits_retain(value.0)
}
}