From b229e2cc1dc3dd73bc8dd3d443296d605b3d20da Mon Sep 17 00:00:00 2001 From: Timon Schelling Date: Sat, 8 Nov 2025 09:45:33 +0000 Subject: [PATCH 1/9] desktop support ui scaling --- desktop/src/app.rs | 46 ++++++---- desktop/src/cef.rs | 84 ++++++++++++------- desktop/src/cef/context.rs | 4 +- desktop/src/cef/context/multithreaded.rs | 8 +- desktop/src/cef/context/singlethreaded.rs | 11 +-- desktop/src/cef/input.rs | 14 ++-- desktop/src/cef/internal.rs | 10 +++ desktop/src/cef/internal/render_handler.rs | 26 +++++- desktop/src/lib.rs | 6 +- desktop/src/window.rs | 4 + .../src/handle_desktop_wrapper_message.rs | 2 +- .../wrapper/src/intercept_editor_message.rs | 15 +--- .../wrapper/src/intercept_frontend_message.rs | 19 ++--- desktop/wrapper/src/messages.rs | 10 +-- .../window/title-bar/TitleBar.svelte | 34 ++++---- node-graph/gstd/src/render_node.rs | 21 +++-- node-graph/gsvg-renderer/src/renderer.rs | 5 +- 17 files changed, 192 insertions(+), 127 deletions(-) diff --git a/desktop/src/app.rs b/desktop/src/app.rs index 3aec9d2e3d..e0ca9977c7 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) => { @@ -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")] @@ -378,20 +384,28 @@ impl ApplicationHandler for App { } fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, _window_id: WindowId, event: WindowEvent) { - self.cef_context.handle_window_event(&event); + self.cef_context.handle_window_event(&event, self.window_scale); match event { 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..a83fbf1b3e 100644 --- a/desktop/src/cef.rs +++ b/desktop/src/cef.rs @@ -39,7 +39,7 @@ use texture_import::SharedTextureHandle; pub(crate) use context::{CefContext, CefContextBuilder, InitError}; pub(crate) trait CefEventHandler: Clone + Send + Sync + 'static { - fn window_size(&self) -> WindowSize; + fn view_info(&self) -> ViewInfo; fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>); #[cfg(feature = "accelerated_paint")] fn draw_gpu(&self, shared_texture: SharedTextureHandle); @@ -53,21 +53,48 @@ pub(crate) trait CefEventHandler: Clone + Send + Sync + 'static { } #[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.0 } + } + 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.0 => { + self.scale = scale; + } + _ => {} + } + } + pub(crate) fn scale(&self) -> f64 { + self.scale + } + pub(crate) fn scaled_width(&self) -> usize { + (self.width as f64 / self.scale).round() as usize + } + pub(crate) fn scaled_height(&self) -> usize { + (self.height as f64 / self.scale).round() as usize } } -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, @@ -93,30 +120,30 @@ impl Read for ResourceReader { 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; @@ -246,15 +273,12 @@ impl CefEventHandler for CefHandler { } } -struct WindowSizeReceiver { - window_size: WindowSize, - receiver: Receiver, +struct ViewInfoReceiver { + view_info: ViewInfo, + receiver: Receiver, } -impl WindowSizeReceiver { - fn new(window_size_receiver: Receiver) -> Self { - Self { - window_size: WindowSize { width: 1, height: 1 }, - receiver: window_size_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..21c07a99eb 100644 --- a/desktop/src/cef/context.rs +++ b/desktop/src/cef/context.rs @@ -8,9 +8,9 @@ pub(crate) use builder::{CefContextBuilder, InitError}; pub(crate) trait CefContext { fn work(&mut self); - fn handle_window_event(&mut self, event: &winit::event::WindowEvent); + fn handle_window_event(&mut self, event: &winit::event::WindowEvent, scale: f64); - 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/multithreaded.rs b/desktop/src/cef/context/multithreaded.rs index 9434a99d86..f871d85967 100644 --- a/desktop/src/cef/context/multithreaded.rs +++ b/desktop/src/cef/context/multithreaded.rs @@ -19,22 +19,22 @@ impl CefContext for MultiThreadedCefContextProxy { // CEF handles its own message loop in multi-threaded mode } - fn handle_window_event(&mut self, event: &WindowEvent) { + fn handle_window_event(&mut self, event: &WindowEvent, scale: f64) { let event_clone = event.clone(); run_on_ui_thread(move || { CONTEXT.with(|b| { if let Some(context) = b.borrow_mut().as_mut() { - context.handle_window_event(&event_clone); + context.handle_window_event(&event_clone, scale); } }); }); } - 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..9d9d434701 100644 --- a/desktop/src/cef/context/singlethreaded.rs +++ b/desktop/src/cef/context/singlethreaded.rs @@ -1,8 +1,9 @@ -use cef::{Browser, ImplBrowser, ImplBrowserHost}; +use cef::{Browser, ImplBrowser}; use winit::event::WindowEvent; use crate::cef::input; use crate::cef::input::InputState; +use crate::cef::internal::NotifyViewInfoChanged; use crate::cef::ipc::{MessageType, SendMessage}; use super::CefContext; @@ -18,12 +19,12 @@ impl CefContext for SingleThreadedCefContext { cef::do_message_loop_work(); } - fn handle_window_event(&mut self, event: &WindowEvent) { - input::handle_window_event(&self.browser, &mut self.input_state, event) + fn handle_window_event(&mut self, event: &WindowEvent, scale: f64) { + input::handle_window_event(&self.browser, &mut self.input_state, event, scale) } - fn notify_of_resize(&self) { - self.browser.host().unwrap().was_resized(); + fn notify_view_info_changed(&self) { + self.browser.host().unwrap().notify_view_info_changed(); } fn send_web_message(&self, message: Vec) { diff --git a/desktop/src/cef/input.rs b/desktop/src/cef/input.rs index feb9eff563..c53a405263 100644 --- a/desktop/src/cef/input.rs +++ b/desktop/src/cef/input.rs @@ -1,7 +1,7 @@ use cef::sys::{cef_event_flags_t, cef_key_event_type_t, cef_mouse_button_type_t}; use cef::{Browser, ImplBrowser, ImplBrowserHost, KeyEvent, KeyEventType, MouseEvent}; use std::time::Instant; -use winit::dpi::PhysicalPosition; +use winit::dpi::LogicalPosition; use winit::event::{ButtonSource, ElementState, MouseButton, MouseScrollDelta, WindowEvent}; mod keymap; @@ -9,17 +9,17 @@ use keymap::{ToNativeKeycode, ToVKBits}; use super::consts::{MULTICLICK_ALLOWED_TRAVEL, MULTICLICK_TIMEOUT, PINCH_ZOOM_SPEED, SCROLL_LINE_HEIGHT, SCROLL_LINE_WIDTH, SCROLL_SPEED_X, SCROLL_SPEED_Y}; -pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputState, event: &WindowEvent) { +pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputState, event: &WindowEvent, scale: f64) { match event { WindowEvent::PointerMoved { position, .. } | WindowEvent::PointerEntered { position, .. } => { - input_state.cursor_move(position); + input_state.cursor_move(&position.to_logical(scale)); 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.to_logical(scale)); } let Some(host) = browser.host() else { return }; @@ -159,7 +159,7 @@ impl InputState { self.modifiers = *modifiers; } - fn cursor_move(&mut self, position: &PhysicalPosition) { + fn cursor_move(&mut self, position: &LogicalPosition) { self.mouse_position = position.into(); } @@ -206,8 +206,8 @@ pub(crate) struct MousePosition { x: usize, y: usize, } -impl From<&PhysicalPosition> for MousePosition { - fn from(position: &PhysicalPosition) -> Self { +impl From<&LogicalPosition> for MousePosition { + fn from(position: &LogicalPosition) -> Self { Self { x: position.x as usize, y: position.y as usize, diff --git a/desktop/src/cef/internal.rs b/desktop/src/cef/internal.rs index 1a9c8645a3..c6e44749b8 100644 --- a/desktop/src/cef/internal.rs +++ b/desktop/src/cef/internal.rs @@ -22,3 +22,13 @@ 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; + +pub(super) trait NotifyViewInfoChanged { + fn notify_view_info_changed(&self); +} +impl NotifyViewInfoChanged for T { + fn notify_view_info_changed(&self) { + self.notify_screen_info_changed(); + self.was_resized(); + } +} diff --git a/desktop/src/cef/internal/render_handler.rs b/desktop/src/cef/internal/render_handler.rs index dd725a01b9..d7fa115b4d 100644 --- a/desktop/src/cef/internal/render_handler.rs +++ b/desktop/src/cef/internal/render_handler.rs @@ -21,16 +21,36 @@ 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.scaled_width() as i32, + height: view_info.scaled_height() as i32, }; } } + fn screen_info(&self, _browser: Option<&mut Browser>, screen_info: Option<&mut cef::ScreenInfo>) -> std::ffi::c_int { + if let Some(screen_info) = screen_info { + let view_info = self.event_handler.view_info(); + + screen_info.device_scale_factor = view_info.scale() as f32; + + let rect = Rect { + x: 0, + y: 0, + width: view_info.scaled_width() as i32, + height: view_info.scaled_height() as i32, + }; + screen_info.rect = rect.clone(); + screen_info.available_rect = rect; + + return 1; + } + 0 + } + fn on_paint( &self, _browser: Option<&mut Browser>, 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..265f01d985 100644 --- a/desktop/wrapper/src/intercept_editor_message.rs +++ b/desktop/wrapper/src/intercept_editor_message.rs @@ -1,23 +1,10 @@ -use graphite_editor::messages::prelude::InputPreprocessorMessage; +use graphite_editor::messages::prelude::*; use super::DesktopWrapperMessageDispatcher; use super::messages::{DesktopFrontendMessage, 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), } } 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} +