mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
parent
93c36ccf78
commit
026b331ba5
|
@ -9,13 +9,12 @@ use winapi::{
|
||||||
winerror::S_OK,
|
winerror::S_OK,
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
libloaderapi::{GetProcAddress, LoadLibraryA},
|
|
||||||
shellscalingapi::{
|
shellscalingapi::{
|
||||||
MDT_EFFECTIVE_DPI, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS,
|
MDT_EFFECTIVE_DPI, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS,
|
||||||
PROCESS_PER_MONITOR_DPI_AWARE,
|
PROCESS_PER_MONITOR_DPI_AWARE,
|
||||||
},
|
},
|
||||||
wingdi::{GetDeviceCaps, LOGPIXELSX},
|
wingdi::{GetDeviceCaps, LOGPIXELSX},
|
||||||
winnt::{HRESULT, LPCSTR},
|
winnt::HRESULT,
|
||||||
winuser::{self, MONITOR_DEFAULTTONEAREST},
|
winuser::{self, MONITOR_DEFAULTTONEAREST},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -35,33 +34,6 @@ type GetDpiForMonitor = unsafe extern "system" fn(
|
||||||
) -> HRESULT;
|
) -> HRESULT;
|
||||||
type EnableNonClientDpiScaling = unsafe extern "system" fn(hwnd: HWND) -> BOOL;
|
type EnableNonClientDpiScaling = unsafe extern "system" fn(hwnd: HWND) -> BOOL;
|
||||||
|
|
||||||
// Helper function to dynamically load function pointer.
|
|
||||||
// `library` and `function` must be zero-terminated.
|
|
||||||
fn get_function_impl(library: &str, function: &str) -> Option<*const c_void> {
|
|
||||||
assert_eq!(library.chars().last(), Some('\0'));
|
|
||||||
assert_eq!(function.chars().last(), Some('\0'));
|
|
||||||
|
|
||||||
// Library names we will use are ASCII so we can use the A version to avoid string conversion.
|
|
||||||
let module = unsafe { LoadLibraryA(library.as_ptr() as LPCSTR) };
|
|
||||||
if module.is_null() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let function_ptr = unsafe { GetProcAddress(module, function.as_ptr() as LPCSTR) };
|
|
||||||
if function_ptr.is_null() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(function_ptr as _)
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! get_function {
|
|
||||||
($lib:expr, $func:ident) => {
|
|
||||||
get_function_impl(concat!($lib, '\0'), concat!(stringify!($func), '\0'))
|
|
||||||
.map(|f| unsafe { mem::transmute::<*const _, $func>(f) })
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref GET_DPI_FOR_WINDOW: Option<GetDpiForWindow> =
|
static ref GET_DPI_FOR_WINDOW: Option<GetDpiForWindow> =
|
||||||
get_function!("user32.dll", GetDpiForWindow);
|
get_function!("user32.dll", GetDpiForWindow);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(non_snake_case)]
|
||||||
//! An events loop on Win32 is a background thread.
|
//! An events loop on Win32 is a background thread.
|
||||||
//!
|
//!
|
||||||
//! Creating an events loop spawns a thread and blocks it in a permanent Win32 events loop.
|
//! Creating an events loop spawns a thread and blocks it in a permanent Win32 events loop.
|
||||||
|
@ -62,6 +63,22 @@ use crate::{
|
||||||
window::WindowId as RootWindowId,
|
window::WindowId as RootWindowId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type GetPointerFrameInfoHistory = unsafe extern "system" fn(
|
||||||
|
pointerId: UINT,
|
||||||
|
entriesCount: *mut UINT,
|
||||||
|
pointerCount: *mut UINT,
|
||||||
|
pointerInfo: *mut winuser::POINTER_INFO,
|
||||||
|
) -> BOOL;
|
||||||
|
|
||||||
|
type SkipPointerFrameMessages = unsafe extern "system" fn(pointerId: UINT) -> BOOL;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref GET_POINTER_FRAME_INFO_HISTORY: Option<GetPointerFrameInfoHistory> =
|
||||||
|
get_function!("user32.dll", GetPointerFrameInfoHistory);
|
||||||
|
static ref SKIP_POINTER_FRAME_MESSAGES: Option<SkipPointerFrameMessages> =
|
||||||
|
get_function!("user32.dll", SkipPointerFrameMessages);
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct SubclassInput<T> {
|
pub(crate) struct SubclassInput<T> {
|
||||||
pub window_state: Arc<Mutex<WindowState>>,
|
pub window_state: Arc<Mutex<WindowState>>,
|
||||||
pub event_loop_runner: EventLoopRunnerShared<T>,
|
pub event_loop_runner: EventLoopRunnerShared<T>,
|
||||||
|
@ -1458,60 +1475,66 @@ 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 => {
|
||||||
let pointer_id = LOWORD(wparam as DWORD) as UINT;
|
if let (Some(GetPointerFrameInfoHistory), Some(SkipPointerFrameMessages)) = (
|
||||||
let mut entries_count = 0 as UINT;
|
*GET_POINTER_FRAME_INFO_HISTORY,
|
||||||
let mut pointers_count = 0 as UINT;
|
*SKIP_POINTER_FRAME_MESSAGES,
|
||||||
if winuser::GetPointerFrameInfoHistory(
|
) {
|
||||||
pointer_id,
|
let pointer_id = LOWORD(wparam as DWORD) as UINT;
|
||||||
&mut entries_count as *mut _,
|
let mut entries_count = 0 as UINT;
|
||||||
&mut pointers_count as *mut _,
|
let mut pointers_count = 0 as UINT;
|
||||||
std::ptr::null_mut(),
|
if GetPointerFrameInfoHistory(
|
||||||
) == 0
|
pointer_id,
|
||||||
{
|
&mut entries_count as *mut _,
|
||||||
return 0;
|
&mut pointers_count as *mut _,
|
||||||
}
|
std::ptr::null_mut(),
|
||||||
|
) == 0
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
let pointer_info_count = (entries_count * pointers_count) as usize;
|
let pointer_info_count = (entries_count * pointers_count) as usize;
|
||||||
let mut pointer_infos = Vec::with_capacity(pointer_info_count);
|
let mut pointer_infos = Vec::with_capacity(pointer_info_count);
|
||||||
pointer_infos.set_len(pointer_info_count);
|
pointer_infos.set_len(pointer_info_count);
|
||||||
if winuser::GetPointerFrameInfoHistory(
|
if GetPointerFrameInfoHistory(
|
||||||
pointer_id,
|
pointer_id,
|
||||||
&mut entries_count as *mut _,
|
&mut entries_count as *mut _,
|
||||||
&mut pointers_count as *mut _,
|
&mut pointers_count as *mut _,
|
||||||
pointer_infos.as_mut_ptr(),
|
pointer_infos.as_mut_ptr(),
|
||||||
) == 0
|
) == 0
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dpi_factor = hwnd_scale_factor(window);
|
let dpi_factor = hwnd_scale_factor(window);
|
||||||
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getpointerframeinfohistory
|
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getpointerframeinfohistory
|
||||||
// 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 x = pointer_info.ptPixelLocation.x as f64;
|
let x = pointer_info.ptPixelLocation.x as f64;
|
||||||
let y = pointer_info.ptPixelLocation.y as f64;
|
let y = pointer_info.ptPixelLocation.y as f64;
|
||||||
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)),
|
||||||
event: WindowEvent::Touch(Touch {
|
event: WindowEvent::Touch(Touch {
|
||||||
phase: if pointer_info.pointerFlags & winuser::POINTER_FLAG_DOWN != 0 {
|
phase: if pointer_info.pointerFlags & winuser::POINTER_FLAG_DOWN != 0 {
|
||||||
TouchPhase::Started
|
TouchPhase::Started
|
||||||
} else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UP != 0 {
|
} else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UP != 0 {
|
||||||
TouchPhase::Ended
|
TouchPhase::Ended
|
||||||
} else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UPDATE != 0 {
|
} else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UPDATE != 0
|
||||||
TouchPhase::Moved
|
{
|
||||||
} else {
|
TouchPhase::Moved
|
||||||
continue;
|
} else {
|
||||||
},
|
continue;
|
||||||
location,
|
},
|
||||||
id: pointer_info.pointerId as u64,
|
location,
|
||||||
device_id: DEVICE_ID,
|
id: pointer_info.pointerId as u64,
|
||||||
}),
|
device_id: DEVICE_ID,
|
||||||
});
|
}),
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
winuser::SkipPointerFrameMessages(pointer_id);
|
SkipPointerFrameMessages(pointer_id);
|
||||||
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,8 @@ impl WindowId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod util;
|
||||||
mod dpi;
|
mod dpi;
|
||||||
mod drop_handler;
|
mod drop_handler;
|
||||||
mod event;
|
mod event;
|
||||||
|
@ -74,6 +76,5 @@ mod event_loop;
|
||||||
mod icon;
|
mod icon;
|
||||||
mod monitor;
|
mod monitor;
|
||||||
mod raw_input;
|
mod raw_input;
|
||||||
mod util;
|
|
||||||
mod window;
|
mod window;
|
||||||
mod window_state;
|
mod window_state;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
io, mem,
|
io, mem,
|
||||||
ops::BitAnd,
|
ops::BitAnd,
|
||||||
|
os::raw::c_void,
|
||||||
ptr, slice,
|
ptr, slice,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
@ -12,9 +13,44 @@ use winapi::{
|
||||||
minwindef::{BOOL, DWORD},
|
minwindef::{BOOL, DWORD},
|
||||||
windef::{HWND, POINT, RECT},
|
windef::{HWND, POINT, RECT},
|
||||||
},
|
},
|
||||||
um::{winbase::lstrlenW, winuser},
|
um::{
|
||||||
|
libloaderapi::{GetProcAddress, LoadLibraryA},
|
||||||
|
winbase::lstrlenW,
|
||||||
|
winnt::LPCSTR,
|
||||||
|
winuser,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper function to dynamically load function pointer.
|
||||||
|
// `library` and `function` must be zero-terminated.
|
||||||
|
pub(super) fn get_function_impl(library: &str, function: &str) -> Option<*const c_void> {
|
||||||
|
assert_eq!(library.chars().last(), Some('\0'));
|
||||||
|
assert_eq!(function.chars().last(), Some('\0'));
|
||||||
|
|
||||||
|
// Library names we will use are ASCII so we can use the A version to avoid string conversion.
|
||||||
|
let module = unsafe { LoadLibraryA(library.as_ptr() as LPCSTR) };
|
||||||
|
if module.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let function_ptr = unsafe { GetProcAddress(module, function.as_ptr() as LPCSTR) };
|
||||||
|
if function_ptr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(function_ptr as _)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! get_function {
|
||||||
|
($lib:expr, $func:ident) => {
|
||||||
|
crate::platform_impl::platform::util::get_function_impl(
|
||||||
|
concat!($lib, '\0'),
|
||||||
|
concat!(stringify!($func), '\0'),
|
||||||
|
)
|
||||||
|
.map(|f| unsafe { std::mem::transmute::<*const _, $func>(f) })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_flag<T>(bitset: T, flag: T) -> bool
|
pub fn has_flag<T>(bitset: T, flag: T) -> bool
|
||||||
where
|
where
|
||||||
T: Copy + PartialEq + BitAnd<T, Output = T>,
|
T: Copy + PartialEq + BitAnd<T, Output = T>,
|
||||||
|
|
Loading…
Reference in a new issue