From 40db0b7337359118e53ac3e3f8b8ec65dc3f24e3 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 27 Sep 2015 14:03:59 +0200 Subject: [PATCH] Make taglists garbage-collectable Similar to what the previous commit does for layoutboxes, this changes the code for the taglist so that there is only a single, global connection to the various signals and these update all taglists via weak tables. Signed-off-by: Uli Schlachter --- lib/awful/widget/taglist.lua | 70 ++++++++++++++++++++++-------------- tests/test-leaks.lua | 4 +++ 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/lib/awful/widget/taglist.lua b/lib/awful/widget/taglist.lua index 843aea380..44e6e0fc6 100644 --- a/lib/awful/widget/taglist.lua +++ b/lib/awful/widget/taglist.lua @@ -27,6 +27,8 @@ local timer = require("gears.timer") local taglist = { mt = {} } taglist.filter = {} +local instances = nil + function taglist.taglist_label(t, args) if not args then args = {} end local theme = beautiful.get() @@ -159,39 +161,53 @@ function taglist.new(screen, filter, buttons, style, update_function, base_widge local data = setmetatable({}, { __mode = 'k' }) local queued_update = {} - local u = function (s) - if s ~= screen then return end - + function w._do_taglist_update() -- Add a delayed callback for the first update. - if not queued_update[s] then + if not queued_update[screen] then timer.delayed_call(function() - taglist_update(s, w, buttons, filter, data, style, uf) - queued_update[s] = false + taglist_update(screen, w, buttons, filter, data, style, uf) + queued_update[screen] = false end) - queued_update[s] = true + queued_update[screen] = true end end - local uc = function (c) return u(c.screen) end - local ut = function (t) return u(tag.getscreen(t)) end - capi.client.connect_signal("focus", uc) - capi.client.connect_signal("unfocus", uc) - tag.attached_connect_signal(screen, "property::selected", ut) - tag.attached_connect_signal(screen, "property::icon", ut) - tag.attached_connect_signal(screen, "property::hide", ut) - tag.attached_connect_signal(screen, "property::name", ut) - tag.attached_connect_signal(screen, "property::activated", ut) - tag.attached_connect_signal(screen, "property::screen", ut) - tag.attached_connect_signal(screen, "property::index", ut) - tag.attached_connect_signal(screen, "property::urgent", ut) - capi.client.connect_signal("property::screen", function(c, old_screen) - if screen == c.screen or screen == old_screen then - u(screen) + if instances == nil then + instances = {} + local function u(s) + local i = instances[s] + if i then + for _, tlist in pairs(i) do + tlist._do_taglist_update() + end + end end - end) - capi.client.connect_signal("tagged", uc) - capi.client.connect_signal("untagged", uc) - capi.client.connect_signal("unmanage", uc) - u(screen) + local uc = function (c) return u(c.screen) end + local ut = function (t) return u(tag.getscreen(t)) end + capi.client.connect_signal("focus", uc) + capi.client.connect_signal("unfocus", uc) + tag.attached_connect_signal(screen, "property::selected", ut) + tag.attached_connect_signal(screen, "property::icon", ut) + tag.attached_connect_signal(screen, "property::hide", ut) + tag.attached_connect_signal(screen, "property::name", ut) + tag.attached_connect_signal(screen, "property::activated", ut) + tag.attached_connect_signal(screen, "property::screen", ut) + tag.attached_connect_signal(screen, "property::index", ut) + tag.attached_connect_signal(screen, "property::urgent", ut) + capi.client.connect_signal("property::screen", function(c, old_screen) + u(c.screen) + u(old_screen) + end) + capi.client.connect_signal("tagged", uc) + capi.client.connect_signal("untagged", uc) + capi.client.connect_signal("unmanage", uc) + end + w._do_taglist_update() + local list = instances[s] + if not list then + list = setmetatable({}, { __mode = "v" }) + instances[screen] = list + end + table.insert(list, w) return w end diff --git a/tests/test-leaks.lua b/tests/test-leaks.lua index df0b99cda..b7639642e 100644 --- a/tests/test-leaks.lua +++ b/tests/test-leaks.lua @@ -37,6 +37,10 @@ collectable(awful.widget.launcher({ image = cairo.ImageSurface(cairo.Format.ARGB collectable(awful.widget.prompt()) collectable(awful.widget.textclock()) collectable(awful.widget.layoutbox(1)) +function prepare_for_collect() + -- Only after doing the pending update can a taglist be GC'd. + awesome.emit_signal("refresh") +end collectable(awful.widget.taglist(1, awful.widget.taglist.filter.all)) -- And finally a full wibox