From 9cf717b994abbb7bae96b5e1c26621d9cd295be6 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sat, 14 Mar 2020 20:21:35 -0400 Subject: [PATCH 01/10] naughty: Replace request::icon by request::action_icon. It wasn't a good idea to use ::icon because sometime the notification themselves needs to request assistance for their icons. --- lib/naughty/core.lua | 13 +++++++++++-- lib/naughty/dbus.lua | 2 +- tests/test-naughty-legacy.lua | 7 +++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/naughty/core.lua b/lib/naughty/core.lua index 7a03d630..6f0db7ff 100644 --- a/lib/naughty/core.lua +++ b/lib/naughty/core.lua @@ -561,9 +561,18 @@ naughty.connect_signal("request::screen", naughty.default_screen_handler) -- If an icon is found, the handler must set the `icon` property on the `action` -- object to a path or a `gears.surface`. -- --- @signal request::icon +-- There is no implementation by default. To use the XDG-icon, the common +-- implementation will be: +-- +-- naughty.connect_signal("request::action_icon", function(a, context, hints) +-- a.icon = menubar.utils.lookup_icon(hints.id) +-- end) +-- +-- @signal request::action_icon -- @tparam naughty.action action The action. --- @tparam string icon_name The icon name. +-- @tparam string context The context. +-- @tparam table hints +-- @tparam string args.id The action id. This will often by the (XDG) icon name. --- Emitted when the screen is not defined or being removed. -- @signal request::screen diff --git a/lib/naughty/dbus.lua b/lib/naughty/dbus.lua index ce7faea2..aa4e8b27 100644 --- a/lib/naughty/dbus.lua +++ b/lib/naughty/dbus.lua @@ -173,7 +173,7 @@ function notif_methods.Notify(sender, object_path, interface, method, parameters -- and `naughty` doesn't depend on `menubar`, so delegate the -- icon "somewhere" using a request. if hints["action-icons"] and action_id ~= "" then - naughty.emit_signal("request::icon", a, action_id) + naughty.emit_signal("request::action_icon", a, "dbus", {id = action_id}) end a:connect_signal("invoked", function() diff --git a/tests/test-naughty-legacy.lua b/tests/test-naughty-legacy.lua index 945ca779..7fc043a9 100644 --- a/tests/test-naughty-legacy.lua +++ b/tests/test-naughty-legacy.lua @@ -892,10 +892,9 @@ local icon_requests = {} table.insert(steps, function() assert(#active == 0) - naughty.connect_signal("request::icon", function(a, icon_name) - icon_requests[icon_name] = a - - a.icon = icon_name == "list-add" and small_icon or big_icon + naughty.connect_signal("request::action_icon", function(a, context, hints) + icon_requests[hints.id] = a + a.icon = hints.id == "list-add" and small_icon or big_icon end) local hints = { From a3c37382be09392e3418f25c7516c9344b71dda1 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 15 Mar 2020 03:35:40 -0400 Subject: [PATCH 02/10] naughty: Add a new request::icon for the main icon. My initial implementation was overly optimistic. It turns out there is no end in sight to "correctly" support icons. Apps randomly use XDG name, paths and URLs. Rather than baloon the size of the implementation, this commit moves toward to request:: pattern found in other APIs. This will allow people who wish to "fix" specific icons to do so in a way that scales. The next 2 commits will move the current implementation to request handlers. --- lib/naughty/core.lua | 37 +++++++++++++++++++++++++ lib/naughty/notification.lua | 51 +++++++++++++++++++++++++---------- tests/test-naughty-legacy.lua | 14 +++++++--- 3 files changed, 85 insertions(+), 17 deletions(-) diff --git a/lib/naughty/core.lua b/lib/naughty/core.lua index 6f0db7ff..9c24c034 100644 --- a/lib/naughty/core.lua +++ b/lib/naughty/core.lua @@ -574,6 +574,43 @@ naughty.connect_signal("request::screen", naughty.default_screen_handler) -- @tparam table hints -- @tparam string args.id The action id. This will often by the (XDG) icon name. +--- Emitted when a notification icon could not be loaded. +-- +-- When an icon is passed in some "encoded" formats, such as XDG icon names or +-- network URLs, AwesomeWM will not attempt to load it. If you wish to see the +-- icon displayed, you must provide an handler. It is highly recommended for +-- handler to only set `n.icon` when they *found* the icon. That way multiple +-- handlers can be attached for multiple protocols. +-- +-- The `context` argument is the origin of the icon to decode. If an handler +-- only supports one if them, it should check the `context` and return if it +-- doesn't handle it. The currently valid contexts are: +-- +-- * app_icon +-- * clients +-- * image +-- * images +-- +-- For example, an implementation which uses the `app_icon` to perform an XDG +-- icon lookup will look like: +-- +-- naughty.connect_signal("request::icon", function(n, context, hints) +-- if context ~= "app_icon" then return end +-- +-- local path = menubar.utils.lookup_icon(hints.app_icon) or +-- menubar.utils.lookup_icon(hints.app_icon:lower()) +-- +-- if path then +-- n.icon = path +-- end +-- end) +-- +-- @signal request::icon +-- @tparam notification n The notification. +-- @tparam string context The source of the icon to look for. +-- @tparam table hints The hints. +-- @tparam string hints.app_icon The name of the icon to look for. + --- Emitted when the screen is not defined or being removed. -- @signal request::screen -- @tparam table notification The `naughty.notification` object. This is diff --git a/lib/naughty/notification.lua b/lib/naughty/notification.lua index f7d1f7b0..5243553b 100644 --- a/lib/naughty/notification.lua +++ b/lib/naughty/notification.lua @@ -648,31 +648,54 @@ for _, prop in ipairs { "category", "resident" } do end function notification.get_icon(self) + -- Honor all overrides. if self._private.icon then return self._private.icon == "" and nil or self._private.icon - elseif self.image and self.image ~= "" then - return self.image - elseif self._private.app_icon and self._private.app_icon ~= "" then - return self._private.app_icon end + local ret = nil + + -- First, check if the image is passed as a surface or a path. + if self.image and self.image ~= "" then + ret = self.image + elseif self._private.app_icon and self._private.app_icon ~= "" then + ret = self._private.app_icon + end + + local s, err = nil, nil + + -- See if this is a valid path. + if ret and ret ~= "" then + s, err = gsurface.load_silently(ret) + end + + if s and not err then + return s + end + + -- The second fallback are the client(s) icon(s). local clients = notification.get_clients(self) - for _, c in ipairs(clients) do - if c.type == "normal" then - self._private.icon = gsurface(c.icon) - return self._private.icon + for _, t in ipairs { "normal", "dialog" } do + for _, c in ipairs(clients) do + if c.type == t then + self._private.icon = gsurface(c.icon) --TODO support other size + return self._private.icon + end end end - for _, c in ipairs(clients) do - if c.type == "dialog" then - self._private.icon = gsurface(c.icon) - return self._private.icon - end + -- Now, it might be an XDG icon name or something a request handler can + -- understand. + if err then + local ctx = self._private.app_icon and "app_icon" or "image" + naughty.emit_signal("request::icon", self, ctx, { + app_icon = self._private.app_icon, + image = self.image + }) end - return nil + return self._private.icon == "" and nil or self._private.icon end function notification.get_clients(self) diff --git a/tests/test-naughty-legacy.lua b/tests/test-naughty-legacy.lua index 7fc043a9..70cef991 100644 --- a/tests/test-naughty-legacy.lua +++ b/tests/test-naughty-legacy.lua @@ -897,6 +897,10 @@ table.insert(steps, function() a.icon = hints.id == "list-add" and small_icon or big_icon end) + naughty.connect_signal("request::icon", function(n, context, hints) + icon_requests[n] = true + end) + local hints = { ["action-icons"] = GLib.Variant("b", true), } @@ -912,6 +916,8 @@ table.insert(steps, function() local n = active[1] + assert(not icon_requests[n]) + assert(n._private.freedesktop_hints) assert(n._private.freedesktop_hints["action-icons"] == true) @@ -952,9 +958,10 @@ table.insert(steps, function() gdebug.deprecate = function() end local n = naughty.notification { - title = "foo", - message = "bar", - timeout = 25000, + title = "foo", + message = "bar", + timeout = 25000, + app_icon = "baz" } -- Make sure the suspension don't cause errors @@ -980,6 +987,7 @@ table.insert(steps, function() assert(not naughty.suspended) -- Replace the text + assert(icon_requests[n]) assert(n.title == "foo") assert(n.message == "bar") assert(n.text == "bar") From 625b9c8901001014e0001dea3b94872693039868 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 15 Mar 2020 04:02:31 -0400 Subject: [PATCH 03/10] object: Add a private API to optimize chain of responsibilities. Currently, emit_signal always call all connected function. However, it is very wasteful for some I/O intensive operations like icon lookup. This commit adds a trick (private API) to stop once a condition is met. It will also in the future be used for the permission system, but this is not yet implementd. --- lib/gears/object.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/gears/object.lua b/lib/gears/object.lua index b8b5d645..8b2411f7 100644 --- a/lib/gears/object.lua +++ b/lib/gears/object.lua @@ -134,7 +134,8 @@ function object:emit_signal(name, ...) end end -function object._setup_class_signals(t) +function object._setup_class_signals(t, args) + args = args or {} local conns = {} function t.connect_signal(name, func) @@ -143,6 +144,18 @@ function object._setup_class_signals(t) table.insert(conns[name], func) end + -- A variant of emit_signal which stops once a condition is met. + if args.allow_chain_of_responsibility then + function t._emit_signal_if(name, condition, ...) + assert(name) + for _, func in pairs(conns[name] or {}) do + if condition(...) then return end + func(...) + end + end + end + + --- Emit a notification signal. -- @tparam string name The signal name. -- @param ... The signal callback arguments From c3cdac368de787866d2ca1ec856a102014e2b4de Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 15 Mar 2020 04:10:08 -0400 Subject: [PATCH 04/10] naughty: Stop request::icon as soon as there is an icon. --- lib/naughty/core.lua | 4 +++- lib/naughty/notification.lua | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/naughty/core.lua b/lib/naughty/core.lua index 9c24c034..4a4bab7a 100644 --- a/lib/naughty/core.lua +++ b/lib/naughty/core.lua @@ -274,7 +274,9 @@ function naughty.suspend() properties.suspended = true end -local conns = gobject._setup_class_signals(naughty) +local conns = gobject._setup_class_signals( + naughty, {allow_chain_of_responsibility=true} +) local function resume() properties.suspended = false diff --git a/lib/naughty/notification.lua b/lib/naughty/notification.lua index 5243553b..49fa26ed 100644 --- a/lib/naughty/notification.lua +++ b/lib/naughty/notification.lua @@ -647,6 +647,11 @@ for _, prop in ipairs { "category", "resident" } do end end +-- Stop the request::icon when one is found. +local function request_filter(self, _, _) + if self._private.icon then return true end +end + function notification.get_icon(self) -- Honor all overrides. if self._private.icon then @@ -689,7 +694,7 @@ function notification.get_icon(self) -- understand. if err then local ctx = self._private.app_icon and "app_icon" or "image" - naughty.emit_signal("request::icon", self, ctx, { + naughty._emit_signal_if("request::icon", request_filter, self, ctx, { app_icon = self._private.app_icon, image = self.image }) From 9e19e7a18cf69205eb11b74e1f9fe5494a531e37 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 15 Mar 2020 04:10:36 -0400 Subject: [PATCH 05/10] tests: Test naughty request::icon. --- tests/test-naughty-legacy.lua | 56 +++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/tests/test-naughty-legacy.lua b/tests/test-naughty-legacy.lua index 70cef991..72c892d7 100644 --- a/tests/test-naughty-legacy.lua +++ b/tests/test-naughty-legacy.lua @@ -886,18 +886,70 @@ table.insert(steps, function() return true end) +-- Check that request::icon stops when an icon is found. +table.insert(steps, function() + + local called = 0 + + local function set_icon1() + called = called + 1 + end + + local function set_icon2(n) + called = called + 1 + n.icon = big_icon + end + + local function set_icon3() + called = called + 1 + end + + naughty.connect_signal("request::icon", set_icon1) + naughty.connect_signal("request::icon", set_icon2) + naughty.connect_signal("request::icon", set_icon3) + + assert(called == 0) + + local n1 = naughty.notification { + title = "foo", + message = "bar", + app_icon = "baz" + } + + assert(called == 2) + + n1:destroy() + + naughty.disconnect_signal("request::icon", set_icon1) + naughty.disconnect_signal("request::icon", set_icon2) + naughty.disconnect_signal("request::icon", set_icon3) + + -- Check if `disconnect_signal` works. + n1 = naughty.notification { + title = "foo", + message = "bar", + app_icon = "baz" + } + + assert(called == 2) + + n1:destroy() + + return true +end) + local icon_requests = {} -- Check if the action icon support is detected. table.insert(steps, function() assert(#active == 0) - naughty.connect_signal("request::action_icon", function(a, context, hints) + naughty.connect_signal("request::action_icon", function(a, _, hints) icon_requests[hints.id] = a a.icon = hints.id == "list-add" and small_icon or big_icon end) - naughty.connect_signal("request::icon", function(n, context, hints) + naughty.connect_signal("request::icon", function(n, _) icon_requests[n] = true end) From 32fd11a2208715b8a88e2950bd9392556f111fd4 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 15 Mar 2020 06:04:42 -0400 Subject: [PATCH 06/10] naughty: Move the get_icon implementation to 2 request handlers. They can now be disconnected or extended. --- lib/naughty/core.lua | 39 +++++++++++++++++++ lib/naughty/notification.lua | 70 ++++++++++++++++------------------- tests/test-naughty-legacy.lua | 2 +- 3 files changed, 72 insertions(+), 39 deletions(-) diff --git a/lib/naughty/core.lua b/lib/naughty/core.lua index 4a4bab7a..faf832a9 100644 --- a/lib/naughty/core.lua +++ b/lib/naughty/core.lua @@ -18,6 +18,7 @@ local gdebug = require("gears.debug") local screen = require("awful.screen") local gtable = require("gears.table") local gobject = require("gears.object") +local gsurface = require("gears.surface") local naughty = {} @@ -590,6 +591,7 @@ naughty.connect_signal("request::screen", naughty.default_screen_handler) -- -- * app_icon -- * clients +-- * path -- * image -- * images -- @@ -607,11 +609,18 @@ naughty.connect_signal("request::screen", naughty.default_screen_handler) -- end -- end) -- +-- The `images` context has no handler. It is part of the specification to +-- handle animations. This is not supported by default. +-- -- @signal request::icon -- @tparam notification n The notification. -- @tparam string context The source of the icon to look for. -- @tparam table hints The hints. -- @tparam string hints.app_icon The name of the icon to look for. +-- @tparam string hints.path The path of the icon. +-- @tparam string hints.image The path or pixmap of the icon. +-- @see naughty.icon_path_handler +-- @see naughty.client_icon_handler --- Emitted when the screen is not defined or being removed. -- @signal request::screen @@ -762,9 +771,39 @@ function naughty.notify(args) return nnotif(args) end +--- Request handler to get the icon using the clients icons. +-- @signalhandler naughty.client_icon_handler +function naughty.client_icon_handler(self, context) + if context ~= "clients" then return end + + local clients = self:get_clients() + + for _, t in ipairs { "normal", "dialog" } do + for _, c in ipairs(clients) do + if c.type == t then + self._private.icon = gsurface(c.icon) --TODO support other size + return + end + end + end +end + +--- Request handler to get the icon using the image or path. +-- @signalhandler naughty.icon_path_handler +function naughty.icon_path_handler(self, context, hints) + if context ~= "image" and context ~= "path" then return end + + self._private.icon = gsurface.load_uncached_silently( + hints.path or hints.image + ) +end + naughty.connect_signal("property::screen" , update_index) naughty.connect_signal("property::position", update_index) +naughty.connect_signal("request::icon", naughty.client_icon_handler) +naughty.connect_signal("request::icon", naughty.icon_path_handler ) + --@DOC_signals_COMMON@ return setmetatable(naughty, {__index = index_miss, __newindex = set_index_miss}) diff --git a/lib/naughty/notification.lua b/lib/naughty/notification.lua index 49fa26ed..fe6f2a1c 100644 --- a/lib/naughty/notification.lua +++ b/lib/naughty/notification.lua @@ -18,8 +18,8 @@ local capi = { screen = screen } local gobject = require("gears.object") local gtable = require("gears.table") -local gsurface = require("gears.surface") local timer = require("gears.timer") +local gfs = require("gears.filesystem") local cst = require("naughty.constants") local naughty = require("naughty.core") local gdebug = require("gears.debug") @@ -658,48 +658,42 @@ function notification.get_icon(self) return self._private.icon == "" and nil or self._private.icon end - local ret = nil - -- First, check if the image is passed as a surface or a path. if self.image and self.image ~= "" then - ret = self.image - elseif self._private.app_icon and self._private.app_icon ~= "" then - ret = self._private.app_icon - end - - local s, err = nil, nil - - -- See if this is a valid path. - if ret and ret ~= "" then - s, err = gsurface.load_silently(ret) - end - - if s and not err then - return s - end - - -- The second fallback are the client(s) icon(s). - local clients = notification.get_clients(self) - - for _, t in ipairs { "normal", "dialog" } do - for _, c in ipairs(clients) do - if c.type == t then - self._private.icon = gsurface(c.icon) --TODO support other size - return self._private.icon - end - end - end - - -- Now, it might be an XDG icon name or something a request handler can - -- understand. - if err then - local ctx = self._private.app_icon and "app_icon" or "image" - naughty._emit_signal_if("request::icon", request_filter, self, ctx, { - app_icon = self._private.app_icon, - image = self.image + naughty._emit_signal_if("request::icon", request_filter, self, "image", { + image = self.image + }) + elseif self.images then + naughty._emit_signal_if("request::icon", request_filter, self, "images", { + images = self.images }) end + if self._private.icon then + return self._private.icon == "" and nil or self._private.icon + end + + -- Second level of fallback, icon paths. + if self._private.app_icon and gfs.file_readable(self._private.app_icon) then + naughty._emit_signal_if("request::icon", request_filter, self, "path", { + path = self._private.app_icon + }) + end + + if self._private.icon then + return self._private.icon == "" and nil or self._private.icon + end + + -- Third level fallback is `app_icon`. + if self._private.app_icon then + naughty._emit_signal_if("request::icon", request_filter, self, "app_icon", { + app_icon = self._private.app_icon + }) + end + + -- Finally, the clients. + naughty._emit_signal_if("request::icon", request_filter, self, "clients", {}) + return self._private.icon == "" and nil or self._private.icon end diff --git a/tests/test-naughty-legacy.lua b/tests/test-naughty-legacy.lua index 72c892d7..1a28cf1a 100644 --- a/tests/test-naughty-legacy.lua +++ b/tests/test-naughty-legacy.lua @@ -968,7 +968,7 @@ table.insert(steps, function() local n = active[1] - assert(not icon_requests[n]) + assert(icon_requests[n]) assert(n._private.freedesktop_hints) assert(n._private.freedesktop_hints["action-icons"] == true) From c75203ac03ff8711ecddf679bd00973baa114998 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 15 Mar 2020 06:10:32 -0400 Subject: [PATCH 07/10] naughty: Handle icon paths with file:// in them. --- lib/naughty/notification.lua | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/naughty/notification.lua b/lib/naughty/notification.lua index fe6f2a1c..4f5acccc 100644 --- a/lib/naughty/notification.lua +++ b/lib/naughty/notification.lua @@ -652,6 +652,20 @@ local function request_filter(self, _, _) if self._private.icon then return true end end +-- Convert encoded local URI to Unix paths. +local function check_path(input) + if type(input) ~= "string" then return nil end + + if input:sub(1,7) == "file://" then + input = input:sub(8) + end + + -- urldecode + input = input:gsub("%%(%x%x)", function(x) return string.char(tonumber(x, 16)) end ) + + return gfs.file_readable(input) and input or nil +end + function notification.get_icon(self) -- Honor all overrides. if self._private.icon then @@ -674,9 +688,11 @@ function notification.get_icon(self) end -- Second level of fallback, icon paths. - if self._private.app_icon and gfs.file_readable(self._private.app_icon) then + local path = check_path(self._private.app_icon) + + if path then naughty._emit_signal_if("request::icon", request_filter, self, "path", { - path = self._private.app_icon + path = path }) end From 64fb4984227b4c1b6baca6da00c39beed5e1a4a9 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 16 Mar 2020 02:46:39 -0400 Subject: [PATCH 08/10] tests: Test the newly added notification icon request handlers. --- tests/test-naughty-legacy.lua | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/test-naughty-legacy.lua b/tests/test-naughty-legacy.lua index 1a28cf1a..86c992ee 100644 --- a/tests/test-naughty-legacy.lua +++ b/tests/test-naughty-legacy.lua @@ -4,6 +4,7 @@ local spawn = require("awful.spawn") local naughty = require("naughty" ) local gdebug = require("gears.debug") local gtable = require("gears.table") +local gfs = require("gears.filesystem") local cairo = require("lgi" ).cairo local beautiful = require("beautiful") local Gio = require("lgi" ).Gio @@ -1135,6 +1136,57 @@ table.insert(steps, function() return true end) +-- Check that the various request::icon work. +table.insert(steps, function() + local gsurface = require("gears.surface") + + local ls = gsurface.load_uncached_silently + + function gsurface.load_uncached_silently(input) + return { + input = input, + get_height = function() return 1 end, + get_width = function() return 1 end, + } + end + + local fr, gc = gfs.file_readable, naughty.notification.get_clients + + local mocked_client = { + type = "normal", + icon = "42", + } + + function naughty.notification.get_clients() + return {mocked_client} + end + + function gfs.file_readable() return true end + + local n = naughty.notification { + app_icon = "file:///one%20two" + } + + assert(type(n.icon) == "table" and n.icon.input == "/one two") + + n:destroy() + + local n2 = naughty.notification { + title = "foo" + } + + assert(type(n2.icon) == "table" and n2.icon.input == "42") + + n2:destroy() + + -- Restore the real methods. + gsurface.load_uncached_silently = ls + naughty.notification.get_clients = gc + gfs.file_readable = fr + + return true +end) + -- Make sure the legacy popup is used when the new APIs fails. table.insert(steps, function() assert(naughty.has_display_handler == true) From 4492a378855a11b922c82cf50a33e7a0a1a7331c Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 16 Mar 2020 03:15:10 -0400 Subject: [PATCH 09/10] naughty: Use a request handler to clear the notification icon. --- lib/naughty/core.lua | 11 +++++++++++ lib/naughty/dbus.lua | 8 ++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/naughty/core.lua b/lib/naughty/core.lua index faf832a9..da783839 100644 --- a/lib/naughty/core.lua +++ b/lib/naughty/core.lua @@ -594,6 +594,7 @@ naughty.connect_signal("request::screen", naughty.default_screen_handler) -- * path -- * image -- * images +-- * dbus_clear -- -- For example, an implementation which uses the `app_icon` to perform an XDG -- icon lookup will look like: @@ -798,11 +799,21 @@ function naughty.icon_path_handler(self, context, hints) ) end +--- Request handler for clearing the icon when asked by ie, DBus. +-- @signalhandler naughty.icon_clear_handler +function naughty.icon_clear_handler(self, context, hints) --luacheck: no unused args + if context ~= "dbus_clear" then return end + + self._private.icon = nil + self:emit_signal("property::icon") +end + naughty.connect_signal("property::screen" , update_index) naughty.connect_signal("property::position", update_index) naughty.connect_signal("request::icon", naughty.client_icon_handler) naughty.connect_signal("request::icon", naughty.icon_path_handler ) +naughty.connect_signal("request::icon", naughty.icon_clear_handler ) --@DOC_signals_COMMON@ diff --git a/lib/naughty/dbus.lua b/lib/naughty/dbus.lua index aa4e8b27..98b36a7f 100644 --- a/lib/naughty/dbus.lua +++ b/lib/naughty/dbus.lua @@ -326,8 +326,12 @@ function notif_methods.Notify(sender, object_path, interface, method, parameters -- Update the icon if necessary. if app_icon ~= notification._private.app_icon then notification._private.app_icon = app_icon - notification._private.icon = nil - notification:emit_signal("property::icon") + + naughty._emit_signal_if( + "request::icon", function() + if notification._private.icon then return true end + end, notification, "dbus_clear", {} + ) end -- Even if no property changed, restart the timeout. From 9601cf4a89a321c3f80d3decc51a95ac1b7c633a Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 16 Mar 2020 04:35:29 -0400 Subject: [PATCH 10/10] naughty: Plug to the permission system. This allows to control which kind of icon actions can be done on individual notifications. Once the second part of the permission system will be merged, this will mostly be used in `ruled.notification`. --- lib/naughty/notification.lua | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/naughty/notification.lua b/lib/naughty/notification.lua index 4f5acccc..3164b665 100644 --- a/lib/naughty/notification.lua +++ b/lib/naughty/notification.lua @@ -23,6 +23,7 @@ local gfs = require("gears.filesystem") local cst = require("naughty.constants") local naughty = require("naughty.core") local gdebug = require("gears.debug") +local pcommon = require("awful.permissions._common") local notification = {} @@ -648,7 +649,8 @@ for _, prop in ipairs { "category", "resident" } do end -- Stop the request::icon when one is found. -local function request_filter(self, _, _) +local function request_filter(self, context, _) + if not pcommon.check(self, "notification", "icon", context) then return true end if self._private.icon then return true end end @@ -1011,6 +1013,22 @@ local function create(args) return n end +--- Grant a permission for a notification. +-- +-- @method grant +-- @tparam string permission The permission name (just the name, no `request::`). +-- @tparam string context The reason why this permission is requested. +-- @see awful.permissions + +--- Deny a permission for a notification +-- +-- @method deny +-- @tparam string permission The permission name (just the name, no `request::`). +-- @tparam string context The reason why this permission is requested. +-- @see awful.permissions + +pcommon.setup_grant(notification, "notification") + -- This allows notification to be updated later. local counter = 1