chore(rustfmt): use nightly (#2325)
Stable rustfmt lacks a lot of features resulting in worse formatted code, thus use nightly formatter.
This commit is contained in:
parent
7006c7ceca
commit
7b0c7b6cb2
154 changed files with 3439 additions and 5891 deletions
|
|
@ -3,21 +3,13 @@
|
|||
use std::{ffi::c_void, ptr};
|
||||
|
||||
use crate::utils::Lazy;
|
||||
use windows_sys::{
|
||||
core::PCSTR,
|
||||
Win32::{
|
||||
Foundation::{BOOL, HWND, NTSTATUS, S_OK},
|
||||
System::{
|
||||
LibraryLoader::{GetProcAddress, LoadLibraryA},
|
||||
SystemInformation::OSVERSIONINFOW,
|
||||
},
|
||||
UI::{
|
||||
Accessibility::{HCF_HIGHCONTRASTON, HIGHCONTRASTA},
|
||||
Controls::SetWindowTheme,
|
||||
WindowsAndMessaging::{SystemParametersInfoA, SPI_GETHIGHCONTRAST},
|
||||
},
|
||||
},
|
||||
};
|
||||
use windows_sys::core::PCSTR;
|
||||
use windows_sys::Win32::Foundation::{BOOL, HWND, NTSTATUS, S_OK};
|
||||
use windows_sys::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryA};
|
||||
use windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW;
|
||||
use windows_sys::Win32::UI::Accessibility::{HCF_HIGHCONTRASTON, HIGHCONTRASTA};
|
||||
use windows_sys::Win32::UI::Controls::SetWindowTheme;
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{SystemParametersInfoA, SPI_GETHIGHCONTRAST};
|
||||
|
||||
use crate::window::Theme;
|
||||
|
||||
|
|
@ -72,11 +64,7 @@ pub fn try_theme(hwnd: HWND, preferred_theme: Option<Theme>) -> Theme {
|
|||
None => should_use_dark_mode(),
|
||||
};
|
||||
|
||||
let theme = if is_dark_mode {
|
||||
Theme::Dark
|
||||
} else {
|
||||
Theme::Light
|
||||
};
|
||||
let theme = if is_dark_mode { Theme::Dark } else { Theme::Light };
|
||||
let theme_name = match theme {
|
||||
Theme::Dark => DARK_THEME_NAME.as_ptr(),
|
||||
Theme::Light => LIGHT_THEME_NAME.as_ptr(),
|
||||
|
|
@ -161,11 +149,7 @@ fn should_apps_use_dark_mode() -> bool {
|
|||
}
|
||||
|
||||
fn is_high_contrast() -> bool {
|
||||
let mut hc = HIGHCONTRASTA {
|
||||
cbSize: 0,
|
||||
dwFlags: 0,
|
||||
lpszDefaultScheme: ptr::null_mut(),
|
||||
};
|
||||
let mut hc = HIGHCONTRASTA { cbSize: 0, dwFlags: 0, lpszDefaultScheme: ptr::null_mut() };
|
||||
|
||||
let ok = unsafe {
|
||||
SystemParametersInfoA(
|
||||
|
|
|
|||
|
|
@ -3,14 +3,10 @@
|
|||
|
||||
use std::ffi::c_void;
|
||||
|
||||
use windows_sys::{
|
||||
core::{IUnknown, GUID, HRESULT},
|
||||
Win32::{
|
||||
Foundation::{BOOL, HWND, POINTL},
|
||||
System::Com::{
|
||||
IAdviseSink, IDataObject, IEnumFORMATETC, IEnumSTATDATA, FORMATETC, STGMEDIUM,
|
||||
},
|
||||
},
|
||||
use windows_sys::core::{IUnknown, GUID, HRESULT};
|
||||
use windows_sys::Win32::Foundation::{BOOL, HWND, POINTL};
|
||||
use windows_sys::Win32::System::Com::{
|
||||
IAdviseSink, IDataObject, IEnumFORMATETC, IEnumSTATDATA, FORMATETC, STGMEDIUM,
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -138,10 +134,10 @@ pub const CLSID_TaskbarList: GUID = GUID {
|
|||
};
|
||||
|
||||
pub const IID_ITaskbarList: GUID = GUID {
|
||||
data1: 0x56FDF342,
|
||||
data2: 0xFD6D,
|
||||
data3: 0x11D0,
|
||||
data4: [0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90],
|
||||
data1: 0x56fdf342,
|
||||
data2: 0xfd6d,
|
||||
data3: 0x11d0,
|
||||
data4: [0x95, 0x8a, 0x00, 0x60, 0x97, 0xc9, 0xa0, 0x90],
|
||||
};
|
||||
|
||||
pub const IID_ITaskbarList2: GUID = GUID {
|
||||
|
|
|
|||
|
|
@ -2,19 +2,15 @@
|
|||
|
||||
use std::sync::Once;
|
||||
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{HWND, S_OK},
|
||||
Graphics::Gdi::{
|
||||
GetDC, GetDeviceCaps, MonitorFromWindow, HMONITOR, LOGPIXELSX, MONITOR_DEFAULTTONEAREST,
|
||||
},
|
||||
UI::{
|
||||
HiDpi::{
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,
|
||||
MDT_EFFECTIVE_DPI, PROCESS_PER_MONITOR_DPI_AWARE,
|
||||
},
|
||||
WindowsAndMessaging::IsProcessDPIAware,
|
||||
},
|
||||
use windows_sys::Win32::Foundation::{HWND, S_OK};
|
||||
use windows_sys::Win32::Graphics::Gdi::{
|
||||
GetDC, GetDeviceCaps, MonitorFromWindow, HMONITOR, LOGPIXELSX, MONITOR_DEFAULTTONEAREST,
|
||||
};
|
||||
use windows_sys::Win32::UI::HiDpi::{
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,
|
||||
MDT_EFFECTIVE_DPI, PROCESS_PER_MONITOR_DPI_AWARE,
|
||||
};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::IsProcessDPIAware;
|
||||
|
||||
use crate::platform_impl::platform::util::{
|
||||
ENABLE_NON_CLIENT_DPI_SCALING, GET_DPI_FOR_MONITOR, GET_DPI_FOR_WINDOW, SET_PROCESS_DPI_AWARE,
|
||||
|
|
|
|||
|
|
@ -1,31 +1,24 @@
|
|||
use std::{
|
||||
ffi::{c_void, OsString},
|
||||
os::windows::ffi::OsStringExt,
|
||||
path::PathBuf,
|
||||
ptr,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
use std::ffi::{c_void, OsString};
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use std::path::PathBuf;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use windows_sys::{
|
||||
core::{IUnknown, GUID, HRESULT},
|
||||
Win32::{
|
||||
Foundation::{DV_E_FORMATETC, HWND, POINTL, S_OK},
|
||||
System::{
|
||||
Com::{IDataObject, DVASPECT_CONTENT, FORMATETC, TYMED_HGLOBAL},
|
||||
Ole::{CF_HDROP, DROPEFFECT_COPY, DROPEFFECT_NONE},
|
||||
},
|
||||
UI::Shell::{DragFinish, DragQueryFileW, HDROP},
|
||||
},
|
||||
};
|
||||
use windows_sys::core::{IUnknown, GUID, HRESULT};
|
||||
use windows_sys::Win32::Foundation::{DV_E_FORMATETC, HWND, POINTL, S_OK};
|
||||
use windows_sys::Win32::System::Com::{IDataObject, DVASPECT_CONTENT, FORMATETC, TYMED_HGLOBAL};
|
||||
use windows_sys::Win32::System::Ole::{CF_HDROP, DROPEFFECT_COPY, DROPEFFECT_NONE};
|
||||
use windows_sys::Win32::UI::Shell::{DragFinish, DragQueryFileW, HDROP};
|
||||
|
||||
use tracing::debug;
|
||||
|
||||
use crate::platform_impl::platform::{
|
||||
definitions::{IDataObjectVtbl, IDropTarget, IDropTargetVtbl, IUnknownVtbl},
|
||||
WindowId,
|
||||
use crate::platform_impl::platform::definitions::{
|
||||
IDataObjectVtbl, IDropTarget, IDropTargetVtbl, IUnknownVtbl,
|
||||
};
|
||||
use crate::platform_impl::platform::WindowId;
|
||||
|
||||
use crate::{event::Event, window::WindowId as RootWindowId};
|
||||
use crate::event::Event;
|
||||
use crate::window::WindowId as RootWindowId;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FileDropHandlerData {
|
||||
|
|
@ -34,7 +27,8 @@ pub struct FileDropHandlerData {
|
|||
window: HWND,
|
||||
send_event: Box<dyn Fn(Event<()>)>,
|
||||
cursor_effect: u32,
|
||||
hovered_is_valid: bool, /* If the currently hovered item is not valid there must not be any `HoveredFileCancelled` emitted */
|
||||
hovered_is_valid: bool, /* If the currently hovered item is not valid there must not be any
|
||||
* `HoveredFileCancelled` emitted */
|
||||
}
|
||||
|
||||
pub struct FileDropHandler {
|
||||
|
|
@ -45,18 +39,14 @@ pub struct FileDropHandler {
|
|||
impl FileDropHandler {
|
||||
pub fn new(window: HWND, send_event: Box<dyn Fn(Event<()>)>) -> FileDropHandler {
|
||||
let data = Box::new(FileDropHandlerData {
|
||||
interface: IDropTarget {
|
||||
lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl,
|
||||
},
|
||||
interface: IDropTarget { lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl },
|
||||
refcount: AtomicUsize::new(1),
|
||||
window,
|
||||
send_event,
|
||||
cursor_effect: DROPEFFECT_NONE,
|
||||
hovered_is_valid: false,
|
||||
});
|
||||
FileDropHandler {
|
||||
data: Box::into_raw(data),
|
||||
}
|
||||
FileDropHandler { data: Box::into_raw(data) }
|
||||
}
|
||||
|
||||
// Implement IUnknown
|
||||
|
|
@ -104,11 +94,8 @@ impl FileDropHandler {
|
|||
})
|
||||
};
|
||||
drop_handler.hovered_is_valid = hdrop.is_some();
|
||||
drop_handler.cursor_effect = if drop_handler.hovered_is_valid {
|
||||
DROPEFFECT_COPY
|
||||
} else {
|
||||
DROPEFFECT_NONE
|
||||
};
|
||||
drop_handler.cursor_effect =
|
||||
if drop_handler.hovered_is_valid { DROPEFFECT_COPY } else { DROPEFFECT_NONE };
|
||||
unsafe {
|
||||
*pdwEffect = drop_handler.cursor_effect;
|
||||
}
|
||||
|
|
@ -190,7 +177,7 @@ impl FileDropHandler {
|
|||
let hdrop = unsafe { medium.u.hGlobal as HDROP };
|
||||
|
||||
// The second parameter (0xFFFFFFFF) instructs the function to return the item count
|
||||
let item_count = unsafe { DragQueryFileW(hdrop, 0xFFFFFFFF, ptr::null_mut(), 0) };
|
||||
let item_count = unsafe { DragQueryFileW(hdrop, 0xffffffff, ptr::null_mut(), 0) };
|
||||
|
||||
for i in 0..item_count {
|
||||
// Get the length of the path string NOT including the terminating null character.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,24 +1,18 @@
|
|||
use std::{
|
||||
any::Any,
|
||||
cell::{Cell, RefCell},
|
||||
collections::VecDeque,
|
||||
mem, panic,
|
||||
rc::Rc,
|
||||
sync::{Arc, Mutex},
|
||||
time::Instant,
|
||||
};
|
||||
use std::any::Any;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use std::{mem, panic};
|
||||
|
||||
use windows_sys::Win32::Foundation::HWND;
|
||||
|
||||
use crate::{
|
||||
dpi::PhysicalSize,
|
||||
event::{Event, InnerSizeWriter, StartCause, WindowEvent},
|
||||
platform_impl::platform::{
|
||||
event_loop::{WindowData, GWL_USERDATA},
|
||||
get_window_long,
|
||||
},
|
||||
window::WindowId,
|
||||
};
|
||||
use crate::dpi::PhysicalSize;
|
||||
use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent};
|
||||
use crate::platform_impl::platform::event_loop::{WindowData, GWL_USERDATA};
|
||||
use crate::platform_impl::platform::get_window_long;
|
||||
use crate::window::WindowId;
|
||||
|
||||
use super::ControlFlow;
|
||||
|
||||
|
|
@ -187,12 +181,12 @@ impl<T> EventLoopRunner<T> {
|
|||
Err(e) => {
|
||||
self.panic_error.set(Some(e));
|
||||
None
|
||||
}
|
||||
},
|
||||
},
|
||||
Some(e) => {
|
||||
self.panic_error.set(Some(e));
|
||||
None
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
self.panic_error.set(panic_error);
|
||||
|
|
@ -212,22 +206,16 @@ impl<T> EventLoopRunner<T> {
|
|||
}
|
||||
|
||||
pub(crate) fn send_event(&self, event: Event<T>) {
|
||||
if let Event::WindowEvent {
|
||||
event: WindowEvent::RedrawRequested,
|
||||
..
|
||||
} = event
|
||||
{
|
||||
if let Event::WindowEvent { event: WindowEvent::RedrawRequested, .. } = event {
|
||||
self.call_event_handler(event);
|
||||
// As a rule, to ensure that `pump_events` can't block an external event loop
|
||||
// for too long, we always guarantee that `pump_events` will return control to
|
||||
// the external loop asap after a `RedrawRequested` event is dispatched.
|
||||
self.interrupt_msg_dispatch.set(true);
|
||||
} else if self.should_buffer() {
|
||||
// If the runner is already borrowed, we're in the middle of an event loop invocation. Add
|
||||
// the event to a buffer to be processed later.
|
||||
self.event_buffer
|
||||
.borrow_mut()
|
||||
.push_back(BufferedEvent::from_event(event))
|
||||
// If the runner is already borrowed, we're in the middle of an event loop invocation.
|
||||
// Add the event to a buffer to be processed later.
|
||||
self.event_buffer.borrow_mut().push_back(BufferedEvent::from_event(event))
|
||||
} else {
|
||||
self.call_event_handler(event);
|
||||
self.dispatch_buffered_events();
|
||||
|
|
@ -240,8 +228,10 @@ impl<T> EventLoopRunner<T> {
|
|||
|
||||
fn call_event_handler(&self, event: Event<T>) {
|
||||
self.catch_unwind(|| {
|
||||
let mut event_handler = self.event_handler.take()
|
||||
.expect("either event handler is re-entrant (likely), or no event handler is registered (very unlikely)");
|
||||
let mut event_handler = self.event_handler.take().expect(
|
||||
"either event handler is re-entrant (likely), or no event handler is registered \
|
||||
(very unlikely)",
|
||||
);
|
||||
|
||||
event_handler(event);
|
||||
|
||||
|
|
@ -290,10 +280,7 @@ impl<T> EventLoopRunner<T> {
|
|||
fn move_state_to(&self, new_runner_state: RunnerState) {
|
||||
use RunnerState::{Destroyed, HandlingMainEvents, Idle, Uninitialized};
|
||||
|
||||
match (
|
||||
self.runner_state.replace(new_runner_state),
|
||||
new_runner_state,
|
||||
) {
|
||||
match (self.runner_state.replace(new_runner_state), new_runner_state) {
|
||||
(Uninitialized, Uninitialized)
|
||||
| (Idle, Idle)
|
||||
| (HandlingMainEvents, HandlingMainEvents)
|
||||
|
|
@ -302,38 +289,38 @@ impl<T> EventLoopRunner<T> {
|
|||
// State transitions that initialize the event loop.
|
||||
(Uninitialized, HandlingMainEvents) => {
|
||||
self.call_new_events(true);
|
||||
}
|
||||
},
|
||||
(Uninitialized, Idle) => {
|
||||
self.call_new_events(true);
|
||||
self.call_event_handler(Event::AboutToWait);
|
||||
self.last_events_cleared.set(Instant::now());
|
||||
}
|
||||
},
|
||||
(Uninitialized, Destroyed) => {
|
||||
self.call_new_events(true);
|
||||
self.call_event_handler(Event::AboutToWait);
|
||||
self.last_events_cleared.set(Instant::now());
|
||||
self.call_event_handler(Event::LoopExiting);
|
||||
}
|
||||
},
|
||||
(_, Uninitialized) => panic!("cannot move state to Uninitialized"),
|
||||
|
||||
// State transitions that start the event handling process.
|
||||
(Idle, HandlingMainEvents) => {
|
||||
self.call_new_events(false);
|
||||
}
|
||||
},
|
||||
(Idle, Destroyed) => {
|
||||
self.call_event_handler(Event::LoopExiting);
|
||||
}
|
||||
},
|
||||
|
||||
(HandlingMainEvents, Idle) => {
|
||||
// This is always the last event we dispatch before waiting for new events
|
||||
self.call_event_handler(Event::AboutToWait);
|
||||
self.last_events_cleared.set(Instant::now());
|
||||
}
|
||||
},
|
||||
(HandlingMainEvents, Destroyed) => {
|
||||
self.call_event_handler(Event::AboutToWait);
|
||||
self.last_events_cleared.set(Instant::now());
|
||||
self.call_event_handler(Event::LoopExiting);
|
||||
}
|
||||
},
|
||||
|
||||
(Destroyed, _) => panic!("cannot move state from Destroyed"),
|
||||
}
|
||||
|
|
@ -341,7 +328,7 @@ impl<T> EventLoopRunner<T> {
|
|||
|
||||
fn call_new_events(&self, init: bool) {
|
||||
let start_cause = match (init, self.control_flow(), self.exit.get()) {
|
||||
(true, _, _) => StartCause::Init,
|
||||
(true, ..) => StartCause::Init,
|
||||
(false, ControlFlow::Poll, None) => StartCause::Poll,
|
||||
(false, _, Some(_)) | (false, ControlFlow::Wait, None) => StartCause::WaitCancelled {
|
||||
requested_resume: None,
|
||||
|
|
@ -359,7 +346,7 @@ impl<T> EventLoopRunner<T> {
|
|||
start: self.last_events_cleared.get(),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
self.call_event_handler(Event::NewEvents(start_cause));
|
||||
// NB: For consistency all platforms must emit a 'resumed' event even though Windows
|
||||
|
|
@ -375,21 +362,12 @@ impl<T> BufferedEvent<T> {
|
|||
pub fn from_event(event: Event<T>) -> BufferedEvent<T> {
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
event:
|
||||
WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
inner_size_writer,
|
||||
},
|
||||
event: WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer },
|
||||
window_id,
|
||||
} => BufferedEvent::ScaleFactorChanged(
|
||||
window_id,
|
||||
scale_factor,
|
||||
*inner_size_writer
|
||||
.new_inner_size
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap(),
|
||||
*inner_size_writer.new_inner_size.upgrade().unwrap().lock().unwrap(),
|
||||
),
|
||||
event => BufferedEvent::Event(event),
|
||||
}
|
||||
|
|
@ -422,7 +400,7 @@ impl<T> BufferedEvent<T> {
|
|||
|
||||
window_flags.set_size((window_id.0).0, inner_size);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,22 @@
|
|||
use std::{ffi::c_void, fmt, io, mem, path::Path, sync::Arc};
|
||||
use std::ffi::c_void;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, io, mem};
|
||||
|
||||
use cursor_icon::CursorIcon;
|
||||
use windows_sys::{
|
||||
core::PCWSTR,
|
||||
Win32::{
|
||||
Foundation::HWND,
|
||||
Graphics::Gdi::{
|
||||
CreateBitmap, CreateCompatibleBitmap, DeleteObject, GetDC, ReleaseDC, SetBitmapBits,
|
||||
},
|
||||
UI::WindowsAndMessaging::{
|
||||
CreateIcon, CreateIconIndirect, DestroyCursor, DestroyIcon, LoadImageW, SendMessageW,
|
||||
HCURSOR, HICON, ICONINFO, ICON_BIG, ICON_SMALL, IMAGE_ICON, LR_DEFAULTSIZE,
|
||||
LR_LOADFROMFILE, WM_SETICON,
|
||||
},
|
||||
},
|
||||
use windows_sys::core::PCWSTR;
|
||||
use windows_sys::Win32::Foundation::HWND;
|
||||
use windows_sys::Win32::Graphics::Gdi::{
|
||||
CreateBitmap, CreateCompatibleBitmap, DeleteObject, GetDC, ReleaseDC, SetBitmapBits,
|
||||
};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
CreateIcon, CreateIconIndirect, DestroyCursor, DestroyIcon, LoadImageW, SendMessageW, HCURSOR,
|
||||
HICON, ICONINFO, ICON_BIG, ICON_SMALL, IMAGE_ICON, LR_DEFAULTSIZE, LR_LOADFROMFILE, WM_SETICON,
|
||||
};
|
||||
|
||||
use crate::cursor::CursorImage;
|
||||
use crate::dpi::PhysicalSize;
|
||||
use crate::icon::*;
|
||||
use crate::{cursor::CursorImage, dpi::PhysicalSize};
|
||||
|
||||
use super::util;
|
||||
|
||||
|
|
@ -142,9 +141,7 @@ impl WinIcon {
|
|||
}
|
||||
|
||||
fn from_handle(handle: HICON) -> Self {
|
||||
Self {
|
||||
inner: Arc::new(RaiiIcon { handle }),
|
||||
}
|
||||
Self { inner: Arc::new(RaiiIcon { handle }) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,19 @@
|
|||
use std::{
|
||||
ffi::{c_void, OsString},
|
||||
os::windows::prelude::OsStringExt,
|
||||
ptr::null_mut,
|
||||
};
|
||||
use std::ffi::{c_void, OsString};
|
||||
use std::os::windows::prelude::OsStringExt;
|
||||
use std::ptr::null_mut;
|
||||
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{POINT, RECT},
|
||||
Globalization::HIMC,
|
||||
UI::{
|
||||
Input::Ime::{
|
||||
ImmAssociateContextEx, ImmGetCompositionStringW, ImmGetContext, ImmReleaseContext,
|
||||
ImmSetCandidateWindow, ImmSetCompositionWindow, ATTR_TARGET_CONVERTED,
|
||||
ATTR_TARGET_NOTCONVERTED, CANDIDATEFORM, CFS_EXCLUDE, CFS_POINT, COMPOSITIONFORM,
|
||||
GCS_COMPATTR, GCS_COMPSTR, GCS_CURSORPOS, GCS_RESULTSTR, IACE_CHILDREN, IACE_DEFAULT,
|
||||
},
|
||||
WindowsAndMessaging::{GetSystemMetrics, SM_IMMENABLED},
|
||||
},
|
||||
use windows_sys::Win32::Foundation::{POINT, RECT};
|
||||
use windows_sys::Win32::Globalization::HIMC;
|
||||
use windows_sys::Win32::UI::Input::Ime::{
|
||||
ImmAssociateContextEx, ImmGetCompositionStringW, ImmGetContext, ImmReleaseContext,
|
||||
ImmSetCandidateWindow, ImmSetCompositionWindow, ATTR_TARGET_CONVERTED,
|
||||
ATTR_TARGET_NOTCONVERTED, CANDIDATEFORM, CFS_EXCLUDE, CFS_POINT, COMPOSITIONFORM, GCS_COMPATTR,
|
||||
GCS_COMPSTR, GCS_CURSORPOS, GCS_RESULTSTR, IACE_CHILDREN, IACE_DEFAULT,
|
||||
};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{GetSystemMetrics, SM_IMMENABLED};
|
||||
|
||||
use crate::{
|
||||
dpi::{Position, Size},
|
||||
platform::windows::HWND,
|
||||
};
|
||||
use crate::dpi::{Position, Size};
|
||||
use crate::platform::windows::HWND;
|
||||
|
||||
pub struct ImeContext {
|
||||
hwnd: HWND,
|
||||
|
|
@ -60,7 +52,8 @@ impl ImeContext {
|
|||
if first.is_some() && last.is_none() {
|
||||
last = Some(text.len());
|
||||
} else if first.is_none() {
|
||||
// IME haven't split words and select any clause yet, so trying to retrieve normal cursor.
|
||||
// IME haven't split words and select any clause yet, so trying to retrieve normal
|
||||
// cursor.
|
||||
let cursor = unsafe { self.get_composition_cursor(&text) };
|
||||
first = cursor;
|
||||
last = cursor;
|
||||
|
|
@ -120,12 +113,7 @@ impl ImeContext {
|
|||
|
||||
let (x, y) = spot.to_physical::<i32>(scale_factor).into();
|
||||
let (width, height): (i32, i32) = size.to_physical::<i32>(scale_factor).into();
|
||||
let rc_area = RECT {
|
||||
left: x,
|
||||
top: y,
|
||||
right: x + width,
|
||||
bottom: y + height,
|
||||
};
|
||||
let rc_area = RECT { left: x, top: y, right: x + width, bottom: y + height };
|
||||
let candidate_form = CANDIDATEFORM {
|
||||
dwIndex: 0,
|
||||
dwStyle: CFS_EXCLUDE,
|
||||
|
|
|
|||
|
|
@ -1,50 +1,39 @@
|
|||
use std::{
|
||||
char,
|
||||
ffi::OsString,
|
||||
mem::MaybeUninit,
|
||||
os::windows::ffi::OsStringExt,
|
||||
sync::{
|
||||
atomic::{AtomicU32, Ordering::Relaxed},
|
||||
Mutex, MutexGuard,
|
||||
},
|
||||
};
|
||||
use std::char;
|
||||
use std::ffi::OsString;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{HWND, LPARAM, WPARAM},
|
||||
System::SystemServices::LANG_KOREAN,
|
||||
UI::{
|
||||
Input::KeyboardAndMouse::{
|
||||
GetAsyncKeyState, GetKeyState, GetKeyboardLayout, GetKeyboardState, MapVirtualKeyExW,
|
||||
MAPVK_VK_TO_VSC_EX, MAPVK_VSC_TO_VK_EX, VIRTUAL_KEY, VK_ABNT_C2, VK_ADD, VK_CAPITAL,
|
||||
VK_CLEAR, VK_CONTROL, VK_DECIMAL, VK_DELETE, VK_DIVIDE, VK_DOWN, VK_END, VK_F4,
|
||||
VK_HOME, VK_INSERT, VK_LCONTROL, VK_LEFT, VK_LMENU, VK_LSHIFT, VK_LWIN, VK_MENU,
|
||||
VK_MULTIPLY, VK_NEXT, VK_NUMLOCK, VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
|
||||
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_PRIOR,
|
||||
VK_RCONTROL, VK_RETURN, VK_RIGHT, VK_RMENU, VK_RSHIFT, VK_RWIN, VK_SCROLL, VK_SHIFT,
|
||||
VK_SUBTRACT, VK_UP,
|
||||
},
|
||||
TextServices::HKL,
|
||||
WindowsAndMessaging::{
|
||||
PeekMessageW, MSG, PM_NOREMOVE, WM_CHAR, WM_DEADCHAR, WM_KEYDOWN, WM_KEYFIRST,
|
||||
WM_KEYLAST, WM_KEYUP, WM_KILLFOCUS, WM_SETFOCUS, WM_SYSCHAR, WM_SYSDEADCHAR,
|
||||
WM_SYSKEYDOWN, WM_SYSKEYUP,
|
||||
},
|
||||
},
|
||||
use windows_sys::Win32::Foundation::{HWND, LPARAM, WPARAM};
|
||||
use windows_sys::Win32::System::SystemServices::LANG_KOREAN;
|
||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::{
|
||||
GetAsyncKeyState, GetKeyState, GetKeyboardLayout, GetKeyboardState, MapVirtualKeyExW,
|
||||
MAPVK_VK_TO_VSC_EX, MAPVK_VSC_TO_VK_EX, VIRTUAL_KEY, VK_ABNT_C2, VK_ADD, VK_CAPITAL, VK_CLEAR,
|
||||
VK_CONTROL, VK_DECIMAL, VK_DELETE, VK_DIVIDE, VK_DOWN, VK_END, VK_F4, VK_HOME, VK_INSERT,
|
||||
VK_LCONTROL, VK_LEFT, VK_LMENU, VK_LSHIFT, VK_LWIN, VK_MENU, VK_MULTIPLY, VK_NEXT, VK_NUMLOCK,
|
||||
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
|
||||
VK_NUMPAD8, VK_NUMPAD9, VK_PRIOR, VK_RCONTROL, VK_RETURN, VK_RIGHT, VK_RMENU, VK_RSHIFT,
|
||||
VK_RWIN, VK_SCROLL, VK_SHIFT, VK_SUBTRACT, VK_UP,
|
||||
};
|
||||
use windows_sys::Win32::UI::TextServices::HKL;
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
PeekMessageW, MSG, PM_NOREMOVE, WM_CHAR, WM_DEADCHAR, WM_KEYDOWN, WM_KEYFIRST, WM_KEYLAST,
|
||||
WM_KEYUP, WM_KILLFOCUS, WM_SETFOCUS, WM_SYSCHAR, WM_SYSDEADCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
|
||||
};
|
||||
|
||||
use smol_str::SmolStr;
|
||||
use tracing::{trace, warn};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::{
|
||||
event::{ElementState, KeyEvent},
|
||||
keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey},
|
||||
platform_impl::platform::{
|
||||
event_loop::ProcResult,
|
||||
keyboard_layout::{Layout, LayoutCache, WindowsModifiers, LAYOUT_CACHE},
|
||||
loword, primarylangid, KeyEventExtra,
|
||||
},
|
||||
use crate::event::{ElementState, KeyEvent};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey};
|
||||
use crate::platform_impl::platform::event_loop::ProcResult;
|
||||
use crate::platform_impl::platform::keyboard_layout::{
|
||||
Layout, LayoutCache, WindowsModifiers, LAYOUT_CACHE,
|
||||
};
|
||||
use crate::platform_impl::platform::{loword, primarylangid, KeyEventExtra};
|
||||
|
||||
pub type ExScancode = u16;
|
||||
|
||||
|
|
@ -60,16 +49,16 @@ pub struct MessageAsKeyEvent {
|
|||
/// window message. Therefore, this type keeps track of certain information from previous events so
|
||||
/// that a `KeyEvent` can be constructed when the last event related to a keypress is received.
|
||||
///
|
||||
/// `PeekMessage` is sometimes used to determine whether the next window message still belongs to the
|
||||
/// current keypress. If it doesn't and the current state represents a key event waiting to be
|
||||
/// `PeekMessage` is sometimes used to determine whether the next window message still belongs to
|
||||
/// the current keypress. If it doesn't and the current state represents a key event waiting to be
|
||||
/// dispatched, then said event is considered complete and is dispatched.
|
||||
///
|
||||
/// The sequence of window messages for a key press event is the following:
|
||||
/// - Exactly one WM_KEYDOWN / WM_SYSKEYDOWN
|
||||
/// - Zero or one WM_DEADCHAR / WM_SYSDEADCHAR
|
||||
/// - Zero or more WM_CHAR / WM_SYSCHAR. These messages each come with a UTF-16 code unit which when
|
||||
/// put together in the sequence they arrived in, forms the text which is the result of pressing the
|
||||
/// key.
|
||||
/// put together in the sequence they arrived in, forms the text which is the result of pressing
|
||||
/// the key.
|
||||
///
|
||||
/// Key release messages are a bit different due to the fact that they don't contribute to
|
||||
/// text input. The "sequence" only consists of one WM_KEYUP / WM_SYSKEYUP event.
|
||||
|
|
@ -79,10 +68,7 @@ pub struct KeyEventBuilder {
|
|||
}
|
||||
impl Default for KeyEventBuilder {
|
||||
fn default() -> Self {
|
||||
KeyEventBuilder {
|
||||
event_info: Mutex::new(None),
|
||||
pending: Default::default(),
|
||||
}
|
||||
KeyEventBuilder { event_info: Mutex::new(None), pending: Default::default() }
|
||||
}
|
||||
}
|
||||
impl KeyEventBuilder {
|
||||
|
|
@ -110,13 +96,13 @@ impl KeyEventBuilder {
|
|||
let kbd_state = get_async_kbd_state();
|
||||
let key_events = Self::synthesize_kbd_state(ElementState::Pressed, &kbd_state);
|
||||
MatchResult::MessagesToDispatch(self.pending.complete_multi(key_events))
|
||||
}
|
||||
},
|
||||
WM_KILLFOCUS => {
|
||||
// sythesize keyup events
|
||||
let kbd_state = get_kbd_state();
|
||||
let key_events = Self::synthesize_kbd_state(ElementState::Released, &kbd_state);
|
||||
MatchResult::MessagesToDispatch(self.pending.complete_multi(key_events))
|
||||
}
|
||||
},
|
||||
WM_KEYDOWN | WM_SYSKEYDOWN => {
|
||||
if msg_kind == WM_SYSKEYDOWN && wparam as VIRTUAL_KEY == VK_F4 {
|
||||
// Don't dispatch Alt+F4 to the application.
|
||||
|
|
@ -162,39 +148,36 @@ impl KeyEventBuilder {
|
|||
let ev = event_info.finalize();
|
||||
return MatchResult::MessagesToDispatch(self.pending.complete_pending(
|
||||
pending_token,
|
||||
MessageAsKeyEvent {
|
||||
event: ev,
|
||||
is_synthetic: false,
|
||||
},
|
||||
MessageAsKeyEvent { event: ev, is_synthetic: false },
|
||||
));
|
||||
}
|
||||
MatchResult::TokenToRemove(pending_token)
|
||||
}
|
||||
},
|
||||
WM_DEADCHAR | WM_SYSDEADCHAR => {
|
||||
let pending_token = self.pending.add_pending();
|
||||
*result = ProcResult::Value(0);
|
||||
// At this point, we know that there isn't going to be any more events related to
|
||||
// this key press
|
||||
// At this point, we know that there isn't going to be any more events related
|
||||
// to this key press
|
||||
let event_info = self.event_info.lock().unwrap().take().unwrap();
|
||||
let ev = event_info.finalize();
|
||||
MatchResult::MessagesToDispatch(self.pending.complete_pending(
|
||||
pending_token,
|
||||
MessageAsKeyEvent {
|
||||
event: ev,
|
||||
is_synthetic: false,
|
||||
},
|
||||
MessageAsKeyEvent { event: ev, is_synthetic: false },
|
||||
))
|
||||
}
|
||||
},
|
||||
WM_CHAR | WM_SYSCHAR => {
|
||||
let mut event_info = self.event_info.lock().unwrap();
|
||||
if event_info.is_none() {
|
||||
trace!("Received a CHAR message but no `event_info` was available. The message is probably IME, returning.");
|
||||
trace!(
|
||||
"Received a CHAR message but no `event_info` was available. The \
|
||||
message is probably IME, returning."
|
||||
);
|
||||
return MatchResult::Nothing;
|
||||
}
|
||||
let pending_token = self.pending.add_pending();
|
||||
*result = ProcResult::Value(0);
|
||||
let is_high_surrogate = (0xD800..=0xDBFF).contains(&wparam);
|
||||
let is_low_surrogate = (0xDC00..=0xDFFF).contains(&wparam);
|
||||
let is_high_surrogate = (0xd800..=0xdbff).contains(&wparam);
|
||||
let is_low_surrogate = (0xdc00..=0xdfff).contains(&wparam);
|
||||
|
||||
let is_utf16 = is_high_surrogate || is_low_surrogate;
|
||||
|
||||
|
|
@ -210,7 +193,7 @@ impl KeyEventBuilder {
|
|||
None => {
|
||||
warn!("The event_info was None when it was expected to be some");
|
||||
return MatchResult::TokenToRemove(pending_token);
|
||||
}
|
||||
},
|
||||
};
|
||||
let start_offset = utf16parts.len();
|
||||
let new_size = utf16parts.len() + 2;
|
||||
|
|
@ -221,16 +204,17 @@ impl KeyEventBuilder {
|
|||
utf16parts.resize(new_size, 0);
|
||||
}
|
||||
}
|
||||
// It's important that we unlock the mutex, and create the pending event token before
|
||||
// calling `next_msg`
|
||||
// It's important that we unlock the mutex, and create the pending event token
|
||||
// before calling `next_msg`
|
||||
std::mem::drop(event_info);
|
||||
let next_msg = next_kbd_msg(hwnd);
|
||||
let more_char_coming = next_msg
|
||||
.map(|m| matches!(m.message, WM_CHAR | WM_SYSCHAR))
|
||||
.unwrap_or(false);
|
||||
if more_char_coming {
|
||||
// No need to produce an event just yet, because there are still more characters that
|
||||
// need to appended to this keyobard event
|
||||
// No need to produce an event just yet, because there are still more
|
||||
// characters that need to appended to this keyobard
|
||||
// event
|
||||
MatchResult::TokenToRemove(pending_token)
|
||||
} else {
|
||||
let mut event_info = self.event_info.lock().unwrap();
|
||||
|
|
@ -239,7 +223,7 @@ impl KeyEventBuilder {
|
|||
None => {
|
||||
warn!("The event_info was None when it was expected to be some");
|
||||
return MatchResult::TokenToRemove(pending_token);
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut layouts = LAYOUT_CACHE.lock().unwrap();
|
||||
// It's okay to call `ToUnicode` here, because at this point the dead key
|
||||
|
|
@ -271,13 +255,10 @@ impl KeyEventBuilder {
|
|||
let ev = event_info.finalize();
|
||||
MatchResult::MessagesToDispatch(self.pending.complete_pending(
|
||||
pending_token,
|
||||
MessageAsKeyEvent {
|
||||
event: ev,
|
||||
is_synthetic: false,
|
||||
},
|
||||
MessageAsKeyEvent { event: ev, is_synthetic: false },
|
||||
))
|
||||
}
|
||||
}
|
||||
},
|
||||
WM_KEYUP | WM_SYSKEYUP => {
|
||||
let pending_token = self.pending.add_pending();
|
||||
*result = ProcResult::Value(0);
|
||||
|
|
@ -289,9 +270,11 @@ impl KeyEventBuilder {
|
|||
ElementState::Released,
|
||||
&mut layouts,
|
||||
);
|
||||
// We MUST release the layout lock before calling `next_kbd_msg`, otherwise it may deadlock
|
||||
// We MUST release the layout lock before calling `next_kbd_msg`, otherwise it
|
||||
// may deadlock
|
||||
drop(layouts);
|
||||
// It's important that we create the pending token before reading the next message.
|
||||
// It's important that we create the pending token before reading the next
|
||||
// message.
|
||||
let next_msg = next_kbd_msg(hwnd);
|
||||
let mut valid_event_info = Some(event_info);
|
||||
if let Some(next_msg) = next_msg {
|
||||
|
|
@ -309,14 +292,11 @@ impl KeyEventBuilder {
|
|||
let event = event_info.finalize();
|
||||
return MatchResult::MessagesToDispatch(self.pending.complete_pending(
|
||||
pending_token,
|
||||
MessageAsKeyEvent {
|
||||
event,
|
||||
is_synthetic: false,
|
||||
},
|
||||
MessageAsKeyEvent { event, is_synthetic: false },
|
||||
));
|
||||
}
|
||||
MatchResult::TokenToRemove(pending_token)
|
||||
}
|
||||
},
|
||||
_ => MatchResult::Nothing,
|
||||
}
|
||||
};
|
||||
|
|
@ -352,12 +332,11 @@ impl KeyEventBuilder {
|
|||
let num_lock_on = kbd_state[VK_NUMLOCK as usize] & 1 != 0;
|
||||
|
||||
// We are synthesizing the press event for caps-lock first for the following reasons:
|
||||
// 1. If caps-lock is *not* held down but *is* active, then we have to
|
||||
// synthesize all printable keys, respecting the caps-lock state.
|
||||
// 2. If caps-lock is held down, we could choose to sythesize its
|
||||
// keypress after every other key, in which case all other keys *must*
|
||||
// be sythesized as if the caps-lock state was be the opposite
|
||||
// of what it currently is.
|
||||
// 1. If caps-lock is *not* held down but *is* active, then we have to synthesize all
|
||||
// printable keys, respecting the caps-lock state.
|
||||
// 2. If caps-lock is held down, we could choose to sythesize its keypress after every other
|
||||
// key, in which case all other keys *must* be sythesized as if the caps-lock state was
|
||||
// be the opposite of what it currently is.
|
||||
// --
|
||||
// For the sake of simplicity we are choosing to always sythesize
|
||||
// caps-lock first, and always use the current caps-lock state
|
||||
|
|
@ -399,14 +378,8 @@ impl KeyEventBuilder {
|
|||
}
|
||||
};
|
||||
let do_modifier = |key_events: &mut Vec<_>, layouts: &mut _| {
|
||||
const CLEAR_MODIFIER_VKS: [VIRTUAL_KEY; 6] = [
|
||||
VK_LCONTROL,
|
||||
VK_LSHIFT,
|
||||
VK_LMENU,
|
||||
VK_RCONTROL,
|
||||
VK_RSHIFT,
|
||||
VK_RMENU,
|
||||
];
|
||||
const CLEAR_MODIFIER_VKS: [VIRTUAL_KEY; 6] =
|
||||
[VK_LCONTROL, VK_LSHIFT, VK_LMENU, VK_RCONTROL, VK_RSHIFT, VK_RMENU];
|
||||
for vk in CLEAR_MODIFIER_VKS.iter() {
|
||||
if is_key_pressed!(*vk) {
|
||||
let event = Self::create_synthetic(
|
||||
|
|
@ -431,11 +404,11 @@ impl KeyEventBuilder {
|
|||
ElementState::Pressed => {
|
||||
do_non_modifier(&mut key_events, &mut layouts);
|
||||
do_modifier(&mut key_events, &mut layouts);
|
||||
}
|
||||
},
|
||||
ElementState::Released => {
|
||||
do_modifier(&mut key_events, &mut layouts);
|
||||
do_non_modifier(&mut key_events, &mut layouts);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
key_events
|
||||
|
|
@ -455,11 +428,8 @@ impl KeyEventBuilder {
|
|||
}
|
||||
let scancode = scancode as ExScancode;
|
||||
let physical_key = scancode_to_physicalkey(scancode as u32);
|
||||
let mods = if caps_lock_on {
|
||||
WindowsModifiers::CAPS_LOCK
|
||||
} else {
|
||||
WindowsModifiers::empty()
|
||||
};
|
||||
let mods =
|
||||
if caps_lock_on { WindowsModifiers::CAPS_LOCK } else { WindowsModifiers::empty() };
|
||||
let layout = layouts.layouts.get(&(locale_id as u64)).unwrap();
|
||||
let logical_key = layout.get_key(mods, num_lock_on, vk, &physical_key);
|
||||
let key_without_modifiers =
|
||||
|
|
@ -484,10 +454,7 @@ impl KeyEventBuilder {
|
|||
let mut event = event_info.finalize();
|
||||
event.logical_key = logical_key;
|
||||
event.platform_specific.text_with_all_modifiers = text;
|
||||
Some(MessageAsKeyEvent {
|
||||
event,
|
||||
is_synthetic: true,
|
||||
})
|
||||
Some(MessageAsKeyEvent { event, is_synthetic: true })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -600,7 +567,7 @@ impl PartialKeyEventInfo {
|
|||
} else {
|
||||
Key::Unidentified(NativeKey::Unidentified)
|
||||
}
|
||||
}
|
||||
},
|
||||
key => key,
|
||||
}
|
||||
};
|
||||
|
|
@ -637,10 +604,10 @@ impl PartialKeyEventInfo {
|
|||
text = Some(SmolStr::new(string));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
PartialText::Text(s) => {
|
||||
text = s.map(SmolStr::new);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
let logical_key = match self.logical_key {
|
||||
|
|
@ -651,7 +618,7 @@ impl PartialKeyEventInfo {
|
|||
} else {
|
||||
Key::Character(s.clone())
|
||||
}
|
||||
}
|
||||
},
|
||||
None => Key::Unidentified(NativeKey::Windows(self.vkey)),
|
||||
},
|
||||
PartialLogicalKey::This(v) => v,
|
||||
|
|
@ -677,7 +644,8 @@ struct KeyLParam {
|
|||
pub scancode: u8,
|
||||
pub extended: bool,
|
||||
|
||||
/// This is `previous_state XOR transition_state`. See the lParam for WM_KEYDOWN and WM_KEYUP for further details.
|
||||
/// This is `previous_state XOR transition_state`. See the lParam for WM_KEYDOWN and WM_KEYUP
|
||||
/// for further details.
|
||||
pub is_repeat: bool,
|
||||
}
|
||||
|
||||
|
|
@ -685,7 +653,7 @@ fn destructure_key_lparam(lparam: LPARAM) -> KeyLParam {
|
|||
let previous_state = (lparam >> 30) & 0x01;
|
||||
let transition_state = (lparam >> 31) & 0x01;
|
||||
KeyLParam {
|
||||
scancode: ((lparam >> 16) & 0xFF) as u8,
|
||||
scancode: ((lparam >> 16) & 0xff) as u8,
|
||||
extended: ((lparam >> 24) & 0x01) != 0,
|
||||
is_repeat: (previous_state ^ transition_state) != 0,
|
||||
}
|
||||
|
|
@ -693,7 +661,7 @@ fn destructure_key_lparam(lparam: LPARAM) -> KeyLParam {
|
|||
|
||||
#[inline]
|
||||
fn new_ex_scancode(scancode: u8, extended: bool) -> ExScancode {
|
||||
(scancode as u16) | (if extended { 0xE000 } else { 0 })
|
||||
(scancode as u16) | (if extended { 0xe000 } else { 0 })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -742,13 +710,11 @@ fn get_async_kbd_state() -> [u8; 256] {
|
|||
/// the next event is a right Alt (AltGr) event. If this is the case, the current event must be the
|
||||
/// fake Ctrl event.
|
||||
fn is_current_fake(curr_info: &PartialKeyEventInfo, next_msg: MSG, layout: &Layout) -> bool {
|
||||
let curr_is_ctrl = matches!(
|
||||
curr_info.logical_key,
|
||||
PartialLogicalKey::This(Key::Named(NamedKey::Control))
|
||||
);
|
||||
let curr_is_ctrl =
|
||||
matches!(curr_info.logical_key, PartialLogicalKey::This(Key::Named(NamedKey::Control)));
|
||||
if layout.has_alt_graph {
|
||||
let next_code = ex_scancode_from_lparam(next_msg.lParam);
|
||||
let next_is_altgr = next_code == 0xE038; // 0xE038 is right alt
|
||||
let next_is_altgr = next_code == 0xe038; // 0xE038 is right alt
|
||||
if curr_is_ctrl && next_is_altgr {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -792,10 +758,7 @@ impl<T> PendingEventQueue<T> {
|
|||
pub fn add_pending(&self) -> PendingMessageToken {
|
||||
let token = self.next_token();
|
||||
let mut pending = self.pending.lock().unwrap();
|
||||
pending.push(IdentifiedPendingMessage {
|
||||
token,
|
||||
msg: PendingMessage::Incomplete,
|
||||
});
|
||||
pending.push(IdentifiedPendingMessage { token, msg: PendingMessage::Incomplete });
|
||||
token
|
||||
}
|
||||
|
||||
|
|
@ -862,15 +825,20 @@ impl<T> PendingEventQueue<T> {
|
|||
}
|
||||
|
||||
fn drain_pending(pending: &mut Vec<IdentifiedPendingMessage<T>>) -> Vec<T> {
|
||||
pending.drain(..).map(|m| {
|
||||
match m.msg {
|
||||
pending
|
||||
.drain(..)
|
||||
.map(|m| match m.msg {
|
||||
PendingMessage::Complete(msg) => msg,
|
||||
PendingMessage::Incomplete => {
|
||||
panic!("Found an incomplete pending message when collecting messages. This indicates a bug in winit.")
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
panic!(
|
||||
"Found an incomplete pending message when collecting messages. This \
|
||||
indicates a bug in winit."
|
||||
)
|
||||
},
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn next_token(&self) -> PendingMessageToken {
|
||||
// It's okay for the u32 to overflow here. Yes, that could mean
|
||||
// that two different messages have the same token,
|
||||
|
|
@ -884,10 +852,7 @@ impl<T> PendingEventQueue<T> {
|
|||
}
|
||||
impl<T> Default for PendingEventQueue<T> {
|
||||
fn default() -> Self {
|
||||
PendingEventQueue {
|
||||
pending: Mutex::new(Vec::new()),
|
||||
next_id: AtomicU32::new(0),
|
||||
}
|
||||
PendingEventQueue { pending: Mutex::new(Vec::new()), next_id: AtomicU32::new(0) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -902,13 +867,8 @@ impl<T> Default for PendingEventQueue<T> {
|
|||
pub fn next_kbd_msg(hwnd: HWND) -> Option<MSG> {
|
||||
unsafe {
|
||||
let mut next_msg = MaybeUninit::uninit();
|
||||
let peek_retval = PeekMessageW(
|
||||
next_msg.as_mut_ptr(),
|
||||
hwnd,
|
||||
WM_KEYFIRST,
|
||||
WM_KEYLAST,
|
||||
PM_NOREMOVE,
|
||||
);
|
||||
let peek_retval =
|
||||
PeekMessageW(next_msg.as_mut_ptr(), hwnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE);
|
||||
(peek_retval != 0).then(|| next_msg.assume_init())
|
||||
}
|
||||
}
|
||||
|
|
@ -916,7 +876,7 @@ pub fn next_kbd_msg(hwnd: HWND) -> Option<MSG> {
|
|||
fn get_location(scancode: ExScancode, hkl: HKL) -> KeyLocation {
|
||||
const ABNT_C2: VIRTUAL_KEY = VK_ABNT_C2 as VIRTUAL_KEY;
|
||||
|
||||
let extension = 0xE000;
|
||||
let extension = 0xe000;
|
||||
let extended = (scancode & extension) == extension;
|
||||
let vkey = unsafe { MapVirtualKeyExW(scancode as u32, MAPVK_VSC_TO_VK_EX, hkl) as VIRTUAL_KEY };
|
||||
|
||||
|
|
@ -934,7 +894,7 @@ fn get_location(scancode: ExScancode, hkl: HKL) -> KeyLocation {
|
|||
} else {
|
||||
KeyLocation::Numpad
|
||||
}
|
||||
}
|
||||
},
|
||||
VK_NUMPAD0 | VK_NUMPAD1 | VK_NUMPAD2 | VK_NUMPAD3 | VK_NUMPAD4 | VK_NUMPAD5
|
||||
| VK_NUMPAD6 | VK_NUMPAD7 | VK_NUMPAD8 | VK_NUMPAD9 | VK_DECIMAL | VK_DIVIDE
|
||||
| VK_MULTIPLY | VK_SUBTRACT | VK_ADD | ABNT_C2 => KeyLocation::Numpad,
|
||||
|
|
@ -957,17 +917,17 @@ pub(crate) fn physicalkey_to_scancode(physical_key: PhysicalKey) -> Option<u32>
|
|||
NativeKeyCode::Windows(scancode) => Some(scancode as u32),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
match code {
|
||||
KeyCode::Backquote => Some(0x0029),
|
||||
KeyCode::Backslash => Some(0x002B),
|
||||
KeyCode::Backspace => Some(0x000E),
|
||||
KeyCode::BracketLeft => Some(0x001A),
|
||||
KeyCode::BracketRight => Some(0x001B),
|
||||
KeyCode::Backslash => Some(0x002b),
|
||||
KeyCode::Backspace => Some(0x000e),
|
||||
KeyCode::BracketLeft => Some(0x001a),
|
||||
KeyCode::BracketRight => Some(0x001b),
|
||||
KeyCode::Comma => Some(0x0033),
|
||||
KeyCode::Digit0 => Some(0x000B),
|
||||
KeyCode::Digit0 => Some(0x000b),
|
||||
KeyCode::Digit1 => Some(0x0002),
|
||||
KeyCode::Digit2 => Some(0x0003),
|
||||
KeyCode::Digit3 => Some(0x0004),
|
||||
|
|
@ -976,14 +936,14 @@ pub(crate) fn physicalkey_to_scancode(physical_key: PhysicalKey) -> Option<u32>
|
|||
KeyCode::Digit6 => Some(0x0007),
|
||||
KeyCode::Digit7 => Some(0x0008),
|
||||
KeyCode::Digit8 => Some(0x0009),
|
||||
KeyCode::Digit9 => Some(0x000A),
|
||||
KeyCode::Equal => Some(0x000D),
|
||||
KeyCode::Digit9 => Some(0x000a),
|
||||
KeyCode::Equal => Some(0x000d),
|
||||
KeyCode::IntlBackslash => Some(0x0056),
|
||||
KeyCode::IntlRo => Some(0x0073),
|
||||
KeyCode::IntlYen => Some(0x007D),
|
||||
KeyCode::KeyA => Some(0x001E),
|
||||
KeyCode::IntlYen => Some(0x007d),
|
||||
KeyCode::KeyA => Some(0x001e),
|
||||
KeyCode::KeyB => Some(0x0030),
|
||||
KeyCode::KeyC => Some(0x002E),
|
||||
KeyCode::KeyC => Some(0x002e),
|
||||
KeyCode::KeyD => Some(0x0020),
|
||||
KeyCode::KeyE => Some(0x0012),
|
||||
KeyCode::KeyF => Some(0x0021),
|
||||
|
|
@ -999,84 +959,84 @@ pub(crate) fn physicalkey_to_scancode(physical_key: PhysicalKey) -> Option<u32>
|
|||
KeyCode::KeyP => Some(0x0019),
|
||||
KeyCode::KeyQ => Some(0x0010),
|
||||
KeyCode::KeyR => Some(0x0013),
|
||||
KeyCode::KeyS => Some(0x001F),
|
||||
KeyCode::KeyS => Some(0x001f),
|
||||
KeyCode::KeyT => Some(0x0014),
|
||||
KeyCode::KeyU => Some(0x0016),
|
||||
KeyCode::KeyV => Some(0x002F),
|
||||
KeyCode::KeyV => Some(0x002f),
|
||||
KeyCode::KeyW => Some(0x0011),
|
||||
KeyCode::KeyX => Some(0x002D),
|
||||
KeyCode::KeyX => Some(0x002d),
|
||||
KeyCode::KeyY => Some(0x0015),
|
||||
KeyCode::KeyZ => Some(0x002C),
|
||||
KeyCode::Minus => Some(0x000C),
|
||||
KeyCode::KeyZ => Some(0x002c),
|
||||
KeyCode::Minus => Some(0x000c),
|
||||
KeyCode::Period => Some(0x0034),
|
||||
KeyCode::Quote => Some(0x0028),
|
||||
KeyCode::Semicolon => Some(0x0027),
|
||||
KeyCode::Slash => Some(0x0035),
|
||||
KeyCode::AltLeft => Some(0x0038),
|
||||
KeyCode::AltRight => Some(0xE038),
|
||||
KeyCode::CapsLock => Some(0x003A),
|
||||
KeyCode::ContextMenu => Some(0xE05D),
|
||||
KeyCode::ControlLeft => Some(0x001D),
|
||||
KeyCode::ControlRight => Some(0xE01D),
|
||||
KeyCode::Enter => Some(0x001C),
|
||||
KeyCode::SuperLeft => Some(0xE05B),
|
||||
KeyCode::SuperRight => Some(0xE05C),
|
||||
KeyCode::ShiftLeft => Some(0x002A),
|
||||
KeyCode::AltRight => Some(0xe038),
|
||||
KeyCode::CapsLock => Some(0x003a),
|
||||
KeyCode::ContextMenu => Some(0xe05d),
|
||||
KeyCode::ControlLeft => Some(0x001d),
|
||||
KeyCode::ControlRight => Some(0xe01d),
|
||||
KeyCode::Enter => Some(0x001c),
|
||||
KeyCode::SuperLeft => Some(0xe05b),
|
||||
KeyCode::SuperRight => Some(0xe05c),
|
||||
KeyCode::ShiftLeft => Some(0x002a),
|
||||
KeyCode::ShiftRight => Some(0x0036),
|
||||
KeyCode::Space => Some(0x0039),
|
||||
KeyCode::Tab => Some(0x000F),
|
||||
KeyCode::Tab => Some(0x000f),
|
||||
KeyCode::Convert => Some(0x0079),
|
||||
KeyCode::Lang1 => {
|
||||
if is_korean {
|
||||
Some(0xE0F2)
|
||||
Some(0xe0f2)
|
||||
} else {
|
||||
Some(0x0072)
|
||||
}
|
||||
}
|
||||
},
|
||||
KeyCode::Lang2 => {
|
||||
if is_korean {
|
||||
Some(0xE0F1)
|
||||
Some(0xe0f1)
|
||||
} else {
|
||||
Some(0x0071)
|
||||
}
|
||||
}
|
||||
},
|
||||
KeyCode::KanaMode => Some(0x0070),
|
||||
KeyCode::NonConvert => Some(0x007B),
|
||||
KeyCode::Delete => Some(0xE053),
|
||||
KeyCode::End => Some(0xE04F),
|
||||
KeyCode::Home => Some(0xE047),
|
||||
KeyCode::Insert => Some(0xE052),
|
||||
KeyCode::PageDown => Some(0xE051),
|
||||
KeyCode::PageUp => Some(0xE049),
|
||||
KeyCode::ArrowDown => Some(0xE050),
|
||||
KeyCode::ArrowLeft => Some(0xE04B),
|
||||
KeyCode::ArrowRight => Some(0xE04D),
|
||||
KeyCode::ArrowUp => Some(0xE048),
|
||||
KeyCode::NumLock => Some(0xE045),
|
||||
KeyCode::NonConvert => Some(0x007b),
|
||||
KeyCode::Delete => Some(0xe053),
|
||||
KeyCode::End => Some(0xe04f),
|
||||
KeyCode::Home => Some(0xe047),
|
||||
KeyCode::Insert => Some(0xe052),
|
||||
KeyCode::PageDown => Some(0xe051),
|
||||
KeyCode::PageUp => Some(0xe049),
|
||||
KeyCode::ArrowDown => Some(0xe050),
|
||||
KeyCode::ArrowLeft => Some(0xe04b),
|
||||
KeyCode::ArrowRight => Some(0xe04d),
|
||||
KeyCode::ArrowUp => Some(0xe048),
|
||||
KeyCode::NumLock => Some(0xe045),
|
||||
KeyCode::Numpad0 => Some(0x0052),
|
||||
KeyCode::Numpad1 => Some(0x004F),
|
||||
KeyCode::Numpad1 => Some(0x004f),
|
||||
KeyCode::Numpad2 => Some(0x0050),
|
||||
KeyCode::Numpad3 => Some(0x0051),
|
||||
KeyCode::Numpad4 => Some(0x004B),
|
||||
KeyCode::Numpad5 => Some(0x004C),
|
||||
KeyCode::Numpad6 => Some(0x004D),
|
||||
KeyCode::Numpad4 => Some(0x004b),
|
||||
KeyCode::Numpad5 => Some(0x004c),
|
||||
KeyCode::Numpad6 => Some(0x004d),
|
||||
KeyCode::Numpad7 => Some(0x0047),
|
||||
KeyCode::Numpad8 => Some(0x0048),
|
||||
KeyCode::Numpad9 => Some(0x0049),
|
||||
KeyCode::NumpadAdd => Some(0x004E),
|
||||
KeyCode::NumpadComma => Some(0x007E),
|
||||
KeyCode::NumpadAdd => Some(0x004e),
|
||||
KeyCode::NumpadComma => Some(0x007e),
|
||||
KeyCode::NumpadDecimal => Some(0x0053),
|
||||
KeyCode::NumpadDivide => Some(0xE035),
|
||||
KeyCode::NumpadEnter => Some(0xE01C),
|
||||
KeyCode::NumpadDivide => Some(0xe035),
|
||||
KeyCode::NumpadEnter => Some(0xe01c),
|
||||
KeyCode::NumpadEqual => Some(0x0059),
|
||||
KeyCode::NumpadMultiply => Some(0x0037),
|
||||
KeyCode::NumpadSubtract => Some(0x004A),
|
||||
KeyCode::NumpadSubtract => Some(0x004a),
|
||||
KeyCode::Escape => Some(0x0001),
|
||||
KeyCode::F1 => Some(0x003B),
|
||||
KeyCode::F2 => Some(0x003C),
|
||||
KeyCode::F3 => Some(0x003D),
|
||||
KeyCode::F4 => Some(0x003E),
|
||||
KeyCode::F5 => Some(0x003F),
|
||||
KeyCode::F1 => Some(0x003b),
|
||||
KeyCode::F2 => Some(0x003c),
|
||||
KeyCode::F3 => Some(0x003d),
|
||||
KeyCode::F4 => Some(0x003e),
|
||||
KeyCode::F5 => Some(0x003f),
|
||||
KeyCode::F6 => Some(0x0040),
|
||||
KeyCode::F7 => Some(0x0041),
|
||||
KeyCode::F8 => Some(0x0042),
|
||||
|
|
@ -1090,36 +1050,36 @@ pub(crate) fn physicalkey_to_scancode(physical_key: PhysicalKey) -> Option<u32>
|
|||
KeyCode::F16 => Some(0x0067),
|
||||
KeyCode::F17 => Some(0x0068),
|
||||
KeyCode::F18 => Some(0x0069),
|
||||
KeyCode::F19 => Some(0x006A),
|
||||
KeyCode::F20 => Some(0x006B),
|
||||
KeyCode::F21 => Some(0x006C),
|
||||
KeyCode::F22 => Some(0x006D),
|
||||
KeyCode::F23 => Some(0x006E),
|
||||
KeyCode::F19 => Some(0x006a),
|
||||
KeyCode::F20 => Some(0x006b),
|
||||
KeyCode::F21 => Some(0x006c),
|
||||
KeyCode::F22 => Some(0x006d),
|
||||
KeyCode::F23 => Some(0x006e),
|
||||
KeyCode::F24 => Some(0x0076),
|
||||
KeyCode::PrintScreen => Some(0xE037),
|
||||
//KeyCode::PrintScreen => Some(0x0054), // Alt + PrintScreen
|
||||
KeyCode::PrintScreen => Some(0xe037),
|
||||
// KeyCode::PrintScreen => Some(0x0054), // Alt + PrintScreen
|
||||
KeyCode::ScrollLock => Some(0x0046),
|
||||
KeyCode::Pause => Some(0x0045),
|
||||
//KeyCode::Pause => Some(0xE046), // Ctrl + Pause
|
||||
KeyCode::BrowserBack => Some(0xE06A),
|
||||
KeyCode::BrowserFavorites => Some(0xE066),
|
||||
KeyCode::BrowserForward => Some(0xE069),
|
||||
KeyCode::BrowserHome => Some(0xE032),
|
||||
KeyCode::BrowserRefresh => Some(0xE067),
|
||||
KeyCode::BrowserSearch => Some(0xE065),
|
||||
KeyCode::BrowserStop => Some(0xE068),
|
||||
KeyCode::LaunchApp1 => Some(0xE06B),
|
||||
KeyCode::LaunchApp2 => Some(0xE021),
|
||||
KeyCode::LaunchMail => Some(0xE06C),
|
||||
KeyCode::MediaPlayPause => Some(0xE022),
|
||||
KeyCode::MediaSelect => Some(0xE06D),
|
||||
KeyCode::MediaStop => Some(0xE024),
|
||||
KeyCode::MediaTrackNext => Some(0xE019),
|
||||
KeyCode::MediaTrackPrevious => Some(0xE010),
|
||||
KeyCode::Power => Some(0xE05E),
|
||||
KeyCode::AudioVolumeDown => Some(0xE02E),
|
||||
KeyCode::AudioVolumeMute => Some(0xE020),
|
||||
KeyCode::AudioVolumeUp => Some(0xE030),
|
||||
// KeyCode::Pause => Some(0xE046), // Ctrl + Pause
|
||||
KeyCode::BrowserBack => Some(0xe06a),
|
||||
KeyCode::BrowserFavorites => Some(0xe066),
|
||||
KeyCode::BrowserForward => Some(0xe069),
|
||||
KeyCode::BrowserHome => Some(0xe032),
|
||||
KeyCode::BrowserRefresh => Some(0xe067),
|
||||
KeyCode::BrowserSearch => Some(0xe065),
|
||||
KeyCode::BrowserStop => Some(0xe068),
|
||||
KeyCode::LaunchApp1 => Some(0xe06b),
|
||||
KeyCode::LaunchApp2 => Some(0xe021),
|
||||
KeyCode::LaunchMail => Some(0xe06c),
|
||||
KeyCode::MediaPlayPause => Some(0xe022),
|
||||
KeyCode::MediaSelect => Some(0xe06d),
|
||||
KeyCode::MediaStop => Some(0xe024),
|
||||
KeyCode::MediaTrackNext => Some(0xe019),
|
||||
KeyCode::MediaTrackPrevious => Some(0xe010),
|
||||
KeyCode::Power => Some(0xe05e),
|
||||
KeyCode::AudioVolumeDown => Some(0xe02e),
|
||||
KeyCode::AudioVolumeMute => Some(0xe020),
|
||||
KeyCode::AudioVolumeUp => Some(0xe030),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -1131,12 +1091,12 @@ pub(crate) fn scancode_to_physicalkey(scancode: u32) -> PhysicalKey {
|
|||
|
||||
PhysicalKey::Code(match scancode {
|
||||
0x0029 => KeyCode::Backquote,
|
||||
0x002B => KeyCode::Backslash,
|
||||
0x000E => KeyCode::Backspace,
|
||||
0x001A => KeyCode::BracketLeft,
|
||||
0x001B => KeyCode::BracketRight,
|
||||
0x002b => KeyCode::Backslash,
|
||||
0x000e => KeyCode::Backspace,
|
||||
0x001a => KeyCode::BracketLeft,
|
||||
0x001b => KeyCode::BracketRight,
|
||||
0x0033 => KeyCode::Comma,
|
||||
0x000B => KeyCode::Digit0,
|
||||
0x000b => KeyCode::Digit0,
|
||||
0x0002 => KeyCode::Digit1,
|
||||
0x0003 => KeyCode::Digit2,
|
||||
0x0004 => KeyCode::Digit3,
|
||||
|
|
@ -1145,14 +1105,14 @@ pub(crate) fn scancode_to_physicalkey(scancode: u32) -> PhysicalKey {
|
|||
0x0007 => KeyCode::Digit6,
|
||||
0x0008 => KeyCode::Digit7,
|
||||
0x0009 => KeyCode::Digit8,
|
||||
0x000A => KeyCode::Digit9,
|
||||
0x000D => KeyCode::Equal,
|
||||
0x000a => KeyCode::Digit9,
|
||||
0x000d => KeyCode::Equal,
|
||||
0x0056 => KeyCode::IntlBackslash,
|
||||
0x0073 => KeyCode::IntlRo,
|
||||
0x007D => KeyCode::IntlYen,
|
||||
0x001E => KeyCode::KeyA,
|
||||
0x007d => KeyCode::IntlYen,
|
||||
0x001e => KeyCode::KeyA,
|
||||
0x0030 => KeyCode::KeyB,
|
||||
0x002E => KeyCode::KeyC,
|
||||
0x002e => KeyCode::KeyC,
|
||||
0x0020 => KeyCode::KeyD,
|
||||
0x0012 => KeyCode::KeyE,
|
||||
0x0021 => KeyCode::KeyF,
|
||||
|
|
@ -1168,74 +1128,74 @@ pub(crate) fn scancode_to_physicalkey(scancode: u32) -> PhysicalKey {
|
|||
0x0019 => KeyCode::KeyP,
|
||||
0x0010 => KeyCode::KeyQ,
|
||||
0x0013 => KeyCode::KeyR,
|
||||
0x001F => KeyCode::KeyS,
|
||||
0x001f => KeyCode::KeyS,
|
||||
0x0014 => KeyCode::KeyT,
|
||||
0x0016 => KeyCode::KeyU,
|
||||
0x002F => KeyCode::KeyV,
|
||||
0x002f => KeyCode::KeyV,
|
||||
0x0011 => KeyCode::KeyW,
|
||||
0x002D => KeyCode::KeyX,
|
||||
0x002d => KeyCode::KeyX,
|
||||
0x0015 => KeyCode::KeyY,
|
||||
0x002C => KeyCode::KeyZ,
|
||||
0x000C => KeyCode::Minus,
|
||||
0x002c => KeyCode::KeyZ,
|
||||
0x000c => KeyCode::Minus,
|
||||
0x0034 => KeyCode::Period,
|
||||
0x0028 => KeyCode::Quote,
|
||||
0x0027 => KeyCode::Semicolon,
|
||||
0x0035 => KeyCode::Slash,
|
||||
0x0038 => KeyCode::AltLeft,
|
||||
0xE038 => KeyCode::AltRight,
|
||||
0x003A => KeyCode::CapsLock,
|
||||
0xE05D => KeyCode::ContextMenu,
|
||||
0x001D => KeyCode::ControlLeft,
|
||||
0xE01D => KeyCode::ControlRight,
|
||||
0x001C => KeyCode::Enter,
|
||||
0xE05B => KeyCode::SuperLeft,
|
||||
0xE05C => KeyCode::SuperRight,
|
||||
0x002A => KeyCode::ShiftLeft,
|
||||
0xe038 => KeyCode::AltRight,
|
||||
0x003a => KeyCode::CapsLock,
|
||||
0xe05d => KeyCode::ContextMenu,
|
||||
0x001d => KeyCode::ControlLeft,
|
||||
0xe01d => KeyCode::ControlRight,
|
||||
0x001c => KeyCode::Enter,
|
||||
0xe05b => KeyCode::SuperLeft,
|
||||
0xe05c => KeyCode::SuperRight,
|
||||
0x002a => KeyCode::ShiftLeft,
|
||||
0x0036 => KeyCode::ShiftRight,
|
||||
0x0039 => KeyCode::Space,
|
||||
0x000F => KeyCode::Tab,
|
||||
0x000f => KeyCode::Tab,
|
||||
0x0079 => KeyCode::Convert,
|
||||
0x0072 => KeyCode::Lang1, // for non-Korean layout
|
||||
0xE0F2 => KeyCode::Lang1, // for Korean layout
|
||||
0xe0f2 => KeyCode::Lang1, // for Korean layout
|
||||
0x0071 => KeyCode::Lang2, // for non-Korean layout
|
||||
0xE0F1 => KeyCode::Lang2, // for Korean layout
|
||||
0xe0f1 => KeyCode::Lang2, // for Korean layout
|
||||
0x0070 => KeyCode::KanaMode,
|
||||
0x007B => KeyCode::NonConvert,
|
||||
0xE053 => KeyCode::Delete,
|
||||
0xE04F => KeyCode::End,
|
||||
0xE047 => KeyCode::Home,
|
||||
0xE052 => KeyCode::Insert,
|
||||
0xE051 => KeyCode::PageDown,
|
||||
0xE049 => KeyCode::PageUp,
|
||||
0xE050 => KeyCode::ArrowDown,
|
||||
0xE04B => KeyCode::ArrowLeft,
|
||||
0xE04D => KeyCode::ArrowRight,
|
||||
0xE048 => KeyCode::ArrowUp,
|
||||
0xE045 => KeyCode::NumLock,
|
||||
0x007b => KeyCode::NonConvert,
|
||||
0xe053 => KeyCode::Delete,
|
||||
0xe04f => KeyCode::End,
|
||||
0xe047 => KeyCode::Home,
|
||||
0xe052 => KeyCode::Insert,
|
||||
0xe051 => KeyCode::PageDown,
|
||||
0xe049 => KeyCode::PageUp,
|
||||
0xe050 => KeyCode::ArrowDown,
|
||||
0xe04b => KeyCode::ArrowLeft,
|
||||
0xe04d => KeyCode::ArrowRight,
|
||||
0xe048 => KeyCode::ArrowUp,
|
||||
0xe045 => KeyCode::NumLock,
|
||||
0x0052 => KeyCode::Numpad0,
|
||||
0x004F => KeyCode::Numpad1,
|
||||
0x004f => KeyCode::Numpad1,
|
||||
0x0050 => KeyCode::Numpad2,
|
||||
0x0051 => KeyCode::Numpad3,
|
||||
0x004B => KeyCode::Numpad4,
|
||||
0x004C => KeyCode::Numpad5,
|
||||
0x004D => KeyCode::Numpad6,
|
||||
0x004b => KeyCode::Numpad4,
|
||||
0x004c => KeyCode::Numpad5,
|
||||
0x004d => KeyCode::Numpad6,
|
||||
0x0047 => KeyCode::Numpad7,
|
||||
0x0048 => KeyCode::Numpad8,
|
||||
0x0049 => KeyCode::Numpad9,
|
||||
0x004E => KeyCode::NumpadAdd,
|
||||
0x007E => KeyCode::NumpadComma,
|
||||
0x004e => KeyCode::NumpadAdd,
|
||||
0x007e => KeyCode::NumpadComma,
|
||||
0x0053 => KeyCode::NumpadDecimal,
|
||||
0xE035 => KeyCode::NumpadDivide,
|
||||
0xE01C => KeyCode::NumpadEnter,
|
||||
0xe035 => KeyCode::NumpadDivide,
|
||||
0xe01c => KeyCode::NumpadEnter,
|
||||
0x0059 => KeyCode::NumpadEqual,
|
||||
0x0037 => KeyCode::NumpadMultiply,
|
||||
0x004A => KeyCode::NumpadSubtract,
|
||||
0x004a => KeyCode::NumpadSubtract,
|
||||
0x0001 => KeyCode::Escape,
|
||||
0x003B => KeyCode::F1,
|
||||
0x003C => KeyCode::F2,
|
||||
0x003D => KeyCode::F3,
|
||||
0x003E => KeyCode::F4,
|
||||
0x003F => KeyCode::F5,
|
||||
0x003b => KeyCode::F1,
|
||||
0x003c => KeyCode::F2,
|
||||
0x003d => KeyCode::F3,
|
||||
0x003e => KeyCode::F4,
|
||||
0x003f => KeyCode::F5,
|
||||
0x0040 => KeyCode::F6,
|
||||
0x0041 => KeyCode::F7,
|
||||
0x0042 => KeyCode::F8,
|
||||
|
|
@ -1249,36 +1209,36 @@ pub(crate) fn scancode_to_physicalkey(scancode: u32) -> PhysicalKey {
|
|||
0x0067 => KeyCode::F16,
|
||||
0x0068 => KeyCode::F17,
|
||||
0x0069 => KeyCode::F18,
|
||||
0x006A => KeyCode::F19,
|
||||
0x006B => KeyCode::F20,
|
||||
0x006C => KeyCode::F21,
|
||||
0x006D => KeyCode::F22,
|
||||
0x006E => KeyCode::F23,
|
||||
0x006a => KeyCode::F19,
|
||||
0x006b => KeyCode::F20,
|
||||
0x006c => KeyCode::F21,
|
||||
0x006d => KeyCode::F22,
|
||||
0x006e => KeyCode::F23,
|
||||
0x0076 => KeyCode::F24,
|
||||
0xE037 => KeyCode::PrintScreen,
|
||||
0xe037 => KeyCode::PrintScreen,
|
||||
0x0054 => KeyCode::PrintScreen, // Alt + PrintScreen
|
||||
0x0046 => KeyCode::ScrollLock,
|
||||
0x0045 => KeyCode::Pause,
|
||||
0xE046 => KeyCode::Pause, // Ctrl + Pause
|
||||
0xE06A => KeyCode::BrowserBack,
|
||||
0xE066 => KeyCode::BrowserFavorites,
|
||||
0xE069 => KeyCode::BrowserForward,
|
||||
0xE032 => KeyCode::BrowserHome,
|
||||
0xE067 => KeyCode::BrowserRefresh,
|
||||
0xE065 => KeyCode::BrowserSearch,
|
||||
0xE068 => KeyCode::BrowserStop,
|
||||
0xE06B => KeyCode::LaunchApp1,
|
||||
0xE021 => KeyCode::LaunchApp2,
|
||||
0xE06C => KeyCode::LaunchMail,
|
||||
0xE022 => KeyCode::MediaPlayPause,
|
||||
0xE06D => KeyCode::MediaSelect,
|
||||
0xE024 => KeyCode::MediaStop,
|
||||
0xE019 => KeyCode::MediaTrackNext,
|
||||
0xE010 => KeyCode::MediaTrackPrevious,
|
||||
0xE05E => KeyCode::Power,
|
||||
0xE02E => KeyCode::AudioVolumeDown,
|
||||
0xE020 => KeyCode::AudioVolumeMute,
|
||||
0xE030 => KeyCode::AudioVolumeUp,
|
||||
0xe046 => KeyCode::Pause, // Ctrl + Pause
|
||||
0xe06a => KeyCode::BrowserBack,
|
||||
0xe066 => KeyCode::BrowserFavorites,
|
||||
0xe069 => KeyCode::BrowserForward,
|
||||
0xe032 => KeyCode::BrowserHome,
|
||||
0xe067 => KeyCode::BrowserRefresh,
|
||||
0xe065 => KeyCode::BrowserSearch,
|
||||
0xe068 => KeyCode::BrowserStop,
|
||||
0xe06b => KeyCode::LaunchApp1,
|
||||
0xe021 => KeyCode::LaunchApp2,
|
||||
0xe06c => KeyCode::LaunchMail,
|
||||
0xe022 => KeyCode::MediaPlayPause,
|
||||
0xe06d => KeyCode::MediaSelect,
|
||||
0xe024 => KeyCode::MediaStop,
|
||||
0xe019 => KeyCode::MediaTrackNext,
|
||||
0xe010 => KeyCode::MediaTrackPrevious,
|
||||
0xe05e => KeyCode::Power,
|
||||
0xe02e => KeyCode::AudioVolumeDown,
|
||||
0xe020 => KeyCode::AudioVolumeMute,
|
||||
0xe030 => KeyCode::AudioVolumeUp,
|
||||
_ => return PhysicalKey::Unidentified(NativeKeyCode::Windows(scancode as u16)),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,60 +1,49 @@
|
|||
use std::{
|
||||
collections::{hash_map::Entry, HashMap, HashSet},
|
||||
ffi::OsString,
|
||||
os::windows::ffi::OsStringExt,
|
||||
sync::Mutex,
|
||||
};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::utils::Lazy;
|
||||
use smol_str::SmolStr;
|
||||
use windows_sys::Win32::{
|
||||
System::SystemServices::{LANG_JAPANESE, LANG_KOREAN},
|
||||
UI::{
|
||||
Input::KeyboardAndMouse::{
|
||||
GetKeyState, GetKeyboardLayout, MapVirtualKeyExW, ToUnicodeEx, MAPVK_VK_TO_VSC_EX,
|
||||
VIRTUAL_KEY, VK_ACCEPT, VK_ADD, VK_APPS, VK_ATTN, VK_BACK, VK_BROWSER_BACK,
|
||||
VK_BROWSER_FAVORITES, VK_BROWSER_FORWARD, VK_BROWSER_HOME, VK_BROWSER_REFRESH,
|
||||
VK_BROWSER_SEARCH, VK_BROWSER_STOP, VK_CANCEL, VK_CAPITAL, VK_CLEAR, VK_CONTROL,
|
||||
VK_CONVERT, VK_CRSEL, VK_DECIMAL, VK_DELETE, VK_DIVIDE, VK_DOWN, VK_END, VK_EREOF,
|
||||
VK_ESCAPE, VK_EXECUTE, VK_EXSEL, VK_F1, VK_F10, VK_F11, VK_F12, VK_F13, VK_F14, VK_F15,
|
||||
VK_F16, VK_F17, VK_F18, VK_F19, VK_F2, VK_F20, VK_F21, VK_F22, VK_F23, VK_F24, VK_F3,
|
||||
VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_FINAL, VK_GAMEPAD_A, VK_GAMEPAD_B,
|
||||
VK_GAMEPAD_DPAD_DOWN, VK_GAMEPAD_DPAD_LEFT, VK_GAMEPAD_DPAD_RIGHT, VK_GAMEPAD_DPAD_UP,
|
||||
VK_GAMEPAD_LEFT_SHOULDER, VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON,
|
||||
VK_GAMEPAD_LEFT_THUMBSTICK_DOWN, VK_GAMEPAD_LEFT_THUMBSTICK_LEFT,
|
||||
VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT, VK_GAMEPAD_LEFT_THUMBSTICK_UP,
|
||||
VK_GAMEPAD_LEFT_TRIGGER, VK_GAMEPAD_MENU, VK_GAMEPAD_RIGHT_SHOULDER,
|
||||
VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON, VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN,
|
||||
VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT, VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT,
|
||||
VK_GAMEPAD_RIGHT_THUMBSTICK_UP, VK_GAMEPAD_RIGHT_TRIGGER, VK_GAMEPAD_VIEW,
|
||||
VK_GAMEPAD_X, VK_GAMEPAD_Y, VK_HANGUL, VK_HANJA, VK_HELP, VK_HOME, VK_ICO_00,
|
||||
VK_ICO_CLEAR, VK_ICO_HELP, VK_INSERT, VK_JUNJA, VK_KANA, VK_KANJI, VK_LAUNCH_APP1,
|
||||
VK_LAUNCH_APP2, VK_LAUNCH_MAIL, VK_LAUNCH_MEDIA_SELECT, VK_LBUTTON, VK_LCONTROL,
|
||||
VK_LEFT, VK_LMENU, VK_LSHIFT, VK_LWIN, VK_MBUTTON, VK_MEDIA_NEXT_TRACK,
|
||||
VK_MEDIA_PLAY_PAUSE, VK_MEDIA_PREV_TRACK, VK_MEDIA_STOP, VK_MENU, VK_MODECHANGE,
|
||||
VK_MULTIPLY, VK_NAVIGATION_ACCEPT, VK_NAVIGATION_CANCEL, VK_NAVIGATION_DOWN,
|
||||
VK_NAVIGATION_LEFT, VK_NAVIGATION_MENU, VK_NAVIGATION_RIGHT, VK_NAVIGATION_UP,
|
||||
VK_NAVIGATION_VIEW, VK_NEXT, VK_NONAME, VK_NONCONVERT, VK_NUMLOCK, VK_NUMPAD0,
|
||||
VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
|
||||
VK_NUMPAD8, VK_NUMPAD9, VK_OEM_1, VK_OEM_102, VK_OEM_2, VK_OEM_3, VK_OEM_4, VK_OEM_5,
|
||||
VK_OEM_6, VK_OEM_7, VK_OEM_8, VK_OEM_ATTN, VK_OEM_AUTO, VK_OEM_AX, VK_OEM_BACKTAB,
|
||||
VK_OEM_CLEAR, VK_OEM_COMMA, VK_OEM_COPY, VK_OEM_CUSEL, VK_OEM_ENLW, VK_OEM_FINISH,
|
||||
VK_OEM_FJ_LOYA, VK_OEM_FJ_MASSHOU, VK_OEM_FJ_ROYA, VK_OEM_FJ_TOUROKU, VK_OEM_JUMP,
|
||||
VK_OEM_MINUS, VK_OEM_NEC_EQUAL, VK_OEM_PA1, VK_OEM_PA2, VK_OEM_PA3, VK_OEM_PERIOD,
|
||||
VK_OEM_PLUS, VK_OEM_RESET, VK_OEM_WSCTRL, VK_PA1, VK_PACKET, VK_PAUSE, VK_PLAY,
|
||||
VK_PRINT, VK_PRIOR, VK_PROCESSKEY, VK_RBUTTON, VK_RCONTROL, VK_RETURN, VK_RIGHT,
|
||||
VK_RMENU, VK_RSHIFT, VK_RWIN, VK_SCROLL, VK_SELECT, VK_SEPARATOR, VK_SHIFT, VK_SLEEP,
|
||||
VK_SNAPSHOT, VK_SPACE, VK_SUBTRACT, VK_TAB, VK_UP, VK_VOLUME_DOWN, VK_VOLUME_MUTE,
|
||||
VK_VOLUME_UP, VK_XBUTTON1, VK_XBUTTON2, VK_ZOOM,
|
||||
},
|
||||
TextServices::HKL,
|
||||
},
|
||||
use windows_sys::Win32::System::SystemServices::{LANG_JAPANESE, LANG_KOREAN};
|
||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::{
|
||||
GetKeyState, GetKeyboardLayout, MapVirtualKeyExW, ToUnicodeEx, MAPVK_VK_TO_VSC_EX, VIRTUAL_KEY,
|
||||
VK_ACCEPT, VK_ADD, VK_APPS, VK_ATTN, VK_BACK, VK_BROWSER_BACK, VK_BROWSER_FAVORITES,
|
||||
VK_BROWSER_FORWARD, VK_BROWSER_HOME, VK_BROWSER_REFRESH, VK_BROWSER_SEARCH, VK_BROWSER_STOP,
|
||||
VK_CANCEL, VK_CAPITAL, VK_CLEAR, VK_CONTROL, VK_CONVERT, VK_CRSEL, VK_DECIMAL, VK_DELETE,
|
||||
VK_DIVIDE, VK_DOWN, VK_END, VK_EREOF, VK_ESCAPE, VK_EXECUTE, VK_EXSEL, VK_F1, VK_F10, VK_F11,
|
||||
VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18, VK_F19, VK_F2, VK_F20, VK_F21, VK_F22,
|
||||
VK_F23, VK_F24, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_FINAL, VK_GAMEPAD_A,
|
||||
VK_GAMEPAD_B, VK_GAMEPAD_DPAD_DOWN, VK_GAMEPAD_DPAD_LEFT, VK_GAMEPAD_DPAD_RIGHT,
|
||||
VK_GAMEPAD_DPAD_UP, VK_GAMEPAD_LEFT_SHOULDER, VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON,
|
||||
VK_GAMEPAD_LEFT_THUMBSTICK_DOWN, VK_GAMEPAD_LEFT_THUMBSTICK_LEFT,
|
||||
VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT, VK_GAMEPAD_LEFT_THUMBSTICK_UP, VK_GAMEPAD_LEFT_TRIGGER,
|
||||
VK_GAMEPAD_MENU, VK_GAMEPAD_RIGHT_SHOULDER, VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON,
|
||||
VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN, VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT,
|
||||
VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT, VK_GAMEPAD_RIGHT_THUMBSTICK_UP, VK_GAMEPAD_RIGHT_TRIGGER,
|
||||
VK_GAMEPAD_VIEW, VK_GAMEPAD_X, VK_GAMEPAD_Y, VK_HANGUL, VK_HANJA, VK_HELP, VK_HOME, VK_ICO_00,
|
||||
VK_ICO_CLEAR, VK_ICO_HELP, VK_INSERT, VK_JUNJA, VK_KANA, VK_KANJI, VK_LAUNCH_APP1,
|
||||
VK_LAUNCH_APP2, VK_LAUNCH_MAIL, VK_LAUNCH_MEDIA_SELECT, VK_LBUTTON, VK_LCONTROL, VK_LEFT,
|
||||
VK_LMENU, VK_LSHIFT, VK_LWIN, VK_MBUTTON, VK_MEDIA_NEXT_TRACK, VK_MEDIA_PLAY_PAUSE,
|
||||
VK_MEDIA_PREV_TRACK, VK_MEDIA_STOP, VK_MENU, VK_MODECHANGE, VK_MULTIPLY, VK_NAVIGATION_ACCEPT,
|
||||
VK_NAVIGATION_CANCEL, VK_NAVIGATION_DOWN, VK_NAVIGATION_LEFT, VK_NAVIGATION_MENU,
|
||||
VK_NAVIGATION_RIGHT, VK_NAVIGATION_UP, VK_NAVIGATION_VIEW, VK_NEXT, VK_NONAME, VK_NONCONVERT,
|
||||
VK_NUMLOCK, VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6,
|
||||
VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_OEM_1, VK_OEM_102, VK_OEM_2, VK_OEM_3, VK_OEM_4,
|
||||
VK_OEM_5, VK_OEM_6, VK_OEM_7, VK_OEM_8, VK_OEM_ATTN, VK_OEM_AUTO, VK_OEM_AX, VK_OEM_BACKTAB,
|
||||
VK_OEM_CLEAR, VK_OEM_COMMA, VK_OEM_COPY, VK_OEM_CUSEL, VK_OEM_ENLW, VK_OEM_FINISH,
|
||||
VK_OEM_FJ_LOYA, VK_OEM_FJ_MASSHOU, VK_OEM_FJ_ROYA, VK_OEM_FJ_TOUROKU, VK_OEM_JUMP,
|
||||
VK_OEM_MINUS, VK_OEM_NEC_EQUAL, VK_OEM_PA1, VK_OEM_PA2, VK_OEM_PA3, VK_OEM_PERIOD, VK_OEM_PLUS,
|
||||
VK_OEM_RESET, VK_OEM_WSCTRL, VK_PA1, VK_PACKET, VK_PAUSE, VK_PLAY, VK_PRINT, VK_PRIOR,
|
||||
VK_PROCESSKEY, VK_RBUTTON, VK_RCONTROL, VK_RETURN, VK_RIGHT, VK_RMENU, VK_RSHIFT, VK_RWIN,
|
||||
VK_SCROLL, VK_SELECT, VK_SEPARATOR, VK_SHIFT, VK_SLEEP, VK_SNAPSHOT, VK_SPACE, VK_SUBTRACT,
|
||||
VK_TAB, VK_UP, VK_VOLUME_DOWN, VK_VOLUME_MUTE, VK_VOLUME_UP, VK_XBUTTON1, VK_XBUTTON2, VK_ZOOM,
|
||||
};
|
||||
use windows_sys::Win32::UI::TextServices::HKL;
|
||||
|
||||
use crate::{
|
||||
keyboard::{Key, KeyCode, ModifiersState, NamedKey, NativeKey, PhysicalKey},
|
||||
platform_impl::{loword, primarylangid, scancode_to_physicalkey},
|
||||
};
|
||||
use crate::keyboard::{Key, KeyCode, ModifiersState, NamedKey, NativeKey, PhysicalKey};
|
||||
use crate::platform_impl::{loword, primarylangid, scancode_to_physicalkey};
|
||||
|
||||
pub(crate) static LAYOUT_CACHE: Lazy<Mutex<LayoutCache>> =
|
||||
Lazy::new(|| Mutex::new(LayoutCache::default()));
|
||||
|
|
@ -279,7 +268,7 @@ impl LayoutCache {
|
|||
Entry::Vacant(entry) => {
|
||||
let layout = Self::prepare_layout(locale_id);
|
||||
(locale_id, entry.insert(layout))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -288,18 +277,9 @@ impl LayoutCache {
|
|||
let filter_out_altgr = layout.has_alt_graph && key_pressed(VK_RMENU);
|
||||
let mut mods = ModifiersState::empty();
|
||||
mods.set(ModifiersState::SHIFT, key_pressed(VK_SHIFT));
|
||||
mods.set(
|
||||
ModifiersState::CONTROL,
|
||||
key_pressed(VK_CONTROL) && !filter_out_altgr,
|
||||
);
|
||||
mods.set(
|
||||
ModifiersState::ALT,
|
||||
key_pressed(VK_MENU) && !filter_out_altgr,
|
||||
);
|
||||
mods.set(
|
||||
ModifiersState::SUPER,
|
||||
key_pressed(VK_LWIN) || key_pressed(VK_RWIN),
|
||||
);
|
||||
mods.set(ModifiersState::CONTROL, key_pressed(VK_CONTROL) && !filter_out_altgr);
|
||||
mods.set(ModifiersState::ALT, key_pressed(VK_MENU) && !filter_out_altgr);
|
||||
mods.set(ModifiersState::SUPER, key_pressed(VK_LWIN) || key_pressed(VK_RWIN));
|
||||
mods
|
||||
}
|
||||
|
||||
|
|
@ -361,9 +341,7 @@ impl LayoutCache {
|
|||
let scancode = unsafe { MapVirtualKeyExW(vk, MAPVK_VK_TO_VSC_EX, locale_id as HKL) };
|
||||
let unicode = Self::to_unicode_string(&key_state, vk, scancode, locale_id);
|
||||
if let ToUnicodeResult::Str(s) = unicode {
|
||||
layout
|
||||
.numlock_on_keys
|
||||
.insert(vk as VIRTUAL_KEY, Key::Character(SmolStr::new(s)));
|
||||
layout.numlock_on_keys.insert(vk as VIRTUAL_KEY, Key::Character(SmolStr::new(s)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -403,16 +381,17 @@ impl LayoutCache {
|
|||
_ => {
|
||||
keys_for_this_mod.insert(key_code, preliminary_key);
|
||||
continue;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
let unicode = Self::to_unicode_string(&key_state, vk, scancode, locale_id);
|
||||
let key = match unicode {
|
||||
ToUnicodeResult::Str(str) => Key::Character(SmolStr::new(str)),
|
||||
ToUnicodeResult::Dead(dead_char) => {
|
||||
//println!("{:?} - {:?} produced dead {:?}", key_code, mod_state, dead_char);
|
||||
// println!("{:?} - {:?} produced dead {:?}", key_code, mod_state,
|
||||
// dead_char);
|
||||
Key::Dead(dead_char)
|
||||
}
|
||||
},
|
||||
ToUnicodeResult::None => {
|
||||
let has_alt = mod_state.contains(WindowsModifiers::ALT);
|
||||
let has_ctrl = mod_state.contains(WindowsModifiers::CONTROL);
|
||||
|
|
@ -424,7 +403,7 @@ impl LayoutCache {
|
|||
// Just use the unidentified key, we got earlier
|
||||
preliminary_key
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Check for alt graph.
|
||||
|
|
@ -750,10 +729,11 @@ fn keycode_to_vkey(keycode: KeyCode, hkl: u64) -> VIRTUAL_KEY {
|
|||
/// a `Key`, with only the information passed in as arguments, are converted.
|
||||
///
|
||||
/// In other words: this function does not need to "prepare" the current layout in order to do
|
||||
/// the conversion, but as such it cannot convert certain keys, like language-specific character keys.
|
||||
/// the conversion, but as such it cannot convert certain keys, like language-specific character
|
||||
/// keys.
|
||||
///
|
||||
/// The result includes all non-character keys defined within `Key` plus characters from numpad keys.
|
||||
/// For example, backspace and tab are included.
|
||||
/// The result includes all non-character keys defined within `Key` plus characters from numpad
|
||||
/// keys. For example, backspace and tab are included.
|
||||
fn vkey_to_non_char_key(
|
||||
vkey: VIRTUAL_KEY,
|
||||
native_code: NativeKey,
|
||||
|
|
@ -787,7 +767,7 @@ fn vkey_to_non_char_key(
|
|||
VK_PAUSE => Key::Named(NamedKey::Pause),
|
||||
VK_CAPITAL => Key::Named(NamedKey::CapsLock),
|
||||
|
||||
//VK_HANGEUL => Key::Named(NamedKey::HangulMode), // Deprecated in favour of VK_HANGUL
|
||||
// VK_HANGEUL => Key::Named(NamedKey::HangulMode), // Deprecated in favour of VK_HANGUL
|
||||
|
||||
// VK_HANGUL and VK_KANA are defined as the same constant, therefore
|
||||
// we use appropriate conditions to differentiate between them
|
||||
|
|
@ -881,7 +861,7 @@ fn vkey_to_non_char_key(
|
|||
VK_NUMLOCK => Key::Named(NamedKey::NumLock),
|
||||
VK_SCROLL => Key::Named(NamedKey::ScrollLock),
|
||||
VK_OEM_NEC_EQUAL => Key::Unidentified(native_code),
|
||||
//VK_OEM_FJ_JISHO => Key::Unidentified(native_code), // Conflicts with `VK_OEM_NEC_EQUAL`
|
||||
// VK_OEM_FJ_JISHO => Key::Unidentified(native_code), // Conflicts with `VK_OEM_NEC_EQUAL`
|
||||
VK_OEM_FJ_MASSHOU => Key::Unidentified(native_code),
|
||||
VK_OEM_FJ_TOUROKU => Key::Unidentified(native_code),
|
||||
VK_OEM_FJ_LOYA => Key::Unidentified(native_code),
|
||||
|
|
@ -897,7 +877,7 @@ fn vkey_to_non_char_key(
|
|||
} else {
|
||||
Key::Named(NamedKey::Alt)
|
||||
}
|
||||
}
|
||||
},
|
||||
VK_BROWSER_BACK => Key::Named(NamedKey::BrowserBack),
|
||||
VK_BROWSER_FORWARD => Key::Named(NamedKey::BrowserForward),
|
||||
VK_BROWSER_REFRESH => Key::Named(NamedKey::BrowserRefresh),
|
||||
|
|
@ -987,7 +967,7 @@ fn vkey_to_non_char_key(
|
|||
// Also see: https://github.com/pyfisch/keyboard-types/issues/9
|
||||
Key::Unidentified(native_code)
|
||||
}
|
||||
}
|
||||
},
|
||||
VK_OEM_COPY => Key::Named(NamedKey::Copy),
|
||||
VK_OEM_AUTO => Key::Named(NamedKey::Hankaku),
|
||||
VK_OEM_ENLW => Key::Named(NamedKey::Zenkaku),
|
||||
|
|
|
|||
|
|
@ -1,21 +1,17 @@
|
|||
#![cfg(windows_platform)]
|
||||
|
||||
use smol_str::SmolStr;
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{HANDLE, HWND},
|
||||
UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX},
|
||||
};
|
||||
use windows_sys::Win32::Foundation::{HANDLE, HWND};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX};
|
||||
|
||||
pub(crate) use self::{
|
||||
event_loop::{
|
||||
ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle,
|
||||
PlatformSpecificEventLoopAttributes,
|
||||
},
|
||||
icon::{SelectedCursor, WinIcon},
|
||||
keyboard::{physicalkey_to_scancode, scancode_to_physicalkey},
|
||||
monitor::{MonitorHandle, VideoModeHandle},
|
||||
window::Window,
|
||||
pub(crate) use self::event_loop::{
|
||||
ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle,
|
||||
PlatformSpecificEventLoopAttributes,
|
||||
};
|
||||
pub(crate) use self::icon::{SelectedCursor, WinIcon};
|
||||
pub(crate) use self::keyboard::{physicalkey_to_scancode, scancode_to_physicalkey};
|
||||
pub(crate) use self::monitor::{MonitorHandle, VideoModeHandle};
|
||||
pub(crate) use self::window::Window;
|
||||
|
||||
pub(crate) use self::icon::WinCursor as PlatformCustomCursor;
|
||||
pub use self::icon::WinIcon as PlatformIcon;
|
||||
|
|
@ -149,17 +145,17 @@ const fn get_y_lparam(x: u32) -> i16 {
|
|||
|
||||
#[inline(always)]
|
||||
pub(crate) const fn primarylangid(lgid: u16) -> u16 {
|
||||
lgid & 0x3FF
|
||||
lgid & 0x3ff
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) const fn loword(x: u32) -> u16 {
|
||||
(x & 0xFFFF) as u16
|
||||
(x & 0xffff) as u16
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
const fn hiword(x: u32) -> u16 {
|
||||
((x >> 16) & 0xFFFF) as u16
|
||||
((x >> 16) & 0xffff) as u16
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
|||
|
|
@ -1,29 +1,21 @@
|
|||
use std::{
|
||||
collections::{BTreeSet, VecDeque},
|
||||
hash::Hash,
|
||||
io, mem, ptr,
|
||||
};
|
||||
use std::collections::{BTreeSet, VecDeque};
|
||||
use std::hash::Hash;
|
||||
use std::{io, mem, ptr};
|
||||
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{BOOL, HWND, LPARAM, POINT, RECT},
|
||||
Graphics::Gdi::{
|
||||
EnumDisplayMonitors, EnumDisplaySettingsExW, GetMonitorInfoW, MonitorFromPoint,
|
||||
MonitorFromWindow, DEVMODEW, DM_BITSPERPEL, DM_DISPLAYFREQUENCY, DM_PELSHEIGHT,
|
||||
DM_PELSWIDTH, ENUM_CURRENT_SETTINGS, HDC, HMONITOR, MONITORINFO, MONITORINFOEXW,
|
||||
MONITOR_DEFAULTTONEAREST, MONITOR_DEFAULTTOPRIMARY,
|
||||
},
|
||||
use windows_sys::Win32::Foundation::{BOOL, HWND, LPARAM, POINT, RECT};
|
||||
use windows_sys::Win32::Graphics::Gdi::{
|
||||
EnumDisplayMonitors, EnumDisplaySettingsExW, GetMonitorInfoW, MonitorFromPoint,
|
||||
MonitorFromWindow, DEVMODEW, DM_BITSPERPEL, DM_DISPLAYFREQUENCY, DM_PELSHEIGHT, DM_PELSWIDTH,
|
||||
ENUM_CURRENT_SETTINGS, HDC, HMONITOR, MONITORINFO, MONITORINFOEXW, MONITOR_DEFAULTTONEAREST,
|
||||
MONITOR_DEFAULTTOPRIMARY,
|
||||
};
|
||||
|
||||
use super::util::decode_wide;
|
||||
use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize},
|
||||
monitor::VideoModeHandle as RootVideoModeHandle,
|
||||
platform_impl::platform::{
|
||||
dpi::{dpi_to_scale_factor, get_monitor_dpi},
|
||||
util::has_flag,
|
||||
window::Window,
|
||||
},
|
||||
};
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::monitor::VideoModeHandle as RootVideoModeHandle;
|
||||
use crate::platform_impl::platform::dpi::{dpi_to_scale_factor, get_monitor_dpi};
|
||||
use crate::platform_impl::platform::util::has_flag;
|
||||
use crate::platform_impl::platform::window::Window;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VideoModeHandle {
|
||||
|
|
@ -144,10 +136,7 @@ pub(crate) fn get_monitor_info(hmonitor: HMONITOR) -> Result<MONITORINFOEXW, io:
|
|||
let mut monitor_info: MONITORINFOEXW = unsafe { mem::zeroed() };
|
||||
monitor_info.monitorInfo.cbSize = mem::size_of::<MONITORINFOEXW>() as u32;
|
||||
let status = unsafe {
|
||||
GetMonitorInfoW(
|
||||
hmonitor,
|
||||
&mut monitor_info as *mut MONITORINFOEXW as *mut MONITORINFO,
|
||||
)
|
||||
GetMonitorInfoW(hmonitor, &mut monitor_info as *mut MONITORINFOEXW as *mut MONITORINFO)
|
||||
};
|
||||
if status == false.into() {
|
||||
Err(io::Error::last_os_error())
|
||||
|
|
@ -164,11 +153,7 @@ impl MonitorHandle {
|
|||
#[inline]
|
||||
pub fn name(&self) -> Option<String> {
|
||||
let monitor_info = get_monitor_info(self.0).unwrap();
|
||||
Some(
|
||||
decode_wide(&monitor_info.szDevice)
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
)
|
||||
Some(decode_wide(&monitor_info.szDevice).to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -212,10 +197,7 @@ impl MonitorHandle {
|
|||
get_monitor_info(self.0)
|
||||
.map(|info| {
|
||||
let rc_monitor = info.monitorInfo.rcMonitor;
|
||||
PhysicalPosition {
|
||||
x: rc_monitor.left,
|
||||
y: rc_monitor.top,
|
||||
}
|
||||
PhysicalPosition { x: rc_monitor.left, y: rc_monitor.top }
|
||||
})
|
||||
.unwrap_or(PhysicalPosition { x: 0, y: 0 })
|
||||
}
|
||||
|
|
@ -238,7 +220,7 @@ impl MonitorHandle {
|
|||
Err(error) => {
|
||||
tracing::warn!("Error from get_monitor_info: {error}");
|
||||
return modes.into_iter().map(mod_map);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let device_name = monitor_info.szDevice.as_ptr();
|
||||
|
|
|
|||
|
|
@ -1,39 +1,31 @@
|
|||
use std::{
|
||||
mem::{self, size_of},
|
||||
ptr,
|
||||
};
|
||||
use std::mem::{self, size_of};
|
||||
use std::ptr;
|
||||
|
||||
use windows_sys::Win32::{
|
||||
Devices::HumanInterfaceDevice::{
|
||||
HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC,
|
||||
},
|
||||
Foundation::{HANDLE, HWND},
|
||||
UI::{
|
||||
Input::{
|
||||
GetRawInputData, GetRawInputDeviceInfoW, GetRawInputDeviceList,
|
||||
KeyboardAndMouse::{MapVirtualKeyW, MAPVK_VK_TO_VSC_EX, VK_NUMLOCK, VK_SHIFT},
|
||||
RegisterRawInputDevices, HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTDEVICELIST,
|
||||
RAWINPUTHEADER, RAWKEYBOARD, RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDEV_REMOVE,
|
||||
RIDI_DEVICEINFO, RIDI_DEVICENAME, RID_DEVICE_INFO, RID_DEVICE_INFO_HID,
|
||||
RID_DEVICE_INFO_KEYBOARD, RID_DEVICE_INFO_MOUSE, RID_INPUT, RIM_TYPEHID,
|
||||
RIM_TYPEKEYBOARD, RIM_TYPEMOUSE,
|
||||
},
|
||||
WindowsAndMessaging::{
|
||||
RI_KEY_E0, RI_KEY_E1, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP,
|
||||
RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP, RI_MOUSE_BUTTON_3_DOWN,
|
||||
RI_MOUSE_BUTTON_3_UP, RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP,
|
||||
RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP,
|
||||
},
|
||||
},
|
||||
use windows_sys::Win32::Devices::HumanInterfaceDevice::{
|
||||
HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC,
|
||||
};
|
||||
use windows_sys::Win32::Foundation::{HANDLE, HWND};
|
||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::{
|
||||
MapVirtualKeyW, MAPVK_VK_TO_VSC_EX, VK_NUMLOCK, VK_SHIFT,
|
||||
};
|
||||
use windows_sys::Win32::UI::Input::{
|
||||
GetRawInputData, GetRawInputDeviceInfoW, GetRawInputDeviceList, RegisterRawInputDevices,
|
||||
HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTDEVICELIST, RAWINPUTHEADER, RAWKEYBOARD,
|
||||
RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDEV_REMOVE, RIDI_DEVICEINFO, RIDI_DEVICENAME,
|
||||
RID_DEVICE_INFO, RID_DEVICE_INFO_HID, RID_DEVICE_INFO_KEYBOARD, RID_DEVICE_INFO_MOUSE,
|
||||
RID_INPUT, RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE,
|
||||
};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
RI_KEY_E0, RI_KEY_E1, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP, RI_MOUSE_BUTTON_2_DOWN,
|
||||
RI_MOUSE_BUTTON_2_UP, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP, RI_MOUSE_BUTTON_4_DOWN,
|
||||
RI_MOUSE_BUTTON_4_UP, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP,
|
||||
};
|
||||
|
||||
use super::scancode_to_physicalkey;
|
||||
use crate::{
|
||||
event::ElementState,
|
||||
event_loop::DeviceEvents,
|
||||
keyboard::{KeyCode, PhysicalKey},
|
||||
platform_impl::platform::util,
|
||||
};
|
||||
use crate::event::ElementState;
|
||||
use crate::event_loop::DeviceEvents;
|
||||
use crate::keyboard::{KeyCode, PhysicalKey};
|
||||
use crate::platform_impl::platform::util;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_raw_input_device_list() -> Option<Vec<RAWINPUTDEVICELIST>> {
|
||||
|
|
@ -91,12 +83,7 @@ pub fn get_raw_input_device_info(handle: HANDLE) -> Option<RawDeviceInfo> {
|
|||
|
||||
let mut minimum_size = 0;
|
||||
let status = unsafe {
|
||||
GetRawInputDeviceInfoW(
|
||||
handle,
|
||||
RIDI_DEVICEINFO,
|
||||
&mut info as *mut _ as _,
|
||||
&mut minimum_size,
|
||||
)
|
||||
GetRawInputDeviceInfoW(handle, RIDI_DEVICEINFO, &mut info as *mut _ as _, &mut minimum_size)
|
||||
};
|
||||
|
||||
if status == u32::MAX || status == 0 {
|
||||
|
|
@ -121,12 +108,7 @@ pub fn get_raw_input_device_name(handle: HANDLE) -> Option<String> {
|
|||
let mut name: Vec<u16> = Vec::with_capacity(minimum_size as _);
|
||||
|
||||
let status = unsafe {
|
||||
GetRawInputDeviceInfoW(
|
||||
handle,
|
||||
RIDI_DEVICENAME,
|
||||
name.as_ptr() as _,
|
||||
&mut minimum_size,
|
||||
)
|
||||
GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, name.as_ptr() as _, &mut minimum_size)
|
||||
};
|
||||
|
||||
if status == u32::MAX || status == 0 {
|
||||
|
|
@ -159,7 +141,7 @@ pub fn register_all_mice_and_keyboards_for_raw_input(
|
|||
DeviceEvents::Never => {
|
||||
window_handle = 0;
|
||||
RIDEV_REMOVE
|
||||
}
|
||||
},
|
||||
DeviceEvents::WhenFocused => RIDEV_DEVNOTIFY,
|
||||
DeviceEvents::Always => RIDEV_DEVNOTIFY | RIDEV_INPUTSINK,
|
||||
};
|
||||
|
|
@ -188,13 +170,7 @@ pub fn get_raw_input_data(handle: HRAWINPUT) -> Option<RAWINPUT> {
|
|||
let header_size = size_of::<RAWINPUTHEADER>() as u32;
|
||||
|
||||
let status = unsafe {
|
||||
GetRawInputData(
|
||||
handle,
|
||||
RID_INPUT,
|
||||
&mut data as *mut _ as _,
|
||||
&mut data_size,
|
||||
header_size,
|
||||
)
|
||||
GetRawInputData(handle, RID_INPUT, &mut data as *mut _ as _, &mut data_size, header_size)
|
||||
};
|
||||
|
||||
if status == u32::MAX || status == 0 {
|
||||
|
|
@ -232,9 +208,9 @@ pub fn get_raw_mouse_button_state(button_flags: u32) -> [Option<ElementState>; 5
|
|||
pub fn get_keyboard_physical_key(keyboard: RAWKEYBOARD) -> Option<PhysicalKey> {
|
||||
let extension = {
|
||||
if util::has_flag(keyboard.Flags, RI_KEY_E0 as _) {
|
||||
0xE000
|
||||
0xe000
|
||||
} else if util::has_flag(keyboard.Flags, RI_KEY_E1 as _) {
|
||||
0xE100
|
||||
0xe100
|
||||
} else {
|
||||
0x0000
|
||||
}
|
||||
|
|
@ -246,7 +222,7 @@ pub fn get_keyboard_physical_key(keyboard: RAWKEYBOARD) -> Option<PhysicalKey> {
|
|||
} else {
|
||||
keyboard.MakeCode | extension
|
||||
};
|
||||
if scancode == 0xE11D || scancode == 0xE02A {
|
||||
if scancode == 0xe11d || scancode == 0xe02a {
|
||||
// At the hardware (or driver?) level, pressing the Pause key is equivalent to pressing
|
||||
// Ctrl+NumLock.
|
||||
// This equvalence means that if the user presses Pause, the keyboard will emit two
|
||||
|
|
@ -307,16 +283,17 @@ pub fn get_keyboard_physical_key(keyboard: RAWKEYBOARD) -> Option<PhysicalKey> {
|
|||
// as well.
|
||||
//
|
||||
// The issue is that in the raw device event (here), the fake shift release
|
||||
// event reports the numpad key as the scancode. Unfortunately, the event doesn't
|
||||
// have any information to tell whether it's the left shift or the right shift
|
||||
// that needs to get the fake release (or press) event so we don't forward this
|
||||
// event reports the numpad key as the scancode. Unfortunately, the event
|
||||
// doesn't have any information to tell whether it's the
|
||||
// left shift or the right shift that needs to get the fake
|
||||
// release (or press) event so we don't forward this
|
||||
// event to the application at all.
|
||||
//
|
||||
// For more on this, read the article by Raymond Chen, titled:
|
||||
// "The shift key overrides NumLock"
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040906-00/?p=37953
|
||||
return None;
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,39 +1,27 @@
|
|||
use std::{
|
||||
ffi::{c_void, OsStr, OsString},
|
||||
io,
|
||||
iter::once,
|
||||
mem,
|
||||
ops::BitAnd,
|
||||
os::windows::prelude::{OsStrExt, OsStringExt},
|
||||
ptr,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
use std::ffi::{c_void, OsStr, OsString};
|
||||
use std::iter::once;
|
||||
use std::ops::BitAnd;
|
||||
use std::os::windows::prelude::{OsStrExt, OsStringExt};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::{io, mem, ptr};
|
||||
|
||||
use crate::utils::Lazy;
|
||||
use windows_sys::{
|
||||
core::{HRESULT, PCWSTR},
|
||||
Win32::{
|
||||
Foundation::{BOOL, HANDLE, HMODULE, HWND, RECT},
|
||||
Graphics::Gdi::{ClientToScreen, HMONITOR},
|
||||
System::{
|
||||
LibraryLoader::{GetProcAddress, LoadLibraryA},
|
||||
SystemServices::IMAGE_DOS_HEADER,
|
||||
},
|
||||
UI::{
|
||||
HiDpi::{DPI_AWARENESS_CONTEXT, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS},
|
||||
Input::{
|
||||
KeyboardAndMouse::GetActiveWindow,
|
||||
Pointer::{POINTER_INFO, POINTER_PEN_INFO, POINTER_TOUCH_INFO},
|
||||
},
|
||||
WindowsAndMessaging::{
|
||||
ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowPlacement,
|
||||
GetWindowRect, IsIconic, ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS,
|
||||
IDC_HAND, IDC_HELP, IDC_IBEAM, IDC_NO, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS,
|
||||
IDC_SIZENWSE, IDC_SIZEWE, IDC_WAIT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN,
|
||||
SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, SW_MAXIMIZE, WINDOWPLACEMENT,
|
||||
},
|
||||
},
|
||||
},
|
||||
use windows_sys::core::{HRESULT, PCWSTR};
|
||||
use windows_sys::Win32::Foundation::{BOOL, HANDLE, HMODULE, HWND, RECT};
|
||||
use windows_sys::Win32::Graphics::Gdi::{ClientToScreen, HMONITOR};
|
||||
use windows_sys::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryA};
|
||||
use windows_sys::Win32::System::SystemServices::IMAGE_DOS_HEADER;
|
||||
use windows_sys::Win32::UI::HiDpi::{
|
||||
DPI_AWARENESS_CONTEXT, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS,
|
||||
};
|
||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::GetActiveWindow;
|
||||
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_PEN_INFO, POINTER_TOUCH_INFO};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowPlacement, GetWindowRect,
|
||||
IsIconic, ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM,
|
||||
IDC_NO, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, IDC_SIZEWE, IDC_WAIT,
|
||||
SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, SW_MAXIMIZE,
|
||||
WINDOWPLACEMENT,
|
||||
};
|
||||
|
||||
use crate::window::CursorIcon;
|
||||
|
|
@ -77,7 +65,7 @@ impl WindowArea {
|
|||
match self {
|
||||
WindowArea::Outer => {
|
||||
win_to_err(unsafe { GetWindowRect(hwnd, &mut rect) })?;
|
||||
}
|
||||
},
|
||||
WindowArea::Inner => unsafe {
|
||||
let mut top_left = mem::zeroed();
|
||||
|
||||
|
|
@ -123,10 +111,7 @@ pub fn get_cursor_clip() -> Result<RECT, io::Error> {
|
|||
/// Note that calling this will automatically dispatch a `WM_MOUSEMOVE` event.
|
||||
pub fn set_cursor_clip(rect: Option<RECT>) -> Result<(), io::Error> {
|
||||
unsafe {
|
||||
let rect_ptr = rect
|
||||
.as_ref()
|
||||
.map(|r| r as *const RECT)
|
||||
.unwrap_or(ptr::null());
|
||||
let rect_ptr = rect.as_ref().map(|r| r as *const RECT).unwrap_or(ptr::null());
|
||||
win_to_err(ClipCursor(rect_ptr))
|
||||
}
|
||||
}
|
||||
|
|
@ -176,7 +161,7 @@ pub(crate) fn to_windows_cursor(cursor: CursorIcon) -> PCWSTR {
|
|||
CursorIcon::NotAllowed | CursorIcon::NoDrop => IDC_NO,
|
||||
CursorIcon::Grab | CursorIcon::Grabbing | CursorIcon::Move | CursorIcon::AllScroll => {
|
||||
IDC_SIZEALL
|
||||
}
|
||||
},
|
||||
CursorIcon::EResize
|
||||
| CursorIcon::WResize
|
||||
| CursorIcon::EwResize
|
||||
|
|
|
|||
|
|
@ -1,92 +1,76 @@
|
|||
#![cfg(windows_platform)]
|
||||
|
||||
use std::{
|
||||
cell::Cell,
|
||||
ffi::c_void,
|
||||
io,
|
||||
mem::{self, MaybeUninit},
|
||||
panic, ptr,
|
||||
sync::{mpsc::channel, Arc, Mutex, MutexGuard},
|
||||
};
|
||||
use std::cell::Cell;
|
||||
use std::ffi::c_void;
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
use std::{io, panic, ptr};
|
||||
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{
|
||||
HWND, LPARAM, OLE_E_WRONGCOMPOBJ, POINT, POINTS, RECT, RPC_E_CHANGED_MODE, S_OK, WPARAM,
|
||||
},
|
||||
Graphics::{
|
||||
Dwm::{
|
||||
DwmEnableBlurBehindWindow, DwmSetWindowAttribute, DWMWA_BORDER_COLOR,
|
||||
DWMWA_CAPTION_COLOR, DWMWA_SYSTEMBACKDROP_TYPE, DWMWA_TEXT_COLOR,
|
||||
DWMWA_WINDOW_CORNER_PREFERENCE, DWM_BB_BLURREGION, DWM_BB_ENABLE, DWM_BLURBEHIND,
|
||||
DWM_SYSTEMBACKDROP_TYPE, DWM_WINDOW_CORNER_PREFERENCE,
|
||||
},
|
||||
Gdi::{
|
||||
ChangeDisplaySettingsExW, ClientToScreen, CreateRectRgn, DeleteObject, InvalidateRgn,
|
||||
RedrawWindow, CDS_FULLSCREEN, DISP_CHANGE_BADFLAGS, DISP_CHANGE_BADMODE,
|
||||
DISP_CHANGE_BADPARAM, DISP_CHANGE_FAILED, DISP_CHANGE_SUCCESSFUL, RDW_INTERNALPAINT,
|
||||
},
|
||||
},
|
||||
System::{
|
||||
Com::{
|
||||
CoCreateInstance, CoInitializeEx, CoUninitialize, CLSCTX_ALL, COINIT_APARTMENTTHREADED,
|
||||
},
|
||||
Ole::{OleInitialize, RegisterDragDrop},
|
||||
},
|
||||
UI::{
|
||||
Input::{
|
||||
KeyboardAndMouse::{
|
||||
EnableWindow, GetActiveWindow, MapVirtualKeyW, ReleaseCapture, SendInput,
|
||||
ToUnicode, INPUT, INPUT_0, INPUT_KEYBOARD, KEYBDINPUT, KEYEVENTF_EXTENDEDKEY,
|
||||
KEYEVENTF_KEYUP, MAPVK_VK_TO_VSC, VIRTUAL_KEY, VK_LMENU, VK_MENU, VK_SPACE,
|
||||
},
|
||||
Touch::{RegisterTouchWindow, TWF_WANTPALM},
|
||||
},
|
||||
WindowsAndMessaging::{
|
||||
CreateWindowExW, EnableMenuItem, FlashWindowEx, GetClientRect, GetCursorPos,
|
||||
GetForegroundWindow, GetSystemMenu, GetSystemMetrics, GetWindowPlacement,
|
||||
GetWindowTextLengthW, GetWindowTextW, IsWindowVisible, LoadCursorW, PeekMessageW,
|
||||
PostMessageW, RegisterClassExW, SetCursor, SetCursorPos, SetForegroundWindow,
|
||||
SetMenuDefaultItem, SetWindowDisplayAffinity, SetWindowPlacement, SetWindowPos,
|
||||
SetWindowTextW, TrackPopupMenu, CS_HREDRAW, CS_VREDRAW, CW_USEDEFAULT, FLASHWINFO,
|
||||
FLASHW_ALL, FLASHW_STOP, FLASHW_TIMERNOFG, FLASHW_TRAY, GWLP_HINSTANCE, HTBOTTOM,
|
||||
HTBOTTOMLEFT, HTBOTTOMRIGHT, HTCAPTION, HTLEFT, HTRIGHT, HTTOP, HTTOPLEFT, HTTOPRIGHT,
|
||||
MENU_ITEM_STATE, MFS_DISABLED, MFS_ENABLED, MF_BYCOMMAND, NID_READY, PM_NOREMOVE,
|
||||
SC_CLOSE, SC_MAXIMIZE, SC_MINIMIZE, SC_MOVE, SC_RESTORE, SC_SIZE, SM_DIGITIZER,
|
||||
SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOSIZE, SWP_NOZORDER, TPM_LEFTALIGN,
|
||||
TPM_RETURNCMD, WDA_EXCLUDEFROMCAPTURE, WDA_NONE, WM_NCLBUTTONDOWN, WM_SYSCOMMAND,
|
||||
WNDCLASSEXW,
|
||||
},
|
||||
},
|
||||
use windows_sys::Win32::Foundation::{
|
||||
HWND, LPARAM, OLE_E_WRONGCOMPOBJ, POINT, POINTS, RECT, RPC_E_CHANGED_MODE, S_OK, WPARAM,
|
||||
};
|
||||
use windows_sys::Win32::Graphics::Dwm::{
|
||||
DwmEnableBlurBehindWindow, DwmSetWindowAttribute, DWMWA_BORDER_COLOR, DWMWA_CAPTION_COLOR,
|
||||
DWMWA_SYSTEMBACKDROP_TYPE, DWMWA_TEXT_COLOR, DWMWA_WINDOW_CORNER_PREFERENCE, DWM_BB_BLURREGION,
|
||||
DWM_BB_ENABLE, DWM_BLURBEHIND, DWM_SYSTEMBACKDROP_TYPE, DWM_WINDOW_CORNER_PREFERENCE,
|
||||
};
|
||||
use windows_sys::Win32::Graphics::Gdi::{
|
||||
ChangeDisplaySettingsExW, ClientToScreen, CreateRectRgn, DeleteObject, InvalidateRgn,
|
||||
RedrawWindow, CDS_FULLSCREEN, DISP_CHANGE_BADFLAGS, DISP_CHANGE_BADMODE, DISP_CHANGE_BADPARAM,
|
||||
DISP_CHANGE_FAILED, DISP_CHANGE_SUCCESSFUL, RDW_INTERNALPAINT,
|
||||
};
|
||||
use windows_sys::Win32::System::Com::{
|
||||
CoCreateInstance, CoInitializeEx, CoUninitialize, CLSCTX_ALL, COINIT_APARTMENTTHREADED,
|
||||
};
|
||||
use windows_sys::Win32::System::Ole::{OleInitialize, RegisterDragDrop};
|
||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::{
|
||||
EnableWindow, GetActiveWindow, MapVirtualKeyW, ReleaseCapture, SendInput, ToUnicode, INPUT,
|
||||
INPUT_0, INPUT_KEYBOARD, KEYBDINPUT, KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP, MAPVK_VK_TO_VSC,
|
||||
VIRTUAL_KEY, VK_LMENU, VK_MENU, VK_SPACE,
|
||||
};
|
||||
use windows_sys::Win32::UI::Input::Touch::{RegisterTouchWindow, TWF_WANTPALM};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
CreateWindowExW, EnableMenuItem, FlashWindowEx, GetClientRect, GetCursorPos,
|
||||
GetForegroundWindow, GetSystemMenu, GetSystemMetrics, GetWindowPlacement, GetWindowTextLengthW,
|
||||
GetWindowTextW, IsWindowVisible, LoadCursorW, PeekMessageW, PostMessageW, RegisterClassExW,
|
||||
SetCursor, SetCursorPos, SetForegroundWindow, SetMenuDefaultItem, SetWindowDisplayAffinity,
|
||||
SetWindowPlacement, SetWindowPos, SetWindowTextW, TrackPopupMenu, CS_HREDRAW, CS_VREDRAW,
|
||||
CW_USEDEFAULT, FLASHWINFO, FLASHW_ALL, FLASHW_STOP, FLASHW_TIMERNOFG, FLASHW_TRAY,
|
||||
GWLP_HINSTANCE, HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTCAPTION, HTLEFT, HTRIGHT, HTTOP,
|
||||
HTTOPLEFT, HTTOPRIGHT, MENU_ITEM_STATE, MFS_DISABLED, MFS_ENABLED, MF_BYCOMMAND, NID_READY,
|
||||
PM_NOREMOVE, SC_CLOSE, SC_MAXIMIZE, SC_MINIMIZE, SC_MOVE, SC_RESTORE, SC_SIZE, SM_DIGITIZER,
|
||||
SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOSIZE, SWP_NOZORDER, TPM_LEFTALIGN, TPM_RETURNCMD,
|
||||
WDA_EXCLUDEFROMCAPTURE, WDA_NONE, WM_NCLBUTTONDOWN, WM_SYSCOMMAND, WNDCLASSEXW,
|
||||
};
|
||||
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
cursor::Cursor,
|
||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||
icon::Icon,
|
||||
platform::windows::{BackdropType, Color, CornerPreference},
|
||||
platform_impl::platform::{
|
||||
dark_mode::try_theme,
|
||||
definitions::{
|
||||
CLSID_TaskbarList, IID_ITaskbarList, IID_ITaskbarList2, ITaskbarList, ITaskbarList2,
|
||||
},
|
||||
dpi::{dpi_to_scale_factor, enable_non_client_dpi_scaling, hwnd_dpi},
|
||||
drop_handler::FileDropHandler,
|
||||
event_loop::{self, ActiveEventLoop, DESTROY_MSG_ID},
|
||||
icon::{self, IconType, WinCursor},
|
||||
ime::ImeContext,
|
||||
keyboard::KeyEventBuilder,
|
||||
monitor::{self, MonitorHandle},
|
||||
util,
|
||||
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
||||
Fullscreen, SelectedCursor, WindowId,
|
||||
},
|
||||
window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
|
||||
WindowButtons, WindowLevel,
|
||||
},
|
||||
use crate::cursor::Cursor;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
|
||||
use crate::icon::Icon;
|
||||
use crate::platform::windows::{BackdropType, Color, CornerPreference};
|
||||
use crate::platform_impl::platform::dark_mode::try_theme;
|
||||
use crate::platform_impl::platform::definitions::{
|
||||
CLSID_TaskbarList, IID_ITaskbarList, IID_ITaskbarList2, ITaskbarList, ITaskbarList2,
|
||||
};
|
||||
use crate::platform_impl::platform::dpi::{
|
||||
dpi_to_scale_factor, enable_non_client_dpi_scaling, hwnd_dpi,
|
||||
};
|
||||
use crate::platform_impl::platform::drop_handler::FileDropHandler;
|
||||
use crate::platform_impl::platform::event_loop::{self, ActiveEventLoop, DESTROY_MSG_ID};
|
||||
use crate::platform_impl::platform::icon::{self, IconType, WinCursor};
|
||||
use crate::platform_impl::platform::ime::ImeContext;
|
||||
use crate::platform_impl::platform::keyboard::KeyEventBuilder;
|
||||
use crate::platform_impl::platform::monitor::{self, MonitorHandle};
|
||||
use crate::platform_impl::platform::window_state::{
|
||||
CursorFlags, SavedWindow, WindowFlags, WindowState,
|
||||
};
|
||||
use crate::platform_impl::platform::{util, Fullscreen, SelectedCursor, WindowId};
|
||||
use crate::window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
|
||||
WindowButtons, WindowLevel,
|
||||
};
|
||||
|
||||
/// The Win32 implementation of the main `Window` object.
|
||||
|
|
@ -178,16 +162,23 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
|
||||
util::WindowArea::Outer.get_rect(self.hwnd())
|
||||
util::WindowArea::Outer
|
||||
.get_rect(self.hwnd())
|
||||
.map(|rect| Ok(PhysicalPosition::new(rect.left, rect.top)))
|
||||
.expect("Unexpected GetWindowRect failure; please report this error to rust-windowing/winit")
|
||||
.expect(
|
||||
"Unexpected GetWindowRect failure; please report this error to \
|
||||
rust-windowing/winit",
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
|
||||
let mut position: POINT = unsafe { mem::zeroed() };
|
||||
if unsafe { ClientToScreen(self.hwnd(), &mut position) } == false.into() {
|
||||
panic!("Unexpected ClientToScreen failure: please report this error to rust-windowing/winit")
|
||||
panic!(
|
||||
"Unexpected ClientToScreen failure: please report this error to \
|
||||
rust-windowing/winit"
|
||||
)
|
||||
}
|
||||
Ok(PhysicalPosition::new(position.x, position.y))
|
||||
}
|
||||
|
|
@ -223,12 +214,12 @@ impl Window {
|
|||
pub fn inner_size(&self) -> PhysicalSize<u32> {
|
||||
let mut rect: RECT = unsafe { mem::zeroed() };
|
||||
if unsafe { GetClientRect(self.hwnd(), &mut rect) } == false.into() {
|
||||
panic!("Unexpected GetClientRect failure: please report this error to rust-windowing/winit")
|
||||
panic!(
|
||||
"Unexpected GetClientRect failure: please report this error to \
|
||||
rust-windowing/winit"
|
||||
)
|
||||
}
|
||||
PhysicalSize::new(
|
||||
(rect.right - rect.left) as u32,
|
||||
(rect.bottom - rect.top) as u32,
|
||||
)
|
||||
PhysicalSize::new((rect.right - rect.left) as u32, (rect.bottom - rect.top) as u32)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -236,10 +227,7 @@ impl Window {
|
|||
util::WindowArea::Outer
|
||||
.get_rect(self.hwnd())
|
||||
.map(|rect| {
|
||||
PhysicalSize::new(
|
||||
(rect.right - rect.left) as u32,
|
||||
(rect.bottom - rect.top) as u32,
|
||||
)
|
||||
PhysicalSize::new((rect.right - rect.left) as u32, (rect.bottom - rect.top) as u32)
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
|
@ -286,8 +274,7 @@ impl Window {
|
|||
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
|
||||
let w = self.window_state_lock();
|
||||
let scale_factor = w.scale_factor;
|
||||
w.resize_increments
|
||||
.map(|size| size.to_physical(scale_factor))
|
||||
w.resize_increments.map(|size| size.to_physical(scale_factor))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -322,18 +309,9 @@ impl Window {
|
|||
self.thread_executor.execute_in_thread(move || {
|
||||
let _ = &window;
|
||||
WindowState::set_window_flags(window_state.lock().unwrap(), window, |f| {
|
||||
f.set(
|
||||
WindowFlags::MINIMIZABLE,
|
||||
buttons.contains(WindowButtons::MINIMIZE),
|
||||
);
|
||||
f.set(
|
||||
WindowFlags::MAXIMIZABLE,
|
||||
buttons.contains(WindowButtons::MAXIMIZE),
|
||||
);
|
||||
f.set(
|
||||
WindowFlags::CLOSABLE,
|
||||
buttons.contains(WindowButtons::CLOSE),
|
||||
)
|
||||
f.set(WindowFlags::MINIMIZABLE, buttons.contains(WindowButtons::MINIMIZE));
|
||||
f.set(WindowFlags::MAXIMIZABLE, buttons.contains(WindowButtons::MAXIMIZE));
|
||||
f.set(WindowFlags::CLOSABLE, buttons.contains(WindowButtons::CLOSE))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -352,6 +330,7 @@ impl Window {
|
|||
}
|
||||
buttons
|
||||
}
|
||||
|
||||
/// Returns the `hwnd` of this window.
|
||||
#[inline]
|
||||
pub fn hwnd(&self) -> HWND {
|
||||
|
|
@ -401,9 +380,7 @@ impl Window {
|
|||
pub fn raw_display_handle_rwh_06(
|
||||
&self,
|
||||
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
|
||||
Ok(rwh_06::RawDisplayHandle::Windows(
|
||||
rwh_06::WindowsDisplayHandle::new(),
|
||||
))
|
||||
Ok(rwh_06::RawDisplayHandle::Windows(rwh_06::WindowsDisplayHandle::new()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -415,21 +392,21 @@ impl Window {
|
|||
let cursor = LoadCursorW(0, util::to_windows_cursor(icon));
|
||||
SetCursor(cursor);
|
||||
});
|
||||
}
|
||||
},
|
||||
Cursor::Custom(cursor) => {
|
||||
let new_cursor = match cursor.inner {
|
||||
WinCursor::Cursor(cursor) => cursor,
|
||||
WinCursor::Failed => {
|
||||
warn!("Requested to apply failed cursor");
|
||||
return;
|
||||
}
|
||||
},
|
||||
};
|
||||
self.window_state_lock().mouse.selected_cursor =
|
||||
SelectedCursor::Custom(new_cursor.clone());
|
||||
self.thread_executor.execute_in_thread(move || unsafe {
|
||||
SetCursor(new_cursor.as_raw_handle());
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +417,7 @@ impl Window {
|
|||
CursorGrabMode::Confined => true,
|
||||
CursorGrabMode::Locked => {
|
||||
return Err(ExternalError::NotSupported(NotSupportedError::new()))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let window = self.window;
|
||||
|
|
@ -520,21 +497,13 @@ impl Window {
|
|||
unsafe { GetCursorPos(&mut pos) };
|
||||
pos
|
||||
};
|
||||
let points = POINTS {
|
||||
x: points.x as i16,
|
||||
y: points.y as i16,
|
||||
};
|
||||
let points = POINTS { x: points.x as i16, y: points.y as i16 };
|
||||
|
||||
// ReleaseCapture needs to execute on the main thread
|
||||
unsafe { ReleaseCapture() };
|
||||
|
||||
unsafe {
|
||||
PostMessageW(
|
||||
window,
|
||||
WM_NCLBUTTONDOWN,
|
||||
wparam,
|
||||
&points as *const _ as LPARAM,
|
||||
)
|
||||
PostMessageW(window, WM_NCLBUTTONDOWN, wparam, &points as *const _ as LPARAM)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
@ -575,7 +544,10 @@ impl Window {
|
|||
point.x = x;
|
||||
point.y = y;
|
||||
if ClientToScreen(self.hwnd(), &mut point) == false.into() {
|
||||
warn!("Can't convert client-area coordinates to screen coordinates when showing window menu.");
|
||||
warn!(
|
||||
"Can't convert client-area coordinates to screen coordinates when showing \
|
||||
window menu."
|
||||
);
|
||||
return;
|
||||
}
|
||||
point
|
||||
|
|
@ -585,7 +557,8 @@ impl Window {
|
|||
let h_menu = GetSystemMenu(self.hwnd(), 0);
|
||||
if h_menu == 0 {
|
||||
warn!("The corresponding window doesn't have a system menu");
|
||||
// This situation should not be treated as an error so just return without showing menu.
|
||||
// This situation should not be treated as an error so just return without showing
|
||||
// menu.
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -616,7 +589,8 @@ impl Window {
|
|||
// Popup the system menu at the position.
|
||||
let result = TrackPopupMenu(
|
||||
h_menu,
|
||||
TPM_RETURNCMD | TPM_LEFTALIGN, // for now im using LTR, but we have to use user layout direction
|
||||
TPM_RETURNCMD | TPM_LEFTALIGN, /* for now im using LTR, but we have to use user
|
||||
* layout direction */
|
||||
point.x,
|
||||
point.y,
|
||||
0,
|
||||
|
|
@ -720,13 +694,14 @@ impl Window {
|
|||
match (&old_fullscreen, &fullscreen) {
|
||||
// Return if we already are in the same fullscreen mode
|
||||
_ if old_fullscreen == fullscreen => return,
|
||||
// Return if saved Borderless(monitor) is the same as current monitor when requested fullscreen is Borderless(None)
|
||||
// Return if saved Borderless(monitor) is the same as current monitor when requested
|
||||
// fullscreen is Borderless(None)
|
||||
(Some(Fullscreen::Borderless(Some(monitor))), Some(Fullscreen::Borderless(None)))
|
||||
if *monitor == monitor::current_monitor(window) =>
|
||||
{
|
||||
return
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
window_state_lock.fullscreen.clone_from(&fullscreen);
|
||||
|
|
@ -756,7 +731,7 @@ impl Window {
|
|||
debug_assert!(res != DISP_CHANGE_BADPARAM);
|
||||
debug_assert!(res != DISP_CHANGE_FAILED);
|
||||
assert_eq!(res, DISP_CHANGE_SUCCESSFUL);
|
||||
}
|
||||
},
|
||||
(Some(Fullscreen::Exclusive(_)), _) => {
|
||||
let res = unsafe {
|
||||
ChangeDisplaySettingsExW(
|
||||
|
|
@ -773,7 +748,7 @@ impl Window {
|
|||
debug_assert!(res != DISP_CHANGE_BADPARAM);
|
||||
debug_assert!(res != DISP_CHANGE_FAILED);
|
||||
assert_eq!(res, DISP_CHANGE_SUCCESSFUL);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
|
@ -805,7 +780,8 @@ impl Window {
|
|||
// Mark as fullscreen window wrt to z-order
|
||||
//
|
||||
// this needs to be called before the below fullscreen SetWindowPos as this itself
|
||||
// will generate WM_SIZE messages of the old window size that can race with what we set below
|
||||
// will generate WM_SIZE messages of the old window size that can race with what we set
|
||||
// below
|
||||
unsafe {
|
||||
taskbar_mark_fullscreen(window, fullscreen.is_some());
|
||||
}
|
||||
|
|
@ -843,7 +819,7 @@ impl Window {
|
|||
);
|
||||
InvalidateRgn(window, 0, false.into());
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
let mut window_state_lock = window_state.lock().unwrap();
|
||||
if let Some(SavedWindow { placement }) = window_state_lock.saved_window.take() {
|
||||
|
|
@ -853,7 +829,7 @@ impl Window {
|
|||
InvalidateRgn(window, 0, false.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -874,9 +850,7 @@ impl Window {
|
|||
#[inline]
|
||||
pub fn is_decorated(&self) -> bool {
|
||||
let window_state = self.window_state_lock();
|
||||
window_state
|
||||
.window_flags
|
||||
.contains(WindowFlags::MARKER_DECORATIONS)
|
||||
window_state.window_flags.contains(WindowFlags::MARKER_DECORATIONS)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -887,14 +861,8 @@ impl Window {
|
|||
self.thread_executor.execute_in_thread(move || {
|
||||
let _ = &window;
|
||||
WindowState::set_window_flags(window_state.lock().unwrap(), window, |f| {
|
||||
f.set(
|
||||
WindowFlags::ALWAYS_ON_TOP,
|
||||
level == WindowLevel::AlwaysOnTop,
|
||||
);
|
||||
f.set(
|
||||
WindowFlags::ALWAYS_ON_BOTTOM,
|
||||
level == WindowLevel::AlwaysOnBottom,
|
||||
);
|
||||
f.set(WindowFlags::ALWAYS_ON_TOP, level == WindowLevel::AlwaysOnTop);
|
||||
f.set(WindowFlags::ALWAYS_ON_BOTTOM, level == WindowLevel::AlwaysOnBottom);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -907,9 +875,7 @@ impl Window {
|
|||
#[inline]
|
||||
pub fn set_window_icon(&self, window_icon: Option<Icon>) {
|
||||
if let Some(ref window_icon) = window_icon {
|
||||
window_icon
|
||||
.inner
|
||||
.set_for_window(self.hwnd(), IconType::Small);
|
||||
window_icon.inner.set_for_window(self.hwnd(), IconType::Small);
|
||||
} else {
|
||||
icon::unset_for_window(self.hwnd(), IconType::Small);
|
||||
}
|
||||
|
|
@ -924,9 +890,7 @@ impl Window {
|
|||
#[inline]
|
||||
pub fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) {
|
||||
if let Some(ref taskbar_icon) = taskbar_icon {
|
||||
taskbar_icon
|
||||
.inner
|
||||
.set_for_window(self.hwnd(), IconType::Big);
|
||||
taskbar_icon.inner.set_for_window(self.hwnd(), IconType::Big);
|
||||
} else {
|
||||
icon::unset_for_window(self.hwnd(), IconType::Big);
|
||||
}
|
||||
|
|
@ -1055,11 +1019,7 @@ impl Window {
|
|||
unsafe {
|
||||
SetWindowDisplayAffinity(
|
||||
self.hwnd(),
|
||||
if protected {
|
||||
WDA_EXCLUDEFROMCAPTURE
|
||||
} else {
|
||||
WDA_NONE
|
||||
},
|
||||
if protected { WDA_EXCLUDEFROMCAPTURE } else { WDA_NONE },
|
||||
)
|
||||
};
|
||||
}
|
||||
|
|
@ -1189,11 +1149,7 @@ impl<'a> InitData<'a> {
|
|||
|
||||
unsafe { ImeContext::set_ime_allowed(window, false) };
|
||||
|
||||
Window {
|
||||
window,
|
||||
window_state,
|
||||
thread_executor: self.event_loop.create_thread_executor(),
|
||||
}
|
||||
Window { window, window_state, thread_executor: self.event_loop.create_thread_executor() }
|
||||
}
|
||||
|
||||
unsafe fn create_window_data(&self, win: &Window) -> event_loop::WindowData {
|
||||
|
|
@ -1205,9 +1161,9 @@ impl<'a> InitData<'a> {
|
|||
panic!("OleInitialize failed! Result was: `OLE_E_WRONGCOMPOBJ`");
|
||||
} else if ole_init_result == RPC_E_CHANGED_MODE {
|
||||
panic!(
|
||||
"OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`. \
|
||||
Make sure other crates are not using multithreaded COM library \
|
||||
on the same thread or disable drag and drop support."
|
||||
"OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`. Make sure other \
|
||||
crates are not using multithreaded COM library on the same thread or disable \
|
||||
drag and drop support."
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1224,10 +1180,7 @@ impl<'a> InitData<'a> {
|
|||
let handler_interface_ptr =
|
||||
unsafe { &mut (*file_drop_handler.data).interface as *mut _ as *mut c_void };
|
||||
|
||||
assert_eq!(
|
||||
unsafe { RegisterDragDrop(win.window, handler_interface_ptr) },
|
||||
S_OK
|
||||
);
|
||||
assert_eq!(unsafe { RegisterDragDrop(win.window, handler_interface_ptr) }, S_OK);
|
||||
Some(file_drop_handler)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -1244,7 +1197,8 @@ impl<'a> InitData<'a> {
|
|||
}
|
||||
|
||||
// Returns a pointer to window user data on success.
|
||||
// The user data will be registered for the window and can be accessed within the window event callback.
|
||||
// The user data will be registered for the window and can be accessed within the window event
|
||||
// callback.
|
||||
pub unsafe fn on_nccreate(&mut self, window: HWND) -> Option<isize> {
|
||||
let runner = self.event_loop.runner_shared.clone();
|
||||
let result = runner.catch_unwind(|| {
|
||||
|
|
@ -1276,10 +1230,7 @@ impl<'a> InitData<'a> {
|
|||
};
|
||||
let hr = unsafe { DwmEnableBlurBehindWindow(win.hwnd(), &bb) };
|
||||
if hr < 0 {
|
||||
warn!(
|
||||
"Setting transparent window is failed. HRESULT Code: 0x{:X}",
|
||||
hr
|
||||
);
|
||||
warn!("Setting transparent window is failed. HRESULT Code: 0x{:X}", hr);
|
||||
}
|
||||
unsafe { DeleteObject(region) };
|
||||
}
|
||||
|
|
@ -1302,15 +1253,11 @@ impl<'a> InitData<'a> {
|
|||
|
||||
win.set_enabled_buttons(attributes.enabled_buttons);
|
||||
|
||||
let size = attributes
|
||||
.inner_size
|
||||
.unwrap_or_else(|| PhysicalSize::new(800, 600).into());
|
||||
let size = attributes.inner_size.unwrap_or_else(|| PhysicalSize::new(800, 600).into());
|
||||
let max_size = attributes
|
||||
.max_inner_size
|
||||
.unwrap_or_else(|| PhysicalSize::new(f64::MAX, f64::MAX).into());
|
||||
let min_size = attributes
|
||||
.min_inner_size
|
||||
.unwrap_or_else(|| PhysicalSize::new(0, 0).into());
|
||||
let min_size = attributes.min_inner_size.unwrap_or_else(|| PhysicalSize::new(0, 0).into());
|
||||
let clamped_size = Size::clamp(size, min_size, max_size, win.scale_factor());
|
||||
win.request_inner_size(clamped_size);
|
||||
|
||||
|
|
@ -1357,18 +1304,12 @@ unsafe fn init(
|
|||
WindowFlags::MARKER_UNDECORATED_SHADOW,
|
||||
attributes.platform_specific.decoration_shadow,
|
||||
);
|
||||
window_flags.set(
|
||||
WindowFlags::ALWAYS_ON_TOP,
|
||||
attributes.window_level == WindowLevel::AlwaysOnTop,
|
||||
);
|
||||
window_flags.set(
|
||||
WindowFlags::ALWAYS_ON_BOTTOM,
|
||||
attributes.window_level == WindowLevel::AlwaysOnBottom,
|
||||
);
|
||||
window_flags.set(
|
||||
WindowFlags::NO_BACK_BUFFER,
|
||||
attributes.platform_specific.no_redirection_bitmap,
|
||||
);
|
||||
window_flags
|
||||
.set(WindowFlags::ALWAYS_ON_TOP, attributes.window_level == WindowLevel::AlwaysOnTop);
|
||||
window_flags
|
||||
.set(WindowFlags::ALWAYS_ON_BOTTOM, attributes.window_level == WindowLevel::AlwaysOnBottom);
|
||||
window_flags
|
||||
.set(WindowFlags::NO_BACK_BUFFER, attributes.platform_specific.no_redirection_bitmap);
|
||||
window_flags.set(WindowFlags::MARKER_ACTIVATE, attributes.active);
|
||||
window_flags.set(WindowFlags::TRANSPARENT, attributes.transparent);
|
||||
// WindowFlags::VISIBLE and MAXIMIZED are set down below after the window has been configured.
|
||||
|
|
@ -1376,20 +1317,17 @@ unsafe fn init(
|
|||
// Will be changed later using `window.set_enabled_buttons` but we need to set a default here
|
||||
// so the diffing later can work.
|
||||
window_flags.set(WindowFlags::CLOSABLE, true);
|
||||
window_flags.set(
|
||||
WindowFlags::CLIP_CHILDREN,
|
||||
attributes.platform_specific.clip_children,
|
||||
);
|
||||
window_flags.set(WindowFlags::CLIP_CHILDREN, attributes.platform_specific.clip_children);
|
||||
|
||||
let mut fallback_parent = || match attributes.platform_specific.owner {
|
||||
Some(parent) => {
|
||||
window_flags.set(WindowFlags::POPUP, true);
|
||||
Some(parent)
|
||||
}
|
||||
},
|
||||
None => {
|
||||
window_flags.set(WindowFlags::ON_TASKBAR, true);
|
||||
None
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(feature = "rwh_06")]
|
||||
|
|
@ -1400,7 +1338,7 @@ unsafe fn init(
|
|||
warn!("Setting a menu on a child window is unsupported");
|
||||
}
|
||||
Some(handle.hwnd.get() as HWND)
|
||||
}
|
||||
},
|
||||
Some(raw) => unreachable!("Invalid raw window handle {raw:?} on Windows"),
|
||||
None => fallback_parent(),
|
||||
};
|
||||
|
|
@ -1411,12 +1349,7 @@ unsafe fn init(
|
|||
let menu = attributes.platform_specific.menu;
|
||||
let fullscreen = attributes.fullscreen.clone();
|
||||
let maximized = attributes.maximized;
|
||||
let mut initdata = InitData {
|
||||
event_loop,
|
||||
attributes,
|
||||
window_flags,
|
||||
window: None,
|
||||
};
|
||||
let mut initdata = InitData { event_loop, attributes, window_flags, window: None };
|
||||
|
||||
let (style, ex_style) = window_flags.to_window_styles();
|
||||
let handle = unsafe {
|
||||
|
|
@ -1450,7 +1383,8 @@ unsafe fn init(
|
|||
let win = initdata.window.unwrap();
|
||||
|
||||
// Need to set FULLSCREEN or MAXIMIZED after CreateWindowEx
|
||||
// This is because if the size is changed in WM_CREATE, the restored size will be stored in that size.
|
||||
// This is because if the size is changed in WM_CREATE, the restored size will be stored in that
|
||||
// size.
|
||||
if fullscreen.is_some() {
|
||||
win.set_fullscreen(fullscreen.map(Into::into));
|
||||
unsafe { force_window_active(win.window) };
|
||||
|
|
@ -1624,13 +1558,7 @@ unsafe fn force_window_active(handle: HWND) {
|
|||
];
|
||||
|
||||
// Simulate a key press and release
|
||||
unsafe {
|
||||
SendInput(
|
||||
inputs.len() as u32,
|
||||
inputs.as_ptr(),
|
||||
mem::size_of::<INPUT>() as i32,
|
||||
)
|
||||
};
|
||||
unsafe { SendInput(inputs.len() as u32, inputs.as_ptr(), mem::size_of::<INPUT>() as i32) };
|
||||
|
||||
unsafe { SetForegroundWindow(handle) };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,23 @@
|
|||
use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize, Size},
|
||||
icon::Icon,
|
||||
keyboard::ModifiersState,
|
||||
platform_impl::platform::{event_loop, util, Fullscreen, SelectedCursor},
|
||||
window::{Theme, WindowAttributes},
|
||||
};
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize, Size};
|
||||
use crate::icon::Icon;
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::platform_impl::platform::{event_loop, util, Fullscreen, SelectedCursor};
|
||||
use crate::window::{Theme, WindowAttributes};
|
||||
use bitflags::bitflags;
|
||||
use std::io;
|
||||
use std::sync::MutexGuard;
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{HWND, RECT},
|
||||
Graphics::Gdi::InvalidateRgn,
|
||||
UI::WindowsAndMessaging::{
|
||||
AdjustWindowRectEx, EnableMenuItem, GetMenu, GetSystemMenu, GetWindowLongW, SendMessageW,
|
||||
SetWindowLongW, SetWindowPos, ShowWindow, GWL_EXSTYLE, GWL_STYLE, HWND_BOTTOM,
|
||||
HWND_NOTOPMOST, HWND_TOPMOST, MF_BYCOMMAND, MF_DISABLED, MF_ENABLED, SC_CLOSE,
|
||||
SWP_ASYNCWINDOWPOS, SWP_FRAMECHANGED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOREPOSITION,
|
||||
SWP_NOSIZE, SWP_NOZORDER, SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOW,
|
||||
SW_SHOWNOACTIVATE, WINDOWPLACEMENT, WINDOW_EX_STYLE, WINDOW_STYLE, WS_BORDER, WS_CAPTION,
|
||||
WS_CHILD, WS_CLIPCHILDREN, WS_CLIPSIBLINGS, WS_EX_ACCEPTFILES, WS_EX_APPWINDOW,
|
||||
WS_EX_LAYERED, WS_EX_NOREDIRECTIONBITMAP, WS_EX_TOPMOST, WS_EX_TRANSPARENT,
|
||||
WS_EX_WINDOWEDGE, WS_MAXIMIZE, WS_MAXIMIZEBOX, WS_MINIMIZE, WS_MINIMIZEBOX,
|
||||
WS_OVERLAPPEDWINDOW, WS_POPUP, WS_SIZEBOX, WS_SYSMENU, WS_VISIBLE,
|
||||
},
|
||||
use windows_sys::Win32::Foundation::{HWND, RECT};
|
||||
use windows_sys::Win32::Graphics::Gdi::InvalidateRgn;
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
AdjustWindowRectEx, EnableMenuItem, GetMenu, GetSystemMenu, GetWindowLongW, SendMessageW,
|
||||
SetWindowLongW, SetWindowPos, ShowWindow, GWL_EXSTYLE, GWL_STYLE, HWND_BOTTOM, HWND_NOTOPMOST,
|
||||
HWND_TOPMOST, MF_BYCOMMAND, MF_DISABLED, MF_ENABLED, SC_CLOSE, SWP_ASYNCWINDOWPOS,
|
||||
SWP_FRAMECHANGED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOREPOSITION, SWP_NOSIZE, SWP_NOZORDER,
|
||||
SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOW, SW_SHOWNOACTIVATE, WINDOWPLACEMENT,
|
||||
WINDOW_EX_STYLE, WINDOW_STYLE, WS_BORDER, WS_CAPTION, WS_CHILD, WS_CLIPCHILDREN,
|
||||
WS_CLIPSIBLINGS, WS_EX_ACCEPTFILES, WS_EX_APPWINDOW, WS_EX_LAYERED, WS_EX_NOREDIRECTIONBITMAP,
|
||||
WS_EX_TOPMOST, WS_EX_TRANSPARENT, WS_EX_WINDOWEDGE, WS_MAXIMIZE, WS_MAXIMIZEBOX, WS_MINIMIZE,
|
||||
WS_MINIMIZEBOX, WS_OVERLAPPEDWINDOW, WS_POPUP, WS_SIZEBOX, WS_SYSMENU, WS_VISIBLE,
|
||||
};
|
||||
|
||||
/// Contains information about states and the window that the callback is going to use.
|
||||
|
|
@ -242,7 +237,7 @@ impl MouseProperties {
|
|||
Err(e) => {
|
||||
self.cursor_flags = old_flags;
|
||||
return Err(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -365,26 +360,20 @@ impl WindowFlags {
|
|||
|
||||
if diff.contains(WindowFlags::MAXIMIZED) || new.contains(WindowFlags::MAXIMIZED) {
|
||||
unsafe {
|
||||
ShowWindow(
|
||||
window,
|
||||
match new.contains(WindowFlags::MAXIMIZED) {
|
||||
true => SW_MAXIMIZE,
|
||||
false => SW_RESTORE,
|
||||
},
|
||||
);
|
||||
ShowWindow(window, match new.contains(WindowFlags::MAXIMIZED) {
|
||||
true => SW_MAXIMIZE,
|
||||
false => SW_RESTORE,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Minimize operations should execute after maximize for proper window animations
|
||||
if diff.contains(WindowFlags::MINIMIZED) {
|
||||
unsafe {
|
||||
ShowWindow(
|
||||
window,
|
||||
match new.contains(WindowFlags::MINIMIZED) {
|
||||
true => SW_MINIMIZE,
|
||||
false => SW_RESTORE,
|
||||
},
|
||||
);
|
||||
ShowWindow(window, match new.contains(WindowFlags::MINIMIZED) {
|
||||
true => SW_MINIMIZE,
|
||||
false => SW_RESTORE,
|
||||
});
|
||||
}
|
||||
|
||||
diff.remove(WindowFlags::MINIMIZED);
|
||||
|
|
@ -392,11 +381,7 @@ impl WindowFlags {
|
|||
|
||||
if diff.contains(WindowFlags::CLOSABLE) || new.contains(WindowFlags::CLOSABLE) {
|
||||
let flags = MF_BYCOMMAND
|
||||
| if new.contains(WindowFlags::CLOSABLE) {
|
||||
MF_ENABLED
|
||||
} else {
|
||||
MF_DISABLED
|
||||
};
|
||||
| if new.contains(WindowFlags::CLOSABLE) { MF_ENABLED } else { MF_DISABLED };
|
||||
|
||||
unsafe {
|
||||
EnableMenuItem(GetSystemMenu(window, 0), SC_CLOSE, flags);
|
||||
|
|
@ -413,12 +398,7 @@ impl WindowFlags {
|
|||
let (style, style_ex) = new.to_window_styles();
|
||||
|
||||
unsafe {
|
||||
SendMessageW(
|
||||
window,
|
||||
event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID.get(),
|
||||
1,
|
||||
0,
|
||||
);
|
||||
SendMessageW(window, event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID.get(), 1, 0);
|
||||
|
||||
// This condition is necessary to avoid having an unrestorable window
|
||||
if !new.contains(WindowFlags::MINIMIZED) {
|
||||
|
|
@ -439,12 +419,7 @@ impl WindowFlags {
|
|||
|
||||
// Refresh the window frame
|
||||
SetWindowPos(window, 0, 0, 0, 0, 0, flags);
|
||||
SendMessageW(
|
||||
window,
|
||||
event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID.get(),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
SendMessageW(window, event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID.get(), 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -454,17 +429,17 @@ impl WindowFlags {
|
|||
let mut style = GetWindowLongW(hwnd, GWL_STYLE) as u32;
|
||||
let style_ex = GetWindowLongW(hwnd, GWL_EXSTYLE) as u32;
|
||||
|
||||
// Frameless style implemented by manually overriding the non-client area in `WM_NCCALCSIZE`.
|
||||
// Frameless style implemented by manually overriding the non-client area in
|
||||
// `WM_NCCALCSIZE`.
|
||||
if !self.contains(WindowFlags::MARKER_DECORATIONS) {
|
||||
style &= !(WS_CAPTION | WS_SIZEBOX);
|
||||
}
|
||||
|
||||
util::win_to_err({
|
||||
let b_menu = GetMenu(hwnd) != 0;
|
||||
if let (Some(get_dpi_for_window), Some(adjust_window_rect_ex_for_dpi)) = (
|
||||
*util::GET_DPI_FOR_WINDOW,
|
||||
*util::ADJUST_WINDOW_RECT_EX_FOR_DPI,
|
||||
) {
|
||||
if let (Some(get_dpi_for_window), Some(adjust_window_rect_ex_for_dpi)) =
|
||||
(*util::GET_DPI_FOR_WINDOW, *util::ADJUST_WINDOW_RECT_EX_FOR_DPI)
|
||||
{
|
||||
let dpi = get_dpi_for_window(hwnd);
|
||||
adjust_window_rect_ex_for_dpi(&mut rect, style, b_menu.into(), style_ex, dpi)
|
||||
} else {
|
||||
|
|
@ -477,12 +452,7 @@ impl WindowFlags {
|
|||
|
||||
pub fn adjust_size(self, hwnd: HWND, size: PhysicalSize<u32>) -> PhysicalSize<u32> {
|
||||
let (width, height): (u32, u32) = size.into();
|
||||
let rect = RECT {
|
||||
left: 0,
|
||||
right: width as i32,
|
||||
top: 0,
|
||||
bottom: height as i32,
|
||||
};
|
||||
let rect = RECT { left: 0, right: width as i32, top: 0, bottom: height as i32 };
|
||||
let rect = self.adjust_rect(hwnd, rect).unwrap_or(rect);
|
||||
|
||||
let outer_x = (rect.right - rect.left).abs();
|
||||
|
|
@ -516,20 +486,16 @@ impl CursorFlags {
|
|||
let cursor_clip = match self.contains(CursorFlags::GRABBED) {
|
||||
true => {
|
||||
if self.contains(CursorFlags::HIDDEN) {
|
||||
// Confine the cursor to the center of the window if the cursor is hidden. This avoids
|
||||
// problems with the cursor activating the taskbar if the window borders or overlaps that.
|
||||
// Confine the cursor to the center of the window if the cursor is hidden.
|
||||
// This avoids problems with the cursor activating
|
||||
// the taskbar if the window borders or overlaps that.
|
||||
let cx = (client_rect.left + client_rect.right) / 2;
|
||||
let cy = (client_rect.top + client_rect.bottom) / 2;
|
||||
Some(RECT {
|
||||
left: cx,
|
||||
right: cx + 1,
|
||||
top: cy,
|
||||
bottom: cy + 1,
|
||||
})
|
||||
Some(RECT { left: cx, right: cx + 1, top: cy, bottom: cy + 1 })
|
||||
} else {
|
||||
Some(client_rect)
|
||||
}
|
||||
}
|
||||
},
|
||||
false => None,
|
||||
};
|
||||
|
||||
|
|
@ -543,8 +509,9 @@ impl CursorFlags {
|
|||
};
|
||||
|
||||
// We do this check because calling `set_cursor_clip` incessantly will flood the event
|
||||
// loop with `WM_MOUSEMOVE` events, and `refresh_os_cursor` is called by `set_cursor_flags`
|
||||
// which at times gets called once every iteration of the eventloop.
|
||||
// loop with `WM_MOUSEMOVE` events, and `refresh_os_cursor` is called by
|
||||
// `set_cursor_flags` which at times gets called once every iteration of the
|
||||
// eventloop.
|
||||
if active_cursor_clip != cursor_clip.map(rect_to_tuple) {
|
||||
util::set_cursor_clip(cursor_clip)?;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue