From f6761e662c7e4168959957ccc5f4a7d723e6d76a Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Fri, 23 Sep 2016 10:07:29 +0200 Subject: [PATCH] wibox.drawable: React to screen changes The previous commit made wibox.drawable turn a "normal redraw" into a complete repaint when it was moved to another screen. However, nothing happened until that normal redraw. This commit triggers a normal redraw when we are (possibly) moved to another screen. More precise, this means that whenever a screen appears, disappears or changes its geometry and when the drawable is moved, we trigger a normal redraw. This redraw will likely do nothing, because no relayout is pending and no part of the surface needs a redraw, so it is cheap. However, if the drawable really ends up on another screen, then the code from the previous commits makes us do a full relayout and redraw. This commit likely fixes the current instability of test-screen-changes.lua. See https://github.com/awesomeWM/awesome/issues/982#issuecomment-231712056. As explained there, the test fails because the fake screen that it created is still referenced, so cannot be garbage collected, but the test doesn't succeed unless the screen is garbage collected. So something is still referencing the screen that was removed. This something can be a client's titlebar, because the underlying drawable still has a context member referring to the old screen. This commit should fix that problem, because we now trigger a redraw which will compute a new context and thus the reference to the old screen is released. Signed-off-by: Uli Schlachter --- lib/wibox/drawable.lua | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/wibox/drawable.lua b/lib/wibox/drawable.lua index a7fd0efd..ef4953b3 100644 --- a/lib/wibox/drawable.lua +++ b/lib/wibox/drawable.lua @@ -24,7 +24,8 @@ local matrix = require("gears.matrix") local hierarchy = require("wibox.hierarchy") local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -local drawables = setmetatable({}, { __mode = 'k' }) +local drawables_draw = setmetatable({}, { __mode = 'k' }) +local drawables_force_complete_repaint = setmetatable({}, { __mode = 'k' }) -- Get the widget context. This should always return the same table (if -- possible), so that our draw and fit caches can work efficiently. @@ -357,9 +358,18 @@ function drawable.new(d, widget_context_skeleton, drawable_name) ret._need_complete_repaint = true ret:draw() end - drawables[ret._do_complete_repaint] = true + 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) d:connect_signal("property::surface", ret._do_complete_repaint) + -- Do a normal redraw when the drawable moves. This will likely do nothing + -- in most cases, but it makes us do a complete repaint when we are moved to + -- a different screen. + d:connect_signal("property::x", ret.draw) + d:connect_signal("property::y", ret.draw) + -- Currently we aren't redrawing on move (signals not connected). -- :set_bg() will later recompute this. ret._redraw_on_move = false @@ -427,11 +437,21 @@ end -- Redraw all drawables when the wallpaper changes capi.awesome.connect_signal("wallpaper_changed", function() - for k in pairs(drawables) do + for k in pairs(drawables_force_complete_repaint) do k() end end) +-- Give drawables a chance to react to screen changes +local function draw_all() + for k in pairs(drawables_draw) do + k() + end +end +screen.connect_signal("property::geometry", draw_all) +screen.connect_signal("added", draw_all) +screen.connect_signal("removed", draw_all) + return setmetatable(drawable, { __call = function(_, ...) return drawable.new(...) end }) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80