1
1
use crate :: CustomEvent ;
2
- use crate :: WindowState ;
3
- use crate :: WindowStateHandle ;
2
+ use crate :: FrameBuffer ;
3
+ use crate :: WindowSize ;
4
4
use crate :: render:: GraphicsState ;
5
5
use std:: sync:: Arc ;
6
+ use std:: sync:: mpsc:: Sender ;
6
7
use std:: time:: Duration ;
7
8
use std:: time:: Instant ;
8
9
use winit:: application:: ApplicationHandler ;
10
+ use winit:: dpi:: PhysicalSize ;
9
11
use winit:: event:: StartCause ;
10
12
use winit:: event:: WindowEvent ;
11
13
use winit:: event_loop:: ActiveEventLoop ;
12
14
use winit:: event_loop:: ControlFlow ;
15
+ use winit:: event_loop:: EventLoopProxy ;
13
16
use winit:: window:: Window ;
14
17
use winit:: window:: WindowId ;
15
18
16
19
use crate :: cef;
17
20
18
21
pub ( crate ) struct WinitApp {
19
- pub ( crate ) window_state : WindowStateHandle ,
20
22
pub ( crate ) cef_context : cef:: Context < cef:: Initialized > ,
21
23
pub ( crate ) window : Option < Arc < Window > > ,
22
24
cef_schedule : Option < Instant > ,
25
+ ui_frame_buffer : Option < FrameBuffer > ,
26
+ window_size_sender : Sender < WindowSize > ,
27
+ _viewport_frame_buffer : Option < FrameBuffer > ,
28
+ graphics_state : Option < GraphicsState > ,
29
+ event_loop_proxy : EventLoopProxy < CustomEvent > ,
23
30
}
24
31
25
32
impl WinitApp {
26
- pub ( crate ) fn new ( window_state : WindowStateHandle , cef_context : cef:: Context < cef:: Initialized > ) -> Self {
33
+ pub ( crate ) fn new ( cef_context : cef:: Context < cef:: Initialized > , window_size_sender : Sender < WindowSize > , event_loop_proxy : EventLoopProxy < CustomEvent > ) -> Self {
27
34
Self {
28
- window_state,
29
35
cef_context,
30
36
window : None ,
31
37
cef_schedule : Some ( Instant :: now ( ) ) ,
38
+ _viewport_frame_buffer : None ,
39
+ ui_frame_buffer : None ,
40
+ graphics_state : None ,
41
+ window_size_sender,
42
+ event_loop_proxy,
32
43
}
33
44
}
34
45
}
35
46
36
47
impl ApplicationHandler < CustomEvent > for WinitApp {
37
48
fn about_to_wait ( & mut self , event_loop : & ActiveEventLoop ) {
38
- let timeout = Instant :: now ( ) + Duration :: from_millis ( 10 ) ;
49
+ // Set a timeout in case we miss any cef schedule requests
50
+ let timeout = Instant :: now ( ) + Duration :: from_millis ( 100 ) ;
39
51
let wait_until = timeout. min ( self . cef_schedule . unwrap_or ( timeout) ) ;
40
52
event_loop. set_control_flow ( ControlFlow :: WaitUntil ( wait_until) ) ;
41
53
}
@@ -50,37 +62,42 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
50
62
}
51
63
52
64
fn resumed ( & mut self , event_loop : & ActiveEventLoop ) {
53
- self . window_state
54
- . with ( |s| {
55
- if let WindowState { width : Some ( w) , height : Some ( h) , .. } = s {
56
- let window = Arc :: new (
57
- event_loop
58
- . create_window (
59
- Window :: default_attributes ( )
60
- . with_title ( "CEF Offscreen Rendering" )
61
- . with_inner_size ( winit:: dpi:: LogicalSize :: new ( * w as u32 , * h as u32 ) ) ,
62
- )
63
- . unwrap ( ) ,
64
- ) ;
65
- let graphics_state = pollster:: block_on ( GraphicsState :: new ( window. clone ( ) ) ) ;
65
+ let window = Arc :: new (
66
+ event_loop
67
+ . create_window (
68
+ Window :: default_attributes ( )
69
+ . with_title ( "CEF Offscreen Rendering" )
70
+ . with_inner_size ( winit:: dpi:: LogicalSize :: new ( 1200 , 800 ) ) ,
71
+ )
72
+ . unwrap ( ) ,
73
+ ) ;
74
+ let graphics_state = pollster:: block_on ( GraphicsState :: new ( window. clone ( ) ) ) ;
66
75
67
- self . window = Some ( window. clone ( ) ) ;
68
- s . graphics_state = Some ( graphics_state) ;
76
+ self . window = Some ( window) ;
77
+ self . graphics_state = Some ( graphics_state) ;
69
78
70
- tracing:: info!( "Winit window created and ready" ) ;
71
- }
72
- } )
73
- . unwrap ( ) ;
79
+ tracing:: info!( "Winit window created and ready" ) ;
74
80
}
75
81
76
82
fn user_event ( & mut self , _: & ActiveEventLoop , event : CustomEvent ) {
77
83
match event {
78
- CustomEvent :: UiUpdate => {
84
+ CustomEvent :: UiUpdate ( frame_buffer) => {
85
+ if let Some ( graphics_state) = self . graphics_state . as_mut ( ) {
86
+ graphics_state. update_texture ( & frame_buffer) ;
87
+ }
88
+ self . ui_frame_buffer = Some ( frame_buffer) ;
79
89
if let Some ( window) = & self . window {
80
90
window. request_redraw ( ) ;
81
91
}
82
92
}
83
93
CustomEvent :: ScheduleBrowserWork ( instant) => {
94
+ if let Some ( graphics_state) = self . graphics_state . as_mut ( )
95
+ && let Some ( frame_buffer) = & self . ui_frame_buffer
96
+ && graphics_state. ui_texture_outdated ( frame_buffer)
97
+ {
98
+ self . cef_context . work ( ) ;
99
+ let _ = self . event_loop_proxy . send_event ( CustomEvent :: ScheduleBrowserWork ( Instant :: now ( ) + Duration :: from_millis ( 1 ) ) ) ;
100
+ }
84
101
self . cef_schedule = Some ( instant) ;
85
102
}
86
103
}
@@ -94,58 +111,33 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
94
111
tracing:: info!( "The close button was pressed; stopping" ) ;
95
112
event_loop. exit ( ) ;
96
113
}
97
- WindowEvent :: Resized ( physical_size) => {
98
- self . window_state
99
- . with ( |s| {
100
- let width = physical_size. width as usize ;
101
- let height = physical_size. height as usize ;
102
- s. width = Some ( width) ;
103
- s. height = Some ( height) ;
104
- if let Some ( graphics_state) = & mut s. graphics_state {
105
- graphics_state. resize ( width, height) ;
106
- }
107
- } )
108
- . unwrap ( ) ;
114
+ WindowEvent :: Resized ( PhysicalSize { width, height } ) => {
115
+ let _ = self . window_size_sender . send ( WindowSize :: new ( width as usize , height as usize ) ) ;
116
+ if let Some ( ref mut graphics_state) = self . graphics_state {
117
+ graphics_state. resize ( width, height) ;
118
+ }
109
119
self . cef_context . notify_of_resize ( ) ;
110
120
}
111
121
112
122
WindowEvent :: RedrawRequested => {
113
- self . cef_context . work ( ) ;
123
+ let Some ( ref mut graphics_state) = self . graphics_state else { return } ;
124
+ // Only rerender once we have a new ui texture to display
114
125
115
- self . window_state
116
- . with ( |s| {
117
- if let WindowState {
118
- width : Some ( width) ,
119
- height : Some ( height) ,
120
- graphics_state : Some ( graphics_state) ,
121
- ui_frame_buffer : ui_fb,
122
- ..
123
- } = s
124
- {
125
- if let Some ( fb) = & * ui_fb {
126
- graphics_state. update_texture ( fb) ;
127
- if fb. width ( ) != * width && fb. height ( ) != * height {
128
- graphics_state. resize ( * width, * height) ;
129
- }
130
- } else if let Some ( window) = & self . window {
131
- window. request_redraw ( ) ;
132
- }
133
-
134
- match graphics_state. render ( ) {
135
- Ok ( _) => { }
136
- Err ( wgpu:: SurfaceError :: Lost ) => {
137
- graphics_state. resize ( * width, * height) ;
138
- }
139
- Err ( wgpu:: SurfaceError :: OutOfMemory ) => {
140
- event_loop. exit ( ) ;
141
- }
142
- Err ( e) => tracing:: error!( "{:?}" , e) ,
143
- }
144
- }
145
- } )
146
- . unwrap ( ) ;
126
+ match graphics_state. render ( ) {
127
+ Ok ( _) => { }
128
+ Err ( wgpu:: SurfaceError :: Lost ) => {
129
+ tracing:: warn!( "lost surface" ) ;
130
+ }
131
+ Err ( wgpu:: SurfaceError :: OutOfMemory ) => {
132
+ event_loop. exit ( ) ;
133
+ }
134
+ Err ( e) => tracing:: error!( "{:?}" , e) ,
135
+ }
147
136
}
148
137
_ => { }
149
138
}
139
+
140
+ // Notify cef of possible input events
141
+ self . cef_context . work ( ) ;
150
142
}
151
143
}
0 commit comments