Merge pull request #2988 from Elv13/notif_rules_groundwork
Fix multiple notifications issue
This commit is contained in:
commit
59b31e74b3
|
@ -1533,7 +1533,7 @@ function placement.next_to(d, args)
|
|||
|
||||
geo.width, geo.height = dgeo.width, dgeo.height
|
||||
|
||||
fit = fit_in_bounding(pos.region.screen, geo, args)
|
||||
fit = fit_in_bounding(pos.region, geo, args)
|
||||
|
||||
if fit then break end
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
-- @popupmod awful.popup
|
||||
---------------------------------------------------------------------------
|
||||
local wibox = require( "wibox" )
|
||||
local util = require( "awful.util" )
|
||||
local gtable = require( "gears.table" )
|
||||
local placement = require( "awful.placement" )
|
||||
local xresources= require("beautiful.xresources")
|
||||
local timer = require( "gears.timer" )
|
||||
|
@ -441,7 +441,7 @@ local function create_popup(_, args)
|
|||
enable_properties = true
|
||||
})
|
||||
|
||||
util.table.crush(ii, main_widget, true)
|
||||
gtable.crush(ii, main_widget, true)
|
||||
|
||||
-- Create a wibox to host the widget
|
||||
local w = wibox(args or {})
|
||||
|
@ -453,7 +453,7 @@ local function create_popup(_, args)
|
|||
widget = child_widget
|
||||
})
|
||||
|
||||
util.table.crush(w, popup)
|
||||
gtable.crush(w, popup)
|
||||
|
||||
ii:set_widget(child_widget)
|
||||
|
||||
|
|
|
@ -80,9 +80,17 @@ end
|
|||
|
||||
--- Return true whether rectangle B is in the right direction
|
||||
-- compared to rectangle A.
|
||||
-- @param dir The direction.
|
||||
-- @param gA The geometric specification for rectangle A.
|
||||
-- @param gB The geometric specification for rectangle B.
|
||||
--
|
||||
-- The valid `dir` are:
|
||||
--
|
||||
-- * up
|
||||
-- * down
|
||||
-- * left
|
||||
-- * right
|
||||
--
|
||||
-- @tparam string dir The direction.
|
||||
-- @tparam table gA The geometric specification for rectangle A.
|
||||
-- @tparam table gB The geometric specification for rectangle B.
|
||||
-- @return True if B is in the direction of A.
|
||||
local function is_in_direction(dir, gA, gB)
|
||||
if dir == "up" then
|
||||
|
@ -100,9 +108,17 @@ end
|
|||
--- Calculate distance between two points.
|
||||
-- i.e: if we want to move to the right, we will take the right border
|
||||
-- of the currently focused screen and the left side of the checked screen.
|
||||
-- @param dir The direction.
|
||||
-- @param _gA The first rectangle.
|
||||
-- @param _gB The second rectangle.
|
||||
--
|
||||
-- The valid `dir` are:
|
||||
--
|
||||
-- * up
|
||||
-- * down
|
||||
-- * left
|
||||
-- * right
|
||||
--
|
||||
-- @tparam string dir The direction.
|
||||
-- @tparam table _gA The first rectangle.
|
||||
-- @tparam table _gB The second rectangle.
|
||||
-- @return The distance between the screens.
|
||||
local function calculate_distance(dir, _gA, _gB)
|
||||
local gAx = _gA.x
|
||||
|
@ -158,6 +174,7 @@ end
|
|||
-- @tparam table a The area.
|
||||
-- @tparam table b The other area.
|
||||
-- @treturn boolean If the areas are identical.
|
||||
-- @staticfct gears.geometry.rectangle.are_equal
|
||||
function gears.geometry.rectangle.are_equal(a, b)
|
||||
for _, v in ipairs {"x", "y", "width", "height"} do
|
||||
if a[v] ~= b[v] then return false end
|
||||
|
@ -165,9 +182,28 @@ function gears.geometry.rectangle.are_equal(a, b)
|
|||
return true
|
||||
end
|
||||
|
||||
--- Return if rectangle `a` is within rectangle `b`.
|
||||
--
|
||||
-- This includes the edges. 100% of `a` area has to be within `b` for this
|
||||
-- function to return true. If you wish to know if any part of `a` intersect
|
||||
-- with `b`, use `gears.geometry.rectangle.get_intersection`.
|
||||
--
|
||||
-- @tparam table a The smaller area.
|
||||
-- @tparam table b The larger area.
|
||||
-- @treturn boolean If the areas are identical.
|
||||
-- @staticfct gears.geometry.rectangle.is_inside
|
||||
-- @see gears.geometry.rectangle.get_intersection
|
||||
function gears.geometry.rectangle.is_inside(a, b)
|
||||
return (a.x >= b.x
|
||||
and a.y >= b.y
|
||||
and a.x+a.width <= b.x + b.width
|
||||
and a.y+a.height <= b.y + b.height
|
||||
)
|
||||
end
|
||||
|
||||
--- Check if an area intersect another area.
|
||||
-- @param a The area.
|
||||
-- @param b The other area.
|
||||
-- @tparam table a The area.
|
||||
-- @tparam table b The other area.
|
||||
-- @return True if they intersect, false otherwise.
|
||||
-- @staticfct gears.geometry.rectangle.area_intersect_area
|
||||
function gears.geometry.rectangle.area_intersect_area(a, b)
|
||||
|
@ -190,6 +226,7 @@ end
|
|||
-- @tparam number b.height The rectangle height
|
||||
-- @treturn table The intersect area.
|
||||
-- @staticfct gears.geometry.rectangle.get_intersection
|
||||
-- @see gears.geometry.rectangle.is_inside
|
||||
function gears.geometry.rectangle.get_intersection(a, b)
|
||||
local g = {}
|
||||
g.x = math.max(a.x, b.x)
|
||||
|
|
|
@ -27,6 +27,7 @@ local action = {}
|
|||
-- The action name.
|
||||
-- @property name
|
||||
-- @tparam string name The name.
|
||||
-- @propemits true false
|
||||
|
||||
-- If the action is selected.
|
||||
--
|
||||
|
@ -35,14 +36,17 @@ local action = {}
|
|||
--
|
||||
-- @property selected
|
||||
-- @param boolean
|
||||
-- @propemits true false
|
||||
|
||||
--- The action position (index).
|
||||
-- @property position
|
||||
-- @param number
|
||||
-- @propemits true false
|
||||
|
||||
--- The action icon.
|
||||
-- @property icon
|
||||
-- @tparam gears.surface|string icon
|
||||
-- @propemits true false
|
||||
|
||||
--- If the action should hide the label and only display the icon.
|
||||
--
|
||||
|
@ -50,6 +54,7 @@ local action = {}
|
|||
--
|
||||
-- @property icon_only
|
||||
-- @param[opt=false] boolean
|
||||
-- @propemits true false
|
||||
|
||||
--- When a notification is invoked.
|
||||
-- @signal invoked
|
||||
|
|
|
@ -36,13 +36,14 @@ local function update_background(notif, wdg)
|
|||
|
||||
wdg:set_bg(bg)
|
||||
wdg:set_shape(shape) -- otherwise there's no borders
|
||||
wdg:set_shape_border_width(bw)
|
||||
wdg:set_shape_border_color(bc)
|
||||
wdg:set_border_width(bw)
|
||||
wdg:set_border_color(bc)
|
||||
end
|
||||
|
||||
--- The attached notification.
|
||||
-- @property notification
|
||||
-- @tparam naughty.notification notification
|
||||
-- @propemits true false
|
||||
|
||||
function background:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
|
@ -66,12 +67,16 @@ function background:set_notification(notif)
|
|||
notif:connect_signal("property::border_width", self._private.background_changed_callback)
|
||||
notif:connect_signal("property::border_color", self._private.background_changed_callback)
|
||||
notif:connect_signal("property::shape" , self._private.background_changed_callback)
|
||||
self:emit_signal("property::notification", notif)
|
||||
end
|
||||
|
||||
--- Create a new naughty.container.background.
|
||||
-- @tparam table args
|
||||
-- @tparam naughty.notification args.notification The notification.
|
||||
-- @constructorfct naughty.container.background
|
||||
-- @usebeautiful beautiful.notification_border_width Fallback when the `border_width` property isn't set.
|
||||
-- @usebeautiful beautiful.notification_border_color Fallback when the `border_color` property isn't set.
|
||||
-- @usebeautiful beautiful.notification_shape Fallback when the `shape` property isn't set.
|
||||
|
||||
local function new(args)
|
||||
args = args or {}
|
||||
|
|
|
@ -102,6 +102,8 @@ gtable.crush(naughty, require("naughty.constants"))
|
|||
--
|
||||
-- @property suspended
|
||||
-- @param boolean
|
||||
-- @emits added
|
||||
-- @propemits true false
|
||||
|
||||
--- Do not allow notifications to auto-expire.
|
||||
--
|
||||
|
@ -111,6 +113,7 @@ gtable.crush(naughty, require("naughty.constants"))
|
|||
--
|
||||
-- @property expiration_paused
|
||||
-- @param[opt=false] boolean
|
||||
-- @propemits true false
|
||||
|
||||
--- A table with all active notifications.
|
||||
--
|
||||
|
@ -122,6 +125,7 @@ gtable.crush(naughty, require("naughty.constants"))
|
|||
--
|
||||
-- @property active
|
||||
-- @param table
|
||||
-- @propemits false false
|
||||
|
||||
--- True when there is a handler connected to `request::display`.
|
||||
-- @property has_display_handler
|
||||
|
@ -134,6 +138,7 @@ gtable.crush(naughty, require("naughty.constants"))
|
|||
--
|
||||
-- @property auto_reset_timeout
|
||||
-- @tparam[opt=true] boolean auto_reset_timeout
|
||||
-- @propemits true false
|
||||
|
||||
--- Enable or disable naughty ability to claim to support animations.
|
||||
--
|
||||
|
@ -143,6 +148,7 @@ gtable.crush(naughty, require("naughty.constants"))
|
|||
--
|
||||
-- @property image_animations_enabled
|
||||
-- @param[opt=false] boolean
|
||||
-- @propemits true false
|
||||
|
||||
--- Enable or disable the persistent notifications.
|
||||
--
|
||||
|
@ -158,6 +164,7 @@ gtable.crush(naughty, require("naughty.constants"))
|
|||
--
|
||||
-- @property persistence_enabled
|
||||
-- @param[opt=false] boolean
|
||||
-- @propemits true false
|
||||
|
||||
local properties = {
|
||||
suspended = false,
|
||||
|
@ -196,6 +203,16 @@ screen.connect_for_each_screen(function(s)
|
|||
end)
|
||||
|
||||
capi.screen.connect_signal("removed", function(scr)
|
||||
-- Allow the notifications to be moved to another screen.
|
||||
|
||||
for _, list in pairs(naughty.notifications[scr]) do
|
||||
-- Clone the list to avoid having an iterator while mutating.
|
||||
list = gtable.clone(list, false)
|
||||
|
||||
for _, n in ipairs(list) do
|
||||
naughty.emit_signal("request::screen", n, "removed", {})
|
||||
end
|
||||
end
|
||||
-- Destroy all notifications on this screen
|
||||
naughty.destroy_all_notifications({scr})
|
||||
naughty.notifications[scr] = nil
|
||||
|
@ -210,6 +227,7 @@ local function remove_from_index(n)
|
|||
for _, ns in pairs(positions) do
|
||||
for k, n2 in ipairs(ns) do
|
||||
if n2 == n then
|
||||
assert(ns[k+1] ~= n, "The notification index is corrupted")
|
||||
table.remove(ns, k)
|
||||
return
|
||||
end
|
||||
|
@ -220,6 +238,11 @@ end
|
|||
|
||||
-- When id or screen are set after the object is created, update the indexing.
|
||||
local function update_index(n)
|
||||
-- Do things in the right order.
|
||||
if not n._private.registered then return end
|
||||
|
||||
assert(not n._private.is_destroyed, "The notification index is corrupted")
|
||||
|
||||
-- Find the only index and remove it (there's an useless loop, but it's small).
|
||||
remove_from_index(n)
|
||||
|
||||
|
@ -231,7 +254,6 @@ local function update_index(n)
|
|||
table.insert(naughty.notifications[s][n.position], n)
|
||||
end
|
||||
|
||||
|
||||
--- Notification state.
|
||||
--
|
||||
-- This function is deprecated, use `naughty.suspended`.
|
||||
|
@ -357,6 +379,9 @@ function naughty.destroy_all_notifications(screens, reason)
|
|||
for _, scr in pairs(screens) do
|
||||
for _, list in pairs(naughty.notifications[scr]) do
|
||||
while #list > 0 do
|
||||
-- Better cause an error than risk an infinite loop.
|
||||
assert(not list[1]._private.is_destroyed)
|
||||
|
||||
ret = ret and list[1]:destroy(reason)
|
||||
end
|
||||
end
|
||||
|
@ -406,6 +431,10 @@ function naughty.get__has_preset_handler()
|
|||
return conns["request::preset"] and #conns["request::preset"] > 0 or false
|
||||
end
|
||||
|
||||
function naughty._reset_display_handlers()
|
||||
conns["request::display"] = nil
|
||||
end
|
||||
|
||||
--- Set new notification timeout.
|
||||
--
|
||||
-- This function is deprecated, use `notification:reset_timeout(new_timeout)`.
|
||||
|
@ -500,6 +529,20 @@ function naughty.set_expiration_paused(p)
|
|||
end
|
||||
end
|
||||
|
||||
--- The default handler for `request::screen`.
|
||||
--
|
||||
-- It selects `awful.screen.focused()`.
|
||||
--
|
||||
-- @signalhandler naughty.default_screen_handler
|
||||
|
||||
function naughty.default_screen_handler(n)
|
||||
if n.screen and n.screen.valid then return end
|
||||
|
||||
n.screen = screen.focused()
|
||||
end
|
||||
|
||||
naughty.connect_signal("request::screen", naughty.default_screen_handler)
|
||||
|
||||
--- Emitted when an error occurred and requires attention.
|
||||
-- @signal request::display_error
|
||||
-- @tparam string message The error message.
|
||||
|
@ -546,15 +589,28 @@ end
|
|||
-- @tparam naughty.action action The action.
|
||||
-- @tparam string icon_name The icon name.
|
||||
|
||||
--- Emitted when the screen is not defined or being removed.
|
||||
-- @signal request::screen
|
||||
-- @tparam table notification The `naughty.notification` object. This is
|
||||
-- currently either "new" or "removed".
|
||||
-- @tparam string context Why is the signal sent.
|
||||
|
||||
-- Register a new notification object.
|
||||
local function register(notification, args)
|
||||
assert(not notification._private.registered)
|
||||
|
||||
-- Add the some more properties
|
||||
rawset(notification, "get_suspended", get_suspended)
|
||||
|
||||
--TODO v5 uncouple the notifications and the screen
|
||||
local s = get_screen(args.screen
|
||||
or (notification.preset and notification.preset.screen)
|
||||
or screen.focused())
|
||||
local s = get_screen(notification.screen or args.screen
|
||||
or (notification.preset and notification.preset.screen))
|
||||
|
||||
if not s then
|
||||
naughty.emit_signal("request::screen", notification, "new", {})
|
||||
s = notification.screen
|
||||
end
|
||||
|
||||
assert(s)
|
||||
|
||||
-- insert the notification to the table
|
||||
table.insert(naughty._active, notification)
|
||||
|
@ -562,6 +618,8 @@ local function register(notification, args)
|
|||
notification.idx = #naughty.notifications[s][notification.position]
|
||||
notification.screen = s
|
||||
|
||||
notification._private.registered = true
|
||||
|
||||
if properties.suspended and not args.ignore_suspend then
|
||||
notification._private.args = args
|
||||
table.insert(naughty.notifications.suspended, notification)
|
||||
|
@ -599,7 +657,7 @@ local function set_index_miss(_, key, value)
|
|||
resume()
|
||||
end
|
||||
|
||||
naughty.emit_signal("property::"..key)
|
||||
naughty.emit_signal("property::"..key, value)
|
||||
else
|
||||
rawset(naughty, key, value)
|
||||
end
|
||||
|
|
|
@ -10,13 +10,16 @@
|
|||
-- @popupmod naughty.layout.box
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
local capi = {screen=screen}
|
||||
local beautiful = require("beautiful")
|
||||
local gtimer = require("gears.timer")
|
||||
local gtable = require("gears.table")
|
||||
local wibox = require("wibox")
|
||||
local popup = require("awful.popup")
|
||||
local awcommon = require("awful.widget.common")
|
||||
local placement = require("awful.placement")
|
||||
local abutton = require("awful.button")
|
||||
local ascreen = require("awful.screen")
|
||||
local gpcall = require("gears.protected_call")
|
||||
local dpi = require("beautiful").xresources.apply_dpi
|
||||
|
||||
|
@ -26,11 +29,33 @@ local box, by_position = {}, {}
|
|||
|
||||
-- Init the weak tables for each positions. It is done ahead of time rather
|
||||
-- than when notifications are added to simplify the code.
|
||||
for _, pos in ipairs { "top_left" , "top_middle" , "top_right",
|
||||
|
||||
local function init_screen(s)
|
||||
if not s.valid then return end
|
||||
|
||||
if by_position[s] then return by_position[s] end
|
||||
|
||||
by_position[s] = setmetatable({},{__mode = "k"})
|
||||
|
||||
for _, pos in ipairs { "top_left" , "top_middle" , "top_right",
|
||||
"bottom_left", "bottom_middle", "bottom_right" } do
|
||||
by_position[pos] = setmetatable({},{__mode = "v"})
|
||||
by_position[s][pos] = setmetatable({},{__mode = "v"})
|
||||
end
|
||||
|
||||
return by_position[s]
|
||||
end
|
||||
|
||||
ascreen.connect_for_each_screen(init_screen)
|
||||
|
||||
-- Manually cleanup to help the GC.
|
||||
capi.screen.connect_signal("removed", function(scr)
|
||||
-- By that time, all direct events should have been handled. Cleanup the
|
||||
-- leftover. Being a weak table doesn't help Lua 5.1.
|
||||
gtimer.delayed_call(function()
|
||||
by_position[scr] = nil
|
||||
end)
|
||||
end)
|
||||
|
||||
local function get_spacing()
|
||||
local margin = beautiful.notification_spacing or 2
|
||||
return {top = margin, bottom = margin}
|
||||
|
@ -42,9 +67,10 @@ local function update_position(position)
|
|||
local align = position:match("_(.*)")
|
||||
:gsub("left", "front"):gsub("right", "back")
|
||||
|
||||
for k, wdg in ipairs(by_position[position]) do
|
||||
for _, pos in pairs(by_position) do
|
||||
for k, wdg in ipairs(pos[position]) do
|
||||
local args = {
|
||||
geometry = by_position[position][k-1],
|
||||
geometry = pos[position][k-1],
|
||||
preferred_positions = {pref },
|
||||
preferred_anchors = {align},
|
||||
margins = get_spacing(),
|
||||
|
@ -57,15 +83,16 @@ local function update_position(position)
|
|||
|
||||
wdg.visible = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function finish(self)
|
||||
self.visible = false
|
||||
assert(by_position[self.position])
|
||||
assert(init_screen(self.screen)[self.position])
|
||||
|
||||
for k, v in ipairs(by_position[self.position]) do
|
||||
for k, v in ipairs(init_screen(self.screen)[self.position]) do
|
||||
if v == self then
|
||||
table.remove(by_position[self.position], k)
|
||||
table.remove(init_screen(self.screen)[self.position], k)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
@ -73,6 +100,17 @@ local function finish(self)
|
|||
update_position(self.position)
|
||||
end
|
||||
|
||||
-- It isn't a good idea to use the `attach` `awful.placement` property. If the
|
||||
-- screen is resized or the notification is moved, it causes side effects.
|
||||
-- Better listen to geometry changes and reflow.
|
||||
capi.screen.connect_signal("property::geometry", function(s)
|
||||
for pos, notifs in pairs(by_position[s]) do
|
||||
if #notifs > 0 then
|
||||
update_position(pos)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- The maximum notification width.
|
||||
-- @beautiful beautiful.notification_max_width
|
||||
-- @tparam[opt=500] number notification_max_width
|
||||
|
@ -92,8 +130,10 @@ end
|
|||
-- @tparam[opt="top_right"] string notification_position
|
||||
|
||||
--- The widget notification object.
|
||||
--
|
||||
-- @property notification
|
||||
-- @param naughty.notification
|
||||
-- @tparam naughty.notification notification
|
||||
-- @propemits true false
|
||||
|
||||
--- The widget template to construct the box content.
|
||||
--
|
||||
|
@ -135,6 +175,8 @@ end
|
|||
--
|
||||
-- @property widget_template
|
||||
-- @param widget
|
||||
-- @usebeautiful beautiful.notification_max_width The maximum width for the
|
||||
-- resulting widget.
|
||||
|
||||
local function generate_widget(args, n)
|
||||
local w = gpcall(wibox.widget.base.make_widget_from_value,
|
||||
|
@ -192,12 +234,15 @@ local function init(self, notification)
|
|||
end
|
||||
end
|
||||
|
||||
local s = notification.screen
|
||||
assert(s)
|
||||
|
||||
-- Add the notification to the active list
|
||||
assert(by_position[position])
|
||||
assert(init_screen(s)[position], "Invalid position "..position)
|
||||
|
||||
self:_apply_size_now()
|
||||
|
||||
table.insert(by_position[position], self)
|
||||
table.insert(init_screen(s)[position], self)
|
||||
|
||||
local function update() update_position(position) end
|
||||
|
||||
|
@ -220,6 +265,8 @@ function box:set_notification(notif)
|
|||
init(self, notif)
|
||||
|
||||
self._private.notification = notif
|
||||
|
||||
self:emit_signal("property::notification", notif)
|
||||
end
|
||||
|
||||
function box:get_position()
|
||||
|
@ -230,19 +277,41 @@ function box:get_position()
|
|||
return "top_right"
|
||||
end
|
||||
|
||||
--- Create a notification popup box.
|
||||
--
|
||||
-- @constructorfct naughty.layout.box
|
||||
-- @tparam[opt=nil] table args
|
||||
-- @tparam table args.widget_template A widget definition template which will
|
||||
-- be instantiated for each box.
|
||||
-- @tparam naughty.notification args.notification The notification object.
|
||||
-- @tparam string args.position The position. See `naughty.notification.position`.
|
||||
--@DOC_wibox_constructor_COMMON@
|
||||
-- @usebeautiful beautiful.notification_position If `position` is not defined
|
||||
-- in the notification object (or in this constructor).
|
||||
|
||||
local function new(args)
|
||||
args = args or {}
|
||||
|
||||
-- Set the default wibox values
|
||||
local new_args = {
|
||||
ontop = true,
|
||||
visible = false,
|
||||
bg = args and args.bg or beautiful.notification_bg,
|
||||
fg = args and args.fg or beautiful.notification_fg,
|
||||
shape = args and args.shape or beautiful.notification_shape,
|
||||
border_width = args and args.border_width or beautiful.notification_border_width or 1,
|
||||
border_color = args and args.border_color or beautiful.notification_border_color,
|
||||
bg = args.bg or beautiful.notification_bg,
|
||||
fg = args.fg or beautiful.notification_fg,
|
||||
shape = args.shape or beautiful.notification_shape,
|
||||
border_width = args.border_width or beautiful.notification_border_width or 1,
|
||||
border_color = args.border_color or beautiful.notification_border_color,
|
||||
}
|
||||
|
||||
new_args = args and setmetatable(new_args, {__index = args}) or new_args
|
||||
-- The C code needs `pairs` to work, so a full copy is required.
|
||||
gtable.crush(new_args, args, true)
|
||||
|
||||
-- Add a weak-table layer for the screen.
|
||||
local weak_args = setmetatable({
|
||||
screen = args.notification and args.notification.screen or nil
|
||||
}, {__mode="v"})
|
||||
|
||||
setmetatable(new_args, {__index = weak_args})
|
||||
|
||||
-- Generate the box before the popup is created to avoid the size changing
|
||||
new_args.widget = generate_widget(new_args, new_args.notification)
|
||||
|
@ -276,6 +345,8 @@ local function new(args)
|
|||
abutton({ }, 3, hide)
|
||||
))
|
||||
|
||||
gtable.crush(ret, box, false)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
|
|
@ -186,23 +186,47 @@ local actionlist = {}
|
|||
|
||||
--- The actionlist parent notification.
|
||||
-- @property notification
|
||||
-- @param notification
|
||||
-- @tparam naughty.notification notification
|
||||
-- @propemits true false
|
||||
-- @see naughty.notification
|
||||
|
||||
--- The actionlist layout.
|
||||
-- If no layout is specified, a `wibox.layout.fixed.horizontal` will be created
|
||||
-- automatically.
|
||||
-- @property layout
|
||||
-- @param widget
|
||||
-- @property base_layout
|
||||
-- @tparam widget base_layout
|
||||
-- @propemits true false
|
||||
-- @see wibox.layout.fixed.horizontal
|
||||
|
||||
--- The actionlist parent notification.
|
||||
-- @property widget_template
|
||||
-- @param table
|
||||
-- @tparam table widget_template
|
||||
-- @propemits true false
|
||||
|
||||
--- A table with values to override each `beautiful.notification_action` values.
|
||||
-- @property style
|
||||
-- @param table
|
||||
-- @tparam table style
|
||||
-- @propemits true false
|
||||
-- @usebeautiful beautiful.font Fallback when the `font` property isn't set.
|
||||
-- @usebeautiful beautiful.notification_action_underline_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_underline_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_icon_only Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_label_only Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_shape_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_shape_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_shape_border_color_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_shape_border_color_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_shape_border_width_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_shape_border_width_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_icon_size_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_icon_size_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_bg_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_bg_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_fg_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_fg_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_bgimage_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_action_bgimage_selected Fallback.
|
||||
|
||||
|
||||
function actionlist:set_notification(notif)
|
||||
self._private.notification = notif
|
||||
|
@ -215,6 +239,7 @@ function actionlist:set_notification(notif)
|
|||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::notification", notif)
|
||||
end
|
||||
|
||||
function actionlist:set_base_layout(layout)
|
||||
|
@ -224,6 +249,7 @@ function actionlist:set_base_layout(layout)
|
|||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::base_layout", layout)
|
||||
end
|
||||
|
||||
function actionlist:set_widget_template(widget_template)
|
||||
|
@ -236,6 +262,7 @@ function actionlist:set_widget_template(widget_template)
|
|||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::widget_template", widget_template)
|
||||
end
|
||||
|
||||
function actionlist:set_style(style)
|
||||
|
@ -246,6 +273,7 @@ function actionlist:set_style(style)
|
|||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::style", style)
|
||||
end
|
||||
|
||||
function actionlist:get_notification()
|
||||
|
|
|
@ -159,23 +159,48 @@ local notificationlist = {}
|
|||
|
||||
--- The notificationlist parent notification.
|
||||
-- @property notification
|
||||
-- @param notification
|
||||
-- @tparam naughty.notification notification
|
||||
-- @propemits true false
|
||||
-- @see naughty.notification
|
||||
|
||||
--- The notificationlist layout.
|
||||
--- A `wibox.layout` to be used to place the entries.
|
||||
--
|
||||
-- If no layout is specified, a `wibox.layout.fixed.vertical` will be created
|
||||
-- automatically.
|
||||
-- @property layout
|
||||
-- @param widget
|
||||
--
|
||||
-- @property base_layout
|
||||
-- @tparam widget base_layout
|
||||
-- @propemits true false
|
||||
-- @usebeautiful beautiful.notification_spacing
|
||||
-- @see wibox.layout.fixed.horizontal
|
||||
-- @see wibox.layout.fixed.vertical
|
||||
-- @see wibox.layout.flex.horizontal
|
||||
-- @see wibox.layout.flex.vertical
|
||||
-- @see wibox.layout.grid
|
||||
|
||||
--- The notificationlist parent notification.
|
||||
-- @property widget_template
|
||||
-- @param table
|
||||
-- @tparam table widget_template
|
||||
-- @propemits true false
|
||||
|
||||
--- A table with values to override each `beautiful.notification_action` values.
|
||||
-- @property style
|
||||
-- @param table
|
||||
-- @tparam table style
|
||||
-- @propemits true false
|
||||
-- @usebeautiful beautiful.notification_shape_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_shape_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_shape_border_color_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_shape_border_color_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_shape_border_width_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_shape_border_width_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_icon_size_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_icon_size_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_bg_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_bg_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_fg_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_fg_selected Fallback.
|
||||
-- @usebeautiful beautiful.notification_bgimage_normal Fallback.
|
||||
-- @usebeautiful beautiful.notification_bgimage_selected Fallback.
|
||||
|
||||
function notificationlist:set_widget_template(widget_template)
|
||||
self._private.widget_template = widget_template
|
||||
|
@ -187,6 +212,7 @@ function notificationlist:set_widget_template(widget_template)
|
|||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::widget_template", widget_template)
|
||||
end
|
||||
|
||||
function notificationlist:set_style(style)
|
||||
|
@ -197,6 +223,7 @@ function notificationlist:set_style(style)
|
|||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::style", style)
|
||||
end
|
||||
|
||||
function notificationlist:layout(_, width, height)
|
||||
|
@ -213,20 +240,12 @@ function notificationlist:fit(context, width, height)
|
|||
return wibox.widget.base.fit_widget(self, context, self._private.base_layout, width, height)
|
||||
end
|
||||
|
||||
--- A `wibox.layout` to be used to place the entries.
|
||||
-- @property base_layout
|
||||
-- @param widget
|
||||
-- @see wibox.layout.fixed.horizontal
|
||||
-- @see wibox.layout.fixed.vertical
|
||||
-- @see wibox.layout.flex.horizontal
|
||||
-- @see wibox.layout.flex.vertical
|
||||
-- @see wibox.layout.grid
|
||||
|
||||
--- A function to prevent some notifications from being added to the list.
|
||||
-- @property filter
|
||||
-- @param function
|
||||
-- @tparam function filter
|
||||
-- @propemits true false
|
||||
|
||||
for _, prop in ipairs { "filter", "client", "clients", "tag", "tags", "screen", "base_layout" } do
|
||||
for _, prop in ipairs { "filter", "base_layout" } do
|
||||
notificationlist["set_"..prop] = function(self, value)
|
||||
self._private[prop] = value
|
||||
|
||||
|
@ -234,6 +253,7 @@ for _, prop in ipairs { "filter", "client", "clients", "tag", "tags", "screen",
|
|||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::"..prop, value)
|
||||
end
|
||||
|
||||
notificationlist["get_"..prop] = function(self)
|
||||
|
@ -319,9 +339,9 @@ end
|
|||
|
||||
module.filter = {}
|
||||
|
||||
---
|
||||
-- @param n The notification.
|
||||
-- @return Always returns true because it doesn't filter anything at all.
|
||||
--- All notifications.
|
||||
-- @tparam naughty.notification n The notification.
|
||||
-- @treturn boolean Always returns true because it doesn't filter anything at all.
|
||||
-- @filterfunction naughty.list.notifications.filter.all
|
||||
function module.filter.all(n) -- luacheck: no unused args
|
||||
return true
|
||||
|
@ -333,9 +353,9 @@ end
|
|||
--
|
||||
-- filter = function(n) return naughty.list.notifications.filter.most_recent(n, 3) end
|
||||
--
|
||||
-- @param n The notification.
|
||||
-- @tparam naughty.notification n The notification.
|
||||
-- @tparam[opt=1] number count The number of recent notifications to allow.
|
||||
-- @return Always returns true because it doesn't filter anything at all.
|
||||
-- @treturn boolean Always returns true because it doesn't filter anything at all.
|
||||
-- @filterfunction naughty.list.notifications.filter.most_recent
|
||||
function module.filter.most_recent(n, count)
|
||||
for i=1, count or 1 do
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
-- @copyright 2017 Emmanuel Lepage Vallee
|
||||
-- @coreclassmod naughty.notification
|
||||
---------------------------------------------------------------------------
|
||||
local capi = { screen = screen }
|
||||
local gobject = require("gears.object")
|
||||
local gtable = require("gears.table")
|
||||
local gsurface = require("gears.surface")
|
||||
|
@ -75,7 +76,8 @@ local notification = {}
|
|||
-- This is the equivalent to a PID as allows external applications to select
|
||||
-- notifications.
|
||||
-- @property id
|
||||
-- @param number
|
||||
-- @tparam number id
|
||||
-- @propemits true false
|
||||
|
||||
--- Text of the notification.
|
||||
--
|
||||
|
@ -89,12 +91,14 @@ local notification = {}
|
|||
--- Title of the notification.
|
||||
--@DOC_naughty_helloworld_EXAMPLE@
|
||||
-- @property title
|
||||
-- @param string
|
||||
-- @tparam string title
|
||||
-- @propemits true false
|
||||
|
||||
--- Time in seconds after which popup expires.
|
||||
-- Set 0 for no timeout.
|
||||
-- @property timeout
|
||||
-- @param number
|
||||
-- @tparam number timeout
|
||||
-- @propemits true false
|
||||
|
||||
--- The notification urgency level.
|
||||
--
|
||||
|
@ -106,6 +110,7 @@ local notification = {}
|
|||
--
|
||||
-- @property urgency
|
||||
-- @param string
|
||||
-- @propemits true false
|
||||
|
||||
--- The notification category.
|
||||
--
|
||||
|
@ -152,6 +157,7 @@ local notification = {}
|
|||
--
|
||||
-- @property category
|
||||
-- @tparam string|nil category
|
||||
-- @propemits true false
|
||||
|
||||
--- True if the notification should be kept when an action is pressed.
|
||||
--
|
||||
|
@ -161,14 +167,17 @@ local notification = {}
|
|||
--
|
||||
-- @property resident
|
||||
-- @param[opt=false] boolean
|
||||
-- @propemits true false
|
||||
|
||||
--- Delay in seconds after which hovered popup disappears.
|
||||
-- @property hover_timeout
|
||||
-- @param number
|
||||
-- @propemits true false
|
||||
|
||||
--- Target screen for the notification.
|
||||
-- @property screen
|
||||
-- @param screen
|
||||
-- @propemits true false
|
||||
|
||||
--- Corner of the workarea displaying the popups.
|
||||
--
|
||||
|
@ -186,6 +195,7 @@ local notification = {}
|
|||
--
|
||||
-- @property position
|
||||
-- @param string
|
||||
-- @propemits true false
|
||||
-- @see awful.placement.next_to
|
||||
|
||||
--- Boolean forcing popups to display on top.
|
||||
|
@ -198,17 +208,20 @@ local notification = {}
|
|||
--
|
||||
-- @property height
|
||||
-- @param number
|
||||
-- @propemits true false
|
||||
-- @see width
|
||||
|
||||
--- Popup width.
|
||||
-- @property width
|
||||
-- @param number
|
||||
-- @propemits true false
|
||||
-- @see height
|
||||
|
||||
--- Notification font.
|
||||
--@DOC_naughty_colors_EXAMPLE@
|
||||
-- @property font
|
||||
-- @param string
|
||||
-- @propemits true false
|
||||
|
||||
--- "All in one" way to access the default image or icon.
|
||||
--
|
||||
|
@ -228,12 +241,14 @@ local notification = {}
|
|||
--
|
||||
-- @property icon
|
||||
-- @tparam string|surface icon
|
||||
-- @propemits true false
|
||||
-- @see app_icon
|
||||
-- @see image
|
||||
|
||||
--- Desired icon size in px.
|
||||
-- @property icon_size
|
||||
-- @param number
|
||||
-- @propemits true false
|
||||
|
||||
--- The icon provided in the `app_icon` field of the DBus notification.
|
||||
--
|
||||
|
@ -242,6 +257,7 @@ local notification = {}
|
|||
--
|
||||
-- @property app_icon
|
||||
-- @param string
|
||||
-- @propemits true false
|
||||
|
||||
--- The notification image.
|
||||
--
|
||||
|
@ -251,6 +267,7 @@ local notification = {}
|
|||
--
|
||||
-- @property image
|
||||
-- @tparam string|surface image
|
||||
-- @propemits true false
|
||||
|
||||
--- The notification (animated) images.
|
||||
--
|
||||
|
@ -262,6 +279,7 @@ local notification = {}
|
|||
--
|
||||
-- @property images
|
||||
-- @tparam nil|table images
|
||||
-- @propemits true false
|
||||
|
||||
--- Foreground color.
|
||||
--
|
||||
|
@ -269,6 +287,7 @@ local notification = {}
|
|||
--
|
||||
-- @property fg
|
||||
-- @tparam string|color|pattern fg
|
||||
-- @propemits true false
|
||||
-- @see title
|
||||
-- @see gears.color
|
||||
|
||||
|
@ -278,13 +297,14 @@ local notification = {}
|
|||
--
|
||||
-- @property bg
|
||||
-- @tparam string|color|pattern bg
|
||||
-- @propemits true false
|
||||
-- @see title
|
||||
-- @see gears.color
|
||||
|
||||
--- Border width.
|
||||
-- @property border_width
|
||||
-- @param number
|
||||
-- @see title
|
||||
-- @propemits true false
|
||||
|
||||
--- Border color.
|
||||
--
|
||||
|
@ -292,7 +312,7 @@ local notification = {}
|
|||
--
|
||||
-- @property border_color
|
||||
-- @param string
|
||||
-- @see title
|
||||
-- @propemits true false
|
||||
-- @see gears.color
|
||||
|
||||
--- Widget shape.
|
||||
|
@ -311,10 +331,12 @@ local notification = {}
|
|||
--
|
||||
-- @property shape
|
||||
-- @tparam gears.shape shape
|
||||
-- @propemits true false
|
||||
|
||||
--- Widget opacity.
|
||||
-- @property opacity
|
||||
-- @tparam number opacity Between 0 to 1.
|
||||
-- @propemits true false
|
||||
|
||||
--- Widget margin.
|
||||
--
|
||||
|
@ -322,6 +344,7 @@ local notification = {}
|
|||
--
|
||||
-- @property margin
|
||||
-- @tparam number|table margin
|
||||
-- @propemits true false
|
||||
-- @see shape
|
||||
|
||||
--- Function to run on left click.
|
||||
|
@ -345,12 +368,14 @@ local notification = {}
|
|||
-- in the preset.
|
||||
-- @property preset
|
||||
-- @param table
|
||||
-- @propemits true false
|
||||
|
||||
--- Function that will be called with all arguments.
|
||||
-- The notification will only be displayed if the function returns true.
|
||||
-- Note: this function is only relevant to notifications sent via dbus.
|
||||
-- @property callback
|
||||
-- @param function
|
||||
-- @propemits true false
|
||||
|
||||
--- A table containing strings that represents actions to buttons.
|
||||
--
|
||||
|
@ -358,6 +383,7 @@ local notification = {}
|
|||
--
|
||||
-- @property actions
|
||||
-- @param table
|
||||
-- @propemits true false
|
||||
|
||||
--- Ignore this notification, do not display.
|
||||
--
|
||||
|
@ -366,16 +392,19 @@ local notification = {}
|
|||
--
|
||||
-- @property ignore
|
||||
-- @param boolean
|
||||
-- @propemits true false
|
||||
|
||||
--- Tell if the notification is currently suspended (read only).
|
||||
--
|
||||
-- This is always equal to `naughty.suspended`
|
||||
--@property suspended
|
||||
--@param boolean
|
||||
-- @propemits true false
|
||||
|
||||
--- If the notification is expired.
|
||||
-- @property is_expired
|
||||
-- @param boolean
|
||||
-- @propemits true false
|
||||
-- @see naughty.expiration_paused
|
||||
|
||||
--- If the timeout needs to be reset when a property changes.
|
||||
|
@ -385,6 +414,7 @@ local notification = {}
|
|||
--
|
||||
-- @property auto_reset_timeout
|
||||
-- @tparam[opt=true] boolean auto_reset_timeout
|
||||
-- @propemits true false
|
||||
|
||||
--- Emitted when the notification is destroyed.
|
||||
-- @signal destroyed
|
||||
|
@ -415,6 +445,7 @@ local notification = {}
|
|||
--
|
||||
-- @property[opt=500] max_width
|
||||
-- @param number
|
||||
-- @propemits true false
|
||||
|
||||
--- The application name specified by the notification.
|
||||
--
|
||||
|
@ -423,6 +454,7 @@ local notification = {}
|
|||
-- In these case, it helps to triage and detect the notification from the rules.
|
||||
-- @property app_name
|
||||
-- @param string
|
||||
-- @propemits true false
|
||||
|
||||
--- The widget template used to represent the notification.
|
||||
--
|
||||
|
@ -431,16 +463,18 @@ local notification = {}
|
|||
--
|
||||
-- @property widget_template
|
||||
-- @param table
|
||||
|
||||
--FIXME remove the screen attribute, let the handlers decide
|
||||
-- document all handler extra properties
|
||||
-- @propemits true false
|
||||
|
||||
--- Destroy notification by notification object.
|
||||
--
|
||||
-- @method destroy
|
||||
-- @tparam string reason One of the reasons from `notification_closed_reason`
|
||||
-- @tparam[opt=false] boolean keep_visible If true, keep the notification visible
|
||||
-- @return True if the popup was successfully destroyed, false otherwise
|
||||
-- @treturn boolean True if the popup was successfully destroyed, false otherwise.
|
||||
-- @emits destroyed
|
||||
-- @emitstparam destroyed integer reason The reason.
|
||||
-- @emitstparam destroyed boolean keep_visible If the notification should be kept.
|
||||
-- @see naughty.notification_closed_reason
|
||||
function notification:destroy(reason, keep_visible)
|
||||
if self._private.is_destroyed then
|
||||
gdebug.print_warning("Trying to destroy the same notification twice. It"..
|
||||
|
@ -525,6 +559,7 @@ function notification:set_timeout(timeout)
|
|||
end
|
||||
self.die = die
|
||||
self._private.timeout = timeout
|
||||
self:emit_signal("property::timeout", timeout)
|
||||
end
|
||||
|
||||
function notification:set_text(txt)
|
||||
|
@ -545,14 +580,14 @@ end
|
|||
|
||||
local properties = {
|
||||
"message" , "title" , "timeout" , "hover_timeout" ,
|
||||
"screen" , "position", "ontop" , "border_width" ,
|
||||
"app_name", "position", "ontop" , "border_width" ,
|
||||
"width" , "font" , "icon" , "icon_size" ,
|
||||
"fg" , "bg" , "height" , "border_color" ,
|
||||
"shape" , "opacity" , "margin" , "ignore_suspend",
|
||||
"destroy" , "preset" , "callback", "actions" ,
|
||||
"run" , "id" , "ignore" , "auto_reset_timeout",
|
||||
"urgency" , "image" , "images" , "widget_template",
|
||||
"max_width", "app_name",
|
||||
"max_width",
|
||||
}
|
||||
|
||||
for _, prop in ipairs(properties) do
|
||||
|
@ -684,6 +719,23 @@ function notification:append_actions(new_actions)
|
|||
|
||||
end
|
||||
|
||||
function notification:set_screen(s)
|
||||
assert(not self._private.screen)
|
||||
|
||||
s = s and capi.screen[s] or nil
|
||||
|
||||
-- Avoid an infinite loop in the management code.
|
||||
if s == self._private.weak_screen[1] then return end
|
||||
|
||||
self._private.weak_screen = setmetatable({s}, {__mode="v"})
|
||||
|
||||
self:emit_signal("property::screen", s)
|
||||
end
|
||||
|
||||
function notification:get_screen()
|
||||
return self._private.weak_screen[1]
|
||||
end
|
||||
|
||||
--TODO v6: remove this
|
||||
local function convert_actions(actions)
|
||||
gdebug.deprecate(
|
||||
|
@ -835,7 +887,7 @@ local function create(args)
|
|||
n:_connect_everything(naughty.emit_signal)
|
||||
|
||||
-- Avoid modifying the original table
|
||||
local private = {}
|
||||
local private = {weak_screen = setmetatable({}, {__mode="v"})}
|
||||
rawset(n, "_private", private)
|
||||
|
||||
-- Allow extensions to create override the preset with custom data
|
||||
|
@ -848,8 +900,12 @@ local function create(args)
|
|||
end
|
||||
|
||||
for k, v in pairs(args) 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
|
||||
private[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
-- It's an automatic property
|
||||
n.is_expired = false
|
||||
|
|
|
@ -77,6 +77,7 @@ end
|
|||
--- The attached notification.
|
||||
-- @property notification
|
||||
-- @tparam naughty.notification notification
|
||||
-- @propemits true false
|
||||
|
||||
function icon:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
|
@ -95,6 +96,7 @@ function icon:set_notification(notif)
|
|||
self._private.notification = notif
|
||||
|
||||
notif:connect_signal("property::icon", self._private.icon_changed_callback)
|
||||
self:emit_signal("property::notification", notif)
|
||||
end
|
||||
|
||||
local valid_strategies = {
|
||||
|
@ -117,7 +119,11 @@ local valid_strategies = {
|
|||
--@DOC_wibox_nwidget_icon_strategy_EXAMPLE@
|
||||
--
|
||||
-- @property resize_strategy
|
||||
-- @param string
|
||||
-- @tparam string resize_strategy
|
||||
-- @propemits true false
|
||||
-- @usebeautiful beautiful.notification_icon_resize_strategy The fallback when
|
||||
-- there is no specified strategy.
|
||||
-- @usebeautiful beautiful.notification_icon_size The size upper bound.
|
||||
|
||||
function icon:set_resize_strategy(strategy)
|
||||
assert(valid_strategies[strategy], "Invalid strategy")
|
||||
|
@ -125,6 +131,7 @@ function icon:set_resize_strategy(strategy)
|
|||
self._private.resize_strategy = strategy
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::resize_strategy", strategy)
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ end
|
|||
--- The attached notification.
|
||||
-- @property notification
|
||||
-- @tparam naughty.notification notification
|
||||
-- @propemits true false
|
||||
|
||||
function message:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
|
@ -53,12 +54,15 @@ function message:set_notification(notif)
|
|||
|
||||
notif:connect_signal("property::message", self._private.message_changed_callback)
|
||||
notif:connect_signal("property::fg" , self._private.message_changed_callback)
|
||||
self:emit_signal("property::notification", notif)
|
||||
end
|
||||
|
||||
--- Create a new naughty.widget.message.
|
||||
-- @tparam table args
|
||||
-- @tparam naughty.notification args.notification The notification.
|
||||
-- @constructorfct naughty.widget.message
|
||||
-- @usebeautiful beautiful.notification_fg
|
||||
-- @usebeautiful beautiful.notification_font
|
||||
|
||||
local function new(args)
|
||||
args = args or {}
|
||||
|
|
|
@ -36,6 +36,7 @@ end
|
|||
--- The attached notification.
|
||||
-- @property notification
|
||||
-- @tparam naughty.notification notification
|
||||
-- @propemits true false
|
||||
|
||||
function title:set_notification(notif)
|
||||
if self._private.notification == notif then return end
|
||||
|
@ -54,12 +55,15 @@ function title:set_notification(notif)
|
|||
|
||||
notif:connect_signal("property::title", self._private.title_changed_callback)
|
||||
notif:connect_signal("property::fg" , self._private.title_changed_callback)
|
||||
self:emit_signal("property::notification", notif)
|
||||
end
|
||||
|
||||
--- Create a new naughty.widget.title.
|
||||
-- @tparam table args
|
||||
-- @tparam naughty.notification args.notification The notification.
|
||||
-- @constructorfct naughty.widget.title
|
||||
-- @usebeautiful beautiful.notification_fg
|
||||
-- @usebeautiful beautiful.notification_font
|
||||
|
||||
local function new(args)
|
||||
args = args or {}
|
||||
|
|
|
@ -145,6 +145,79 @@ describe("gears.geometry", function()
|
|||
end)
|
||||
end)
|
||||
|
||||
describe("rectangle.is_inside", function()
|
||||
|
||||
it("equality1", function()
|
||||
assert.is_true(geo.rectangle.is_inside(
|
||||
{x=0, y=0, width=10, height=10},
|
||||
{x=0, y=0, width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("equality2", function()
|
||||
assert.is_true(geo.rectangle.is_inside(
|
||||
{x=10, y=10, width=10, height=10},
|
||||
{x=10, y=10, width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("top left edge", function()
|
||||
assert.is_true(geo.rectangle.is_inside(
|
||||
{x=0, y=0, width=5 , height=5 },
|
||||
{x=0, y=0, width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("bottom right edge", function()
|
||||
assert.is_true(geo.rectangle.is_inside(
|
||||
{x=5, y=5, width=5 , height=5 },
|
||||
{x=0, y=0, width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("middle", function()
|
||||
assert.is_true(geo.rectangle.is_inside(
|
||||
{x=2.5, y=2.5, width=5 , height=5 },
|
||||
{x=0 , y=0 , width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("edge overflow", function()
|
||||
assert.is_false(geo.rectangle.is_inside(
|
||||
{x=0, y=0, width=11, height=11},
|
||||
{x=0, y=0, width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("middle overflow", function()
|
||||
assert.is_false(geo.rectangle.is_inside(
|
||||
{x=2.5, y=2.5, width=11, height=11},
|
||||
{x=0 , y=0 , width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("top left outside", function()
|
||||
assert.is_false(geo.rectangle.is_inside(
|
||||
{x=-10, y=-10, width=11, height=11},
|
||||
{x=0 , y=0 , width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("no intersect top left", function()
|
||||
assert.is_false(geo.rectangle.is_inside(
|
||||
{x=-10, y=-10, width=5 , height=5 },
|
||||
{x=0 , y=0 , width=10, height=10}
|
||||
))
|
||||
end)
|
||||
|
||||
it("no intersect bottom right", function()
|
||||
assert.is_false(geo.rectangle.is_inside(
|
||||
{x=11, y=11, width=5 , height=5 },
|
||||
{x=0 , y=0 , width=10, height=10}
|
||||
))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("rectangle.area_remove", function()
|
||||
-- TODO perhaps it would be better to compare against a cairo.region
|
||||
-- than to have this overly specific tests?
|
||||
|
|
|
@ -11,6 +11,9 @@ local GLib = require("lgi" ).GLib
|
|||
local gpcall = require("gears.protected_call")
|
||||
local dwidget = require("naughty.widget._default")
|
||||
|
||||
-- Bypass the new rc.lua and force the legacy mode again.
|
||||
naughty._reset_display_handlers()
|
||||
|
||||
-- This module test deprecated APIs
|
||||
require("gears.debug").deprecate = function() end
|
||||
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
--- This test suite focuses on the AwesomeWM v4.4+ notification API and
|
||||
-- specifically how the `naughty.layout.box` popup widgets handle multi-screen
|
||||
-- scenario.
|
||||
local steps = {}
|
||||
|
||||
local naughty = require("naughty")
|
||||
local grect = require("gears.geometry").rectangle
|
||||
|
||||
-- Do not use whatever `rc.lua` has. This avoids having to update the test
|
||||
-- every time.
|
||||
|
||||
naughty._reset_display_handlers()
|
||||
|
||||
local called = 0
|
||||
|
||||
naughty.connect_signal("request::display", function(n)
|
||||
called = called + 1
|
||||
n._private._box_wibox = naughty.layout.box { notification = n }
|
||||
end)
|
||||
|
||||
local positions = {
|
||||
"top_left" , "top_middle" , "top_right" ,
|
||||
"bottom_left" , "bottom_middle" , "bottom_right" ,
|
||||
}
|
||||
|
||||
local objs = {}
|
||||
|
||||
local s1, s2 = mouse.screen, nil
|
||||
|
||||
for _, p in ipairs(positions) do
|
||||
objs[p] = setmetatable({},{
|
||||
__index=function(t,k) t[k]={};return t[k] end,
|
||||
__mode = "k"
|
||||
})
|
||||
end
|
||||
|
||||
local function add_many(s)
|
||||
for _, pos in ipairs(positions) do
|
||||
for i=1, 5 do
|
||||
table.insert(objs[pos][s], naughty.notification {
|
||||
message = pos..i,
|
||||
position = pos,
|
||||
screen = s,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_at(s, idx)
|
||||
-- This will be validated with many asserts in the code.
|
||||
for _, pos in ipairs(positions) do
|
||||
local n = table.remove(objs[pos][s], idx)
|
||||
assert(n)
|
||||
|
||||
n:destroy()
|
||||
assert(n._private.is_destroyed)
|
||||
end
|
||||
end
|
||||
|
||||
local function check_screen(s)
|
||||
for _, pos in ipairs(positions) do
|
||||
for _, n in pairs(objs[pos][s]) do
|
||||
assert(n.screen == s)
|
||||
assert(n._private._box_wibox)
|
||||
assert(grect.is_inside(
|
||||
n._private._box_wibox:geometry(),
|
||||
s.geometry
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Create notifications in each position.
|
||||
table.insert(steps, function()
|
||||
add_many(s1)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Make sure removing notification works.
|
||||
table.insert(steps, function()
|
||||
|
||||
remove_at(s1, 2)
|
||||
|
||||
-- Split the screen
|
||||
s1:split()
|
||||
|
||||
s2 = screen[2]
|
||||
assert(s1 ~= s2)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Make sure the notification moved as the screen shrunk.
|
||||
table.insert(steps, function()
|
||||
check_screen(s1)
|
||||
|
||||
-- Make sure we can still remove them without errors.
|
||||
remove_at(s1, 2)
|
||||
|
||||
-- Add more!
|
||||
add_many(s2)
|
||||
|
||||
-- Make sure none got moved to the wrong position due to a fallback code
|
||||
-- path triggered by accident. The first few iteration were prone to this.
|
||||
check_screen(s1)
|
||||
check_screen(s2)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Remove everything and see what happens.
|
||||
table.insert(steps, function()
|
||||
|
||||
for _=1, 3 do
|
||||
for _, s in ipairs {s1,s2} do
|
||||
remove_at(s, 1)
|
||||
end
|
||||
end
|
||||
|
||||
for _=1, 2 do
|
||||
remove_at(s2, 1)
|
||||
end
|
||||
|
||||
-- And add them again.
|
||||
add_many(s1)
|
||||
add_many(s2)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
--local weak = nil --FIXME
|
||||
|
||||
-- Delete a screen and make sure it gets GCed.
|
||||
table.insert(steps, function()
|
||||
s2:fake_remove()
|
||||
|
||||
-- Help the weak tables a little.
|
||||
for _, pos in ipairs(positions) do
|
||||
objs[pos][s1] = nil
|
||||
end
|
||||
|
||||
-- Drop our string reference to s2.
|
||||
--weak, s2 = setmetatable({s2}, {__mode="v"}), nil --FIXME
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
--FIXME
|
||||
--table.insert(steps, function()
|
||||
-- if weak[1] == nil then return true end
|
||||
--
|
||||
-- for _=1, 10 do
|
||||
-- collectgarbage("collect")
|
||||
-- end
|
||||
--end)
|
||||
|
||||
require("_runner").run_steps(steps)
|
Loading…
Reference in New Issue