Giter VIP home page Giter VIP logo

Comments (2)

Rhys-T avatar Rhys-T commented on July 19, 2024 1

My guess is that because hs.osascript (and most other HS modules) run on the main thread, Hammerspoon is busy - essentially frozen - while the script is running, and can't respond to Accessibility messages from the System Events app. So you end up with a deadlock, until System Events times out and decides that the menu bar doesn't exist. I can think of a few possible workarounds.

Note: I don't use Bartender myself, so any Bartender-specific info below is pieced-together guesswork on my part, and might not work without modification.

Option 1: Skip Bartender, open the menu directly

Hammerspoon can open the menu for a given hs.menubar object at an arbitrary point on screen, regardless of whether the corresponding menu bar item is visible. You can even pop it up right below the cursor so you don't have to reach for it:

hs.hotkey.bind({'cmd', 'ctrl'}, 'p', function()
	proxyMenu:popupMenu(hs.mouse.absolutePosition())
end)

Option 2: Use Bartender's own hotkey system

As I understand it, Bartender has its own way of letting you set up hotkeys to show/open hidden menus. If it can track hs.menubars reliably, that might be easier than trying to control it from an hs.hotkey.

Option 3: Instead of guessing the ID, set it

I'm not sure how Bartender constructs the menu IDs, but the Item-0 part looks suspiciously like an autosaveName. Basically, every menu extra/status item has an internal name that is used to store the menu's position in the app's preferences. If the app doesn't set this name, it defaults to Item-0, Item-1, etc. If that really is what Bartender is using, you should be able to set it using the :autosaveName() method (or the second parameter to hs.menubar.new() when you first create it), and not have to care about its index:

proxyMenu:autosaveName("Proxy Menu")
hs.hotkey.bind({'cmd', 'ctrl'}, 'p', function()
	hs.osascript.applescript([[
		tell application id "com.surteesstudios.Bartender"
			activate "org.hammerspoon.Hammerspoon-Proxy Menu"
		end
	]])
end)

Option 4: hs.axuielement

For some reason, Hammerspoon doesn't deadlock when I use hs.axuielement to make it talk to its own Accessibility interface - only when I make it use AppleScript and the System Events app. So you could do something like this:

-- Get a reference to Hammerspoon itself:
local axHammerspoon = hs.axuielement.applicationElement(hs.processInfo.processID)
local proxyMenuFrame = proxyMenu:frame()
local proxyMenuID
for i, axMenuBarItem in ipairs(axHammerspoon.AXExtrasMenuBar.AXChildren) do
	-- I'm not sure if the AXMenuBarItem's AXFrame is guaranteed to be an exact match for the hs.menubar's frame(), so…
	if hs.geometry(axMenuBarItem.AXFrame).center:inside(proxyMenuFrame) then
		-- Lua's indexes are 1-based - convert to 0-based
		local proxyMenuIndex = i - 1
		-- NOTE: If you have multiple screens, and have "Displays have separate Spaces" turned on, you might need to do:
		-- 	numberOfScreens = #hs.screen.allScreens()
		-- 	proxyMenuIndex = proxyMenuIndex / numberOfScreens
		-- because each menu appears multiple times - once for each screen / menu bar.
		proxyMenuID = ("%s-Item-%d"):format(hs.processInfo.bundleID, proxyMenuIndex)
		break
	end
end
if not proxyMenuID then
	error("Couldn't find proxy menu's ID")
end
local proxyMenuActivateScript = [[
	tell application id "com.surteesstudios.Bartender"
		activate "]]..proxyMenuID..[["
	end
]]
hs.hotkey.bind({'cmd', 'ctrl'}, 'p', function()
	hs.osascript.applescript(proxyMenuActivateScript)
end)

Note that if Bartender is using the autosaveName (see option 3), and you have that set on any of your other hs.menubars, that will throw off the index that this code comes up with.


Hope this helps.

from hammerspoon.

avegetablechicken avatar avegetablechicken commented on July 19, 2024 1

Thanks a lot @Rhys-T . I tried option 3 & option 4. Both of them work perfectly!

from hammerspoon.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.