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 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,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue