Tony Finch - Keyboard shortcuts for positioning windows in Mac OS X

dotatfanf wrote
on 30th July 2010 at 02:41
Previous Entry Add to Memories Share Next Entry

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:

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 Terminal.app you end up
-- trying to move osascript's windows not Terminal.app's, and that fails.
tell application "System Events"
	set myFrontMost to name of first item of (processes whose frontmost is true)
end tell

try
	tell application myFrontMost
		if resizable of front window then
			set bounds of front window to {Xmin, Ymin, Xmax, Ymax}
		else
			-- 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 Preview.app
	-- 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

(Leave a comment)
From:ronebofh
Date:2010-07-30 02:08 (UTC)
(Link)
Can you tell me how to remap Cmd-Q to nothing and Cmd-Shift-Q to quit in Firefox? I fatfinger Cmd-W and Cmd-A all the time and quit my browser.
(Reply) (Thread)
From:fanf
Date:2010-07-30 11:17 (UTC)
(Link)
A bit of experimentation reveals that any Application Shortcuts you set through the Keyboard Preferences pane override the application's default shortcuts. So you can just add a Firefox-specific shortcut for the menu item "Quit Firefox" and set it to ⌥⌘Q or whatever. I don't think you can globally rebind Quit in one go since each app puts its name in its quit menu item. Note that ⇧⌘Q is bound to Log Out by default.
(Reply) (Parent) (Thread)
From:ronebofh
Date:2010-07-30 11:39 (UTC)
(Link)
No dice; after setting ⌘Q to About Mozilla Firefox and ⌥⌘Q to Quit (and the change is visible in the Firefox menu), ⌘Q still quits the browser.
(Reply) (Parent) (Thread)
From:fanf
Date:2010-07-30 12:19 (UTC)
(Link)
Hmm, I tested with Google Chrome and it also works with Safari but not with Firefox. This is clearly a bug in Firefox.
(Reply) (Parent) (Thread)
From:ronebofh
Date:2010-07-30 12:22 (UTC)
(Link)
See icon.
(Reply) (Parent) (Thread)
From:fanf
Date:2010-07-30 12:30 (UTC)
(Link)
(Reply) (Parent) (Thread)
From:coordinatedorg
Date:2010-07-30 11:46 (UTC)

Overriding CMD-Q for Firefox

(Link)
Unfortunately, that's never worked for me (FF3.6.8 on OS-X 10.6.4).
I have 'Quit Firefox' bound to SHIFT-CTRL-ALT-CMD-Q!
Firefox ignores the OS-X keyboard preferences, and still intercepts CMD-Q.

I've misplaced my bookmark to the relevant Bugzilla ID, but I believe this is a known problem and part of a wider-scale issue with Firefox's keyboard handling on OS-X.

Hoping this is fixed in FF4, but haven't tested whether this is fixed in FF4b yet...

Best wishes,
Steve
(Reply) (Parent) (Thread)
From:fanf
Date:2010-07-30 12:50 (UTC)

Re: Overriding CMD-Q for Firefox

(Link)
Looks like the relevant bug is https://bugzilla.mozilla.org/show_bug.cgi?id=429824
(Reply) (Parent) (Thread)
From:coordinatedorg
Date:2010-07-30 12:52 (UTC)
(Link)
Cool. I've been using similar AppleScript with iTerm's
Library/Application\ Support/iTerm/AutoLaunch.scpt
to do similar things (open multiple SSH sessions in multiple tabs in multiple windows in different Spaces).
[Note to self: share this code soon!]

I also like MercuryMover for general window movement/placement (which supports limited keyboard "bookmarks"):
http://www.heliumfoot.com/mercurymover/

(Reply) (Thread)
From:fanf
Date:2010-07-30 12:59 (UTC)
(Link)
For about 12 years I have had some very formulaic window positioning shortcuts in my X window manager setup. (That is, general window placement usually isn't what I want.) I'm pleased to find out that Mac OS X can do basically the same thing without add-ons :-)
(Reply) (Parent) (Thread)
From:http://www.hughes-family.org/wordpress/
Date:2010-07-31 01:04 (UTC)

Not just positioning, but layout too

(Link)
I use an applescript to layout windows into non-overlapping 2-column views, so that the screen is filled and the windows are equi-sized. Mostly I use this in Adium when I have a bunch of conversation windows open, to tile them across the screen in a sensible way. I don't have an easy way of posting this as a file right now, but here it is inline for copy/pastage:


property numCols : 2
property screenWidth : 1440
property screenHeight : 900
-- If you don't want to hard-code your screen width, because eg. you use multiple screens with differing properties at different times, then uncomment the 2 lines below, or use the 'bounds of window of desktop of application "Finder"' trick
--set screenWidth to word 3 of (do shell script "defaults read /Library/Preferences/com.apple.windowserver | grep -w Width") as number
--set screenHeight to word 3 of (do shell script "defaults read /Library/Preferences/com.apple.windowserver | grep -w Height") as number

set menubarHeight to 22

tell application "System Events"
set frontApp to name of first application process whose frontmost is true
end tell

--some apps are wacky and put the windows higher for some reason, adjust for this bug.
if (frontApp is equal to "Finder" or frontApp is equal to "Microsoft Entourage") then
set menubarHeight to 44
end if
--leave room for the Excel Toolbar
if (frontApp is equal to "Microsoft Excel") then
set menubarHeight to 55
end if

try
tell application frontApp
-- We are going to not layout any windows that are invisible or that do not have a title
set windowList to (index of windows whose visible is true and name is not "" and name is not "Contacts")
set windowCount to count of windowList

-- Special case is there's only one window
if windowCount = 1 then
set numRows to 1
set numCols to 1
else
set numRows to round (windowCount / numCols)
end if

repeat with j from 0 to numRows - 1
repeat with i from 0 to numCols - 1
-- If we've done all the windows, then just get out
if (j * numCols + i + 1) > windowCount then
exit repeat
end if
-- Get a handle to the window we might want to resize
set theWindow to item (j * numCols + i + 1) of windowList

-- resize the window
set bounds of (window index theWindow) to {¬
round (i * screenWidth / numCols), ¬
menubarHeight + (round (j * (screenHeight - menubarHeight) / numRows)), ¬
round ((i * screenWidth / numCols) + (screenWidth / numCols)), ¬
round ((menubarHeight + (round (j * (screenHeight - menubarHeight) / numRows))) + (screenHeight - menubarHeight) / numRows) ¬
}
end repeat
end repeat
end tell
on error the error_message number the error_number
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
end try
(Reply) (Thread)
From:(Anonymous)
Date:2010-09-07 11:27 (UTC)

Thanks for the tip - however its not working yet

(Link)
I'm trying to follow instructions, and everything OK except all my 'Services' menus still say "No Services Apply". Any advice?

Thanks,
Rob Cole
(Reply) (Thread)
From:fanf
Date:2010-09-07 12:37 (UTC)

Re: Thanks for the tip - however its not working yet

(Link)
I *think* (without testing) you need to go to system preferences -> keyboard -> keyboard shortcuts. Choose "services" in the left panel. Ensure the services that you want are enabled. Choose "application shortcuts" in the left panel to give services key shortcuts.
(Reply) (Parent) (Thread)

(Leave a comment)

Powered by LiveJournal.com