11use crate :: CustomEvent ;
2- use crate :: WindowState ;
3- use crate :: WindowStateHandle ;
2+ use crate :: FrameBuffer ;
3+ use crate :: WindowSize ;
44use crate :: render:: GraphicsState ;
55use std:: sync:: Arc ;
6+ use std:: sync:: mpsc:: Sender ;
67use std:: time:: Duration ;
78use std:: time:: Instant ;
89use winit:: application:: ApplicationHandler ;
10+ use winit:: dpi:: PhysicalSize ;
911use winit:: event:: StartCause ;
1012use winit:: event:: WindowEvent ;
1113use winit:: event_loop:: ActiveEventLoop ;
1214use winit:: event_loop:: ControlFlow ;
15+ use winit:: event_loop:: EventLoopProxy ;
1316use winit:: window:: Window ;
1417use winit:: window:: WindowId ;
1518
1619use crate :: cef;
1720
1821pub ( crate ) struct WinitApp {
19- pub ( crate ) window_state : WindowStateHandle ,
2022 pub ( crate ) cef_context : cef:: Context < cef:: Initialized > ,
2123 pub ( crate ) window : Option < Arc < Window > > ,
2224 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 > ,
2330}
2431
2532impl 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 {
2734 Self {
28- window_state,
2935 cef_context,
3036 window : None ,
3137 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,
3243 }
3344 }
3445}
3546
3647impl ApplicationHandler < CustomEvent > for WinitApp {
3748 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 ) ;
3951 let wait_until = timeout. min ( self . cef_schedule . unwrap_or ( timeout) ) ;
4052 event_loop. set_control_flow ( ControlFlow :: WaitUntil ( wait_until) ) ;
4153 }
@@ -50,37 +62,42 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
5062 }
5163
5264 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 ( ) ) ) ;
6675
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) ;
6978
70- tracing:: info!( "Winit window created and ready" ) ;
71- }
72- } )
73- . unwrap ( ) ;
79+ tracing:: info!( "Winit window created and ready" ) ;
7480 }
7581
7682 fn user_event ( & mut self , _: & ActiveEventLoop , event : CustomEvent ) {
7783 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) ;
7989 if let Some ( window) = & self . window {
8090 window. request_redraw ( ) ;
8191 }
8292 }
8393 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+ }
84101 self . cef_schedule = Some ( instant) ;
85102 }
86103 }
@@ -94,58 +111,33 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
94111 tracing:: info!( "The close button was pressed; stopping" ) ;
95112 event_loop. exit ( ) ;
96113 }
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+ }
109119 self . cef_context . notify_of_resize ( ) ;
110120 }
111121
112122 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
114125
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+ }
147136 }
148137 _ => { }
149138 }
139+
140+ // Notify cef of possible input events
141+ self . cef_context . work ( ) ;
150142 }
151143}
0 commit comments