diff --git a/src/event_loop.rs b/src/event_loop.rs index c2af36890..174d30089 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -11,6 +11,7 @@ //! [send_event]: ./struct.EventLoopProxy.html#method.send_event use std::{fmt, error}; use std::time::Instant; +use std::ops::Deref; use platform_impl; use event::Event; @@ -34,6 +35,11 @@ pub struct EventLoop { pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync } +pub struct EventLoopWindowTarget { + pub(crate) p: platform_impl::EventLoopWindowTarget, + pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync +} + impl fmt::Debug for EventLoop { fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { fmtr.pad("EventLoop { .. }") @@ -123,7 +129,7 @@ impl EventLoop { /// [`ControlFlow`]: ./enum.ControlFlow.html #[inline] pub fn run(self, event_handler: F) -> ! - where F: 'static + FnMut(Event, &EventLoop, &mut ControlFlow) + where F: 'static + FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow) { self.event_loop.run(event_handler) } @@ -137,6 +143,13 @@ impl EventLoop { } } +impl Deref for EventLoop { + type Target = EventLoopWindowTarget; + fn deref(&self) -> &EventLoopWindowTarget { + self.event_loop.window_target() + } +} + /// Used to send custom events to `EventLoop`. #[derive(Clone)] pub struct EventLoopProxy { diff --git a/src/platform/desktop.rs b/src/platform/desktop.rs index 5f32460b2..0f9f9fe07 100644 --- a/src/platform/desktop.rs +++ b/src/platform/desktop.rs @@ -5,7 +5,7 @@ ))] use event::Event; -use event_loop::{EventLoop, ControlFlow}; +use event_loop::{EventLoop, EventLoopWindowTarget, ControlFlow}; /// Additional methods on `EventLoop` that are specific to desktop platforms. pub trait EventLoopExtDesktop { @@ -17,14 +17,14 @@ pub trait EventLoopExtDesktop { /// Unlikes `run`, this function accepts non-`'static` (i.e. non-`move`) closures and returns /// control flow to the caller when `control_flow` is set to `ControlFlow::Exit`. fn run_return(&mut self, event_handler: F) - where F: FnMut(Event, &EventLoop, &mut ControlFlow); + where F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow); } impl EventLoopExtDesktop for EventLoop { type UserEvent = T; fn run_return(&mut self, event_handler: F) - where F: FnMut(Event, &EventLoop, &mut ControlFlow) + where F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow) { self.event_loop.run_return(event_handler) } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 19fe8346d..aa3c1f052 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -22,6 +22,7 @@ use std::time::{Duration, Instant}; use std::rc::Rc; use std::cell::RefCell; use std::collections::VecDeque; +use std::marker::PhantomData; use parking_lot::Mutex; use winapi::ctypes::c_int; @@ -43,7 +44,7 @@ use winapi::um::winnt::{LONG, LPCSTR, SHORT}; use window::WindowId as RootWindowId; use monitor::MonitorHandle; -use event_loop::{ControlFlow, EventLoop as RootEventLoop, EventLoopClosed}; +use event_loop::{ControlFlow, EventLoopWindowTarget as RootELW, EventLoopClosed}; use dpi::{LogicalPosition, LogicalSize, PhysicalSize}; use event::{DeviceEvent, Touch, TouchPhase, StartCause, KeyboardInput, Event, WindowEvent}; use platform_impl::platform::{event, Cursor, WindowId, DEVICE_ID, wrap_device_id, util}; @@ -138,11 +139,15 @@ impl ThreadMsgTargetSubclassInput { } } -pub struct EventLoop { +pub struct EventLoop { // Id of the background thread from the Win32 API. - thread_id: DWORD, thread_msg_target: HWND, thread_msg_sender: Sender, + window_target: RootELW +} + +pub struct EventLoopWindowTarget { + thread_id: DWORD, trigger_newevents_on_redraw: Arc, pub(crate) runner_shared: EventLoopRunnerShared, } @@ -152,6 +157,10 @@ impl EventLoop { Self::with_dpi_awareness(true) } + pub fn window_target(&self) -> &RootELW { + &self.window_target + } + pub fn with_dpi_awareness(dpi_aware: bool) -> EventLoop { become_dpi_aware(dpi_aware); @@ -163,37 +172,40 @@ impl EventLoop { let (thread_msg_target, thread_msg_sender) = thread_event_target_window(runner_shared.clone()); EventLoop { - thread_id, thread_msg_target, thread_msg_sender, - trigger_newevents_on_redraw: Arc::new(AtomicBool::new(true)), - runner_shared + window_target: RootELW { + p: EventLoopWindowTarget { + thread_id, + trigger_newevents_on_redraw: Arc::new(AtomicBool::new(true)), + runner_shared + }, + _marker: PhantomData + } } } pub fn run(mut self, event_handler: F) -> ! - where F: 'static + FnMut(Event, &RootEventLoop, &mut ControlFlow) + where F: 'static + FnMut(Event, &RootELW, &mut ControlFlow) { self.run_return(event_handler); ::std::process::exit(0); } pub fn run_return(&mut self, mut event_handler: F) - where F: FnMut(Event, &RootEventLoop, &mut ControlFlow) + where F: FnMut(Event, &RootELW, &mut ControlFlow) { unsafe{ winuser::IsGUIThread(1); } - assert_eq!(mem::size_of::>(), mem::size_of::>()); - let self_ptr = self as *const EventLoop; + let event_loop_windows_ref = &self.window_target; let mut runner = unsafe{ EventLoopRunner::new( self, move |event, control_flow| { - let event_loop_ref = &*(self_ptr as *const RootEventLoop); - event_handler(event, event_loop_ref, control_flow) + event_handler(event, event_loop_windows_ref, control_flow) } ) }; { - let runner_shared = self.runner_shared.clone(); + let runner_shared = self.window_target.p.runner_shared.clone(); let mut runner_ref = runner_shared.runner.borrow_mut(); loop { let event = runner_shared.buffer.borrow_mut().pop_front(); @@ -206,7 +218,7 @@ impl EventLoop { } macro_rules! runner { - () => {{ self.runner_shared.runner.borrow_mut().as_mut().unwrap() }}; + () => {{ self.window_target.p.runner_shared.runner.borrow_mut().as_mut().unwrap() }}; } unsafe { @@ -244,7 +256,7 @@ impl EventLoop { } runner!().call_event_handler(Event::LoopDestroyed); - *self.runner_shared.runner.borrow_mut() = None; + *self.window_target.p.runner_shared.runner.borrow_mut() = None; } pub fn create_proxy(&self) -> EventLoopProxy { @@ -253,7 +265,9 @@ impl EventLoop { event_send: self.thread_msg_sender.clone() } } +} +impl EventLoopWindowTarget { #[inline(always)] pub(crate) fn create_thread_executor(&self) -> EventLoopThreadExecutor { EventLoopThreadExecutor { @@ -309,7 +323,7 @@ impl EventLoopRunner { where F: FnMut(Event, &mut ControlFlow) { EventLoopRunner { - trigger_newevents_on_redraw: event_loop.trigger_newevents_on_redraw.clone(), + trigger_newevents_on_redraw: event_loop.window_target.p.trigger_newevents_on_redraw.clone(), control_flow: ControlFlow::default(), runner_state: RunnerState::New, in_modal_loop: false, @@ -545,8 +559,6 @@ impl Drop for EventLoop { fn drop(&mut self) { unsafe { winuser::DestroyWindow(self.thread_msg_target); - // Posting `WM_QUIT` will cause `GetMessage` to stop. - winuser::PostThreadMessageA(self.thread_id, winuser::WM_QUIT, 0, 0); } } } diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 5e989bf0b..b088201b0 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -3,7 +3,7 @@ use winapi; use winapi::shared::windef::HWND; -pub use self::event_loop::{EventLoop, EventLoopProxy}; +pub use self::event_loop::{EventLoop, EventLoopWindowTarget, EventLoopProxy}; pub use self::monitor::MonitorHandle; pub use self::window::Window; diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 3c8c46fdf..0eaf5730e 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -23,7 +23,7 @@ use dpi::{LogicalPosition, LogicalSize, PhysicalSize}; use monitor::MonitorHandle as RootMonitorHandle; use platform_impl::platform::{Cursor, PlatformSpecificWindowBuilderAttributes, WindowId}; use platform_impl::platform::dpi::{dpi_to_scale_factor, get_hwnd_dpi}; -use platform_impl::platform::event_loop::{self, EventLoop, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID, REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID}; +use platform_impl::platform::event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID, REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID}; use platform_impl::platform::event_loop::WindowState; use platform_impl::platform::icon::{self, IconType, WinIcon}; use platform_impl::platform::monitor; @@ -69,7 +69,7 @@ unsafe fn unjust_window_rect(prc: &mut RECT, style: DWORD, ex_style: DWORD) -> B impl Window { pub fn new( - event_loop: &EventLoop, + event_loop: &EventLoopWindowTarget, w_attr: WindowAttributes, pl_attr: PlatformSpecificWindowBuilderAttributes, ) -> Result { @@ -857,7 +857,7 @@ pub unsafe fn adjust_size( unsafe fn init( mut attributes: WindowAttributes, mut pl_attribs: PlatformSpecificWindowBuilderAttributes, - event_loop: &event_loop::EventLoop, + event_loop: &EventLoopWindowTarget, ) -> Result { let title = OsStr::new(&attributes.title) .encode_wide() diff --git a/src/window.rs b/src/window.rs index a68919980..871eef351 100644 --- a/src/window.rs +++ b/src/window.rs @@ -2,7 +2,7 @@ use std::{fmt, error}; use platform_impl; -use event_loop::EventLoop; +use event_loop::EventLoopWindowTarget; use monitor::{AvailableMonitorsIter, MonitorHandle}; use dpi::{LogicalPosition, LogicalSize}; @@ -283,7 +283,7 @@ impl WindowBuilder { /// Error should be very rare and only occur in case of permission denied, incompatible system, /// out of memory, etc. #[inline] - pub fn build(mut self, event_loop: &EventLoop) -> Result { + pub fn build(mut self, window_target: &EventLoopWindowTarget) -> Result { self.window.dimensions = Some(self.window.dimensions.unwrap_or_else(|| { if let Some(ref monitor) = self.window.fullscreen { // resizing the window to the dimensions of the monitor when fullscreen @@ -296,7 +296,7 @@ impl WindowBuilder { // building platform_impl::Window::new( - &event_loop.event_loop, + &window_target.p, self.window, self.platform_specific, ).map(|window| Window { window }) @@ -311,7 +311,7 @@ impl Window { /// Error should be very rare and only occur in case of permission denied, incompatible system, /// out of memory, etc. #[inline] - pub fn new(event_loop: &EventLoop) -> Result { + pub fn new(event_loop: &EventLoopWindowTarget) -> Result { let builder = WindowBuilder::new(); builder.build(event_loop) }