mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
fix: respect notch in MacOS non-native fullscreen mode
This patch adds top padding to respect macOS notch cutout in non-native fullscreen mode. I do not have any experience with swift & swiftui, so please let me know if there's a better way to implement this!
This commit is contained in:
@ -333,7 +333,15 @@ class BaseTerminalController: NSWindowController,
|
||||
}
|
||||
}
|
||||
|
||||
func fullscreenDidChange() {
|
||||
func fullscreenDidChange(mode: FullscreenMode, enabled: Bool) {
|
||||
NotificationCenter.default.post(
|
||||
name: Ghostty.Notification.ghosttyDidToggleFullscreen,
|
||||
object: self.window,
|
||||
userInfo: [
|
||||
Ghostty.Notification.FullscreenEnabledKey: enabled,
|
||||
Ghostty.Notification.FullscreenModeKey: mode,
|
||||
]
|
||||
)
|
||||
// For some reason focus can get lost when we change fullscreen. Regardless of
|
||||
// mode above we just move it back.
|
||||
if let focusedSurface {
|
||||
|
@ -95,8 +95,8 @@ class TerminalController: BaseTerminalController {
|
||||
}
|
||||
|
||||
|
||||
override func fullscreenDidChange() {
|
||||
super.fullscreenDidChange()
|
||||
override func fullscreenDidChange(mode: FullscreenMode, enabled: Bool) {
|
||||
super.fullscreenDidChange(mode: mode, enabled: enabled)
|
||||
|
||||
// When our fullscreen state changes, we resync our appearance because some
|
||||
// properties change when fullscreen or not.
|
||||
|
@ -269,6 +269,10 @@ extension Ghostty.Notification {
|
||||
static let ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen")
|
||||
static let FullscreenModeKey = ghosttyToggleFullscreen.rawValue
|
||||
|
||||
/// Toggle fullscreen of current window
|
||||
static let ghosttyDidToggleFullscreen = Notification.Name("com.mitchellh.ghostty.didToggleFullscreen")
|
||||
static let FullscreenEnabledKey = ghosttyDidToggleFullscreen.rawValue + ".bool"
|
||||
|
||||
/// Notification sent to toggle split maximize/unmaximize.
|
||||
static let didToggleSplitZoom = Notification.Name("com.mitchellh.ghostty.didToggleSplitZoom")
|
||||
|
||||
|
@ -49,6 +49,9 @@ extension Ghostty {
|
||||
// Maintain whether our window has focus (is key) or not
|
||||
@State private var windowFocus: Bool = true
|
||||
|
||||
// Maintain whether our window is fullscreen or not
|
||||
@State private var paddingTop: CGFloat = 0
|
||||
|
||||
// True if we're hovering over the left URL view, so we can show it on the right.
|
||||
@State private var isHoveringURLLeft: Bool = false
|
||||
|
||||
@ -70,9 +73,11 @@ extension Ghostty {
|
||||
#if canImport(AppKit)
|
||||
let pubBecomeKey = center.publisher(for: NSWindow.didBecomeKeyNotification)
|
||||
let pubResign = center.publisher(for: NSWindow.didResignKeyNotification)
|
||||
let pubFullscreen = center.publisher(for: Ghostty.Notification.ghosttyDidToggleFullscreen)
|
||||
#endif
|
||||
|
||||
Surface(view: surfaceView, size: geo.size)
|
||||
let adjustedSize = CGSize(width: geo.size.width, height: geo.size.height - paddingTop)
|
||||
Surface(view: surfaceView, size: adjustedSize)
|
||||
.focused($surfaceFocus)
|
||||
.focusedValue(\.ghosttySurfaceTitle, surfaceView.title)
|
||||
.focusedValue(\.ghosttySurfacePwd, surfaceView.pwd)
|
||||
@ -80,6 +85,19 @@ extension Ghostty {
|
||||
.focusedValue(\.ghosttySurfaceCellSize, surfaceView.cellSize)
|
||||
#if canImport(AppKit)
|
||||
.backport.pointerStyle(surfaceView.pointerStyle)
|
||||
.onReceive(pubFullscreen) { notification in
|
||||
guard let enabled = notification.userInfo?[Ghostty.Notification.FullscreenEnabledKey] as? Bool else {
|
||||
return
|
||||
}
|
||||
guard let mode = notification.userInfo?[Ghostty.Notification.FullscreenModeKey] as? FullscreenMode else {
|
||||
return
|
||||
}
|
||||
guard let window = notification.object as? NSWindow else { return }
|
||||
guard let screen = window.screen else {
|
||||
return
|
||||
}
|
||||
paddingTop = enabled && mode == FullscreenMode.nonNative ? screen.safeAreaInsets.top : 0;
|
||||
}
|
||||
.onReceive(pubBecomeKey) { notification in
|
||||
guard let window = notification.object as? NSWindow else { return }
|
||||
guard let surfaceWindow = surfaceView.window else { return }
|
||||
@ -92,6 +110,7 @@ extension Ghostty {
|
||||
windowFocus = false
|
||||
}
|
||||
}
|
||||
.padding(.top, paddingTop)
|
||||
.onDrop(of: [.fileURL], isTargeted: nil) { providers in
|
||||
providers.forEach { provider in
|
||||
_ = provider.loadObject(ofClass: URL.self) { url, _ in
|
||||
@ -125,6 +144,7 @@ extension Ghostty {
|
||||
.ghosttySurfaceView(surfaceView)
|
||||
|
||||
#if canImport(AppKit)
|
||||
|
||||
// If we are in the middle of a key sequence, then we show a visual element. We only
|
||||
// support this on macOS currently although in theory we can support mobile with keyboards!
|
||||
if !surfaceView.keySequence.isEmpty {
|
||||
|
@ -38,11 +38,11 @@ protocol FullscreenStyle {
|
||||
protocol FullscreenDelegate: AnyObject {
|
||||
/// Called whenever the fullscreen state changed. You can call isFullscreen to see
|
||||
/// the current state.
|
||||
func fullscreenDidChange()
|
||||
func fullscreenDidChange(mode: FullscreenMode, enabled: Bool)
|
||||
}
|
||||
|
||||
extension FullscreenDelegate {
|
||||
func fullscreenDidChange() {}
|
||||
func fullscreenDidChange(mode: FullscreenMode, enabled: Bool) {}
|
||||
}
|
||||
|
||||
/// The base class for fullscreen implementations, cannot be used as a FullscreenStyle on its own.
|
||||
@ -74,11 +74,11 @@ class FullscreenBase {
|
||||
}
|
||||
|
||||
@objc private func didEnterFullScreenNotification(_ notification: Notification) {
|
||||
delegate?.fullscreenDidChange()
|
||||
delegate?.fullscreenDidChange(mode: FullscreenMode.native, enabled: true)
|
||||
}
|
||||
|
||||
@objc private func didExitFullScreenNotification(_ notification: Notification) {
|
||||
delegate?.fullscreenDidChange()
|
||||
delegate?.fullscreenDidChange(mode: FullscreenMode.native, enabled: false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
|
||||
// https://github.com/ghostty-org/ghostty/issues/1996
|
||||
DispatchQueue.main.async {
|
||||
self.window.setFrame(self.fullscreenFrame(screen), display: true)
|
||||
self.delegate?.fullscreenDidChange()
|
||||
self.delegate?.fullscreenDidChange(mode: FullscreenMode.nonNative, enabled: true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
|
||||
// Notify the delegate
|
||||
self.delegate?.fullscreenDidChange()
|
||||
self.delegate?.fullscreenDidChange(mode: FullscreenMode.nonNative, enabled: false)
|
||||
}
|
||||
|
||||
private func fullscreenFrame(_ screen: NSScreen) -> NSRect {
|
||||
|
Reference in New Issue
Block a user