Tony Finch (fanf) wrote,
Tony Finch

Keyboard shortcuts for positioning windows in Mac OS X

It took me a few false starts to work out how to create arbitrary keyboard shortcuts in Mac OS X 10.6 "Snow Leopard", so with any luck this article will make it easier for other people who want to do something similar...

The way to attach an arbitrary script to a keyboard shortcut is as follows:

  • Open and create a new "service".
  • To the left of the Automator window is a library of actions, towards the bottom of which is the "Utilities" category. Select it.
  • In the list of actions immediately to the right are interesting things like "Run Shell Script" and "Run AppleScript". Since I wanted to script the Mac layer (not the Unix layer) I double-clicked on the latter.
  • A box appears into which you can type your script. More about that below.
  • When you save your script It will appear in the "services" submenu of every application.
  • The script is saved in ~/Library/Services/Something.workflow which is a kind of .app directory. The interesting bit is the XML inside .../Contents/document.wflow
  • Also in the Services submenu is an option to open Services Preferences. Select it.
  • This takes you to the Services list on the Keyboard Shortcuts pane of System Preferences which allows you to control what appears in the services submenu. Your new service should be at the bottom of the list. Bizarrely, you can't set a keyboard shortcut for it directly on this list, so just ensure its tickybox is turned on.
  • Click the "+" button to add an application shortcut.
  • Choose "All Applications" from the list.
  • Next to "Menu Title" type in the name of your service.
  • Give it a keyboard shortcut and click "Add".
  • Your service and its keyboard shortcut will now appear in the "Application Shortcuts" list.
  • Your keyboard shortcut should also appear next to your service in the services submenu in all applications.

I tried doing something similar using the AppleScript Editor and the script menu, but for some reason the script menu is not eligible for keyboard shortcuts.

I wanted shortcuts to move a window into the left or right halves of the screen or maximize it to full screen. This is slightly less straightforward than it should be. See the comments in the following for details:

tell application "Finder"
	set screenBounds to bounds of window of desktop
	set Xmin to item 1 of screenBounds
	set Ymin to item 2 of screenBounds
	set Xmax to item 3 of screenBounds
	set Ymax to item 4 of screenBounds
	-- use the following line to move windows to the right half of the screen
	set Xmin to (Xmin + Xmax) / 2
	-- or this line to move them to the left half
	set Xmin to (Xmin + Xmax) / 2
	-- or leave them out to maximize
	set Xmid to (Xmin + Xmax) / 2
	set Ymid to (Ymin + Ymax) / 2
end tell

-- normally you should be able to just use "name of current application"
-- but when testing this using osascript in you end up
-- trying to move osascript's windows not's, and that fails.
tell application "System Events"
	set myFrontMost to name of first item of (processes whose frontmost is true)
end tell

	tell application myFrontMost
		if resizable of front window then
			set bounds of front window to {Xmin, Ymin, Xmax, Ymax}
			-- just move non-resizable windows
			-- weirdly shaped preferences windows are amusing, though :-)
			set winBounds to bounds of front window
			set wXmin to item 1 of winBounds
			set wYmin to item 2 of winBounds
			set wXmax to item 3 of winBounds
			set wYmax to item 4 of winBounds
			set w to wXmax - wXmin
			set h to wYmax - wYmin
			set bounds of front window to {Xmid - w / 2, Ymid - h / 2, Xmid + w / 2, Ymid + h / 2}
		end if
	end tell
on error
	-- the above can fail if the target application is not scriptable enough
	-- one prominent example is
	-- to solve that problem we use the GUI scripting functionality
	-- you need to go to System Preferences -> Universal Access
	-- and "enable access for assistive devices"
	tell application "System Events"
		tell process myFrontMost
			set position of front window to {Xmin, Ymin}
			set size of front window to {Xmax - Xmin, Ymax - Ymin}
		end tell
	end tell
end try
  • Post a new comment


    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.