run action if no windows are active.

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

@peavine,

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. :smiley: It is worthwhile improvement. Thanks to you and to @Mocman.