Skip to content

Instantly share code, notes, and snippets.

@johnnyt
Created May 5, 2009 18:37
Show Gist options
  • Save johnnyt/107113 to your computer and use it in GitHub Desktop.
Save johnnyt/107113 to your computer and use it in GitHub Desktop.
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