diff --git a/desktop/src/app.rs b/desktop/src/app.rs index 3aec9d2e3d..d0557cd143 100644 --- a/desktop/src/app.rs +++ b/desktop/src/app.rs @@ -8,6 +8,7 @@ use std::thread; use std::time::Duration; use std::time::Instant; use winit::application::ApplicationHandler; +use winit::dpi::PhysicalSize; use winit::event::WindowEvent; use winit::event_loop::ActiveEventLoop; use winit::event_loop::ControlFlow; @@ -25,8 +26,9 @@ use crate::wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, seri pub(crate) struct App { cef_context: Box, window: Option, + window_scale: f64, cef_schedule: Option, - cef_window_size_sender: Sender, + cef_view_info_sender: Sender, graphics_state: Option, wgpu_context: WgpuContext, app_event_receiver: Receiver, @@ -44,7 +46,7 @@ pub(crate) struct App { impl App { pub(crate) fn new( cef_context: Box, - window_size_sender: Sender, + cef_view_info_sender: Sender, wgpu_context: WgpuContext, app_event_receiver: Receiver, app_event_scheduler: AppEventScheduler, @@ -66,9 +68,10 @@ impl App { Self { cef_context, window: None, + window_scale: 1.0, cef_schedule: Some(Instant::now()), graphics_state: None, - cef_window_size_sender: window_size_sender, + cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, @@ -147,19 +150,19 @@ impl App { } }); } - DesktopFrontendMessage::UpdateViewportBounds { x, y, width, height } => { + DesktopFrontendMessage::UpdateViewportPhysicalBounds { x, y, width, height } => { if let Some(graphics_state) = &mut self.graphics_state && let Some(window) = &self.window { let window_size = window.surface_size(); - let viewport_offset_x = x / window_size.width as f32; - let viewport_offset_y = y / window_size.height as f32; - graphics_state.set_viewport_offset([viewport_offset_x, viewport_offset_y]); + let viewport_offset_x = x / window_size.width as f64; + let viewport_offset_y = y / window_size.height as f64; + graphics_state.set_viewport_offset([viewport_offset_x as f32, viewport_offset_y as f32]); - let viewport_scale_x = if width != 0.0 { window_size.width as f32 / width } else { 1.0 }; - let viewport_scale_y = if height != 0.0 { window_size.height as f32 / height } else { 1.0 }; - graphics_state.set_viewport_scale([viewport_scale_x, viewport_scale_y]); + let viewport_scale_x = if width != 0.0 { window_size.width as f64 / width } else { 1.0 }; + let viewport_scale_y = if height != 0.0 { window_size.height as f64 / height } else { 1.0 }; + graphics_state.set_viewport_scale([viewport_scale_x as f32, viewport_scale_y as f32]); } } DesktopFrontendMessage::UpdateOverlays(scene) => { @@ -179,7 +182,7 @@ impl App { } DesktopFrontendMessage::DragWindow => { if let Some(window) = &self.window { - let _ = window.start_drag(); + window.start_drag(); } } DesktopFrontendMessage::CloseWindow => { @@ -352,14 +355,17 @@ impl App { impl ApplicationHandler for App { fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { let window = Window::new(event_loop, self.app_event_scheduler.clone()); + + self.window_scale = window.scale_factor(); + let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(self.window_scale)); + self.cef_context.notify_view_info_changed(); + self.window = Some(window); let graphics_state = GraphicsState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone()); self.graphics_state = Some(graphics_state); - tracing::info!("Winit window created and ready"); - self.desktop_wrapper.init(self.wgpu_context.clone()); #[cfg(target_os = "windows")] @@ -384,14 +390,22 @@ impl ApplicationHandler for App { WindowEvent::CloseRequested => { self.app_event_scheduler.schedule(AppEvent::CloseWindow); } - WindowEvent::SurfaceResized(size) => { - let _ = self.cef_window_size_sender.send(size.into()); - self.cef_context.notify_of_resize(); + WindowEvent::SurfaceResized(PhysicalSize { width, height }) => { + let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size { + width: width as usize, + height: height as usize, + }); + self.cef_context.notify_view_info_changed(); if let Some(window) = &self.window { let maximized = window.is_maximized(); self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateMaximized { maximized })); } } + WindowEvent::ScaleFactorChanged { scale_factor, .. } => { + self.window_scale = scale_factor; + let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(self.window_scale)); + self.cef_context.notify_view_info_changed(); + } WindowEvent::RedrawRequested => { let Some(ref mut graphics_state) = self.graphics_state else { return }; // Only rerender once we have a new UI texture to display diff --git a/desktop/src/cef.rs b/desktop/src/cef.rs index 666379893b..135c036173 100644 --- a/desktop/src/cef.rs +++ b/desktop/src/cef.rs @@ -38,8 +38,8 @@ use texture_import::SharedTextureHandle; pub(crate) use context::{CefContext, CefContextBuilder, InitError}; -pub(crate) trait CefEventHandler: Clone + Send + Sync + 'static { - fn window_size(&self) -> WindowSize; +pub(crate) trait CefEventHandler: Send + Sync + 'static { + fn view_info(&self) -> ViewInfo; fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>); #[cfg(feature = "accelerated_paint")] fn draw_gpu(&self, shared_texture: SharedTextureHandle); @@ -50,24 +50,54 @@ pub(crate) trait CefEventHandler: Clone + Send + Sync + 'static { fn schedule_cef_message_loop_work(&self, scheduled_time: Instant); fn initialized_web_communication(&self); fn receive_web_message(&self, message: &[u8]); + fn duplicate(&self) -> Self + where + Self: Sized; } #[derive(Clone, Copy)] -pub(crate) struct WindowSize { - pub(crate) width: usize, - pub(crate) height: usize, +pub(crate) struct ViewInfo { + width: usize, + height: usize, + scale: f64, } -impl WindowSize { - pub(crate) fn new(width: usize, height: usize) -> Self { - Self { width, height } +impl ViewInfo { + pub(crate) fn new() -> Self { + Self { width: 1, height: 1, scale: 1. } + } + pub(crate) fn apply_update(&mut self, update: ViewInfoUpdate) { + match update { + ViewInfoUpdate::Size { width, height } if width > 0 && height > 0 => { + self.width = width; + self.height = height; + } + ViewInfoUpdate::Scale(scale) if scale > 0. => { + self.scale = scale; + } + _ => {} + } + } + pub(crate) fn zoom(&self) -> f64 { + self.scale.ln() / 1.2_f64.ln() + } + pub(crate) fn width(&self) -> usize { + self.width + } + pub(crate) fn height(&self) -> usize { + self.height } } -impl From> for WindowSize { - fn from(size: winit::dpi::PhysicalSize) -> Self { - Self::new(size.width as usize, size.height as usize) +impl Default for ViewInfo { + fn default() -> Self { + Self::new() } } +pub(crate) enum ViewInfoUpdate { + Size { width: usize, height: usize }, + Scale(f64), +} + #[derive(Clone)] pub(crate) struct Resource { pub(crate) reader: ResourceReader, @@ -89,34 +119,33 @@ impl Read for ResourceReader { } } -#[derive(Clone)] pub(crate) struct CefHandler { wgpu_context: WgpuContext, app_event_scheduler: AppEventScheduler, - window_size_receiver: Arc>, + view_info_receiver: Arc>, } impl CefHandler { - pub(crate) fn new(wgpu_context: WgpuContext, app_event_scheduler: AppEventScheduler, window_size_receiver: Receiver) -> Self { + pub(crate) fn new(wgpu_context: WgpuContext, app_event_scheduler: AppEventScheduler, view_info_receiver: Receiver) -> Self { Self { wgpu_context, app_event_scheduler, - window_size_receiver: Arc::new(Mutex::new(WindowSizeReceiver::new(window_size_receiver))), + view_info_receiver: Arc::new(Mutex::new(ViewInfoReceiver::new(view_info_receiver))), } } } impl CefEventHandler for CefHandler { - fn window_size(&self) -> WindowSize { - let Ok(mut guard) = self.window_size_receiver.lock() else { - tracing::error!("Failed to lock window_size_receiver"); - return WindowSize::new(1, 1); + fn view_info(&self) -> ViewInfo { + let Ok(mut guard) = self.view_info_receiver.lock() else { + tracing::error!("Failed to lock view_info_receiver"); + return ViewInfo::new(); }; - let WindowSizeReceiver { receiver, window_size } = &mut *guard; - for new_window_size in receiver.try_iter() { - *window_size = new_window_size; + let ViewInfoReceiver { receiver, view_info } = &mut *guard; + for update in receiver.try_iter() { + view_info.apply_update(update); } - *window_size + *view_info } fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>) { let width = frame_buffer.width() as u32; @@ -244,17 +273,25 @@ impl CefEventHandler for CefHandler { }; self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(desktop_wrapper_message)); } -} -struct WindowSizeReceiver { - window_size: WindowSize, - receiver: Receiver, -} -impl WindowSizeReceiver { - fn new(window_size_receiver: Receiver) -> Self { + fn duplicate(&self) -> Self + where + Self: Sized, + { Self { - window_size: WindowSize { width: 1, height: 1 }, - receiver: window_size_receiver, + wgpu_context: self.wgpu_context.clone(), + app_event_scheduler: self.app_event_scheduler.clone(), + view_info_receiver: self.view_info_receiver.clone(), } } } + +struct ViewInfoReceiver { + view_info: ViewInfo, + receiver: Receiver, +} +impl ViewInfoReceiver { + fn new(receiver: Receiver) -> Self { + Self { view_info: ViewInfo::new(), receiver } + } +} diff --git a/desktop/src/cef/context.rs b/desktop/src/cef/context.rs index 1f6279c388..53eac0aeef 100644 --- a/desktop/src/cef/context.rs +++ b/desktop/src/cef/context.rs @@ -10,7 +10,7 @@ pub(crate) trait CefContext { fn handle_window_event(&mut self, event: &winit::event::WindowEvent); - fn notify_of_resize(&self); + fn notify_view_info_changed(&self); fn send_web_message(&self, message: Vec); } diff --git a/desktop/src/cef/context/builder.rs b/desktop/src/cef/context/builder.rs index cd586089d3..8932c5212c 100644 --- a/desktop/src/cef/context/builder.rs +++ b/desktop/src/cef/context/builder.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use cef::args::Args; use cef::sys::{CEF_API_VERSION_LAST, cef_resultcode_t}; use cef::{ - App, BrowserSettings, CefString, Client, DictionaryValue, ImplCommandLine, ImplRequestContext, RenderHandler, RequestContextSettings, SchemeHandlerFactory, Settings, WindowInfo, api_hash, + App, BrowserSettings, CefString, Client, DictionaryValue, ImplCommandLine, ImplRequestContext, RequestContextSettings, SchemeHandlerFactory, Settings, WindowInfo, api_hash, browser_host_create_browser_sync, execute_process, }; @@ -13,7 +13,7 @@ use crate::cef::CefEventHandler; use crate::cef::consts::{RESOURCE_DOMAIN, RESOURCE_SCHEME}; use crate::cef::dirs::create_instance_dir; use crate::cef::input::InputState; -use crate::cef::internal::{BrowserProcessAppImpl, BrowserProcessClientImpl, RenderHandlerImpl, RenderProcessAppImpl, SchemeHandlerFactoryImpl}; +use crate::cef::internal::{BrowserProcessAppImpl, BrowserProcessClientImpl, RenderProcessAppImpl, SchemeHandlerFactoryImpl}; pub(crate) struct CefContextBuilder { pub(crate) args: Args, @@ -131,7 +131,7 @@ impl CefContextBuilder { fn initialize_inner(self, event_handler: &H, settings: Settings) -> Result<(), InitError> { // Attention! Wrapping this in an extra App is necessary, otherwise the program still compiles but segfaults - let mut cef_app = App::new(BrowserProcessAppImpl::new(event_handler.clone())); + let mut cef_app = App::new(BrowserProcessAppImpl::new(event_handler.duplicate())); let result = cef::initialize(Some(self.args.as_main_args()), Some(&settings), Some(&mut cef_app), std::ptr::null_mut()); if result != 1 { @@ -146,8 +146,7 @@ impl CefContextBuilder { } fn create_browser(event_handler: H, instance_dir: PathBuf, disable_gpu_acceleration: bool) -> Result { - let render_handler = RenderHandler::new(RenderHandlerImpl::new(event_handler.clone())); - let mut client = Client::new(BrowserProcessClientImpl::new(render_handler, event_handler.clone())); + let mut client = Client::new(BrowserProcessClientImpl::new(&event_handler)); #[cfg(feature = "accelerated_paint")] let use_accelerated_paint = if disable_gpu_acceleration { @@ -180,7 +179,7 @@ fn create_browser(event_handler: H, instance_dir: PathBuf, d return Err(InitError::RequestContextCreationFailed); }; - let mut scheme_handler_factory = SchemeHandlerFactory::new(SchemeHandlerFactoryImpl::new(event_handler.clone())); + let mut scheme_handler_factory = SchemeHandlerFactory::new(SchemeHandlerFactoryImpl::new(event_handler.duplicate())); incognito_request_context.clear_scheme_handler_factories(); incognito_request_context.register_scheme_handler_factory(Some(&CefString::from(RESOURCE_SCHEME)), Some(&CefString::from(RESOURCE_DOMAIN)), Some(&mut scheme_handler_factory)); @@ -197,6 +196,7 @@ fn create_browser(event_handler: H, instance_dir: PathBuf, d if let Some(browser) = browser { Ok(SingleThreadedCefContext { + event_handler: Box::new(event_handler), browser, input_state: InputState::default(), instance_dir, diff --git a/desktop/src/cef/context/multithreaded.rs b/desktop/src/cef/context/multithreaded.rs index 9434a99d86..90c8001fd7 100644 --- a/desktop/src/cef/context/multithreaded.rs +++ b/desktop/src/cef/context/multithreaded.rs @@ -30,11 +30,11 @@ impl CefContext for MultiThreadedCefContextProxy { }); } - fn notify_of_resize(&self) { + fn notify_view_info_changed(&self) { run_on_ui_thread(move || { CONTEXT.with(|b| { if let Some(context) = b.borrow_mut().as_mut() { - context.notify_of_resize(); + context.notify_view_info_changed(); } }); }); diff --git a/desktop/src/cef/context/singlethreaded.rs b/desktop/src/cef/context/singlethreaded.rs index 2825b78418..d59a2c638b 100644 --- a/desktop/src/cef/context/singlethreaded.rs +++ b/desktop/src/cef/context/singlethreaded.rs @@ -1,13 +1,14 @@ use cef::{Browser, ImplBrowser, ImplBrowserHost}; use winit::event::WindowEvent; -use crate::cef::input; use crate::cef::input::InputState; use crate::cef::ipc::{MessageType, SendMessage}; +use crate::cef::{CefEventHandler, input}; use super::CefContext; pub(super) struct SingleThreadedCefContext { + pub(super) event_handler: Box, pub(super) browser: Browser, pub(super) input_state: InputState, pub(super) instance_dir: std::path::PathBuf, @@ -19,11 +20,14 @@ impl CefContext for SingleThreadedCefContext { } fn handle_window_event(&mut self, event: &WindowEvent) { - input::handle_window_event(&self.browser, &mut self.input_state, event) + input::handle_window_event(&self.browser, &mut self.input_state, event); } - fn notify_of_resize(&self) { - self.browser.host().unwrap().was_resized(); + fn notify_view_info_changed(&self) { + let view_info = self.event_handler.view_info(); + let host = self.browser.host().unwrap(); + host.set_zoom_level(view_info.zoom()); + host.was_resized(); } fn send_web_message(&self, message: Vec) { diff --git a/desktop/src/cef/input.rs b/desktop/src/cef/input.rs index feb9eff563..d2a99d3baa 100644 --- a/desktop/src/cef/input.rs +++ b/desktop/src/cef/input.rs @@ -12,14 +12,14 @@ use super::consts::{MULTICLICK_ALLOWED_TRAVEL, MULTICLICK_TIMEOUT, PINCH_ZOOM_SP pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputState, event: &WindowEvent) { match event { WindowEvent::PointerMoved { position, .. } | WindowEvent::PointerEntered { position, .. } => { - input_state.cursor_move(position); + input_state.cursor_move(&position); let Some(host) = browser.host() else { return }; host.send_mouse_move_event(Some(&input_state.into()), 0); } WindowEvent::PointerLeft { position, .. } => { if let Some(position) = position { - input_state.cursor_move(position); + input_state.cursor_move(&position); } let Some(host) = browser.host() else { return }; diff --git a/desktop/src/cef/internal.rs b/desktop/src/cef/internal.rs index 1a9c8645a3..e07a28d2b3 100644 --- a/desktop/src/cef/internal.rs +++ b/desktop/src/cef/internal.rs @@ -2,6 +2,7 @@ mod browser_process_app; mod browser_process_client; mod browser_process_handler; mod browser_process_life_span_handler; +mod browser_process_load_handler; mod render_process_app; mod render_process_handler; @@ -19,6 +20,5 @@ pub(super) mod task; pub(super) use browser_process_app::BrowserProcessAppImpl; pub(super) use browser_process_client::BrowserProcessClientImpl; -pub(super) use render_handler::RenderHandlerImpl; pub(super) use render_process_app::RenderProcessAppImpl; pub(super) use scheme_handler_factory::SchemeHandlerFactoryImpl; diff --git a/desktop/src/cef/internal/browser_process_app.rs b/desktop/src/cef/internal/browser_process_app.rs index 2ecae79100..75fa5a812e 100644 --- a/desktop/src/cef/internal/browser_process_app.rs +++ b/desktop/src/cef/internal/browser_process_app.rs @@ -13,7 +13,7 @@ pub(crate) struct BrowserProcessAppImpl { object: *mut RcImpl<_cef_app_t, Self>, event_handler: H, } -impl BrowserProcessAppImpl { +impl BrowserProcessAppImpl { pub(crate) fn new(event_handler: H) -> Self { Self { object: std::ptr::null_mut(), @@ -22,9 +22,9 @@ impl BrowserProcessAppImpl { } } -impl ImplApp for BrowserProcessAppImpl { +impl ImplApp for BrowserProcessAppImpl { fn browser_process_handler(&self) -> Option { - Some(BrowserProcessHandler::new(BrowserProcessHandlerImpl::new(self.event_handler.clone()))) + Some(BrowserProcessHandler::new(BrowserProcessHandlerImpl::new(self.event_handler.duplicate()))) } fn on_register_custom_schemes(&self, registrar: Option<&mut SchemeRegistrar>) { @@ -80,7 +80,7 @@ impl ImplApp for BrowserProcessAppImpl { } } -impl Clone for BrowserProcessAppImpl { +impl Clone for BrowserProcessAppImpl { fn clone(&self) -> Self { unsafe { let rc_impl = &mut *self.object; @@ -88,7 +88,7 @@ impl Clone for BrowserProcessAppImpl { } Self { object: self.object, - event_handler: self.event_handler.clone(), + event_handler: self.event_handler.duplicate(), } } } @@ -100,7 +100,7 @@ impl Rc for BrowserProcessAppImpl { } } } -impl WrapApp for BrowserProcessAppImpl { +impl WrapApp for BrowserProcessAppImpl { fn wrap_rc(&mut self, object: *mut RcImpl<_cef_app_t, Self>) { self.object = object; } diff --git a/desktop/src/cef/internal/browser_process_client.rs b/desktop/src/cef/internal/browser_process_client.rs index 3fcd7aad63..549373f5f4 100644 --- a/desktop/src/cef/internal/browser_process_client.rs +++ b/desktop/src/cef/internal/browser_process_client.rs @@ -1,26 +1,30 @@ use cef::rc::{Rc, RcImpl}; use cef::sys::{_cef_client_t, cef_base_ref_counted_t}; -use cef::{DisplayHandler, ImplClient, LifeSpanHandler, RenderHandler, WrapClient}; +use cef::{DisplayHandler, ImplClient, LifeSpanHandler, LoadHandler, RenderHandler, WrapClient}; use crate::cef::CefEventHandler; use crate::cef::ipc::{MessageType, UnpackMessage, UnpackedMessage}; use super::browser_process_life_span_handler::BrowserProcessLifeSpanHandlerImpl; +use super::browser_process_load_handler::LoadHandlerImpl; use super::display_handler::DisplayHandlerImpl; +use super::render_handler::RenderHandlerImpl; pub(crate) struct BrowserProcessClientImpl { object: *mut RcImpl<_cef_client_t, Self>, - render_handler: RenderHandler, event_handler: H, + load_handler: LoadHandler, + render_handler: RenderHandler, display_handler: DisplayHandler, } impl BrowserProcessClientImpl { - pub(crate) fn new(render_handler: RenderHandler, event_handler: H) -> Self { + pub(crate) fn new(event_handler: &H) -> Self { Self { object: std::ptr::null_mut(), - render_handler, - event_handler: event_handler.clone(), - display_handler: DisplayHandler::new(DisplayHandlerImpl::new(event_handler)), + event_handler: event_handler.duplicate(), + load_handler: LoadHandler::new(LoadHandlerImpl::new(event_handler.duplicate())), + render_handler: RenderHandler::new(RenderHandlerImpl::new(event_handler.duplicate())), + display_handler: DisplayHandler::new(DisplayHandlerImpl::new(event_handler.duplicate())), } } } @@ -52,6 +56,10 @@ impl ImplClient for BrowserProcessClientImpl { 1 } + fn load_handler(&self) -> Option { + Some(self.load_handler.clone()) + } + fn render_handler(&self) -> Option { Some(self.render_handler.clone()) } @@ -77,8 +85,9 @@ impl Clone for BrowserProcessClientImpl { } Self { object: self.object, + event_handler: self.event_handler.duplicate(), + load_handler: self.load_handler.clone(), render_handler: self.render_handler.clone(), - event_handler: self.event_handler.clone(), display_handler: self.display_handler.clone(), } } diff --git a/desktop/src/cef/internal/browser_process_handler.rs b/desktop/src/cef/internal/browser_process_handler.rs index 74604b16b1..71c0e9956e 100644 --- a/desktop/src/cef/internal/browser_process_handler.rs +++ b/desktop/src/cef/internal/browser_process_handler.rs @@ -19,7 +19,7 @@ impl BrowserProcessHandlerImpl { } } -impl ImplBrowserProcessHandler for BrowserProcessHandlerImpl { +impl ImplBrowserProcessHandler for BrowserProcessHandlerImpl { fn on_schedule_message_pump_work(&self, delay_ms: i64) { self.event_handler.schedule_cef_message_loop_work(Instant::now() + Duration::from_millis(delay_ms as u64)); } @@ -33,7 +33,7 @@ impl ImplBrowserProcessHandler for BrowserProcessHan } } -impl Clone for BrowserProcessHandlerImpl { +impl Clone for BrowserProcessHandlerImpl { fn clone(&self) -> Self { unsafe { let rc_impl = &mut *self.object; @@ -41,7 +41,7 @@ impl Clone for BrowserProcessHandlerImpl { } Self { object: self.object, - event_handler: self.event_handler.clone(), + event_handler: self.event_handler.duplicate(), } } } @@ -53,7 +53,7 @@ impl Rc for BrowserProcessHandlerImpl { } } } -impl WrapBrowserProcessHandler for BrowserProcessHandlerImpl { +impl WrapBrowserProcessHandler for BrowserProcessHandlerImpl { fn wrap_rc(&mut self, object: *mut RcImpl<_cef_browser_process_handler_t, Self>) { self.object = object; } diff --git a/desktop/src/cef/internal/browser_process_load_handler.rs b/desktop/src/cef/internal/browser_process_load_handler.rs new file mode 100644 index 0000000000..92973a32bd --- /dev/null +++ b/desktop/src/cef/internal/browser_process_load_handler.rs @@ -0,0 +1,60 @@ +use cef::rc::{Rc, RcImpl}; +use cef::sys::{_cef_load_handler_t, cef_base_ref_counted_t, cef_load_handler_t}; +use cef::{ImplBrowser, ImplBrowserHost, ImplLoadHandler, WrapLoadHandler}; + +use crate::cef::CefEventHandler; + +pub(crate) struct LoadHandlerImpl { + object: *mut RcImpl, + event_handler: H, +} +impl LoadHandlerImpl { + pub(crate) fn new(event_handler: H) -> Self { + Self { + object: std::ptr::null_mut(), + event_handler, + } + } +} + +impl ImplLoadHandler for LoadHandlerImpl { + fn on_loading_state_change(&self, browser: Option<&mut cef::Browser>, is_loading: ::std::os::raw::c_int, _can_go_back: ::std::os::raw::c_int, _can_go_forward: ::std::os::raw::c_int) { + let view_info = self.event_handler.view_info(); + + if let Some(browser) = browser + && is_loading == 0 + { + browser.host().unwrap().set_zoom_level(view_info.zoom()); + } + } + + fn get_raw(&self) -> *mut _cef_load_handler_t { + self.object.cast() + } +} + +impl Clone for LoadHandlerImpl { + fn clone(&self) -> Self { + unsafe { + let rc_impl = &mut *self.object; + rc_impl.interface.add_ref(); + } + Self { + object: self.object, + event_handler: self.event_handler.duplicate(), + } + } +} +impl Rc for LoadHandlerImpl { + fn as_base(&self) -> &cef_base_ref_counted_t { + unsafe { + let base = &*self.object; + std::mem::transmute(&base.cef_object) + } + } +} +impl WrapLoadHandler for LoadHandlerImpl { + fn wrap_rc(&mut self, object: *mut RcImpl<_cef_load_handler_t, Self>) { + self.object = object; + } +} diff --git a/desktop/src/cef/internal/display_handler.rs b/desktop/src/cef/internal/display_handler.rs index de56609bd2..a42d9815f7 100644 --- a/desktop/src/cef/internal/display_handler.rs +++ b/desktop/src/cef/internal/display_handler.rs @@ -122,7 +122,7 @@ impl Clone for DisplayHandlerImpl { } Self { object: self.object, - event_handler: self.event_handler.clone(), + event_handler: self.event_handler.duplicate(), } } } diff --git a/desktop/src/cef/internal/render_handler.rs b/desktop/src/cef/internal/render_handler.rs index dd725a01b9..a424e4ffe5 100644 --- a/desktop/src/cef/internal/render_handler.rs +++ b/desktop/src/cef/internal/render_handler.rs @@ -21,12 +21,12 @@ impl RenderHandlerImpl { impl ImplRenderHandler for RenderHandlerImpl { fn view_rect(&self, _browser: Option<&mut Browser>, rect: Option<&mut Rect>) { if let Some(rect) = rect { - let view = self.event_handler.window_size(); + let view_info = self.event_handler.view_info(); *rect = Rect { x: 0, y: 0, - width: view.width as i32, - height: view.height as i32, + width: view_info.width() as i32, + height: view_info.height() as i32, }; } } @@ -78,7 +78,7 @@ impl Clone for RenderHandlerImpl { } Self { object: self.object, - event_handler: self.event_handler.clone(), + event_handler: self.event_handler.duplicate(), } } } diff --git a/desktop/src/cef/internal/scheme_handler_factory.rs b/desktop/src/cef/internal/scheme_handler_factory.rs index 44f51fe1ab..2c597df5ef 100644 --- a/desktop/src/cef/internal/scheme_handler_factory.rs +++ b/desktop/src/cef/internal/scheme_handler_factory.rs @@ -55,7 +55,7 @@ impl Clone for SchemeHandlerFactoryImpl { } Self { object: self.object, - event_handler: self.event_handler.clone(), + event_handler: self.event_handler.duplicate(), } } } diff --git a/desktop/src/lib.rs b/desktop/src/lib.rs index 34332555bd..fdf504d04d 100644 --- a/desktop/src/lib.rs +++ b/desktop/src/lib.rs @@ -44,9 +44,9 @@ pub fn start() { let (app_event_sender, app_event_receiver) = std::sync::mpsc::channel(); let app_event_scheduler = event_loop.create_app_event_scheduler(app_event_sender); - let (window_size_sender, window_size_receiver) = std::sync::mpsc::channel(); + let (cef_view_info_sender, cef_view_info_receiver) = std::sync::mpsc::channel(); - let cef_handler = cef::CefHandler::new(wgpu_context.clone(), app_event_scheduler.clone(), window_size_receiver); + let cef_handler = cef::CefHandler::new(wgpu_context.clone(), app_event_scheduler.clone(), cef_view_info_receiver); let cef_context = match cef_context_builder.initialize(cef_handler, cli.disable_ui_acceleration) { Ok(c) => { tracing::info!("CEF initialized successfully"); @@ -70,7 +70,7 @@ pub fn start() { } }; - let mut app = App::new(Box::new(cef_context), window_size_sender, wgpu_context, app_event_receiver, app_event_scheduler, cli.files); + let mut app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, cli.files); event_loop.run_app(&mut app).unwrap(); } diff --git a/desktop/src/window.rs b/desktop/src/window.rs index 9e43860288..e9994d23ca 100644 --- a/desktop/src/window.rs +++ b/desktop/src/window.rs @@ -68,6 +68,10 @@ impl Window { self.winit_window.surface_size() } + pub(crate) fn scale_factor(&self) -> f64 { + self.winit_window.scale_factor() + } + pub(crate) fn minimize(&self) { self.winit_window.set_minimized(true); } diff --git a/desktop/wrapper/src/handle_desktop_wrapper_message.rs b/desktop/wrapper/src/handle_desktop_wrapper_message.rs index 06b641f160..c649a4335a 100644 --- a/desktop/wrapper/src/handle_desktop_wrapper_message.rs +++ b/desktop/wrapper/src/handle_desktop_wrapper_message.rs @@ -2,7 +2,7 @@ use graphene_std::Color; use graphene_std::raster::Image; use graphite_editor::messages::app_window::app_window_message_handler::AppWindowPlatform; use graphite_editor::messages::layout::LayoutMessage; -use graphite_editor::messages::prelude::{AppWindowMessage, DocumentMessage, FrontendMessage, PortfolioMessage, PreferencesMessage}; +use graphite_editor::messages::prelude::*; use graphite_editor::messages::tool::tool_messages::tool_prelude::{LayoutTarget, WidgetId}; use crate::messages::Platform; diff --git a/desktop/wrapper/src/intercept_editor_message.rs b/desktop/wrapper/src/intercept_editor_message.rs index 4fc869f8c5..0f3bf93967 100644 --- a/desktop/wrapper/src/intercept_editor_message.rs +++ b/desktop/wrapper/src/intercept_editor_message.rs @@ -1,23 +1,7 @@ -use graphite_editor::messages::prelude::InputPreprocessorMessage; - use super::DesktopWrapperMessageDispatcher; -use super::messages::{DesktopFrontendMessage, EditorMessage}; +use super::messages::EditorMessage; -pub(super) fn intercept_editor_message(dispatcher: &mut DesktopWrapperMessageDispatcher, message: EditorMessage) -> Option { - match message { - EditorMessage::InputPreprocessor(message) => { - if let InputPreprocessorMessage::BoundsOfViewports { bounds_of_viewports } = &message { - let top_left = bounds_of_viewports[0].top_left; - let bottom_right = bounds_of_viewports[0].bottom_right; - dispatcher.respond(DesktopFrontendMessage::UpdateViewportBounds { - x: top_left.x as f32, - y: top_left.y as f32, - width: (bottom_right.x - top_left.x) as f32, - height: (bottom_right.y - top_left.y) as f32, - }); - } - Some(EditorMessage::InputPreprocessor(message)) - } - m => Some(m), - } +pub(super) fn intercept_editor_message(_dispatcher: &mut DesktopWrapperMessageDispatcher, message: EditorMessage) -> Option { + // TODO: remove it turns out to be unnecessary + Some(message) } diff --git a/desktop/wrapper/src/intercept_frontend_message.rs b/desktop/wrapper/src/intercept_frontend_message.rs index 50a55d57f7..97adb05cc6 100644 --- a/desktop/wrapper/src/intercept_frontend_message.rs +++ b/desktop/wrapper/src/intercept_frontend_message.rs @@ -79,6 +79,9 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD FrontendMessage::TriggerMaximizeWindow => { dispatcher.respond(DesktopFrontendMessage::MaximizeWindow); } + FrontendMessage::UpdateViewportPhysicalBounds { x, y, width, height } => { + dispatcher.respond(DesktopFrontendMessage::UpdateViewportPhysicalBounds { x, y, width, height }); + } FrontendMessage::TriggerPersistenceWriteDocument { document_id, document, details } => { dispatcher.respond(DesktopFrontendMessage::PersistenceWriteDocument { id: document_id, @@ -133,8 +136,8 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD None } -fn convert_menu_bar_entries_to_menu_items(layout: &Vec) -> Vec { - layout.iter().filter_map(|entry| convert_menu_bar_entry_to_menu_item(entry)).collect() +fn convert_menu_bar_entries_to_menu_items(layout: &[MenuBarEntry]) -> Vec { + layout.iter().filter_map(convert_menu_bar_entry_to_menu_item).collect() } fn convert_menu_bar_entry_to_menu_item( @@ -161,13 +164,7 @@ fn convert_menu_bar_entry_to_menu_item( } let shortcut = match shortcut { - Some(ActionKeys::Keys(LayoutKeysGroup(keys))) => { - if let Some(shortcut) = convert_layout_keys_to_shortcut(&keys) { - Some(shortcut) - } else { - None - } - } + Some(ActionKeys::Keys(LayoutKeysGroup(keys))) => convert_layout_keys_to_shortcut(keys), _ => None, }; @@ -197,7 +194,7 @@ fn convert_menu_bar_entry_to_menu_item( Some(MenuItem::Action { id, text, shortcut, enabled }) } -fn convert_menu_bar_entry_children_to_menu_items(children: &Vec>) -> Vec { +fn convert_menu_bar_entry_children_to_menu_items(children: &[Vec]) -> Vec { let mut items = Vec::new(); for (i, section) in children.iter().enumerate() { for entry in section.iter() { @@ -327,5 +324,5 @@ fn convert_layout_keys_to_shortcut(layout_keys: &Vec) -> Option key = None, } } - if let Some(key) = key { Some(Shortcut { key, modifiers }) } else { None } + key.map(|key| Shortcut { key, modifiers }) } diff --git a/desktop/wrapper/src/messages.rs b/desktop/wrapper/src/messages.rs index a7e1a86edc..b6afbfbf38 100644 --- a/desktop/wrapper/src/messages.rs +++ b/desktop/wrapper/src/messages.rs @@ -25,11 +25,11 @@ pub enum DesktopFrontendMessage { content: Vec, }, OpenUrl(String), - UpdateViewportBounds { - x: f32, - y: f32, - width: f32, - height: f32, + UpdateViewportPhysicalBounds { + x: f64, + y: f64, + width: f64, + height: f64, }, UpdateOverlays(vello::Scene), MinimizeWindow, diff --git a/frontend/src/components/window/title-bar/TitleBar.svelte b/frontend/src/components/window/title-bar/TitleBar.svelte index e9d4d8acd0..3843ae4667 100644 --- a/frontend/src/components/window/title-bar/TitleBar.svelte +++ b/frontend/src/components/window/title-bar/TitleBar.svelte @@ -59,26 +59,26 @@ - {#if platform !== "Mac"} - - + + + {#if platform !== "Mac"} {#each entries as entry} {/each} - - - editor.handle.appWindowDrag()} on:dblclick={() => editor.handle.appWindowMaximize()} /> - - - {#if platform === "Web"} - - {:else if platform === "Windows"} - - {:else if platform === "Linux"} - - {/if} - - {/if} + {/if} + + + editor.handle.appWindowDrag()} on:dblclick={() => editor.handle.appWindowMaximize()} /> + + + {#if platform === "Web"} + + {:else if platform === "Windows"} + + {:else if platform === "Linux"} + + {/if} +