Correctly Identifying GUI Elements

While trying to debug a macro, it occurred to me
that the macro may have failed, because I'm not using the correct terminology
in the macro logic.

I told the macro to "Pause until Conditions Met"
Pause Until: A Button
With This Name: Displays
Exists

system

However, the script logic failed. I'm thinking that the six
buttons at the top of the About This Mac dialogue
are not actually buttons, even though they look/act like them.

If they are not buttons, what are they called?

Hello Cappy,

Pause until A button only detect standard button, you will find the difference use Accessibility Inspector.app (/Applications/Xcode.app/Contents/Applications/Accessibility Inspector.app) as picture below:

Keyboard Maestro is superior when handling complex workflow by take advantage of macOS underneath automation structure: Apple Script (include GUI Scripting, AppleScriptObjC), Accessibility etc.

Though Keyboard Maestro also can finish some GUI job like click or find image in the screen, but these feature should use as workaround. ( Like another post you joined, if you want to switch wifi status, first you should consider user Shell Script or Apple Script, instead of ask Keyboard Maestro to click the wifi button)

2 Likes

Hey Tony,

In general you can use my Front Window Analysis Tool for System Events macro to suss out the UI structure of windows.

It's not as sophisticated as UI Browser or Script Debugger, but it's free.

In this case it doesn't work unaltered, because it can't tell the About window belongs to the "System Information" process.

I had to figure that out and then manually change the process name in the macro to produce this
examination of the window.

application Process "System Information"
   window About This Mac
      image 1
      button "System Report…"
      static text "8 GB 1067 MHz DDR3"
      static text "••••••••••••"
      button "Software Update…"
      static text "Mercury"
   static text "NVIDIA GeForce GT 330M 512 MB
      Intel HD Graphics 288 MB"
      static text "Version"
      static text "2.66 GHz Intel Core i7"
      static text "MacBook Pro (17-inch, Mid 2010)"
      static text "Processor"
      static text "Memory"
      static text "Startup Disk"
      static text "Graphics"
      static text "Serial Number"
      static text "macOS Sierra"
      static text "10.12.6"
      static text "™ and © 1983-2018 Apple Inc. All Rights Reserved."
      button "License Agreement"
      button 4
      button 5
      button 6
      toolbar 1
         group 1
            radio group 1
               radio button "Overview"
               radio button "Displays"
               radio button "Storage"
               radio button "Memory"
               radio button "Support"
               radio button "Service"

Given that information it was easy enough for me to write a UI-Scripting AppleScript to press a named radio-button in the About window and incorporate that into a macro:

Open About This Mac and Select a Given Panel.kmmacros (5.9 KB)

You can change the panel that's displayed by changing the button named in this line of the AppleScript:

tell radio button "Displays"

-Chris

1 Like

Thanks. I've created GUIs on Windows and have used inspectors too, but never on OS X.
As such, I know what a radio button is- but completely forgot about it :wink:
Even though that inspector shows the button is radio button- I didn't see any features in KM to wait until Radio Button exits, then Click on a Radio Button.

Hey Tony,

There is none.

If you want to work with radio buttons you have to use the Click at Found Image action, or use AppleScript UI-Scripting as I did above.

-Chris

1 Like

Oh no. I cant beleive the KM authors dont have Click Radio Button actions.

A Radio Button is a button, so the Press a Button action works.

Hmmm- I tried that it didn't work (see previous replies from @ccstone).
I had to do the Click on Found Image

I just tested this, and Peter is correct: KM can detect Radio Buttons.

But, they have to be on a window that KM can see, and KM can NOT see the Mac Info window shown by Apple > About This Mac.

But KM can see the System Preferences window, and so can detect Radio Buttons on it:

image
image


Questions?

Hey Peter,

Is this true in all cases where the UI elements is of type “radio button”?

I know I've tried to operate radio buttons with Keyboard Maestro in the past and had failures with some of them.

Unfortunately I can't recall a specific instance to demonstrate this now.


[EDIT 2018/08/15 19:32 CDT]

@JMichaelTX notes above that Keyboard Maestro must be able to see the window the radio button – but I'm fairly certain that was not the problem when the failures occurred.


-Chris

Hey @peternlewis,

Is it possible for you to provide a method of displaying exactly what buttons Keyboard Maestro can see?

A text-token would be sufficient (%list-available-buttons%), although some sort of name-picker UI would be nice.

-Chris

Ha ha ha, you're funny ;-). Surely @ccstone you know very well that the accessibility of controls is extremely variable from window to window and application to application.

Heck, I've seen windows with infinitely recursive accessibility controls!

So Radio Buttons are generally buttons, and its absolutely worth a try using the Press a Button action, but nothing is a guarantee.

The todo list includes an item related to selecting the button from a popup menu like the Select a Menu Item action.

2 Likes

:sunglasses:

That would save users a lot of confusion I do believe.

If it's not a priority then please consider the text-token method as an interim solution.

Using that and a Prompt with List action we could whip up a pretty effective macro in no time.

-Chris

I'm pretty sure you could whip up an AppleScript to query the accessibility of a window and list all the radio buttons faster than I could do it in Keyboard Maestro :wink:

Could be.

But I don't know how deep Keyboard Maestro looks.

If you'll give me a clue to that I'll try fooling with it.

Also:

Keyboard Maestro will let you provide a path for menu item discovery.

Is there any way to give a Press Button action a full path to the button?

-Chris

1 Like

I created this macro a while ago to identify UI elements for the purposes of AppleScripting. I position the mouse over the element I'd like to query, hold down ⟨control⟩+⟨option⟩, then tap ⟨command⟩. An AppleScript record is copied to the clipboard containing some pertinent information on the UI element

AppleScript
use application "System Events"
use framework "Foundation"
use scripting additions

property NSEvent : a reference to current application's NSEvent
property NSScreen : a reference to current application's NSScreen

-- Screen dimensions
set display to NSDeviceSize ¬
	of deviceDescription() ¬
	of item 1 ¬
	of NSScreen's screens() as record
-- Mouse position relative to bottom-left of screen
set mouseLocation to NSEvent's mouseLocation as any
-- Adjust mouse position coordinates to be relative to top-left of screen
set mouseLocation's y to (the display's height) - (mouseLocation's y)

set obj to click at the mouseLocation's {x, y}

set R to {UIObject:obj ¬
	, UIProperties:obj's properties ¬
	, UIChildren:obj's UI elements ¬
	, UIAttributes:name of obj's attributes ¬
	, UIActions:name of obj's actions}

set the clipboard to ¬
	"tell application \"System Events\" to set R to ¬
" & coerceToString(R)
--------------------------------------------------------------------------
to coerceToString(object)
	local object
	
	try
		set S to object as text
	on error E --> "Can’t make %object% into type text."
		set the text item delimiters to "Can’t make "
		set S to rest of text items of E as text
		
		set the text item delimiters to " into type text."
		set S to text items 1 thru -2 of S as text
	end try
end coerceToString

Identify UI Element.kmmacros (18.6 KB)

6 Likes

Hey @CJK,

That looks pretty useful. I'll have to play with it a bit.

-Chris

@CJK, this sounds very interesting, but I can't get it to work.
When I try it I get nothing on the clipboard.

When I run it from Script Debugger, I get this error. What am I doing wrong?

Can’t set clipboard to "tell application "System Events" to set R to >¬
{UIObject:«class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", UIProperties:{«class minW»:missing value, «class orie»:missing value, «class posn»:{2048, 44}, class:«class tbar», «class rold»:"toolbar", «class axds»:missing value, «class focu»:false, «class titl»:missing value, size:{1183, 40}, «class valL»:missing value, «class help»:missing value, «class enaB»:missing value, «class maxV»:missing value, «class role»:"AXToolbar", «class ects»:{}, «class sbrl»:missing value, «class selE»:missing value, name:missing value, «class desc»:"toolbar"}, UIChildren:{«class sgrp» 1 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", «class sgrp» 2 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", «class butT» 1 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", «class butT» 2 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", «class butT» 3 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", «class butT» 4 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", «class butT» 5 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", «class sgrp» 3 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events", «class sgrp» 4 of «class tbar» 1 of window "Identify UI Element Under Mouse.scpt" of «class pcap» "Script Debugger" of application "System Events"}, UIAttributes:{"AXOverflowButton", "AXParent", "AXChildren", "AXFocused", "AXSize", "AXRole", "AXTopLevelUIElement", "AXSelectedChildren", "AXHelp", "AXChildrenInNavigationOrder", "AXPosition", "AXWindow", "AXRoleDescription", "AXFrame"}, UIActions:{"AXShowMenu"}}".

1 Like

All the way to the bottom (except it gives up for infinite loops).

No, there is no such concept (at least, not yet, I am pondering ideas for the future).

1 Like

Hey Peter,

Cool.

@CJK's script has given me an idea that I think is going to work for virtually any UI-Element.

I've got to test some more to be reasonably sure though.

-Chris

1 Like