fix(macos): sync restored fullscreen chrome

This commit is contained in:
edde746
2026-05-09 11:35:36 +02:00
parent bb66ab6526
commit afda61119e
8 changed files with 112 additions and 36 deletions
+3 -3
View File
@@ -31,14 +31,14 @@ class MainFlutterWindow: NSWindow {
WindowUtilsPlugin.register(
with: flutterViewController.registrar(forPlugin: "WindowUtilsPlugin"))
WindowUtilsPlugin.setWindow(self)
// Set custom traffic light positions using centralized values from plugin
WindowUtilsPlugin.setInitialTrafficLightPositions()
WindowUtilsPlugin.installWindowDelegate()
WindowUtilsPlugin.syncWindowChrome()
RegisterGeneratedPlugins(registry: flutterViewController)
// Enable window position/size persistence
self.setFrameAutosaveName("com.edde746.plezy.MainWindow")
WindowUtilsPlugin.syncWindowChrome()
super.awakeFromNib()
}
+32 -14
View File
@@ -20,6 +20,36 @@ class WindowDelegate: NSObject, NSWindowDelegate {
channel?.invokeMethod(method, arguments: nil)
}
func syncWindowChrome() {
guard let window = window else { return }
if window.styleMask.contains(.fullScreen) {
applyFullScreenChrome(to: window)
} else {
applyWindowedChrome(to: window)
}
}
private func applyFullScreenChrome(to window: NSWindow) {
window.toolbar = nil
window.titleVisibility = .visible
window.titlebarAppearsTransparent = false
WindowUtilsPlugin.setTrafficLightsVisible(true, window: window)
WindowUtilsPlugin.setTrafficLightPositions(custom: false, window: window)
}
private func applyWindowedChrome(to window: NSWindow) {
window.titleVisibility = .hidden
window.titlebarAppearsTransparent = true
window.styleMask.insert(.fullSizeContentView)
if window.toolbar == nil, let flutterVC = window.contentViewController {
window.toolbar = ForwardingToolbar(flutterViewController: flutterVC)
}
WindowUtilsPlugin.setTrafficLightsVisible(true, window: window)
WindowUtilsPlugin.setTrafficLightPositions(custom: true, window: window)
}
// MARK: - NSWindowDelegate
func window(
@@ -31,13 +61,7 @@ class WindowDelegate: NSObject, NSWindowDelegate {
func windowWillEnterFullScreen(_ notification: Notification) {
guard let window = window else { return }
// Remove toolbar before entering fullscreen
window.toolbar = nil
// Show title and make titlebar opaque for native fullscreen look
window.titleVisibility = .visible
window.titlebarAppearsTransparent = false
// Reset traffic light positions to default
WindowUtilsPlugin.setTrafficLightPositions(custom: false, window: window)
applyFullScreenChrome(to: window)
// Notify Dart for state management only
emit("windowWillEnterFullScreen")
}
@@ -56,13 +80,7 @@ class WindowDelegate: NSObject, NSWindowDelegate {
func windowDidExitFullScreen(_ notification: Notification) {
guard let window = window else { return }
// Restore toolbar
if let flutterVC = window.contentViewController {
let toolbar = ForwardingToolbar(flutterViewController: flutterVC)
window.toolbar = toolbar
}
// Restore custom traffic light positions
WindowUtilsPlugin.setTrafficLightPositions(custom: true, window: window)
applyWindowedChrome(to: window)
emit("windowDidExitFullScreen")
}
}
+42 -11
View File
@@ -88,12 +88,17 @@ class WindowUtilsPlugin: NSObject, FlutterPlugin {
static func setWindow(_ window: NSWindow) {
instance?.window = window
instance?.windowDelegate?.window = window
}
/// Apply custom traffic light positions. Called by MainFlutterWindow on startup.
static func setInitialTrafficLightPositions() {
static func installWindowDelegate() {
guard let instance = instance, let window = instance.window else { return }
instance.applyTrafficLightPositions(custom: true, window: window)
instance.installWindowDelegate(window: window)
}
static func syncWindowChrome() {
guard let instance = instance else { return }
instance.syncWindowChrome()
}
/// Apply traffic light positions. Called by WindowDelegate during fullscreen transitions.
@@ -102,6 +107,12 @@ class WindowUtilsPlugin: NSObject, FlutterPlugin {
instance.applyTrafficLightPositions(custom: custom, window: window)
}
static func setTrafficLightsVisible(_ visible: Bool, window: NSWindow) {
for buttonType in [NSWindow.ButtonType.closeButton, .miniaturizeButton, .zoomButton] {
window.standardWindowButton(buttonType)?.isHidden = !visible
}
}
private func applyTrafficLightPositions(custom: Bool, window: NSWindow) {
if custom {
for (buttonType, offset) in WindowUtilsPlugin.customButtonPositions {
@@ -130,9 +141,11 @@ class WindowUtilsPlugin: NSObject, FlutterPlugin {
case "setTrafficLightsVisible":
let args = call.arguments as? [String: Any]
let visible = args?["visible"] as? Bool ?? true
for buttonType in [NSWindow.ButtonType.closeButton, .miniaturizeButton, .zoomButton] {
window.standardWindowButton(buttonType)?.isHidden = !visible
}
WindowUtilsPlugin.setTrafficLightsVisible(visible, window: window)
result(nil)
case "syncWindowChrome":
syncWindowChrome()
result(nil)
case "enterFullscreen":
@@ -159,12 +172,30 @@ class WindowUtilsPlugin: NSObject, FlutterPlugin {
self.window = window
if enableWindowDelegate {
let delegate = WindowDelegate()
delegate.channel = channel
delegate.window = window
windowDelegate = delegate
window.delegate = delegate
installWindowDelegate(window: window)
}
windowDelegate?.syncWindowChrome()
}
private func installWindowDelegate(window: NSWindow) {
let delegate = windowDelegate ?? WindowDelegate()
delegate.channel = channel
delegate.window = window
windowDelegate = delegate
window.delegate = delegate
}
private func syncWindowChrome() {
guard let window = window else { return }
if windowDelegate == nil {
installWindowDelegate(window: window)
} else {
windowDelegate?.channel = channel
windowDelegate?.window = window
window.delegate = windowDelegate
}
windowDelegate?.syncWindowChrome()
}
private func withButton(