Skip to content

Commit 7532bd7

Browse files
Desktop: Hide menu bar in fullscreen mode on Mac (#3464)
hide menu bar in fullscreen mode on mac
1 parent 6d852f1 commit 7532bd7

8 files changed

Lines changed: 94 additions & 36 deletions

File tree

desktop/src/app.rs

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub(crate) struct App {
2828
wgpu_context: WgpuContext,
2929
window: Option<Window>,
3030
window_scale: f64,
31+
window_size: PhysicalSize<u32>,
32+
window_maximized: bool,
33+
window_fullscreen: bool,
3134
app_event_receiver: Receiver<AppEvent>,
3235
app_event_scheduler: AppEventScheduler,
3336
desktop_wrapper: DesktopWrapper,
@@ -81,6 +84,9 @@ impl App {
8184
wgpu_context,
8285
window: None,
8386
window_scale: 1.,
87+
window_size: PhysicalSize { width: 0, height: 0 },
88+
window_maximized: false,
89+
window_fullscreen: false,
8490
app_event_receiver,
8591
app_event_scheduler,
8692
desktop_wrapper: DesktopWrapper::new(),
@@ -97,6 +103,56 @@ impl App {
97103
}
98104
}
99105

106+
fn resize(&mut self) {
107+
let Some(window) = &self.window else {
108+
tracing::error!("Resize failed due to missing window");
109+
return;
110+
};
111+
112+
let maximized = window.is_maximized();
113+
if maximized != self.window_maximized {
114+
self.window_maximized = maximized;
115+
self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateMaximized { maximized }));
116+
}
117+
118+
let fullscreen = window.is_fullscreen();
119+
if fullscreen != self.window_fullscreen {
120+
self.window_fullscreen = fullscreen;
121+
self.app_event_scheduler
122+
.schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateFullscreen { fullscreen }));
123+
}
124+
125+
let size = window.surface_size();
126+
let scale = window.scale_factor();
127+
let is_new_size = size != self.window_size;
128+
let is_new_scale = scale != self.window_scale;
129+
130+
if !is_new_size && !is_new_scale {
131+
return;
132+
}
133+
134+
if is_new_size {
135+
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size {
136+
width: size.width,
137+
height: size.height,
138+
});
139+
}
140+
if is_new_scale {
141+
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(scale));
142+
}
143+
144+
self.cef_context.notify_view_info_changed();
145+
146+
if let Some(render_state) = &mut self.render_state {
147+
render_state.resize(size.width, size.height);
148+
}
149+
150+
window.request_redraw();
151+
152+
self.window_size = size;
153+
self.window_scale = scale;
154+
}
155+
100156
fn handle_desktop_frontend_message(&mut self, message: DesktopFrontendMessage, responses: &mut Vec<DesktopWrapperMessage>) {
101157
match message {
102158
DesktopFrontendMessage::ToWeb(messages) => {
@@ -393,22 +449,13 @@ impl App {
393449
impl ApplicationHandler for App {
394450
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
395451
let window = Window::new(event_loop, self.app_event_scheduler.clone());
396-
397-
self.window_scale = window.scale_factor();
398-
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(self.window_scale));
399-
400-
// Ensures the CEF texture does not remain at 1x1 pixels until the window is resized by the user
401-
// Affects only some Mac devices (issue found on 2023 M2 Mac Mini).
402-
let PhysicalSize { width, height } = window.surface_size();
403-
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size { width, height });
404-
405-
self.cef_context.notify_view_info_changed();
406-
407452
self.window = Some(window);
408453

409454
let render_state = RenderState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone());
410455
self.render_state = Some(render_state);
411456

457+
self.resize();
458+
412459
self.desktop_wrapper.init(self.wgpu_context.clone());
413460

414461
#[cfg(target_os = "windows")]
@@ -433,32 +480,15 @@ impl ApplicationHandler for App {
433480
WindowEvent::CloseRequested => {
434481
self.app_event_scheduler.schedule(AppEvent::CloseWindow);
435482
}
436-
WindowEvent::SurfaceResized(PhysicalSize { width, height }) => {
437-
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size { width, height });
438-
self.cef_context.notify_view_info_changed();
439-
440-
if let Some(render_state) = &mut self.render_state {
441-
render_state.resize(width, height);
442-
}
443-
444-
if let Some(window) = &self.window {
445-
let maximized = window.is_maximized();
446-
self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateMaximized { maximized }));
447-
448-
window.request_redraw();
449-
}
450-
}
451-
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
452-
self.window_scale = scale_factor;
453-
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(self.window_scale));
454-
self.cef_context.notify_view_info_changed();
483+
WindowEvent::SurfaceResized(_) | WindowEvent::ScaleFactorChanged { .. } => {
484+
self.resize();
455485
}
456486
WindowEvent::RedrawRequested => {
487+
#[cfg(target_os = "macos")]
488+
self.resize();
489+
457490
let Some(render_state) = &mut self.render_state else { return };
458491
if let Some(window) = &self.window {
459-
let size = window.surface_size();
460-
render_state.resize(size.width, size.height);
461-
462492
match render_state.render(window) {
463493
Ok(_) => {}
464494
Err(RenderError::OutdatedUITextureError) => {

desktop/src/window.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ impl Window {
9999
self.winit_window.is_maximized()
100100
}
101101

102+
pub(crate) fn is_fullscreen(&self) -> bool {
103+
self.winit_window.fullscreen().is_some()
104+
}
105+
102106
pub(crate) fn start_drag(&self) {
103107
let _ = self.winit_window.drag_window();
104108
}

desktop/wrapper/src/handle_desktop_wrapper_message.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ pub(super) fn handle_desktop_wrapper_message(dispatcher: &mut DesktopWrapperMess
121121
let message = FrontendMessage::UpdateMaximized { maximized };
122122
dispatcher.queue_editor_message(message);
123123
}
124+
DesktopWrapperMessage::UpdateFullscreen { fullscreen } => {
125+
let message = FrontendMessage::UpdateFullscreen { fullscreen };
126+
dispatcher.queue_editor_message(message);
127+
}
124128
DesktopWrapperMessage::LoadDocument {
125129
id,
126130
document,

desktop/wrapper/src/messages.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ pub enum DesktopWrapperMessage {
103103
UpdateMaximized {
104104
maximized: bool,
105105
},
106+
UpdateFullscreen {
107+
fullscreen: bool,
108+
},
106109
LoadDocument {
107110
id: DocumentId,
108111
document: Document,

editor/src/messages/frontend/frontend_message.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ pub enum FrontendMessage {
326326
UpdateMaximized {
327327
maximized: bool,
328328
},
329+
UpdateFullscreen {
330+
fullscreen: bool,
331+
},
329332
UpdateViewportHolePunch {
330333
active: bool,
331334
},

frontend/src/components/window/MainWindow.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
</script>
1919

2020
<LayoutCol class="main-window" classes={{ "viewport-hole-punch": $appWindow.viewportHolePunch }}>
21-
<TitleBar />
21+
{#if !($appWindow.platform == "Mac" && $appWindow.fullscreen)}
22+
<TitleBar />
23+
{/if}
2224
<Workspace />
2325
<StatusBar />
2426
{#if $dialog.visible}

frontend/src/messages.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ export class UpdateMaximized extends JsMessage {
302302
readonly maximized!: boolean;
303303
}
304304

305+
export class UpdateFullscreen extends JsMessage {
306+
readonly fullscreen!: boolean;
307+
}
308+
305309
export class CloseWindow extends JsMessage {}
306310

307311
export class UpdateViewportHolePunch extends JsMessage {
@@ -1742,7 +1746,6 @@ export const messageMakers: Record<string, MessageMaker> = {
17421746
UpdateLayersPanelControlBarRightLayout,
17431747
UpdateLayersPanelState,
17441748
UpdateLayerWidths,
1745-
UpdateMaximized,
17461749
UpdateMenuBarLayout,
17471750
UpdateMouseCursor,
17481751
UpdateNodeGraphControlBarLayout,
@@ -1754,6 +1757,8 @@ export const messageMakers: Record<string, MessageMaker> = {
17541757
UpdateNodeThumbnail,
17551758
UpdateOpenDocumentsList,
17561759
UpdatePlatform,
1760+
UpdateMaximized,
1761+
UpdateFullscreen,
17571762
UpdatePropertiesPanelLayout,
17581763
UpdatePropertiesPanelState,
17591764
UpdateStatusBarHintsLayout,

frontend/src/state-providers/app-window.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { writable } from "svelte/store";
22

33
import { type Editor } from "@graphite/editor";
4-
import { type AppWindowPlatform, UpdatePlatform, UpdateViewportHolePunch, UpdateMaximized as UpdateMaximized } from "@graphite/messages";
4+
import { type AppWindowPlatform, UpdatePlatform, UpdateViewportHolePunch, UpdateMaximized, UpdateFullscreen } from "@graphite/messages";
55

66
export function createAppWindowState(editor: Editor) {
77
const { subscribe, update } = writable({
88
platform: "Web" as AppWindowPlatform,
99
maximized: false,
10+
fullscreen: false,
1011
viewportHolePunch: false,
1112
});
1213

@@ -23,6 +24,12 @@ export function createAppWindowState(editor: Editor) {
2324
return state;
2425
});
2526
});
27+
editor.subscriptions.subscribeJsMessage(UpdateFullscreen, (updateFullscreen) => {
28+
update((state) => {
29+
state.fullscreen = updateFullscreen.fullscreen;
30+
return state;
31+
});
32+
});
2633
editor.subscriptions.subscribeJsMessage(UpdateViewportHolePunch, (viewportHolePunch) => {
2734
update((state) => {
2835
state.viewportHolePunch = viewportHolePunch.active;

0 commit comments

Comments
 (0)