1
1
// Copyright 2024 the Xilem Authors
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
- use std:: cmp:: Reverse ;
5
- use std:: collections:: BinaryHeap ;
6
4
use std:: num:: NonZeroUsize ;
7
5
use std:: sync:: Arc ;
8
6
use std:: time:: Instant ;
@@ -19,13 +17,14 @@ use winit::event::{
19
17
DeviceEvent as WinitDeviceEvent , DeviceId , MouseButton as WinitMouseButton ,
20
18
WindowEvent as WinitWindowEvent ,
21
19
} ;
22
- use winit:: event_loop:: ActiveEventLoop ;
20
+ use winit:: event_loop:: { ActiveEventLoop , ControlFlow } ;
23
21
use winit:: window:: { Window , WindowAttributes , WindowId } ;
24
22
25
23
use crate :: app_driver:: { AppDriver , DriverCtx } ;
26
24
use crate :: dpi:: LogicalPosition ;
27
25
use crate :: event:: { PointerButton , PointerState , WindowEvent } ;
28
26
use crate :: render_root:: { self , RenderRoot , WindowSizePolicy } ;
27
+ use crate :: timers:: TimerQueue ;
29
28
use crate :: { Color , PointerEvent , TextEvent , Widget , WidgetId } ;
30
29
31
30
#[ derive( Debug ) ]
@@ -83,8 +82,7 @@ pub struct MasonryState<'a> {
83
82
proxy : EventLoopProxy ,
84
83
#[ cfg( feature = "tracy" ) ]
85
84
frame : Option < tracing_tracy:: client:: Frame > ,
86
- // timers as a min priority queue
87
- timers : BinaryHeap < Reverse < Instant > > ,
85
+ timers : TimerQueue ,
88
86
89
87
// Per-Window state
90
88
// In future, this will support multiple windows
@@ -163,20 +161,12 @@ impl ApplicationHandler<MasonryUserEvent> for MainState<'_> {
163
161
self . masonry_state . handle_suspended ( event_loop) ;
164
162
}
165
163
166
- fn new_events ( & mut self , event_loop : & ActiveEventLoop , cause : StartCause ) {
167
- // check if timers have elapsed and set event loop to wake at next timer deadline
168
- let now = Instant :: now ( ) ;
169
- loop {
170
- let Some ( next_timer) = self . masonry_state . timers . peek ( ) . cloned ( ) else {
171
- break ;
172
- } ;
173
- let next_timer = next_timer. 0 ;
174
- if next_timer > now {
175
- break ;
176
- }
177
- // timer has elapsed - remove from heap and handle
178
- self . masonry_state . timers . pop ( ) ;
179
- }
164
+ fn new_events (
165
+ & mut self ,
166
+ event_loop : & winit:: event_loop:: ActiveEventLoop ,
167
+ cause : winit:: event:: StartCause ,
168
+ ) {
169
+ self . masonry_state . handle_new_events ( event_loop, cause) ;
180
170
}
181
171
182
172
fn window_event (
@@ -220,14 +210,6 @@ impl ApplicationHandler<MasonryUserEvent> for MainState<'_> {
220
210
self . masonry_state . handle_about_to_wait ( event_loop) ;
221
211
}
222
212
223
- fn new_events (
224
- & mut self ,
225
- event_loop : & winit:: event_loop:: ActiveEventLoop ,
226
- cause : winit:: event:: StartCause ,
227
- ) {
228
- self . masonry_state . handle_new_events ( event_loop, cause) ;
229
- }
230
-
231
213
fn exiting ( & mut self , event_loop : & winit:: event_loop:: ActiveEventLoop ) {
232
214
self . masonry_state . handle_exiting ( event_loop) ;
233
215
}
@@ -264,6 +246,7 @@ impl MasonryState<'_> {
264
246
frame : None ,
265
247
pointer_state : PointerState :: empty ( ) ,
266
248
proxy : event_loop. create_proxy ( ) ,
249
+ timers : TimerQueue :: new ( ) ,
267
250
268
251
window : WindowState :: Uninitialized ( window) ,
269
252
background_color,
@@ -678,10 +661,35 @@ impl MasonryState<'_> {
678
661
self . handle_signals ( event_loop, app_driver) ;
679
662
}
680
663
681
- // --- MARK: EMPTY WINIT HANDLERS ---
682
- pub fn handle_about_to_wait ( & mut self , _: & ActiveEventLoop ) { }
664
+ // --- MARK: TIMERS ---
665
+ pub fn handle_new_events ( & mut self , _: & ActiveEventLoop , _: winit:: event:: StartCause ) {
666
+ // check if timers have elapsed and set event loop to wake at next timer deadline
667
+ let now = Instant :: now ( ) ;
668
+ loop {
669
+ let Some ( next_timer) = self . timers . peek ( ) else {
670
+ break ;
671
+ } ;
672
+ if next_timer. deadline > now {
673
+ break ;
674
+ }
675
+ // timer has elapsed - remove from heap and handle
676
+ let Some ( elapsed_timer) = self . timers . pop ( ) else {
677
+ debug_panic ! ( "should be unreachable: peek was Some" ) ;
678
+ break ;
679
+ } ;
680
+ self . render_root . handle_elapsed_timer ( elapsed_timer) ;
681
+ }
682
+ }
683
+
684
+ pub fn handle_about_to_wait ( & mut self , event_loop : & ActiveEventLoop ) {
685
+ if let Some ( next_timer) = self . timers . peek ( ) {
686
+ event_loop. set_control_flow ( ControlFlow :: WaitUntil ( next_timer. deadline ) ) ;
687
+ } else {
688
+ event_loop. set_control_flow ( ControlFlow :: Wait ) ;
689
+ }
690
+ }
683
691
684
- pub fn handle_new_events ( & mut self , _ : & ActiveEventLoop , _ : winit :: event :: StartCause ) { }
692
+ // --- MARK: EMPTY WINIT HANDLERS ---
685
693
686
694
pub fn handle_exiting ( & mut self , _: & ActiveEventLoop ) { }
687
695
@@ -706,6 +714,9 @@ impl MasonryState<'_> {
706
714
app_driver. on_action ( & mut driver_ctx, widget_id, action) ;
707
715
} ) ;
708
716
}
717
+ render_root:: RenderRootSignal :: TimerRequested ( timer) => {
718
+ self . timers . push ( timer) ;
719
+ }
709
720
render_root:: RenderRootSignal :: StartIme => {
710
721
window. set_ime_allowed ( true ) ;
711
722
}
0 commit comments