diff --git a/Cargo.toml b/Cargo.toml index 11641f863..dc9ac5598 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,9 +35,6 @@ cocoa = "0.18.4" core-foundation = "0.6" core-graphics = "0.17.3" -[target.'cfg(target_os = "windows")'.dependencies.crossbeam-channel] -version = "0.3" - [target.'cfg(target_os = "windows")'.dependencies.winapi] version = "0.3.6" features = [ diff --git a/src/event_loop.rs b/src/event_loop.rs index 2d484a900..efd14aea6 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -29,7 +29,7 @@ use monitor::{AvailableMonitorsIter, MonitorHandle}; /// forbidding it), as such it is neither `Send` nor `Sync`. If you need cross-thread access, the /// `Window` created from this `EventLoop` _can_ be sent to an other thread, and the /// `EventLoopProxy` allows you to wake up an `EventLoop` from an other thread. -pub struct EventLoop { +pub struct EventLoop { pub(crate) event_loop: platform_impl::EventLoop, pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync } diff --git a/src/lib.rs b/src/lib.rs index 48972433a..86323be6b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -89,9 +89,6 @@ extern crate serde; #[cfg(target_os = "windows")] extern crate winapi; -#[cfg(target_os = "windows")] -#[macro_use] -extern crate crossbeam_channel; #[cfg(any(target_os = "macos", target_os = "ios"))] #[macro_use] extern crate objc; diff --git a/src/platform_impl/windows/drop_handler.rs b/src/platform_impl/windows/drop_handler.rs index 188d7be0c..44034b3c7 100644 --- a/src/platform_impl/windows/drop_handler.rs +++ b/src/platform_impl/windows/drop_handler.rs @@ -3,7 +3,6 @@ use std::os::windows::ffi::OsStringExt; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; use std::{mem, ptr}; -use crossbeam_channel::Sender; use winapi::ctypes::c_void; use winapi::shared::guiddef::REFIID; @@ -25,7 +24,7 @@ pub struct FileDropHandlerData { pub interface: IDropTarget, refcount: AtomicUsize, window: HWND, - // event_sender: Sender> + send_event: Box)> } pub struct FileDropHandler { @@ -34,14 +33,14 @@ pub struct FileDropHandler { #[allow(non_snake_case)] impl FileDropHandler { - pub fn new(window: HWND/*, event_sender: Sender>*/) -> FileDropHandler { + pub fn new(window: HWND, send_event: Box)>) -> FileDropHandler { let data = Box::new(FileDropHandlerData { interface: IDropTarget { lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl, }, refcount: AtomicUsize::new(1), window, - // event_sender, + send_event, }); FileDropHandler { data: Box::into_raw(data), @@ -187,7 +186,7 @@ impl FileDropHandler { impl FileDropHandlerData { fn send_event(&self, event: Event<()>) { - // self.event_sender.send(event).ok(); + (self.send_event)(event); } } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index c42c2f8f3..19fe8346d 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -17,12 +17,12 @@ use winapi::shared::basetsd::UINT_PTR; use std::{mem, ptr}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc::{self, Sender, Receiver}; use std::time::{Duration, Instant}; use std::rc::Rc; use std::cell::RefCell; use std::collections::VecDeque; use parking_lot::Mutex; -use crossbeam_channel::{self, Sender, Receiver}; use winapi::ctypes::c_int; use winapi::shared::minwindef::{ @@ -147,7 +147,7 @@ pub struct EventLoop { pub(crate) runner_shared: EventLoopRunnerShared, } -impl EventLoop { +impl EventLoop { pub fn new() -> EventLoop { Self::with_dpi_awareness(true) } @@ -181,27 +181,24 @@ impl EventLoop { where F: FnMut(Event, &RootEventLoop, &mut ControlFlow) { unsafe{ winuser::IsGUIThread(1); } - let mut runner = EventLoopRunner { - event_loop: self, - control_flow: ControlFlow::default(), - runner_state: RunnerState::New, - in_modal_loop: false, - modal_redraw_window: self.thread_msg_target, - event_handler: unsafe { - // Transmute used to erase lifetimes. - mem::transmute::< - &mut FnMut(Event, &RootEventLoop, &mut ControlFlow), - *mut FnMut(Event, &RootEventLoop, &mut ControlFlow) - >(&mut event_handler) + + assert_eq!(mem::size_of::>(), mem::size_of::>()); + let self_ptr = self as *const EventLoop; + + 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) } - }; + ) }; { let runner_shared = self.runner_shared.clone(); let mut runner_ref = runner_shared.runner.borrow_mut(); loop { let event = runner_shared.buffer.borrow_mut().pop_front(); match event { - Some(e) => unsafe{ runner.process_event(e); }, + Some(e) => { runner.process_event(e); }, None => break } } @@ -246,7 +243,7 @@ impl EventLoop { } } - unsafe{ runner!().call_event_handler(Event::LoopDestroyed) } + runner!().call_event_handler(Event::LoopDestroyed); *self.runner_shared.runner.borrow_mut() = None; } @@ -272,16 +269,16 @@ pub(crate) struct ELRShared { buffer: RefCell>> } pub(crate) struct EventLoopRunner { - event_loop: *const EventLoop, + trigger_newevents_on_redraw: Arc, control_flow: ControlFlow, runner_state: RunnerState, modal_redraw_window: HWND, in_modal_loop: bool, - event_handler: *mut FnMut(Event, &RootEventLoop, &mut ControlFlow) + event_handler: Box, &mut ControlFlow)> } impl ELRShared { - unsafe fn send_event(&self, event: Event) { + pub(crate) unsafe fn send_event(&self, event: Event) { if let Ok(mut runner_ref) = self.runner.try_borrow_mut() { if let Some(ref mut runner) = *runner_ref { runner.process_event(event); @@ -308,7 +305,23 @@ enum RunnerState { } impl EventLoopRunner { - unsafe fn new_events(&mut self) { + unsafe fn new(event_loop: &EventLoop, f: F) -> EventLoopRunner + where F: FnMut(Event, &mut ControlFlow) + { + EventLoopRunner { + trigger_newevents_on_redraw: event_loop.trigger_newevents_on_redraw.clone(), + control_flow: ControlFlow::default(), + runner_state: RunnerState::New, + in_modal_loop: false, + modal_redraw_window: event_loop.thread_msg_target, + event_handler: mem::transmute::< + Box, &mut ControlFlow)>, + Box, &mut ControlFlow)> + >(Box::new(f)) + } + } + + fn new_events(&mut self) { self.runner_state = match self.runner_state { // If we're already handling events or have deferred `NewEvents`, we don't need to do // do any processing. @@ -359,19 +372,21 @@ impl EventLoopRunner { }; } - unsafe fn process_event(&mut self, event: Event) { + fn process_event(&mut self, event: Event) { // If we're in the modal loop, we need to have some mechanism for finding when the event // queue has been cleared so we can call `events_cleared`. Windows doesn't give any utilities // for doing this, but it DOES guarantee that WM_PAINT will only occur after input events have // been processed. So, we send WM_PAINT to a dummy window which calls `events_cleared` when // the events queue has been emptied. if self.in_modal_loop { - winuser::RedrawWindow( - self.modal_redraw_window, - ptr::null(), - ptr::null_mut(), - winuser::RDW_INTERNALPAINT - ); + unsafe { + winuser::RedrawWindow( + self.modal_redraw_window, + ptr::null(), + ptr::null_mut(), + winuser::RDW_INTERNALPAINT + ); + } } // If new event processing has to be done (i.e. call NewEvents or defer), do it. If we're @@ -419,7 +434,7 @@ impl EventLoopRunner { self.call_event_handler(event); } - unsafe fn events_cleared(&mut self) { + fn events_cleared(&mut self) { match self.runner_state { // If we were handling events, send the EventsCleared message. RunnerState::HandlingEvents => { @@ -462,20 +477,18 @@ impl EventLoopRunner { } } - unsafe fn call_event_handler(&mut self, event: Event) { + fn call_event_handler(&mut self, event: Event) { match event { - Event::NewEvents(_) => (*self.event_loop).trigger_newevents_on_redraw.store(true, Ordering::Relaxed), - Event::EventsCleared => (*self.event_loop).trigger_newevents_on_redraw.store(false, Ordering::Relaxed), + Event::NewEvents(_) => self.trigger_newevents_on_redraw.store(true, Ordering::Relaxed), + Event::EventsCleared => self.trigger_newevents_on_redraw.store(false, Ordering::Relaxed), _ => () } - assert_eq!(mem::size_of::>(), mem::size_of::>()); - let event_loop_ref = &*(self.event_loop as *const RootEventLoop); if self.control_flow != ControlFlow::Exit { - (*self.event_handler)(event, event_loop_ref, &mut self.control_flow); + (*self.event_handler)(event, &mut self.control_flow); } else { - (*self.event_handler)(event, event_loop_ref, &mut ControlFlow::Exit); + (*self.event_handler)(event, &mut ControlFlow::Exit); } } } @@ -699,7 +712,7 @@ fn thread_event_target_window(event_loop_runner: EventLoopRunnerShared) -> (winuser::WS_VISIBLE | winuser::WS_POPUP) as _ ); - let (tx, rx) = crossbeam_channel::unbounded(); + let (tx, rx) = mpsc::channel(); let subclass_input = ThreadMsgTargetSubclassInput { event_loop_runner, diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 8140cc19e..ee40fcfd1 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -68,7 +68,7 @@ unsafe fn unjust_window_rect(prc: &mut RECT, style: DWORD, ex_style: DWORD) -> B } impl Window { - pub fn new( + pub fn new( event_loop: &EventLoop, w_attr: WindowAttributes, pl_attr: PlatformSpecificWindowBuilderAttributes, @@ -91,7 +91,11 @@ impl Window { panic!("OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`"); } - let file_drop_handler = FileDropHandler::new(win.window.0/*, event_loop.event_send.clone()*/); + let file_drop_runner = event_loop.runner_shared.clone(); + let file_drop_handler = FileDropHandler::new( + win.window.0, + Box::new(move |event| if let Ok(e) = event.map_nonuser_event() {file_drop_runner.send_event(e)}) + ); let handler_interface_ptr = &mut (*file_drop_handler.data).interface as LPDROPTARGET; assert_eq!(ole2::RegisterDragDrop(win.window.0, handler_interface_ptr), S_OK); @@ -849,7 +853,7 @@ pub unsafe fn adjust_size( (rect.right - rect.left, rect.bottom - rect.top) } -unsafe fn init( +unsafe fn init( mut attributes: WindowAttributes, mut pl_attribs: PlatformSpecificWindowBuilderAttributes, event_loop: &event_loop::EventLoop, diff --git a/src/window.rs b/src/window.rs index eeed57aa3..05fe6a552 100644 --- a/src/window.rs +++ b/src/window.rs @@ -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, event_loop: &EventLoop) -> 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 @@ -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: &EventLoop) -> Result { let builder = WindowBuilder::new(); builder.build(event_loop) }