naughty: Never hold a strong reference to the notification in the box.
luajit was failing to GC the notification about 5% of the time. This commit stores all widget notifications in a weak table and don't let any lambda access the parent object notification object. Each of those changes reduces the failure rate. There might still be a couple in there, but the test passed 200x on my laptop with 100% success rate.
This commit is contained in:
parent
6e8b0d5a85
commit
9dcfde32e0
|
@ -46,22 +46,24 @@ end
|
|||
-- @propemits true false
|
||||
|
||||
function background:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
local old = self._private.notification[1]
|
||||
|
||||
if self._private.notification then
|
||||
self._private.notification:disconnect_signal("property::bg",
|
||||
if old == notif then return end
|
||||
|
||||
if old then
|
||||
old:disconnect_signal("property::bg",
|
||||
self._private.background_changed_callback)
|
||||
self._private.notification:disconnect_signal("property::border_width",
|
||||
old:disconnect_signal("property::border_width",
|
||||
self._private.background_changed_callback)
|
||||
self._private.notification:disconnect_signal("property::border_color",
|
||||
old:disconnect_signal("property::border_color",
|
||||
self._private.background_changed_callback)
|
||||
self._private.notification:disconnect_signal("property::shape",
|
||||
old:disconnect_signal("property::shape",
|
||||
self._private.background_changed_callback)
|
||||
end
|
||||
|
||||
update_background(notif, self)
|
||||
|
||||
self._private.notification = notif
|
||||
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||
|
||||
notif:connect_signal("property::bg" , self._private.background_changed_callback)
|
||||
notif:connect_signal("property::border_width", self._private.background_changed_callback)
|
||||
|
@ -82,12 +84,13 @@ local function new(args)
|
|||
args = args or {}
|
||||
|
||||
local bg = wbg()
|
||||
bg._private.notification = {}
|
||||
bg:set_border_strategy("inner")
|
||||
|
||||
gtable.crush(bg, background, true)
|
||||
|
||||
function bg._private.background_changed_callback()
|
||||
update_background(bg._private.notification, bg)
|
||||
update_background(bg._private.notification[1], bg)
|
||||
end
|
||||
|
||||
if args.notification then
|
||||
|
|
|
@ -47,14 +47,16 @@ local function init_screen(s)
|
|||
end
|
||||
|
||||
local function disconnect(self)
|
||||
if self._private.notification then
|
||||
self._private.notification:disconnect_signal("destroyed",
|
||||
local n = self._private.notification[1]
|
||||
|
||||
if n then
|
||||
n:disconnect_signal("destroyed",
|
||||
self._private.destroy_callback)
|
||||
|
||||
self._private.notification:disconnect_signal("property::margin",
|
||||
n:disconnect_signal("property::margin",
|
||||
self._private.update)
|
||||
|
||||
self._private.notification:disconnect_signal("property::suspended",
|
||||
n:disconnect_signal("property::suspended",
|
||||
self._private.hide)
|
||||
end
|
||||
end
|
||||
|
@ -102,7 +104,7 @@ local function update_position(position, preset)
|
|||
honor_workarea = true,
|
||||
}
|
||||
if k == 1 then
|
||||
args.offset = get_offset(position, preset)
|
||||
args.offset = get_offset(position, preset)
|
||||
end
|
||||
|
||||
-- The first entry is aligned to the workarea, then the following to the
|
||||
|
@ -123,14 +125,13 @@ local function finish(self)
|
|||
end
|
||||
end
|
||||
|
||||
local preset
|
||||
if self.private and self.private.args and self.private.args.notification then
|
||||
preset = self.private.args.notification.preset
|
||||
end
|
||||
local preset = (self._private.notification[1] or {}).preset
|
||||
|
||||
update_position(self.position, preset)
|
||||
|
||||
disconnect(self)
|
||||
|
||||
self._private.notification = {}
|
||||
end
|
||||
|
||||
-- It isn't a good idea to use the `attach` `awful.placement` property. If the
|
||||
|
@ -236,21 +237,19 @@ local function generate_widget(args, n)
|
|||
end
|
||||
|
||||
-- Call `:set_notification` on all children
|
||||
awcommon._set_common_property(w, "notification", n or args.notification)
|
||||
awcommon._set_common_property(w, "notification", n)
|
||||
|
||||
return w
|
||||
end
|
||||
|
||||
local function init(self, notification)
|
||||
local args = self._private.args
|
||||
|
||||
local preset = notification.preset or {}
|
||||
|
||||
local position = args.position or notification.position or
|
||||
local position = self._private.position or notification.position or
|
||||
preset.position or beautiful.notification_position or "top_right"
|
||||
|
||||
if not self.widget then
|
||||
self.widget = generate_widget(self._private.args, notification)
|
||||
self.widget = generate_widget(self._private, notification)
|
||||
end
|
||||
|
||||
local bg = self._private.widget:get_children_by_id( "background_role" )[1]
|
||||
|
@ -295,20 +294,26 @@ local function init(self, notification)
|
|||
end
|
||||
|
||||
function box:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
if self._private.notification[1] == notif then return end
|
||||
|
||||
disconnect(self)
|
||||
|
||||
init(self, notif)
|
||||
|
||||
self._private.notification = notif
|
||||
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||
|
||||
self:emit_signal("property::notification", notif)
|
||||
end
|
||||
|
||||
function box:get_notification()
|
||||
return self._private.notification[1]
|
||||
end
|
||||
|
||||
function box:get_position()
|
||||
if self._private.notification then
|
||||
return self._private.notification:get_position()
|
||||
local n = self._private.notification[1]
|
||||
|
||||
if n then
|
||||
return n:get_position()
|
||||
end
|
||||
|
||||
return "top_right"
|
||||
|
@ -357,7 +362,9 @@ local function new(args)
|
|||
if not new_args.widget then return nil end
|
||||
|
||||
local ret = popup(new_args)
|
||||
ret._private.args = new_args
|
||||
ret._private.notification = {}
|
||||
ret._private.widget_template = args.widget_template
|
||||
ret._private.position = args.position
|
||||
|
||||
gtable.crush(ret, box, true)
|
||||
|
||||
|
@ -371,8 +378,10 @@ local function new(args)
|
|||
|
||||
--TODO remove
|
||||
local function hide()
|
||||
if ret._private.notification then
|
||||
ret._private.notification:destroy()
|
||||
local n = ret._private.notification[1]
|
||||
|
||||
if n then
|
||||
n:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -168,14 +168,16 @@ local function wb_label(action, self)
|
|||
end
|
||||
|
||||
local function update(self)
|
||||
if not self._private.layout or not self._private.notification then return end
|
||||
local n = self._private.notification[1]
|
||||
|
||||
if not self._private.layout or not n then return end
|
||||
|
||||
awcommon.list_update(
|
||||
self._private.layout,
|
||||
self._private.default_buttons,
|
||||
function(o) return wb_label(o, self) end,
|
||||
self._private.data,
|
||||
self._private.notification.actions,
|
||||
n.actions,
|
||||
{
|
||||
widget_template = self._private.widget_template
|
||||
}
|
||||
|
@ -229,7 +231,7 @@ local actionlist = {}
|
|||
|
||||
|
||||
function actionlist:set_notification(notif)
|
||||
self._private.notification = notif
|
||||
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||
|
||||
if not self._private.layout then
|
||||
self._private.layout = wibox.layout.fixed.horizontal()
|
||||
|
@ -329,8 +331,9 @@ local function new(_, args)
|
|||
gtable.crush(wdg, actionlist, true)
|
||||
|
||||
wdg._private.data = {}
|
||||
wdg._private.notification = {}
|
||||
|
||||
gtable.crush(wdg, args)
|
||||
gtable.crush(wdg, args, false)
|
||||
|
||||
wdg._private.style = wdg._private.style or {}
|
||||
|
||||
|
@ -338,7 +341,7 @@ local function new(_, args)
|
|||
|
||||
wdg._private.default_buttons = gtable.join(
|
||||
abutton({ }, 1, function(a)
|
||||
local notif = wdg._private.notification or args.notification
|
||||
local notif = wdg._private.notification[1]
|
||||
a:invoke(notif)
|
||||
end)
|
||||
)
|
||||
|
|
|
@ -22,7 +22,7 @@ local function notif_size()
|
|||
constraint:set_width(beautiful.notification_max_width or dpi(500))
|
||||
|
||||
rawset(constraint, "set_notification", function(_, notif)
|
||||
constraint._private.notification = notif
|
||||
constraint._private.notification = setmetatable({notif}, {__mode = "v"})
|
||||
local s = false
|
||||
|
||||
if notif.width and notif.width ~= beautiful.notification_max_width then
|
||||
|
@ -37,6 +37,10 @@ local function notif_size()
|
|||
constraint.strategy = s and "exact" or "max"
|
||||
end)
|
||||
|
||||
rawset(constraint, "get_notification", function()
|
||||
return constraint._private.notification[1]
|
||||
end)
|
||||
|
||||
return constraint
|
||||
end
|
||||
|
||||
|
|
|
@ -83,10 +83,12 @@ end
|
|||
-- @propemits true false
|
||||
|
||||
function icon:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
local old = (self._private.notification or {})[1]
|
||||
|
||||
if self._private.notification then
|
||||
self._private.notification:disconnect_signal("destroyed",
|
||||
if old == notif then return end
|
||||
|
||||
if old then
|
||||
old:disconnect_signal("destroyed",
|
||||
self._private.icon_changed_callback)
|
||||
end
|
||||
|
||||
|
@ -96,7 +98,7 @@ function icon:set_notification(notif)
|
|||
self:set_image(icn)
|
||||
end
|
||||
|
||||
self._private.notification = notif
|
||||
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||
|
||||
notif:connect_signal("property::icon", self._private.icon_changed_callback)
|
||||
self:emit_signal("property::notification", notif)
|
||||
|
@ -154,10 +156,14 @@ local function new(args)
|
|||
local tb = imagebox()
|
||||
|
||||
gtable.crush(tb, icon, true)
|
||||
tb._private.notification = {}
|
||||
|
||||
function tb._private.icon_changed_callback()
|
||||
local n = tb._private.notification[1]
|
||||
|
||||
local icn = gsurface.load_silently(tb._private.notification.icon)
|
||||
if not n then return end
|
||||
|
||||
local icn = gsurface.load_silently(n.icon)
|
||||
|
||||
if icn then
|
||||
tb:set_image(icn)
|
||||
|
|
|
@ -27,18 +27,20 @@ local message = {}
|
|||
-- @propemits true false
|
||||
|
||||
function message:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
local old = self._private.notification[1]
|
||||
|
||||
if self._private.notification then
|
||||
self._private.notification:disconnect_signal("property::message",
|
||||
if old == notif then return end
|
||||
|
||||
if old then
|
||||
old:disconnect_signal("property::message",
|
||||
self._private.message_changed_callback)
|
||||
self._private.notification:disconnect_signal("property::fg",
|
||||
old:disconnect_signal("property::fg",
|
||||
self._private.message_changed_callback)
|
||||
end
|
||||
|
||||
markup(self, notif.message, notif.fg, notif.font)
|
||||
|
||||
self._private.notification = notif
|
||||
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||
|
||||
notif:connect_signal("property::message", self._private.message_changed_callback)
|
||||
notif:connect_signal("property::fg" , self._private.message_changed_callback)
|
||||
|
@ -57,16 +59,23 @@ local function new(args)
|
|||
local tb = textbox()
|
||||
tb:set_wrap("word")
|
||||
tb:set_font(beautiful.notification_font)
|
||||
tb._private.notification = {}
|
||||
|
||||
gtable.crush(tb, message, true)
|
||||
|
||||
function tb._private.message_changed_callback()
|
||||
markup(
|
||||
tb,
|
||||
tb._private.notification.message,
|
||||
tb._private.notification.fg,
|
||||
tb._private.notification.font
|
||||
)
|
||||
local n = tb._private.notification[1]
|
||||
|
||||
if n then
|
||||
markup(
|
||||
tb,
|
||||
n.message,
|
||||
n.fg,
|
||||
n.font
|
||||
)
|
||||
else
|
||||
markup(tb, nil, nil)
|
||||
end
|
||||
end
|
||||
|
||||
if args.notification then
|
||||
|
|
|
@ -27,18 +27,20 @@ local title = {}
|
|||
-- @propemits true false
|
||||
|
||||
function title:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
local old = self._private.notification[1]
|
||||
|
||||
if self._private.notification then
|
||||
self._private.notification:disconnect_signal("property::message",
|
||||
if old == notif then return end
|
||||
|
||||
if old then
|
||||
old:disconnect_signal("property::message",
|
||||
self._private.title_changed_callback)
|
||||
self._private.notification:disconnect_signal("property::fg",
|
||||
old:disconnect_signal("property::fg",
|
||||
self._private.title_changed_callback)
|
||||
end
|
||||
|
||||
markup(self, notif.title, notif.fg, notif.font)
|
||||
|
||||
self._private.notification = notif
|
||||
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||
self._private.title_changed_callback()
|
||||
|
||||
notif:connect_signal("property::title", self._private.title_changed_callback)
|
||||
|
@ -58,16 +60,23 @@ local function new(args)
|
|||
local tb = textbox()
|
||||
tb:set_wrap("word")
|
||||
tb:set_font(beautiful.notification_font)
|
||||
tb._private.notification = {}
|
||||
|
||||
gtable.crush(tb, title, true)
|
||||
|
||||
function tb._private.title_changed_callback()
|
||||
markup(
|
||||
tb,
|
||||
tb._private.notification.title,
|
||||
tb._private.notification.fg,
|
||||
tb._private.notification.font
|
||||
)
|
||||
local n = tb._private.notification[1]
|
||||
|
||||
if n then
|
||||
markup(
|
||||
tb,
|
||||
n.title,
|
||||
n.fg,
|
||||
n.font
|
||||
)
|
||||
else
|
||||
markup("", nil, nil)
|
||||
end
|
||||
end
|
||||
|
||||
if args.notification then
|
||||
|
|
Loading…
Reference in New Issue