asmagill / hammerspoon_asm

Hammerspoon modules in progress...
MIT License
52 stars 12 forks source link

AXSelectedChildren? #7

Closed latenitefilms closed 6 years ago

latenitefilms commented 8 years ago

I have an AXGroup that I need to select programatically. The only way I can do this is by adding a valid value to it's AXSelectedChildren property. If I do this in UI Browser via the "Edit in Window" feature it works - however I have no idea how to achieve this using code.

I've tried using the "select" command in AppleScript, but it doesn't seem to do anything - for example:

select UI element 3 of group 2 of group 1 of scroll area 2 of splitter group 1 of group 8 of splitter group 1 of window "Final Cut Pro"

I've also tried getting the value of an already selected UI element in Hammerspoon with attributeValue("AXSelectedChildren") saving it, then feeding it back in via setAttributeValue("AXSelectedChildren", previousValue) - however that doesn't seem to work either.

Any ideas how I can achieve this? Thanks in advance!

screen shot 2016-09-29 at 1 23 30 am
asmagill commented 8 years ago

Off the top of my head, copying the selected item and then re-applying it should work, if the child element in the saved value is still valid (exists)... some accessibility elements don't exist until created by some other action -- for example, in the Dock, the menu item elements for an applications Dock menu don't exist until the dock menu is first shown -- and once it goes away (is no longer shown), so do they... a future re-showing of the menu creates entirely new accessibility objects for the menu items.

According to the docks for kAXSelectedChildrenAttribute:

• kAXSelectedChildrenAttribute

Indicates the selected sub elements of a given element in the visual element hierarchy. This is a the subset of the element's kAXChildrenAttribute that are selected. This is commonly used in lists so an assistive app can know which list item are selected.

Value: A CFArrayRef of AXUIElementRefs.

Writable? Only if there is no other way to manipulate the set of selected elements via accessibilty attributes or actions. Even if other ways exist, this attribute can be writable as a convenience to assistive applications and their users. If kAXSelectedChildrenAttribute is writable, a write request with a value of an empty array should deselect all selected children.

You might see if the element you're trying to set the children for has any actions which can be performed to make the selection... whatever element/variable you're trying the attributeValue("AXSelectedChildren") method on (let's call it x for convenience here), try the following:

hs.inspect(x:actionNames())

And see if any of the names seem like they might perform the selection for you. You can perform an action by prefixing the action name with "do" (for example, if x represented a button object, you could do x:doAXPress() or x:doPress())

asmagill commented 7 years ago

I still want to see if there are any ways that axuielement can be simplified or sped up when searching for specific elements or trying to go backwards from specific element -> ... -> window when trying to locate items, so I'm going to leave this open as a reminder.

latenitefilms commented 7 years ago

FYI: In regards to the original question in the post, we actually solved this... Here's some example code for anyone else who's reading (we're obviously using a lot of private functions here - but you get the point)...

    --------------------------------------------------------------------------------
    -- Find the requested Generator:
    --------------------------------------------------------------------------------    
    local currentItemsUI = generators:currentItemsUI()
    local whichItem = nil
    for i, v in ipairs(currentItemsUI) do       
        if v:attributeValue("AXTitle") == name then
            whichItem = v
        end     
    end
    local grid = currentItemsUI[1]:attributeValue("AXParent")

    --------------------------------------------------------------------------------
    -- Select the chosen Generator:
    --------------------------------------------------------------------------------
    grid:setAttributeValue("AXSelectedChildren", {whichItem})   
    whichItem:setAttributeValue("AXFocused", true)