2019-01-04 09:24:28 +01:00
|
|
|
-- This test suite tries to prevent the legacy notification popups from
|
|
|
|
-- regressing as the new notification API is improving.
|
|
|
|
local spawn = require("awful.spawn")
|
|
|
|
local naughty = require("naughty" )
|
2019-02-16 21:18:33 +01:00
|
|
|
local gdebug = require("gears.debug")
|
2019-01-04 09:24:28 +01:00
|
|
|
local cairo = require("lgi" ).cairo
|
|
|
|
local beautiful = require("beautiful")
|
2019-02-19 18:35:09 +01:00
|
|
|
local Gio = require("lgi" ).Gio
|
|
|
|
local GLib = require("lgi" ).GLib
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
-- This module test deprecated APIs
|
|
|
|
require("gears.debug").deprecate = function() end
|
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
local dbus_connection = assert(Gio.bus_get_sync(Gio.BusType.SESSION))
|
|
|
|
|
|
|
|
local function send_notify(app, id, icon, summary, body, actions, hints, timeout, callback)
|
|
|
|
local parameters = GLib.Variant("(susssasa{sv}i)", {
|
|
|
|
app, id, icon, summary, body, actions, hints, timeout
|
|
|
|
})
|
|
|
|
local reply_type = GLib.VariantType.new("(u)")
|
|
|
|
|
|
|
|
local function invoke_callback(conn, result)
|
|
|
|
local new_id = conn:call_finish(result).value[1]
|
|
|
|
if callback then
|
|
|
|
callback(new_id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
dbus_connection:call("org.freedesktop.Notifications",
|
|
|
|
"/org/freedesktop/Notifications", "org.freedesktop.Notifications",
|
|
|
|
"Notify", parameters, reply_type, Gio.DBusCallFlags.NO_AUTO_START, -1,
|
|
|
|
nil, invoke_callback)
|
|
|
|
end
|
|
|
|
|
2019-01-04 09:24:28 +01:00
|
|
|
local steps = {}
|
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
local has_cmd_notify = false
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
-- Use `notify-send` instead of the shimmed version to better test the dbus
|
|
|
|
-- to notification code.
|
|
|
|
local function check_cmd()
|
|
|
|
local path = os.getenv("PATH")
|
|
|
|
local pos = 1
|
|
|
|
while path:find(":", pos) do
|
|
|
|
local np = path:find(":", pos)
|
|
|
|
local p = path:sub(pos, np-1).."/"
|
|
|
|
|
|
|
|
pos = np+1
|
|
|
|
|
|
|
|
local f = io.open(p.."notify-send")
|
|
|
|
if f then
|
|
|
|
f:close()
|
|
|
|
has_cmd_notify = true
|
|
|
|
end
|
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
if has_cmd_notify then return end
|
2019-01-04 09:24:28 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
check_cmd()
|
|
|
|
|
2019-02-17 10:21:18 +01:00
|
|
|
if not has_cmd_notify then
|
|
|
|
require("gears.debug").print_warning("Did not find notify-send, skipping some tests")
|
|
|
|
end
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
local active, destroyed, reasons, counter = {}, {}, {}, 0
|
|
|
|
|
|
|
|
local default_width, default_height = 0, 0
|
|
|
|
|
2019-02-16 21:18:33 +01:00
|
|
|
local function added_callback(n)
|
2019-01-04 09:24:28 +01:00
|
|
|
table.insert(active, n)
|
|
|
|
counter = counter + 1
|
2019-02-16 21:18:33 +01:00
|
|
|
end
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-16 21:18:33 +01:00
|
|
|
naughty.connect_signal("added", added_callback)
|
|
|
|
|
|
|
|
local function destroyed_callback(n, reason)
|
2019-01-04 09:24:28 +01:00
|
|
|
local found = false
|
|
|
|
|
|
|
|
for k, n2 in ipairs(active) do
|
|
|
|
if n2 == n then
|
|
|
|
found = true
|
|
|
|
table.remove(active, k)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert(found)
|
|
|
|
|
|
|
|
if reason then
|
|
|
|
reasons[reason] = reasons[reason] and reasons[reason] + 1 or 1
|
|
|
|
end
|
|
|
|
|
|
|
|
table.insert(destroyed, n)
|
2019-02-16 21:18:33 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
naughty.connect_signal("destroyed", destroyed_callback)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if not has_cmd_notify then return true end
|
|
|
|
|
naughty test: Use array-style spawn() calls
When a string is spawned, the C code has to split this into an array for
the execve() syscall. When an array is given directly, this array does
not need to be transformed in any way. This makes it much more clear
what is actually started.
This commit removes some quotation marks that were previously removed by
the C code. For example,
array:string:1,"four",2,"five",3,"six"
became
array:string:1,four,2,five,3,six
because otherwise the action was called "four" instead of four and the
test failed.
Signed-off-by: Uli Schlachter <psychon@znc.in>
2019-02-17 10:30:31 +01:00
|
|
|
spawn{ 'notify-send', 'title', 'message', '-t', '25000' }
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if not has_cmd_notify then return true end
|
|
|
|
if #active ~= 1 then return end
|
|
|
|
|
|
|
|
local n = active[1]
|
|
|
|
|
|
|
|
assert(n.box)
|
|
|
|
local offset = 2*n.box.border_width
|
|
|
|
default_width = n.box.width+offset
|
|
|
|
default_height = n.box.height + offset + naughty.config.spacing
|
|
|
|
|
|
|
|
assert(default_width > 0)
|
|
|
|
assert(default_height > 0)
|
|
|
|
|
|
|
|
-- Make sure the expiration timer is started
|
|
|
|
assert(n.timer)
|
|
|
|
assert(n.timer.started)
|
|
|
|
assert(n.is_expired == false)
|
|
|
|
|
|
|
|
n:destroy()
|
|
|
|
|
|
|
|
assert(#active == 0)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test pausing incoming notifications.
|
|
|
|
table.insert(steps, function()
|
|
|
|
assert(not naughty.suspended)
|
|
|
|
|
|
|
|
naughty.suspended = true
|
|
|
|
|
|
|
|
-- There is some magic behind this, check it works
|
|
|
|
assert(naughty.suspended)
|
|
|
|
|
naughty test: Use array-style spawn() calls
When a string is spawned, the C code has to split this into an array for
the execve() syscall. When an array is given directly, this array does
not need to be transformed in any way. This makes it much more clear
what is actually started.
This commit removes some quotation marks that were previously removed by
the C code. For example,
array:string:1,"four",2,"five",3,"six"
became
array:string:1,four,2,five,3,six
because otherwise the action was called "four" instead of four and the
test failed.
Signed-off-by: Uli Schlachter <psychon@znc.in>
2019-02-17 10:30:31 +01:00
|
|
|
spawn{ 'notify-send', 'title', 'message', '-t', '25000' }
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test resuming incoming notifications.
|
|
|
|
table.insert(steps, function(count)
|
|
|
|
if count ~= 4 then return end
|
|
|
|
|
|
|
|
assert(#active == 0)
|
|
|
|
assert(#naughty.notifications.suspended == 1)
|
|
|
|
assert(naughty.notifications.suspended[1]:get_suspended())
|
|
|
|
|
|
|
|
naughty.resume()
|
|
|
|
|
|
|
|
assert(not naughty.suspended)
|
|
|
|
assert(#naughty.notifications.suspended == 0)
|
|
|
|
assert(#active == 1)
|
|
|
|
|
|
|
|
active[1]:destroy()
|
|
|
|
assert(#active == 0)
|
|
|
|
|
naughty test: Use array-style spawn() calls
When a string is spawned, the C code has to split this into an array for
the execve() syscall. When an array is given directly, this array does
not need to be transformed in any way. This makes it much more clear
what is actually started.
This commit removes some quotation marks that were previously removed by
the C code. For example,
array:string:1,"four",2,"five",3,"six"
became
array:string:1,four,2,five,3,six
because otherwise the action was called "four" instead of four and the
test failed.
Signed-off-by: Uli Schlachter <psychon@znc.in>
2019-02-17 10:30:31 +01:00
|
|
|
spawn{ 'notify-send', 'title', 'message', '-t', '1' }
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test automatic expiration.
|
|
|
|
table.insert(steps, function()
|
|
|
|
if counter ~= 3 then return end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if #active > 0 then return end
|
|
|
|
|
|
|
|
-- It expired after one milliseconds, so it should be gone as soon as
|
|
|
|
-- it is registered.
|
|
|
|
assert(#active == 0)
|
|
|
|
|
|
|
|
assert(not naughty.expiration_paused)
|
|
|
|
naughty.expiration_paused = true
|
|
|
|
|
|
|
|
-- There is some magic behind this, make sure it works
|
|
|
|
assert(naughty.expiration_paused)
|
|
|
|
|
naughty test: Use array-style spawn() calls
When a string is spawned, the C code has to split this into an array for
the execve() syscall. When an array is given directly, this array does
not need to be transformed in any way. This makes it much more clear
what is actually started.
This commit removes some quotation marks that were previously removed by
the C code. For example,
array:string:1,"four",2,"five",3,"six"
became
array:string:1,four,2,five,3,six
because otherwise the action was called "four" instead of four and the
test failed.
Signed-off-by: Uli Schlachter <psychon@znc.in>
2019-02-17 10:30:31 +01:00
|
|
|
spawn{ 'notify-send', 'title', 'message', '-t', '1' }
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test disabling automatic expiration.
|
|
|
|
table.insert(steps, function()
|
|
|
|
if counter ~= 4 then return end
|
|
|
|
|
|
|
|
-- It should not expire by itself, so that should always be true
|
|
|
|
assert(#active == 1)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Wait long enough to avoid races.
|
|
|
|
table.insert(steps, function(count)
|
|
|
|
if count ~= 4 then return end
|
|
|
|
|
|
|
|
assert(#active == 1)
|
|
|
|
assert(active[1].is_expired)
|
|
|
|
|
|
|
|
naughty.expiration_paused = false
|
|
|
|
assert(not naughty.expiration_paused)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Make sure enabling expiration process the expired queue.
|
|
|
|
table.insert(steps, function()
|
|
|
|
-- Right now this doesn't require a step for itself, but this could change
|
|
|
|
-- so better not "document" the instantaneous clearing of the queue.
|
|
|
|
if #active > 0 then return end
|
|
|
|
|
naughty test: Use array-style spawn() calls
When a string is spawned, the C code has to split this into an array for
the execve() syscall. When an array is given directly, this array does
not need to be transformed in any way. This makes it much more clear
what is actually started.
This commit removes some quotation marks that were previously removed by
the C code. For example,
array:string:1,"four",2,"five",3,"six"
became
array:string:1,four,2,five,3,six
because otherwise the action was called "four" instead of four and the
test failed.
Signed-off-by: Uli Schlachter <psychon@znc.in>
2019-02-17 10:30:31 +01:00
|
|
|
spawn{ 'notify-send', 'low', 'message', '-t', '25000', '-u', 'low' }
|
|
|
|
spawn{ 'notify-send', 'normal', 'message', '-t', '25000', '-u', 'normal' }
|
|
|
|
spawn{ 'notify-send', 'critical', 'message', '-t', '25000', '-u', 'critical' }
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test the urgency level and default preset.
|
|
|
|
table.insert(steps, function()
|
|
|
|
if counter ~= 7 then return end
|
|
|
|
|
|
|
|
while #active > 0 do
|
|
|
|
active[1]:destroy()
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test what happens when the screen has the maximum number of notification it
|
|
|
|
-- can display at one.
|
|
|
|
table.insert(steps, function()
|
|
|
|
local wa = mouse.screen.workarea
|
|
|
|
local max_notif = math.floor(wa.height/default_height)
|
|
|
|
|
|
|
|
-- Everything should fit, otherwise the math is wrong in
|
|
|
|
-- `neughty.layout.legacy` and its a regression.
|
|
|
|
for i=1, max_notif do
|
naughty test: Use array-style spawn() calls
When a string is spawned, the C code has to split this into an array for
the execve() syscall. When an array is given directly, this array does
not need to be transformed in any way. This makes it much more clear
what is actually started.
This commit removes some quotation marks that were previously removed by
the C code. For example,
array:string:1,"four",2,"five",3,"six"
became
array:string:1,four,2,five,3,six
because otherwise the action was called "four" instead of four and the
test failed.
Signed-off-by: Uli Schlachter <psychon@znc.in>
2019-02-17 10:30:31 +01:00
|
|
|
spawn{ 'notify-send', 'notif '..i, 'message', '-t', '25000', '-u', 'low' }
|
2019-01-04 09:24:28 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test vertical overlapping
|
|
|
|
local function test_overlap()
|
|
|
|
local wa = mouse.screen.workarea
|
|
|
|
|
|
|
|
for _, n1 in ipairs(active) do
|
|
|
|
assert(n1.box)
|
2019-02-22 17:17:25 +01:00
|
|
|
assert(n1.id)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
|
|
|
-- Check for overlapping the workarea
|
|
|
|
assert(n1.box.y+default_height < wa.y+wa.height)
|
|
|
|
assert(n1.box.y >= wa.y)
|
|
|
|
|
|
|
|
-- Check for overlapping each other
|
|
|
|
for _, n2 in ipairs(active) do
|
|
|
|
assert(n2.box)
|
|
|
|
if n1 ~= n2 then
|
|
|
|
local geo1, geo2 = n1.box:geometry(), n2.box:geometry()
|
|
|
|
assert(geo1.height == geo2.height)
|
|
|
|
assert(geo1.height + 2*n1.box.border_width + naughty.config.spacing
|
|
|
|
== default_height)
|
|
|
|
|
|
|
|
if n1.position == n2.position then
|
|
|
|
assert(
|
|
|
|
geo1.y >= geo2.y+default_height or
|
|
|
|
geo2.y >= geo1.y+default_height
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Check the lack of overlapping and the presence of the expected content.
|
|
|
|
table.insert(steps, function()
|
|
|
|
local wa = mouse.screen.workarea
|
|
|
|
local max_notif = math.floor(wa.height/default_height)
|
|
|
|
if counter ~= 7 + max_notif then return end
|
|
|
|
|
|
|
|
assert(#active == max_notif)
|
|
|
|
|
|
|
|
test_overlap()
|
|
|
|
|
|
|
|
-- Now add even more!
|
|
|
|
for i=1, 5 do
|
naughty test: Use array-style spawn() calls
When a string is spawned, the C code has to split this into an array for
the execve() syscall. When an array is given directly, this array does
not need to be transformed in any way. This makes it much more clear
what is actually started.
This commit removes some quotation marks that were previously removed by
the C code. For example,
array:string:1,"four",2,"five",3,"six"
became
array:string:1,four,2,five,3,six
because otherwise the action was called "four" instead of four and the
test failed.
Signed-off-by: Uli Schlachter <psychon@znc.in>
2019-02-17 10:30:31 +01:00
|
|
|
spawn{ 'notify-send', 'notif '..i, 'message', '-t', '25000', '-u', 'low' }
|
2019-01-04 09:24:28 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test the code to hide the older notifications when there is too many for the
|
|
|
|
-- screen.
|
|
|
|
table.insert(steps, function()
|
|
|
|
local wa = mouse.screen.workarea
|
|
|
|
local max_notif = math.floor(wa.height/default_height)
|
|
|
|
if counter ~= 7 + max_notif + 5 then return end
|
|
|
|
|
|
|
|
-- The other should have been hidden
|
|
|
|
assert(#active == max_notif)
|
|
|
|
|
|
|
|
assert(reasons[naughty.notification_closed_reason.too_many_on_screen] == 5)
|
|
|
|
|
|
|
|
test_overlap()
|
|
|
|
|
|
|
|
while #active > 0 do
|
|
|
|
active[1]:destroy()
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
local positions = {
|
|
|
|
"top_left" , "top_middle" , "top_right" ,
|
|
|
|
"bottom_left" , "bottom_middle" , "bottom_right" ,
|
|
|
|
}
|
|
|
|
|
|
|
|
-- Test each corners.
|
|
|
|
table.insert(steps, function()
|
|
|
|
for _, pos in ipairs(positions) do
|
|
|
|
for i=1, 3 do
|
|
|
|
-- Skip dbus for this one.
|
|
|
|
naughty.notification {
|
|
|
|
position = pos,
|
|
|
|
title = "At "..pos.." "..i,
|
|
|
|
message = "some message",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if #active ~= #positions*3 then return end
|
|
|
|
|
|
|
|
test_overlap()
|
|
|
|
|
|
|
|
while #active > 0 do
|
|
|
|
active[1]:destroy()
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
local big_icon = cairo.ImageSurface(cairo.Format.ARGB32, 256, 256)
|
|
|
|
local cr = cairo.Context(big_icon)
|
|
|
|
local small_icon = cairo.ImageSurface(cairo.Format.ARGB32, 32 , 32 )
|
|
|
|
local cr2 = cairo.Context(small_icon)
|
|
|
|
local wierd_ratio1 = cairo.ImageSurface(cairo.Format.ARGB32, 256, 128)
|
|
|
|
local cr3 = cairo.Context(wierd_ratio1)
|
|
|
|
local wierd_ratio2 = cairo.ImageSurface(cairo.Format.ARGB32, 128, 256)
|
|
|
|
local cr4 = cairo.Context(wierd_ratio2)
|
|
|
|
|
|
|
|
-- Checkboard shirt pattern icon!
|
|
|
|
for i=1, 5 do
|
|
|
|
for j=1, 5 do
|
|
|
|
cr:set_source_rgb(
|
|
|
|
i%2 == 1 and 1 or 0, j%2 == 1 and 1 or 0, i%2 == 0 and 0 or 1
|
|
|
|
)
|
|
|
|
cr:rectangle( (i-1)*48, (j-1)*48, 48, 48 )
|
|
|
|
cr:fill()
|
|
|
|
|
|
|
|
cr2:set_source_rgb(
|
|
|
|
i%2 == 1 and 1 or 0, j%2 == 1 and 1 or 0, i%2 == 0 and 0 or 1
|
|
|
|
)
|
|
|
|
cr2:rectangle( (i-1)*6, (j-1)*6, 6, 6 )
|
|
|
|
cr2:fill()
|
|
|
|
|
|
|
|
cr3:set_source_rgb(
|
|
|
|
i%2 == 1 and 1 or 0, j%2 == 1 and 1 or 0, i%2 == 0 and 0 or 1
|
|
|
|
)
|
|
|
|
cr3:rectangle( (i-1)*48, (j-1)*24, 48, 24 )
|
|
|
|
cr3:fill()
|
|
|
|
|
|
|
|
cr4:set_source_rgb(
|
|
|
|
i%2 == 1 and 1 or 0, j%2 == 1 and 1 or 0, i%2 == 0 and 0 or 1
|
|
|
|
)
|
|
|
|
cr4:rectangle( (i-1)*24, (j-1)*48, 24, 48 )
|
|
|
|
cr4:fill()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Test the icon size constraints.
|
|
|
|
table.insert(steps, function()
|
|
|
|
beautiful.notification_icon_size = 64
|
|
|
|
|
|
|
|
-- Icons that are too large (they should be downscaled)
|
|
|
|
local n1 = naughty.notification {
|
|
|
|
icon = big_icon,
|
|
|
|
title = "Has a nice icon!",
|
|
|
|
message = "big",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
2019-02-22 17:17:25 +01:00
|
|
|
assert(n1.id)
|
2019-01-04 09:24:28 +01:00
|
|
|
assert(n1.iconbox)
|
|
|
|
assert(n1.iconbox._private.image:get_width () == beautiful.notification_icon_size)
|
|
|
|
assert(n1.iconbox._private.image:get_height() == beautiful.notification_icon_size)
|
|
|
|
assert(n1.iconbox._private.image:get_width () == n1.size_info.icon_w)
|
|
|
|
assert(n1.iconbox._private.image:get_height() == n1.size_info.icon_h)
|
|
|
|
assert(n1.size_info.icon_scale_factor == 1/4)
|
|
|
|
|
|
|
|
-- Icons that are too small (they should not be upscaled)
|
|
|
|
local n2 = naughty.notification {
|
|
|
|
icon = small_icon,
|
|
|
|
title = "Has a nice icon!",
|
|
|
|
message = "small",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
2019-02-22 17:17:25 +01:00
|
|
|
assert(n2.id)
|
2019-01-04 09:24:28 +01:00
|
|
|
assert(n2.iconbox)
|
|
|
|
assert(n2.iconbox._private.image:get_width () == 32)
|
|
|
|
assert(n2.iconbox._private.image:get_height() == 32)
|
|
|
|
assert(n2.iconbox._private.image:get_width () == n2.size_info.icon_w)
|
|
|
|
assert(n2.iconbox._private.image:get_height() == n2.size_info.icon_h)
|
|
|
|
assert(not n2.size_info.icon_scale_factor)
|
|
|
|
|
|
|
|
-- Downscaled non square icons (aspect ratio should be kept).
|
|
|
|
local n3 = naughty.notification {
|
|
|
|
icon = wierd_ratio1,
|
|
|
|
title = "Has a nice icon!",
|
|
|
|
message = "big",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
local n4 = naughty.notification {
|
|
|
|
icon = wierd_ratio2,
|
|
|
|
title = "Has a nice icon!",
|
|
|
|
message = "big",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(n3.iconbox)
|
|
|
|
assert(n3.iconbox._private.image:get_width () == beautiful.notification_icon_size)
|
|
|
|
assert(n3.iconbox._private.image:get_height() == beautiful.notification_icon_size/2)
|
|
|
|
assert(n3.iconbox._private.image:get_width () == n3.size_info.icon_w)
|
|
|
|
assert(n3.iconbox._private.image:get_height() == n3.size_info.icon_h)
|
|
|
|
assert(n3.size_info.icon_scale_factor == 1/4)
|
|
|
|
|
|
|
|
assert(n4.iconbox)
|
|
|
|
assert(n4.iconbox._private.image:get_width () == beautiful.notification_icon_size/2)
|
|
|
|
assert(n4.iconbox._private.image:get_height() == beautiful.notification_icon_size)
|
|
|
|
assert(n4.iconbox._private.image:get_width () == n4.size_info.icon_w)
|
|
|
|
assert(n4.iconbox._private.image:get_height() == n4.size_info.icon_h)
|
|
|
|
assert(n4.size_info.icon_scale_factor == 1/4)
|
|
|
|
|
|
|
|
-- The notification size should change proportionally to the icon size.
|
|
|
|
assert(n1.box.width == n2.box.width + 32)
|
|
|
|
assert(n1.box.height == n2.box.height + 32)
|
|
|
|
assert(n1.box.height == n3.box.height + 32)
|
|
|
|
assert(n1.box.width == n4.box.width + 32)
|
|
|
|
assert(n1.box.height == n4.box.height)
|
|
|
|
assert(n1.box.width == n3.box.width )
|
|
|
|
|
|
|
|
-- Make sure unconstrained icons work as expected.
|
|
|
|
beautiful.notification_icon_size = nil
|
|
|
|
|
|
|
|
local n5 = naughty.notification {
|
|
|
|
icon = big_icon,
|
|
|
|
title = "Has a nice icon!",
|
|
|
|
message = "big",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(n5.iconbox)
|
|
|
|
assert(n5.iconbox._private.image:get_width () == 256)
|
|
|
|
assert(n5.iconbox._private.image:get_height() == 256)
|
|
|
|
assert(n5.iconbox._private.image:get_width () == n5.size_info.icon_w)
|
|
|
|
assert(n5.iconbox._private.image:get_height() == n5.size_info.icon_h)
|
|
|
|
assert(not n5.size_info.icon_scale_factor)
|
|
|
|
|
|
|
|
-- Make sure invalid icons don't prevent the message from being shown.
|
|
|
|
local n6 = naughty.notification {
|
|
|
|
icon = "this/is/an/invlid/path",
|
|
|
|
title = "Has a nice icon!",
|
|
|
|
message = "Very important life saving advice",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
n1:destroy()
|
|
|
|
n2:destroy()
|
|
|
|
n3:destroy()
|
|
|
|
n4:destroy()
|
|
|
|
n5:destroy()
|
|
|
|
n6:destroy()
|
|
|
|
assert(#active == 0)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test notifications with size constraints.
|
|
|
|
table.insert(steps, function()
|
|
|
|
local str = "foobar! "
|
|
|
|
assert(#active == 0)
|
|
|
|
|
|
|
|
-- 2^9 foobars is a lot of foobars.
|
|
|
|
for _=1, 10 do
|
|
|
|
str = str .. str
|
|
|
|
end
|
|
|
|
|
|
|
|
-- First, see what happen without any constraint and enormous messages.
|
|
|
|
-- This also test notifications larger than the workarea.
|
|
|
|
|
|
|
|
local n1 = naughty.notification {
|
|
|
|
title = str,
|
|
|
|
message = str,
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
-- Same, but with an icon and larger borders.
|
|
|
|
local n2 = naughty.notification {
|
|
|
|
icon = big_icon,
|
|
|
|
title = str,
|
|
|
|
message = str,
|
|
|
|
timeout = 25000,
|
|
|
|
border_width = 40,
|
|
|
|
}
|
|
|
|
|
|
|
|
local wa = mouse.screen.workarea
|
|
|
|
assert(n1.box.width +2*n1.box.border_width <= wa.width )
|
|
|
|
assert(n1.box.height+2*n1.box.border_width <= wa.height)
|
|
|
|
assert(n2.box.width +2*n2.box.border_width <= wa.width )
|
|
|
|
assert(n2.box.height+2*n2.box.border_width <= wa.height)
|
|
|
|
|
|
|
|
n1:destroy()
|
|
|
|
n2:destroy()
|
|
|
|
|
|
|
|
-- Now set a maximum size and try again.
|
|
|
|
beautiful.notification_max_width = 256
|
|
|
|
beautiful.notification_max_height = 96
|
|
|
|
|
|
|
|
local n3 = naughty.notification {
|
|
|
|
title = str,
|
|
|
|
message = str,
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(n3.box.width <= 256)
|
|
|
|
assert(n3.box.height <= 96 )
|
|
|
|
|
|
|
|
-- Now test when the icon is larger than the maximum.
|
|
|
|
local n4 = naughty.notification {
|
|
|
|
icon = big_icon,
|
|
|
|
title = str,
|
|
|
|
message = str,
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(n4.box.width <= 256)
|
|
|
|
assert(n4.box.height <= 96 )
|
|
|
|
assert(n4.iconbox._private.image:get_width () == n4.size_info.icon_w)
|
|
|
|
assert(n4.iconbox._private.image:get_height() == n4.size_info.icon_h)
|
|
|
|
assert(n4.size_info.icon_w <= 256)
|
|
|
|
assert(n4.size_info.icon_h <= 96 )
|
|
|
|
|
|
|
|
n3:destroy()
|
|
|
|
n4:destroy()
|
|
|
|
assert(#active == 0)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test more advanced features than what notify-send can provide.
|
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
-- Test the actions.
|
|
|
|
table.insert(steps, function()
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
assert(#active == 0)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
send_notify("Awesome test", 0, "", "title", "message body",
|
|
|
|
{ "1", "one", "2", "two", "3", "three" }, {}, 25000)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
return true
|
|
|
|
end)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
table.insert(steps, function()
|
|
|
|
if #active == 0 then return end
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
assert(#active == 1)
|
|
|
|
local n = active[1]
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
assert(n.box)
|
|
|
|
assert(#n.actions == 3)
|
|
|
|
assert(n.actions[1].name == "one" )
|
|
|
|
assert(n.actions[2].name == "two" )
|
|
|
|
assert(n.actions[3].name == "three")
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
n:destroy()
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
return true
|
|
|
|
end)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
--TODO Test too many actions.
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
--TODO Test action with long names.
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
local nid, name_u, message_u, actions_u = nil
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
-- Test updating a notification.
|
|
|
|
table.insert(steps, function()
|
|
|
|
send_notify("Awesome test", 0, "", "title", "message body",
|
|
|
|
{ "1", "one", "2", "two", "3", "three" }, {}, 25000, function(id)
|
|
|
|
nid = id
|
2019-01-04 09:24:28 +01:00
|
|
|
end)
|
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
return true
|
|
|
|
end)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
table.insert(steps, function()
|
|
|
|
if #active == 0 or not nid then return end
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
local n = active[1]
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
n:connect_signal("property::title" , function() name_u = true end)
|
|
|
|
n:connect_signal("property::message", function() message_u = true end)
|
|
|
|
n:connect_signal("property::actions", function() actions_u = true end)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
send_notify("Awesome test", nid, "", "updated title", "updated message body",
|
|
|
|
{ "1", "four", "2", "five", "3", "six" }, {}, 25000)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
return true
|
|
|
|
end)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
-- Test if all properties have been updated.
|
|
|
|
table.insert(steps, function()
|
|
|
|
if not name_u then return end
|
|
|
|
if not message_u then return end
|
|
|
|
if not actions_u then return end
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
-- No new notification should have been created.
|
|
|
|
assert(#active == 1)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
local n = active[1]
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
assert(n.title == "updated title" )
|
|
|
|
assert(n.message == "updated message body")
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
assert(#n.actions == 3)
|
|
|
|
assert(n.actions[1].name == "four" )
|
|
|
|
assert(n.actions[2].name == "five" )
|
|
|
|
assert(n.actions[3].name == "six" )
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-19 18:35:09 +01:00
|
|
|
return true
|
|
|
|
end)
|
2019-01-04 09:24:28 +01:00
|
|
|
|
2019-02-22 17:17:25 +01:00
|
|
|
local int_n = nil
|
|
|
|
|
|
|
|
-- Test replace_id with internally generated notifications.
|
|
|
|
-- Even if it makes little sense, it should work and is used in the wild.
|
|
|
|
table.insert(steps, function()
|
|
|
|
int_n = naughty.notification {
|
|
|
|
title = "foo",
|
|
|
|
message = "bar",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
local nid2 = int_n.id
|
|
|
|
assert(int_n.id)
|
|
|
|
local res, err = pcall(function()
|
|
|
|
int_n.id = 1337
|
|
|
|
end)
|
|
|
|
|
|
|
|
assert(err:match("Notification identifier can only be set once"))
|
|
|
|
assert(not res)
|
|
|
|
assert(int_n.id == nid2)
|
|
|
|
|
|
|
|
-- watch out, capi.dbus signals are not normal object signals
|
|
|
|
send_notify("Awesome test", nid2, "", "title2", "text2",
|
|
|
|
{ "the one action" }, {}, 123)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Test that the values were replaced
|
|
|
|
table.insert(steps, function()
|
|
|
|
if int_n.title ~= "title2" then return end
|
|
|
|
|
|
|
|
assert(int_n.title == "title2")
|
|
|
|
assert(int_n.message == "text2" )
|
|
|
|
--assert(int_n.timeout == 123 ) --FIXME
|
|
|
|
int_n:destroy()
|
|
|
|
|
|
|
|
--TODO test what happens when updating a destroyed notification
|
|
|
|
-- There is currently no API to resurrect notifications.
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
2019-02-16 21:18:33 +01:00
|
|
|
-- Now check if the old deprecated (but still supported) APIs don't have errors.
|
|
|
|
table.insert(steps, function()
|
|
|
|
-- Tests are (by default) not allowed to call deprecated APIs
|
|
|
|
gdebug.deprecate = function() end
|
|
|
|
|
|
|
|
local n = naughty.notification {
|
|
|
|
title = "foo",
|
|
|
|
message = "bar",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
|
|
|
|
-- Make sure the suspension don't cause errors
|
|
|
|
assert(not naughty.is_suspended())
|
|
|
|
assert(not naughty.suspended)
|
|
|
|
naughty.suspend()
|
|
|
|
assert(naughty.is_suspended())
|
|
|
|
assert(naughty.suspended)
|
|
|
|
naughty.resume()
|
|
|
|
assert(not naughty.is_suspended())
|
|
|
|
assert(not naughty.suspended)
|
|
|
|
naughty.toggle()
|
|
|
|
assert(naughty.is_suspended())
|
|
|
|
assert(naughty.suspended)
|
|
|
|
naughty.toggle()
|
|
|
|
assert(not naughty.is_suspended())
|
|
|
|
assert(not naughty.suspended)
|
|
|
|
naughty.suspended = not naughty.suspended
|
|
|
|
assert(naughty.is_suspended())
|
|
|
|
assert(naughty.suspended)
|
|
|
|
naughty.suspended = not naughty.suspended
|
|
|
|
assert(not naughty.is_suspended())
|
|
|
|
assert(not naughty.suspended)
|
|
|
|
|
|
|
|
-- Replace the text
|
2019-02-24 19:21:04 +01:00
|
|
|
assert(n.title == "foo")
|
2019-02-16 21:18:33 +01:00
|
|
|
assert(n.message == "bar")
|
|
|
|
assert(n.text == "bar")
|
2019-02-24 19:21:04 +01:00
|
|
|
local width, height = n.width, n.height
|
|
|
|
assert(width)
|
|
|
|
assert(height)
|
2019-02-16 21:18:33 +01:00
|
|
|
naughty.replace_text(n, "foobar", "baz")
|
|
|
|
assert(n.title == "foobar")
|
|
|
|
assert(n.message == "baz")
|
|
|
|
assert(n.text == "baz")
|
2019-02-24 19:21:04 +01:00
|
|
|
assert(n.width > width)
|
|
|
|
assert(n.height == height)
|
|
|
|
width, height = n.width, n.height
|
|
|
|
naughty.replace_text(n, "foo", "bar\nbaz")
|
|
|
|
assert(n.title == "foo")
|
|
|
|
assert(n.message == "bar\nbaz")
|
|
|
|
assert(n.text == "bar\nbaz")
|
|
|
|
assert(n.width < width)
|
|
|
|
assert(n.height > height)
|
|
|
|
width, height = n.width, n.height
|
|
|
|
naughty.replace_text(n, "foo", "bar")
|
|
|
|
assert(n.title == "foo")
|
|
|
|
assert(n.message == "bar")
|
|
|
|
assert(n.text == "bar")
|
|
|
|
assert(n.width == width)
|
|
|
|
assert(n.height < height)
|
2019-02-16 21:18:33 +01:00
|
|
|
|
|
|
|
-- Test the ID system
|
2019-02-22 17:17:25 +01:00
|
|
|
local id = n.id
|
|
|
|
assert(naughty.getById(id) == n)
|
|
|
|
assert(naughty.get_by_id(id) == n)
|
|
|
|
assert(naughty.getById(42) ~= n)
|
|
|
|
assert(naughty.get_by_id(42) ~= n)
|
2019-02-16 21:18:33 +01:00
|
|
|
|
|
|
|
-- The timeout
|
|
|
|
naughty.reset_timeout(n, 1337)
|
|
|
|
|
|
|
|
-- Destroy using the old API
|
|
|
|
local old_count = #destroyed
|
|
|
|
naughty.destroy(n)
|
|
|
|
assert(old_count == #destroyed - 1)
|
|
|
|
|
|
|
|
-- Destroy using the old API, while suspended
|
|
|
|
local n2 = naughty.notification {
|
|
|
|
title = "foo",
|
|
|
|
message = "bar",
|
|
|
|
timeout = 25000,
|
|
|
|
}
|
|
|
|
naughty.suspended = true
|
|
|
|
naughty.destroy(n2)
|
|
|
|
assert(old_count == #destroyed - 2)
|
|
|
|
naughty.suspended = false
|
|
|
|
|
|
|
|
-- The old notify function and "text" instead of "message"
|
|
|
|
naughty.notify { text = "foo" }
|
|
|
|
|
|
|
|
-- Finish by testing disconnect_signal
|
|
|
|
naughty.disconnect_signal("destroyed", destroyed_callback)
|
|
|
|
naughty.disconnect_signal("added", added_callback)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
2019-01-04 09:24:28 +01:00
|
|
|
-- Test many screens.
|
|
|
|
|
|
|
|
require("_runner").run_steps(steps)
|