I would like to make an apple script to unhide the dock when there are no windows open on the desktop but I don’t know how to detect if any windows are open. New to mac and AppleScript
I am not aware of any simple method to determine if no windows are open. The following does what you want, and it worked reliably in my testing, but there may be instances when it will fail.
use framework "AppKit"
use framework "Foundation"
use scripting additions
set theWorkspace to current application's NSWorkspace's sharedWorkspace()
set openApps to theWorkspace's runningApplications()
set thePredicate to current application's NSPredicate's predicateWithFormat:"activationPolicy = 0"
set openApps to (openApps's filteredArrayUsingPredicate:thePredicate)'s valueForKey:"processIdentifier"
tell application "System Events"
repeat with anAppID in openApps
set anAppName to name of (first process whose unix id is (anAppID as integer))
tell (first process whose unix id is (anAppID as integer))
if (count windows) > 0 then
display alert "The app " & quote & anAppName & quote & " has an open window"
error number -128
end if
end tell
end repeat
set the autohide of the dock preferences to false
end tell
The following does the same thing, but it’s slower:
tell application "System Events"
set openApps to name of every process whose background only is false
repeat with anApp in openApps
tell process anApp
if (count windows) > 0 then
display alert "The app " & quote & anApp & quote & " has an open window"
error number -128
end if
end tell
end repeat
set the autohide of the dock preferences to false
end tell
Basically everything is correct. But logically speaking, the OP wants to keep track of until all windows are closed.
That is, the script should not be interrupted anyway (stay-open application). Therefore, again, an on idle handler is needed. In addition, your script will be at least 1.5 times faster with the following amendments:
use framework "AppKit"
use framework "Foundation"
use scripting additions
property thePredicate : missing value
property theWorkspace : missing value
set theWorkspace to current application's NSWorkspace's sharedWorkspace()
set thePredicate to current application's NSPredicate's predicateWithFormat:"activationPolicy = 0"
on idle
set openApps to theWorkspace's runningApplications()
set openApps to ((openApps's filteredArrayUsingPredicate:thePredicate)'s valueForKey:"processIdentifier") as list -- get list of integers directly, to not coerce later
tell application "System Events"
set noWindows to true -- set flag's start value
repeat with anAppID in openApps
tell (first process whose unix id is anAppID)
if windows is not {} then -- this exits with 1st founded window
set noWindows to false
exit repeat
end if
end tell
end repeat
if noWindows then set autohide of dock preferences to false -- if flag unchanged then...
end tell
return 1
Wouldn’t it be a lighter request to ask…
[format] if windows is {} then[/format]
Why count them?
KniazidisR. For my script to have practical value, the use of a stay-open application with idle handler certainly makes sense.
I saved your script as a stay-open application and after running it received this error message: “The variable openApps is not defined.” Also, shouldn’t openApps be set in the idle handler? Otherwise, it would seem that applications started after the stay-open application is started would not be included in openApps? Just as a test, I moved all of the code into the idle handler and it seemed to work as desired.
Yes, you are absolutely right. I updated my script. Thank you for your attention.
I ran some additional timing tests and Mockman’s suggestion (except with not) reduced the timing result by 35 milliseconds or almost 40 percent, which surprised me. It’s certainly a worthwhile change.
For several years now, I’ve made sure that count windows at least doesn’t add runtime to just windows.
I don’t know how you tested. But in Script Geek I get either the same time or slightly faster with count windows.
I tested with 3 Finder windows open and using
tell application "Finder" to (count windows) ≠ 0 -- 7 msec
and
tell application "Finder" to windows ≠ {} -- 8 msec
Following gives same results:
tell application "Finder" to (count of windows) > 0 -- 7 msec
tell application "Finder" to not (windows is {}) -- 8 msec
KniazidisR. I used Script Geek and the actual script I tested is shown below. I tried to stay as close as possible to the original scripts but still to get meaningful results. As mentioned, I was surprised by the results and surmised that doing the count in a tell statement made a difference. Or, perhaps my testing procedure is faulty.
use framework "AppKit"
use framework "Foundation"
use scripting additions
set theWorkspace to current application's NSWorkspace's sharedWorkspace()
set openApps to theWorkspace's runningApplications()
set thePredicate to current application's NSPredicate's predicateWithFormat:"activationPolicy = 0"
set openApps to (openApps's filteredArrayUsingPredicate:thePredicate)'s valueForKey:"processIdentifier"
tell application "System Events"
repeat with anAppID in openApps
tell (first process whose unix id is (anAppID as integer))
if (count windows) > 0 then -- 92 milliseconds
-- if windows is not {} then -- 53 milliseconds
exit repeat
end if
end tell
end repeat
end tell
Wow, you are right. It seems counting windows of processes takes more time then counting windows of applications… So, it is time to update my script again. It is worthwhile improvement. Thanks to you and to @Mocman.