wibox.drawable: Stop using weak tables

Instead of tracking all drawables that are alive, the code now only
tracks visible drawables. When a drawable is made visible it is
completely repainted. This should not cause a difference when a wibox is
initially made visible, because it has to be redrawn anyway. However,
this introduces a full repaint when a wibox is hidden and then made
visible again.

Thanks to this change, we can stop using weak tables. Visible drawables
cannot be collected and so we can keep a strong reference to them. This
allows us to get rid of the weak tables which solves various problems
involving finalizers and using objects after finalisation.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2016-10-04 21:20:55 +02:00
parent 843d0bdcf5
commit 650b01eb71

View file

@ -24,8 +24,7 @@ local matrix = require("gears.matrix")
local hierarchy = require("wibox.hierarchy") local hierarchy = require("wibox.hierarchy")
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
local drawables_draw = setmetatable({}, { __mode = 'k' }) local visible_drawables = {}
local drawables_force_complete_repaint = setmetatable({}, { __mode = 'k' })
-- Get the widget context. This should always return the same table (if -- Get the widget context. This should always return the same table (if
-- possible), so that our draw and fit caches can work efficiently. -- possible), so that our draw and fit caches can work efficiently.
@ -267,6 +266,13 @@ function drawable:set_fg(c)
end end
function drawable:_inform_visible(visible) function drawable:_inform_visible(visible)
if visible then
visible_drawables[self] = true
-- The wallpaper or widgets might have changed
self:_do_complete_repaint()
else
visible_drawables[self] = nil
end
end end
local function emit_difference(name, list, skip) local function emit_difference(name, list, skip)
@ -361,8 +367,6 @@ function drawable.new(d, widget_context_skeleton, drawable_name)
ret._need_complete_repaint = true ret._need_complete_repaint = true
ret:draw() ret:draw()
end end
drawables_draw[ret.draw] = true
drawables_force_complete_repaint[ret._do_complete_repaint] = true
-- Do a full redraw if the surface changes (the new surface has no content yet) -- Do a full redraw if the surface changes (the new surface has no content yet)
d:connect_signal("property::surface", ret._do_complete_repaint) d:connect_signal("property::surface", ret._do_complete_repaint)
@ -449,15 +453,15 @@ end
-- Redraw all drawables when the wallpaper changes -- Redraw all drawables when the wallpaper changes
capi.awesome.connect_signal("wallpaper_changed", function() capi.awesome.connect_signal("wallpaper_changed", function()
for k in pairs(drawables_force_complete_repaint) do for d in pairs(visible_drawables) do
k() d:_do_complete_repaint()
end end
end) end)
-- Give drawables a chance to react to screen changes -- Give drawables a chance to react to screen changes
local function draw_all() local function draw_all()
for k in pairs(drawables_draw) do for d in pairs(visible_drawables) do
k() d:draw()
end end
end end
screen.connect_signal("property::geometry", draw_all) screen.connect_signal("property::geometry", draw_all)