Merge pull request #3436 from Elv13/fix_3428

Fix setting the screen in a notification preset.
This commit is contained in:
Emmanuel Lepage Vallée 2021-09-24 07:53:54 -07:00 committed by GitHub
commit eddabebac4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 275 additions and 83 deletions

View File

@ -191,6 +191,10 @@ naughty.notifications = { suspended = { }, _expired = {{}} }
naughty._active = {} naughty._active = {}
local function get_screen(s)
return s and capi.screen[s]
end
local function init_screen(s) local function init_screen(s)
if naughty.notifications[s] then return end if naughty.notifications[s] then return end
@ -218,15 +222,18 @@ capi.screen.connect_signal("removed", function(scr)
naughty.emit_signal("request::screen", n, "removed", {}) naughty.emit_signal("request::screen", n, "removed", {})
end end
end end
for _, n in ipairs(naughty._active) do
if n._private.args and get_screen(n._private.args.screen) == scr then
n._private.args.screen = nil
end
end
-- Destroy all notifications on this screen -- Destroy all notifications on this screen
naughty.destroy_all_notifications({scr}) naughty.destroy_all_notifications({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) local function remove_from_index(n)
for _, positions in pairs(naughty.notifications) do for _, positions in pairs(naughty.notifications) do
for _, ns in pairs(positions) do for _, ns in pairs(positions) do

View File

@ -62,6 +62,12 @@ screen.connect_for_each_screen(function(s)
} }
end) end)
capi.screen.connect_signal("removed", function(s)
timer.delayed_call(function()
current_notifications[s] = nil
end)
end)
--- Sum heights of notifications at position --- Sum heights of notifications at position
-- --
-- @param s Screen to use -- @param s Screen to use
@ -128,7 +134,7 @@ local function get_offset(s, position, idx, width, height)
local find_old_to_replace = function() local find_old_to_replace = function()
for i = 1, idx-1 do for i = 1, idx-1 do
local n = current_notifications[s][position][i] local n = current_notifications[s][position][i]
if n.timeout > 0 then if n and n.timeout > 0 then
return n return n
end end
end end

View File

@ -570,6 +570,27 @@ function notification:set_timeout(timeout)
self:emit_signal("property::timeout", timeout) self:emit_signal("property::timeout", timeout)
end end
function notification:get_message()
-- This property was called "text" in older versions.
-- Some modules like `lain` abused of the presets (they
-- had little choice at the time) to set the message on
-- an existing popup.
local p = rawget(self, "preset") or {}
local message = self._private.message or p.message or ""
if message == "" and p.text and p.text ~= "" then
gdebug.deprecate(
"Using the preset configuration to set the notification "..
"message is not supported. Please use `n.message = 'text'`.",
{deprecated_in=5}
)
return p.text
end
return message
end
function notification:set_text(txt) function notification:set_text(txt)
gdebug.deprecate( gdebug.deprecate(
"The `text` attribute is deprecated, use `message`", "The `text` attribute is deprecated, use `message`",
@ -861,10 +882,18 @@ local function select_legacy_preset(n, args)
)) ))
for k, v in pairs(n.preset) do for k, v in pairs(n.preset) do
-- Don't keep a strong reference to the screen, Lua 5.1 GC wont be
-- smart enough to unwind the mess of circular weak references.
if k ~= "screen" then
n._private[k] = v n._private[k] = v
end end
end end
if n.preset.screen then
n._private.weak_screen[1] = capi.screen[n.preset.screen]
end
end
--- Create a notification. --- Create a notification.
-- --
-- @tparam table args The argument table containing any of the arguments below. -- @tparam table args The argument table containing any of the arguments below.

View File

@ -160,6 +160,15 @@ end
-- @staticfct ruled.notification.apply -- @staticfct ruled.notification.apply
function module.apply(n) function module.apply(n)
local callbacks, props = {}, {} local callbacks, props = {}, {}
if n.preset then
for k, v in pairs(n.preset) do
if not n._private[v] then
props[k] = v
end
end
end
for _, v in ipairs(nrules._matching_source) do for _, v in ipairs(nrules._matching_source) do
v.callback(nrules, n, props, callbacks) v.callback(nrules, n, props, callbacks)
end end

View File

@ -444,6 +444,9 @@ options_check_args(int argc, char **argv, int *init_flags, string_array_t *paths
if (confpath != NULL) if (confpath != NULL)
fatal("--config may only be specified once"); fatal("--config may only be specified once");
confpath = a_strdup(optarg); confpath = a_strdup(optarg);
/* Make sure multi-file config works */
string_array_append(paths, g_path_get_dirname(optarg));
break; break;
case 'm': case 'm':
/* Validation */ /* Validation */

View File

@ -256,7 +256,7 @@ local new1, new2 = nil, nil
-- Check that you can add new default key/mousebindings at any time. -- Check that you can add new default key/mousebindings at any time.
table.insert(steps, function() table.insert(steps, function()
assert(#mouse.screen.clients == 0) if #mouse.screen.clients > 0 then return end
new1 = module.key { new1 = module.key {
key = "a", key = "a",

View File

@ -0,0 +1,85 @@
local naughty = require("naughty")
local notification = require("naughty.notification")
require("ruled.notification"):_clear()
local steps = {}
local BAD_IDEA = "never do this in practice, compat only"
local notif = setmetatable({}, {__mode="v"})
screen[1]:split()
for _, legacy_preset in ipairs {true, false} do
table.insert(steps, function()
-- This will either take the legacy preset path
-- or the ruled preset path.
function naughty.get__has_preset_handler()
return legacy_preset
end
local custom_preset = {
bg = "#00ff00",
fg = "#ff0000",
text = BAD_IDEA
}
notif[1] = notification {
preset = custom_preset,
}
assert(notif[1].bg == "#00ff00")
assert(notif[1].message == BAD_IDEA)
return true
end)
table.insert(steps, function()
notif[1]:destroy()
return true
end)
for s in screen do
-- Make sure the screen doesn't cause a memory leak.
table.insert(steps, function()
collectgarbage("collect")
if notif[1] then return end
local custom_preset = {
bg = "#0000ff",
fg = "#ff0000",
screen = s
}
notif[1] = notification {
preset = custom_preset,
title = "test",
}
assert(notif[1].bg == "#0000ff")
assert(notif[1].screen == s)
return true
end)
table.insert(steps, function()
assert(notif[1].screen == s)
notif[1]:destroy()
return true
end)
table.insert(steps, function()
collectgarbage("collect")
if notif[1] then return end
return true
end)
end
end
require("_runner").run_steps(steps)

View File

@ -30,11 +30,34 @@ local s1, s2 = mouse.screen, nil
for _, p in ipairs(positions) do for _, p in ipairs(positions) do
objs[p] = setmetatable({},{ objs[p] = setmetatable({},{
__index=function(t,k) t[k]={};return t[k] end, __index = function(t,k)
t[k] = setmetatable({}, {__mode = "kv"})
return t[k]
end,
__mode = "k" __mode = "k"
}) })
end end
local function cleanup(n)
-- Wait until there is no notifications left.
for _, pos in ipairs(positions) do
for s, notifs in pairs(objs[pos]) do
for k, n2 in ipairs(notifs) do
if n == n2 then
table.remove(notifs, k)
if #notifs == 0 then
objs[pos][s] = nil
end
return
end
end
end
end
end
naughty.connect_signal("property::screen", cleanup)
naughty.connect_signal("destroyed", cleanup)
local function add_many(s) local function add_many(s)
for _, pos in ipairs(positions) do for _, pos in ipairs(positions) do
for i=1, 5 do for i=1, 5 do
@ -71,8 +94,14 @@ local function check_screen(s)
end end
end end
for _, legacy_preset in ipairs {true, false} do
-- Create notifications in each position. -- Create notifications in each position.
table.insert(steps, function() table.insert(steps, function()
function naughty.get__has_preset_handler()
return legacy_preset
end
rnotif._clear() rnotif._clear()
add_many(s1) add_many(s1)
@ -131,30 +160,40 @@ table.insert(steps, function()
return true return true
end) end)
--local weak = nil --FIXME local weak = nil
-- Delete a screen and make sure it gets GCed. -- Delete a screen and make sure it gets GCed.
table.insert(steps, function() table.insert(steps, function()
s2:fake_remove() s2:fake_remove()
-- Help the weak tables a little. return true
end)
-- Check if notifications are moved.
table.insert(steps, function()
-- Wait until there is no notifications left.
for _, pos in ipairs(positions) do for _, pos in ipairs(positions) do
objs[pos][s1] = nil if #objs[pos][s2] > 0 then
collectgarbage("collect")
return
end
end end
-- Drop our string reference to s2. -- Drop our string reference to s2.
--weak, s2 = setmetatable({s2}, {__mode="v"}), nil --FIXME weak, s2 = setmetatable({s2}, {__mode="v"}), nil
return true return true
end) end)
--FIXME
--table.insert(steps, function() table.insert(steps, function()
-- if weak[1] == nil then return true end if weak[1] == nil then return true end
--
-- for _=1, 10 do for _=1, 10 do
-- collectgarbage("collect") collectgarbage("collect")
-- end end
--end) end)
end
require("_runner").run_steps(steps) require("_runner").run_steps(steps)

View File

@ -475,15 +475,29 @@ table.insert(steps, function()
rwibar:remove() rwibar:remove()
twibar:remove() twibar:remove()
for _, w in ipairs(wibars) do
assert(not w.visible)
end
-- Make sure the placement doesn't hold a reference. -- Make sure the placement doesn't hold a reference.
bwibar, lwibar, rwibar, twibar = nil, nil, nil, nil bwibar, lwibar, rwibar, twibar = nil, nil, nil, nil
screen.primary.mywibox = nil screen.primary.mywibox = nil
return true
end)
table.insert(steps, function()
for _=1, 3 do for _=1, 3 do
collectgarbage("collect") collectgarbage("collect")
end end
assert(not next(wibars)) if next(wibars) then
for _, w in ipairs(wibars) do
assert(not w.visible)
end
return
end
return true return true
end) end)