16
16
use crate :: CustomEvent ;
17
17
use crate :: render:: FrameBufferRef ;
18
18
use graphite_desktop_wrapper:: { WgpuContext , deserialize_editor_message} ;
19
+ use std:: fs:: File ;
20
+ use std:: io:: { Cursor , Read } ;
21
+ use std:: path:: PathBuf ;
19
22
use std:: sync:: mpsc:: Receiver ;
20
23
use std:: sync:: { Arc , Mutex } ;
21
24
use std:: time:: Instant ;
@@ -27,7 +30,6 @@ mod input;
27
30
mod internal;
28
31
mod ipc;
29
32
mod platform;
30
- mod scheme_handler;
31
33
mod utility;
32
34
33
35
#[ cfg( feature = "accelerated_paint" ) ]
@@ -38,11 +40,12 @@ use texture_import::SharedTextureHandle;
38
40
pub ( crate ) use context:: { CefContext , CefContextBuilder , InitError } ;
39
41
use winit:: event_loop:: EventLoopProxy ;
40
42
41
- pub ( crate ) trait CefEventHandler : Clone {
43
+ pub ( crate ) trait CefEventHandler : Clone + Send + Sync + ' static {
42
44
fn window_size ( & self ) -> WindowSize ;
43
45
fn draw < ' a > ( & self , frame_buffer : FrameBufferRef < ' a > ) ;
44
46
#[ cfg( feature = "accelerated_paint" ) ]
45
47
fn draw_gpu ( & self , shared_texture : SharedTextureHandle ) ;
48
+ fn load_resource ( & self , path : PathBuf ) -> Option < Resource > ;
46
49
/// Scheudule the main event loop to run the cef event loop after the timeout
47
50
/// [`_cef_browser_process_handler_t::on_schedule_message_pump_work`] for more documentation.
48
51
fn schedule_cef_message_loop_work ( & self , scheduled_time : Instant ) ;
@@ -62,12 +65,34 @@ impl WindowSize {
62
65
}
63
66
}
64
67
68
+ #[ derive( Clone ) ]
69
+ pub ( crate ) struct Resource {
70
+ pub ( crate ) reader : ResourceReader ,
71
+ pub ( crate ) mimetype : Option < String > ,
72
+ }
73
+
74
+ #[ expect( dead_code) ]
75
+ #[ derive( Clone ) ]
76
+ pub ( crate ) enum ResourceReader {
77
+ Embedded ( Cursor < & ' static [ u8 ] > ) ,
78
+ File ( Arc < File > ) ,
79
+ }
80
+ impl Read for ResourceReader {
81
+ fn read ( & mut self , buf : & mut [ u8 ] ) -> std:: io:: Result < usize > {
82
+ match self {
83
+ ResourceReader :: Embedded ( cursor) => cursor. read ( buf) ,
84
+ ResourceReader :: File ( file) => file. as_ref ( ) . read ( buf) ,
85
+ }
86
+ }
87
+ }
88
+
65
89
#[ derive( Clone ) ]
66
90
pub ( crate ) struct CefHandler {
67
91
window_size_receiver : Arc < Mutex < WindowSizeReceiver > > ,
68
92
event_loop_proxy : EventLoopProxy < CustomEvent > ,
69
93
wgpu_context : WgpuContext ,
70
94
}
95
+
71
96
struct WindowSizeReceiver {
72
97
receiver : Receiver < WindowSize > ,
73
98
window_size : WindowSize ,
@@ -142,6 +167,73 @@ impl CefEventHandler for CefHandler {
142
167
let _ = self . event_loop_proxy . send_event ( CustomEvent :: UiUpdate ( texture) ) ;
143
168
}
144
169
170
+ #[ cfg( feature = "accelerated_paint" ) ]
171
+ fn draw_gpu ( & self , shared_texture : SharedTextureHandle ) {
172
+ match shared_texture. import_texture ( & self . wgpu_context . device ) {
173
+ Ok ( texture) => {
174
+ let _ = self . event_loop_proxy . send_event ( CustomEvent :: UiUpdate ( texture) ) ;
175
+ }
176
+ Err ( e) => {
177
+ tracing:: error!( "Failed to import shared texture: {}" , e) ;
178
+ }
179
+ }
180
+ }
181
+
182
+ fn load_resource ( & self , path : PathBuf ) -> Option < Resource > {
183
+ let path = if path. as_os_str ( ) . is_empty ( ) { PathBuf :: from ( "index.html" ) } else { path } ;
184
+
185
+ let mimetype = match path. extension ( ) . and_then ( |s| s. to_str ( ) ) . unwrap_or ( "" ) {
186
+ "html" => Some ( "text/html" . to_string ( ) ) ,
187
+ "css" => Some ( "text/css" . to_string ( ) ) ,
188
+ "txt" => Some ( "text/plain" . to_string ( ) ) ,
189
+ "wasm" => Some ( "application/wasm" . to_string ( ) ) ,
190
+ "js" => Some ( "application/javascript" . to_string ( ) ) ,
191
+ "png" => Some ( "image/png" . to_string ( ) ) ,
192
+ "jpg" | "jpeg" => Some ( "image/jpeg" . to_string ( ) ) ,
193
+ "svg" => Some ( "image/svg+xml" . to_string ( ) ) ,
194
+ "xml" => Some ( "application/xml" . to_string ( ) ) ,
195
+ "json" => Some ( "application/json" . to_string ( ) ) ,
196
+ "ico" => Some ( "image/x-icon" . to_string ( ) ) ,
197
+ "woff" => Some ( "font/woff" . to_string ( ) ) ,
198
+ "woff2" => Some ( "font/woff2" . to_string ( ) ) ,
199
+ "ttf" => Some ( "font/ttf" . to_string ( ) ) ,
200
+ "otf" => Some ( "font/otf" . to_string ( ) ) ,
201
+ "webmanifest" => Some ( "application/manifest+json" . to_string ( ) ) ,
202
+ "graphite" => Some ( "application/graphite+json" . to_string ( ) ) ,
203
+ _ => None ,
204
+ } ;
205
+
206
+ #[ cfg( feature = "embedded_resources" ) ]
207
+ {
208
+ if let Some ( resources) = & graphite_desktop_embedded_resources:: EMBEDDED_RESOURCES
209
+ && let Some ( file) = resources. get_file ( & path)
210
+ {
211
+ return Some ( Resource {
212
+ reader : ResourceReader :: Embedded ( Cursor :: new ( file. contents ( ) ) ) ,
213
+ mimetype,
214
+ } ) ;
215
+ }
216
+ }
217
+
218
+ #[ cfg( not( feature = "embedded_resources" ) ) ]
219
+ {
220
+ use std:: path:: Path ;
221
+ let asset_path_env = std:: env:: var ( "GRAPHITE_RESOURCES" ) . ok ( ) ?;
222
+ let asset_path = Path :: new ( & asset_path_env) ;
223
+ let file_path = asset_path. join ( path. strip_prefix ( "/" ) . unwrap_or ( & path) ) ;
224
+ if file_path. exists ( ) && file_path. is_file ( ) {
225
+ if let Ok ( file) = std:: fs:: File :: open ( file_path) {
226
+ return Some ( Resource {
227
+ reader : ResourceReader :: File ( file. into ( ) ) ,
228
+ mimetype,
229
+ } ) ;
230
+ }
231
+ }
232
+ }
233
+
234
+ None
235
+ }
236
+
145
237
fn schedule_cef_message_loop_work ( & self , scheduled_time : std:: time:: Instant ) {
146
238
let _ = self . event_loop_proxy . send_event ( CustomEvent :: ScheduleBrowserWork ( scheduled_time) ) ;
147
239
}
@@ -157,16 +249,4 @@ impl CefEventHandler for CefHandler {
157
249
} ;
158
250
let _ = self . event_loop_proxy . send_event ( CustomEvent :: DesktopWrapperMessage ( desktop_wrapper_message) ) ;
159
251
}
160
-
161
- #[ cfg( feature = "accelerated_paint" ) ]
162
- fn draw_gpu ( & self , shared_texture : SharedTextureHandle ) {
163
- match shared_texture. import_texture ( & self . wgpu_context . device ) {
164
- Ok ( texture) => {
165
- let _ = self . event_loop_proxy . send_event ( CustomEvent :: UiUpdate ( texture) ) ;
166
- }
167
- Err ( e) => {
168
- tracing:: error!( "Failed to import shared texture: {}" , e) ;
169
- }
170
- }
171
- }
172
252
}
0 commit comments