diff --git a/desktop/src/app.rs b/desktop/src/app.rs index a33bec6bd..8fcb4077f 100644 --- a/desktop/src/app.rs +++ b/desktop/src/app.rs @@ -28,6 +28,9 @@ pub(crate) struct App { wgpu_context: WgpuContext, window: Option, window_scale: f64, + window_size: PhysicalSize, + window_maximized: bool, + window_fullscreen: bool, app_event_receiver: Receiver, app_event_scheduler: AppEventScheduler, desktop_wrapper: DesktopWrapper, @@ -81,6 +84,9 @@ impl App { wgpu_context, window: None, window_scale: 1., + window_size: PhysicalSize { width: 0, height: 0 }, + window_maximized: false, + window_fullscreen: false, app_event_receiver, app_event_scheduler, desktop_wrapper: DesktopWrapper::new(), @@ -97,6 +103,56 @@ impl App { } } + fn resize(&mut self) { + let Some(window) = &self.window else { + tracing::error!("Resize failed due to missing window"); + return; + }; + + let maximized = window.is_maximized(); + if maximized != self.window_maximized { + self.window_maximized = maximized; + self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateMaximized { maximized })); + } + + let fullscreen = window.is_fullscreen(); + if fullscreen != self.window_fullscreen { + self.window_fullscreen = fullscreen; + self.app_event_scheduler + .schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateFullscreen { fullscreen })); + } + + let size = window.surface_size(); + let scale = window.scale_factor(); + let is_new_size = size != self.window_size; + let is_new_scale = scale != self.window_scale; + + if !is_new_size && !is_new_scale { + return; + } + + if is_new_size { + let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size { + width: size.width, + height: size.height, + }); + } + if is_new_scale { + let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(scale)); + } + + self.cef_context.notify_view_info_changed(); + + if let Some(render_state) = &mut self.render_state { + render_state.resize(size.width, size.height); + } + + window.request_redraw(); + + self.window_size = size; + self.window_scale = scale; + } + fn handle_desktop_frontend_message(&mut self, message: DesktopFrontendMessage, responses: &mut Vec) { match message { DesktopFrontendMessage::ToWeb(messages) => { @@ -393,22 +449,13 @@ 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)); - - // Ensures the CEF texture does not remain at 1x1 pixels until the window is resized by the user - // Affects only some Mac devices (issue found on 2023 M2 Mac Mini). - let PhysicalSize { width, height } = window.surface_size(); - let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size { width, height }); - - self.cef_context.notify_view_info_changed(); - self.window = Some(window); let render_state = RenderState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone()); self.render_state = Some(render_state); + self.resize(); + self.desktop_wrapper.init(self.wgpu_context.clone()); #[cfg(target_os = "windows")] @@ -433,32 +480,15 @@ impl ApplicationHandler for App { WindowEvent::CloseRequested => { self.app_event_scheduler.schedule(AppEvent::CloseWindow); } - WindowEvent::SurfaceResized(PhysicalSize { width, height }) => { - let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size { width, height }); - self.cef_context.notify_view_info_changed(); - - if let Some(render_state) = &mut self.render_state { - render_state.resize(width, height); - } - - if let Some(window) = &self.window { - let maximized = window.is_maximized(); - self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateMaximized { maximized })); - - window.request_redraw(); - } - } - 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::SurfaceResized(_) | WindowEvent::ScaleFactorChanged { .. } => { + self.resize(); } WindowEvent::RedrawRequested => { + #[cfg(target_os = "macos")] + self.resize(); + let Some(render_state) = &mut self.render_state else { return }; if let Some(window) = &self.window { - let size = window.surface_size(); - render_state.resize(size.width, size.height); - match render_state.render(window) { Ok(_) => {} Err(RenderError::OutdatedUITextureError) => { diff --git a/desktop/src/window.rs b/desktop/src/window.rs index 27ef43ab1..76b8ca1de 100644 --- a/desktop/src/window.rs +++ b/desktop/src/window.rs @@ -99,6 +99,10 @@ impl Window { self.winit_window.is_maximized() } + pub(crate) fn is_fullscreen(&self) -> bool { + self.winit_window.fullscreen().is_some() + } + pub(crate) fn start_drag(&self) { let _ = self.winit_window.drag_window(); } diff --git a/desktop/wrapper/src/handle_desktop_wrapper_message.rs b/desktop/wrapper/src/handle_desktop_wrapper_message.rs index 721bd3874..01daee633 100644 --- a/desktop/wrapper/src/handle_desktop_wrapper_message.rs +++ b/desktop/wrapper/src/handle_desktop_wrapper_message.rs @@ -121,6 +121,10 @@ pub(super) fn handle_desktop_wrapper_message(dispatcher: &mut DesktopWrapperMess let message = FrontendMessage::UpdateMaximized { maximized }; dispatcher.queue_editor_message(message); } + DesktopWrapperMessage::UpdateFullscreen { fullscreen } => { + let message = FrontendMessage::UpdateFullscreen { fullscreen }; + dispatcher.queue_editor_message(message); + } DesktopWrapperMessage::LoadDocument { id, document, diff --git a/desktop/wrapper/src/messages.rs b/desktop/wrapper/src/messages.rs index a92ab0d5a..350bf5e70 100644 --- a/desktop/wrapper/src/messages.rs +++ b/desktop/wrapper/src/messages.rs @@ -103,6 +103,9 @@ pub enum DesktopWrapperMessage { UpdateMaximized { maximized: bool, }, + UpdateFullscreen { + fullscreen: bool, + }, LoadDocument { id: DocumentId, document: Document, diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index dc875f139..573dc8ffd 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -326,6 +326,9 @@ pub enum FrontendMessage { UpdateMaximized { maximized: bool, }, + UpdateFullscreen { + fullscreen: bool, + }, UpdateViewportHolePunch { active: bool, }, diff --git a/frontend/src/components/window/MainWindow.svelte b/frontend/src/components/window/MainWindow.svelte index 67611db25..19be805d9 100644 --- a/frontend/src/components/window/MainWindow.svelte +++ b/frontend/src/components/window/MainWindow.svelte @@ -18,7 +18,9 @@ - + {#if !($appWindow.platform == "Mac" && $appWindow.fullscreen)} + + {/if} {#if $dialog.visible} diff --git a/frontend/src/messages.ts b/frontend/src/messages.ts index e7fa5efca..65ee12013 100644 --- a/frontend/src/messages.ts +++ b/frontend/src/messages.ts @@ -302,6 +302,10 @@ export class UpdateMaximized extends JsMessage { readonly maximized!: boolean; } +export class UpdateFullscreen extends JsMessage { + readonly fullscreen!: boolean; +} + export class CloseWindow extends JsMessage {} export class UpdateViewportHolePunch extends JsMessage { @@ -1742,7 +1746,6 @@ export const messageMakers: Record = { UpdateLayersPanelControlBarRightLayout, UpdateLayersPanelState, UpdateLayerWidths, - UpdateMaximized, UpdateMenuBarLayout, UpdateMouseCursor, UpdateNodeGraphControlBarLayout, @@ -1754,6 +1757,8 @@ export const messageMakers: Record = { UpdateNodeThumbnail, UpdateOpenDocumentsList, UpdatePlatform, + UpdateMaximized, + UpdateFullscreen, UpdatePropertiesPanelLayout, UpdatePropertiesPanelState, UpdateStatusBarHintsLayout, diff --git a/frontend/src/state-providers/app-window.ts b/frontend/src/state-providers/app-window.ts index 9f83ca1cf..77e10e123 100644 --- a/frontend/src/state-providers/app-window.ts +++ b/frontend/src/state-providers/app-window.ts @@ -1,12 +1,13 @@ import { writable } from "svelte/store"; import { type Editor } from "@graphite/editor"; -import { type AppWindowPlatform, UpdatePlatform, UpdateViewportHolePunch, UpdateMaximized as UpdateMaximized } from "@graphite/messages"; +import { type AppWindowPlatform, UpdatePlatform, UpdateViewportHolePunch, UpdateMaximized, UpdateFullscreen } from "@graphite/messages"; export function createAppWindowState(editor: Editor) { const { subscribe, update } = writable({ platform: "Web" as AppWindowPlatform, maximized: false, + fullscreen: false, viewportHolePunch: false, }); @@ -23,6 +24,12 @@ export function createAppWindowState(editor: Editor) { return state; }); }); + editor.subscriptions.subscribeJsMessage(UpdateFullscreen, (updateFullscreen) => { + update((state) => { + state.fullscreen = updateFullscreen.fullscreen; + return state; + }); + }); editor.subscriptions.subscribeJsMessage(UpdateViewportHolePunch, (viewportHolePunch) => { update((state) => { state.viewportHolePunch = viewportHolePunch.active;