mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 13:51:30 +11:00
Remove RedrawEventsCleared + MainEventsCleared, and added AboutToWait
The idea that redraw events are dispatched with a specific ordering that makes it possible to specifically report when we have finished dispatching redraw events isn't portable and the way in which we dispatched RedrawEventsCleared was inconsistent across backends. More generally speaking, there is no inherent relationship between redrawing and event loop iterations. An event loop may wake up at any frequency depending on what sources of input events are being listened to but redrawing is generally throttled and in some way synchronized with the display frequency. Similarly there's no inherent relationship between a single event loop iteration and the dispatching of any specific kind of "main" event. An event loop wakes up when there are events to read (e.g. input events or responses from a display server / compositor) and goes back to waiting when there's nothing else to read. There isn't really a special kind of "main" event that is dispatched in order with respect to other events. What we can do more portably is emit an event when the event loop is about to block and wait for new events. In practice this is very similar to how MainEventsCleared was implemented except it wasn't the very last event previously since redraw events could be dispatched afterwards. The main backend where we don't strictly know when we're going to wait for events is Web (since the real event loop is internal to the browser). For now we emulate AboutToWait on Web similar to how MainEventsCleared was dispatched. In practice most applications almost certainly shouldn't care about AboutToWait because the frequency of event loop iterations is essentially arbitrary and usually irrelevant.
This commit is contained in:
parent
935146d299
commit
ae7497e18f
|
@ -31,6 +31,9 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
- `RedrawRequested` is no longer guaranteed to be emitted after `MainEventsCleared`, it is now platform-specific when the event is emitted after being requested via `redraw_request()`.
|
- `RedrawRequested` is no longer guaranteed to be emitted after `MainEventsCleared`, it is now platform-specific when the event is emitted after being requested via `redraw_request()`.
|
||||||
- On Windows, `RedrawRequested` is now driven by `WM_PAINT` messages which are requested via `redraw_request()`
|
- On Windows, `RedrawRequested` is now driven by `WM_PAINT` messages which are requested via `redraw_request()`
|
||||||
- **Breaking** `LoopDestroyed` renamed to `LoopExiting` ([#2900](https://github.com/rust-windowing/winit/issues/2900))
|
- **Breaking** `LoopDestroyed` renamed to `LoopExiting` ([#2900](https://github.com/rust-windowing/winit/issues/2900))
|
||||||
|
- **Breaking** `RedrawEventsCleared` removed ([#2900](https://github.com/rust-windowing/winit/issues/2900))
|
||||||
|
- **Breaking** `MainEventsCleared` removed ([#2900](https://github.com/rust-windowing/winit/issues/2900))
|
||||||
|
- Added `AboutToWait` event which is emitted when the event loop is about to block and wait for new events ([#2900](https://github.com/rust-windowing/winit/issues/2900))
|
||||||
|
|
||||||
# 0.29.0-beta.0
|
# 0.29.0-beta.0
|
||||||
|
|
||||||
|
|
|
@ -95,18 +95,11 @@ fn main() -> Result<(), impl std::error::Error> {
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
Event::MainEventsCleared => {
|
Event::AboutToWait => {
|
||||||
if request_redraw && !wait_cancelled && !close_requested {
|
if request_redraw && !wait_cancelled && !close_requested {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
if close_requested {
|
|
||||||
control_flow.set_exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::RedrawRequested(_window_id) => {
|
|
||||||
fill::fill_window(&window);
|
|
||||||
}
|
|
||||||
Event::RedrawEventsCleared => {
|
|
||||||
match mode {
|
match mode {
|
||||||
Mode::Wait => control_flow.set_wait(),
|
Mode::Wait => control_flow.set_wait(),
|
||||||
Mode::WaitUntil => {
|
Mode::WaitUntil => {
|
||||||
|
@ -119,6 +112,13 @@ fn main() -> Result<(), impl std::error::Error> {
|
||||||
control_flow.set_poll();
|
control_flow.set_poll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if close_requested {
|
||||||
|
control_flow.set_exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::RedrawRequested(_window_id) => {
|
||||||
|
fill::fill_window(&window);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub fn main() -> Result<(), impl std::error::Error> {
|
||||||
event: WindowEvent::CloseRequested,
|
event: WindowEvent::CloseRequested,
|
||||||
window_id,
|
window_id,
|
||||||
} if window_id == window.id() => control_flow.set_exit(),
|
} if window_id == window.id() => control_flow.set_exit(),
|
||||||
Event::MainEventsCleared => {
|
Event::AboutToWait => {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
Event::WindowEvent {
|
Event::WindowEvent {
|
||||||
|
|
|
@ -29,7 +29,7 @@ fn main() -> Result<(), impl std::error::Error> {
|
||||||
event: WindowEvent::CloseRequested,
|
event: WindowEvent::CloseRequested,
|
||||||
window_id,
|
window_id,
|
||||||
} if window_id == window.id() => control_flow.set_exit(),
|
} if window_id == window.id() => control_flow.set_exit(),
|
||||||
Event::MainEventsCleared => {
|
Event::AboutToWait => {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
Event::RedrawRequested(_) => {
|
Event::RedrawRequested(_) => {
|
||||||
|
|
|
@ -43,7 +43,7 @@ fn main() -> Result<(), impl std::error::Error> {
|
||||||
println!("--------------------------------------------------------- Window {idx} CloseRequested");
|
println!("--------------------------------------------------------- Window {idx} CloseRequested");
|
||||||
app.window = None;
|
app.window = None;
|
||||||
}
|
}
|
||||||
Event::MainEventsCleared => window.request_redraw(),
|
Event::AboutToWait => window.request_redraw(),
|
||||||
Event::RedrawRequested(_) => {
|
Event::RedrawRequested(_) => {
|
||||||
fill::fill_window(window);
|
fill::fill_window(window);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ fn main() -> Result<(), impl std::error::Error> {
|
||||||
WindowEvent::KeyboardInput { .. } => println!("KeyboardInput: {event:?}"),
|
WindowEvent::KeyboardInput { .. } => println!("KeyboardInput: {event:?}"),
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
Event::MainEventsCleared => {
|
Event::AboutToWait => {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
Event::RedrawRequested(_) => {
|
Event::RedrawRequested(_) => {
|
||||||
|
|
|
@ -45,7 +45,7 @@ fn main() -> std::process::ExitCode {
|
||||||
event: WindowEvent::CloseRequested,
|
event: WindowEvent::CloseRequested,
|
||||||
window_id,
|
window_id,
|
||||||
} if window_id == window.id() => control_flow.set_exit(),
|
} if window_id == window.id() => control_flow.set_exit(),
|
||||||
Event::MainEventsCleared => {
|
Event::AboutToWait => {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
Event::RedrawRequested(_) => {
|
Event::RedrawRequested(_) => {
|
||||||
|
|
|
@ -54,7 +54,7 @@ fn main() -> Result<(), impl std::error::Error> {
|
||||||
debug!("Had increments: {}", new_increments.is_none());
|
debug!("Had increments: {}", new_increments.is_none());
|
||||||
window.set_resize_increments(new_increments);
|
window.set_resize_increments(new_increments);
|
||||||
}
|
}
|
||||||
Event::MainEventsCleared => window.request_redraw(),
|
Event::AboutToWait => window.request_redraw(),
|
||||||
Event::RedrawRequested(_) => {
|
Event::RedrawRequested(_) => {
|
||||||
fill::fill_window(&window);
|
fill::fill_window(&window);
|
||||||
}
|
}
|
||||||
|
|
63
src/event.rs
63
src/event.rs
|
@ -16,13 +16,12 @@
|
||||||
//! for e in (window events, user events, device events) {
|
//! for e in (window events, user events, device events) {
|
||||||
//! event_handler(e, ..., &mut control_flow);
|
//! event_handler(e, ..., &mut control_flow);
|
||||||
//! }
|
//! }
|
||||||
//! event_handler(MainEventsCleared, ..., &mut control_flow);
|
|
||||||
//!
|
//!
|
||||||
//! for w in (redraw windows) {
|
//! for w in (redraw windows) {
|
||||||
//! event_handler(RedrawRequested(w), ..., &mut control_flow);
|
//! event_handler(RedrawRequested(w), ..., &mut control_flow);
|
||||||
//! }
|
//! }
|
||||||
//! event_handler(RedrawEventsCleared, ..., &mut control_flow);
|
|
||||||
//!
|
//!
|
||||||
|
//! event_handler(AboutToWait, ..., &mut control_flow);
|
||||||
//! start_cause = wait_if_necessary(control_flow);
|
//! start_cause = wait_if_necessary(control_flow);
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
@ -207,53 +206,30 @@ pub enum Event<'a, T: 'static> {
|
||||||
/// [`Suspended`]: Self::Suspended
|
/// [`Suspended`]: Self::Suspended
|
||||||
Resumed,
|
Resumed,
|
||||||
|
|
||||||
/// Emitted when all of the event loop's input events have been processed and redraw processing
|
/// Emitted when the event loop is about to block and wait for new events.
|
||||||
/// is about to begin.
|
|
||||||
///
|
///
|
||||||
/// This event is useful as a place to put your code that should be run after all
|
/// Most applications shouldn't need to hook into this event since there is no real relationship
|
||||||
/// state-changing events have been handled and you want to do stuff (updating state, performing
|
/// between how often the event loop needs to wake up and the dispatching of any specific events.
|
||||||
/// calculations, etc) that happens as the "main body" of your event loop. If your program only draws
|
///
|
||||||
/// graphics when something changes, it's usually better to do it in response to
|
/// High frequency event sources, such as input devices could potentially lead to lots of wake
|
||||||
/// [`Event::RedrawRequested`](crate::event::Event::RedrawRequested), which gets emitted
|
/// ups and also lots of corresponding `AboutToWait` events.
|
||||||
/// immediately after this event. Programs that draw graphics continuously, like most games,
|
///
|
||||||
/// can render here unconditionally for simplicity.
|
/// This is not an ideal event to drive application rendering from and instead applications
|
||||||
MainEventsCleared,
|
/// should render in response to [`Event::RedrawRequested`](crate::event::Event::RedrawRequested)
|
||||||
|
/// events.
|
||||||
|
AboutToWait,
|
||||||
|
|
||||||
/// Emitted after [`MainEventsCleared`] when a window should be redrawn.
|
/// Emitted when a window should be redrawn.
|
||||||
///
|
///
|
||||||
/// This gets triggered in two scenarios:
|
/// This gets triggered in two scenarios:
|
||||||
/// - The OS has performed an operation that's invalidated the window's contents (such as
|
/// - The OS has performed an operation that's invalidated the window's contents (such as
|
||||||
/// resizing the window).
|
/// resizing the window).
|
||||||
/// - The application has explicitly requested a redraw via [`Window::request_redraw`].
|
/// - The application has explicitly requested a redraw via [`Window::request_redraw`].
|
||||||
///
|
///
|
||||||
/// During each iteration of the event loop, Winit will aggregate duplicate redraw requests
|
/// Winit will aggregate duplicate redraw requests into a single event, to
|
||||||
/// into a single event, to help avoid duplicating rendering work.
|
/// help avoid duplicating rendering work.
|
||||||
///
|
|
||||||
/// Mainly of interest to applications with mostly-static graphics that avoid redrawing unless
|
|
||||||
/// something changes, like most non-game GUIs.
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// ## Platform-specific
|
|
||||||
///
|
|
||||||
/// - **macOS / iOS:** Due to implementation difficulties, this will often, but not always, be
|
|
||||||
/// emitted directly inside `drawRect:`, with neither a preceding [`MainEventsCleared`] nor
|
|
||||||
/// subsequent `RedrawEventsCleared`. See [#2640] for work on this.
|
|
||||||
///
|
|
||||||
/// [`MainEventsCleared`]: Self::MainEventsCleared
|
|
||||||
/// [`RedrawEventsCleared`]: Self::RedrawEventsCleared
|
|
||||||
/// [#2640]: https://github.com/rust-windowing/winit/issues/2640
|
|
||||||
RedrawRequested(WindowId),
|
RedrawRequested(WindowId),
|
||||||
|
|
||||||
/// Emitted after all [`RedrawRequested`] events have been processed and control flow is about to
|
|
||||||
/// be taken away from the program. If there are no `RedrawRequested` events, it is emitted
|
|
||||||
/// immediately after `MainEventsCleared`.
|
|
||||||
///
|
|
||||||
/// This event is useful for doing any cleanup or bookkeeping work after all the rendering
|
|
||||||
/// tasks have been completed.
|
|
||||||
///
|
|
||||||
/// [`RedrawRequested`]: Self::RedrawRequested
|
|
||||||
RedrawEventsCleared,
|
|
||||||
|
|
||||||
/// Emitted when the event loop is being shut down.
|
/// Emitted when the event loop is being shut down.
|
||||||
///
|
///
|
||||||
/// This is irreversible - if this event is emitted, it is guaranteed to be the last event that
|
/// This is irreversible - if this event is emitted, it is guaranteed to be the last event that
|
||||||
|
@ -275,9 +251,8 @@ impl<T: Clone> Clone for Event<'static, T> {
|
||||||
event: event.clone(),
|
event: event.clone(),
|
||||||
},
|
},
|
||||||
NewEvents(cause) => NewEvents(*cause),
|
NewEvents(cause) => NewEvents(*cause),
|
||||||
MainEventsCleared => MainEventsCleared,
|
AboutToWait => AboutToWait,
|
||||||
RedrawRequested(wid) => RedrawRequested(*wid),
|
RedrawRequested(wid) => RedrawRequested(*wid),
|
||||||
RedrawEventsCleared => RedrawEventsCleared,
|
|
||||||
LoopExiting => LoopExiting,
|
LoopExiting => LoopExiting,
|
||||||
Suspended => Suspended,
|
Suspended => Suspended,
|
||||||
Resumed => Resumed,
|
Resumed => Resumed,
|
||||||
|
@ -294,9 +269,8 @@ impl<'a, T> Event<'a, T> {
|
||||||
WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }),
|
WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }),
|
||||||
DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }),
|
DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }),
|
||||||
NewEvents(cause) => Ok(NewEvents(cause)),
|
NewEvents(cause) => Ok(NewEvents(cause)),
|
||||||
MainEventsCleared => Ok(MainEventsCleared),
|
AboutToWait => Ok(AboutToWait),
|
||||||
RedrawRequested(wid) => Ok(RedrawRequested(wid)),
|
RedrawRequested(wid) => Ok(RedrawRequested(wid)),
|
||||||
RedrawEventsCleared => Ok(RedrawEventsCleared),
|
|
||||||
LoopExiting => Ok(LoopExiting),
|
LoopExiting => Ok(LoopExiting),
|
||||||
Suspended => Ok(Suspended),
|
Suspended => Ok(Suspended),
|
||||||
Resumed => Ok(Resumed),
|
Resumed => Ok(Resumed),
|
||||||
|
@ -314,9 +288,8 @@ impl<'a, T> Event<'a, T> {
|
||||||
UserEvent(event) => Some(UserEvent(event)),
|
UserEvent(event) => Some(UserEvent(event)),
|
||||||
DeviceEvent { device_id, event } => Some(DeviceEvent { device_id, event }),
|
DeviceEvent { device_id, event } => Some(DeviceEvent { device_id, event }),
|
||||||
NewEvents(cause) => Some(NewEvents(cause)),
|
NewEvents(cause) => Some(NewEvents(cause)),
|
||||||
MainEventsCleared => Some(MainEventsCleared),
|
AboutToWait => Some(AboutToWait),
|
||||||
RedrawRequested(wid) => Some(RedrawRequested(wid)),
|
RedrawRequested(wid) => Some(RedrawRequested(wid)),
|
||||||
RedrawEventsCleared => Some(RedrawEventsCleared),
|
|
||||||
LoopExiting => Some(LoopExiting),
|
LoopExiting => Some(LoopExiting),
|
||||||
Suspended => Some(Suspended),
|
Suspended => Some(Suspended),
|
||||||
Resumed => Some(Resumed),
|
Resumed => Some(Resumed),
|
||||||
|
|
|
@ -149,7 +149,7 @@ impl<T> fmt::Debug for EventLoopWindowTarget<T> {
|
||||||
|
|
||||||
/// Set by the user callback given to the [`EventLoop::run`] method.
|
/// Set by the user callback given to the [`EventLoop::run`] method.
|
||||||
///
|
///
|
||||||
/// Indicates the desired behavior of the event loop after [`Event::RedrawEventsCleared`] is emitted.
|
/// Indicates the desired behavior of the event loop after [`Event::AboutToWait`] is emitted.
|
||||||
///
|
///
|
||||||
/// Defaults to [`Poll`].
|
/// Defaults to [`Poll`].
|
||||||
///
|
///
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
//! println!("The close button was pressed; stopping");
|
//! println!("The close button was pressed; stopping");
|
||||||
//! control_flow.set_exit();
|
//! control_flow.set_exit();
|
||||||
//! },
|
//! },
|
||||||
//! Event::MainEventsCleared => {
|
//! Event::AboutToWait => {
|
||||||
//! // Application update code.
|
//! // Application update code.
|
||||||
//!
|
//!
|
||||||
//! // Queue a RedrawRequested event.
|
//! // Queue a RedrawRequested event.
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
//! // Redraw the application.
|
//! // Redraw the application.
|
||||||
//! //
|
//! //
|
||||||
//! // It's preferable for applications that do not render continuously to render in
|
//! // It's preferable for applications that do not render continuously to render in
|
||||||
//! // this event rather than in MainEventsCleared, since rendering in here allows
|
//! // this event rather than in AboutToWait, since rendering in here allows
|
||||||
//! // the program to gracefully handle redraws requested by the OS.
|
//! // the program to gracefully handle redraws requested by the OS.
|
||||||
//! },
|
//! },
|
||||||
//! _ => ()
|
//! _ => ()
|
||||||
|
|
|
@ -74,7 +74,7 @@ pub trait EventLoopExtPumpEvents {
|
||||||
/// event: WindowEvent::CloseRequested,
|
/// event: WindowEvent::CloseRequested,
|
||||||
/// window_id,
|
/// window_id,
|
||||||
/// } if window_id == window.id() => control_flow.set_exit(),
|
/// } if window_id == window.id() => control_flow.set_exit(),
|
||||||
/// Event::MainEventsCleared => {
|
/// Event::AboutToWait => {
|
||||||
/// window.request_redraw();
|
/// window.request_redraw();
|
||||||
/// }
|
/// }
|
||||||
/// _ => (),
|
/// _ => (),
|
||||||
|
|
|
@ -484,13 +484,6 @@ impl<T: 'static> EventLoop<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sticky_exit_callback(
|
|
||||||
event::Event::MainEventsCleared,
|
|
||||||
self.window_target(),
|
|
||||||
&mut control_flow,
|
|
||||||
callback,
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.running {
|
if self.running {
|
||||||
if resized {
|
if resized {
|
||||||
let size = if let Some(native_window) = self.android_app.native_window().as_ref() {
|
let size = if let Some(native_window) = self.android_app.native_window().as_ref() {
|
||||||
|
@ -515,8 +508,9 @@ impl<T: 'static> EventLoop<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is always the last event we dispatch before poll again
|
||||||
sticky_exit_callback(
|
sticky_exit_callback(
|
||||||
event::Event::RedrawEventsCleared,
|
event::Event::AboutToWait,
|
||||||
self.window_target(),
|
self.window_target(),
|
||||||
&mut control_flow,
|
&mut control_flow,
|
||||||
callback,
|
callback,
|
||||||
|
|
|
@ -753,21 +753,18 @@ pub unsafe fn handle_main_events_cleared() {
|
||||||
};
|
};
|
||||||
drop(this);
|
drop(this);
|
||||||
|
|
||||||
// User events are always sent out at the end of the "MainEventLoop"
|
|
||||||
handle_user_events();
|
handle_user_events();
|
||||||
handle_nonuser_event(EventWrapper::StaticEvent(Event::MainEventsCleared));
|
|
||||||
|
|
||||||
let mut this = AppState::get_mut();
|
let mut this = AppState::get_mut();
|
||||||
let mut redraw_events: Vec<EventWrapper> = this
|
let redraw_events: Vec<EventWrapper> = this
|
||||||
.main_events_cleared_transition()
|
.main_events_cleared_transition()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|window| EventWrapper::StaticEvent(Event::RedrawRequested(RootWindowId(window.id()))))
|
.map(|window| EventWrapper::StaticEvent(Event::RedrawRequested(RootWindowId(window.id()))))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
redraw_events.push(EventWrapper::StaticEvent(Event::RedrawEventsCleared));
|
|
||||||
drop(this);
|
drop(this);
|
||||||
|
|
||||||
handle_nonuser_events(redraw_events);
|
handle_nonuser_events(redraw_events);
|
||||||
|
handle_nonuser_event(EventWrapper::StaticEvent(Event::AboutToWait));
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires main thread
|
// requires main thread
|
||||||
|
|
|
@ -237,10 +237,10 @@ fn setup_control_flow_observers() {
|
||||||
|
|
||||||
// Core Animation registers its `CFRunLoopObserver` that performs drawing operations in
|
// Core Animation registers its `CFRunLoopObserver` that performs drawing operations in
|
||||||
// `CA::Transaction::ensure_implicit` with a priority of `0x1e8480`. We set the main_end
|
// `CA::Transaction::ensure_implicit` with a priority of `0x1e8480`. We set the main_end
|
||||||
// priority to be 0, in order to send MainEventsCleared before RedrawRequested. This value was
|
// 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
|
// 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
|
// 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 `MainEventsCleared`.
|
// 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 `0x1e8480` was determined by inspecting stack traces and the associated
|
||||||
// registers for every `CFRunLoopAddObserver` call on an iPad Air 2 running iOS 11.4.
|
// registers for every `CFRunLoopAddObserver` call on an iPad Air 2 running iOS 11.4.
|
||||||
|
|
|
@ -42,14 +42,9 @@ declare_class!(
|
||||||
fn draw_rect(&self, rect: CGRect) {
|
fn draw_rect(&self, rect: CGRect) {
|
||||||
let window = self.window().unwrap();
|
let window = self.window().unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
app_state::handle_nonuser_events(
|
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawRequested(
|
||||||
std::iter::once(EventWrapper::StaticEvent(Event::RedrawRequested(
|
RootWindowId(window.id()),
|
||||||
RootWindowId(window.id()),
|
)));
|
||||||
)))
|
|
||||||
.chain(std::iter::once(EventWrapper::StaticEvent(
|
|
||||||
Event::RedrawEventsCleared,
|
|
||||||
))),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let _: () = unsafe { msg_send![super(self), drawRect: rect] };
|
let _: () = unsafe { msg_send![super(self), drawRect: rect] };
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,14 +475,6 @@ impl<T: 'static> EventLoop<T> {
|
||||||
sticky_exit_callback(event, &self.window_target, &mut control_flow, &mut callback);
|
sticky_exit_callback(event, &self.window_target, &mut control_flow, &mut callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send events cleared.
|
|
||||||
sticky_exit_callback(
|
|
||||||
Event::MainEventsCleared,
|
|
||||||
&self.window_target,
|
|
||||||
&mut control_flow,
|
|
||||||
&mut callback,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Collect the window ids
|
// Collect the window ids
|
||||||
self.with_state(|state| {
|
self.with_state(|state| {
|
||||||
window_ids.extend(state.window_requests.get_mut().keys());
|
window_ids.extend(state.window_requests.get_mut().keys());
|
||||||
|
@ -525,9 +517,9 @@ impl<T: 'static> EventLoop<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send RedrawEventCleared.
|
// This is always the last event we dispatch before poll again
|
||||||
sticky_exit_callback(
|
sticky_exit_callback(
|
||||||
Event::RedrawEventsCleared,
|
Event::AboutToWait,
|
||||||
&self.window_target,
|
&self.window_target,
|
||||||
&mut control_flow,
|
&mut control_flow,
|
||||||
&mut callback,
|
&mut callback,
|
||||||
|
|
|
@ -659,15 +659,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// send MainEventsCleared
|
|
||||||
{
|
|
||||||
sticky_exit_callback(
|
|
||||||
crate::event::Event::MainEventsCleared,
|
|
||||||
&self.target,
|
|
||||||
&mut control_flow,
|
|
||||||
callback,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Empty the redraw requests
|
// Empty the redraw requests
|
||||||
{
|
{
|
||||||
let mut windows = HashSet::new();
|
let mut windows = HashSet::new();
|
||||||
|
@ -686,10 +678,11 @@ impl<T: 'static> EventLoop<T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// send RedrawEventsCleared
|
|
||||||
|
// This is always the last event we dispatch before poll again
|
||||||
{
|
{
|
||||||
sticky_exit_callback(
|
sticky_exit_callback(
|
||||||
crate::event::Event::RedrawEventsCleared,
|
crate::event::Event::AboutToWait,
|
||||||
&self.target,
|
&self.target,
|
||||||
&mut control_flow,
|
&mut control_flow,
|
||||||
callback,
|
callback,
|
||||||
|
|
|
@ -615,13 +615,13 @@ impl AppState {
|
||||||
for event in HANDLER.take_events() {
|
for event in HANDLER.take_events() {
|
||||||
HANDLER.handle_nonuser_event(event);
|
HANDLER.handle_nonuser_event(event);
|
||||||
}
|
}
|
||||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::MainEventsCleared));
|
|
||||||
|
|
||||||
for window_id in HANDLER.should_redraw() {
|
for window_id in HANDLER.should_redraw() {
|
||||||
HANDLER
|
HANDLER
|
||||||
.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawRequested(window_id)));
|
.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawRequested(window_id)));
|
||||||
}
|
}
|
||||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawEventsCleared));
|
|
||||||
|
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::AboutToWait));
|
||||||
HANDLER.set_in_callback(false);
|
HANDLER.set_in_callback(false);
|
||||||
|
|
||||||
if HANDLER.should_exit() {
|
if HANDLER.should_exit() {
|
||||||
|
|
|
@ -64,7 +64,7 @@ extern "C" fn control_flow_begin_handler(
|
||||||
}
|
}
|
||||||
|
|
||||||
// end is queued with the lowest priority to ensure it is processed after other observers
|
// end is queued with the lowest priority to ensure it is processed after other observers
|
||||||
// without that, LoopExiting would get sent after MainEventsCleared
|
// without that, LoopExiting would get sent after AboutToWait
|
||||||
extern "C" fn control_flow_end_handler(
|
extern "C" fn control_flow_end_handler(
|
||||||
_: CFRunLoopObserverRef,
|
_: CFRunLoopObserverRef,
|
||||||
activity: CFRunLoopActivity,
|
activity: CFRunLoopActivity,
|
||||||
|
|
|
@ -594,12 +594,6 @@ impl<T: 'static> EventLoop<T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
event_handler(
|
|
||||||
event::Event::MainEventsCleared,
|
|
||||||
&self.window_target,
|
|
||||||
&mut control_flow,
|
|
||||||
);
|
|
||||||
|
|
||||||
// To avoid deadlocks the redraws lock is not held during event processing.
|
// To avoid deadlocks the redraws lock is not held during event processing.
|
||||||
while let Some(window_id) = {
|
while let Some(window_id) = {
|
||||||
let mut redraws = self.window_target.p.redraws.lock().unwrap();
|
let mut redraws = self.window_target.p.redraws.lock().unwrap();
|
||||||
|
@ -613,7 +607,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
event_handler(
|
event_handler(
|
||||||
event::Event::RedrawEventsCleared,
|
event::Event::AboutToWait,
|
||||||
&self.window_target,
|
&self.window_target,
|
||||||
&mut control_flow,
|
&mut control_flow,
|
||||||
);
|
);
|
||||||
|
|
|
@ -535,7 +535,7 @@ impl<T: 'static> Shared<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the destroy-pending windows. This should only be called from
|
// Process the destroy-pending windows. This should only be called from
|
||||||
// `run_until_cleared`, somewhere between emitting `NewEvents` and `MainEventsCleared`.
|
// `run_until_cleared`, somewhere between emitting `NewEvents` and `AboutToWait`.
|
||||||
fn process_destroy_pending_windows(&self, control: &mut ControlFlow) {
|
fn process_destroy_pending_windows(&self, control: &mut ControlFlow) {
|
||||||
while let Some(id) = self.0.destroy_pending.borrow_mut().pop_front() {
|
while let Some(id) = self.0.destroy_pending.borrow_mut().pop_front() {
|
||||||
self.0
|
self.0
|
||||||
|
@ -563,14 +563,14 @@ impl<T: 'static> Shared<T> {
|
||||||
self.handle_event(event.into(), &mut control);
|
self.handle_event(event.into(), &mut control);
|
||||||
}
|
}
|
||||||
self.process_destroy_pending_windows(&mut control);
|
self.process_destroy_pending_windows(&mut control);
|
||||||
self.handle_event(Event::MainEventsCleared, &mut control);
|
|
||||||
|
|
||||||
// Collect all of the redraw events to avoid double-locking the RefCell
|
// Collect all of the redraw events to avoid double-locking the RefCell
|
||||||
let redraw_events: Vec<WindowId> = self.0.redraw_pending.borrow_mut().drain().collect();
|
let redraw_events: Vec<WindowId> = self.0.redraw_pending.borrow_mut().drain().collect();
|
||||||
for window_id in redraw_events {
|
for window_id in redraw_events {
|
||||||
self.handle_event(Event::RedrawRequested(window_id), &mut control);
|
self.handle_event(Event::RedrawRequested(window_id), &mut control);
|
||||||
}
|
}
|
||||||
self.handle_event(Event::RedrawEventsCleared, &mut control);
|
|
||||||
|
self.handle_event(Event::AboutToWait, &mut control);
|
||||||
|
|
||||||
self.apply_control_flow(control);
|
self.apply_control_flow(control);
|
||||||
// If the event loop is closed, it has been closed this iteration and now the closing
|
// If the event loop is closed, it has been closed this iteration and now the closing
|
||||||
|
|
|
@ -403,7 +403,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We aim to be consistent with the MacOS backend which has a RunLoop
|
// We aim to be consistent with the MacOS backend which has a RunLoop
|
||||||
// observer that will dispatch MainEventsCleared when about to wait for
|
// observer that will dispatch AboutToWait when about to wait for
|
||||||
// events, and NewEvents after the RunLoop wakes up.
|
// events, and NewEvents after the RunLoop wakes up.
|
||||||
//
|
//
|
||||||
// We emulate similar behaviour by treating `GetMessage` as our wait
|
// We emulate similar behaviour by treating `GetMessage` as our wait
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub(crate) enum RunnerState {
|
||||||
/// The event loop is idling.
|
/// The event loop is idling.
|
||||||
Idle,
|
Idle,
|
||||||
/// The event loop is handling the OS's events and sending them to the user's callback.
|
/// The event loop is handling the OS's events and sending them to the user's callback.
|
||||||
/// `NewEvents` has been sent, and `MainEventsCleared` hasn't.
|
/// `NewEvents` has been sent, and `AboutToWait` hasn't.
|
||||||
HandlingMainEvents,
|
HandlingMainEvents,
|
||||||
/// The event loop has been destroyed. No other events will be emitted.
|
/// The event loop has been destroyed. No other events will be emitted.
|
||||||
Destroyed,
|
Destroyed,
|
||||||
|
@ -250,8 +250,9 @@ impl<T> EventLoopRunner<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dispatch control flow events (`NewEvents`, `MainEventsCleared`, `RedrawEventsCleared`, and
|
/// Dispatch control flow events (`NewEvents`, `AboutToWait`, and
|
||||||
/// `LoopExiting`) as necessary to bring the internal `RunnerState` to the new runner state.
|
/// `LoopExiting`) as necessary to bring the internal `RunnerState` to the
|
||||||
|
/// new runner state.
|
||||||
///
|
///
|
||||||
/// The state transitions are defined as follows:
|
/// The state transitions are defined as follows:
|
||||||
///
|
///
|
||||||
|
@ -291,13 +292,13 @@ impl<T> EventLoopRunner<T> {
|
||||||
}
|
}
|
||||||
(Uninitialized, Idle) => {
|
(Uninitialized, Idle) => {
|
||||||
self.call_new_events(true);
|
self.call_new_events(true);
|
||||||
self.call_event_handler(Event::MainEventsCleared);
|
self.call_event_handler(Event::AboutToWait);
|
||||||
self.call_redraw_events_cleared();
|
self.last_events_cleared.set(Instant::now());
|
||||||
}
|
}
|
||||||
(Uninitialized, Destroyed) => {
|
(Uninitialized, Destroyed) => {
|
||||||
self.call_new_events(true);
|
self.call_new_events(true);
|
||||||
self.call_event_handler(Event::MainEventsCleared);
|
self.call_event_handler(Event::AboutToWait);
|
||||||
self.call_redraw_events_cleared();
|
self.last_events_cleared.set(Instant::now());
|
||||||
self.call_event_handler(Event::LoopExiting);
|
self.call_event_handler(Event::LoopExiting);
|
||||||
}
|
}
|
||||||
(_, Uninitialized) => panic!("cannot move state to Uninitialized"),
|
(_, Uninitialized) => panic!("cannot move state to Uninitialized"),
|
||||||
|
@ -311,12 +312,13 @@ impl<T> EventLoopRunner<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
(HandlingMainEvents, Idle) => {
|
(HandlingMainEvents, Idle) => {
|
||||||
self.call_event_handler(Event::MainEventsCleared);
|
// This is always the last event we dispatch before waiting for new events
|
||||||
self.call_redraw_events_cleared();
|
self.call_event_handler(Event::AboutToWait);
|
||||||
|
self.last_events_cleared.set(Instant::now());
|
||||||
}
|
}
|
||||||
(HandlingMainEvents, Destroyed) => {
|
(HandlingMainEvents, Destroyed) => {
|
||||||
self.call_event_handler(Event::MainEventsCleared);
|
self.call_event_handler(Event::AboutToWait);
|
||||||
self.call_redraw_events_cleared();
|
self.last_events_cleared.set(Instant::now());
|
||||||
self.call_event_handler(Event::LoopExiting);
|
self.call_event_handler(Event::LoopExiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,11 +358,6 @@ impl<T> EventLoopRunner<T> {
|
||||||
}
|
}
|
||||||
self.dispatch_buffered_events();
|
self.dispatch_buffered_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_redraw_events_cleared(&self) {
|
|
||||||
self.call_event_handler(Event::RedrawEventsCleared);
|
|
||||||
self.last_events_cleared.set(Instant::now());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> BufferedEvent<T> {
|
impl<T> BufferedEvent<T> {
|
||||||
|
|
Loading…
Reference in a new issue