mirror of
https://github.com/rust-windowing/winit.git
synced 2026-09-03 07:10:05 -04:00
Remove crossbeam dependency and make drop events work again
This commit is contained in:
@@ -35,9 +35,6 @@ cocoa = "0.18.4"
|
|||||||
core-foundation = "0.6"
|
core-foundation = "0.6"
|
||||||
core-graphics = "0.17.3"
|
core-graphics = "0.17.3"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies.crossbeam-channel]
|
|
||||||
version = "0.3"
|
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies.winapi]
|
[target.'cfg(target_os = "windows")'.dependencies.winapi]
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
features = [
|
features = [
|
||||||
|
|||||||
@@ -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
|
/// 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
|
/// `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.
|
/// `EventLoopProxy` allows you to wake up an `EventLoop` from an other thread.
|
||||||
pub struct EventLoop<T> {
|
pub struct EventLoop<T: 'static> {
|
||||||
pub(crate) event_loop: platform_impl::EventLoop<T>,
|
pub(crate) event_loop: platform_impl::EventLoop<T>,
|
||||||
pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync
|
pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,9 +89,6 @@ extern crate serde;
|
|||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
extern crate winapi;
|
extern crate winapi;
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
#[macro_use]
|
|
||||||
extern crate crossbeam_channel;
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate objc;
|
extern crate objc;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use std::os::windows::ffi::OsStringExt;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
use crossbeam_channel::Sender;
|
|
||||||
|
|
||||||
use winapi::ctypes::c_void;
|
use winapi::ctypes::c_void;
|
||||||
use winapi::shared::guiddef::REFIID;
|
use winapi::shared::guiddef::REFIID;
|
||||||
@@ -25,7 +24,7 @@ pub struct FileDropHandlerData {
|
|||||||
pub interface: IDropTarget,
|
pub interface: IDropTarget,
|
||||||
refcount: AtomicUsize,
|
refcount: AtomicUsize,
|
||||||
window: HWND,
|
window: HWND,
|
||||||
// event_sender: Sender<Event<()>>
|
send_event: Box<Fn(Event<()>)>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FileDropHandler {
|
pub struct FileDropHandler {
|
||||||
@@ -34,14 +33,14 @@ pub struct FileDropHandler {
|
|||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
impl FileDropHandler {
|
impl FileDropHandler {
|
||||||
pub fn new(window: HWND/*, event_sender: Sender<Event<()>>*/) -> FileDropHandler {
|
pub fn new(window: HWND, send_event: Box<Fn(Event<()>)>) -> FileDropHandler {
|
||||||
let data = Box::new(FileDropHandlerData {
|
let data = Box::new(FileDropHandlerData {
|
||||||
interface: IDropTarget {
|
interface: IDropTarget {
|
||||||
lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl,
|
lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl,
|
||||||
},
|
},
|
||||||
refcount: AtomicUsize::new(1),
|
refcount: AtomicUsize::new(1),
|
||||||
window,
|
window,
|
||||||
// event_sender,
|
send_event,
|
||||||
});
|
});
|
||||||
FileDropHandler {
|
FileDropHandler {
|
||||||
data: Box::into_raw(data),
|
data: Box::into_raw(data),
|
||||||
@@ -187,7 +186,7 @@ impl FileDropHandler {
|
|||||||
|
|
||||||
impl FileDropHandlerData {
|
impl FileDropHandlerData {
|
||||||
fn send_event(&self, event: Event<()>) {
|
fn send_event(&self, event: Event<()>) {
|
||||||
// self.event_sender.send(event).ok();
|
(self.send_event)(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ use winapi::shared::basetsd::UINT_PTR;
|
|||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::mpsc::{self, Sender, Receiver};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use crossbeam_channel::{self, Sender, Receiver};
|
|
||||||
|
|
||||||
use winapi::ctypes::c_int;
|
use winapi::ctypes::c_int;
|
||||||
use winapi::shared::minwindef::{
|
use winapi::shared::minwindef::{
|
||||||
@@ -147,7 +147,7 @@ pub struct EventLoop<T> {
|
|||||||
pub(crate) runner_shared: EventLoopRunnerShared<T>,
|
pub(crate) runner_shared: EventLoopRunnerShared<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> EventLoop<T> {
|
impl<T: 'static> EventLoop<T> {
|
||||||
pub fn new() -> EventLoop<T> {
|
pub fn new() -> EventLoop<T> {
|
||||||
Self::with_dpi_awareness(true)
|
Self::with_dpi_awareness(true)
|
||||||
}
|
}
|
||||||
@@ -181,27 +181,24 @@ impl<T> EventLoop<T> {
|
|||||||
where F: FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow)
|
where F: FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow)
|
||||||
{
|
{
|
||||||
unsafe{ winuser::IsGUIThread(1); }
|
unsafe{ winuser::IsGUIThread(1); }
|
||||||
let mut runner = EventLoopRunner {
|
|
||||||
event_loop: self,
|
assert_eq!(mem::size_of::<RootEventLoop<T>>(), mem::size_of::<EventLoop<T>>());
|
||||||
control_flow: ControlFlow::default(),
|
let self_ptr = self as *const EventLoop<T>;
|
||||||
runner_state: RunnerState::New,
|
|
||||||
in_modal_loop: false,
|
let mut runner = unsafe{ EventLoopRunner::new(
|
||||||
modal_redraw_window: self.thread_msg_target,
|
self,
|
||||||
event_handler: unsafe {
|
move |event, control_flow| {
|
||||||
// Transmute used to erase lifetimes.
|
let event_loop_ref = &*(self_ptr as *const RootEventLoop<T>);
|
||||||
mem::transmute::<
|
event_handler(event, event_loop_ref, control_flow)
|
||||||
&mut FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow),
|
|
||||||
*mut FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow)
|
|
||||||
>(&mut event_handler)
|
|
||||||
}
|
}
|
||||||
};
|
) };
|
||||||
{
|
{
|
||||||
let runner_shared = self.runner_shared.clone();
|
let runner_shared = self.runner_shared.clone();
|
||||||
let mut runner_ref = runner_shared.runner.borrow_mut();
|
let mut runner_ref = runner_shared.runner.borrow_mut();
|
||||||
loop {
|
loop {
|
||||||
let event = runner_shared.buffer.borrow_mut().pop_front();
|
let event = runner_shared.buffer.borrow_mut().pop_front();
|
||||||
match event {
|
match event {
|
||||||
Some(e) => unsafe{ runner.process_event(e); },
|
Some(e) => { runner.process_event(e); },
|
||||||
None => break
|
None => break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +243,7 @@ impl<T> EventLoop<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe{ runner!().call_event_handler(Event::LoopDestroyed) }
|
runner!().call_event_handler(Event::LoopDestroyed);
|
||||||
*self.runner_shared.runner.borrow_mut() = None;
|
*self.runner_shared.runner.borrow_mut() = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,16 +269,16 @@ pub(crate) struct ELRShared<T> {
|
|||||||
buffer: RefCell<VecDeque<Event<T>>>
|
buffer: RefCell<VecDeque<Event<T>>>
|
||||||
}
|
}
|
||||||
pub(crate) struct EventLoopRunner<T> {
|
pub(crate) struct EventLoopRunner<T> {
|
||||||
event_loop: *const EventLoop<T>,
|
trigger_newevents_on_redraw: Arc<AtomicBool>,
|
||||||
control_flow: ControlFlow,
|
control_flow: ControlFlow,
|
||||||
runner_state: RunnerState,
|
runner_state: RunnerState,
|
||||||
modal_redraw_window: HWND,
|
modal_redraw_window: HWND,
|
||||||
in_modal_loop: bool,
|
in_modal_loop: bool,
|
||||||
event_handler: *mut FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow)
|
event_handler: Box<FnMut(Event<T>, &mut ControlFlow)>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ELRShared<T> {
|
impl<T> ELRShared<T> {
|
||||||
unsafe fn send_event(&self, event: Event<T>) {
|
pub(crate) unsafe fn send_event(&self, event: Event<T>) {
|
||||||
if let Ok(mut runner_ref) = self.runner.try_borrow_mut() {
|
if let Ok(mut runner_ref) = self.runner.try_borrow_mut() {
|
||||||
if let Some(ref mut runner) = *runner_ref {
|
if let Some(ref mut runner) = *runner_ref {
|
||||||
runner.process_event(event);
|
runner.process_event(event);
|
||||||
@@ -308,7 +305,23 @@ enum RunnerState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> EventLoopRunner<T> {
|
impl<T> EventLoopRunner<T> {
|
||||||
unsafe fn new_events(&mut self) {
|
unsafe fn new<F>(event_loop: &EventLoop<T>, f: F) -> EventLoopRunner<T>
|
||||||
|
where F: FnMut(Event<T>, &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<FnMut(Event<T>, &mut ControlFlow)>,
|
||||||
|
Box<FnMut(Event<T>, &mut ControlFlow)>
|
||||||
|
>(Box::new(f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_events(&mut self) {
|
||||||
self.runner_state = match self.runner_state {
|
self.runner_state = match self.runner_state {
|
||||||
// If we're already handling events or have deferred `NewEvents`, we don't need to do
|
// If we're already handling events or have deferred `NewEvents`, we don't need to do
|
||||||
// do any processing.
|
// do any processing.
|
||||||
@@ -359,13 +372,14 @@ impl<T> EventLoopRunner<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn process_event(&mut self, event: Event<T>) {
|
fn process_event(&mut self, event: Event<T>) {
|
||||||
// If we're in the modal loop, we need to have some mechanism for finding when the 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
|
// 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
|
// 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
|
// been processed. So, we send WM_PAINT to a dummy window which calls `events_cleared` when
|
||||||
// the events queue has been emptied.
|
// the events queue has been emptied.
|
||||||
if self.in_modal_loop {
|
if self.in_modal_loop {
|
||||||
|
unsafe {
|
||||||
winuser::RedrawWindow(
|
winuser::RedrawWindow(
|
||||||
self.modal_redraw_window,
|
self.modal_redraw_window,
|
||||||
ptr::null(),
|
ptr::null(),
|
||||||
@@ -373,6 +387,7 @@ impl<T> EventLoopRunner<T> {
|
|||||||
winuser::RDW_INTERNALPAINT
|
winuser::RDW_INTERNALPAINT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If new event processing has to be done (i.e. call NewEvents or defer), do it. If we're
|
// If new event processing has to be done (i.e. call NewEvents or defer), do it. If we're
|
||||||
// already in processing nothing happens with this call.
|
// already in processing nothing happens with this call.
|
||||||
@@ -419,7 +434,7 @@ impl<T> EventLoopRunner<T> {
|
|||||||
self.call_event_handler(event);
|
self.call_event_handler(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn events_cleared(&mut self) {
|
fn events_cleared(&mut self) {
|
||||||
match self.runner_state {
|
match self.runner_state {
|
||||||
// If we were handling events, send the EventsCleared message.
|
// If we were handling events, send the EventsCleared message.
|
||||||
RunnerState::HandlingEvents => {
|
RunnerState::HandlingEvents => {
|
||||||
@@ -462,20 +477,18 @@ impl<T> EventLoopRunner<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn call_event_handler(&mut self, event: Event<T>) {
|
fn call_event_handler(&mut self, event: Event<T>) {
|
||||||
match event {
|
match event {
|
||||||
Event::NewEvents(_) => (*self.event_loop).trigger_newevents_on_redraw.store(true, Ordering::Relaxed),
|
Event::NewEvents(_) => self.trigger_newevents_on_redraw.store(true, Ordering::Relaxed),
|
||||||
Event::EventsCleared => (*self.event_loop).trigger_newevents_on_redraw.store(false, Ordering::Relaxed),
|
Event::EventsCleared => self.trigger_newevents_on_redraw.store(false, Ordering::Relaxed),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(mem::size_of::<RootEventLoop<T>>(), mem::size_of::<EventLoop<T>>());
|
|
||||||
let event_loop_ref = &*(self.event_loop as *const RootEventLoop<T>);
|
|
||||||
|
|
||||||
if self.control_flow != ControlFlow::Exit {
|
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 {
|
} 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<T>(event_loop_runner: EventLoopRunnerShared<T>) ->
|
|||||||
(winuser::WS_VISIBLE | winuser::WS_POPUP) as _
|
(winuser::WS_VISIBLE | winuser::WS_POPUP) as _
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tx, rx) = crossbeam_channel::unbounded();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
let subclass_input = ThreadMsgTargetSubclassInput {
|
let subclass_input = ThreadMsgTargetSubclassInput {
|
||||||
event_loop_runner,
|
event_loop_runner,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ unsafe fn unjust_window_rect(prc: &mut RECT, style: DWORD, ex_style: DWORD) -> B
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new<T>(
|
pub fn new<T: 'static>(
|
||||||
event_loop: &EventLoop<T>,
|
event_loop: &EventLoop<T>,
|
||||||
w_attr: WindowAttributes,
|
w_attr: WindowAttributes,
|
||||||
pl_attr: PlatformSpecificWindowBuilderAttributes,
|
pl_attr: PlatformSpecificWindowBuilderAttributes,
|
||||||
@@ -91,7 +91,11 @@ impl Window {
|
|||||||
panic!("OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`");
|
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;
|
let handler_interface_ptr = &mut (*file_drop_handler.data).interface as LPDROPTARGET;
|
||||||
|
|
||||||
assert_eq!(ole2::RegisterDragDrop(win.window.0, handler_interface_ptr), S_OK);
|
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)
|
(rect.right - rect.left, rect.bottom - rect.top)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init<T>(
|
unsafe fn init<T: 'static>(
|
||||||
mut attributes: WindowAttributes,
|
mut attributes: WindowAttributes,
|
||||||
mut pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
mut pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||||
event_loop: &event_loop::EventLoop<T>,
|
event_loop: &event_loop::EventLoop<T>,
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ impl WindowBuilder {
|
|||||||
/// Error should be very rare and only occur in case of permission denied, incompatible system,
|
/// Error should be very rare and only occur in case of permission denied, incompatible system,
|
||||||
/// out of memory, etc.
|
/// out of memory, etc.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build<T>(mut self, event_loop: &EventLoop<T>) -> Result<Window, CreationError> {
|
pub fn build<T: 'static>(mut self, event_loop: &EventLoop<T>) -> Result<Window, CreationError> {
|
||||||
self.window.dimensions = Some(self.window.dimensions.unwrap_or_else(|| {
|
self.window.dimensions = Some(self.window.dimensions.unwrap_or_else(|| {
|
||||||
if let Some(ref monitor) = self.window.fullscreen {
|
if let Some(ref monitor) = self.window.fullscreen {
|
||||||
// resizing the window to the dimensions of the monitor when 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,
|
/// Error should be very rare and only occur in case of permission denied, incompatible system,
|
||||||
/// out of memory, etc.
|
/// out of memory, etc.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new<T>(event_loop: &EventLoop<T>) -> Result<Window, CreationError> {
|
pub fn new<T: 'static>(event_loop: &EventLoop<T>) -> Result<Window, CreationError> {
|
||||||
let builder = WindowBuilder::new();
|
let builder = WindowBuilder::new();
|
||||||
builder.build(event_loop)
|
builder.build(event_loop)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user