Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, PHP, and whatever else I happen to feel like hacking at.

Stack windows on top of each other

Jerry Stratton, March 18, 2010

I check in on the Nisus scripting forum every once in a while to see if there are any new tricks I can pick up for managing my online documents (such as my Gods & Monsters gamebooks).

On that forum, member bjast asked “How would I go about writing a macro to automatically stack all of the open windows exactly on top of each other?” Well, it turns out that Nisus macros are designed mainly for working within documents, and its window manipulation is not very extensive. But being a well-designed Mac OS X application, it also has AppleScript support. And there are standard tools for manipulating windows in AppleScript that most applications get automatically by supporting AppleScript.

[toggle code]

  • tell application "Nisus Writer Pro"
    • copy windows to windowList
    • copy the bounds of the first item of windowList to windowBounds
    • repeat with aLowerWindow in the rest of windowList
      • if aLowerWindow is visible then set the bounds of aLowerWindow to windowBounds
    • end repeat
  • end tell

This will grab the “bounds” of the focus window and set all other windows in Nisus Writer Pro to have the same bounds. They’ll all go behind the focus window (which is almost always the top-most window).

This is useful for comparing similar documents. Besides Nisus Writer Pro, it also works in AppleScript Editor, AppleWorks 6, Mail, Microsoft Word X, Safari, Smultron, and TaskPaper1.

There appears to be some sort of oddity or bug in Terminal; it sometimes works in Terminal, and sometimes it positions lower windows horizontally but not vertically.

By only setting the bounds of windows that are “visible” the script ignores hidden windows, obviously, but also docked windows. It does not ignore windows in other spaces if you use Spaces; I couldn’t find a way to distinguish them. However, it will not pull them into the current space, it will just position them in their own space to be where your document is in the current space.

To use this, you need to enable the script menu in your Mac’s menu bar. When you go to AppleScript Editor to paste the script in, check your preferences to make sure that “Show Script menu in menu bar” is checked. Then, whenever you go into an application (such as Nisus) you can choose “Open Scripts Folder” from the script menu in your menu bar. Any script you place in the application’s folder will show in that menu when you use that application.

Given that the script is useful in a variety of applications, it would be useful to be able to place it in the Scripts folder and run it for any app; but while it will then appear in every application’s script menu, there’s no way of knowing what the current application is. “tell the current application” always tells Script Runner, not the application you called it from.

August 1, 2012: AppleScript Preview in Snow Leopard and Lion

The one app that didn’t seem to support AppleScript control over window location was the one app it would have been most useful in: the built-in Preview application on Mac OS X.

It turns out, Preview does support AppleScript, but that support is turned off by default. Thanks to Trash Man at MacScripter.net for the commands that turn it back on:

  • sudo defaults write /Applications/Preview.app/Contents/Info NSAppleScriptEnabled -bool true
  • sudo chmod 644 /Applications/Preview.app/Contents/Info.plist
  • sudo codesign -f -s - /Applications/Preview.app

The first line enables AppleScripting Preview; the next two lines are necessary in Snow Leopard, Lion, and, presumably, above, because starting with Snow Leopard Mac OS X signs the built-in applications. When you change the default, that changes the signature, and Preview will fail to start because its signature doesn’t match what the OS expects. The next two lines re-sign Preview so that the OS will accept it.

If you use Leopard or earlier, you should only need the first line.

Once you enable scripting, we can stack PDFs or other documents in Preview directly on top of each other for easy comparison using command-~ document switching.

[toggle code]

  • tell application "Preview"
    • copy (every window whose visible is true and resizable is true) to windowList
    • copy the bounds of the first item of windowList to windowBounds
    • repeat with aLowerWindow in the rest of windowList
      • set the bounds of aLowerWindow to windowBounds
    • end repeat
  • end tell

Works great for comparing the differences between an original image and an optimized image, or for minor differences in the text of a PDF document.

Note that this is an improvement on the script in the earlier article. In the earlier script, if the first window happened to be an invisible or unmodifiable one, the script might end up resizing all of them to be too small to work with.

  1. I’m testing this on Snow Leopard

  1. <- All roads lead up
  2. Inkscape extension color-picker ->