Desktop: Hide menu bar in fullscreen mode on Mac (#3464)
Some checks failed
Editor: Dev & CI / build (push) Has been cancelled
Editor: Dev & CI / cargo-deny (push) Has been cancelled

hide menu bar in fullscreen mode on mac
This commit is contained in:
Timon 2025-12-12 13:09:31 +00:00 committed by GitHub
parent 6d852f11af
commit 7532bd7260
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 94 additions and 36 deletions

View file

@ -28,6 +28,9 @@ pub(crate) struct App {
wgpu_context: WgpuContext,
window: Option<Window>,
window_scale: f64,
window_size: PhysicalSize<u32>,
window_maximized: bool,
window_fullscreen: bool,
app_event_receiver: Receiver<AppEvent>,
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<DesktopWrapperMessage>) {
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) => {

View file

@ -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();
}

View file

@ -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,

View file

@ -103,6 +103,9 @@ pub enum DesktopWrapperMessage {
UpdateMaximized {
maximized: bool,
},
UpdateFullscreen {
fullscreen: bool,
},
LoadDocument {
id: DocumentId,
document: Document,

View file

@ -326,6 +326,9 @@ pub enum FrontendMessage {
UpdateMaximized {
maximized: bool,
},
UpdateFullscreen {
fullscreen: bool,
},
UpdateViewportHolePunch {
active: bool,
},

View file

@ -18,7 +18,9 @@
</script>
<LayoutCol class="main-window" classes={{ "viewport-hole-punch": $appWindow.viewportHolePunch }}>
<TitleBar />
{#if !($appWindow.platform == "Mac" && $appWindow.fullscreen)}
<TitleBar />
{/if}
<Workspace />
<StatusBar />
{#if $dialog.visible}

View file

@ -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<string, MessageMaker> = {
UpdateLayersPanelControlBarRightLayout,
UpdateLayersPanelState,
UpdateLayerWidths,
UpdateMaximized,
UpdateMenuBarLayout,
UpdateMouseCursor,
UpdateNodeGraphControlBarLayout,
@ -1754,6 +1757,8 @@ export const messageMakers: Record<string, MessageMaker> = {
UpdateNodeThumbnail,
UpdateOpenDocumentsList,
UpdatePlatform,
UpdateMaximized,
UpdateFullscreen,
UpdatePropertiesPanelLayout,
UpdatePropertiesPanelState,
UpdateStatusBarHintsLayout,

View file

@ -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;