Front window of front application finder "exists" when it does not

This seems a bug to me... or certainly a somewhat annoying feature.

In the case where no windows are selected, the frontmost application is Finder. Yet even when there is no Finder window at all, much less a selected front window, the "Front window of front application exists" condition is satisfied in "If Then Else" and "Pause Until" tests. This seems like exactly the circumstance under which KM should report that the front window of the front app does not exist.

When there is a Finder window %WindowFrame%1% gives the frame of that window, even if it is not selected and minimized.

When there are no Finder windows open at all, KM reports that the front window exists. In this instance %WindowFrame%1% gives -1920,0,7040,1692, which is the span of X and Y values across all three of my monitors.

Yea Finder is a unique beast. If I need to see if the front window exists I just look to the Close Window menu item... if it's enabled it's because the front window exists, if it's not it's because there isn't one... generally speaking anyway haha.

I appreciate the suggestion! I'll give that a try!

Amusingly the Finder-related rabbit hole that I'm going down at the moment also led to a "What's up?" email to Script Debugger. There are strange differences between Script Debugger and Script Editor in how they talk to System Events. Just by repeatedly asking Script Debugger to tell System Events to get process Finder I can consistently hang System Events effectively enough to have to restart the process.

There be dragons... :wink:

Haha oh man I feel your pain. I cringe anytime I have to do anything with AppleScript and Finder… though I use Script Debugger exclusively so don’t really know about any Script Editor issues.

Actually it is a Script Debugger issue. Script Editor works fine. First time in a VERY long while that I've cranked up Script Editor to do anything but print out a dictionary!

Thanks again for the suggestion. Works like a charm.

And for completeness:

ps aux | grep "System Events" | grep -v grep | awk '{printf("kill -1 %d\n", $2)}' | sh
open "/System/Library/CoreServices/System Events.app"

:rofl:

IIRC, your Desktop is a window, albeit a rather special one -- so when you have no other Finder windows open, it's the Desktop window that is frontmost.

I think the trick is that the Desktop is the only Finder window without a title, so "title of frontmost window is empty" will be true when either no Finder windows are open or they are but not active (eg you've clicked on the Desktop).

2 Likes

@Nige_S Thanks for the suggestion, but I played with that and couldn't make it work.

While the desktop is nominally a Finder window, set w to every Finder window doesn't see it. It only sees the windows themselves. desktop window is a recognized noun, but it has no properties. Also, frontmost is a property of the process, not a window. The "frontmost window" is just the window with index 1.

If the desktop is selected and there are no Finder windows, it's easy. Finder is the frontmost process, but set w to every window followed by set n to count of w gives 0.

The difficulty is if the desktop is selected, but there are other Finder windows. set w to every window and set w to every Finder window see all of the windows (other than the desktop), but give no direct information on whether item 1 of w is the active window.

I also tried coming at it through System Events, telling process "Finder" things like set x to value of attribute 1 of item 1 of w. (Attribute 1 is "AXFocused".) The result of that one is false, regardless of whether the window is selected.

I'm not an AppleScript guru by any means, but after a fair bit of poking around (including finding difficulties with how Script Debugger talks to System Events) I couldn't make it work. If there is a way to do it I'd love to see it, if for no other reason than I'd learn something.

Cdthomer's suggestion works. This returns 1 if Finder is frontmost with the desktop selected:

# Flag the situation where the Desktop is selected.
tell application "Finder"
	set w to every Finder window
	set nWindows to count of w
end tell

tell application "System Events"
	
	set fp to every process whose frontmost is true
	if (name of item 1 of fp) ≠ "Finder" then return 0
	
	if nWindows = 0 then return 1
	
	tell process "Finder"
		set menuBar to menu bar 1
		set canClose to value of attribute "AXEnabled" of menu item "Close Window" of menu "File" of menuBar
		if canClose then return 0
		return 1
	end tell
end tell

But what I would really like to do is use pause until front window of front application exists to wait for me to select a window. I can do that by looping the code above every .3 seconds or so, then breaking out of the loop when AXEnabled is true. But it's ugly...

You look to be playing in AppleScript? I thought you were after a KM action? This displays rather than pauses, but you get the idea:

You could also use a text token and "Is empty" in the first condition.

What it doesn't handle is minimised windows, which may or may not be a problem for you.

AppleScript-wise, for me on High Sierra this

tell application "Finder"
	front window exists
end tell

...returns false when no windows are open, true otherwise (including minimised). As you say, the problem is when there's a window that isn't active. Annoyingly, while the dictionary says that "desktop window" inherits from "Finder window" (which inherits from "window"), it has no available properties. (I'm intrigued, and will carry on looking...)

But we can do a quick'n'dirty based on @cdthomer's idea. The 5 second delay is so you can test in Script Editor by hitting the run button then making Finder active:

delay 5
tell application "System Events"
	tell process "Finder"
		if enabled of menu item "Close Window" of menu "File" of menu bar 1 then
			display dialog "Window is active"
		else
			if front window exists then
				display dialog "Desktop is active, window(s) open"
			else
				display dialog "Desktop only"
			end if
		end if
	end tell
end tell

Plenty of choice, depends where you want to do this

2 Likes

@Nige_S Thanks much for the pure KM version! Brilliant!

When the KM test for the existence of the front window of the front application failed, I fell back to AppleScript to get a sense for what was going on, and kind of got pulled in by the strangeness.

I'm a Script Debugger guy. The comment about Script Editor was just a comparison I ran between the two (and found differences). And agree that the business with the desktop window is peculiar.

tell application "Finder"
	set itsThere to front window exists
end tell

As you note, doesn't do the trick. For my application I am specifically worried about whether the desktop is selected, regardless of what windows might be open.

I posted my version of @cdthomer 's suggestion above, which also works well.

Again, thanks much! But I still find it curious that Front Window of Front Application Exists doesn't catch it. :wink: It might be nice to have a "Desktop is selected" condition.

I do keep trying Script Debugger, but always fall back to Script Editor. It would probably be different if I did more AppleScripting, if I spent more time using Debugger, or if I wasn't too cheap to actually pay for it!

Yes, sorry. Stream-of-consciousness happening and I didn't refer back. This might be slightly faster than the previous as it only calls notoriously slow "System Events" if one or more windows are open:

tell application "Finder"
	if front window exists then
		tell application "System Events"
			tell process "Finder"
				if enabled of menu item "Close Window" of menu "File" of menu bar 1 then
					display dialog "Window is active"
				else
					display dialog "Desktop is active, window(s) open"
				end if
			end tell
		end tell
	else
		display dialog "Desktop only"
	end if
end tell

I've a feeling that KM is "right" in that the Desktop does exist and is a window (in the broadest sense), while AppleScript is "wrong" in that it doesn't consider "desktop window" to be a window (or even have getable properties) even while stating that it inherits from "Finder window" and, as a result from "window".

But I'm no system API programmer, so pure conjecture on my part...

Yeah. Calling System Events "notoriously slow" is a bit like calling the Pope "notoriously Catholic." While playing around with this I also managed to hang System Events repeatedly. Just telling it to grab a process twice in a row without resetting can do it. Plus you pays your money and you takes your chances with just exactly what you get back. You can get most of the properties some of the time, and some of the properties all of the time (so long as System Events doesn't catch a freight train for Sheboygan), but you are very unlikely to get all of the properties any of the time.

Script Debugger... What can I say? I have a penchant for silly coding mistakes. A real IDE made a world of difference. I wish there were something like it for JXA.

Cheers!