Created
May 5, 2009 18:37
-
-
Save johnnyt/107113 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
property menubar_height : 22 | |
property fuzzy_limit : 10 -- number of pixels that the top and bottom could be off by | |
property unmaximized_window_bounds : {200, 100, 1200, 700} -- size that the unmaximized window should be (it will be places on its current monitor) | |
property apps_with_wacky_coords : {"Dragon's Lair"} | |
property apps_without_title_bars : {} | |
property apps_with_double_title_height : {"Finder", "Thunderbird"} | |
property not_working_apps : {"Thunderbird"} | |
global window_is_on_primary_monitor | |
set window_is_on_primary_monitor to true | |
global monitor_properties | |
set monitor_properties to my monitorProperties() | |
global primary_monitor_bounds | |
set primary_monitor_bounds to my bounds_from_properties(monitor1 of monitor_properties) | |
global secondary_monitor_bounds | |
global multiple_monitors | |
if monitorCount of monitor_properties is equal to 2 then | |
set multiple_monitors to true | |
set secondary_monitor_bounds to my bounds_from_properties(monitor2 of monitor_properties) | |
else | |
set multiple_monitors to false | |
set secondary_monitor_bounds to {0, 0, 0, 0} | |
end if | |
set app_name to short name of (info for (path to frontmost application)) | |
my toggle_window(app_name) | |
on toggle_window(app_name) | |
try | |
set win_to_toggle to get front window of application app_name | |
if apps_with_wacky_coords contains app_name then | |
set window_bounds to my convert_bounds(bounds of win_to_toggle) | |
else | |
set window_bounds to bounds of win_to_toggle | |
end if | |
set monitor_bounds to my get_monitor_bounds(window_bounds) | |
-- Already maximized | |
if fuzzy_match_bounds(window_bounds, monitor_bounds, (apps_with_double_title_height contains app_name)) then | |
unmaximize_window(win_to_toggle, monitor_bounds) | |
else | |
if (apps_without_title_bars contains app_name) and window_is_on_primary_monitor then | |
set item 2 of monitor_bounds to ((item 2 of monitor_bounds) - menubar_height) | |
set item 4 of monitor_bounds to ((item 4 of monitor_bounds) - menubar_height) | |
end if | |
set bounds of win_to_toggle to convert_bounds(monitor_bounds) | |
-- Some apps (e.g. MacVim) have a grid for bounds, and may need to be adjusted up a little | |
set set_bounds to bounds of win_to_toggle | |
if (apps_with_wacky_coords does not contain app_name) and (item 2 of set_bounds) is not equal to (item 2 of monitor_bounds) then | |
set item 4 of monitor_bounds to ((item 4 of monitor_bounds) - 4) | |
set bounds of win_to_toggle to monitor_bounds | |
end if | |
end if | |
on error | |
tell application "System Events" | |
--set FrontApplication to (get name of every process whose frontmost is true) as string | |
tell process app_name --FrontApplication | |
click button 2 of window 1 | |
--button 2 is the green "zoom" button for all applications | |
--window 1 is always the frontmost window. | |
end tell | |
end tell | |
end try | |
end toggle_window | |
on get_monitor_bounds(window_bounds) | |
set is_in_primary_width to my is_within(item 1 of window_bounds, {item 1 of primary_monitor_bounds, item 3 of primary_monitor_bounds}) | |
set is_in_primary_height to my is_within(item 2 of window_bounds, {item 2 of primary_monitor_bounds, item 4 of primary_monitor_bounds}) | |
-- Is on primary monitor | |
if (not multiple_monitors) or (is_in_primary_width and is_in_primary_height) then | |
return {item 1 of primary_monitor_bounds, menubar_height, item 3 of primary_monitor_bounds, item 4 of primary_monitor_bounds} | |
else | |
set window_is_on_primary_monitor to false | |
return secondary_monitor_bounds | |
end if | |
end get_monitor_bounds | |
on bounds_from_properties(monitor_props) | |
set _left to OriginX of monitor_props | |
set _top to OriginY of monitor_props | |
return {_left, _top, (_left + (width of monitor_props)), (_top + (height of monitor_props))} | |
end bounds_from_properties | |
on is_within(var, range) | |
return (var ≥ item 1 of range and var < item 2 of range) | |
end is_within | |
on convert_bounds(old_bounds) | |
set pm_height to (item 4 of primary_monitor_bounds) | |
set sm_height to (item 4 of secondary_monitor_bounds) | |
set screen_height to item 4 of primary_monitor_bounds | |
set window_height to (item 4 of old_bounds) - (item 2 of old_bounds) | |
if multiple_monitors then | |
set new_top to -(item 2 of old_bounds) + (pm_height - sm_height) | |
set new_bottom to -(item 4 of old_bounds) + (pm_height + sm_height) | |
else | |
set new_bottom to screen_height - (item 4 of old_bounds) + window_height | |
set new_top to screen_height - (item 2 of old_bounds) - window_height | |
end if | |
return {item 1 of old_bounds, new_top, item 3 of old_bounds, new_bottom} | |
end convert_bounds | |
on unmaximize_window(win_to_change, monitor_bounds) | |
set new_bounds to {0, 0, 0, 0} | |
repeat with i from 1 to 4 | |
set item i of new_bounds to (item (((i - 1) mod 2) + 1) of monitor_bounds) + (item i of unmaximized_window_bounds) | |
end repeat | |
set bounds of win_to_change to new_bounds | |
end unmaximize_window | |
on fuzzy_match_bounds(win_bounds, mon_bounds, window_has_double_title_height) | |
set win_top to item 2 of win_bounds | |
if window_has_double_title_height then set win_top to win_top - menubar_height | |
set left_matches to (item 1 of win_bounds is equal to item 1 of mon_bounds) | |
set right_matches to (is_within(item 3 of win_bounds, {((item 3 of mon_bounds) - fuzzy_limit), ((item 3 of mon_bounds) + fuzzy_limit)})) | |
set top_matches to is_within(win_top, {((item 2 of mon_bounds) - fuzzy_limit), ((item 2 of mon_bounds) + fuzzy_limit)}) | |
set bottom_matches to is_within(item 4 of win_bounds, {((item 4 of mon_bounds) - fuzzy_limit), ((item 4 of mon_bounds) + fuzzy_limit)}) | |
-- return {left_matches, right_matches, top_matches, bottom_matches} | |
return left_matches and right_matches and top_matches and bottom_matches | |
end fuzzy_match_bounds | |
on monitorProperties() | |
--system_profiler parsing | |
set SPDisplaysData to (do shell script "system_profiler SPDisplaysDataType") | |
set text item delimiters to "Displays:" | |
set SPDisplaysData to text item 3 of SPDisplaysData | |
set text item delimiters to (word 1 of SPDisplaysData) | |
copy text item 1 of SPDisplaysData to text item delimiters | |
set SPDisplaysData to text items 2 thru -1 of SPDisplaysData | |
set text item delimiters to "" | |
repeat with i from 2 to length of SPDisplaysData | |
if character 1 of item i of SPDisplaysData is not " " then | |
set display1 to items 2 thru (i - 1) of SPDisplaysData | |
set display2 to items (i + 1) thru -1 of SPDisplaysData | |
exit repeat | |
end if | |
end repeat | |
--END OF system_profiler parsing | |
set layout_values to (do shell script "displays_layout") | |
set {displayCount, output} to {1, {}} | |
repeat with curList in {display1, display2} | |
set mainDisplay to false | |
-- We have already parsed the primary monitor and are looking at the non-existent secondary monitor | |
if item 1 of curList contains "Status: No display connected" then | |
set monitorCount to 1 | |
set display2 to {width:missing value, height:missing value, OriginX:missing value, OriginY:missing value} | |
else | |
repeat with i from 1 to length of curList | |
set curItem to item i of curList | |
if curItem contains "Resolution:" then | |
set {y, x} to {word 2 of curItem, word 4 of curItem} | |
end if | |
if curItem contains "Main Display: Yes" then | |
set mainDisplay to true | |
end if | |
end repeat | |
if mainDisplay then | |
set display1 to {width:y as integer, height:x as integer, OriginX:(word 4 of layout_values) as integer, OriginY:(word 5 of layout_values) as integer} | |
else | |
set monitorCount to 2 | |
set display2 to {width:y as integer, height:x as integer, OriginX:(word 9 of layout_values) as integer, OriginY:(word 10 of layout_values) as integer} | |
end if | |
end if | |
end repeat | |
return {monitor1:display1, monitor2:display2, monitorCount:monitorCount} | |
end monitorProperties |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment