asmagill / hs._asm.axuielement

Accessing Accessibility Objects with Hammerspoon
33 stars 2 forks source link

Element Observers #5

Closed randomeizer closed 6 years ago

randomeizer commented 7 years ago

Hi there. I'm working with @latenitefilms on the FCPX Hacks project. We are hitting a performance issue where we are having to continually walk the whole path of element to find specific ones we are after for a particular function. Ideally, we would like to cache the axuielementObjects, but we would need to know when they are getting destroyed so we can refresh that part of the cache.

Any chance that observers are getting implemented soon? Or can we use 'hs.element' observers somehow in the meantime?

Alternately, a fast way of probing the cached axuielementObject we have to see if it's still valid would work as well. That way we could check myCache:stillExists() (or whatever) before returning it.

randomeizer commented 7 years ago

So, in lieu of an observer, I think I prefer to have a 'stillExists()' type method. Currently, I can achieve that by checking for a known 'attribute' (e.g. 'AXRole') - if it's null and it shouldn't be null, the axuielement is no longer connected.

However, it runs a bit slow, probably because there are various metatable function lookups happening. If you could add a more specific function that checked and ran faster, that would be awesome.

asmagill commented 7 years ago

both good ideas... let me see what I can do with this next week after we get the next formal release of Hammerspoon finished. Ultimately this is also a module I'd like to see added to core as well, so getting feedback and ideas about how it might actually be used and what its missing/needs improvement is helpful!

latenitefilms commented 7 years ago

Awesome. Thanks so much for all your help and support @asmagill! HUGELY APPRECIATED!

randomeizer commented 7 years ago

Thanks, great :)

asmagill commented 6 years ago

@latenitefilms and @randomeizer I've been looking at the observer functions with an eye towards working on them probably this weekend or next week, and I have a question...

The core functions for observers work by creating an observer based on an application and the callback is assigned for that observer object. Then, one or more notification-axuielement pairs (with the assumption that the axuielement is in fact an object of the specified application, or the application object if you're watching for creation notifications) are assigned to that observer. These pairs can be added or removed at will, but all will invoke the same callback. This is the simplest approach. It may be possible to create a separate dictionary in the c code (i.e. you'd never see it on the lua side) that maps an observer to a notification assigned to it which then maps to a lua function reference so that each element being watched would have its own callback. The down side is that this will be harder to code and debug (though by no means impossible, just harder).

For your expected usage, is a single callback that you have to create your own logic on the lua side to determine which of the currently assigned objects being observed triggered the callback sufficient or is a separate callback per notification instead of a separate callback per application preferable?

(In theory you could create multiple observers for the same application but assign them different notifications, thus getting the separate callbacks that way, but the down side is that each separate observer means a new addition to the Hammerspoon runloop, potentially decreasing responsiveness under a heavy load).

Thoughts or preferences? At the moment I have no idea how much of a performance difference it will make, but remember every addition to the run loop means a new set of transitions from the macOS to the Hammerspoon application to lua and back (and this applies to all timers and other callbacks as well, hence some earlier discussions -- I forget the issue numbers -- about a fundamental rewrite of eventtap that is on hold, but something I'd still like to eventually do, when I have the time to figure out what parts of eventtap are background thread safe)

latenitefilms commented 6 years ago

AMAZING! I've been hoping you might come back to this, as I think this will be a MASSIVE help to us, as basically our whole application is based around hs._asm.axuielement.

@randomeizer might have some more educated thoughts, however, I don't see any issues with having a single callback, then we just do all the processing in Lua-land?

randomeizer commented 6 years ago

This can be closed now, with the addition of axuelement:isValid() and the observer support from a while back.