Make layoutbox kind-of garbage-collectable

Instead of connecting to the needed tag-update-signal again for every layoutbox,
this now just creates a single connection and updates all layoutboxes from here.
A new weak table is used to find the layoutboxes from these callbacks.
Additionally, layoutboxes are now per-screen unique. So even if you try to
create three layoutboxes for screen 1, the code will now always return the same
instance.

This kind-of fixes the leak test for layoutboxes. The problem is that the
default config also creates a layoutbox and adds it to a wibox. Since this is
now the same layoutbox, the test still fails. Just removing the layoutbox-part
from the default config makes this problem go away.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2015-09-27 13:19:12 +02:00
parent e9377c4808
commit 6f2e7bba25

View file

@ -18,29 +18,46 @@ local imagebox = require("wibox.widget.imagebox")
local layoutbox = { mt = {} }
local function update(w, screen, tooltip)
local boxes = nil
local function update(w, screen)
local layout = layout.getname(layout.get(screen))
tooltip:set_text(layout or "[no name]")
w._layoutbox_tooltip:set_text(layout or "[no name]")
w:set_image(layout and beautiful["layout_" .. layout])
end
local function update_from_tag(t)
local screen = tag.getscreen(t)
local w = boxes[screen]
if w then
update(w, screen)
end
end
--- Create a layoutbox widget. It draws a picture with the current layout
-- symbol of the current tag.
-- @param screen The screen number that the layout will be represented for.
-- @return An imagebox widget configured as a layoutbox.
function layoutbox.new(screen)
local screen = screen or 1
local w = imagebox()
local tooltip = tooltip({ objects = {w}, delay_show = 1 })
update(w, screen, tooltip)
local function update_on_tag_selection(t)
return update(w, tag.getscreen(t), tooltip)
-- Do we already have the update callbacks registered?
if boxes == nil then
boxes = setmetatable({}, { __mode = "v" })
tag.attached_connect_signal(nil, "property::selected", update_from_tag)
tag.attached_connect_signal(nil, "property::layout", update_from_tag)
layoutbox.boxes = boxes
end
tag.attached_connect_signal(screen, "property::selected", update_on_tag_selection)
tag.attached_connect_signal(screen, "property::layout", update_on_tag_selection)
-- Do we already have a layoutbox for this screen?
local w = boxes[screen]
if not w then
w = imagebox()
w._layoutbox_tooltip = tooltip({ objects = {w}, delay_show = 1 })
update(w, screen)
boxes[screen] = w
end
return w
end