-
-
Save dmohs/78f80c16caf13edfa0a5b493525e5ade to your computer and use it in GitHub Desktop.
function setDefaultBrowser(appFileName, notify) | |
local logger = hs.logger.new('defbr', 5) | |
local app = hs.application.open('com.apple.systempreferences') | |
local axapp = hs.axuielement.applicationElement(app) | |
-- Attempt to open the menu until it successfully opens (returns true) | |
hs.timer.waitUntil(function() | |
return app:selectMenuItem({'View', 'General'}) | |
end, function() | |
print('General group opened.') | |
findPopup() | |
end) | |
function findPopup() | |
local dwbPopup = nil | |
-- Attempt to find the popup (combo box) | |
hs.timer.doUntil(function() return dwbPopup end, function() | |
axapp:elementSearch(function(msg, results) | |
if results then dwbPopup = results[1] end | |
end, function(e) | |
return e:attributeValue('AXDescription') == 'Default Web Browser popup' | |
end) | |
end) | |
hs.timer.waitUntil(function() return dwbPopup end, function() | |
print('Popup found.') | |
chooseAppFileName(dwbPopup) | |
end) | |
end | |
function chooseAppFileName(dwbPopup) | |
dwbPopup:performAction('AXShowMenu') | |
dwbPopup:elementSearch(function(msg, results) | |
local item = results[1] | |
item:performAction('AXPress') | |
notify() | |
end, function(e) | |
return e:attributeValue('AXTitle') == appFileName | |
end) | |
end | |
end |
@asmagill It would be quite useful to document the tiny chunking that elementSearch does somewhere in the docs: https://www.hammerspoon.org/docs/hs.axuielement.html#elementSearch
@asmagill, indeed, both changes improve the performance significantly. I had originally tried a timer interval of 0.1, but I removed it because it wasn't obvious that it helped and I worried that floats were not acceptable arguments. I assumed elementSearch
was expensive, but also that the page was relatively small and would be searched quickly. I suspect that both of these incorrect assumptions combined to make it feel like I wasn't getting anywhere. Your changes make this delightfully snappy!
Thank you so much for putting the time and energy into this and helping me understand it better.
Re adding details, it's hinted at in the first line of the Notes (• This method utilizes coroutines to keep Hammerspoon responsive), but you're right, it's not clear and just mentions slow when includeParents
is set. I'll give it some thought to see how best to re-word it -- I have some time coming up in the next couple of weeks that I plan to devote to Hammerspoon and will clarify it then.
Glad that it helps! I have a couple of tools I use when trying to narrow axuielement
searches and I'm hoping to provide some wiki articles showing and discussing them during the same period.
Two thoughts...
hs.timer.waitUntil
anddoUntil
only check once a second. You can add a third argument which indicates how often to run the check, e.g.hs.timer.waitUntil(function() ... end, function() ... end, 0.1)
would check every tenth a second (or as close to it as your machine's activity will allow).hs.axuielement:elementSearch
is slow. It's powerful, and needed when you really don't know where something is located, but avoid it when you can, or limit the search space by starting as close to the element as you can reasonably get with reliability because by its nature it has to iterate over all of the elements from the starting point until it finds a result.The following seemed a little snappier on my machine:
Two notes about these changes:
elementSearch
infindPopup
, don't change the check time ofhs.timer.doUntil
--elementSearch
already breaks up it's work into tiny chuncks to keep your system responsive and avoid blocking in Hammerspoon and decreasing the timer check interval slows this down even further.elementSearch
for the menu item inchooseAppFileName
is a perfectly fine use of the method because we're already on a fairly limited branch -- a single menu; it won't search outside of the menu, just to its end.