Remove lifetime from the Event
Lifetimes don't work nicely when dealing with multithreaded environments in the current design of the existing winit's event handling model, so remove it in favor of `InnerSizeWriter` fences passed to client, so they could try to update the size. Fixes #1387.
This commit is contained in:
parent
2b2dd6b65d
commit
9ac3259a79
31 changed files with 252 additions and 429 deletions
|
|
@ -30,7 +30,7 @@ pub struct FileDropHandlerData {
|
|||
pub interface: IDropTarget,
|
||||
refcount: AtomicUsize,
|
||||
window: HWND,
|
||||
send_event: Box<dyn Fn(Event<'static, ()>)>,
|
||||
send_event: Box<dyn Fn(Event<()>)>,
|
||||
cursor_effect: u32,
|
||||
hovered_is_valid: bool, /* If the currently hovered item is not valid there must not be any `HoveredFileCancelled` emitted */
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ pub struct FileDropHandler {
|
|||
|
||||
#[allow(non_snake_case)]
|
||||
impl FileDropHandler {
|
||||
pub fn new(window: HWND, send_event: Box<dyn Fn(Event<'static, ()>)>) -> FileDropHandler {
|
||||
pub fn new(window: HWND, send_event: Box<dyn Fn(Event<()>)>) -> FileDropHandler {
|
||||
let data = Box::new(FileDropHandlerData {
|
||||
interface: IDropTarget {
|
||||
lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl,
|
||||
|
|
@ -211,7 +211,7 @@ impl FileDropHandler {
|
|||
}
|
||||
|
||||
impl FileDropHandlerData {
|
||||
fn send_event(&self, event: Event<'static, ()>) {
|
||||
fn send_event(&self, event: Event<()>) {
|
||||
(self.send_event)(event);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,10 @@ use windows_sys::Win32::{
|
|||
use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize},
|
||||
error::RunLoopError,
|
||||
event::{DeviceEvent, Event, Force, Ime, RawKeyEvent, Touch, TouchPhase, WindowEvent},
|
||||
event::{
|
||||
DeviceEvent, Event, Force, Ime, InnerSizeWriter, RawKeyEvent, Touch, TouchPhase,
|
||||
WindowEvent,
|
||||
},
|
||||
event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW},
|
||||
keyboard::{KeyCode, ModifiersState},
|
||||
platform::{pump_events::PumpStatus, scancode::KeyCodeExtScancode},
|
||||
|
|
@ -142,7 +145,7 @@ pub(crate) struct WindowData<T: 'static> {
|
|||
}
|
||||
|
||||
impl<T> WindowData<T> {
|
||||
unsafe fn send_event(&self, event: Event<'_, T>) {
|
||||
unsafe fn send_event(&self, event: Event<T>) {
|
||||
self.event_loop_runner.send_event(event);
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +160,7 @@ struct ThreadMsgTargetData<T: 'static> {
|
|||
}
|
||||
|
||||
impl<T> ThreadMsgTargetData<T> {
|
||||
unsafe fn send_event(&self, event: Event<'_, T>) {
|
||||
unsafe fn send_event(&self, event: Event<T>) {
|
||||
self.event_loop_runner.send_event(event);
|
||||
}
|
||||
}
|
||||
|
|
@ -245,14 +248,14 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
pub fn run<F>(mut self, event_handler: F) -> Result<(), RunLoopError>
|
||||
where
|
||||
F: 'static + FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
self.run_ondemand(event_handler)
|
||||
}
|
||||
|
||||
pub fn run_ondemand<F>(&mut self, mut event_handler: F) -> Result<(), RunLoopError>
|
||||
where
|
||||
F: FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
F: FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
{
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
|
@ -298,7 +301,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
pub fn pump_events<F>(&mut self, timeout: Option<Duration>, mut event_handler: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
F: FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
{
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
|
@ -2051,7 +2054,7 @@ unsafe fn public_window_callback_inner<T: 'static>(
|
|||
|
||||
// `allow_resize` prevents us from re-applying DPI adjustment to the restored size after
|
||||
// exiting fullscreen (the restored size is already DPI adjusted).
|
||||
let mut new_physical_inner_size = match allow_resize {
|
||||
let new_physical_inner_size = match allow_resize {
|
||||
// We calculate our own size because the default suggested rect doesn't do a great job
|
||||
// of preserving the window's logical size.
|
||||
true => old_physical_inner_size
|
||||
|
|
@ -2060,14 +2063,18 @@ unsafe fn public_window_callback_inner<T: 'static>(
|
|||
false => old_physical_inner_size,
|
||||
};
|
||||
|
||||
let new_inner_size = Arc::new(Mutex::new(new_physical_inner_size));
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(WindowId(window)),
|
||||
event: ScaleFactorChanged {
|
||||
scale_factor: new_scale_factor,
|
||||
new_inner_size: &mut new_physical_inner_size,
|
||||
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)),
|
||||
},
|
||||
});
|
||||
|
||||
let new_physical_inner_size = *new_inner_size.lock().unwrap();
|
||||
drop(new_inner_size);
|
||||
|
||||
let dragging_window: bool;
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
collections::VecDeque,
|
||||
mem, panic,
|
||||
rc::Rc,
|
||||
sync::{Arc, Mutex},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
|
|
@ -11,7 +12,7 @@ use windows_sys::Win32::Foundation::HWND;
|
|||
|
||||
use crate::{
|
||||
dpi::PhysicalSize,
|
||||
event::{Event, StartCause, WindowEvent},
|
||||
event::{Event, InnerSizeWriter, StartCause, WindowEvent},
|
||||
event_loop::ControlFlow,
|
||||
platform_impl::platform::{
|
||||
event_loop::{WindowData, GWL_USERDATA},
|
||||
|
|
@ -22,7 +23,7 @@ use crate::{
|
|||
|
||||
pub(crate) type EventLoopRunnerShared<T> = Rc<EventLoopRunner<T>>;
|
||||
|
||||
type EventHandler<T> = Cell<Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>>;
|
||||
type EventHandler<T> = Cell<Option<Box<dyn FnMut(Event<T>, &mut ControlFlow)>>>;
|
||||
|
||||
pub(crate) struct EventLoopRunner<T: 'static> {
|
||||
// The event loop's win32 handles
|
||||
|
|
@ -59,7 +60,7 @@ pub(crate) enum RunnerState {
|
|||
}
|
||||
|
||||
enum BufferedEvent<T: 'static> {
|
||||
Event(Event<'static, T>),
|
||||
Event(Event<T>),
|
||||
ScaleFactorChanged(WindowId, f64, PhysicalSize<u32>),
|
||||
}
|
||||
|
||||
|
|
@ -90,11 +91,11 @@ impl<T> EventLoopRunner<T> {
|
|||
/// undefined behaviour.
|
||||
pub(crate) unsafe fn set_event_handler<F>(&self, f: F)
|
||||
where
|
||||
F: FnMut(Event<'_, T>, &mut ControlFlow),
|
||||
F: FnMut(Event<T>, &mut ControlFlow),
|
||||
{
|
||||
let old_event_handler = self.event_handler.replace(mem::transmute::<
|
||||
Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>,
|
||||
Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>,
|
||||
Option<Box<dyn FnMut(Event<T>, &mut ControlFlow)>>,
|
||||
Option<Box<dyn FnMut(Event<T>, &mut ControlFlow)>>,
|
||||
>(Some(Box::new(f))));
|
||||
assert!(old_event_handler.is_none());
|
||||
}
|
||||
|
|
@ -196,7 +197,7 @@ impl<T> EventLoopRunner<T> {
|
|||
self.move_state_to(RunnerState::HandlingMainEvents);
|
||||
}
|
||||
|
||||
pub(crate) fn send_event(&self, event: Event<'_, T>) {
|
||||
pub(crate) fn send_event(&self, event: Event<T>) {
|
||||
if let Event::RedrawRequested(_) = event {
|
||||
self.call_event_handler(event);
|
||||
// As a rule, to ensure that `pump_events` can't block an external event loop
|
||||
|
|
@ -219,7 +220,7 @@ impl<T> EventLoopRunner<T> {
|
|||
self.move_state_to(RunnerState::Destroyed);
|
||||
}
|
||||
|
||||
fn call_event_handler(&self, event: Event<'_, T>) {
|
||||
fn call_event_handler(&self, event: Event<T>) {
|
||||
self.catch_unwind(|| {
|
||||
let mut control_flow = self.control_flow.take();
|
||||
let mut event_handler = self.event_handler.take()
|
||||
|
|
@ -361,38 +362,50 @@ impl<T> EventLoopRunner<T> {
|
|||
}
|
||||
|
||||
impl<T> BufferedEvent<T> {
|
||||
pub fn from_event(event: Event<'_, T>) -> BufferedEvent<T> {
|
||||
pub fn from_event(event: Event<T>) -> BufferedEvent<T> {
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
event:
|
||||
WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
new_inner_size,
|
||||
inner_size_writer,
|
||||
},
|
||||
window_id,
|
||||
} => BufferedEvent::ScaleFactorChanged(window_id, scale_factor, *new_inner_size),
|
||||
event => BufferedEvent::Event(event.to_static().unwrap()),
|
||||
} => BufferedEvent::ScaleFactorChanged(
|
||||
window_id,
|
||||
scale_factor,
|
||||
*inner_size_writer
|
||||
.new_inner_size
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap(),
|
||||
),
|
||||
event => BufferedEvent::Event(event),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dispatch_event(self, dispatch: impl FnOnce(Event<'_, T>)) {
|
||||
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) => {
|
||||
Self::ScaleFactorChanged(window_id, scale_factor, new_inner_size) => {
|
||||
let new_inner_size = Arc::new(Mutex::new(new_inner_size));
|
||||
dispatch(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
new_inner_size: &mut new_inner_size,
|
||||
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)),
|
||||
},
|
||||
});
|
||||
let inner_size = *new_inner_size.lock().unwrap();
|
||||
drop(new_inner_size);
|
||||
|
||||
let window_flags = unsafe {
|
||||
let userdata =
|
||||
get_window_long(window_id.0.into(), GWL_USERDATA) as *mut WindowData<T>;
|
||||
(*userdata).window_state_lock().window_flags
|
||||
};
|
||||
window_flags.set_size((window_id.0).0, new_inner_size);
|
||||
window_flags.set_size((window_id.0).0, inner_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue