I need to get a count of all windows per application. Every way I've tried to do this, I only get a count of windows that are assigned to the current (Mission Control) Desktop. (I'm currently running Mac OS X 10.7, so post-Spaces.) Is there any way to get a per-application count of all windows across all Desktops?
The crux of what I've tried:
tell application "System Events"
repeat with _app in (every process whose visible is true)
tell _app
log (name as string) & ": " & (count of every window)
end tell
end repeat
end tell
Note that the whose visible is true clause isn't the problem. It finds all of the appropriate processes, but once I ask the processes for windows, they only count the ones in the active Desktop.
I've tried pulling the log line out of the tell and using name of _app and count of every window of _app, but there's no difference. I've tried grabbing things other than processes from System Events, but anything useful ends up effectively being just a different way to get the same object. I've tried iterating over UI elements, but no windows show up that aren't on the current Desktop, though I do get a menubar for each application.
I'm fine with iterating across all Desktops (though not actually switching to all of them), but I can't even find a way to get a list of Desktops. This answer claims to describe how to do that, but I only ever get a single element inside every desktop. Not that there's an obvious way to get windows once you have that Desktop object anyway.
It's also worth pointing out that desktops are controlled by the Dock, and not by Mission Control. I'm not aware of any way for AppleScript to talk to the Dock, so if you know of something, then an answer or comment about that might help point me in the right direction.
Am I trying to do something impossible?
I ran your code, setting up the Applescript version to 2.4 (do that as a habit); on the first run, your code presented me with the appropriate count of all the windows per application.
This code is what I tried, and the results seem to be satisfactory. Is there something I'm not seeing?
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
tell application "System Events"
set my_list to {}
repeat with _app in (every process whose visible is true)
tell _app
log (name as string) & ": " & (count of every window)
set my_list to my_list & {name as string, count of every window}
end tell
end repeat
log my_list
end tell
As the OP is over six years old and I am unable to test under OS X 10.7, which is what was being used at that time, nonetheless, the following example AppleScript code works for me under macOS Catalina and returned the correct window count across all Desktops/Spaces, with the exception of any application that does understand the given AppleScript command and why the try and on error statements are being used.
Example AppleScript code:
tell application "System Events" to ¬
set appBundleIdentifierList to ¬
the bundle identifier of ¬
(every process whose visible is true)
repeat with appBundleIdentifier in appBundleIdentifierList
try
tell application id appBundleIdentifier to ¬
set {appName, winCount} to {name, (count windows)}
log appName & ": " & winCount
on error errorMessage
log errorMessage
end try
end repeat
Sample output on my system that has multiple Desktops/Spaces with windows of the application on all or some of the Desktops/Spaces and the window count for each is correct across all Desktops/Spaces, not just the active Desktop/Space the script was run from.
(*Safari: 6*)
(*Terminal: 2*)
(*TextEdit: 4*)
(*Script Editor: 7*)
(*Finder: 3*)
(*BBEdit: 1*)
(*Norton Secure VPN got an error: every window doesn’t understand the “count” message.*)
(*Music: 2*)
Notes:
Not all applications are AppleScript scriptable, in that some do not contain an AppleScript dictionary within their application bundle.
Since the application process cannot return the correct number of windows across all Desktops/Spaces, this method relies on the application to return the number of windows across all Desktops/Spaces.
Update:
The following example AppleScript code does the following:
Gets the bundle identifier of every process whose visible is true.
For each bundle identifier, get its name and the window count by querying the application directly. If the application understands the AppleScript command, then if goes to the next item in the appBundleIdentifierList list. If it does not understand, then the window count is calculated by the following:
Attempts to get an invisible window count as they would not show up on the Window menu of an application.
Calculates the window count by the number of windows shown on the Window menu of the application.
Failing these methods it get the window count by querying the application process, with is only accurate fo the active Desktop/Space and is included only for completeness of trying to ascertain the window count just using basic vanilla AppleScript.
Goes to the the application in the appBundleIdentifierList list.
Example AppleScript code:
set menuName to "Window"
tell application id "com.apple.systemevents" to ¬
set appBundleIdentifierList to ¬
the bundle identifier of ¬
(every process whose visible is true)
repeat with appBundleIdentifier in appBundleIdentifierList
try
tell application id appBundleIdentifier to ¬
set {appName, winCount} to {name, (count windows)}
log appName & ": " & winCount & ¬
" -- By querying the application directly."
on error
set winCount to 0
set notVisibleWindowList to {}
set errAppName to ¬
name of application id appBundleIdentifier
tell application id "com.apple.systemevents"
try
tell application process errAppName
set notVisibleWindowList to ¬
(windows whose visible is false)
if notVisibleWindowList is {} then ¬
set winCount to ¬
length of notVisibleWindowList
end tell
end try
try
set theTargetMenuItemsList to ¬
the reverse of ¬
(get name of ¬
menu items of ¬
menu menuName of ¬
menu bar item menuName of ¬
menu bar 1 of ¬
application process errAppName)
on error
set theTargetMenuItemsList to {}
end try
end tell
if theTargetMenuItemsList is not {} then
repeat with anItem in theTargetMenuItemsList
if contents of anItem is ¬
missing value then exit repeat
set winCount to winCount + 1
end repeat
log errAppName & ": " & winCount & ¬
" -- By querying the Window menu of the application process."
else
try
tell application id "com.apple.systemevents" to ¬
set winCount to ¬
(count windows of ¬
application process errAppName)
log errAppName & ": " & winCount & ¬
" -- By querying the application process. " & ¬
"May not be accurate, verify as necessary."
end try
end if
end try
end repeat
Running both versions of the example AppleScript code to show the difference in output:
First version of example AppleScript code:
(*Safari: 6*)
(*TextEdit: 4*)
(*Finder: 3*)
(*BBEdit: 1*)
(*Norton Secure VPN got an error: every window doesn’t understand the “count” message.*)
(*Music: 2*)
(*Sublime Text 2 got an error: every window doesn’t understand the “count” message.*)
(*DiskCatalogMaker got an error: every window doesn’t understand the “count” message.*)
(*Script Editor: 7*)
(*System Preferences: 2*)
(*VMware Fusion got an error: every window doesn’t understand the “count” message.*)
(*Activity Monitor got an error: every window doesn’t understand the “count” message.*)
(*Terminal: 2*)
Second version of example AppleScript code:
(*Safari: 6 -- By querying the application directly.*)
(*TextEdit: 4 -- By querying the application directly.*)
(*Finder: 3 -- By querying the application directly.*)
(*BBEdit: 1 -- By querying the application directly.*)
(*Norton Secure VPN: 0 -- By querying the application process. May not be accurate, verify as necessary.*)
(*Music: 2 -- By querying the application directly.*)
(*Sublime Text 2: 4 -- By querying the Window menu of the application process.*)
(*DiskCatalogMaker: 2 -- By querying the Window menu of the application process.*)
(*Script Editor: 7 -- By querying the application directly.*)
(*System Preferences: 2 -- By querying the application directly.*)
(*VMware Fusion: 1 -- By querying the Window menu of the application process.*)
(*Activity Monitor: 0 -- By querying the Window menu of the application process.*)
(*Terminal: 2 -- By querying the application directly.*)
As you can see even Activity Monitor, a native default macOS application, the Window menu had to be queried as the application directly didn't understand the basic count windows AppleScript command.
Although the output of the second version of the code was accurate across all Desktops/Spaces at the time it was executed, any application that has "By querying the application process. May not be accurate, verify as necessary." as part of its output only includes the window count of the active Desktop/Space it was executed form. The bottom line is using basic vanilla AppleScript there is no guarantee to get a complete accurate window count of every visible application unless all the applications at that time cen be queried directly. Querying the Window menu by its application process should also be accurate.
With that said, I think other methods may need to be used to get an accurate count.
Related
I'm a newbie in AppleScript.
I'm trying to write a short automator script that involves getting/setting window's miniaturized (or minimized for some apps apparently).
I'm totally lost at the point: Why the first attempt works but not the second one in the following codes?
# Run this, and switch to Google Chrome, within 3 seconds
delay 3
# This works
tell application "/Applications/Google Chrome.app/"
log (get minimized of first window)
end tell
tell application "System Events"
set process_bid to get the bundle identifier of (first application process whose frontmost is true)
set application_name to file of (application processes where bundle identifier is process_bid)
end tell
set front_app to POSIX path of (application_name as string)
# They're same
log (front_app = "/Applications/Google Chrome.app/")
# Then why is this not working?
tell application front_app
log (get minimized of first window)
end tell
The argument of tell application must be a literal (a constant) because the terminology of the application inside the tell block is evaluated at compile time.
You could add a using terms from block, then the argument of tell application can be a variable. But this requires the argument of the block to be a constant.
# Run this, and switch to Google Chrome, within 3 seconds
delay 3
# This works
tell application id "com.google.Chrome" to log (get minimized of first window)
tell application "System Events"
set process_bid to bundle identifier of (1st process whose frontmost is true)
end tell
# They're same
log (process_bid = "com.google.Chrome")
log (run script ("tell application id \"" & process_bid & "\" to minimized of window 1"))
Another (simple) example for testing:
set process_bid to "com.google.Chrome"
run script ("tell application id \"" & process_bid & "\" to minimized of window 1")
I'm trying to understand code belong, and can't find anything explain what means "tab group 1"..
And I don't know how to debug to find the value with "tab group 1"
Btw, I test "tab group 0",its ok, but "tab group 2" its error..
set devices to {}
tell application "System Preferences"
reveal pane "声音"
end tell
tell application "System Events"
tell application process "System Preferences"
repeat until exists window "声音"
end repeat
tell tab group 1 of window "声音"
get properties
click radio button "输出"
tell table 1 of scroll area 1
set selected_row to (first UI element whose selected is true)
set currentOutput to value of text field 1 of selected_row as text
repeat with r in rows
try
set deviceName to value of text field 1 of r as text
set end of devices to deviceName
end try
end repeat
end tell
end tell
end tell
end tell
if application "System Preferences" is running then
tell application "System Preferences" to quit
end if
set text item delimiters to "‡"
set devicesStr to devices as text
set comm to "bash ./main.sh" & " \"" & devicesStr & "\"" & " \"" & currentOutput & "\"" & " output"
log comm
#do shell script comm
AppleScript GUI scripting involves working its way down through the view hierarchy of the application's windows. In this case, 'Tab Group [X]' means that there are at least [X] tab groups within the container at that level of the hierarchy, and you need to determine which one contains the lower-level element you're trying to access. Unfortunately, the elements of the view hierarchy aren't always immediately visible (there may be 'hidden' containers and such), and the hierarchy may change significantly from one app update to the next. That can be headache inducing.
You can debug this manually (with a little patience) by working your way down the hierarchy yourself until you find the elements you need, using a series of every UI element of.. commands. I.e., begin with:
tell application "System Events"
tell application process "System Preferences"
tell window "声音"
get every UI element
end tell
end tell
end tell
Then choose a likely UI element from the list it produces and add a new tell block. However, it's easier to use the Accessibility Inspector app, which gives you a look into the details of any applications view hierarchy. Accessibility Inspector is included with Xcode downloads (which is free, and worth having around); I don't know if there's a place to download it separately.
See Apple's Guide of Testing Accessibility.
What I try to do:
When I'm in one of my text editors (TextEdit, Byword, FoldingText) I want this AppleScript to display the file path.
I figured asking for the frontmost window app get's me the apps name nice and easily and then I can ask for the POSIX path in the next step.
The Problem:
The script is already 99% there, but I'm missing something. When I try to use the variable of activeApp it doesn't work and I get this error:
Error Number:System Events got an error: Can’t get application {"TextEdit"}.
-1728
Here's the script:
tell application "System Events"
set activeApp to name of application processes whose frontmost is true
--This doesn't work either:
--do shell script "php -r 'echo urldecode(\"" & activeApp & "\");'"
tell application activeApp
set myPath to POSIX path of (get file of front document)
end tell
display dialog myPath
end tell
If I exchange activeApp with "TextEdit" everything works. Help would be appreciated.
Maybe there's something in here that helps: Get process name from application name and vice versa, using Applescript
Either get the path property of a document or use System Events to get value of attribute "AXDocument":
try
tell application (path to frontmost application as text)
(path of document 1) as text
end tell
on error
try
tell application "System Events" to tell (process 1 where frontmost is true)
value of attribute "AXDocument" of window 1
end tell
do shell script "x=" & quoted form of result & "
x=${x/#file:\\/\\/}
x=${x/#localhost} # 10.8 and earlier
printf ${x//%/\\\\x}"
end try
end try
The first method didn't work with Preview, TextMate 2, Sublime Text, or iChm, and the second method didn't work with Acorn. The second method requires access for assistive devices to be enabled.
You are asking for...
set activeApp to name of application processes whose frontmost is true
Notice "processes", that's plural meaning you can get several processes in response so applescript gives you a list of names. Even though only one application is returned it's still in list format. Also see that your error contains {"TextEdit"}. The brackets around the name mean it's a list, so the error is showing you the problem.
You can't pass a list of names to the next line of code. As such you have a couple of choices. 1) you can ask for only 1 process instead of all processes. That will return a string instead of a list. Try this code...
set activeApp to name of first application process whose frontmost is true
2) you can work with the list by using "item 1 of the list". Try this code...
set activeApps to name of application processes whose frontmost is true
set activeApp to item 1 of activeApps
Finally, you shouldn't be telling system events to tell the application. Separate those 2 tell blocks of code. Here's how I would write your code.
tell application "System Events"
set activeApp to name of first application process whose frontmost is true
end tell
try
tell application activeApp
set myPath to POSIX path of (get file of front document)
end tell
tell me
activate
display dialog myPath
end tell
on error theError number errorNumber
tell me
activate
display dialog "There was an error: " & (errorNumber as text) & return & return & theError buttons {"OK"} default button 1 with icon stop
end tell
end try
I can't promise the "get file of front document" code will work. That depends on the application. Not all applications will understand that request. That's why I used a try block. In any case though you can be certain you are addressing the proper application. Good luck.
I've been using this snippet for a while, seems to work for all Cocoa apps (not sure about X11):
set front_app to (path to frontmost application as Unicode text)
tell application front_app
-- Your code here
end tell
None of this seems to work with a compiled AppleScript saved as an application and placed on the Dock. Whenever you run the application, IT is the frontmost, not the application that is showing its front window. That application becomes inactive as my Applescript runs. How do I write an Applescript application that isn't active when it runs?
I may have found a solution to the problem listed above. Just tell the user to reactivate the desired application, and give them time.
tell application "Finder"
activate
say "Click front window of your application"
delay 5
set myapp to get name of first application process whose frontmost is true
-- etc.
-- your code
end tell
I'm trying to different events depending on what application is currently the "open" application - The one which is foremost of the screen. I have managed to save the name of the application using a variable. Using this code.
tell application "System Events"
item 1 of (get name of processes whose frontmost is true)
set openWindow to (get name of processes whose frontmost is true)
do shell script "echo " & openWindow & " > /Users/name/temp/currentWindow.txt"
end tell
I then tried to use this code do different events for each open application
tell application "System Events"
if openWindow = "AppleScript Editor" then
display dialog "my variable: " & openWindow
end if
end tell
However this code does not apper to do anything, I don't have any error messages or anything however the code doesn't display the dialog box. If I place the code for the dialog box in the first section of code it will display the name of the open application.
Any ideas on how to get this to work, it would be very helpful
To explain your problem, it's because of this code...
set openWindow to (get name of processes whose frontmost is true)
That code returns a list of items. Notice you asked for processes (plural), so you can get more than one so applescript gives it to you as a list whether there's one or more items found. What's strange is that in the line above this you do ask for "item 1" of the list but for some reason you don't do anything with that line of code. Normally I would write that line of code like this so I only get item 1...
set openWindow to name of first process whose frontmost is true
Anyway, you can't compare the string "AppleScript Editor" to a list {"AppleScript Editor"}. They are not equal so your if statement is never true.
Display dialog displays a string. So when you move that code outside the if statement, applescript is smart enough to convert your list into a string so it can be displayed.
So bottom line is you are getting a list and you must access the items of the list. The items are strings so get one (in your case you want item 1) and use that in the if statement.
Hopefully you can learn from this explanation. Good luck.
In the first script cast the openWindow variable to a string:
set openWindow to (get name of processes whose frontmost is true) as string
There doesn't seem to be any information on this in the official Apple documentation. How do you make an application use Lion's new fullscreen feature via AppleScript?
Not only is it not documented, but the behavior is downright byzantine.
The following applies to Mountain Lion (as of 10.8.1), but I suspect it applies to Lion equally.
The short of it:
You can only examine a fullscreen window's state if it is the active window of the frontmost application. Thus, you must first activate any window you want to examine.
If that window is indeed currently in fullscreen mode but not the active one, activating will take some time - the duration of the transition animation - only after which the window is accessible programmatically.
As long as you're only interested in the active (front) window of the active (frontmost) application, everything's dandy; you're in for pain otherwise.
Below are scripts that do the following:
Indicate if the active window in the active (frontmost) application is in fullscreen mode.
Toggle fullscreen status of the active window in the active application.
Indicate if a specifiable application has any fullscreen windows.
A general-purpose fullscreen-management script that can target a specifiable application; this is much more complex than it should have to be.
Finally, there's some additional background information at the end - great fun.
Note that the scripts below require access for assistive devices to be enabled via System Preferences > Accessibility, or via the following command: tell application "System Events" to set UI elements enabled to true; administrative privileges are required.
Indicates if the active window in the active (frontmost) application is in fullscreen mode
(*
Indicates if the active window of the active application is currently in fullscreen mode.
Fails silently in case of error and returns false.
*)
on isFullScreen()
tell application "System Events"
try
tell front window of (first process whose frontmost is true)
return get value of attribute "AXFullScreen"
end tell
end try
end tell
return false
end isFullScreen
Toggles fullscreen status of the active window in the active application
(*
Toggles fullscreen status of the active window of the active application.
Return value indicates if the window is in fullscreen mode *after* toggling.
Fails silently in case of error, e.g., if the active application doesn't support fullscreen mode, and returns false.
*)
on toggleFullScreen()
set isFullScreenAfter to false
tell application "System Events"
try
tell front window of (first process whose frontmost is true)
set isFullScreen to get value of attribute "AXFullScreen"
set isFullScreenAfter to not isFullScreen
set value of attribute "AXFullScreen" to isFullScreenAfter
end tell
end try
end tell
return isFullScreenAfter
end toggleFullScreen
Indicates if a specifiable application has any fullscreen windows
** Note: This subroutine will only work with AppleScript-enabled applications.**
(*
Determine if the specified, *AppleScript-enabled* application currently has windows in fullscreen mode or not.
Note: Assumes that the application name is the same as the process name.
*)
on hasFullScreenWindows(appName)
-- We compare the count of visible application windows to the count of the application *process'* windows.
-- Since process windows either do not include the fullscreen windows or, if a fullscreen window
-- is active, only report that one window, a discrepancy tells us that there must be at least one fullscreen window.
set countAllWindows to count (windows of application appName whose visible is true)
tell application "System Events" to set countProcessWindows to count windows of process appName
if countAllWindows is not countProcessWindows then
set hasAny to true
else
set hasAny to false
-- The app-window count equals the process-window count.
-- We must investigate one additional case: the app may be currently frontmost and could have
-- a single window that is in fullscreen mode.
tell application "System Events"
set activeProcName to name of first process whose frontmost is true
if activeProcName is appName then
tell process appName
tell front window
set hasAny to get value of attribute "AXFullScreen"
end tell
end tell
end if
end tell
end if
return hasAny
end hasFullScreenWindows
General-purpose fullscreen-management script that can target a specifiable application
** Note: This subroutine will only work with AppleScript-enabled applications.**
(*
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
More background information:
The application windows collection - the one accessible in the context of a tell application ... block - always reports the total number of windows, whether they're in fullscreen mode or not. Unfortunately, such window objects canNOT be used to determine or set fullscreen mode - this must be done via the window objects reported by process objects in the context of the "System Events" application, as only they contain the relevant "AXFullScreen" attribute. It is important to note that the application windows collection - unlike the process windows collection - only works with applications that have AppleScript support.
Unfortunately, the window collection exposed by process objects in the context of the "System Events" application behaves strangely:
○ When an application is not frontmost or one of its NON-fullscreen windows is active, it only contains the NON-fullscreen windows
○ By contrast, when an application is frontmost and one of its fullscreen windows is active, it only ever contains that single fullscreen window, even if other windows (irrespective of whether they're fullscreen or not) exist.
○ Correlating application and process windows is tricky, because only application windows have an 'id' property; the only property the two types share directly is 'name' (i.e., the window title); both types also contains size information, though not in the same format.
○ (Also, process windows never include hidden windows, whereas the application-window collection must be filtered with whose visible is true to exclude hidden windows.)
As a result, if you want to process all windows of a given application, the basic approach is as follows:
○ Activate the application.
○ Loop over all (visible) application window objects.
○ Make each window the front window.
○ Wait for the corresponding process window to become programmatically accessible; this will take quite a while if the window activation involves a fullscreen transition.
○ Examine or change the fullscreen state of the process window (value of attribute "AXFullScreen").
If an application has only full-screen windows, AppleScript can get confused
over what the front window is: what it reports as the front window may not be
the one that is active when you activate the application with AppleScript or Cmd-tab to it.
When using activate to activate an application, a NON-fullscreen window of the target application will be activated, if there is one, even if a fullscreen window of that app was previously active.
You can, however, set the index of a fullscreen window to 1 to activate it.
if you want to toggle between fullscreen and normal mode use this hint
tell application "iTunes"
activate
tell application "System Events" to tell window "iTunes"
of application process "iTunes"
click (every button whose description contains "full screen")
end tell
end tell
You can detect full screen in Lion:
tell application "System Events"
tell process "Safari"
get value of attribute "AXFullScreen" of window 1
end tell
end tell
display dialog result as text
(from http://dougscripts.com/itunes/2011/07/detect-full-screen-mode/).
Another way to do this assuming you have not changed the default keyboard shortcut for "Enter Full Screen" is simply to have System Events invoke that shortcut (⌃⌘F). As with mklement0's wonderfully thorough answer, this requires making the relevant window active.
For instance, to toggle the full-screen state of the frontmost window in Safari, run:
tell application "Safari" to activate
tell application "System Events"
keystroke "f" using {command down, control down}
end tell
(Since the question was about Lion: I'm running macOS Sierra, but unless "Enter Full Screen" and "Exit Full Screen" are not available as menu options in Lion, I expect this would work in Lion as well. If the menu options are available in Lion but are not associated with a keyboard shortcut, it should be possible to add a shortcut under keyboard settings in System Preferences.)