Created
October 7, 2012 23:12
-
-
Save joshbetz/3849924 to your computer and use it in GitHub Desktop.
AppleScript for unfullscreening apps (only works with apps that support AppleScript)
This file contains hidden or 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
tell application "System Events" | |
repeat with p in (every process whose visible is true) | |
try | |
my setFullScreen(displayed name of p, 0, true) | |
end try | |
end repeat | |
end tell | |
(* | |
Sets the fullscreen status for either the front window or all windows of the specified, *AppleScript-enabled* application. | |
The 2nd parameter can take the following values: | |
0 … turn fullscreen OFF | |
1 … turn fullscreen ON | |
2 … toggle fullscreen | |
The 3rd parameter is used to specify whether *all* windows should be targeted. | |
Example: | |
my setFullScreen("Safari", 2, false) toggles fullscreen status of Safari's front window. | |
NOTE: | |
- ONLY works with AppleScript-enabled applications. | |
- The targeted application is also activated (also required for technical reasons). | |
- If you target *all* windows of an application, this subroutine will activate them one by one, which | |
is required for technical reasons, unfortunately. | |
This means: Whenever you target *all* windows, expect a lot of visual activity, even when | |
the fullscreen status needs no changing; activity is prolonged when fullscreen transitions | |
are involved. | |
- If the target application has a mix of fullscreen and non-fullscreen windows and the application | |
is not currently frontmost, the OS considers the first *non*-fullscreen window to | |
be the front one, even if a fullscreen window was active when the application was | |
last frontmost. | |
*) | |
on setFullScreen(appName, zeroForOffOneForOnTwoForToggle, allWindows) | |
# Get window list and count. | |
tell application appName | |
set wapp_list to windows whose visible is true | |
set wcount to count of wapp_list | |
## set wapp_names to name of windows whose visible is true | |
## log wapp_names | |
end tell | |
set MAX_TRIES to 20 # Max. number of attempts to obtain the relevant process window. | |
set toggle to zeroForOffOneForOnTwoForToggle is 2 | |
set turnOn to false | |
if not toggle then set turnOn to zeroForOffOneForOnTwoForToggle is 1 | |
if allWindows and wcount > 1 then -- Target *all* the application's windows. | |
tell application "System Events" | |
tell process appName | |
set indexOfTrueFrontWin to -1 | |
set wproc_target to missing value | |
set wproc_targetName to missing value | |
-- Loop over application windows: | |
-- Note that we have 2 extra iterations: | |
-- Index 0 to determine the index of the true front window, and count + 1 to process the true front window last. | |
repeat with i from 0 to wcount + 1 | |
## log "iteration " & i | |
if i ≠ 0 and i = indexOfTrueFrontWin then | |
## log "ignoring true front win for now: " & i | |
else | |
set ok to false | |
if i ≠ 0 then | |
set wapp_index to i | |
if i = wcount + 1 then set wapp_index to indexOfTrueFrontWin | |
set wapp_target to get item wapp_index of wapp_list | |
set wapp_targetName to get name of wapp_target -- Note: We get the name up front, as accessing the property below sometimes fails. | |
end if | |
repeat with attempt from 1 to MAX_TRIES | |
## log "looking for #" & i & ": [" & wapp_targetName & "] (" & id of wapp_target & ")" | |
# NOTE: We MUST activate the application and the specific window in case that window is in fullscreen mode. | |
# Bizzarrely, without activating both, we would not gain access to that active window's *process* window, | |
# which we need to examine and change fullscreen status. | |
if i ≠ 0 then | |
## log "making front window: " & wapp_targetName | |
set index of wapp_target to 1 -- Make the window the front (active) one; we try this *repeatedly*, as it can get ignored if a switch from a previous window hasn't completed yet. | |
end if | |
set frontmost to true -- Activate the application; we also do this repeatedly in the interest of robustness. | |
delay 0.2 -- Note: Only when the window at hand is currently in fullscreen mode are several iterations needed - presumably, because switching to that window's space takes time. | |
try | |
-- Obtain the same window as a *process* window. | |
-- Note: This can fail before switching to a fullscreen window is complete. | |
set wproc_current to front window | |
-- See if the desired process window is now active. | |
-- Note that at this point a previous, fullscreen window may still be reported as the active one, so we must | |
-- test whether the process window just obtained it is the desired one. | |
-- We test by *name* (window title), as that is the only property that the *application* | |
-- window class and the *process* window class (directly) share; sadly, only application windows | |
-- have an 'id' property. | |
-- (There is potential for making this more robust, though, by also comparing window sizes.) | |
if i = 0 then | |
-- We determine the index of the *actual* front window, so we can process it *last* | |
-- so we return to the same window that was originally active; with fullscreen windows | |
-- involved, sadly, `front window` is NOT always the true front window. | |
set indexOfTrueFrontWin to 1 | |
repeat with ndx from 1 to wcount | |
if name of (item ndx of wapp_list) is name of wproc_current then | |
set indexOfTrueFrontWin to ndx | |
exit repeat | |
end if | |
end repeat | |
## log "true front index: " & indexOfTrueFrontWin | |
set ok to true | |
exit repeat | |
else | |
if (name of wproc_current) is wapp_targetName then | |
## log "processing: [" & name of wproc_current & "]" | |
tell wproc_current | |
set isFullScreen to get value of attribute "AXFullScreen" | |
if toggle then set turnOn to not isFullScreen | |
if isFullScreen is not turnOn then | |
## log "setting fullscreen to: " & turnOn | |
set value of attribute "AXFullScreen" to turnOn | |
delay 0.3 -- For good measure; it seems turning fullscreen *on* sometimes fails (you'll hear a pop sound). | |
else | |
## log "no change needed" | |
end if | |
end tell | |
set ok to true | |
exit repeat | |
else | |
## log "no match; waiting for '" & wapp_targetName & "', actual: '" & name of wproc_current & "'" | |
end if | |
end if | |
end try | |
end repeat | |
if not ok then error "Obtaining process window '" & wapp_targetName & "' of application " & appName & " timed out." | |
end if | |
end repeat | |
end tell | |
end tell | |
else if wcount > 0 then -- Target *current* window only (if there is one). | |
tell application "System Events" | |
tell process appName | |
# NOTE: We MUST activate the application in case its active window is in fullscreen mode. | |
# Bizzarrely, without activating, we would not gain access to that active window's *process* window. | |
set frontmost to true | |
set ok to false | |
repeat with attempt from 1 to MAX_TRIES | |
delay 0.2 -- Note: Only when the active window is currently in fullscreen mode are several iterations needed - presumably, because switching to that window's space takes time. | |
try | |
-- Obtain the same window as a *process* window, as only a process window allows us to examine or | |
-- change fullscreen status. | |
tell front window -- Note: This can fail before switching to a fullscreen space is complete. | |
set isFullScreen to get value of attribute "AXFullScreen" | |
if toggle then set turnOn to not isFullScreen | |
if isFullScreen is not turnOn then | |
set value of attribute "AXFullScreen" to turnOn | |
end if | |
end tell | |
set ok to true | |
exit repeat | |
end try | |
end repeat | |
if not ok then error "Obtaining active process window of application" & appName & " timed out." | |
end tell | |
end tell | |
end if | |
end setFullScreen |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment