diff --git a/CHANGELOG.md b/CHANGELOG.md index 937995c6..6548f581 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +- On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop. + # 0.20.0 (2020-01-05) - On X11, fix `ModifiersChanged` emitting incorrect modifier change events diff --git a/Cargo.toml b/Cargo.toml index be6b9430..a1948b92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ bitflags = "1" [dev-dependencies] image = "0.21" -env_logger = "0.5" +simple_logger = "1" [target.'cfg(target_os = "android")'.dependencies.android_glue] version = "0.2" diff --git a/examples/cursor.rs b/examples/cursor.rs index 70c2ec03..de45adae 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -5,6 +5,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new().build(&event_loop).unwrap(); diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index dd25179c..5ed193ec 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -5,6 +5,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new() diff --git a/examples/custom_events.rs b/examples/custom_events.rs index 3ed0c8b2..c59299ca 100644 --- a/examples/custom_events.rs +++ b/examples/custom_events.rs @@ -11,6 +11,7 @@ fn main() { Timer, } + simple_logger::init().unwrap(); let event_loop = EventLoop::::with_user_event(); let _window = WindowBuilder::new() diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index d4b83bb0..4cdb7b63 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -5,6 +5,7 @@ use winit::monitor::{MonitorHandle, VideoMode}; use winit::window::{Fullscreen, WindowBuilder}; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); print!("Please choose the fullscreen mode: (1) exclusive, (2) borderless: "); diff --git a/examples/handling_close.rs b/examples/handling_close.rs index d67c0046..cbd57053 100644 --- a/examples/handling_close.rs +++ b/examples/handling_close.rs @@ -5,6 +5,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let _window = WindowBuilder::new() diff --git a/examples/min_max_size.rs b/examples/min_max_size.rs index 8a5b6699..f4fd00c1 100644 --- a/examples/min_max_size.rs +++ b/examples/min_max_size.rs @@ -6,6 +6,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new().build(&event_loop).unwrap(); diff --git a/examples/minimize.rs b/examples/minimize.rs index cce72de3..871cfe2e 100644 --- a/examples/minimize.rs +++ b/examples/minimize.rs @@ -5,6 +5,7 @@ use winit::event_loop::{ControlFlow, EventLoop}; use winit::window::WindowBuilder; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new() diff --git a/examples/monitor_list.rs b/examples/monitor_list.rs index a6b24d29..66f48baf 100644 --- a/examples/monitor_list.rs +++ b/examples/monitor_list.rs @@ -1,6 +1,7 @@ use winit::{event_loop::EventLoop, window::WindowBuilder}; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new().build(&event_loop).unwrap(); diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index 65e85464..60f9d802 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -1,7 +1,5 @@ #[cfg(not(target_arch = "wasm32"))] fn main() { - extern crate env_logger; - use std::{collections::HashMap, sync::mpsc, thread, time::Duration}; use winit::{ @@ -14,7 +12,7 @@ fn main() { const WINDOW_COUNT: usize = 3; const WINDOW_SIZE: PhysicalSize = PhysicalSize::new(600, 400); - env_logger::init(); + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let mut window_senders = HashMap::with_capacity(WINDOW_COUNT); for _ in 0..WINDOW_COUNT { diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 57a20c5b..01c91bb6 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -6,6 +6,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let mut windows = HashMap::new(); diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs index ea6760d6..5d761ae4 100644 --- a/examples/request_redraw.rs +++ b/examples/request_redraw.rs @@ -5,6 +5,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new() diff --git a/examples/resizable.rs b/examples/resizable.rs index 2ddb8b25..6a903919 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -6,6 +6,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let mut resizable = false; diff --git a/examples/timer.rs b/examples/timer.rs index e1e3f290..52a1444e 100644 --- a/examples/timer.rs +++ b/examples/timer.rs @@ -7,6 +7,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let _window = WindowBuilder::new() diff --git a/examples/transparent.rs b/examples/transparent.rs index a1fdefe9..78e3c4da 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -5,6 +5,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new() diff --git a/examples/video_modes.rs b/examples/video_modes.rs index f923fa92..366c5195 100644 --- a/examples/video_modes.rs +++ b/examples/video_modes.rs @@ -1,6 +1,7 @@ use winit::event_loop::EventLoop; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let monitor = event_loop.primary_monitor(); diff --git a/examples/window.rs b/examples/window.rs index 331ee98a..c028a50f 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -5,6 +5,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new() diff --git a/examples/window_debug.rs b/examples/window_debug.rs index 5f8293f8..f6e960a7 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -8,6 +8,7 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); let event_loop = EventLoop::new(); let window = WindowBuilder::new() diff --git a/examples/window_icon.rs b/examples/window_icon.rs index 86ea9556..b7c84679 100644 --- a/examples/window_icon.rs +++ b/examples/window_icon.rs @@ -7,6 +7,8 @@ use winit::{ }; fn main() { + simple_logger::init().unwrap(); + // You'll have to choose an icon size at your own discretion. On X11, the desired size varies // by WM, and on Windows, you still have to account for screen scaling. Here we use 32px, // since it seems to work well enough in most cases. Be careful about going too high, or diff --git a/examples/window_run_return.rs b/examples/window_run_return.rs index 703c12ee..bde7f6a1 100644 --- a/examples/window_run_return.rs +++ b/examples/window_run_return.rs @@ -18,6 +18,7 @@ fn main() { }; let mut event_loop = EventLoop::new(); + simple_logger::init().unwrap(); let _window = WindowBuilder::new() .with_title("A fantastic window!") .build(&event_loop) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 53e937a0..8d90e247 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -100,13 +100,9 @@ pub(crate) struct SubclassInput { } impl SubclassInput { - unsafe fn send_event(&self, event: Event<'static, T>) { + unsafe fn send_event(&self, event: Event<'_, T>) { self.event_loop_runner.send_event(event); } - - unsafe fn send_event_unbuffered<'e>(&self, event: Event<'e, T>) -> Result<(), Event<'e, T>> { - self.event_loop_runner.send_event_unbuffered(event) - } } struct ThreadMsgTargetSubclassInput { @@ -116,7 +112,7 @@ struct ThreadMsgTargetSubclassInput { } impl ThreadMsgTargetSubclassInput { - unsafe fn send_event(&self, event: Event<'static, T>) { + unsafe fn send_event(&self, event: Event<'_, T>) { self.event_loop_runner.send_event(event); } } @@ -216,28 +212,57 @@ impl EventLoop { unsafe { let mut msg = mem::zeroed(); - let mut msg_unprocessed = false; + let mut unread_message_exists = false; 'main: loop { - runner.new_events(); - loop { - if !msg_unprocessed { - if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 1) { - break; - } - } - winuser::TranslateMessage(&mut msg); - winuser::DispatchMessageW(&mut msg); - - msg_unprocessed = false; - } - runner.events_cleared(); if let Err(payload) = runner.take_panic_error() { runner.destroy_runner(); panic::resume_unwind(payload); } - if !msg_unprocessed { + runner.new_events(); + loop { + if !unread_message_exists { + if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 1) { + break; + } + } + if msg.message == winuser::WM_PAINT { + unread_message_exists = true; + break; + } + winuser::TranslateMessage(&mut msg); + winuser::DispatchMessageW(&mut msg); + + unread_message_exists = false; + } + runner.main_events_cleared(); + loop { + if !unread_message_exists { + if 0 == winuser::PeekMessageW( + &mut msg, + ptr::null_mut(), + winuser::WM_PAINT, + winuser::WM_PAINT, + 1, + ) { + break; + } + } + + winuser::TranslateMessage(&mut msg); + winuser::DispatchMessageW(&mut msg); + + unread_message_exists = false; + } + if runner.redraw_events_cleared().events_buffered() { + if runner.control_flow() == ControlFlow::Exit { + break 'main; + } + continue; + } + + if !unread_message_exists { let control_flow = runner.control_flow(); match control_flow { ControlFlow::Exit => break 'main, @@ -245,7 +270,7 @@ impl EventLoop { if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) { break 'main; } - msg_unprocessed = true; + unread_message_exists = true; } ControlFlow::WaitUntil(resume_time) => { wait_until_time_or_msg(resume_time); @@ -651,6 +676,7 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_PAINT => { + subclass_input.event_loop_runner.main_events_cleared(); subclass_input.send_event(Event::RedrawRequested(RootWindowId(WindowId(window)))); commctrl::DefSubclassProc(window, msg, wparam, lparam) } @@ -1497,7 +1523,7 @@ unsafe extern "system" fn public_window_callback( false => old_physical_inner_size, }; - let _ = subclass_input.send_event_unbuffered(Event::WindowEvent { + let _ = subclass_input.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), event: ScaleFactorChanged { scale_factor: new_dpi_factor, @@ -1697,44 +1723,49 @@ unsafe extern "system" fn thread_event_target_callback( let in_modal_loop = subclass_input.event_loop_runner.in_modal_loop(); if in_modal_loop { let mut msg = mem::zeroed(); - loop { - if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 0) { - break; + if 0 == winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 0) { + if msg.message != 0 && msg.message != winuser::WM_PAINT { + queue_call_again(); + return 0; } - // Clear all paint/timer messages from the queue before sending the events cleared message. - match msg.message { - // Flush the event queue of WM_PAINT messages. - winuser::WM_PAINT | winuser::WM_TIMER => { - // Remove the message from the message queue. - winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, 1); - if msg.hwnd != window { - winuser::TranslateMessage(&mut msg); - winuser::DispatchMessageW(&mut msg); - } + subclass_input.event_loop_runner.main_events_cleared(); + loop { + if 0 == winuser::PeekMessageW( + &mut msg, + ptr::null_mut(), + winuser::WM_PAINT, + winuser::WM_PAINT, + 1, + ) { + break; } - // If the message isn't one of those three, it may be handled by the modal - // loop so we should return control flow to it. - _ => { - queue_call_again(); - return 0; + + if msg.hwnd != window { + winuser::TranslateMessage(&mut msg); + winuser::DispatchMessageW(&mut msg); } } } + // we don't borrow until here because TODO SAFETY let runner = &subclass_input.event_loop_runner; - runner.events_cleared(); - match runner.control_flow() { - // Waiting is handled by the modal loop. - ControlFlow::Exit | ControlFlow::Wait => runner.new_events(), - ControlFlow::WaitUntil(resume_time) => { - wait_until_time_or_msg(resume_time); - runner.new_events(); - queue_call_again(); - } - ControlFlow::Poll => { - runner.new_events(); - queue_call_again(); + if runner.redraw_events_cleared().events_buffered() { + queue_call_again(); + runner.new_events(); + } else { + match runner.control_flow() { + // Waiting is handled by the modal loop. + ControlFlow::Exit | ControlFlow::Wait => runner.new_events(), + ControlFlow::WaitUntil(resume_time) => { + wait_until_time_or_msg(resume_time); + runner.new_events(); + queue_call_again(); + } + ControlFlow::Poll => { + runner.new_events(); + queue_call_again(); + } } } } diff --git a/src/platform_impl/windows/event_loop/runner.rs b/src/platform_impl/windows/event_loop/runner.rs index db807cac..ce376eb2 100644 --- a/src/platform_impl/windows/event_loop/runner.rs +++ b/src/platform_impl/windows/event_loop/runner.rs @@ -3,16 +3,17 @@ use std::{any::Any, cell::RefCell, collections::VecDeque, mem, panic, ptr, rc::R use winapi::{shared::windef::HWND, um::winuser}; use crate::{ - event::{Event, StartCause}, + dpi::PhysicalSize, + event::{Event, StartCause, WindowEvent}, event_loop::ControlFlow, - platform_impl::platform::event_loop::EventLoop, + platform_impl::platform::{event_loop::EventLoop, util}, window::WindowId, }; pub(crate) type EventLoopRunnerShared = Rc>; pub(crate) struct ELRShared { runner: RefCell>>, - buffer: RefCell>>, + buffer: RefCell>>, redraw_buffer: Rc>>, } struct EventLoopRunner { @@ -26,6 +27,63 @@ struct EventLoopRunner { } pub type PanicError = Box; +pub enum BufferedEvent { + Event(Event<'static, T>), + ScaleFactorChanged(WindowId, f64, PhysicalSize), +} + +#[must_use] +#[derive(Debug, Clone, Copy)] +pub enum AreEventsBuffered { + EventsBuffered, + ReadyToSleep, +} + +impl AreEventsBuffered { + pub fn events_buffered(&self) -> bool { + match self { + Self::EventsBuffered => true, + Self::ReadyToSleep => false, + } + } +} + +impl BufferedEvent { + pub fn from_event(event: Event<'_, T>) -> BufferedEvent { + match event { + Event::WindowEvent { + event: + WindowEvent::ScaleFactorChanged { + scale_factor, + new_inner_size, + }, + window_id, + } => BufferedEvent::ScaleFactorChanged(window_id, scale_factor, *new_inner_size), + event => BufferedEvent::Event(event.to_static().unwrap()), + } + } + + pub fn dispatch_event(self, dispatch: impl FnOnce(Event<'_, T>)) { + match self { + Self::Event(event) => dispatch(event), + Self::ScaleFactorChanged(window_id, scale_factor, mut new_inner_size) => { + dispatch(Event::WindowEvent { + window_id, + event: WindowEvent::ScaleFactorChanged { + scale_factor, + new_inner_size: &mut new_inner_size, + }, + }); + util::set_inner_size_physical( + (window_id.0).0, + new_inner_size.width as _, + new_inner_size.height as _, + ); + } + } + } +} + impl ELRShared { pub(crate) fn new() -> ELRShared { ELRShared { @@ -45,9 +103,7 @@ impl ELRShared { loop { let event = self.buffer.borrow_mut().pop_front(); match event { - Some(e) => { - runner.process_event(e); - } + Some(e) => e.dispatch_event(|e| runner.process_event(e)), None => break, } } @@ -63,35 +119,65 @@ impl ELRShared { let mut runner_ref = self.runner.borrow_mut(); if let Some(ref mut runner) = *runner_ref { runner.new_events(); + loop { + let buffered_event_opt = self.buffer.borrow_mut().pop_front(); + match buffered_event_opt { + Some(e) => e.dispatch_event(|e| runner.process_event(e)), + None => break, + } + } } } - pub(crate) unsafe fn send_event(&self, event: Event<'static, T>) { - if let Err(event) = self.send_event_unbuffered(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.buffer_event(event); + pub(crate) unsafe fn send_event(&self, event: Event<'_, T>) { + let handling_redraw = self + .runner + .borrow() + .as_ref() + .map(|r| RunnerState::HandlingRedraw == r.runner_state) + .unwrap_or(false); + let mut send = None; + if handling_redraw { + if let Event::RedrawRequested(_) = event { + send = Some(event); + } else { + self.buffer_event(event); + } + } else { + send = Some(event); + } + if let Some(event) = send { + if let Err(event) = self.send_event_unbuffered(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.buffer_event(event); + } } } - pub(crate) unsafe fn send_event_unbuffered<'e>( - &self, - event: Event<'e, T>, - ) -> Result<(), Event<'e, T>> { + unsafe fn send_event_unbuffered<'e>(&self, event: Event<'e, T>) -> Result<(), Event<'e, T>> { if let Ok(mut runner_ref) = self.runner.try_borrow_mut() { if let Some(ref mut runner) = *runner_ref { runner.process_event(event); - // Dispatch any events that were buffered during the call to `process_event`. - loop { - // We do this instead of using a `while let` loop because if we use a `while let` - // loop the reference returned `borrow_mut()` doesn't get dropped until the end - // of the loop's body and attempts to add events to the event buffer while in - // `process_event` will fail. - let buffered_event_opt = self.buffer.borrow_mut().pop_front(); - match buffered_event_opt { - Some(event) => runner.process_event(event), - None => break, + let handling_redraw = if let RunnerState::HandlingRedraw = runner.runner_state { + true + } else { + false + }; + + if !handling_redraw { + // Dispatch any events that were buffered during the call to `process_event`. + loop { + // We do this instead of using a `while let` loop because if we use a `while let` + // loop the reference returned `borrow_mut()` doesn't get dropped until the end + // of the loop's body and attempts to add events to the event buffer while in + // `process_event` will fail. + let buffered_event_opt = self.buffer.borrow_mut().pop_front(); + match buffered_event_opt { + Some(e) => e.dispatch_event(|e| runner.process_event(e)), + None => break, + } } } @@ -111,10 +197,21 @@ impl ELRShared { } } - pub(crate) fn events_cleared(&self) { + pub(crate) fn main_events_cleared(&self) { let mut runner_ref = self.runner.borrow_mut(); if let Some(ref mut runner) = *runner_ref { - runner.events_cleared(); + runner.main_events_cleared(); + } + } + + pub(crate) fn redraw_events_cleared(&self) -> AreEventsBuffered { + let mut runner_ref = self.runner.borrow_mut(); + if let Some(ref mut runner) = *runner_ref { + runner.redraw_events_cleared(); + } + match self.buffer.borrow().len() { + 0 => AreEventsBuffered::ReadyToSleep, + _ => AreEventsBuffered::EventsBuffered, } } @@ -152,12 +249,15 @@ impl ELRShared { } } - fn buffer_event(&self, event: Event<'static, T>) { + fn buffer_event(&self, event: Event<'_, T>) { match event { Event::RedrawRequested(window_id) => { self.redraw_buffer.borrow_mut().push_back(window_id) } - _ => self.buffer.borrow_mut().push_back(event), + _ => self + .buffer + .borrow_mut() + .push_back(BufferedEvent::from_event(event)), } } } @@ -317,16 +417,20 @@ impl EventLoopRunner { (RunnerState::HandlingRedraw, Event::RedrawRequested(_)) => { self.call_event_handler(event) } - (_, Event::RedrawRequested(_)) => { - self.call_event_handler(Event::MainEventsCleared); - self.runner_state = RunnerState::HandlingRedraw; + (RunnerState::New, Event::RedrawRequested(_)) + | (RunnerState::Idle(..), Event::RedrawRequested(_)) => { + self.new_events(); + self.main_events_cleared(); self.call_event_handler(event); } + (_, Event::RedrawRequested(_)) => { + panic!("redraw event in non-redraw phase"); + } (RunnerState::HandlingRedraw, _) => { - warn!("Non-redraw event dispatched durning redraw phase"); - self.events_cleared(); - self.new_events(); - self.call_event_handler(event); + panic!( + "Non-redraw event dispatched durning redraw phase: {:?}", + event.map_nonuser_event::<()>().ok() + ); } (_, _) => { self.runner_state = RunnerState::HandlingEvents; @@ -345,17 +449,64 @@ impl EventLoopRunner { } } - fn events_cleared(&mut self) { + fn main_events_cleared(&mut self) { match self.runner_state { // If we were handling events, send the EventsCleared message. RunnerState::HandlingEvents => { self.call_event_handler(Event::MainEventsCleared); + self.runner_state = RunnerState::HandlingRedraw; + } + + RunnerState::HandlingRedraw => (), + + // If we *weren't* handling events, we don't have to do anything. + RunnerState::New | RunnerState::Idle(..) => (), + + // Some control flows require a NewEvents call even if no events were received. This + // branch handles those. + RunnerState::DeferredNewEvents(wait_start) => { + match self.control_flow { + // If we had deferred a Poll, send the Poll NewEvents and EventsCleared. + ControlFlow::Poll => { + self.call_event_handler(Event::NewEvents(StartCause::Poll)); + self.call_event_handler(Event::MainEventsCleared); + self.runner_state = RunnerState::HandlingRedraw; + } + // If we had deferred a WaitUntil and the resume time has since been reached, + // send the resume notification and EventsCleared event. + ControlFlow::WaitUntil(resume_time) => { + if Instant::now() >= resume_time { + self.call_event_handler(Event::NewEvents( + StartCause::ResumeTimeReached { + start: wait_start, + requested_resume: resume_time, + }, + )); + self.call_event_handler(Event::MainEventsCleared); + self.runner_state = RunnerState::HandlingRedraw; + } + } + // If we deferred a wait and no events were received, the user doesn't have to + // get an event. + ControlFlow::Wait | ControlFlow::Exit => (), + } + } + } + } + + fn redraw_events_cleared(&mut self) { + match self.runner_state { + // If we were handling events, send the EventsCleared message. + RunnerState::HandlingEvents => { + self.call_event_handler(Event::MainEventsCleared); + self.runner_state = RunnerState::HandlingRedraw; self.flush_redraws(); self.call_event_handler(Event::RedrawEventsCleared); self.runner_state = RunnerState::Idle(Instant::now()); } RunnerState::HandlingRedraw => { + self.flush_redraws(); self.call_event_handler(Event::RedrawEventsCleared); self.runner_state = RunnerState::Idle(Instant::now()); } diff --git a/src/platform_impl/windows/util.rs b/src/platform_impl/windows/util.rs index 1b984503..a5c60f9b 100644 --- a/src/platform_impl/windows/util.rs +++ b/src/platform_impl/windows/util.rs @@ -88,6 +88,38 @@ pub fn adjust_size(hwnd: HWND, size: PhysicalSize) -> PhysicalSize { PhysicalSize::new((rect.right - rect.left) as _, (rect.bottom - rect.top) as _) } +pub(crate) fn set_inner_size_physical(window: HWND, x: u32, y: u32) { + unsafe { + let rect = adjust_window_rect( + window, + RECT { + top: 0, + left: 0, + bottom: y as LONG, + right: x as LONG, + }, + ) + .expect("adjust_window_rect failed"); + + let outer_x = (rect.right - rect.left).abs() as _; + let outer_y = (rect.top - rect.bottom).abs() as _; + winuser::SetWindowPos( + window, + ptr::null_mut(), + 0, + 0, + outer_x, + outer_y, + winuser::SWP_ASYNCWINDOWPOS + | winuser::SWP_NOZORDER + | winuser::SWP_NOREPOSITION + | winuser::SWP_NOMOVE + | winuser::SWP_NOACTIVATE, + ); + winuser::UpdateWindow(window); + } +} + pub fn adjust_window_rect(hwnd: HWND, rect: RECT) -> Option { unsafe { let style = winuser::GetWindowLongW(hwnd, winuser::GWL_STYLE); diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 83609a27..f3e7851a 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -24,7 +24,7 @@ use winapi::{ oleidl::LPDROPTARGET, shobjidl_core::{CLSID_TaskbarList, ITaskbarList2}, wingdi::{CreateRectRgn, DeleteObject}, - winnt::{LONG, LPCWSTR}, + winnt::LPCWSTR, winuser, }, }; @@ -215,38 +215,6 @@ impl Window { .unwrap() } - pub(crate) fn set_inner_size_physical(&self, x: u32, y: u32) { - unsafe { - let rect = util::adjust_window_rect( - self.window.0, - RECT { - top: 0, - left: 0, - bottom: y as LONG, - right: x as LONG, - }, - ) - .expect("adjust_window_rect failed"); - - let outer_x = (rect.right - rect.left).abs() as c_int; - let outer_y = (rect.top - rect.bottom).abs() as c_int; - winuser::SetWindowPos( - self.window.0, - ptr::null_mut(), - 0, - 0, - outer_x, - outer_y, - winuser::SWP_ASYNCWINDOWPOS - | winuser::SWP_NOZORDER - | winuser::SWP_NOREPOSITION - | winuser::SWP_NOMOVE - | winuser::SWP_NOACTIVATE, - ); - winuser::UpdateWindow(self.window.0); - } - } - #[inline] pub fn set_inner_size(&self, size: Size) { let dpi_factor = self.scale_factor(); @@ -260,7 +228,7 @@ impl Window { }); }); - self.set_inner_size_physical(width, height); + util::set_inner_size_physical(self.window.0, width, height); } #[inline]