Controlling Display Text Windows When Screen Not Visible

I am doing some cleanup and have a few questions in respect of the attached actions and macros.

The macros are here:

__Display Macros.kmmacros (313.3 KB)

The specific actions are here:

Summary

As a start:

  1. Attached actions appear 10 times in the macro group spread over 4 macros (as attached above).

  2. I am thinking that the macros should be placed in a separate macro or subroutine to “improve maintenance”, "improve readability", shorten the impacted macros, etc.

  3. The specific actions:
    a. Check whether the screens are visible because Keyboard Maestro cannot close a display text window when the screens are not visible.

b. If the screen are not visible then i) pauses the macro until the screens are visible and ii) pause the macro for an additional 5 seconds so the display text window is visible to the user once the screens become visible.

c. Checks whether the display text window is open because Keyboard Maestro's i) macro call will fail to close an already closed display text window and ii) generate an error message when trying to close an already closed window.

d. If the window is open then call the close display text window macro.

Question 1:

Assuming you agree that the actions should be placed in a separate macro or subroutine, should it be a macro or subroutine?

I think it is correct that the separate macro or subroutine must run synchronously to pause the calling / parent macro to avoid the calling / parent macro from spawning / trying to spawn additional display text windows when the screens are not visible as the macro will run when the screen are not visible. Is this correct / true (what happens when the calling / parent macro tries to spawn display text windows when the screens are not visible noting my experience suggest that it spawns empty display text windows)?

If the above is correct / true, then both a macro and a subroutine are possible because both can run synchronously.

The decision then hinges on the whether the AppleScript which needs the parameter Local_DisplayTextID can use %TriggerValue% in its place (i.e., if yes, then either a macro or subroutine can be used and, if n, then a subroutine must be used). What is the answer?

With the above noted, what is the correct answer (i.e., macro or subroutine) and why?

Question 2:
The last action in the group of action is an Asynchronous call to the closing macro.

When creating the new macro or subroutine, should the Asynchronous call to the closing macro be left in place or should it be replaced by the synchronous close display text window action.

With the Asynchronous call doing nothing other than closing the display text window, I am thinking it is fast, uses few resources and would not noticeably slow down the new macro / subroutine perhaps should be replaced by the close display text window action.

Would appreciate comments / thoughts as to what is best between i) leaving the Asynchronous call or ii) replacing the the Asynchronous call with the close display text window action.

Question 3:

Wondering whether there is a better way of doing this noting:

  1. I thought about replacing the multiple instances with a single pause at the start of the macros should the screen not be visible but this does not account for the situation where the screens become invisible after the macro has spawned a window.

The can happen in multiple scenarios:

a. At home: I am working at my desk, I get up to grab some food during which time a window has been spawned and the screen saver has engaged.

b, At work: I am working at my desk, a window is spawned, before its closes, I leave my desk to speak to a co-worker and look my screen when so doing.

What, if any, other ways are there?

What does the "Keyboard_Close Display Text (Keyboard Maestro)" macro do?

Apologies, I should have posted it. All it does is close the window per the below.

I don't know whether it will be helpful or not, but here is the sub-macro that I crafted during the interim (which can be easily changed should be thinking not be correct): :slight_smile:

Close Display Text.kmmacros (40.6 KB)

Look forward to your response.

Thanks.

KM can close a window when the screen is locked or the screensaver is running -- just not with the "Close Window" Action. You can do it with AppleScript:

set inst to system attribute "KMINSTANCE"
tell application "Keyboard Maestro Engine"
	set winID to (getvariable "Local_varName" instance inst) as number
	try
		close window winID
	on error
		--do nothing
	end try
end tell

Putting the command in a try block will suppress the error if the window has already been closed.

So all you actually care about is the "if nothing's showing on the screen then wait until something is, then wait another 5 seconds, then close the window" -- a completely different problem!

And because of that requirement you can use the KM Action and not waste time running the AppleScript. That is, your point 3a is irrelevant.

As written, your plan closes the window instantly if the screen is active. I'm going to assume you want to give the user time to read it so have moved the 5s pause so it happens in both cases:

Whether that's worth moving into a sub macro is debatable. You won't be doing much maintenance on this section, you can Group the Actions and close that down so it doesn't impact readability, and they don't add much to the size of the macro. And remember that there's an expense to executing a sub macro/subroutine.

It's not the only way, but it's certainly the easiest! So it makes sense to do that here.

You don't need the AppleScript at all. It just checks whether the window is there -- why do you care? Just close the window with the KM Action, setting it to neither abort nor notify on error.

Awesome and good to know.

I will put the AppleScript into my macro in lieu of the Keyboard Maestro Close Window action, much better!

I don't even care about that!

I was working on the basis that Keyboard Maestro could not close a window when the screens are not visible so what I decided to do was:

a) Check whether the screens are visible before the Close Window action.

b) If the screens are visible. then close the window. If the screens are not visible then wait until the screens are visible, display the window for 5 seconds and then close the window.

c) The displaying the window for 5 seconds was "just for fun" as there is a 60 second pause before entering the "Screensaver() + Screencount()" test which is ample time for the Display Text window to be viewed.

I was good up to this point but you may have lost me.

Is your point that I can use the Keyboard Maestro Close Window action with both a) the "Screensaver() + Screencount()" Pause Until action and iI) the Close Window action is set to neither abort nor notify on failure?

Should this be the point then I understand and, if not, then please explain!

Agreed and understood as this is the implementation of the previous section.

I created the macro inclusive of the AppleScript testing that the window exists because I have the Close Window action set to abort on failure and notify on failure to assist in making sure there were no kinks but once confirmed, I completely agree that the AppleScript testing the window can be removed!

Appreciated.

Easiest is good!

Agreed as noted above.

One follow up

I think the best, easiest, fastest and simplest way to proceed is with you below AppleScript because then there is never need to even / ever pause the macro.

If the macro spawns a Display Text window and the screen saver kicks in before the "60 second display time / pause" has been reached then so be it, the AppleScript will the close the window, no window will ever be orphaned and life goes on! Plus, theory blocks makes sure there is no error message should I close a window manually!

Comments / thoughts?

set inst to system attribute "KMINSTANCE"
tell application "Keyboard Maestro Engine"
	set winID to (getvariable "Local_varName" instance inst) as number
	try
		close window winID
	on error
		--do nothing
	end try
end tell

If you are always going to pause until the screen is "active" then there's no need to worry about "How do I close the window when the screen is "inactive". I'm pretty sure from your other responses that you got this, and my labouring the point just confused things :wink:

But the point is moot since, now you have a way, you're closing the window irrespective of screen state.

Agreed and happily so thanks to you! :joy: :folded_hands:

I have added your AppleScript that closes DisplayText windows regardless of whether the screen is / is not visible as there is little point to seeing values that were measured before the screens were not visible (plus, if you looked at my macro ⌥⌘G provides the lunar status "on demand').

One follow up: Is my understanding correct that attempts to spawn Display Text windows when the screens are not visible results in i) completed / filled Display Text windows when written to by AppleScript and ii) empty Display Text windows when written to by Keyboard Maestro?

Thank you.

Why would you think that?

It would have been quicker to test than to write out your question!

Now, whether your utility returns results that can be displayed in that dialog if the screen is locked or running the screen saver is another matter...

Agreed and apologies. I should not have been that lazy!

That said, I wrongly assumed that was the case because:

  1. Keyboard Maestro cannot close a Display Text window when the screens are not visible led me to think that it cannot write to a Display Text window when teh screens are not visible; and

  2. Prior to pausing the macro until both screens were visible, I was getting spawned Display Text windows that were empty.

And this, I think is the crux of it!

It is not a question as to whether the Display Text window can be spawn -- we know that it can -- but rather whether the Python Script that I am using can.

It is time to test this and revert back!

One Follow up: Why then when the screen are not visible, can Keyboard Maestro spawn Display Text windows but cannot close Display Text windows (via the Close Window action)? I would think they would be aligned.

Huge thanks!

@Nige_S

I have replicated your test but in a few states (i.e., lock screen, screen saver and sleep mode) and confirm that in all of these states that Keyboard Maestro can spawn and fill Display Text windows. That is there is no situation in whch it cannot spawn a Display Text window.

Why then when the screens are not visible, can Keyboard Maestro spawn Display Text windows but cannot close Display Text windows (via the Close Window action) ? I would think they would be aligned.

Presumably the system APIs it uses to close a window answer with "I can't do that, Dave" in those situations.

9 times out of 10, if KM can't do something that seems obviously doable it's because Apple says "No" in its public APIs (or simply hasn't provided a method to do it).

Appreciated and thank you.