mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-26 14:49:07 -04:00
Apple: Trace CFRunLoop activities
Add two run loop observers that:
- Create a TRACE-level span when the run loop enters a new state.
- Drops the span when the run loop exits that state.
These spans attach information to events, such that e.g. resizing a view
produces messages like:
```
TRACE inside runloop{mode=NSEventTrackingRunLoopMode}:timers:
winit_appkit::util: Triggered `drawRect:` target="winit_appkit::view"
TRACE inside runloop{mode=NSEventTrackingRunLoopMode}:timers:
winit_appkit::util: Completed `drawRect:` target="winit_appkit::view"
```
This commit is contained in:
@@ -12,7 +12,7 @@ use objc2_ui_kit::{
|
||||
UIApplicationWillResignActiveNotification, UIApplicationWillTerminateNotification, UIScreen,
|
||||
};
|
||||
use rwh_06::HasDisplayHandle;
|
||||
use winit_common::core_foundation::{MainRunLoop, MainRunLoopObserver};
|
||||
use winit_common::core_foundation::{MainRunLoop, MainRunLoopObserver, tracing_observers};
|
||||
use winit_core::application::ApplicationHandler;
|
||||
use winit_core::cursor::{CustomCursor, CustomCursorSource};
|
||||
use winit_core::error::{EventLoopError, NotSupportedError, RequestError};
|
||||
@@ -134,6 +134,7 @@ pub struct EventLoop {
|
||||
_will_terminate_observer: Retained<ProtocolObject<dyn NSObjectProtocol>>,
|
||||
_did_receive_memory_warning_observer: Retained<ProtocolObject<dyn NSObjectProtocol>>,
|
||||
|
||||
_tracing_observers: Option<(MainRunLoopObserver, MainRunLoopObserver)>,
|
||||
_wakeup_observer: MainRunLoopObserver,
|
||||
_main_events_cleared_observer: MainRunLoopObserver,
|
||||
_events_cleared_observer: MainRunLoopObserver,
|
||||
@@ -226,12 +227,19 @@ impl EventLoop {
|
||||
let main_loop = MainRunLoop::get(mtm);
|
||||
let mode = unsafe { kCFRunLoopDefaultMode }.unwrap();
|
||||
|
||||
// Tracing observers have the lowest and highest orderings.
|
||||
let _tracing_observers = tracing_observers(mtm).inspect(|(start, end)| {
|
||||
main_loop.add_observer(start, mode);
|
||||
main_loop.add_observer(end, mode);
|
||||
});
|
||||
|
||||
let _wakeup_observer = MainRunLoopObserver::new(
|
||||
mtm,
|
||||
CFRunLoopActivity::AfterWaiting,
|
||||
true,
|
||||
// Queued with the highest priority to ensure it is processed before other observers.
|
||||
CFIndex::MIN,
|
||||
// Queued with the second-highest priority (tracing observers use the highest) to
|
||||
// ensure it is processed before other observers.
|
||||
CFIndex::MIN + 1,
|
||||
move |_| app_state::handle_wakeup_transition(mtm),
|
||||
);
|
||||
main_loop.add_observer(&_wakeup_observer, mode);
|
||||
@@ -241,17 +249,17 @@ impl EventLoop {
|
||||
CFRunLoopActivity::BeforeWaiting,
|
||||
true,
|
||||
// Core Animation registers its `CFRunLoopObserver` that performs drawing operations in
|
||||
// `CA::Transaction::ensure_implicit` with a priority of `0x1e8480`. We set the
|
||||
// `CA::Transaction::ensure_implicit` with a priority of `2000000`. We set the
|
||||
// main_end priority to be 0, in order to send `AboutToWait` before `RedrawRequested`.
|
||||
// This value was chosen conservatively to guard against apple using different
|
||||
// priorities for their redraw observers in different OS's or on different devices. If
|
||||
// it so happens that it's too conservative, the main symptom would be non-redraw
|
||||
// events coming in after `AboutToWait`.
|
||||
//
|
||||
// The value of `0x1e8480` was determined by inspecting stack traces and the associated
|
||||
// The value of `2000000` was determined by inspecting stack traces and the associated
|
||||
// registers for every `CFRunLoopAddObserver` call on an iPad Air 2 running iOS 11.4.
|
||||
//
|
||||
// Also tested to be `0x1e8480` on iPhone 8, iOS 13 beta 4.
|
||||
// Also tested to be `2000000` on iPhone 8, iOS 13 beta 4.
|
||||
0,
|
||||
move |_| app_state::handle_main_events_cleared(mtm),
|
||||
);
|
||||
@@ -261,8 +269,9 @@ impl EventLoop {
|
||||
mtm,
|
||||
CFRunLoopActivity::BeforeWaiting,
|
||||
true,
|
||||
// Queued with the lowest priority to ensure it is processed after other observers.
|
||||
CFIndex::MAX,
|
||||
// Queued with the second-lowest priority (tracing observers use the lowest) to ensure
|
||||
// it is processed after other observers.
|
||||
CFIndex::MAX - 1,
|
||||
move |_| app_state::handle_events_cleared(mtm),
|
||||
);
|
||||
main_loop.add_observer(&_events_cleared_observer, mode);
|
||||
@@ -277,6 +286,7 @@ impl EventLoop {
|
||||
_did_enter_background_observer,
|
||||
_will_terminate_observer,
|
||||
_did_receive_memory_warning_observer,
|
||||
_tracing_observers,
|
||||
_wakeup_observer,
|
||||
_main_events_cleared_observer,
|
||||
_events_cleared_observer,
|
||||
|
||||
Reference in New Issue
Block a user