mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
Use himetric values in WM_POINTER events (#1053)
* Use himetric location for WM_POINTER events * Ran rustfmt
This commit is contained in:
parent
a28b60578d
commit
454d4190b7
|
@ -39,7 +39,7 @@ use winapi::{
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
commctrl, libloaderapi, ole2, processthreadsapi, winbase,
|
commctrl, libloaderapi, ole2, processthreadsapi, winbase,
|
||||||
winnt::{LONG, LPCSTR, SHORT},
|
winnt::{HANDLE, LONG, LPCSTR, SHORT},
|
||||||
winuser,
|
winuser,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -71,12 +71,19 @@ type GetPointerFrameInfoHistory = unsafe extern "system" fn(
|
||||||
) -> BOOL;
|
) -> BOOL;
|
||||||
|
|
||||||
type SkipPointerFrameMessages = unsafe extern "system" fn(pointerId: UINT) -> BOOL;
|
type SkipPointerFrameMessages = unsafe extern "system" fn(pointerId: UINT) -> BOOL;
|
||||||
|
type GetPointerDeviceRects = unsafe extern "system" fn(
|
||||||
|
device: HANDLE,
|
||||||
|
pointerDeviceRect: *mut RECT,
|
||||||
|
displayRect: *mut RECT,
|
||||||
|
) -> BOOL;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref GET_POINTER_FRAME_INFO_HISTORY: Option<GetPointerFrameInfoHistory> =
|
static ref GET_POINTER_FRAME_INFO_HISTORY: Option<GetPointerFrameInfoHistory> =
|
||||||
get_function!("user32.dll", GetPointerFrameInfoHistory);
|
get_function!("user32.dll", GetPointerFrameInfoHistory);
|
||||||
static ref SKIP_POINTER_FRAME_MESSAGES: Option<SkipPointerFrameMessages> =
|
static ref SKIP_POINTER_FRAME_MESSAGES: Option<SkipPointerFrameMessages> =
|
||||||
get_function!("user32.dll", SkipPointerFrameMessages);
|
get_function!("user32.dll", SkipPointerFrameMessages);
|
||||||
|
static ref GET_POINTER_DEVICE_RECTS: Option<GetPointerDeviceRects> =
|
||||||
|
get_function!("user32.dll", GetPointerDeviceRects);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct SubclassInput<T> {
|
pub(crate) struct SubclassInput<T> {
|
||||||
|
@ -1484,9 +1491,14 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
}
|
}
|
||||||
|
|
||||||
winuser::WM_POINTERDOWN | winuser::WM_POINTERUPDATE | winuser::WM_POINTERUP => {
|
winuser::WM_POINTERDOWN | winuser::WM_POINTERUPDATE | winuser::WM_POINTERUP => {
|
||||||
if let (Some(GetPointerFrameInfoHistory), Some(SkipPointerFrameMessages)) = (
|
if let (
|
||||||
|
Some(GetPointerFrameInfoHistory),
|
||||||
|
Some(SkipPointerFrameMessages),
|
||||||
|
Some(GetPointerDeviceRects),
|
||||||
|
) = (
|
||||||
*GET_POINTER_FRAME_INFO_HISTORY,
|
*GET_POINTER_FRAME_INFO_HISTORY,
|
||||||
*SKIP_POINTER_FRAME_MESSAGES,
|
*SKIP_POINTER_FRAME_MESSAGES,
|
||||||
|
*GET_POINTER_DEVICE_RECTS,
|
||||||
) {
|
) {
|
||||||
let pointer_id = LOWORD(wparam as DWORD) as UINT;
|
let pointer_id = LOWORD(wparam as DWORD) as UINT;
|
||||||
let mut entries_count = 0 as UINT;
|
let mut entries_count = 0 as UINT;
|
||||||
|
@ -1519,17 +1531,44 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
// The information retrieved appears in reverse chronological order, with the most recent entry in the first
|
// The information retrieved appears in reverse chronological order, with the most recent entry in the first
|
||||||
// row of the returned array
|
// row of the returned array
|
||||||
for pointer_info in pointer_infos.iter().rev() {
|
for pointer_info in pointer_infos.iter().rev() {
|
||||||
|
let mut device_rect: RECT = mem::uninitialized();
|
||||||
|
let mut display_rect: RECT = mem::uninitialized();
|
||||||
|
|
||||||
|
if (GetPointerDeviceRects(
|
||||||
|
pointer_info.sourceDevice,
|
||||||
|
&mut device_rect as *mut _,
|
||||||
|
&mut display_rect as *mut _,
|
||||||
|
)) == 0
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the most precise himetric to pixel conversion we calculate the ratio between the resolution
|
||||||
|
// of the display device (pixel) and the touch device (himetric).
|
||||||
|
let himetric_to_pixel_ratio_x = (display_rect.right - display_rect.left) as f64
|
||||||
|
/ (device_rect.right - device_rect.left) as f64;
|
||||||
|
let himetric_to_pixel_ratio_y = (display_rect.bottom - display_rect.top) as f64
|
||||||
|
/ (device_rect.bottom - device_rect.top) as f64;
|
||||||
|
|
||||||
|
// ptHimetricLocation's origin is 0,0 even on multi-monitor setups.
|
||||||
|
// On multi-monitor setups we need to translate the himetric location to the rect of the
|
||||||
|
// display device it's attached to.
|
||||||
|
let x = display_rect.left as f64
|
||||||
|
+ pointer_info.ptHimetricLocation.x as f64 * himetric_to_pixel_ratio_x;
|
||||||
|
let y = display_rect.top as f64
|
||||||
|
+ pointer_info.ptHimetricLocation.y as f64 * himetric_to_pixel_ratio_y;
|
||||||
|
|
||||||
let mut location = POINT {
|
let mut location = POINT {
|
||||||
x: pointer_info.ptPixelLocation.x,
|
x: x.floor() as i32,
|
||||||
y: pointer_info.ptPixelLocation.y,
|
y: y.floor() as i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
if winuser::ScreenToClient(window, &mut location as *mut _) == 0 {
|
if winuser::ScreenToClient(window, &mut location as *mut _) == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = location.x as f64;
|
let x = location.x as f64 + x.fract();
|
||||||
let y = location.y as f64;
|
let y = location.y as f64 + y.fract();
|
||||||
let location = LogicalPosition::from_physical((x, y), dpi_factor);
|
let location = LogicalPosition::from_physical((x, y), dpi_factor);
|
||||||
subclass_input.send_event(Event::WindowEvent {
|
subclass_input.send_event(Event::WindowEvent {
|
||||||
window_id: RootWindowId(WindowId(window)),
|
window_id: RootWindowId(WindowId(window)),
|
||||||
|
|
Loading…
Reference in a new issue