notification: Make the position index more robust.

If the notification screen or position changed, it would end up in the
wrong index and removing it would fail. This cannot happen anymore.
This commit is contained in:
Emmanuel Lepage Vallee 2019-07-09 01:29:33 -04:00
parent 4df8120acb
commit 12f1908ef8
2 changed files with 48 additions and 8 deletions

View File

@ -165,6 +165,35 @@ capi.screen.connect_signal("removed", function(scr)
naughty.notifications[scr] = nil naughty.notifications[scr] = nil
end) end)
local function get_screen(s)
return s and capi.screen[s]
end
local function remove_from_index(n)
for _, positions in pairs(naughty.notifications) do
for _, ns in pairs(positions) do
for k, n2 in ipairs(ns) do
if n2 == n then
table.remove(ns, k)
return
end
end
end
end
end
-- When id or screen are set after the object is created, update the indexing.
local function update_index(n)
-- Find the only index and remove it (there's an useless loop, but it's small).
remove_from_index(n)
-- Add to the index again
local s = get_screen(n.screen or n.preset.screen or screen.focused())
naughty.notifications[s] = naughty.notifications[s] or {}
table.insert(naughty.notifications[s][n.position], n)
end
--- Notification state. --- Notification state.
-- --
-- This function is deprecated, use `naughty.suspended`. -- This function is deprecated, use `naughty.suspended`.
@ -406,7 +435,7 @@ local function cleanup(self, reason)
local scr = self.screen local scr = self.screen
assert(naughty.notifications[scr][self.position][self.idx] == self) assert(naughty.notifications[scr][self.position][self.idx] == self)
table.remove(naughty.notifications[scr][self.position], self.idx) remove_from_index(self)
-- Update all indices -- Update all indices
for k, n in ipairs(naughty.notifications[scr][self.position]) do for k, n in ipairs(naughty.notifications[scr][self.position]) do
@ -433,10 +462,6 @@ end
naughty.connect_signal("destroyed", cleanup) naughty.connect_signal("destroyed", cleanup)
local function get_screen(s)
return s and capi.screen[s]
end
-- Proxy the global suspension state on all notification objects -- Proxy the global suspension state on all notification objects
local function get_suspended(self) local function get_suspended(self)
return properties.suspended and not self.ignore_suspend return properties.suspended and not self.ignore_suspend
@ -482,7 +507,6 @@ end
-- Register a new notification object. -- Register a new notification object.
local function register(notification, args) local function register(notification, args)
-- Add the some more properties -- Add the some more properties
rawset(notification, "get_suspended", get_suspended) rawset(notification, "get_suspended", get_suspended)
@ -611,6 +635,9 @@ function naughty.notify(args)
return nnotif(args) return nnotif(args)
end end
naughty.connect_signal("property::screen" , update_index)
naughty.connect_signal("property::position", update_index)
return setmetatable(naughty, {__index = index_miss, __newindex = set_index_miss}) return setmetatable(naughty, {__index = index_miss, __newindex = set_index_miss})
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -266,14 +266,27 @@ local function set_escaped_text(self)
if self.size_info then update_size(self) end if self.size_info then update_size(self) end
end end
local function seek_and_destroy(n)
for _, positions in pairs(current_notifications) do
for _, pos in pairs(positions) do
for k, n2 in ipairs(pos) do
if n == n2 then
table.remove(pos, k)
return
end
end
end
end
end
local function cleanup(self, _ --[[reason]], keep_visible) local function cleanup(self, _ --[[reason]], keep_visible)
-- It is not a legacy notification -- It is not a legacy notification
if not self.box then return end if not self.box then return end
local scr = self.screen local scr = self.screen
assert(current_notifications[scr][self.position][self.idx] == self) -- Brute force find it, the position could have been replaced.
table.remove(current_notifications[scr][self.position], self.idx) seek_and_destroy(self)
if (not keep_visible) or (not scr) then if (not keep_visible) or (not scr) then
self.box.visible = false self.box.visible = false