Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cascading in custom NSWindowController

I have a document-based application. I override NSDocument's makeWindowControllers to instantiate a custom window controller. Its initializer calls init(window: NSWindow?) of its superclass, i.e. it does not use any of the initializers that involve a nib file.

How do I make cascading work (see shouldCascadeWindows)? At the moment each window is opening in the same position on the 1st screen.

Can I somehow reuse the existing cascading logic, maybe by calling something on NSWindowController?

If I have to implement it myself manually, how should I best get the position of the top-most document window? And which of the potentially many windows of a document should be the window from which to compute the offset?

like image 462
mistercake Avatar asked Oct 28 '25 04:10

mistercake


1 Answers

func cascadeTopLeft(from topLeftPoint: NSPoint) -> NSPoint

Positions the window's top left to a given point.

Parameters

topLeftPoint The new top-left point, in screen coordinates, for the window. When NSZeroPoint, the window is not moved, except as needed to constrain to the visible screen

NSZeroPoint is the starting point for the first window.

Return Value The point shifted from top left of the window in screen coordinates.

Discussion

The returned point can be passed to a subsequent invocation of cascadeTopLeft(from:) to position the next window so the title bars of both windows are fully visible.

The returned point is the starting point for the next window.

Example (like TextEdit):

static var cascadingPoint = NSZeroPoint

override func makeWindowControllers() {
    let window = NSWindow(contentRect: NSMakeRect(100, 100, 500, 500), styleMask: .titled, backing: .buffered, defer: true)
    Document.cascadingPoint = window.cascadeTopLeft(from: Document.cascadingPoint)
    let windowController = NSWindowController(window: window)
    addWindowController(windowController)
}

Another example (like Safari)

override func makeWindowControllers() {
    let window = NSWindow(contentRect: NSMakeRect(100, 100, 500, 500), styleMask: .titled, backing: .buffered, defer: true)
    let cascadingPoint = NSApp.mainWindow?.cascadeTopLeft(from: NSZeroPoint) ?? NSZeroPoint
    window.cascadeTopLeft(from: cascadingPoint)
    let windowController = NSWindowController(window: window)
    addWindowController(windowController)
}
like image 96
Willeke Avatar answered Oct 30 '25 21:10

Willeke