macOS: Call ApplicationHandler directly instead of using Event (#3753)

Additionally, always queue events in `handle_scale_factor_changed`.

These events were intentionally not queued before, since they are
executed inside `handle_scale_factor_changed`, which is itself queued.
Though that's a bit too subtle, so let's just take the minuscule perf
hit of redundantly checking whether we need to queue again.

Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
This commit is contained in:
Mads Marquart 2024-06-23 23:14:22 +02:00 committed by GitHub
parent 10dc0674bb
commit c0c14aaf00
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 184 additions and 103 deletions

View file

@ -5,6 +5,7 @@ use objc2_app_kit::{NSApplication, NSEvent, NSEventModifierFlags, NSEventType, N
use objc2_foundation::{MainThreadMarker, NSObject}; use objc2_foundation::{MainThreadMarker, NSObject};
use super::app_state::ApplicationDelegate; use super::app_state::ApplicationDelegate;
use super::DEVICE_ID;
use crate::event::{DeviceEvent, ElementState}; use crate::event::{DeviceEvent, ElementState};
declare_class!( declare_class!(
@ -57,29 +58,47 @@ fn maybe_dispatch_device_event(delegate: &ApplicationDelegate, event: &NSEvent)
let delta_y = unsafe { event.deltaY() } as f64; let delta_y = unsafe { event.deltaY() } as f64;
if delta_x != 0.0 { if delta_x != 0.0 {
delegate.maybe_queue_device_event(DeviceEvent::Motion { axis: 0, value: delta_x }); delegate.maybe_queue_with_handler(move |app, event_loop| {
app.device_event(event_loop, DEVICE_ID, DeviceEvent::Motion {
axis: 0,
value: delta_x,
});
});
} }
if delta_y != 0.0 { if delta_y != 0.0 {
delegate.maybe_queue_device_event(DeviceEvent::Motion { axis: 1, value: delta_y }) delegate.maybe_queue_with_handler(move |app, event_loop| {
app.device_event(event_loop, DEVICE_ID, DeviceEvent::Motion {
axis: 1,
value: delta_y,
});
})
} }
if delta_x != 0.0 || delta_y != 0.0 { if delta_x != 0.0 || delta_y != 0.0 {
delegate.maybe_queue_device_event(DeviceEvent::MouseMotion { delegate.maybe_queue_with_handler(move |app, event_loop| {
delta: (delta_x, delta_y), app.device_event(event_loop, DEVICE_ID, DeviceEvent::MouseMotion {
delta: (delta_x, delta_y),
});
}); });
} }
}, },
NSEventType::LeftMouseDown | NSEventType::RightMouseDown | NSEventType::OtherMouseDown => { NSEventType::LeftMouseDown | NSEventType::RightMouseDown | NSEventType::OtherMouseDown => {
delegate.maybe_queue_device_event(DeviceEvent::Button { let button = unsafe { event.buttonNumber() } as u32;
button: unsafe { event.buttonNumber() } as u32, delegate.maybe_queue_with_handler(move |app, event_loop| {
state: ElementState::Pressed, app.device_event(event_loop, DEVICE_ID, DeviceEvent::Button {
button,
state: ElementState::Pressed,
});
}); });
}, },
NSEventType::LeftMouseUp | NSEventType::RightMouseUp | NSEventType::OtherMouseUp => { NSEventType::LeftMouseUp | NSEventType::RightMouseUp | NSEventType::OtherMouseUp => {
delegate.maybe_queue_device_event(DeviceEvent::Button { let button = unsafe { event.buttonNumber() } as u32;
button: unsafe { event.buttonNumber() } as u32, delegate.maybe_queue_with_handler(move |app, event_loop| {
state: ElementState::Released, app.device_event(event_loop, DEVICE_ID, DeviceEvent::Button {
button,
state: ElementState::Released,
});
}); });
}, },
_ => (), _ => (),

View file

@ -8,13 +8,15 @@ use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass};
use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy, NSApplicationDelegate}; use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy, NSApplicationDelegate};
use objc2_foundation::{MainThreadMarker, NSNotification, NSObject, NSObjectProtocol}; use objc2_foundation::{MainThreadMarker, NSNotification, NSObject, NSObjectProtocol};
use crate::application::ApplicationHandler;
use crate::event::{StartCause, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow};
use crate::window::WindowId as RootWindowId;
use super::event_handler::EventHandler; use super::event_handler::EventHandler;
use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo}; use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo};
use super::observer::{EventLoopWaker, RunLoop}; use super::observer::{EventLoopWaker, RunLoop};
use super::{menu, WindowId, DEVICE_ID}; use super::{menu, WindowId};
use crate::event::{DeviceEvent, Event, StartCause, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow};
use crate::window::WindowId as RootWindowId;
#[derive(Debug)] #[derive(Debug)]
pub(super) struct AppState { pub(super) struct AppState {
@ -166,7 +168,7 @@ impl ApplicationDelegate {
/// of the given closure. /// of the given closure.
pub fn set_event_handler<R>( pub fn set_event_handler<R>(
&self, &self,
handler: impl FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop), handler: &mut dyn ApplicationHandler<HandlePendingUserEvents>,
closure: impl FnOnce() -> R, closure: impl FnOnce() -> R,
) -> R { ) -> R {
self.ivars().event_handler.set(handler, closure) self.ivars().event_handler.set(handler, closure)
@ -200,7 +202,9 @@ impl ApplicationDelegate {
/// NOTE: that if the `NSApplication` has been launched then that state is preserved, /// NOTE: that if the `NSApplication` has been launched then that state is preserved,
/// and we won't need to re-launch the app if subsequent EventLoops are run. /// and we won't need to re-launch the app if subsequent EventLoops are run.
pub fn internal_exit(&self) { pub fn internal_exit(&self) {
self.handle_event(Event::LoopExiting); self.with_handler(|app, event_loop| {
app.exiting(event_loop);
});
self.set_is_running(false); self.set_is_running(false);
self.set_stop_on_redraw(false); self.set_stop_on_redraw(false);
@ -241,26 +245,13 @@ impl ApplicationDelegate {
self.ivars().control_flow.get() self.ivars().control_flow.get()
} }
pub fn maybe_queue_window_event(&self, window_id: WindowId, event: WindowEvent) {
self.maybe_queue_event(Event::WindowEvent { window_id: RootWindowId(window_id), event });
}
pub fn handle_window_event(&self, window_id: WindowId, event: WindowEvent) {
self.handle_event(Event::WindowEvent { window_id: RootWindowId(window_id), event });
}
pub fn maybe_queue_device_event(&self, event: DeviceEvent) {
self.maybe_queue_event(Event::DeviceEvent { device_id: DEVICE_ID, event });
}
pub fn handle_redraw(&self, window_id: WindowId) { pub fn handle_redraw(&self, window_id: WindowId) {
let mtm = MainThreadMarker::from(self); let mtm = MainThreadMarker::from(self);
// Redraw request might come out of order from the OS. // Redraw request might come out of order from the OS.
// -> Don't go back into the event handler when our callstack originates from there // -> Don't go back into the event handler when our callstack originates from there
if !self.ivars().event_handler.in_use() { if !self.ivars().event_handler.in_use() {
self.handle_event(Event::WindowEvent { self.with_handler(|app, event_loop| {
window_id: RootWindowId(window_id), app.window_event(event_loop, RootWindowId(window_id), WindowEvent::RedrawRequested);
event: WindowEvent::RedrawRequested,
}); });
// `pump_events` will request to stop immediately _after_ dispatching RedrawRequested // `pump_events` will request to stop immediately _after_ dispatching RedrawRequested
@ -282,7 +273,11 @@ impl ApplicationDelegate {
} }
#[track_caller] #[track_caller]
fn maybe_queue_event(&self, event: Event<HandlePendingUserEvents>) { pub fn maybe_queue_with_handler(
&self,
callback: impl FnOnce(&mut dyn ApplicationHandler<HandlePendingUserEvents>, &RootActiveEventLoop)
+ 'static,
) {
// Most programmer actions in AppKit (e.g. change window fullscreen, set focused, etc.) // Most programmer actions in AppKit (e.g. change window fullscreen, set focused, etc.)
// result in an event being queued, and applied at a later point. // result in an event being queued, and applied at a later point.
// //
@ -290,25 +285,33 @@ impl ApplicationDelegate {
// so to make sure that we don't encounter re-entrancy issues, we first check if we're // so to make sure that we don't encounter re-entrancy issues, we first check if we're
// currently handling another event, and if we are, we queue the event instead. // currently handling another event, and if we are, we queue the event instead.
if !self.ivars().event_handler.in_use() { if !self.ivars().event_handler.in_use() {
self.handle_event(event); self.with_handler(callback);
} else { } else {
tracing::debug!(?event, "had to queue event since another is currently being handled"); tracing::debug!("had to queue event since another is currently being handled");
let this = self.retain(); let this = self.retain();
self.ivars().run_loop.queue_closure(move || this.handle_event(event)); self.ivars().run_loop.queue_closure(move || {
this.with_handler(callback);
});
} }
} }
#[track_caller] #[track_caller]
fn handle_event(&self, event: Event<HandlePendingUserEvents>) { fn with_handler<
self.ivars().event_handler.handle_event(event, &ActiveEventLoop::new_root(self.retain())) F: FnOnce(&mut dyn ApplicationHandler<HandlePendingUserEvents>, &RootActiveEventLoop),
>(
&self,
callback: F,
) {
let event_loop = ActiveEventLoop::new_root(self.retain());
self.ivars().event_handler.handle(callback, &event_loop);
} }
/// dispatch `NewEvents(Init)` + `Resumed` /// dispatch `NewEvents(Init)` + `Resumed`
pub fn dispatch_init_events(&self) { pub fn dispatch_init_events(&self) {
self.handle_event(Event::NewEvents(StartCause::Init)); self.with_handler(|app, event_loop| app.new_events(event_loop, StartCause::Init));
// NB: For consistency all platforms must emit a 'resumed' event even though macOS // NB: For consistency all platforms must emit a 'resumed' event even though macOS
// applications don't themselves have a formal suspend/resume lifecycle. // applications don't themselves have a formal suspend/resume lifecycle.
self.handle_event(Event::Resumed); self.with_handler(|app, event_loop| app.resumed(event_loop));
} }
// Called by RunLoopObserver after finishing waiting for new events // Called by RunLoopObserver after finishing waiting for new events
@ -341,7 +344,7 @@ impl ApplicationDelegate {
}, },
}; };
self.handle_event(Event::NewEvents(cause)); self.with_handler(|app, event_loop| app.new_events(event_loop, cause));
} }
// Called by RunLoopObserver before waiting for new events // Called by RunLoopObserver before waiting for new events
@ -358,17 +361,17 @@ impl ApplicationDelegate {
return; return;
} }
self.handle_event(Event::UserEvent(HandlePendingUserEvents)); self.with_handler(|app, event_loop| app.user_event(event_loop, HandlePendingUserEvents));
let redraw = mem::take(&mut *self.ivars().pending_redraw.borrow_mut()); let redraw = mem::take(&mut *self.ivars().pending_redraw.borrow_mut());
for window_id in redraw { for window_id in redraw {
self.handle_event(Event::WindowEvent { self.with_handler(|app, event_loop| {
window_id: RootWindowId(window_id), app.window_event(event_loop, RootWindowId(window_id), WindowEvent::RedrawRequested);
event: WindowEvent::RedrawRequested,
}); });
} }
self.with_handler(|app, event_loop| {
self.handle_event(Event::AboutToWait); app.about_to_wait(event_loop);
});
if self.exiting() { if self.exiting() {
let app = NSApplication::sharedApplication(mtm); let app = NSApplication::sharedApplication(mtm);

View file

@ -2,31 +2,31 @@ use std::cell::RefCell;
use std::{fmt, mem}; use std::{fmt, mem};
use super::app_state::HandlePendingUserEvents; use super::app_state::HandlePendingUserEvents;
use crate::event::Event; use crate::application::ApplicationHandler;
use crate::event_loop::ActiveEventLoop as RootActiveEventLoop; use crate::event_loop::ActiveEventLoop as RootActiveEventLoop;
struct EventHandlerData { #[derive(Default)]
#[allow(clippy::type_complexity)]
handler: Box<dyn FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) + 'static>,
}
impl fmt::Debug for EventHandlerData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EventHandlerData").finish_non_exhaustive()
}
}
#[derive(Debug)]
pub(crate) struct EventHandler { pub(crate) struct EventHandler {
/// This can be in the following states: /// This can be in the following states:
/// - Not registered by the event loop (None). /// - Not registered by the event loop (None).
/// - Present (Some(handler)). /// - Present (Some(handler)).
/// - Currently executing the handler / in use (RefCell borrowed). /// - Currently executing the handler / in use (RefCell borrowed).
inner: RefCell<Option<EventHandlerData>>, inner: RefCell<Option<&'static mut dyn ApplicationHandler<HandlePendingUserEvents>>>,
}
impl fmt::Debug for EventHandler {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let state = match self.inner.try_borrow().as_deref() {
Ok(Some(_)) => "<available>",
Ok(None) => "<not set>",
Err(_) => "<in use>",
};
f.debug_struct("EventHandler").field("state", &state).finish_non_exhaustive()
}
} }
impl EventHandler { impl EventHandler {
pub(crate) const fn new() -> Self { pub(crate) fn new() -> Self {
Self { inner: RefCell::new(None) } Self { inner: RefCell::new(None) }
} }
@ -37,7 +37,7 @@ impl EventHandler {
/// from within the closure. /// from within the closure.
pub(crate) fn set<'handler, R>( pub(crate) fn set<'handler, R>(
&self, &self,
handler: impl FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) + 'handler, app: &'handler mut dyn ApplicationHandler<HandlePendingUserEvents>,
closure: impl FnOnce() -> R, closure: impl FnOnce() -> R,
) -> R { ) -> R {
// SAFETY: We extend the lifetime of the handler here so that we can // SAFETY: We extend the lifetime of the handler here so that we can
@ -48,9 +48,9 @@ impl EventHandler {
// extended beyond `'handler`. // extended beyond `'handler`.
let handler = unsafe { let handler = unsafe {
mem::transmute::< mem::transmute::<
Box<dyn FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) + 'handler>, &'handler mut dyn ApplicationHandler<HandlePendingUserEvents>,
Box<dyn FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) + 'static>, &'static mut dyn ApplicationHandler<HandlePendingUserEvents>,
>(Box::new(handler)) >(app)
}; };
match self.inner.try_borrow_mut().as_deref_mut() { match self.inner.try_borrow_mut().as_deref_mut() {
@ -58,7 +58,7 @@ impl EventHandler {
unreachable!("tried to set handler while another was already set"); unreachable!("tried to set handler while another was already set");
}, },
Ok(data @ None) => { Ok(data @ None) => {
*data = Some(EventHandlerData { handler }); *data = Some(handler);
}, },
Err(_) => { Err(_) => {
unreachable!("tried to set handler that is currently in use"); unreachable!("tried to set handler that is currently in use");
@ -109,20 +109,22 @@ impl EventHandler {
matches!(self.inner.try_borrow().as_deref(), Ok(Some(_))) matches!(self.inner.try_borrow().as_deref(), Ok(Some(_)))
} }
pub(crate) fn handle_event( pub(crate) fn handle<
F: FnOnce(&mut dyn ApplicationHandler<HandlePendingUserEvents>, &RootActiveEventLoop),
>(
&self, &self,
event: Event<HandlePendingUserEvents>, callback: F,
event_loop: &RootActiveEventLoop, event_loop: &RootActiveEventLoop,
) { ) {
match self.inner.try_borrow_mut().as_deref_mut() { match self.inner.try_borrow_mut().as_deref_mut() {
Ok(Some(EventHandlerData { handler })) => { Ok(Some(user_app)) => {
// It is important that we keep the reference borrowed here, // It is important that we keep the reference borrowed here,
// so that `in_use` can properly detect that the handler is // so that `in_use` can properly detect that the handler is
// still in use. // still in use.
// //
// If the handler unwinds, the `RefMut` will ensure that the // If the handler unwinds, the `RefMut` will ensure that the
// handler is no longer borrowed. // handler is no longer borrowed.
(handler)(event, event_loop); callback(*user_app, event_loop);
}, },
Ok(None) => { Ok(None) => {
// `NSApplication`, our app delegate and this handler are all // `NSApplication`, our app delegate and this handler are all

View file

@ -27,7 +27,6 @@ use super::monitor::{self, MonitorHandle};
use super::observer::setup_control_flow_observers; use super::observer::setup_control_flow_observers;
use crate::application::ApplicationHandler; use crate::application::ApplicationHandler;
use crate::error::EventLoopError; use crate::error::EventLoopError;
use crate::event::Event;
use crate::event_loop::{ use crate::event_loop::{
ActiveEventLoop as RootWindowTarget, ControlFlow, DeviceEvents, EventLoopClosed, ActiveEventLoop as RootWindowTarget, ControlFlow, DeviceEvents, EventLoopClosed,
}; };
@ -156,28 +155,78 @@ impl ActiveEventLoop {
} }
} }
fn map_user_event<T: 'static, A: ApplicationHandler<T>>( // Temporary helper, will be removed in https://github.com/rust-windowing/winit/pull/3694
app: &mut A, struct MapUserEvent<T, A> {
app: A,
receiver: Rc<mpsc::Receiver<T>>, receiver: Rc<mpsc::Receiver<T>>,
) -> impl FnMut(Event<HandlePendingUserEvents>, &RootWindowTarget) + '_ { }
move |event, window_target| match event {
Event::NewEvents(cause) => app.new_events(window_target, cause), impl<A: ApplicationHandler<T>, T: 'static> ApplicationHandler<HandlePendingUserEvents>
Event::WindowEvent { window_id, event } => { for MapUserEvent<T, A>
app.window_event(window_target, window_id, event) {
}, #[inline]
Event::DeviceEvent { device_id, event } => { fn new_events(
app.device_event(window_target, device_id, event) &mut self,
}, event_loop: &crate::event_loop::ActiveEventLoop,
Event::UserEvent(_) => { cause: crate::event::StartCause,
for event in receiver.try_iter() { ) {
app.user_event(window_target, event); self.app.new_events(event_loop, cause);
} }
},
Event::Suspended => app.suspended(window_target), #[inline]
Event::Resumed => app.resumed(window_target), fn resumed(&mut self, event_loop: &crate::event_loop::ActiveEventLoop) {
Event::AboutToWait => app.about_to_wait(window_target), self.app.resumed(event_loop);
Event::LoopExiting => app.exiting(window_target), }
Event::MemoryWarning => app.memory_warning(window_target),
#[inline]
fn user_event(
&mut self,
event_loop: &crate::event_loop::ActiveEventLoop,
_event: HandlePendingUserEvents,
) {
for event in self.receiver.try_iter() {
self.app.user_event(event_loop, event);
}
}
#[inline]
fn window_event(
&mut self,
event_loop: &crate::event_loop::ActiveEventLoop,
window_id: crate::window::WindowId,
event: crate::event::WindowEvent,
) {
self.app.window_event(event_loop, window_id, event);
}
#[inline]
fn device_event(
&mut self,
event_loop: &crate::event_loop::ActiveEventLoop,
device_id: crate::event::DeviceId,
event: crate::event::DeviceEvent,
) {
self.app.device_event(event_loop, device_id, event);
}
#[inline]
fn about_to_wait(&mut self, event_loop: &crate::event_loop::ActiveEventLoop) {
self.app.about_to_wait(event_loop);
}
#[inline]
fn suspended(&mut self, event_loop: &crate::event_loop::ActiveEventLoop) {
self.app.suspended(event_loop);
}
#[inline]
fn exiting(&mut self, event_loop: &crate::event_loop::ActiveEventLoop) {
self.app.exiting(event_loop);
}
#[inline]
fn memory_warning(&mut self, event_loop: &crate::event_loop::ActiveEventLoop) {
self.app.memory_warning(event_loop);
} }
} }
@ -284,9 +333,9 @@ impl<T> EventLoop<T> {
&mut self, &mut self,
app: &mut A, app: &mut A,
) -> Result<(), EventLoopError> { ) -> Result<(), EventLoopError> {
let handler = map_user_event(app, self.receiver.clone()); let mut handler = MapUserEvent { app, receiver: self.receiver.clone() };
self.delegate.set_event_handler(handler, || { self.delegate.set_event_handler(&mut handler, || {
autoreleasepool(|_| { autoreleasepool(|_| {
// clear / normalize pump_events state // clear / normalize pump_events state
self.delegate.set_wait_timeout(None); self.delegate.set_wait_timeout(None);
@ -324,9 +373,9 @@ impl<T> EventLoop<T> {
timeout: Option<Duration>, timeout: Option<Duration>,
app: &mut A, app: &mut A,
) -> PumpStatus { ) -> PumpStatus {
let handler = map_user_event(app, self.receiver.clone()); let mut handler = MapUserEvent { app, receiver: self.receiver.clone() };
self.delegate.set_event_handler(handler, || { self.delegate.set_event_handler(&mut handler, || {
autoreleasepool(|_| { autoreleasepool(|_| {
// As a special case, if the application hasn't been launched yet then we at least // As a special case, if the application hasn't been launched yet then we at least
// run the loop until it has fully launched. // run the loop until it has fully launched.

View file

@ -31,6 +31,7 @@ use crate::event::{
}; };
use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey}; use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey};
use crate::platform::macos::OptionAsAlt; use crate::platform::macos::OptionAsAlt;
use crate::window::WindowId as RootWindowId;
#[derive(Debug)] #[derive(Debug)]
struct CursorState { struct CursorState {
@ -686,7 +687,9 @@ declare_class!(
self.update_modifiers(event, false); self.update_modifiers(event, false);
self.ivars().app_delegate.maybe_queue_device_event(DeviceEvent::MouseWheel { delta }); self.ivars().app_delegate.maybe_queue_with_handler(move |app, event_loop|
app.device_event(event_loop, DEVICE_ID, DeviceEvent::MouseWheel { delta })
);
self.queue_event(WindowEvent::MouseWheel { self.queue_event(WindowEvent::MouseWheel {
device_id: DEVICE_ID, device_id: DEVICE_ID,
delta, delta,
@ -830,7 +833,10 @@ impl WinitView {
} }
fn queue_event(&self, event: WindowEvent) { fn queue_event(&self, event: WindowEvent) {
self.ivars().app_delegate.maybe_queue_window_event(self.window().id(), event); let window_id = RootWindowId(self.window().id());
self.ivars().app_delegate.maybe_queue_with_handler(move |app, event_loop| {
app.window_event(event_loop, window_id, event);
});
} }
fn scale_factor(&self) -> f64 { fn scale_factor(&self) -> f64 {

View file

@ -39,7 +39,7 @@ use crate::event::{InnerSizeWriter, WindowEvent};
use crate::platform::macos::{OptionAsAlt, WindowExtMacOS}; use crate::platform::macos::{OptionAsAlt, WindowExtMacOS};
use crate::window::{ use crate::window::{
Cursor, CursorGrabMode, Icon, ImePurpose, ResizeDirection, Theme, UserAttentionType, Cursor, CursorGrabMode, Icon, ImePurpose, ResizeDirection, Theme, UserAttentionType,
WindowAttributes, WindowButtons, WindowLevel, WindowAttributes, WindowButtons, WindowId as RootWindowId, WindowLevel,
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -807,11 +807,13 @@ impl WindowDelegate {
} }
pub(crate) fn queue_event(&self, event: WindowEvent) { pub(crate) fn queue_event(&self, event: WindowEvent) {
self.ivars().app_delegate.maybe_queue_window_event(self.window().id(), event); let window_id = RootWindowId(self.window().id());
self.ivars().app_delegate.maybe_queue_with_handler(move |app, event_loop| {
app.window_event(event_loop, window_id, event);
});
} }
fn handle_scale_factor_changed(&self, scale_factor: CGFloat) { fn handle_scale_factor_changed(&self, scale_factor: CGFloat) {
let app_delegate = &self.ivars().app_delegate;
let window = self.window(); let window = self.window();
let content_size = window.contentRectForFrameRect(window.frame()).size; let content_size = window.contentRectForFrameRect(window.frame()).size;
@ -819,7 +821,7 @@ impl WindowDelegate {
let suggested_size = content_size.to_physical(scale_factor); let suggested_size = content_size.to_physical(scale_factor);
let new_inner_size = Arc::new(Mutex::new(suggested_size)); let new_inner_size = Arc::new(Mutex::new(suggested_size));
app_delegate.handle_window_event(window.id(), WindowEvent::ScaleFactorChanged { self.queue_event(WindowEvent::ScaleFactorChanged {
scale_factor, scale_factor,
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)),
}); });
@ -831,7 +833,7 @@ impl WindowDelegate {
let size = NSSize::new(logical_size.width, logical_size.height); let size = NSSize::new(logical_size.width, logical_size.height);
window.setContentSize(size); window.setContentSize(size);
} }
app_delegate.handle_window_event(window.id(), WindowEvent::Resized(physical_size)); self.queue_event(WindowEvent::Resized(physical_size));
} }
fn emit_move_event(&self) { fn emit_move_event(&self) {