Merge pull request #2463 from ghostty-org/push-zynwrqnmkryv

macos: clamp window size to screen size on screen parameter changes
This commit is contained in:
Mitchell Hashimoto
2024-10-19 10:18:44 -07:00
committed by GitHub
5 changed files with 97 additions and 2 deletions

View File

@ -61,6 +61,7 @@
A59FB5CF2AE0DB50009128F3 /* InspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */; }; A59FB5CF2AE0DB50009128F3 /* InspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */; };
A59FB5D12AE0DEA7009128F3 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59FB5D02AE0DEA7009128F3 /* MetalView.swift */; }; A59FB5D12AE0DEA7009128F3 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59FB5D02AE0DEA7009128F3 /* MetalView.swift */; };
A5A1F8852A489D6800D1E8BC /* terminfo in Resources */ = {isa = PBXBuildFile; fileRef = A5A1F8842A489D6800D1E8BC /* terminfo */; }; A5A1F8852A489D6800D1E8BC /* terminfo in Resources */ = {isa = PBXBuildFile; fileRef = A5A1F8842A489D6800D1E8BC /* terminfo */; };
A5A6F72A2CC41B8900B232A5 /* Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A6F7292CC41B8700B232A5 /* Xcode.swift */; };
A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A5B30538299BEAAB0047F10C /* Assets.xcassets */; }; A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A5B30538299BEAAB0047F10C /* Assets.xcassets */; };
A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */; }; A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */; };
A5CBD0582C9F30960017A1AE /* Cursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0572C9F30860017A1AE /* Cursor.swift */; }; A5CBD0582C9F30960017A1AE /* Cursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0572C9F30860017A1AE /* Cursor.swift */; };
@ -139,6 +140,7 @@
A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorView.swift; sourceTree = "<group>"; }; A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorView.swift; sourceTree = "<group>"; };
A59FB5D02AE0DEA7009128F3 /* MetalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = "<group>"; }; A59FB5D02AE0DEA7009128F3 /* MetalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = "<group>"; };
A5A1F8842A489D6800D1E8BC /* terminfo */ = {isa = PBXFileReference; lastKnownFileType = folder; name = terminfo; path = "../zig-out/share/terminfo"; sourceTree = "<group>"; }; A5A1F8842A489D6800D1E8BC /* terminfo */ = {isa = PBXFileReference; lastKnownFileType = folder; name = terminfo; path = "../zig-out/share/terminfo"; sourceTree = "<group>"; };
A5A6F7292CC41B8700B232A5 /* Xcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Xcode.swift; sourceTree = "<group>"; };
A5B30531299BEAAA0047F10C /* Ghostty.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ghostty.app; sourceTree = BUILT_PRODUCTS_DIR; }; A5B30531299BEAAA0047F10C /* Ghostty.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ghostty.app; sourceTree = BUILT_PRODUCTS_DIR; };
A5B30538299BEAAB0047F10C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; A5B30538299BEAAB0047F10C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
A5B3053D299BEAAB0047F10C /* Ghostty.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Ghostty.entitlements; sourceTree = "<group>"; }; A5B3053D299BEAAB0047F10C /* Ghostty.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Ghostty.entitlements; sourceTree = "<group>"; };
@ -233,6 +235,7 @@
A534263D2A7DCBB000EBB7A2 /* Helpers */ = { A534263D2A7DCBB000EBB7A2 /* Helpers */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A5A6F7292CC41B8700B232A5 /* Xcode.swift */,
A5CEAFFE29C2410700646FDA /* Backport.swift */, A5CEAFFE29C2410700646FDA /* Backport.swift */,
A5333E1B2B5A1CE3008AEFF7 /* CrossKit.swift */, A5333E1B2B5A1CE3008AEFF7 /* CrossKit.swift */,
A5CBD0572C9F30860017A1AE /* Cursor.swift */, A5CBD0572C9F30860017A1AE /* Cursor.swift */,
@ -582,6 +585,7 @@
A52FFF5D2CAB4D08000C6A5B /* NSScreen+Extension.swift in Sources */, A52FFF5D2CAB4D08000C6A5B /* NSScreen+Extension.swift in Sources */,
A53426352A7DA53D00EBB7A2 /* AppDelegate.swift in Sources */, A53426352A7DA53D00EBB7A2 /* AppDelegate.swift in Sources */,
A5CBD0582C9F30960017A1AE /* Cursor.swift in Sources */, A5CBD0582C9F30960017A1AE /* Cursor.swift in Sources */,
A5A6F72A2CC41B8900B232A5 /* Xcode.swift in Sources */,
A52FFF5B2CAA54B1000C6A5B /* FullscreenMode+Extension.swift in Sources */, A52FFF5B2CAA54B1000C6A5B /* FullscreenMode+Extension.swift in Sources */,
A5333E222B5A2128008AEFF7 /* SurfaceView_AppKit.swift in Sources */, A5333E222B5A2128008AEFF7 /* SurfaceView_AppKit.swift in Sources */,
A5CDF1952AAFA19600513312 /* ConfigurationErrorsView.swift in Sources */, A5CDF1952AAFA19600513312 /* ConfigurationErrorsView.swift in Sources */,

View File

@ -57,6 +57,14 @@ class BaseTerminalController: NSWindowController,
/// Event monitor (see individual events for why) /// Event monitor (see individual events for why)
private var eventMonitor: Any? = nil private var eventMonitor: Any? = nil
/// The previous frame information from the window
private var savedFrame: SavedFrame? = nil
struct SavedFrame {
let window: NSRect
let screen: NSRect
}
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) is not supported for this view") fatalError("init(coder:) is not supported for this view")
} }
@ -80,6 +88,11 @@ class BaseTerminalController: NSWindowController,
selector: #selector(onConfirmClipboardRequest), selector: #selector(onConfirmClipboardRequest),
name: Ghostty.Notification.confirmClipboard, name: Ghostty.Notification.confirmClipboard,
object: nil) object: nil)
center.addObserver(
self,
selector: #selector(didChangeScreenParametersNotification),
name: NSApplication.didChangeScreenParametersNotification,
object: nil)
// Listen for local events that we need to know of outside of // Listen for local events that we need to know of outside of
// single surface handlers. // single surface handlers.
@ -89,6 +102,8 @@ class BaseTerminalController: NSWindowController,
} }
deinit { deinit {
NotificationCenter.default.removeObserver(self)
if let eventMonitor { if let eventMonitor {
NSEvent.removeMonitor(eventMonitor) NSEvent.removeMonitor(eventMonitor)
} }
@ -121,6 +136,57 @@ class BaseTerminalController: NSWindowController,
} }
} }
// Call this whenever the frame changes
private func windowFrameDidChange() {
// We need to update our saved frame information in case of monitor
// changes (see didChangeScreenParameters notification).
savedFrame = nil
guard let window, let screen = window.screen else { return }
savedFrame = .init(window: window.frame, screen: screen.visibleFrame)
}
// MARK: Notifications
@objc private func didChangeScreenParametersNotification(_ notification: Notification) {
// If we have a window that is visible and it is outside the bounds of the
// screen then we clamp it back to within the screen.
guard let window else { return }
guard window.isVisible else { return }
guard let screen = window.screen else { return }
let visibleFrame = screen.visibleFrame
var newFrame = window.frame
// Clamp width/height
if newFrame.size.width > visibleFrame.size.width {
newFrame.size.width = visibleFrame.size.width
}
if newFrame.size.height > visibleFrame.size.height {
newFrame.size.height = visibleFrame.size.height
}
// Ensure the window is on-screen. We only do this if the previous frame
// was also on screen. If a user explicitly wanted their window off screen
// then we let it stay that way.
x: if newFrame.origin.x < visibleFrame.origin.x {
if let savedFrame, savedFrame.window.origin.x < savedFrame.screen.origin.x {
break x;
}
newFrame.origin.x = visibleFrame.origin.x
}
y: if newFrame.origin.y < visibleFrame.origin.y {
if let savedFrame, savedFrame.window.origin.y < savedFrame.screen.origin.y {
break y;
}
newFrame.origin.y = visibleFrame.origin.y
}
// Apply the new window frame
window.setFrame(newFrame, display: true)
}
// MARK: Local Events // MARK: Local Events
private func localEventHandler(_ event: NSEvent) -> NSEvent? { private func localEventHandler(_ event: NSEvent) -> NSEvent? {
@ -371,6 +437,14 @@ class BaseTerminalController: NSWindowController,
} }
} }
func windowDidResize(_ notification: Notification) {
windowFrameDidChange()
}
func windowDidMove(_ notification: Notification) {
windowFrameDidChange()
}
// MARK: First Responder // MARK: First Responder
@IBAction func close(_ sender: Any) { @IBAction func close(_ sender: Any) {

View File

@ -358,7 +358,8 @@ class TerminalController: BaseTerminalController {
self.fixTabBar() self.fixTabBar()
} }
func windowDidMove(_ notification: Notification) { override func windowDidMove(_ notification: Notification) {
super.windowDidMove(notification)
self.fixTabBar() self.fixTabBar()
} }

View File

@ -56,7 +56,13 @@ extension Ghostty {
// same filesystem concept. // same filesystem concept.
#if os(macOS) #if os(macOS)
ghostty_config_load_default_files(cfg); ghostty_config_load_default_files(cfg);
// We only load CLI args when not running in Xcode because in Xcode we
// pass some special parameters to control the debugger.
if !isRunningInXcode() {
ghostty_config_load_cli_args(cfg); ghostty_config_load_cli_args(cfg);
}
ghostty_config_load_recursive_files(cfg); ghostty_config_load_recursive_files(cfg);
#endif #endif

View File

@ -0,0 +1,10 @@
import Foundation
/// True if we appear to be running in Xcode.
func isRunningInXcode() -> Bool {
if let _ = ProcessInfo.processInfo.environment["__XCODE_BUILT_PRODUCTS_DIR_PATHS"] {
return true
}
return false
}