mirror of
https://github.com/rust-windowing/winit.git
synced 2026-09-01 06:10:07 -04:00
macOS/iOS: Various refactorings in application state (#3720)
I'm preparing to get rid of our application delegate in favour of registering notification observers, to do so I'm renaming `app_delegate.rs` to `app_state.rs`, and moving the functionality out of the Objective-C method into a normal method. Additionally, `AppState` previously implemented `Default`, but really, this was a hack done because someone (probably myself) was too lazy to write out the full initialization in `AppDelegate::new`.
This commit is contained in:
committed by
Kirill Chibisov
parent
3a0928af45
commit
21e266f3b7
@@ -1,11 +1,9 @@
|
|||||||
use objc2::{declare_class, mutability, ClassType, DeclaredClass};
|
use objc2::{declare_class, mutability, ClassType, DeclaredClass};
|
||||||
use objc2_foundation::{MainThreadMarker, NSObject, NSObjectProtocol};
|
use objc2_foundation::{MainThreadMarker, NSObject};
|
||||||
use objc2_ui_kit::{UIApplication, UIWindow};
|
use objc2_ui_kit::UIApplication;
|
||||||
|
|
||||||
use super::app_state::{self, EventWrapper};
|
use super::app_state::{self, send_occluded_event_for_all_windows, EventWrapper};
|
||||||
use super::window::WinitUIWindow;
|
use crate::event::Event;
|
||||||
use crate::event::{Event, WindowEvent};
|
|
||||||
use crate::window::WindowId as RootWindowId;
|
|
||||||
|
|
||||||
declare_class!(
|
declare_class!(
|
||||||
pub struct AppDelegate;
|
pub struct AppDelegate;
|
||||||
@@ -40,35 +38,17 @@ declare_class!(
|
|||||||
|
|
||||||
#[method(applicationWillEnterForeground:)]
|
#[method(applicationWillEnterForeground:)]
|
||||||
fn will_enter_foreground(&self, application: &UIApplication) {
|
fn will_enter_foreground(&self, application: &UIApplication) {
|
||||||
self.send_occluded_event_for_all_windows(application, false);
|
send_occluded_event_for_all_windows(application, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[method(applicationDidEnterBackground:)]
|
#[method(applicationDidEnterBackground:)]
|
||||||
fn did_enter_background(&self, application: &UIApplication) {
|
fn did_enter_background(&self, application: &UIApplication) {
|
||||||
self.send_occluded_event_for_all_windows(application, true);
|
send_occluded_event_for_all_windows(application, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[method(applicationWillTerminate:)]
|
#[method(applicationWillTerminate:)]
|
||||||
fn will_terminate(&self, application: &UIApplication) {
|
fn will_terminate(&self, application: &UIApplication) {
|
||||||
let mut events = Vec::new();
|
app_state::terminated(application);
|
||||||
#[allow(deprecated)]
|
|
||||||
for window in application.windows().iter() {
|
|
||||||
if window.is_kind_of::<WinitUIWindow>() {
|
|
||||||
// SAFETY: We just checked that the window is a `winit` window
|
|
||||||
let window = unsafe {
|
|
||||||
let ptr: *const UIWindow = window;
|
|
||||||
let ptr: *const WinitUIWindow = ptr.cast();
|
|
||||||
&*ptr
|
|
||||||
};
|
|
||||||
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
|
||||||
window_id: RootWindowId(window.id()),
|
|
||||||
event: WindowEvent::Destroyed,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mtm = MainThreadMarker::new().unwrap();
|
|
||||||
app_state::handle_nonuser_events(mtm, events);
|
|
||||||
app_state::terminated(mtm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[method(applicationDidReceiveMemoryWarning:)]
|
#[method(applicationDidReceiveMemoryWarning:)]
|
||||||
@@ -78,26 +58,3 @@ declare_class!(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
impl AppDelegate {
|
|
||||||
fn send_occluded_event_for_all_windows(&self, application: &UIApplication, occluded: bool) {
|
|
||||||
let mut events = Vec::new();
|
|
||||||
#[allow(deprecated)]
|
|
||||||
for window in application.windows().iter() {
|
|
||||||
if window.is_kind_of::<WinitUIWindow>() {
|
|
||||||
// SAFETY: We just checked that the window is a `winit` window
|
|
||||||
let window = unsafe {
|
|
||||||
let ptr: *const UIWindow = window;
|
|
||||||
let ptr: *const WinitUIWindow = ptr.cast();
|
|
||||||
&*ptr
|
|
||||||
};
|
|
||||||
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
|
||||||
window_id: RootWindowId(window.id()),
|
|
||||||
event: WindowEvent::Occluded(occluded),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mtm = MainThreadMarker::new().unwrap();
|
|
||||||
app_state::handle_nonuser_events(mtm, events);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use objc2_foundation::{
|
|||||||
CGRect, CGSize, MainThreadMarker, NSInteger, NSObjectProtocol, NSOperatingSystemVersion,
|
CGRect, CGSize, MainThreadMarker, NSInteger, NSObjectProtocol, NSOperatingSystemVersion,
|
||||||
NSProcessInfo,
|
NSProcessInfo,
|
||||||
};
|
};
|
||||||
use objc2_ui_kit::{UICoordinateSpace, UIView};
|
use objc2_ui_kit::{UIApplication, UICoordinateSpace, UIView, UIWindow};
|
||||||
|
|
||||||
use super::window::WinitUIWindow;
|
use super::window::WinitUIWindow;
|
||||||
use crate::dpi::PhysicalSize;
|
use crate::dpi::PhysicalSize;
|
||||||
@@ -662,6 +662,28 @@ fn handle_user_events(mtm: MainThreadMarker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn send_occluded_event_for_all_windows(application: &UIApplication, occluded: bool) {
|
||||||
|
let mtm = MainThreadMarker::from(application);
|
||||||
|
|
||||||
|
let mut events = Vec::new();
|
||||||
|
#[allow(deprecated)]
|
||||||
|
for window in application.windows().iter() {
|
||||||
|
if window.is_kind_of::<WinitUIWindow>() {
|
||||||
|
// SAFETY: We just checked that the window is a `winit` window
|
||||||
|
let window = unsafe {
|
||||||
|
let ptr: *const UIWindow = window;
|
||||||
|
let ptr: *const WinitUIWindow = ptr.cast();
|
||||||
|
&*ptr
|
||||||
|
};
|
||||||
|
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
|
window_id: RootWindowId(window.id()),
|
||||||
|
event: WindowEvent::Occluded(occluded),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handle_nonuser_events(mtm, events);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_main_events_cleared(mtm: MainThreadMarker) {
|
pub fn handle_main_events_cleared(mtm: MainThreadMarker) {
|
||||||
let mut this = AppState::get_mut(mtm);
|
let mut this = AppState::get_mut(mtm);
|
||||||
if !this.has_launched() || this.has_terminated() {
|
if !this.has_launched() || this.has_terminated() {
|
||||||
@@ -696,7 +718,27 @@ pub fn handle_events_cleared(mtm: MainThreadMarker) {
|
|||||||
AppState::get_mut(mtm).events_cleared_transition();
|
AppState::get_mut(mtm).events_cleared_transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn terminated(mtm: MainThreadMarker) {
|
pub(crate) fn terminated(application: &UIApplication) {
|
||||||
|
let mtm = MainThreadMarker::from(application);
|
||||||
|
|
||||||
|
let mut events = Vec::new();
|
||||||
|
#[allow(deprecated)]
|
||||||
|
for window in application.windows().iter() {
|
||||||
|
if window.is_kind_of::<WinitUIWindow>() {
|
||||||
|
// SAFETY: We just checked that the window is a `winit` window
|
||||||
|
let window = unsafe {
|
||||||
|
let ptr: *const UIWindow = window;
|
||||||
|
let ptr: *const WinitUIWindow = ptr.cast();
|
||||||
|
&*ptr
|
||||||
|
};
|
||||||
|
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
|
window_id: RootWindowId(window.id()),
|
||||||
|
event: WindowEvent::Destroyed,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handle_nonuser_events(mtm, events);
|
||||||
|
|
||||||
let mut this = AppState::get_mut(mtm);
|
let mut this = AppState::get_mut(mtm);
|
||||||
let mut handler = this.terminated_transition();
|
let mut handler = this.terminated_transition();
|
||||||
drop(this);
|
drop(this);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use objc2::{declare_class, msg_send, mutability, ClassType, DeclaredClass};
|
|||||||
use objc2_app_kit::{NSApplication, NSEvent, NSEventModifierFlags, NSEventType, NSResponder};
|
use objc2_app_kit::{NSApplication, NSEvent, NSEventModifierFlags, NSEventType, NSResponder};
|
||||||
use objc2_foundation::{MainThreadMarker, NSObject};
|
use objc2_foundation::{MainThreadMarker, NSObject};
|
||||||
|
|
||||||
use super::app_delegate::ApplicationDelegate;
|
use super::app_state::ApplicationDelegate;
|
||||||
use crate::event::{DeviceEvent, ElementState};
|
use crate::event::{DeviceEvent, ElementState};
|
||||||
|
|
||||||
declare_class!(
|
declare_class!(
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ use std::rc::Weak;
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use objc2::rc::Retained;
|
use objc2::rc::Retained;
|
||||||
use objc2::runtime::AnyObject;
|
|
||||||
use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass};
|
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, NSObject, NSObjectProtocol};
|
use objc2_foundation::{MainThreadMarker, NSNotification, NSObject, NSObjectProtocol};
|
||||||
|
|
||||||
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};
|
||||||
@@ -18,17 +17,8 @@ use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow};
|
|||||||
use crate::window::WindowId as RootWindowId;
|
use crate::window::WindowId as RootWindowId;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Policy(NSApplicationActivationPolicy);
|
pub(super) struct AppState {
|
||||||
|
activation_policy: NSApplicationActivationPolicy,
|
||||||
impl Default for Policy {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self(NSApplicationActivationPolicy::Regular)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub(super) struct State {
|
|
||||||
activation_policy: Policy,
|
|
||||||
default_menu: bool,
|
default_menu: bool,
|
||||||
activate_ignoring_other_apps: bool,
|
activate_ignoring_other_apps: bool,
|
||||||
run_loop: RunLoop,
|
run_loop: RunLoop,
|
||||||
@@ -63,62 +53,20 @@ declare_class!(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DeclaredClass for ApplicationDelegate {
|
impl DeclaredClass for ApplicationDelegate {
|
||||||
type Ivars = State;
|
type Ivars = AppState;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl NSObjectProtocol for ApplicationDelegate {}
|
unsafe impl NSObjectProtocol for ApplicationDelegate {}
|
||||||
|
|
||||||
unsafe impl NSApplicationDelegate for ApplicationDelegate {
|
unsafe impl NSApplicationDelegate for ApplicationDelegate {
|
||||||
// NOTE: This will, globally, only be run once, no matter how many
|
|
||||||
// `EventLoop`s the user creates.
|
|
||||||
#[method(applicationDidFinishLaunching:)]
|
#[method(applicationDidFinishLaunching:)]
|
||||||
fn did_finish_launching(&self, _sender: Option<&AnyObject>) {
|
fn app_did_finish_launching(&self, notification: &NSNotification) {
|
||||||
trace_scope!("applicationDidFinishLaunching:");
|
self.did_finish_launching(notification)
|
||||||
self.ivars().is_launched.set(true);
|
|
||||||
|
|
||||||
let mtm = MainThreadMarker::from(self);
|
|
||||||
let app = NSApplication::sharedApplication(mtm);
|
|
||||||
// We need to delay setting the activation policy and activating the app
|
|
||||||
// until `applicationDidFinishLaunching` has been called. Otherwise the
|
|
||||||
// menu bar is initially unresponsive on macOS 10.15.
|
|
||||||
app.setActivationPolicy(self.ivars().activation_policy.0);
|
|
||||||
|
|
||||||
window_activation_hack(&app);
|
|
||||||
#[allow(deprecated)]
|
|
||||||
app.activateIgnoringOtherApps(self.ivars().activate_ignoring_other_apps);
|
|
||||||
|
|
||||||
if self.ivars().default_menu {
|
|
||||||
// The menubar initialization should be before the `NewEvents` event, to allow
|
|
||||||
// overriding of the default menu even if it's created
|
|
||||||
menu::initialize(&app);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ivars().waker.borrow_mut().start();
|
|
||||||
|
|
||||||
self.set_is_running(true);
|
|
||||||
self.dispatch_init_events();
|
|
||||||
|
|
||||||
// If the application is being launched via `EventLoop::pump_app_events()` then we'll
|
|
||||||
// want to stop the app once it is launched (and return to the external loop)
|
|
||||||
//
|
|
||||||
// In this case we still want to consider Winit's `EventLoop` to be "running",
|
|
||||||
// so we call `start_running()` above.
|
|
||||||
if self.ivars().stop_on_launch.get() {
|
|
||||||
// NOTE: the original idea had been to only stop the underlying `RunLoop`
|
|
||||||
// for the app but that didn't work as expected (`-[NSApplication run]`
|
|
||||||
// effectively ignored the attempt to stop the RunLoop and re-started it).
|
|
||||||
//
|
|
||||||
// So we return from `pump_events` by stopping the application.
|
|
||||||
let app = NSApplication::sharedApplication(mtm);
|
|
||||||
stop_app_immediately(&app);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[method(applicationWillTerminate:)]
|
#[method(applicationWillTerminate:)]
|
||||||
fn will_terminate(&self, _sender: Option<&AnyObject>) {
|
fn app_will_terminate(&self, notification: &NSNotification) {
|
||||||
trace_scope!("applicationWillTerminate:");
|
self.will_terminate(notification)
|
||||||
// TODO: Notify every window that it will be destroyed, like done in iOS?
|
|
||||||
self.internal_exit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -130,16 +78,78 @@ impl ApplicationDelegate {
|
|||||||
default_menu: bool,
|
default_menu: bool,
|
||||||
activate_ignoring_other_apps: bool,
|
activate_ignoring_other_apps: bool,
|
||||||
) -> Retained<Self> {
|
) -> Retained<Self> {
|
||||||
let this = mtm.alloc().set_ivars(State {
|
let this = mtm.alloc().set_ivars(AppState {
|
||||||
activation_policy: Policy(activation_policy),
|
activation_policy,
|
||||||
default_menu,
|
default_menu,
|
||||||
activate_ignoring_other_apps,
|
activate_ignoring_other_apps,
|
||||||
run_loop: RunLoop::main(mtm),
|
run_loop: RunLoop::main(mtm),
|
||||||
..Default::default()
|
event_handler: EventHandler::new(),
|
||||||
|
stop_on_launch: Cell::new(false),
|
||||||
|
stop_before_wait: Cell::new(false),
|
||||||
|
stop_after_wait: Cell::new(false),
|
||||||
|
stop_on_redraw: Cell::new(false),
|
||||||
|
is_launched: Cell::new(false),
|
||||||
|
is_running: Cell::new(false),
|
||||||
|
exit: Cell::new(false),
|
||||||
|
control_flow: Cell::new(ControlFlow::default()),
|
||||||
|
waker: RefCell::new(EventLoopWaker::new()),
|
||||||
|
start_time: Cell::new(None),
|
||||||
|
wait_timeout: Cell::new(None),
|
||||||
|
pending_redraw: RefCell::new(vec![]),
|
||||||
});
|
});
|
||||||
unsafe { msg_send_id![super(this), init] }
|
unsafe { msg_send_id![super(this), init] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: This will, globally, only be run once, no matter how many
|
||||||
|
// `EventLoop`s the user creates.
|
||||||
|
fn did_finish_launching(&self, _notification: &NSNotification) {
|
||||||
|
trace_scope!("applicationDidFinishLaunching:");
|
||||||
|
self.ivars().is_launched.set(true);
|
||||||
|
|
||||||
|
let mtm = MainThreadMarker::from(self);
|
||||||
|
let app = NSApplication::sharedApplication(mtm);
|
||||||
|
// We need to delay setting the activation policy and activating the app
|
||||||
|
// until `applicationDidFinishLaunching` has been called. Otherwise the
|
||||||
|
// menu bar is initially unresponsive on macOS 10.15.
|
||||||
|
app.setActivationPolicy(self.ivars().activation_policy);
|
||||||
|
|
||||||
|
window_activation_hack(&app);
|
||||||
|
#[allow(deprecated)]
|
||||||
|
app.activateIgnoringOtherApps(self.ivars().activate_ignoring_other_apps);
|
||||||
|
|
||||||
|
if self.ivars().default_menu {
|
||||||
|
// The menubar initialization should be before the `NewEvents` event, to allow
|
||||||
|
// overriding of the default menu even if it's created
|
||||||
|
menu::initialize(&app);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ivars().waker.borrow_mut().start();
|
||||||
|
|
||||||
|
self.set_is_running(true);
|
||||||
|
self.dispatch_init_events();
|
||||||
|
|
||||||
|
// If the application is being launched via `EventLoop::pump_app_events()` then we'll
|
||||||
|
// want to stop the app once it is launched (and return to the external loop)
|
||||||
|
//
|
||||||
|
// In this case we still want to consider Winit's `EventLoop` to be "running",
|
||||||
|
// so we call `start_running()` above.
|
||||||
|
if self.ivars().stop_on_launch.get() {
|
||||||
|
// NOTE: the original idea had been to only stop the underlying `RunLoop`
|
||||||
|
// for the app but that didn't work as expected (`-[NSApplication run]`
|
||||||
|
// effectively ignored the attempt to stop the RunLoop and re-started it).
|
||||||
|
//
|
||||||
|
// So we return from `pump_events` by stopping the application.
|
||||||
|
let app = NSApplication::sharedApplication(mtm);
|
||||||
|
stop_app_immediately(&app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn will_terminate(&self, _notification: &NSNotification) {
|
||||||
|
trace_scope!("applicationWillTerminate:");
|
||||||
|
// TODO: Notify every window that it will be destroyed, like done in iOS?
|
||||||
|
self.internal_exit();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get(mtm: MainThreadMarker) -> Retained<Self> {
|
pub fn get(mtm: MainThreadMarker) -> Retained<Self> {
|
||||||
let app = NSApplication::sharedApplication(mtm);
|
let app = NSApplication::sharedApplication(mtm);
|
||||||
let delegate =
|
let delegate =
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::{fmt, mem};
|
use std::{fmt, mem};
|
||||||
|
|
||||||
use super::app_delegate::HandlePendingUserEvents;
|
use super::app_state::HandlePendingUserEvents;
|
||||||
use crate::event::Event;
|
use crate::event::Event;
|
||||||
use crate::event_loop::ActiveEventLoop as RootActiveEventLoop;
|
use crate::event_loop::ActiveEventLoop as RootActiveEventLoop;
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ impl fmt::Debug for EventHandlerData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[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).
|
||||||
@@ -26,6 +26,10 @@ pub(crate) struct EventHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EventHandler {
|
impl EventHandler {
|
||||||
|
pub(crate) const fn new() -> Self {
|
||||||
|
Self { inner: RefCell::new(None) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the event loop handler for the duration of the given closure.
|
/// Set the event loop handler for the duration of the given closure.
|
||||||
///
|
///
|
||||||
/// This is similar to using the `scoped-tls` or `scoped-tls-hkt` crates
|
/// This is similar to using the `scoped-tls` or `scoped-tls-hkt` crates
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy, NSWindow};
|
|||||||
use objc2_foundation::{MainThreadMarker, NSObjectProtocol};
|
use objc2_foundation::{MainThreadMarker, NSObjectProtocol};
|
||||||
|
|
||||||
use super::app::WinitApplication;
|
use super::app::WinitApplication;
|
||||||
use super::app_delegate::{ApplicationDelegate, HandlePendingUserEvents};
|
use super::app_state::{ApplicationDelegate, HandlePendingUserEvents};
|
||||||
use super::event::dummy_event;
|
use super::event::dummy_event;
|
||||||
use super::monitor::{self, MonitorHandle};
|
use super::monitor::{self, MonitorHandle};
|
||||||
use super::observer::setup_control_flow_observers;
|
use super::observer::setup_control_flow_observers;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod app_delegate;
|
mod app_state;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod event;
|
mod event;
|
||||||
mod event_handler;
|
mod event_handler;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use core_foundation::runloop::{
|
|||||||
use objc2_foundation::MainThreadMarker;
|
use objc2_foundation::MainThreadMarker;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use super::app_delegate::ApplicationDelegate;
|
use super::app_state::ApplicationDelegate;
|
||||||
use super::event_loop::{stop_app_on_panic, PanicInfo};
|
use super::event_loop::{stop_app_on_panic, PanicInfo};
|
||||||
use super::ffi;
|
use super::ffi;
|
||||||
|
|
||||||
@@ -251,8 +251,8 @@ impl Drop for EventLoopWaker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EventLoopWaker {
|
impl EventLoopWaker {
|
||||||
fn default() -> EventLoopWaker {
|
pub(crate) fn new() -> Self {
|
||||||
extern "C" fn wakeup_main_loop(_timer: CFRunLoopTimerRef, _info: *mut c_void) {}
|
extern "C" fn wakeup_main_loop(_timer: CFRunLoopTimerRef, _info: *mut c_void) {}
|
||||||
unsafe {
|
unsafe {
|
||||||
// Create a timer with a 0.1µs interval (1ns does not work) to mimic polling.
|
// Create a timer with a 0.1µs interval (1ns does not work) to mimic polling.
|
||||||
@@ -268,12 +268,10 @@ impl Default for EventLoopWaker {
|
|||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
);
|
);
|
||||||
CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes);
|
CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes);
|
||||||
EventLoopWaker { timer, start_instant: Instant::now(), next_fire_date: None }
|
Self { timer, start_instant: Instant::now(), next_fire_date: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl EventLoopWaker {
|
|
||||||
pub fn stop(&mut self) {
|
pub fn stop(&mut self) {
|
||||||
if self.next_fire_date.is_some() {
|
if self.next_fire_date.is_some() {
|
||||||
self.next_fire_date = None;
|
self.next_fire_date = None;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use objc2_foundation::{
|
|||||||
NSPoint, NSRange, NSRect, NSSize, NSString, NSUInteger,
|
NSPoint, NSRange, NSRect, NSSize, NSString, NSUInteger,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app_delegate::ApplicationDelegate;
|
use super::app_state::ApplicationDelegate;
|
||||||
use super::cursor::{default_cursor, invisible_cursor};
|
use super::cursor::{default_cursor, invisible_cursor};
|
||||||
use super::event::{
|
use super::event::{
|
||||||
code_to_key, code_to_location, create_key_event, event_mods, lalt_pressed, ralt_pressed,
|
code_to_key, code_to_location, create_key_event, event_mods, lalt_pressed, ralt_pressed,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use objc2_foundation::{
|
|||||||
NSPoint, NSRect, NSSize, NSString,
|
NSPoint, NSRect, NSSize, NSString,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app_delegate::ApplicationDelegate;
|
use super::app_state::ApplicationDelegate;
|
||||||
use super::cursor::cursor_from_icon;
|
use super::cursor::cursor_from_icon;
|
||||||
use super::monitor::{self, flip_window_screen_coordinates, get_display_id};
|
use super::monitor::{self, flip_window_screen_coordinates, get_display_id};
|
||||||
use super::observer::RunLoop;
|
use super::observer::RunLoop;
|
||||||
|
|||||||
Reference in New Issue
Block a user