Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 63 additions & 10 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,17 +833,64 @@ unsafe extern "system" fn public_window_callback<T>(
}

winuser::WM_NCLBUTTONDOWN => {
// jumpstart the modal loop
winuser::RedrawWindow(
window,
ptr::null(),
ptr::null_mut(),
winuser::RDW_INTERNALPAINT,
);
if wparam == winuser::HTCAPTION as _ {
winuser::PostMessageW(window, winuser::WM_MOUSEMOVE, 0, 0);
match wparam as isize {
winuser::HTMAXBUTTON | winuser::HTMINBUTTON | winuser::HTCLOSE => {
// Discard the non-client button-down event and defer the processing until
// the non-client button-up event. This prevents a pause in the message loop
// while the user has the mouse button pressed on one of these buttons.
let mut window_state = subclass_input.window_state.lock();
window_state.deferred_nclbuttondown_wparam = Some(wparam);
0
}
_ => {
// jumpstart the modal loop
winuser::RedrawWindow(
window,
ptr::null(),
ptr::null_mut(),
winuser::RDW_INTERNALPAINT,
);
if wparam == winuser::HTCAPTION as _ {
winuser::PostMessageW(window, winuser::WM_MOUSEMOVE, 0, 0);
}
commctrl::DefSubclassProc(window, msg, wparam, lparam)
}
}
}

winuser::WM_NCLBUTTONUP => {
let deferred_wparam = subclass_input
.window_state
.lock()
.deferred_nclbuttondown_wparam
.filter(|deferred_wparam| *deferred_wparam == wparam)
.map(|wparam| wparam as isize)
.take();
// Manually apply min, max, restore, and close since we discarded the button down event,
// but only in the event that the user did not cancel the operation. If the user canelled
// the operation, WM_LBUTTONUP will fire and we'll clear the deferred state there as well.
match deferred_wparam {
Some(winuser::HTMAXBUTTON) => {
let window_state = subclass_input.window_state.lock();
let window_flags = window_state.window_flags();
drop(window_state);
if window_flags.contains(WindowFlags::MAXIMIZED) {
winuser::ShowWindow(window, winuser::SW_RESTORE);
} else {
winuser::ShowWindow(window, winuser::SW_MAXIMIZE);
}
0
}
Some(winuser::HTMINBUTTON) => {
winuser::ShowWindow(window, winuser::SW_MINIMIZE);
0
}
Some(winuser::HTCLOSE) => {
winuser::PostMessageW(window, winuser::WM_CLOSE, 0, 0);
0
}
_ => commctrl::DefSubclassProc(window, msg, wparam, lparam),
}
commctrl::DefSubclassProc(window, msg, wparam, lparam)
}

winuser::WM_CLOSE => {
Expand Down Expand Up @@ -1149,6 +1196,12 @@ unsafe extern "system" fn public_window_callback<T>(
ElementState::Released, MouseButton::Left, WindowEvent::MouseInput,
};

subclass_input
.window_state
.lock()
.deferred_nclbuttondown_wparam
.take();

release_mouse(&mut *subclass_input.window_state.lock());

subclass_input.send_event(Event::WindowEvent {
Expand Down
4 changes: 3 additions & 1 deletion src/platform_impl/windows/window_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use parking_lot::MutexGuard;
use std::{io, ptr};
use winapi::{
shared::{
minwindef::DWORD,
minwindef::{DWORD, WPARAM},
windef::{HWND, RECT},
},
um::winuser,
Expand All @@ -30,6 +30,7 @@ pub struct WindowState {
pub dpi_factor: f64,

pub fullscreen: Option<MonitorHandle>,
pub deferred_nclbuttondown_wparam: Option<WPARAM>,
window_flags: WindowFlags,
}

Expand Down Expand Up @@ -111,6 +112,7 @@ impl WindowState {

fullscreen: None,
window_flags: WindowFlags::empty(),
deferred_nclbuttondown_wparam: None,
}
}

Expand Down