Window Cascade

The Window menu of most macOS apps contains a menu item labeled Arrange in Front. It reorders, cascades, and then centers the app’s windows. This works well and most users will need nothing more.

The arrange-in-front menu item doesn’t work exactly as I want and so I wrote the script included below. It differs in the following respects:

  1. The focused window retains the focus and the windows are not centered on the screen.

  2. Cascaded windows are resized to have the same size as the focused window and all windows are resized if necessary to fit vertically on the screen.

  3. The user can specify in the script the amount of window overlap and top and bottom buffers.

To test this script:

  1. Paste it into Script Editor.

  2. Open and resize several additional Script-Edtitor windows and move them to various locations on the screen.

  3. Run the script.


set topBuffer to 23 -- includes menu bar so 23 results in no top buffer
set windowOverlap to 23 -- normally should be 23 or more
set screenHeight to 1080 -- should be vertical screen resolution minus desired bottom buffer

tell application "System Events"
	tell process (name of first process whose frontmost is true)
		
		set windowCount to count windows
		
		if windowCount < 2 then error number -128
		
		set {x, y} to position of window 1
		set {w, h} to size of window 1
		
		set requiredSpace to ((windowCount - 1) * windowOverlap) + topBuffer
		
		if y < requiredSpace then
			set y to requiredSpace
			set position of window 1 to {x, y}
		end if
		
		if h > (screenHeight - y) then
			set h to screenHeight - y
			set size of window 1 to {w, h}
		end if
		
		repeat with i from 2 to windowCount
			set {x, y} to {x - windowOverlap, y - windowOverlap}
			set position of window i to {x, y}
			set size of window i to {w, h}
		end repeat
		
	end tell
end tell

One thing to keep in mind: process names are not necessarily the same as application names.

Thanks Shane. I haven’t encountered that, but there’s a great many apps I’ve never used. To avoid this, I’ll modify my script to take the following approach:

tell application "System Events"
tell process (name of first process whose frontmost is true)

It’s a bit slower but should avoid any issues with process names.