mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
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:
@ -61,6 +61,7 @@
|
||||
A59FB5CF2AE0DB50009128F3 /* InspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */; };
|
||||
A59FB5D12AE0DEA7009128F3 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59FB5D02AE0DEA7009128F3 /* MetalView.swift */; };
|
||||
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 */; };
|
||||
A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0552C9E65A50017A1AE /* DraggableWindowView.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>"; };
|
||||
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>"; };
|
||||
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; };
|
||||
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>"; };
|
||||
@ -233,6 +235,7 @@
|
||||
A534263D2A7DCBB000EBB7A2 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A5A6F7292CC41B8700B232A5 /* Xcode.swift */,
|
||||
A5CEAFFE29C2410700646FDA /* Backport.swift */,
|
||||
A5333E1B2B5A1CE3008AEFF7 /* CrossKit.swift */,
|
||||
A5CBD0572C9F30860017A1AE /* Cursor.swift */,
|
||||
@ -582,6 +585,7 @@
|
||||
A52FFF5D2CAB4D08000C6A5B /* NSScreen+Extension.swift in Sources */,
|
||||
A53426352A7DA53D00EBB7A2 /* AppDelegate.swift in Sources */,
|
||||
A5CBD0582C9F30960017A1AE /* Cursor.swift in Sources */,
|
||||
A5A6F72A2CC41B8900B232A5 /* Xcode.swift in Sources */,
|
||||
A52FFF5B2CAA54B1000C6A5B /* FullscreenMode+Extension.swift in Sources */,
|
||||
A5333E222B5A2128008AEFF7 /* SurfaceView_AppKit.swift in Sources */,
|
||||
A5CDF1952AAFA19600513312 /* ConfigurationErrorsView.swift in Sources */,
|
||||
|
@ -57,6 +57,14 @@ class BaseTerminalController: NSWindowController,
|
||||
/// Event monitor (see individual events for why)
|
||||
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) {
|
||||
fatalError("init(coder:) is not supported for this view")
|
||||
}
|
||||
@ -80,6 +88,11 @@ class BaseTerminalController: NSWindowController,
|
||||
selector: #selector(onConfirmClipboardRequest),
|
||||
name: Ghostty.Notification.confirmClipboard,
|
||||
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
|
||||
// single surface handlers.
|
||||
@ -89,6 +102,8 @@ class BaseTerminalController: NSWindowController,
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
|
||||
if let 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
|
||||
|
||||
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
|
||||
|
||||
@IBAction func close(_ sender: Any) {
|
||||
|
@ -358,7 +358,8 @@ class TerminalController: BaseTerminalController {
|
||||
self.fixTabBar()
|
||||
}
|
||||
|
||||
func windowDidMove(_ notification: Notification) {
|
||||
override func windowDidMove(_ notification: Notification) {
|
||||
super.windowDidMove(notification)
|
||||
self.fixTabBar()
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,13 @@ extension Ghostty {
|
||||
// same filesystem concept.
|
||||
#if os(macOS)
|
||||
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_recursive_files(cfg);
|
||||
#endif
|
||||
|
||||
|
10
macos/Sources/Helpers/Xcode.swift
Normal file
10
macos/Sources/Helpers/Xcode.swift
Normal 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
|
||||
}
|
Reference in New Issue
Block a user