Fix memory leak in the default config on screen removal
The default config had tables like mywibox and mywibox[s] was the wibox that is visible on screen s. When a screen is removed, nothing cleans up these tables and so the screen and the wibox could not be garbage collected. The same applies to the layoutbox, taglist etc. This commit removes the global mywibox table and instead saves it as a property on the screen. This way, the screen is not explicitly referenced and when it is removed, the screen, its wibox and all of its widgets become unreachable and can be garbage collected. This commit also updates the docs and the tests that referenced things (mostly the wibox) via mywibox[s] to now use s.mywibox. Fixes: https://github.com/awesomeWM/awesome/issues/1125 Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
b6a3ae43fb
commit
da6012da3e
|
@ -124,12 +124,8 @@ mykeyboardlayout = awful.widget.keyboardlayout()
|
||||||
mytextclock = wibox.widget.textclock()
|
mytextclock = wibox.widget.textclock()
|
||||||
|
|
||||||
-- Create a wibox for each screen and add it
|
-- Create a wibox for each screen and add it
|
||||||
mywibox = {}
|
|
||||||
mypromptbox = {}
|
|
||||||
mylayoutbox = {}
|
|
||||||
mytaglist = {}
|
|
||||||
-- @TAGLIST_BUTTON@
|
-- @TAGLIST_BUTTON@
|
||||||
mytaglist.buttons = awful.util.table.join(
|
local taglist_buttons = awful.util.table.join(
|
||||||
awful.button({ }, 1, function(t) t:view_only() end),
|
awful.button({ }, 1, function(t) t:view_only() end),
|
||||||
awful.button({ modkey }, 1, function(t)
|
awful.button({ modkey }, 1, function(t)
|
||||||
if client.focus then
|
if client.focus then
|
||||||
|
@ -146,9 +142,8 @@ mytaglist.buttons = awful.util.table.join(
|
||||||
awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
|
awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
|
||||||
)
|
)
|
||||||
|
|
||||||
mytasklist = {}
|
|
||||||
-- @TASKLIST_BUTTON@
|
-- @TASKLIST_BUTTON@
|
||||||
mytasklist.buttons = awful.util.table.join(
|
local tasklist_buttons = awful.util.table.join(
|
||||||
awful.button({ }, 1, function (c)
|
awful.button({ }, 1, function (c)
|
||||||
if c == client.focus then
|
if c == client.focus then
|
||||||
c.minimized = true
|
c.minimized = true
|
||||||
|
@ -198,42 +193,42 @@ awful.screen.connect_for_each_screen(function(s)
|
||||||
awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
|
awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
|
||||||
|
|
||||||
-- Create a promptbox for each screen
|
-- Create a promptbox for each screen
|
||||||
mypromptbox[s] = awful.widget.prompt()
|
s.mypromptbox = awful.widget.prompt()
|
||||||
-- Create an imagebox widget which will contains an icon indicating which layout we're using.
|
-- Create an imagebox widget which will contains an icon indicating which layout we're using.
|
||||||
-- We need one layoutbox per screen.
|
-- We need one layoutbox per screen.
|
||||||
mylayoutbox[s] = awful.widget.layoutbox(s)
|
s.mylayoutbox = awful.widget.layoutbox(s)
|
||||||
mylayoutbox[s]:buttons(awful.util.table.join(
|
s.mylayoutbox:buttons(awful.util.table.join(
|
||||||
awful.button({ }, 1, function () awful.layout.inc( 1) end),
|
awful.button({ }, 1, function () awful.layout.inc( 1) end),
|
||||||
awful.button({ }, 3, function () awful.layout.inc(-1) end),
|
awful.button({ }, 3, function () awful.layout.inc(-1) end),
|
||||||
awful.button({ }, 4, function () awful.layout.inc( 1) end),
|
awful.button({ }, 4, function () awful.layout.inc( 1) end),
|
||||||
awful.button({ }, 5, function () awful.layout.inc(-1) end)))
|
awful.button({ }, 5, function () awful.layout.inc(-1) end)))
|
||||||
-- Create a taglist widget
|
-- Create a taglist widget
|
||||||
mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
|
s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
|
||||||
|
|
||||||
-- Create a tasklist widget
|
-- Create a tasklist widget
|
||||||
mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
|
s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
|
||||||
|
|
||||||
-- @DOC_WIBAR@
|
-- @DOC_WIBAR@
|
||||||
-- Create the wibox
|
-- Create the wibox
|
||||||
mywibox[s] = awful.wibar({ position = "top", screen = s })
|
s.mywibox = awful.wibar({ position = "top", screen = s })
|
||||||
|
|
||||||
-- @DOC_SETUP_WIDGETS@
|
-- @DOC_SETUP_WIDGETS@
|
||||||
-- Add widgets to the wibox
|
-- Add widgets to the wibox
|
||||||
mywibox[s]:setup {
|
s.mywibox:setup {
|
||||||
layout = wibox.layout.align.horizontal,
|
layout = wibox.layout.align.horizontal,
|
||||||
{ -- Left widgets
|
{ -- Left widgets
|
||||||
layout = wibox.layout.fixed.horizontal,
|
layout = wibox.layout.fixed.horizontal,
|
||||||
mylauncher,
|
mylauncher,
|
||||||
mytaglist[s],
|
s.mytaglist,
|
||||||
mypromptbox[s],
|
s.mypromptbox,
|
||||||
},
|
},
|
||||||
mytasklist[s], -- Middle widget
|
s.mytasklist, -- Middle widget
|
||||||
{ -- Right widgets
|
{ -- Right widgets
|
||||||
layout = wibox.layout.fixed.horizontal,
|
layout = wibox.layout.fixed.horizontal,
|
||||||
mykeyboardlayout,
|
mykeyboardlayout,
|
||||||
wibox.widget.systray(),
|
wibox.widget.systray(),
|
||||||
mytextclock,
|
mytextclock,
|
||||||
mylayoutbox[s],
|
s.mylayoutbox,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
@ -332,13 +327,13 @@ globalkeys = awful.util.table.join(
|
||||||
{description = "restore minimized", group = "client"}),
|
{description = "restore minimized", group = "client"}),
|
||||||
|
|
||||||
-- Prompt
|
-- Prompt
|
||||||
awful.key({ modkey }, "r", function () mypromptbox[awful.screen.focused()]:run() end,
|
awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end,
|
||||||
{description = "run prompt", group = "launcher"}),
|
{description = "run prompt", group = "launcher"}),
|
||||||
|
|
||||||
awful.key({ modkey }, "x",
|
awful.key({ modkey }, "x",
|
||||||
function ()
|
function ()
|
||||||
awful.prompt.run({ prompt = "Run Lua code: " },
|
awful.prompt.run({ prompt = "Run Lua code: " },
|
||||||
mypromptbox[awful.screen.focused()].widget,
|
awful.screen.focused().mypromptbox.widget,
|
||||||
awful.util.eval, nil,
|
awful.util.eval, nil,
|
||||||
awful.util.get_cache_dir() .. "/history_eval")
|
awful.util.get_cache_dir() .. "/history_eval")
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -39,7 +39,7 @@ and usually provide some options.
|
||||||
|
|
||||||
Code:
|
Code:
|
||||||
|
|
||||||
mywibox[s] : setup {
|
s.mywibox : setup {
|
||||||
s == 1 and my_first_widget, -- Only display on screen 1
|
s == 1 and my_first_widget, -- Only display on screen 1
|
||||||
my_second_widget,
|
my_second_widget,
|
||||||
{ -- Add a background color/pattern for my_third_widget
|
{ -- Add a background color/pattern for my_third_widget
|
||||||
|
@ -66,7 +66,7 @@ declarative layout, or `nil`.
|
||||||
|
|
||||||
Code:
|
Code:
|
||||||
|
|
||||||
mywibox[s] : setup {
|
s.mywibox : setup {
|
||||||
{
|
{
|
||||||
-- Force the textbox to always be 300 pixel long
|
-- Force the textbox to always be 300 pixel long
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,7 @@ and `right` can be defined
|
||||||
|
|
||||||
Code:
|
Code:
|
||||||
|
|
||||||
mywibox[s] : setup {
|
s.mywibox : setup {
|
||||||
my_textbox1, -- Left
|
my_textbox1, -- Left
|
||||||
nil, -- Nothing in the middle
|
nil, -- Nothing in the middle
|
||||||
my_textbox2, -- Right
|
my_textbox2, -- Right
|
||||||
|
@ -129,7 +129,7 @@ is a simple circle widget:
|
||||||
|
|
||||||
Code:
|
Code:
|
||||||
|
|
||||||
mywibox[s] : setup {
|
s.mywibox : setup {
|
||||||
fit = function(self, context, width, height)
|
fit = function(self, context, width, height)
|
||||||
return height, height -- A square taking the full height
|
return height, height -- A square taking the full height
|
||||||
end,
|
end,
|
||||||
|
@ -165,7 +165,7 @@ Code:
|
||||||
tb:set_markup("Hello world! ")
|
tb:set_markup("Hello world! ")
|
||||||
|
|
||||||
-- Repeat "tb" 3 times
|
-- Repeat "tb" 3 times
|
||||||
mywibox[s] : setup {
|
s.mywibox : setup {
|
||||||
tb,
|
tb,
|
||||||
tb,
|
tb,
|
||||||
tb,
|
tb,
|
||||||
|
@ -198,7 +198,7 @@ underscore characters and non-numeric first character)
|
||||||
|
|
||||||
Code:
|
Code:
|
||||||
|
|
||||||
mywibox[s] : setup {
|
s.mywibox : setup {
|
||||||
{
|
{
|
||||||
id = "second",
|
id = "second",
|
||||||
widget = wibox.widget.textbox
|
widget = wibox.widget.textbox
|
||||||
|
@ -211,8 +211,8 @@ Code:
|
||||||
layout = wibox.layout.fixed.horizontal,
|
layout = wibox.layout.fixed.horizontal,
|
||||||
}
|
}
|
||||||
|
|
||||||
mywibox[s].first.second:set_markup("changed!")
|
s.mywibox.first.second:set_markup("changed!")
|
||||||
mywibox[s]:get_children_by_id("third")[1]:set_markup("Also changed!")
|
s.mywibox:get_children_by_id("third")[1]:set_markup("Also changed!")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ Code:
|
||||||
vicious.register(w, f(args))
|
vicious.register(w, f(args))
|
||||||
end
|
end
|
||||||
|
|
||||||
mywibox[s] : setup {
|
s.mywibox : setup {
|
||||||
{
|
{
|
||||||
vicious = {vicious.widgets.cpu, "CPU: $1%", 3},
|
vicious = {vicious.widgets.cpu, "CPU: $1%", 3},
|
||||||
widget = wibox.widget.textbox
|
widget = wibox.widget.textbox
|
||||||
|
@ -273,7 +273,7 @@ Code:
|
||||||
local l = wibox.widget.align()
|
local l = wibox.widget.align()
|
||||||
|
|
||||||
-- 3 circle
|
-- 3 circle
|
||||||
mywibox[s] : setup {
|
s.mywibox : setup {
|
||||||
circle,
|
circle,
|
||||||
circle,
|
circle,
|
||||||
circle,
|
circle,
|
||||||
|
@ -287,5 +287,5 @@ Code:
|
||||||
table.insert(three_circle, circle)
|
table.insert(three_circle, circle)
|
||||||
end
|
end
|
||||||
|
|
||||||
mywibox[s] : setup (three_circle)
|
s.mywibox : setup (three_circle)
|
||||||
|
|
||||||
|
|
|
@ -160,4 +160,4 @@ some examples. Here is the most simple example you can get:
|
||||||
This can then be used as `bgimage` for a `wibox`, `awful.wibar` or
|
This can then be used as `bgimage` for a `wibox`, `awful.wibar` or
|
||||||
`wibox.container.background`:
|
`wibox.container.background`:
|
||||||
|
|
||||||
mywibox[screen.primary].bgimage = img
|
screen.primary.mywibox.bgimage = img
|
||||||
|
|
|
@ -145,7 +145,7 @@ You can use a `clientkeys` binding.:
|
||||||
Add the following key binding to your `globalkeys`:
|
Add the following key binding to your `globalkeys`:
|
||||||
|
|
||||||
awful.key({ modkey }, "b", function ()
|
awful.key({ modkey }, "b", function ()
|
||||||
mywibox[mouse.screen].visible = not mywibox[mouse.screen].visible
|
mouse.screen.mywibox.visible = not mouse.screen.mywibox.visible
|
||||||
end),
|
end),
|
||||||
|
|
||||||
### How to toggle clients floating state?
|
### How to toggle clients floating state?
|
||||||
|
|
|
@ -236,7 +236,7 @@ end
|
||||||
-- hooks = {
|
-- hooks = {
|
||||||
-- -- Apply startup notification properties with Shift-Return.
|
-- -- Apply startup notification properties with Shift-Return.
|
||||||
-- {{"Shift" }, "Return", function(command)
|
-- {{"Shift" }, "Return", function(command)
|
||||||
-- mypromptbox[awful.screen.focused()]:spawn_and_handle_error(
|
-- awful.screen.focused().mypromptbox:spawn_and_handle_error(
|
||||||
-- command, {floating=true})
|
-- command, {floating=true})
|
||||||
-- end},
|
-- end},
|
||||||
-- -- Override default behavior of "Return": launch commands prefixed
|
-- -- Override default behavior of "Return": launch commands prefixed
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
-- 221 end
|
-- 221 end
|
||||||
-- 222 end
|
-- 222 end
|
||||||
-- 223 end),
|
-- 223 end),
|
||||||
-- 224 mylayoutbox[s],
|
-- 224 s.mylayoutbox,
|
||||||
--
|
--
|
||||||
-- ![Example screenshot](../images/awful_widget_watch.png)
|
-- ![Example screenshot](../images/awful_widget_watch.png)
|
||||||
--
|
--
|
||||||
|
|
|
@ -12,13 +12,12 @@ local function emit_refresh()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Make the layoutbox in the default config GC'able
|
-- Make the layoutbox in the default config GC'able
|
||||||
-- luacheck: globals mywibox mylayoutbox
|
|
||||||
for s in screen do
|
for s in screen do
|
||||||
mywibox[s]:set_widget(wibox.widget.textbox())
|
s.mywibox:set_widget(wibox.widget.textbox())
|
||||||
mywibox[s].visible = false
|
s.mywibox.visible = false
|
||||||
|
s.mywibox = nil
|
||||||
|
s.mylayoutbox = nil
|
||||||
end
|
end
|
||||||
mywibox = nil
|
|
||||||
mylayoutbox = nil
|
|
||||||
emit_refresh()
|
emit_refresh()
|
||||||
|
|
||||||
-- Test if some objects can be garbage collected
|
-- Test if some objects can be garbage collected
|
||||||
|
|
|
@ -47,7 +47,7 @@ local steps = {
|
||||||
assert(geom.width + 2*bw == 600, geom.width + 2*bw)
|
assert(geom.width + 2*bw == 600, geom.width + 2*bw)
|
||||||
assert(geom.height + 2*bw == 610, geom.height + 2*bw)
|
assert(geom.height + 2*bw == 610, geom.height + 2*bw)
|
||||||
|
|
||||||
local wb = mywibox[fake_screen]
|
local wb = fake_screen.mywibox
|
||||||
assert(wb.screen == fake_screen, tostring(wb.screen) .. " ~= " .. tostring(fake_screen))
|
assert(wb.screen == fake_screen, tostring(wb.screen) .. " ~= " .. tostring(fake_screen))
|
||||||
assert(wb.x == 100, wb.x)
|
assert(wb.x == 100, wb.x)
|
||||||
assert(wb.y == 110, wb.y)
|
assert(wb.y == 110, wb.y)
|
||||||
|
@ -58,19 +58,12 @@ local steps = {
|
||||||
|
|
||||||
-- Step 3: Say goodbye to the screen
|
-- Step 3: Say goodbye to the screen
|
||||||
function()
|
function()
|
||||||
|
local wb = fake_screen.mywibox
|
||||||
fake_screen:fake_remove()
|
fake_screen:fake_remove()
|
||||||
|
|
||||||
-- Now that the screen is invalid, the wibox shouldn't refer to it any
|
-- Now that the screen is invalid, the wibox shouldn't refer to it any
|
||||||
-- more
|
-- more
|
||||||
assert(mywibox[fake_screen].screen ~= fake_screen)
|
assert(wb.screen ~= fake_screen)
|
||||||
|
|
||||||
-- TODO: This is a hack to make the test work, how to do this so that it
|
|
||||||
-- also works "in the wild"?
|
|
||||||
mypromptbox[fake_screen] = nil
|
|
||||||
mylayoutbox[fake_screen] = nil
|
|
||||||
mytaglist[fake_screen] = nil
|
|
||||||
mytasklist[fake_screen] = nil
|
|
||||||
mywibox[fake_screen] = nil
|
|
||||||
|
|
||||||
-- Wrap in a weak table to allow garbage collection
|
-- Wrap in a weak table to allow garbage collection
|
||||||
fake_screen = setmetatable({ fake_screen }, { __mode = "v" })
|
fake_screen = setmetatable({ fake_screen }, { __mode = "v" })
|
||||||
|
|
|
@ -2,12 +2,11 @@ local placement = require("awful.placement")
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
local wibar = require("awful.wibar")
|
local wibar = require("awful.wibar")
|
||||||
|
|
||||||
-- luacheck: globals mywibox
|
|
||||||
local steps = {}
|
local steps = {}
|
||||||
|
|
||||||
local parent, small
|
local parent, small
|
||||||
|
|
||||||
local twibar, bwibar, lwibar, rwibar = mywibox[screen.primary]
|
local twibar, bwibar, lwibar, rwibar = screen.primary.mywibox
|
||||||
|
|
||||||
-- Test the struts without using wibars
|
-- Test the struts without using wibars
|
||||||
table.insert(steps, function()
|
table.insert(steps, function()
|
||||||
|
|
Loading…
Reference in New Issue