mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-19 14:00:29 +00:00
macOS: fix window cascading (#11426)
Added test case for cascading **without moving previous window**, #11161 will follow up for more accurate cascading after this. Fixed window cascading after last pr, now we should perform cascading **after** showing the window.
This commit is contained in:
@@ -10,6 +10,61 @@ import XCTest
|
||||
final class GhosttyWindowPositionUITests: GhosttyCustomConfigCase {
|
||||
override static var runsForEachTargetApplicationUIConfiguration: Bool { false }
|
||||
|
||||
// MARK: - Cascading
|
||||
|
||||
@MainActor func testWindowCascading() async throws {
|
||||
try updateConfig(
|
||||
"""
|
||||
title = "GhosttyWindowPositionUITests"
|
||||
"""
|
||||
)
|
||||
|
||||
let app = try ghosttyApplication()
|
||||
// Suppress Restoration
|
||||
app.launchArguments += ["-NSQuitAlwaysKeepsWindows", "NO"]
|
||||
// Clean run
|
||||
app.launchEnvironment["GHOSTTY_CLEAR_USER_DEFAULTS"] = "YES"
|
||||
|
||||
app.launch() // window in the center
|
||||
|
||||
// app.menuBarItems["Window"].firstMatch.click()
|
||||
// app.menuItems["_zoomTopLeft:"].firstMatch.click()
|
||||
//
|
||||
// // wait for the animation to finish
|
||||
// try await Task.sleep(for: .seconds(0.5))
|
||||
|
||||
let window = app.windows.firstMatch
|
||||
let windowFrame = window.frame
|
||||
// XCTAssertEqual(windowFrame.minX, 0, "Window should be on the left")
|
||||
|
||||
app.typeKey("n", modifierFlags: [.command])
|
||||
|
||||
let window2 = app.windows.firstMatch
|
||||
XCTAssertTrue(window2.waitForExistence(timeout: 5), "New window should appear")
|
||||
let windowFrame2 = window2.frame
|
||||
XCTAssertNotEqual(windowFrame, windowFrame2, "New window should have moved")
|
||||
|
||||
XCTAssertEqual(windowFrame2.minX, windowFrame.minX + 30, accuracy: 5, "New window should be on the right")
|
||||
|
||||
app.typeKey("n", modifierFlags: [.command])
|
||||
|
||||
let window3 = app.windows.firstMatch
|
||||
XCTAssertTrue(window3.waitForExistence(timeout: 5), "New window should appear")
|
||||
let windowFrame3 = window3.frame
|
||||
XCTAssertNotEqual(windowFrame2, windowFrame3, "New window should have moved")
|
||||
|
||||
XCTAssertEqual(windowFrame3.minX, windowFrame2.minX + 30, accuracy: 5, "New window should be on the right")
|
||||
|
||||
app.typeKey("n", modifierFlags: [.command])
|
||||
|
||||
let window4 = app.windows.firstMatch
|
||||
XCTAssertTrue(window4.waitForExistence(timeout: 5), "New window should appear")
|
||||
let windowFrame4 = window4.frame
|
||||
XCTAssertNotEqual(windowFrame3, windowFrame4, "New window should have moved")
|
||||
|
||||
XCTAssertEqual(windowFrame4.minX, windowFrame3.minX + 30, accuracy: 5, "New window should be on the right")
|
||||
}
|
||||
|
||||
// MARK: - Restore round-trip per titlebar style
|
||||
|
||||
@MainActor func testRestoredNative() throws { try runRestoreTest(titlebarStyle: "native") }
|
||||
|
||||
@@ -200,7 +200,9 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||
if all.count > 1 {
|
||||
lastCascadePoint = window.cascadeTopLeft(from: lastCascadePoint)
|
||||
} else {
|
||||
lastCascadePoint = window.cascadeTopLeft(from: NSPoint(x: window.frame.minX, y: window.frame.maxY))
|
||||
// We assume the window frame is already correct at this point,
|
||||
// so we pass .zero to let cascade use the current frame position.
|
||||
lastCascadePoint = window.cascadeTopLeft(from: .zero)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,6 +258,8 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||
// take effect. Our best theory is there is some next-event-loop-tick logic
|
||||
// that Cocoa is doing that we need to be after.
|
||||
DispatchQueue.main.async {
|
||||
c.showWindow(self)
|
||||
|
||||
// Only cascade if we aren't fullscreen.
|
||||
if let window = c.window {
|
||||
if !window.styleMask.contains(.fullScreen) {
|
||||
@@ -264,8 +268,6 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||
}
|
||||
}
|
||||
|
||||
c.showWindow(self)
|
||||
|
||||
// All new_window actions force our app to be active, so that the new
|
||||
// window is focused and visible.
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
|
||||
Reference in New Issue
Block a user