From 1626c8cd3a6b8d2602641a7a3207a880cc116893 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 2 Sep 2023 09:15:50 -0700 Subject: [PATCH] macos: hacks for split focus to work correctly on macos 12 --- macos/Sources/Ghostty/Ghostty.SplitView.swift | 13 +++++++++++++ macos/Sources/Ghostty/Package.swift | 4 ++++ macos/Sources/Ghostty/SurfaceView.swift | 15 +++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/macos/Sources/Ghostty/Ghostty.SplitView.swift b/macos/Sources/Ghostty/Ghostty.SplitView.swift index 553ede47f..9ea1a7351 100644 --- a/macos/Sources/Ghostty/Ghostty.SplitView.swift +++ b/macos/Sources/Ghostty/Ghostty.SplitView.swift @@ -322,6 +322,19 @@ extension Ghostty { if previous != view { _ = previous.resignFirstResponder() } + + // On newer versions of macOS everything above works great so we're done. + if #available(macOS 13, *) { return } + + // On macOS 12, splits do not properly gain focus. I don't know why, but + // it seems like the `focused` SwiftUI method doesn't work. We use + // NotificationCenter as a blunt force instrument to make it work. + if #available(macOS 12, *) { + NotificationCenter.default.post( + name: Notification.didBecomeFocusedSurface, + object: view + ) + } } } } diff --git a/macos/Sources/Ghostty/Package.swift b/macos/Sources/Ghostty/Package.swift index 7a09fd872..1b4517c22 100644 --- a/macos/Sources/Ghostty/Package.swift +++ b/macos/Sources/Ghostty/Package.swift @@ -91,6 +91,10 @@ extension Ghostty.Notification { /// Toggle fullscreen of current window static let ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen") static let NonNativeFullscreenKey = ghosttyToggleFullscreen.rawValue + + /// Notification that a surface is becoming focused. This is only sent on macOS 12 to + /// work around bugs. macOS 13+ should use the ".focused()" attribute. + static let didBecomeFocusedSurface = Notification.Name("com.mitchellh.ghostty.didBecomeFocusedSurface") } // Make the input enum hashable. diff --git a/macos/Sources/Ghostty/SurfaceView.swift b/macos/Sources/Ghostty/SurfaceView.swift index 8448cb5d2..d6e885d55 100644 --- a/macos/Sources/Ghostty/SurfaceView.swift +++ b/macos/Sources/Ghostty/SurfaceView.swift @@ -54,7 +54,8 @@ extension Ghostty { // resize callback. GeometryReader { geo in // We use these notifications to determine when the window our surface is - // attached to is or is not focused. + // attached to is or is not focused. + let pubBecomeFocused = NotificationCenter.default.publisher(for: Notification.didBecomeFocusedSurface, object: surfaceView) let pubBecomeKey = NotificationCenter.default.publisher(for: NSWindow.didBecomeKeyNotification) let pubResign = NotificationCenter.default.publisher(for: NSWindow.didResignKeyNotification) @@ -74,6 +75,16 @@ extension Ghostty { windowFocus = false } } + .onReceive(pubBecomeFocused) { notification in + // We only want to run this on older macOS versions where the .focused + // method doesn't work properly. See the dispatch of this notification + // for more information. + if #available(macOS 13, *) { return } + + DispatchQueue.main.async { + surfaceFocus = true + } + } .onAppear() { // Welcome to the SwiftUI bug house of horrors. On macOS 12 (at least // 12.5.1, didn't test other versions), the order in which the view @@ -119,7 +130,7 @@ extension Ghostty { /// The view to render for the terminal surface. let view: SurfaceView - /// This should be set to true wen the surface has focus. This is up to the parent because + /// This should be set to true when the surface has focus. This is up to the parent because /// focus is also defined by window focus. It is important this is set correctly since if it is /// false then the surface will idle at almost 0% CPU. let hasFocus: Bool