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:
parent
10dc0674bb
commit
c0c14aaf00
6 changed files with 184 additions and 103 deletions
|
|
@ -5,6 +5,7 @@ use objc2_app_kit::{NSApplication, NSEvent, NSEventModifierFlags, NSEventType, N
|
|||
use objc2_foundation::{MainThreadMarker, NSObject};
|
||||
|
||||
use super::app_state::ApplicationDelegate;
|
||||
use super::DEVICE_ID;
|
||||
use crate::event::{DeviceEvent, ElementState};
|
||||
|
||||
declare_class!(
|
||||
|
|
@ -57,29 +58,47 @@ fn maybe_dispatch_device_event(delegate: &ApplicationDelegate, event: &NSEvent)
|
|||
let delta_y = unsafe { event.deltaY() } as f64;
|
||||
|
||||
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 {
|
||||
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 {
|
||||
delegate.maybe_queue_device_event(DeviceEvent::MouseMotion {
|
||||
delta: (delta_x, delta_y),
|
||||
delegate.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.device_event(event_loop, DEVICE_ID, DeviceEvent::MouseMotion {
|
||||
delta: (delta_x, delta_y),
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
NSEventType::LeftMouseDown | NSEventType::RightMouseDown | NSEventType::OtherMouseDown => {
|
||||
delegate.maybe_queue_device_event(DeviceEvent::Button {
|
||||
button: unsafe { event.buttonNumber() } as u32,
|
||||
state: ElementState::Pressed,
|
||||
let button = unsafe { event.buttonNumber() } as u32;
|
||||
delegate.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.device_event(event_loop, DEVICE_ID, DeviceEvent::Button {
|
||||
button,
|
||||
state: ElementState::Pressed,
|
||||
});
|
||||
});
|
||||
},
|
||||
NSEventType::LeftMouseUp | NSEventType::RightMouseUp | NSEventType::OtherMouseUp => {
|
||||
delegate.maybe_queue_device_event(DeviceEvent::Button {
|
||||
button: unsafe { event.buttonNumber() } as u32,
|
||||
state: ElementState::Released,
|
||||
let button = unsafe { event.buttonNumber() } as u32;
|
||||
delegate.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.device_event(event_loop, DEVICE_ID, DeviceEvent::Button {
|
||||
button,
|
||||
state: ElementState::Released,
|
||||
});
|
||||
});
|
||||
},
|
||||
_ => (),
|
||||
|
|
|
|||
|
|
@ -8,13 +8,15 @@ use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass};
|
|||
use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy, NSApplicationDelegate};
|
||||
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_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo};
|
||||
use super::observer::{EventLoopWaker, RunLoop};
|
||||
use super::{menu, WindowId, DEVICE_ID};
|
||||
use crate::event::{DeviceEvent, Event, StartCause, WindowEvent};
|
||||
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow};
|
||||
use crate::window::WindowId as RootWindowId;
|
||||
use super::{menu, WindowId};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AppState {
|
||||
|
|
@ -166,7 +168,7 @@ impl ApplicationDelegate {
|
|||
/// of the given closure.
|
||||
pub fn set_event_handler<R>(
|
||||
&self,
|
||||
handler: impl FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop),
|
||||
handler: &mut dyn ApplicationHandler<HandlePendingUserEvents>,
|
||||
closure: impl FnOnce() -> R,
|
||||
) -> R {
|
||||
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,
|
||||
/// and we won't need to re-launch the app if subsequent EventLoops are run.
|
||||
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_stop_on_redraw(false);
|
||||
|
|
@ -241,26 +245,13 @@ impl ApplicationDelegate {
|
|||
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) {
|
||||
let mtm = MainThreadMarker::from(self);
|
||||
// Redraw request might come out of order from the OS.
|
||||
// -> Don't go back into the event handler when our callstack originates from there
|
||||
if !self.ivars().event_handler.in_use() {
|
||||
self.handle_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: WindowEvent::RedrawRequested,
|
||||
self.with_handler(|app, event_loop| {
|
||||
app.window_event(event_loop, RootWindowId(window_id), WindowEvent::RedrawRequested);
|
||||
});
|
||||
|
||||
// `pump_events` will request to stop immediately _after_ dispatching RedrawRequested
|
||||
|
|
@ -282,7 +273,11 @@ impl ApplicationDelegate {
|
|||
}
|
||||
|
||||
#[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.)
|
||||
// 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
|
||||
// currently handling another event, and if we are, we queue the event instead.
|
||||
if !self.ivars().event_handler.in_use() {
|
||||
self.handle_event(event);
|
||||
self.with_handler(callback);
|
||||
} 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();
|
||||
self.ivars().run_loop.queue_closure(move || this.handle_event(event));
|
||||
self.ivars().run_loop.queue_closure(move || {
|
||||
this.with_handler(callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn handle_event(&self, event: Event<HandlePendingUserEvents>) {
|
||||
self.ivars().event_handler.handle_event(event, &ActiveEventLoop::new_root(self.retain()))
|
||||
fn with_handler<
|
||||
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`
|
||||
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
|
||||
// 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
|
||||
|
|
@ -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
|
||||
|
|
@ -358,17 +361,17 @@ impl ApplicationDelegate {
|
|||
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());
|
||||
for window_id in redraw {
|
||||
self.handle_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: WindowEvent::RedrawRequested,
|
||||
self.with_handler(|app, event_loop| {
|
||||
app.window_event(event_loop, RootWindowId(window_id), WindowEvent::RedrawRequested);
|
||||
});
|
||||
}
|
||||
|
||||
self.handle_event(Event::AboutToWait);
|
||||
self.with_handler(|app, event_loop| {
|
||||
app.about_to_wait(event_loop);
|
||||
});
|
||||
|
||||
if self.exiting() {
|
||||
let app = NSApplication::sharedApplication(mtm);
|
||||
|
|
|
|||
|
|
@ -2,31 +2,31 @@ use std::cell::RefCell;
|
|||
use std::{fmt, mem};
|
||||
|
||||
use super::app_state::HandlePendingUserEvents;
|
||||
use crate::event::Event;
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::event_loop::ActiveEventLoop as RootActiveEventLoop;
|
||||
|
||||
struct EventHandlerData {
|
||||
#[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)]
|
||||
#[derive(Default)]
|
||||
pub(crate) struct EventHandler {
|
||||
/// This can be in the following states:
|
||||
/// - Not registered by the event loop (None).
|
||||
/// - Present (Some(handler)).
|
||||
/// - 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 {
|
||||
pub(crate) const fn new() -> Self {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self { inner: RefCell::new(None) }
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ impl EventHandler {
|
|||
/// from within the closure.
|
||||
pub(crate) fn set<'handler, R>(
|
||||
&self,
|
||||
handler: impl FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) + 'handler,
|
||||
app: &'handler mut dyn ApplicationHandler<HandlePendingUserEvents>,
|
||||
closure: impl FnOnce() -> R,
|
||||
) -> R {
|
||||
// SAFETY: We extend the lifetime of the handler here so that we can
|
||||
|
|
@ -48,9 +48,9 @@ impl EventHandler {
|
|||
// extended beyond `'handler`.
|
||||
let handler = unsafe {
|
||||
mem::transmute::<
|
||||
Box<dyn FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) + 'handler>,
|
||||
Box<dyn FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) + 'static>,
|
||||
>(Box::new(handler))
|
||||
&'handler mut dyn ApplicationHandler<HandlePendingUserEvents>,
|
||||
&'static mut dyn ApplicationHandler<HandlePendingUserEvents>,
|
||||
>(app)
|
||||
};
|
||||
|
||||
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");
|
||||
},
|
||||
Ok(data @ None) => {
|
||||
*data = Some(EventHandlerData { handler });
|
||||
*data = Some(handler);
|
||||
},
|
||||
Err(_) => {
|
||||
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(_)))
|
||||
}
|
||||
|
||||
pub(crate) fn handle_event(
|
||||
pub(crate) fn handle<
|
||||
F: FnOnce(&mut dyn ApplicationHandler<HandlePendingUserEvents>, &RootActiveEventLoop),
|
||||
>(
|
||||
&self,
|
||||
event: Event<HandlePendingUserEvents>,
|
||||
callback: F,
|
||||
event_loop: &RootActiveEventLoop,
|
||||
) {
|
||||
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,
|
||||
// so that `in_use` can properly detect that the handler is
|
||||
// still in use.
|
||||
//
|
||||
// If the handler unwinds, the `RefMut` will ensure that the
|
||||
// handler is no longer borrowed.
|
||||
(handler)(event, event_loop);
|
||||
callback(*user_app, event_loop);
|
||||
},
|
||||
Ok(None) => {
|
||||
// `NSApplication`, our app delegate and this handler are all
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ use super::monitor::{self, MonitorHandle};
|
|||
use super::observer::setup_control_flow_observers;
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::EventLoopError;
|
||||
use crate::event::Event;
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootWindowTarget, ControlFlow, DeviceEvents, EventLoopClosed,
|
||||
};
|
||||
|
|
@ -156,28 +155,78 @@ impl ActiveEventLoop {
|
|||
}
|
||||
}
|
||||
|
||||
fn map_user_event<T: 'static, A: ApplicationHandler<T>>(
|
||||
app: &mut A,
|
||||
// Temporary helper, will be removed in https://github.com/rust-windowing/winit/pull/3694
|
||||
struct MapUserEvent<T, A> {
|
||||
app: A,
|
||||
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),
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(window_target, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(window_target, device_id, event)
|
||||
},
|
||||
Event::UserEvent(_) => {
|
||||
for event in receiver.try_iter() {
|
||||
app.user_event(window_target, event);
|
||||
}
|
||||
},
|
||||
Event::Suspended => app.suspended(window_target),
|
||||
Event::Resumed => app.resumed(window_target),
|
||||
Event::AboutToWait => app.about_to_wait(window_target),
|
||||
Event::LoopExiting => app.exiting(window_target),
|
||||
Event::MemoryWarning => app.memory_warning(window_target),
|
||||
}
|
||||
|
||||
impl<A: ApplicationHandler<T>, T: 'static> ApplicationHandler<HandlePendingUserEvents>
|
||||
for MapUserEvent<T, A>
|
||||
{
|
||||
#[inline]
|
||||
fn new_events(
|
||||
&mut self,
|
||||
event_loop: &crate::event_loop::ActiveEventLoop,
|
||||
cause: crate::event::StartCause,
|
||||
) {
|
||||
self.app.new_events(event_loop, cause);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn resumed(&mut self, event_loop: &crate::event_loop::ActiveEventLoop) {
|
||||
self.app.resumed(event_loop);
|
||||
}
|
||||
|
||||
#[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,
|
||||
app: &mut A,
|
||||
) -> 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(|_| {
|
||||
// clear / normalize pump_events state
|
||||
self.delegate.set_wait_timeout(None);
|
||||
|
|
@ -324,9 +373,9 @@ impl<T> EventLoop<T> {
|
|||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> 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(|_| {
|
||||
// As a special case, if the application hasn't been launched yet then we at least
|
||||
// run the loop until it has fully launched.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use crate::event::{
|
|||
};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey};
|
||||
use crate::platform::macos::OptionAsAlt;
|
||||
use crate::window::WindowId as RootWindowId;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CursorState {
|
||||
|
|
@ -686,7 +687,9 @@ declare_class!(
|
|||
|
||||
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 {
|
||||
device_id: DEVICE_ID,
|
||||
delta,
|
||||
|
|
@ -830,7 +833,10 @@ impl WinitView {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ use crate::event::{InnerSizeWriter, WindowEvent};
|
|||
use crate::platform::macos::{OptionAsAlt, WindowExtMacOS};
|
||||
use crate::window::{
|
||||
Cursor, CursorGrabMode, Icon, ImePurpose, ResizeDirection, Theme, UserAttentionType,
|
||||
WindowAttributes, WindowButtons, WindowLevel,
|
||||
WindowAttributes, WindowButtons, WindowId as RootWindowId, WindowLevel,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -807,11 +807,13 @@ impl WindowDelegate {
|
|||
}
|
||||
|
||||
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) {
|
||||
let app_delegate = &self.ivars().app_delegate;
|
||||
let window = self.window();
|
||||
|
||||
let content_size = window.contentRectForFrameRect(window.frame()).size;
|
||||
|
|
@ -819,7 +821,7 @@ impl WindowDelegate {
|
|||
|
||||
let suggested_size = content_size.to_physical(scale_factor);
|
||||
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,
|
||||
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);
|
||||
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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue