wibox.drawable: Support forced screens

Up to now, a drawable always figured out the screen that it is on by
looking at its position. This causes memleak-like problems with wibars:
A wibar has a screen assigned, but its underlying drawable will end up
referring to another screen. Via this, we were managing to build a long
reference chain of screens and drawable that meant that none of the fake
screens that our test suite added could be garbage collected.

To fix this, add wibox.drawable._force_screen(s). After this function is
called, the normal screen detection based on the position is skipped and
instead the given screen is always used. This breaks the above reference
chain and things become garbage-collectable.

Also, this chains the drawable to the life time of the screen: When the
screen becomes invalid (.valid == false), the drawable will stop
redrawing.

Fixes: https://github.com/awesomeWM/awesome/issues/1237
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2016-11-27 18:09:10 +01:00
parent ab38876b0d
commit 4d2a1d5534
2 changed files with 14 additions and 5 deletions

View File

@ -30,14 +30,17 @@ local visible_drawables = {}
local function get_widget_context(self)
local geom = self.drawable:geometry()
local sgeos = {}
local s = self._forced_screen
if not s then
local sgeos = {}
for s in capi.screen do
sgeos[s] = s.geometry
for s in capi.screen do
sgeos[s] = s.geometry
end
s = grect.get_by_coord(sgeos, geom.x, geom.y) or capi.screen.primary
end
local s = grect.get_by_coord(sgeos, geom.x, geom.y) or capi.screen.primary
local context = self._widget_context
local dpi = beautiful.xresources.get_dpi(s)
if (not context) or context.screen ~= s or context.dpi ~= dpi then
@ -59,6 +62,7 @@ end
local function do_redraw(self)
if not self.drawable.valid then return end
if self._forced_screen and not self._forced_screen.valid then return end
local surf = surface.load_silently(self.drawable.surface, false)
-- The surface can be nil if the drawable's parent was already finalized
@ -274,6 +278,10 @@ function drawable:set_fg(c)
self._do_complete_repaint()
end
function drawable:_force_screen(s)
self._forced_screen = s
end
function drawable:_inform_visible(visible)
self._visible = visible
if visible then

View File

@ -86,6 +86,7 @@ function wibox:set_screen(s)
-- Remember this screen so things work correctly if screens overlap and
-- (x,y) is not enough to figure out the correct screen.
self.screen_assigned = s
self._drawable:_force_screen(s)
end
for _, k in pairs{ "buttons", "struts", "geometry", "get_xproperty", "set_xproperty" } do