Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hs.menubar.new(false) appearing in system menubar? #1567

Closed
latenitefilms opened this issue Oct 3, 2017 · 7 comments
Closed

hs.menubar.new(false) appearing in system menubar? #1567

latenitefilms opened this issue Oct 3, 2017 · 7 comments

Comments

@latenitefilms
Copy link
Contributor

I have a hs.menubar "attached" to a hs.chooser, so that when I right click on the hs.chooser it pops up the menubar. I've noticed though, that ever now and again, even though I'm using hs.menubar.new(false), the menubar will appear in the system menubar. It doesn't have any text value or icon, so you'd only notice if you click up there, or if another application has something in the menubar and you notice the weird space between the icons - but it's a little... odd.

Possibly related to #1566?

@latenitefilms
Copy link
Contributor Author

latenitefilms commented Oct 5, 2017

I can reproduce this with:

-- hs.chooser Example

local inspect = require("hs.inspect")

local logger = require("hs.logger")
logger.defaultLogLevel = 'debug'
log = logger.new("chooser")

local chooser = require("hs.chooser")
local menubar = require("hs.menubar")
local mouse = require("hs.mouse")

showAChoice = true
numberOfChoices = 100000

function choicesA()
	local result = {}

	for i=1, numberOfChoices, 1 do
		table.insert(result, {
			["text"] = "Choice " .. tostring(i),
			["subText"] = "This is the subtext of choice " .. tostring(i),
			["uuid"] = tostring(i)
		})
	end

	return result
end

function choicesB()
	local result = {}

	for i=1, numberOfChoices, 1 do
		table.insert(result, {
			["text"] = "New Choice " .. tostring(i),
			["subText"] = "This is the subtext of choice " .. tostring(i),
			["uuid"] = tostring(i)
		})
	end

	return result
end

myMenubar = menubar.new(false)
	:setMenu({
       {
       	title = "Refresh",
       	fn = function()
       		log.df("Refreshing Choices.")
       		if showAChoice then
       			choices = choicesB()
       		else
       			choices = choicesA()
       		end
       		showAChoice = not showAChoice
			myChooser:refreshChoicesCallback()
       	end
       },
   })

function completionFn(value)
	log.df("completionFn value: %s", inspect(value))
end

function choicesFn(value)
	if not choices then
		choices = choicesA()
	end
	return choices
end

function rightClickFn()
	local point = mouse.getAbsolutePosition()
	myMenubar:popupMenu(point)
end

function queryChangedFn(value)
	log.df("queryChangedFn value: %s", inspect(value))
end

function showFn()
	log.df("showFn triggered.")
end

myChooser = chooser.new(completionFn)
	:choices(choicesFn)
	--:queryChangedCallback(queryChangedFn)
	:showCallback(showFn)
	:rightClickCallback(rightClickFn)
	:show()

screen shot 2017-10-05 at 5 11 45 pm

@latenitefilms
Copy link
Contributor Author

This however works fine:

-- hs.chooser Example

local inspect = require("hs.inspect")

local logger = require("hs.logger")
logger.defaultLogLevel = 'debug'
log = logger.new("chooser")

local chooser = require("hs.chooser")
local menubar = require("hs.menubar")
local mouse = require("hs.mouse")

showAChoice = true
numberOfChoices = 100000

function choicesA()
	local result = {}

	for i=1, numberOfChoices, 1 do
		table.insert(result, {
			["text"] = "Choice " .. tostring(i),
			["subText"] = "This is the subtext of choice " .. tostring(i),
			["uuid"] = tostring(i)
		})
	end

	return result
end

function choicesB()
	local result = {}

	for i=1, numberOfChoices, 1 do
		table.insert(result, {
			["text"] = "New Choice " .. tostring(i),
			["subText"] = "This is the subtext of choice " .. tostring(i),
			["uuid"] = tostring(i)
		})
	end

	return result
end

myMenubar = menubar.new()
	:setMenu({
       {
       	title = "Refresh",
       	fn = function()
       		log.df("Refreshing Choices.")
       		if showAChoice then
       			choices = choicesB()
       		else
       			choices = choicesA()
       		end
       		showAChoice = not showAChoice
			myChooser:refreshChoicesCallback()
       	end
       },
   })
   :removeFromMenuBar()

function completionFn(value)
	log.df("completionFn value: %s", inspect(value))
end

function choicesFn(value)
	if not choices then
		choices = choicesA()
	end
	return choices
end

function rightClickFn()
	local point = mouse.getAbsolutePosition()
	myMenubar:popupMenu(point)
end

function queryChangedFn(value)
	log.df("queryChangedFn value: %s", inspect(value))
end

function showFn()
	log.df("showFn triggered.")
end

myChooser = chooser.new(completionFn)
	:choices(choicesFn)
	--:queryChangedCallback(queryChangedFn)
	:showCallback(showFn)
	:rightClickCallback(rightClickFn)
	:show()

So the trick is you need to use menubar.new() and call :removeFromMenuBar() directly AFTER :setMenu().

Can anyone else reproduce?

@latenitefilms
Copy link
Contributor Author

I'm also getting an issue which each time I reload Hammerspoon, my system menubar item gets further and further away from the other icons.

I wonder if there's something funky in hs.menubar's garbage collection?

The code does have this note:

TODO: Should we keep a registry of menubar items and clean them up here? They ought to have been __gc'd by this point.

Maybe related? Any ideas @asmagill ?

screen shot 2017-10-21 at 12 07 47 pm

@asmagill
Copy link
Member

Sorry must have missed this before... FWIW I am working on a replacement for hs.menubar as part of the guitk suite that I'm hoping to move to core soon. With the new menubar module, creating a menu (unless using the legacy wrapper) is independent of creating the actual item which appears in the menubar at the top of the screen (technically its an NSStatusItem), so this particular issue should be a non-issue, hopefully soon.

@latenitefilms
Copy link
Contributor Author

To keep things tidy, I'm going to close this issue in favour of #1530.

@latenitefilms
Copy link
Contributor Author

Given #1530 is probably still a while off, I'm going to reopen this issue.

This code incorrectly shows the popup menu in the system menu bar:

menubar = hs.menubar.new(false)
menubar:setTitle("Hidden Menu")
menubar:setMenu( {
       { title = "my menu item", fn = function() print("you clicked my menu item!") end },
       { title = "-" },
       { title = "other item", fn = some_function },
       { title = "disabled item", disabled = true },
       { title = "checked item", checked = true },
   })
menubar:popupMenu(hs.mouse.getAbsolutePosition(), true)

This code works correctly:

menubar = hs.menubar.new(true)
menubar:setTitle("Hidden Menu")
menubar:setMenu( {
       { title = "my menu item", fn = function() print("you clicked my menu item!") end },
       { title = "-" },
       { title = "other item", fn = some_function },
       { title = "disabled item", disabled = true },
       { title = "checked item", checked = true },
   })
menubar:removeFromMenuBar()   
menubar:popupMenu(hs.mouse.getAbsolutePosition(), true)

Any ideas @cmsj ?

@latenitefilms latenitefilms reopened this Dec 27, 2018
asmagill added a commit to asmagill/hammerspoon that referenced this issue Aug 1, 2019
cmsj pushed a commit that referenced this issue Aug 15, 2019
@latenitefilms
Copy link
Contributor Author

I believe this issue is now fixed, so closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants