Merge pull request #2726 from Elv13/doc_tests_and_notif_p5

notification: Add the view components (not used by default until v4.5)
This commit is contained in:
Emmanuel Lepage Vallée 2019-06-08 20:43:20 -04:00 committed by GitHub
commit 140f11b106
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 2539 additions and 64 deletions

View File

@ -28,6 +28,15 @@ configurable rules.
@DOC_layout_WIDGET_LIST@ @DOC_layout_WIDGET_LIST@
### Other
Notifications also have their own widgets.
<img src="../images/AUTOGEN_wibox_nwidget_default.svg" />
More information about the notification widgets can be found on the
`naughty.notification` documentation page.
### The different type of widget boxes (Wibox) ### The different type of widget boxes (Wibox)
The Awesome API uses the word "wibox" (widget box) to describe an area of the The Awesome API uses the word "wibox" (widget box) to describe an area of the
@ -54,6 +63,9 @@ positioning, relative positioning, and manual positioning.
The `awful.tooltip` is a very simple `wibox` that allows to display text next The `awful.tooltip` is a very simple `wibox` that allows to display text next
to an object such as the mouse. to an object such as the mouse.
The `naughty.layout.box` allows to provide custom widgets to use within the
notifications.
Finally, the `awful.titlebar`, while not technically a real `wibox`, acts Finally, the `awful.titlebar`, while not technically a real `wibox`, acts
exactly the same way and allows to attach widgets on each side of clients. exactly the same way and allows to attach widgets on each side of clients.
@ -424,3 +436,27 @@ Code:
s.mywibox : setup (three_circle) s.mywibox : setup (three_circle)
### Instantiation rules
Whenever it can, Awesome tries to be asynchronous. This can take various form
depending on the situation. For example, the `connect_signal` method allows to
execute code when an event arrives. `awful.screen.connect_for_each_screen` also
allows to instantiate various elements when a new screen is added. In the later
case, it is why some widgets are added as properties to other objects instead of
being global variables like in previous versions of Awesome.
However, there is a case where this isn't enough and another abstract widget has
to be used. This concept is called the `widget_template` and is an optional
property of many widgets such as the `awful.widget.taglist`,
`awful.widget.tasklist` and `naughty.layout.box`. These templates are a
**table** using the exact same syntax as the declarative widgets, but without
the `wibox.widget` prefix in front of the curly braces. These templates
represents future widgets that will be created by their parent widget. This is
necessary for three reasons:
* The widget must create many instances of the template at different points in
time.
* The widget data is only partially available and other fields must be set
at a later time (by the parent widget).
* The code is highly redundant and some of the logic is delegated to the parent
widget to simplify everything.

View File

@ -149,6 +149,10 @@ file = {
-- Ignore some parts of the widget library -- Ignore some parts of the widget library
'../lib/awful/widget/init.lua', '../lib/awful/widget/init.lua',
'../lib/naughty/layout/init.lua', '../lib/naughty/layout/init.lua',
'../lib/naughty/widget/init.lua',
'../lib/naughty/container/init.lua',
'../lib/naughty/list/init.lua',
'../lib/naughty/widget/_default.lua',
-- Deprecated classes for one years or more don't deserve entries -- Deprecated classes for one years or more don't deserve entries
-- in the index -- in the index

View File

@ -6,7 +6,7 @@
-- --
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt; -- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2019 Emmanuel Lepage Vallee -- @copyright 2019 Emmanuel Lepage Vallee
-- @classmod naughty.action -- @coreclassmod naughty.action
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
local gtable = require("gears.table" ) local gtable = require("gears.table" )
local gobject = require("gears.object") local gobject = require("gears.object")
@ -43,6 +43,10 @@ local action = {}
-- @property icon -- @property icon
-- @tparam gears.surface|string icon -- @tparam gears.surface|string icon
--- If the action should hide the label and only display the icon.
-- @property icon_only
-- @param[opt=false] boolean
--- The notification. --- The notification.
-- @property notification -- @property notification
-- @tparam naughty.notification notification -- @tparam naughty.notification notification
@ -80,7 +84,7 @@ function action:set_position(value)
--TODO make sure the position is unique --TODO make sure the position is unique
end end
for _, prop in ipairs { "name", "icon", "notification" } do for _, prop in ipairs { "name", "icon", "notification", "icon_only" } do
action["get_"..prop] = function(self) action["get_"..prop] = function(self)
return self._private[prop] return self._private[prop]
end end
@ -97,6 +101,10 @@ for _, prop in ipairs { "name", "icon", "notification" } do
end end
--- Execute this action. --- Execute this action.
--
-- This only emits the `invoked` signal.
--
-- @method invoke
function action:invoke() function action:invoke()
assert(self._private.notification, assert(self._private.notification,
"Cannot invoke an action without a notification") "Cannot invoke an action without a notification")

View File

@ -0,0 +1,99 @@
----------------------------------------------------------------------------
--- A notification background.
--
-- This widget holds the boilerplate code associated with the notification
-- background. This includes the color and potentially some other styling
-- elements such as the shape and border.
--
-- * Honor the `beautiful` notification variables.
-- * React to the `naughty.notification` changes.
--
--@DOC_wibox_nwidget_background_simple_EXAMPLE@
--
-- Note that this widget is based on the `wibox.container.background`. This is
-- an implementation detail and may change in the future without prior notice.
--
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2019 Emmanuel Lepage Vallee
-- @containermod naughty.widget.background
-- @see wibox.container.background
----------------------------------------------------------------------------
local wbg = require("wibox.container.background")
local gtable = require("gears.table")
local beautiful = require("beautiful")
local gshape = require("gears.shape")
local background = {}
local function update_background(notif, wdg)
local bg = notif.bg or beautiful.notification_bg
local bw = notif.border_width or beautiful.notification_border_width
local bc = notif.border_color or beautiful.notification_border_color
-- Always fallback to the rectangle to make sure the border works
local shape = notif.shape or
beautiful.notification_shape or gshape.rectangle
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)
end
--- The attached notification.
-- @property notification
-- @tparam naughty.notification notification
function background:set_notification(notif)
if self._private.notification == notif then return end
if self._private.notification then
self._private.notification:disconnect_signal("poperty::bg",
self._private.background_changed_callback)
self._private.notification:disconnect_signal("poperty::border_width",
self._private.background_changed_callback)
self._private.notification:disconnect_signal("poperty::border_color",
self._private.background_changed_callback)
self._private.notification:disconnect_signal("poperty::shape",
self._private.background_changed_callback)
end
update_background(notif, self)
self._private.notification = notif
notif:connect_signal("poperty::bg" , self._private.background_changed_callback)
notif:connect_signal("poperty::border_width", self._private.background_changed_callback)
notif:connect_signal("poperty::border_color", self._private.background_changed_callback)
notif:connect_signal("poperty::shape" , self._private.background_changed_callback)
end
--- Create a new naughty.container.background.
-- @tparam table args
-- @tparam naughty.notification args.notification The notification.
-- @constructorfct naughty.container.background
local function new(args)
args = args or {}
local bg = wbg()
bg:set_border_strategy("inner")
gtable.crush(bg, background, true)
function bg._private.background_changed_callback()
update_background(bg._private.notification, bg)
end
if args.notification then
bg:set_notification(args.notification)
end
return bg
end
--@DOC_widget_COMMON@
--@DOC_object_COMMON@
return setmetatable(background, {__call = function(_, ...) return new(...) end})

View File

@ -0,0 +1,9 @@
---------------------------------------------------------------------------
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2019 Emmanuel Lepage Vallee
-- @module naughty.container
---------------------------------------------------------------------------
return {
background = require( "naughty.container.background" );
}

View File

@ -122,6 +122,10 @@ gtable.crush(naughty, require("naughty.constants"))
-- @property active -- @property active
-- @param table -- @param table
--- True when there is a handler connected to `request::display`.
-- @property has_display_handler
-- @param boolean
local properties = { local properties = {
suspended = false, suspended = false,
expiration_paused = false expiration_paused = false
@ -346,6 +350,10 @@ function naughty.get_active()
return naughty._active return naughty._active
end end
function naughty.get_has_display_handler()
return conns["request::display"] and #conns["request::display"] > 0 or false
end
--- Set new notification timeout. --- Set new notification timeout.
-- --
-- This function is deprecated, use `notification:reset_timeout(new_timeout)`. -- This function is deprecated, use `notification:reset_timeout(new_timeout)`.
@ -454,7 +462,7 @@ end
--- Emitted when a notification has to be displayed. --- Emitted when a notification has to be displayed.
-- --
-- To add an handler, use: -- To add a handler, use:
-- --
-- naughty.connect_signal("request::display", function(notification, args) -- naughty.connect_signal("request::display", function(notification, args)
-- -- do something -- -- do something

View File

@ -10,7 +10,11 @@ if dbus then
end end
naughty.action = require("naughty.action") naughty.action = require("naughty.action")
naughty.list = require("naughty.list")
naughty.layout = require("naughty.layout") naughty.layout = require("naughty.layout")
naughty.widget = require("naughty.widget")
naughty.container = require("naughty.container")
naughty.action = require("naughty.action")
naughty.notification = require("naughty.notification") naughty.notification = require("naughty.notification")
return naughty return naughty

261
lib/naughty/layout/box.lua Normal file
View File

@ -0,0 +1,261 @@
----------------------------------------------------------------------------
--- A notification popup widget.
--
-- By default, the box is composed of many other widgets:
--
--@DOC_wibox_nwidget_default_EXAMPLE@
--
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2017 Emmanuel Lepage Vallee
-- @popupmod naughty.layout.box
----------------------------------------------------------------------------
local beautiful = require("beautiful")
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 default_widget = require("naughty.widget._default")
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",
"bottom_left", "bottom_middle", "bottom_right" } do
by_position[pos] = setmetatable({},{__mode = "v"})
end
local function get_spacing()
local margin = beautiful.notification_spacing or 2
return {top = margin, bottom = margin}
end
-- Leverage `awful.placement` to create the stacks.
local function update_position(position)
local pref = position:match("top_") and "bottom" or "top"
local align = position:match("_(.*)")
:gsub("left", "front"):gsub("right", "back")
for k, wdg in ipairs(by_position[position]) do
local args = {
geometry = by_position[position][k-1],
preferred_positions = {pref },
preferred_anchors = {align},
margins = get_spacing(),
honor_workarea = true,
}
-- The first entry is aligned to the workarea, then the following to the
-- previous widget.
placement[k==1 and position:gsub("_middle", "") or "next_to"](wdg, args)
wdg.visible = true
end
end
local function finish(self)
self.visible = false
assert(by_position[self.position])
for k, v in ipairs(by_position[self.position]) do
if v == self then
table.remove(by_position[self.position], k)
break
end
end
update_position(self.position)
end
--- The maximum notification width.
-- @beautiful beautiful.notification_max_width
-- @tparam[opt=500] number notification_max_width
--- The maximum notification position.
--
-- Valid values are:
--
-- * top_left
-- * top_middle
-- * top_right
-- * bottom_left
-- * bottom_middle
-- * bottom_right
--
-- @beautiful beautiful.notification_position
-- @tparam[opt="top_right"] string notification_position
--- The widget notification object.
-- @property notification
-- @param naughty.notification
--- The widget template to construct the box content.
--
--@DOC_wibox_nwidget_default_EXAMPLE@
--
-- The default template is (less or more):
--
-- {
-- {
-- {
-- {
-- {
-- naughty.widget.icon,
-- {
-- naughty.widget.title,
-- naughty.widget.message,
-- spacing = 4,
-- layout = wibox.layout.fixed.vertical,
-- },
-- fill_space = true,
-- spacing = 4,
-- layout = wibox.layout.fixed.horizontal,
-- },
-- naughty.list.actions,
-- spacing = 10,
-- layout = wibox.layout.fixed.vertical,
-- },
-- margins = beautiful.notification_margin,
-- widget = wibox.container.margins,
-- },
-- id = "background_role",
-- widget = naughty.container.background,
-- },
-- strategy = "max",
-- width = width(beautiful.notification_max_width
-- or beautiful.xresources.apply_dpi(500)
-- widget = wibox.container.constraint,
-- }
--
-- @property widget_template
-- @param widget
local function generate_widget(args, n)
local w = wibox.widget.base.make_widget_from_value(
args.widget_template or default_widget
)
-- Call `:set_notification` on all children
awcommon._set_common_property(w, "notification", n or args.notification)
return w
end
local function init(self, notification)
local args = self._private.args
local preset = notification.preset
assert(preset)
local position = args.position or notification.position or
beautiful.notification_position or preset.position or "top_right"
if not self.widget then
self.widget = generate_widget(self._private.args, notification)
end
local bg = self._private.widget:get_children_by_id( "background_role" )[1]
-- Make sure the border isn't set twice, favor the widget one since it is
-- shared by the notification list and the notification box.
if bg then
if bg.set_notification then
bg:set_notification(notification)
self.border_width = 0
else
bg:set_bg(notification.bg)
self.border_width = notification.border_width
end
end
-- Add the notification to the active list
assert(by_position[position])
self:_apply_size_now()
table.insert(by_position[position], self)
local function update() update_position(position) end
self:connect_signal("property::geometry", update)
notification:connect_signal("property::margin", update)
notification:connect_signal("destroyed", self._private.destroy_callback)
update_position(position)
end
function box:set_notification(notif)
if self._private.notification == notif then return end
if self._private.notification then
self._private.notification:disconnect_signal("destroyed",
self._private.destroy_callback)
end
init(self, notif)
self._private.notification = notif
end
function box:get_position()
if self._private.notification then
return self._private.notification:get_position()
end
return "top_right"
end
local function new(args)
-- 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,
}
new_args = args and setmetatable(new_args, {__index = args}) or new_args
-- Generate the box before the popup is created to avoid the size changing
new_args.widget = generate_widget(new_args)
local ret = popup(new_args)
ret._private.args = new_args
gtable.crush(ret, box, true)
function ret._private.destroy_callback()
finish(ret)
end
if new_args.notification then
ret:set_notification(new_args.notification)
end
--TODO remove
local function hide()
if ret._private.notification then
ret._private.notification:destroy()
end
end
--FIXME there's another pull request for this
ret:buttons(gtable.join(
abutton({ }, 1, hide),
abutton({ }, 3, hide)
))
return ret
end
--@DOC_wibox_COMMON@
return setmetatable(box, {__call = function(_, args) return new(args) end})

View File

@ -5,5 +5,6 @@
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
return { return {
legacy = require("naughty.layout.legacy") legacy = require( "naughty.layout.legacy" );
box = require( "naughty.layout.box" );
} }

View File

@ -13,6 +13,11 @@
-- --
--@DOC_naughty_actions_EXAMPLE@ --@DOC_naughty_actions_EXAMPLE@
-- --
-- Use the `naughty.notification.position` property to control where the popup
-- is located.
--
--@DOC_awful_notification_corner_EXAMPLE@
--
-- @author koniu &lt;gkusnierz@gmail.com&gt; -- @author koniu &lt;gkusnierz@gmail.com&gt;
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt; -- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2008 koniu -- @copyright 2008 koniu
@ -279,23 +284,10 @@ end
naughty.connect_signal("destroyed", cleanup) naughty.connect_signal("destroyed", cleanup)
--- The default notification GUI handler.
--
-- To disable this handler, use:
--
-- naughty.disconnect_signal(
-- "request::display", naughty.default_notification_handler
-- )
--
-- It looks like:
--
--@DOC_naughty_actions_EXAMPLE@
--
-- @tparam table notification The `naughty.notification` object.
-- @tparam table args Any arguments passed to the `naughty.notify` function,
-- including, but not limited to all `naughty.notification` properties.
-- @signalhandler naughty.default_notification_handler
function naughty.default_notification_handler(notification, args) function naughty.default_notification_handler(notification, args)
-- This is a fallback for users whose config doesn't have the newer
-- `request::display` section.
if naughty.has_display_handler then return end
-- If request::display is called more than once, simply make sure the wibox -- If request::display is called more than once, simply make sure the wibox
-- is visible. -- is visible.
@ -415,8 +407,14 @@ function naughty.default_notification_handler(notification, args)
local action_width = w + 2 * margin local action_width = w + 2 * margin
actionmarginbox:buttons(gtable.join( actionmarginbox:buttons(gtable.join(
button({ }, 1, function() action:invoke() end), button({ }, 1, function()
button({ }, 3, function() action:invoke() end) action:invoke()
notification:destroy()
end),
button({ }, 3, function()
action:invoke()
notification:destroy()
end)
)) ))
actionslayout:add(actionmarginbox) actionslayout:add(actionmarginbox)
@ -561,4 +559,4 @@ function naughty.default_notification_handler(notification, args)
end end
end end
naughty.connect_signal("request::display", naughty.default_notification_handler) naughty.connect_signal("request::fallback", naughty.default_notification_handler)

View File

@ -0,0 +1,324 @@
----------------------------------------------------------------------------
--- Manage a notification action list.
--
-- A notification action is a "button" that will trigger an action on the sender
-- process. `notify-send` doesn't support actions, but `libnotify` based
-- applications do.
--
--@DOC_wibox_nwidget_actionlist_simple_EXAMPLE@
--
-- This example has a custom vertical widget template:
--
--@DOC_wibox_nwidget_actionlist_fancy_EXAMPLE@
--
-- This example has a horizontal widget template and icons:
--
--@DOC_wibox_nwidget_actionlist_fancy_icons_EXAMPLE@
--
-- This example uses the theme/style variables instead of the template. This is
-- less flexible, but easier to put in the theme file. Note that each style
-- variable has a `beautiful` equivalent.
--
--@DOC_wibox_nwidget_actionlist_style_EXAMPLE@
--
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2017 Emmanuel Lepage Vallee
-- @widgetmod naughty.list.actions
-- @see awful.widget.common
----------------------------------------------------------------------------
local wibox = require("wibox")
local awcommon = require("awful.widget.common")
local abutton = require("awful.button")
local gtable = require("gears.table")
local beautiful= require("beautiful")
local module = {}
--- Whether or not to underline the action name.
-- @beautiful beautiful.notification_action_underline_normal
-- @param[opt=true] boolean
--- Whether or not to underline the selected action name.
-- @beautiful beautiful.notification_action_underline_selected
-- @param[opt=true] boolean
--- Whether or not the action label should be shown.
-- @beautiful beautiful.notification_action_icon_only
-- @param[opt=false] boolean
--- Whether or not the action icon should be shown.
-- @beautiful beautiful.notification_action_label_only
-- @param[opt=false] boolean
--- The shape used for a normal action.
-- @beautiful beautiful.notification_action_shape_normal
-- @tparam[opt=gears.shape.rectangle] gears.shape shape
-- @see gears.shape
--- The shape used for a selected action.
-- @beautiful beautiful.notification_action_shape_selected
-- @tparam[opt=gears.shape.rectangle] gears.shape shape
-- @see gears.shape
--- The shape border color for normal actions.
-- @beautiful beautiful.notification_action_shape_border_color_normal
-- @param color
-- @see gears.color
--- The shape border color for selected actions.
-- @beautiful beautiful.notification_action_shape_border_color_selected
-- @param color
-- @see gears.color
--- The shape border width for normal actions.
-- @beautiful beautiful.notification_action_shape_border_width_normal
-- @param[opt=0] number
--- The shape border width for selected actions.
-- @beautiful beautiful.notification_action_shape_border_width_selected
-- @param[opt=0] number
--- The action icon size.
-- @beautiful beautiful.notification_action_icon_size_normal
-- @param[opt=0] number
--- The selected action icon size.
-- @beautiful beautiful.notification_action_icon_size_selected
-- @param[opt=0] number
--- The background color for normal actions.
-- @beautiful beautiful.notification_action_bg_normal
-- @param color
-- @see gears.color
--- The background color for selected actions.
-- @beautiful beautiful.notification_action_bg_selected
-- @param color
-- @see gears.color
--- The foreground color for normal actions.
-- @beautiful beautiful.notification_action_fg_normal
-- @param color
-- @see gears.color
--- The foreground color for selected actions.
-- @beautiful beautiful.notification_action_fg_selected
-- @param color
-- @see gears.color
--- The background image for normal actions.
-- @beautiful beautiful.notification_action_bgimage_normal
-- @tparam gears.surface|string action_bgimage_normal
-- @see gears.surface
--- The background image for selected actions.
-- @beautiful beautiful.notification_action_bgimage_selected
-- @tparam gears.surface|string action_bgimage_selected
-- @see gears.surface
local default_buttons = gtable.join(
abutton({ }, 1, function(a) a:invoke() end)
)
local props = {"shape_border_color", "bg_image" , "fg",
"shape_border_width", "underline", "bg",
"shape", "icon_size", }
-- Use a cached loop instead of an large function like the taglist and tasklist
local function update_style(self)
self._private.style_cache = self._private.style_cache or {}
for _, state in ipairs {"normal", "selected"} do
local s = {}
for _, prop in ipairs(props) do
if self._private.style[prop.."_"..state] ~= nil then
s[prop] = self._private.style[prop.."_"..state]
else
s[prop] = beautiful["notification_action_"..prop.."_"..state]
end
end
-- Set a fallback for the icon size to prevent them from being gigantic
s.icon_size = s.icon_size
or beautiful.get_font_height(beautiful.font) * 1.5
self._private.style_cache[state] = s
end
end
local function wb_label(action, self)
-- Get the name
local name = action.name
local style = self._private.style_cache[action.selected and "selected" or "normal"]
-- Add the underline
name = style.underline ~= false and
("<u>"..name.."</u>") or name
local icon = beautiful.notification_action_label_only ~= true and action.icon or nil
if style.fg then
name = "<span color='" .. style.fg .. "'>" .. name .. "</span>"
end
if action.icon_only or beautiful.notification_action_icon_only then
name = nil
end
return name, style.bg, style.bg_image, icon, style
end
local function update(self)
if not self._private.layout or not self._private.notification then return end
awcommon.list_update(
self._private.layout,
default_buttons,
function(o) return wb_label(o, self) end,
self._private.data,
self._private.notification.actions,
{
widget_template = self._private.widget_template
}
)
end
local actionlist = {}
--- The actionlist parent notification.
-- @property notification
-- @param notification
-- @see naughty.notification
--- The actionlist layout.
-- If no layout is specified, a `wibox.layout.fixed.horizontal` will be created
-- automatically.
-- @property layout
-- @param widget
-- @see wibox.layout.fixed.horizontal
--- The actionlist parent notification.
-- @property widget_template
-- @param table
--- A table with values to override each `beautiful.notification_action` values.
-- @property style
-- @param table
function actionlist:set_notification(notif)
self._private.notification = notif
if not self._private.layout then
self._private.layout = wibox.layout.fixed.horizontal()
end
update(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::redraw_needed")
end
function actionlist:set_base_layout(layout)
self._private.layout = layout
update(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::redraw_needed")
end
function actionlist:set_widget_template(widget_template)
self._private.widget_template = widget_template
-- Remove the existing instances
self._private.data = {}
update(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::redraw_needed")
end
function actionlist:set_style(style)
self._private.style = style or {}
update_style(self)
update(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::redraw_needed")
end
function actionlist:get_notification()
return self._private.notification
end
function actionlist:layout(_, width, height)
if self._private.layout then
return { wibox.widget.base.place_widget_at(self._private.layout, 0, 0, width, height) }
end
end
function actionlist:fit(context, width, height)
if not self._private.layout then
return 0, 0
end
return wibox.widget.base.fit_widget(self, context, self._private.layout, width, height)
end
--- Create an action list.
--
-- @tparam table args
-- @tparam naughty.notification args.notification The notification/
-- @tparam widget args.base_layout The action layout.
-- @tparam table args.style Override the beautiful values.
-- @tparam boolean args.style.underline_normal
-- @tparam boolean args.style.underline_selected
-- @tparam gears.shape args.style.shape_normal
-- @tparam gears.shape args.style.shape_selected
-- @tparam gears.color|string args.style.shape_border_color_normal
-- @tparam gears.color|string args.style.shape_border_color_selected
-- @tparam number args.style.shape_border_width_normal
-- @tparam number args.style.shape_border_width_selected
-- @tparam number args.style.icon_size
-- @tparam gears.color|string args.style.bg_normal
-- @tparam gears.color|string args.style.bg_selected
-- @tparam gears.color|string args.style.fg_normal
-- @tparam gears.color|string args.style.fg_selected
-- @tparam gears.surface|string args.style.bgimage_normal
-- @tparam gears.surface|string args.style.bgimage_selected
-- @tparam[opt] table widget_template A custom widget to be used for each action.
-- @treturn widget The action widget.
-- @constructorfct naughty.list.actions
local function new(_, args)
args = args or {}
local wdg = wibox.widget.base.make_widget(nil, nil, {
enable_properties = true,
})
gtable.crush(wdg, actionlist, true)
wdg._private.data = {}
gtable.crush(wdg, args)
wdg._private.style = wdg._private.style or {}
update_style(wdg)
return wdg
end
--@DOC_widget_COMMON@
--@DOC_object_COMMON@
return setmetatable(module, {__call = new})
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

10
lib/naughty/list/init.lua Normal file
View File

@ -0,0 +1,10 @@
---------------------------------------------------------------------------
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2017-2019 Emmanuel Lepage Vallee
-- @module naughty.list
---------------------------------------------------------------------------
return {
actions = require( "naughty.list.actions" );
notifications = require( "naughty.list.notifications" );
}

View File

@ -0,0 +1,356 @@
----------------------------------------------------------------------------
--- Get a list of all currently active notifications.
--
-- @DOC_awful_notification_notificationlist_bottombar_EXAMPLE@
--
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2017 Emmanuel Lepage Vallee
-- @widgetmod naughty.list.notifications
-- @see awful.widget.common
----------------------------------------------------------------------------
local wibox = require("wibox")
local awcommon = require("awful.widget.common")
local abutton = require("awful.button")
local gtable = require("gears.table")
local gtimer = require("gears.timer")
local beautiful= require("beautiful")
local naughty = require("naughty.core")
local default_widget = require("naughty.widget._default")
local module = {}
--- The shape used for a normal notification.
-- @beautiful beautiful.notification_shape_normal
-- @tparam[opt=gears.shape.rectangle] gears.shape shape
-- @see gears.shape
--- The shape used for a selected notification.
-- @beautiful beautiful.notification_shape_selected
-- @tparam[opt=gears.shape.rectangle] gears.shape shape
-- @see gears.shape
--- The shape border color for normal notifications.
-- @beautiful beautiful.notification_shape_border_color_normal
-- @param color
-- @see gears.color
--- The shape border color for selected notifications.
-- @beautiful beautiful.notification_shape_border_color_selected
-- @param color
-- @see gears.color
--- The shape border width for normal notifications.
-- @beautiful beautiful.notification_shape_border_width_normal
-- @param[opt=0] number
--- The shape border width for selected notifications.
-- @beautiful beautiful.notification_shape_border_width_selected
-- @param[opt=0] number
--- The notification icon size.
-- @beautiful beautiful.notification_icon_size_normal
-- @param[opt=0] number
--- The selected notification icon size.
-- @beautiful beautiful.notification_icon_size_selected
-- @param[opt=0] number
--- The background color for normal notifications.
-- @beautiful beautiful.notification_bg_normal
-- @param color
-- @see gears.color
--- The background color for selected notifications.
-- @beautiful beautiful.notification_bg_selected
-- @param color
-- @see gears.color
--- The foreground color for normal notifications.
-- @beautiful beautiful.notification_fg_normal
-- @param color
-- @see gears.color
--- The foreground color for selected notifications.
-- @beautiful beautiful.notification_fg_selected
-- @param color
-- @see gears.color
--- The background image for normal notifications.
-- @beautiful beautiful.notification_bgimage_normal
-- @tparam string|gears.surface bgimage_normal
-- @see gears.surface
--- The background image for selected notifications.
-- @beautiful beautiful.notification_bgimage_selected
-- @tparam string|gears.surface bgimage_selected
-- @see gears.surface
local default_buttons = gtable.join(
abutton({ }, 1, function(n) n:destroy() end),
abutton({ }, 3, function(n) n:destroy() end)
)
local props = {"shape_border_color", "bg_image" , "fg",
"shape_border_width", "shape" , "bg",
"icon_size"}
-- Use a cached loop instead of an large function like the taglist and tasklist
local function update_style(self)
self._private.style_cache = self._private.style_cache or {}
for _, state in ipairs {"normal", "selected"} do
local s = {}
for _, prop in ipairs(props) do
if self._private.style[prop.."_"..state] ~= nil then
s[prop] = self._private.style[prop.."_"..state]
else
s[prop] = beautiful["notification_"..prop.."_"..state]
end
end
self._private.style_cache[state] = s
end
end
local function wb_label(notification, self)
-- Get the title
local title = notification.title
local style = self._private.style_cache[notification.selected and "selected" or "normal"]
if notification.fg or style.fg then
title = "<span color='" .. (notification.fg or style.fg) .. "'>" .. title .. "</span>"
end
return title, notification.bg or style.bg, style.bg_image, notification.icon, {
shape = notification.shape or style.shape,
shape_border_width = notification.border_width or style.shape_border_width,
shape_border_color = notification.border_color or style.shape_border_color,
icon_size = style.icon_size,
}
end
-- Remove some callback boilerplate from the user provided templates.
local function create_callback(w, n)
awcommon._set_common_property(w, "notification", n)
end
local function update(self)
-- Checking style_cache helps to avoid useless redraw during initialization
if not self._private.base_layout or not self._private.style_cache then return end
awcommon.list_update(
self._private.base_layout,
default_buttons,
function(o) return wb_label(o, self) end,
self._private.data,
naughty.active,
{
create_callback = create_callback,
widget_template = self._private.widget_template or default_widget
}
)
end
local notificationlist = {}
--- The notificationlist parent notification.
-- @property notification
-- @param notification
-- @see naughty.notification
--- The notificationlist layout.
-- If no layout is specified, a `wibox.layout.fixed.vertical` will be created
-- automatically.
-- @property layout
-- @param widget
-- @see wibox.layout.fixed.vertical
--- The notificationlist parent notification.
-- @property widget_template
-- @param table
--- A table with values to override each `beautiful.notification_action` values.
-- @property style
-- @param table
function notificationlist:set_widget_template(widget_template)
self._private.widget_template = widget_template
-- Remove the existing instances
self._private.data = {}
update(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::redraw_needed")
end
function notificationlist:set_style(style)
self._private.style = style or {}
update_style(self)
update(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::redraw_needed")
end
function notificationlist:layout(_, width, height)
if self._private.base_layout then
return { wibox.widget.base.place_widget_at(self._private.base_layout, 0, 0, width, height) }
end
end
function notificationlist:fit(context, width, height)
if not self._private.base_layout then
return 0, 0
end
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
for _, prop in ipairs { "filter", "client", "clients", "tag", "tags", "screen", "base_layout" } do
notificationlist["set_"..prop] = function(self, value)
self._private[prop] = value
update(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::redraw_needed")
end
notificationlist["get_"..prop] = function(self)
return self._private[prop]
end
end
--- Create an notification list.
--
-- @tparam table args
-- @tparam widget args.base_layout The notification list base_layout.
-- @tparam widget args.filter The list filter.
-- @tparam table args.style Override the beautiful values.
-- @tparam gears.shape args.style.shape_normal
-- @tparam gears.shape args.style.shape_selected
-- @tparam gears.color|string args.style.shape_border_color_normal
-- @tparam gears.color|string args.style.shape_border_color_selected
-- @tparam number args.style.shape_border_width_normal
-- @tparam number args.style.shape_border_width_selected
-- @tparam number args.style.icon_size
-- @tparam gears.color|string args.style.bg_normal
-- @tparam gears.color|string args.style.bg_selected
-- @tparam gears.color|string args.style.fg_normal
-- @tparam gears.color|string args.style.fg_selected
-- @tparam gears.surface|string args.style.bgimage_normal
-- @tparam gears.surface|string args.style.bgimage_selected
-- @tparam[opt] table widget_template A custom widget to be used for each
-- notifications.
-- @treturn widget The notification list widget.
-- @constructorfct naughty.list.notifications
local function new(_, args)
args = args or {}
local wdg = wibox.widget.base.make_widget(nil, nil, {
enable_properties = true,
})
gtable.crush(wdg, notificationlist, true)
wdg._private.data = {}
gtable.crush(wdg, args)
wdg._private.style = wdg._private.style or {}
-- Don't do this right away since the base_layout may not have been set yet.
-- This also avoids `update()` being executed during initialization and
-- causing an output that isn't reproducible.
gtimer.delayed_call(function()
update_style(wdg)
if not wdg._private.base_layout then
wdg._private.base_layout = wibox.layout.flex.horizontal()
wdg._private.base_layout:set_spacing(beautiful.notification_spacing or 0)
wdg:emit_signal("widget::layout_changed")
wdg:emit_signal("widget::redraw_needed")
end
update(wdg)
local is_scheduled = false
-- Prevent multiple updates due to the many signals.
local function f()
if is_scheduled then return end
is_scheduled = true
gtimer.delayed_call(function() update(wdg); is_scheduled = false end)
end
-- Yes, this will cause 2 updates when a new notification arrives, but
-- on the other hand, request::display is required to auto-disable the
-- fallback legacy mode and property::active is needed to remove the
-- destroyed notifications.
naughty.connect_signal("property::active", f)
naughty.connect_signal("request::display", f)
end)
return wdg
end
module.filter = {}
---
-- @param n The notification.
-- @return 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
end
--- Only get the most recent notification(s).
--
-- To set the count, the function needs to be wrapped:
--
-- filter = function(n) return naughty.list.notifications.filter.most_recent(n, 3) end
--
-- @param 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.
-- @filterfunction naughty.list.notifications.filter.most_recent
function module.filter.most_recent(n, count)
for i=1, count or 1 do
if n == naughty.active[i] then
return true
end
end
return false
end
--@DOC_widget_COMMON@
--@DOC_object_COMMON@
return setmetatable(module, {__call = new})
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -53,7 +53,7 @@ local notification = {}
-- @beautiful beautiful.notification_opacity -- @beautiful beautiful.notification_opacity
-- @tparam[opt] int notification_opacity -- @tparam[opt] int notification_opacity
--- Notifications margin. --- The margins inside of the notification widget (or popup).
-- @beautiful beautiful.notification_margin -- @beautiful beautiful.notification_margin
-- @tparam int notification_margin -- @tparam int notification_margin
@ -65,6 +65,11 @@ local notification = {}
-- @beautiful beautiful.notification_height -- @beautiful beautiful.notification_height
-- @tparam int notification_height -- @tparam int notification_height
--- The spacing between the notifications.
-- @beautiful beautiful.notification_spacing
-- @param[opt=2] number
-- @see gears.surface
-- Unique identifier of the notification. -- Unique identifier of the notification.
-- This is the equivalent to a PID as allows external applications to select -- This is the equivalent to a PID as allows external applications to select
-- notifications. -- notifications.
@ -72,8 +77,12 @@ local notification = {}
-- @param string -- @param string
-- @see title -- @see title
-- Text of the notification [[deprecated]] --- Text of the notification.
-- @property text --
-- This exists only for the pre-AwesomeWM v4.4 new notification implementation.
-- Please always use `title`.
--
-- @deprecatedproperty text
-- @param string -- @param string
-- @see title -- @see title
@ -107,22 +116,28 @@ local notification = {}
-- * *bottom_middle* -- * *bottom_middle*
-- * *middle* -- * *middle*
-- --
--@DOC_awful_notification_corner_EXAMPLE@ --@DOC_awful_notification_box_corner_EXAMPLE@
-- --
-- @property position -- @property position
-- @param string -- @param string
-- @see awful.placement.next_to
--- Boolean forcing popups to display on top. --- Boolean forcing popups to display on top.
-- @property ontop -- @property ontop
-- @param boolean -- @param boolean
--- Popup height. --- Popup height.
--
--@DOC_awful_notification_geometry_EXAMPLE@
--
-- @property height -- @property height
-- @param number -- @param number
-- @see width
--- Popup width. --- Popup width.
-- @property width -- @property width
-- @param number -- @param number
-- @see height
--- Notification font. --- Notification font.
--@DOC_naughty_colors_EXAMPLE@ --@DOC_naughty_colors_EXAMPLE@
@ -138,12 +153,18 @@ local notification = {}
-- @param number -- @param number
--- Foreground color. --- Foreground color.
--
--@DOC_awful_notification_fg_EXAMPLE@
--
-- @property fg -- @property fg
-- @tparam string|color|pattern fg -- @tparam string|color|pattern fg
-- @see title -- @see title
-- @see gears.color -- @see gears.color
--- Background color. --- Background color.
--
--@DOC_awful_notification_bg_EXAMPLE@
--
-- @property bg -- @property bg
-- @tparam string|color|pattern bg -- @tparam string|color|pattern bg
-- @see title -- @see title
@ -155,32 +176,58 @@ local notification = {}
-- @see title -- @see title
--- Border color. --- Border color.
--
--@DOC_awful_notification_border_color_EXAMPLE@
--
-- @property border_color -- @property border_color
-- @param string -- @param string
-- @see title -- @see title
-- @see gears.color -- @see gears.color
--- Widget shape. --- Widget shape.
--
-- Note that when using a custom `request::display` handler or `naughty.rules`,
-- choosing between multiple shapes depending on the content can be done using
-- expressions like:
--
-- -- The notification object is called `n`
-- shape = #n.actions > 0 and
-- gears.shape.rounded_rect or gears.shape.rounded_bar,
--
--@DOC_awful_notification_shape_EXAMPLE@
--
--@DOC_naughty_shape_EXAMPLE@ --@DOC_naughty_shape_EXAMPLE@
--
-- @property shape -- @property shape
-- @param gears.shape -- @tparam gears.shape shape
--- Widget opacity. --- Widget opacity.
-- @property opacity -- @property opacity
-- @param number From 0 to 1 -- @tparam number opacity Between 0 to 1.
--- Widget margin. --- Widget margin.
--
--@DOC_awful_notification_margin_EXAMPLE@
--
-- @property margin -- @property margin
-- @tparam number|table margin -- @tparam number|table margin
-- @see shape -- @see shape
--- Function to run on left click. --- Function to run on left click.
-- @property run --
-- Use the signals rather than this.
--
-- @deprecatedproperty run
-- @param function -- @param function
-- @see destroyed
--- Function to run when notification is destroyed. --- Function to run when notification is destroyed.
-- @property destroy --
-- Use the signals rather than this.
--
-- @deprecatedproperty destroy
-- @param function -- @param function
-- @see destroyed
--- Table with any of the above parameters. --- Table with any of the above parameters.
-- args will override ones defined -- args will override ones defined
@ -380,16 +427,18 @@ local function convert_actions(actions)
local naction = require("naughty.action") local naction = require("naughty.action")
local new_actions = {}
-- Does not attempt to handle when there is a mix of strings and objects -- Does not attempt to handle when there is a mix of strings and objects
for idx, name in pairs(actions) do for idx, name in pairs(actions) do
local cb = nil local cb, old_idx = nil, idx
if type(name) == "function" then if type(name) == "function" then
cb = name cb = name
end end
if type(idx) == "string" then if type(idx) == "string" then
name, idx = idx, nil name, idx = idx, #actions+1
end end
local a = naction { local a = naction {
@ -401,9 +450,14 @@ local function convert_actions(actions)
a:connect_signal("invoked", cb) a:connect_signal("invoked", cb)
end end
-- Yes, it modifies `args`, this is legacy code, cloning the args new_actions[old_idx] = a
-- just for this isn't worth it. end
actions[idx] = a
-- Yes, it modifies `args`, this is legacy code, cloning the args
-- just for this isn't worth it.
for old_idx, a in pairs(new_actions) do
actions[a.position] = a
actions[ old_idx ] = nil
end end
end end
@ -497,7 +551,7 @@ local function create(args)
rawget(n, "preset") or {} rawget(n, "preset") or {}
)) ))
if is_old_action then if is_old_action then
convert_actions(args.actions) convert_actions(args.actions)
end end
@ -509,6 +563,16 @@ local function create(args)
private[k] = v private[k] = v
end end
-- notif.actions should not be nil to allow cheching if there is actions
-- using the shorthand `if #notif.actions > 0 then`
private.actions = private.actions or {}
-- Make sure the action are for this notification. Sharing actions with
-- multiple notification is not supported.
for _, a in ipairs(private.actions) do
a.notification = n
end
-- It's an automatic property -- It's an automatic property
n.is_expired = false n.is_expired = false
@ -524,7 +588,8 @@ local function create(args)
-- Let all listeners handle the actual visual aspects -- Let all listeners handle the actual visual aspects
if (not n.ignore) and (not n.preset.ignore) then if (not n.ignore) and (not n.preset.ignore) then
naughty.emit_signal("request::display", n, args) naughty.emit_signal("request::display" , n, args)
naughty.emit_signal("request::fallback", n, args)
end end
-- Because otherwise the setter logic would not be executed -- Because otherwise the setter logic would not be executed

View File

@ -0,0 +1,85 @@
----------------------------------------------------------------------------
--- The default widget template for the notifications.
--
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2019 Emmanuel Lepage Vallee
-- @classmod naughty.widget._default
----------------------------------------------------------------------------
local wibox = require("wibox")
local actionlist = require("naughty.list.actions")
local wtitle = require("naughty.widget.title")
local wmessage = require("naughty.widget.message")
local wicon = require("naughty.widget.icon")
local wbg = require("naughty.container.background")
local beautiful = require("beautiful")
local dpi = require("beautiful").xresources.apply_dpi
-- It is not worth doing a special widget for this.
local function notif_size()
local constraint = wibox.container.constraint()
constraint:set_strategy("max")
constraint:set_width(beautiful.notification_max_width or dpi(500))
rawset(constraint, "set_notification", function(_, notif)
constraint._private.notification = notif
local s = false
if notif.width and notif.width ~= beautiful.notification_max_width then
constraint.width = notif.width
s = true
end
if notif.height then
constraint.height = notif.height
s = true
end
constraint.strategy = s and "exact" or "max"
end)
return constraint
end
-- It is not worth doing a special widget for this either.
local function notif_margins()
local margins = wibox.container.margin()
margins:set_margins(beautiful.notification_margin or 4)
rawset(margins, "set_notification", function(_, notif)
if notif.margin then
margins:set_margins(notif.margin)
end
end)
return margins
end
-- Used as a fallback when no widget_template is provided, emulate the legacy
-- widget.
return {
{
{
{
{
wicon,
{
wtitle,
wmessage,
spacing = 4,
layout = wibox.layout.fixed.vertical,
},
fill_space = true,
spacing = 4,
layout = wibox.layout.fixed.horizontal,
},
actionlist,
spacing = 10,
layout = wibox.layout.fixed.vertical,
},
widget = notif_margins,
},
id = "background_role",
widget = wbg,
},
widget = notif_size,
}

158
lib/naughty/widget/icon.lua Normal file
View File

@ -0,0 +1,158 @@
----------------------------------------------------------------------------
--- A notification square icon.
--
-- This widget is a specialized `wibox.widget.imagebox` with the following extra
-- features:
--
-- * Honor the `beautiful` notification variables.
-- * Restrict the size avoid huge notifications
-- * Provides some strategies to handle small icons
-- * React to the `naughty.notification` object icon changes.
--
--@DOC_wibox_nwidget_icon_simple_EXAMPLE@
--
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2017 Emmanuel Lepage Vallee
-- @widgetmod naughty.widget.icon
-- @see wibox.widget.imagebox
----------------------------------------------------------------------------
local imagebox = require("wibox.widget.imagebox")
local gtable = require("gears.table")
local beautiful = require("beautiful")
local dpi = require("beautiful.xresources").apply_dpi
local icon = {}
-- The default way to resize the icon.
-- @beautiful beautiful.notification_icon_resize_strategy
-- @param number
function icon:fit(_, width, height)
-- Until someone complains, adding a "leave blank space" isn't supported
if not self._private.image then return 0, 0 end
local maximum = math.min(width, height)
local strategy = self._private.resize_strategy or "resize"
local optimal = math.min(beautiful.notification_icon_size or dpi(48), maximum)
local w = self._private.image:get_width()
local h = self._private.image:get_height()
if strategy == "resize" then
return math.min(w, optimal, maximum), math.min(h, optimal, maximum)
else
return optimal, optimal
end
end
function icon:draw(_, cr, width, height)
if not self._private.image then return end
if width == 0 or height == 0 then return end
-- Let's scale the image so that it fits into (width, height)
local strategy = self._private.resize_strategy or "resize"
local w = self._private.image:get_width()
local h = self._private.image:get_height()
local aspect = width / w
local aspect_h = height / h
if aspect > aspect_h then aspect = aspect_h end
if aspect < 1 or (strategy == "scale" and (w < width or h < height)) then
cr:scale(aspect, aspect)
end
local x, y = 0, 0
if (strategy == "center" and aspect > 1) or strategy == "resize" then
x = math.floor((width - w) / 2)
y = math.floor((height - h) / 2)
end
cr:set_source_surface(self._private.image, x, y)
cr:paint()
end
--- The attached notification.
-- @property notification
-- @tparam naughty.notification notification
function icon:set_notification(notif)
if self._private.notification == notif then return end
if self._private.notification then
self._private.notification:disconnect_signal("destroyed",
self._private.icon_changed_callback)
end
self:set_image(notif.icon)
self._private.notification = notif
notif:connect_signal("poperty::icon", self._private.icon_changed_callback)
end
local valid_strategies = {
scale = true,
center = true,
resize = true,
}
--- How small icons are handled.
--
-- Valid values are:
--
-- * **scale**: Scale the icon up to the optimal size.
-- * **center**: Keep the icon size and draw it in the center
-- * **resize**: Change the size of the widget itself (*default*).
--
-- Note that the size upper bound is defined by
-- `beautiful.notification_icon_size`.
--
--@DOC_wibox_nwidget_icon_strategy_EXAMPLE@
--
-- @property resize_strategy
-- @param string
function icon:set_resize_strategy(strategy)
assert(valid_strategies[strategy], "Invalid strategy")
self._private.resize_strategy = strategy
self:emit_signal("widget::redraw_needed")
end
function icon:get_resize_strategy()
return self._private.resize_strategy
or beautiful.notification_icon_resize_strategy
or "resize"
end
--- Create a new naughty.widget.icon.
-- @tparam table args
-- @tparam naughty.notification args.notification The notification.
-- @constructorfct naughty.widget.icon
local function new(args)
args = args or {}
local tb = imagebox()
gtable.crush(tb, icon, true)
function tb._private.icon_changed_callback()
tb:set_image(tb._private.notification.icon)
end
if args.notification then
tb:set_notification(args.notification)
end
return tb
end
--@DOC_widget_COMMON@
--@DOC_object_COMMON@
return setmetatable(icon, {__call = function(_, ...) return new(...) end})

View File

@ -0,0 +1,11 @@
---------------------------------------------------------------------------
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2017 Emmanuel Lepage Vallee
-- @module naughty.widget
---------------------------------------------------------------------------
return {
title = require( "naughty.widget.title" );
icon = require( "naughty.widget.icon" );
message = require( "naughty.widget.message" );
}

View File

@ -0,0 +1,86 @@
----------------------------------------------------------------------------
--- A notification content message.
--
-- This widget is a specialized `wibox.widget.textbox` with the following extra
-- features:
--
-- * Honor the `beautiful` notification variables.
-- * React to the `naughty.notification` object message changes.
--
--@DOC_wibox_nwidget_message_simple_EXAMPLE@
--
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2017 Emmanuel Lepage Vallee
-- @widgetmod naughty.widget.message
-- @see wibox.widget.textbox
----------------------------------------------------------------------------
local textbox = require("wibox.widget.textbox")
local gtable = require("gears.table")
local beautiful = require("beautiful")
local message = {}
local function markup(notif, wdg)
local ret = notif.message or ""
local fg = notif.fg or beautiful.notification_fg
wdg:set_font(notif.font or beautiful.notification_font)
if fg then
ret = "<span color='" .. fg .. "'>" .. ret .. "</span>"
end
return ret
end
--- The attached notification.
-- @property notification
-- @tparam naughty.notification notification
function message:set_notification(notif)
if self._private.notification == notif then return end
if self._private.notification then
self._private.notification:disconnect_signal("poperty::message",
self._private.message_changed_callback)
self._private.notification:disconnect_signal("poperty::fg",
self._private.message_changed_callback)
end
self:set_markup(markup(notif, self))
self._private.notification = notif
notif:connect_signal("poperty::message", self._private.message_changed_callback)
notif:connect_signal("poperty::fg" , self._private.message_changed_callback)
end
--- Create a new naughty.widget.message.
-- @tparam table args
-- @tparam naughty.notification args.notification The notification.
-- @constructorfct naughty.widget.message
local function new(args)
args = args or {}
local tb = textbox()
tb:set_wrap("word")
tb:set_font(beautiful.notification_font)
gtable.crush(tb, message, true)
function tb._private.message_changed_callback()
tb:set_markup(markup(tb._private.notification, tb))
end
if args.notification then
tb:set_notification(args.notification)
end
return tb
end
--@DOC_widget_COMMON@
--@DOC_object_COMMON@
return setmetatable(message, {__call = function(_, ...) return new(...) end})

View File

@ -0,0 +1,87 @@
----------------------------------------------------------------------------
--- A notification title.
--
-- This widget is a specialized `wibox.widget.textbox` with the following extra
-- features:
--
-- * Honor the `beautiful` notification variables.
-- * React to the `naughty.notification` object title changes.
--
--@DOC_wibox_nwidget_title_simple_EXAMPLE@
--
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2017 Emmanuel Lepage Vallee
-- @widgetmod naughty.widget.title
-- @see wibox.widget.textbox
----------------------------------------------------------------------------
local textbox = require("wibox.widget.textbox")
local gtable = require("gears.table")
local beautiful = require("beautiful")
local title = {}
local function markup(notif, wdg)
local ret = "<b>"..(notif.title or "").."</b>"
local fg = notif.fg or beautiful.notification_fg
wdg:set_font(notif.font or beautiful.notification_font)
if fg then
ret = "<span color='" .. fg .. "'>" .. ret .. "</span>"
end
return ret
end
--- The attached notification.
-- @property notification
-- @tparam naughty.notification notification
function title:set_notification(notif)
if self._private.notification == notif then return end
if self._private.notification then
self._private.notification:disconnect_signal("poperty::message",
self._private.title_changed_callback)
self._private.notification:disconnect_signal("poperty::fg",
self._private.title_changed_callback)
end
self:set_markup(markup(notif, self))
self._private.notification = notif
self._private.title_changed_callback()
notif:connect_signal("poperty::title", self._private.title_changed_callback)
notif:connect_signal("poperty::fg" , self._private.title_changed_callback)
end
--- Create a new naughty.widget.title.
-- @tparam table args
-- @tparam naughty.notification args.notification The notification.
-- @constructorfct naughty.widget.title
local function new(args)
args = args or {}
local tb = textbox()
tb:set_wrap("word")
tb:set_font(beautiful.notification_font)
gtable.crush(tb, title, true)
function tb._private.title_changed_callback()
tb:set_markup(markup(tb._private.notification, tb))
end
if args.notification then
tb:set_notification(args.notification)
end
return tb
end
--@DOC_widget_COMMON@
--@DOC_object_COMMON@
return setmetatable(title, {__call = function(_, ...) return new(...) end})

View File

@ -0,0 +1,31 @@
--DOC_GEN_IMAGE --DOC_NO_USAGE
require("_default_look") --DOC_HIDE
local awful = {wibar = require("awful.wibar")} --DOC_HIDE
local naughty = require("naughty") --DOC_HIDE
screen[1]._resize {width = 640, height = 240} --DOC_HIDE
local some_wibar = awful.wibar {position = "bottom", height = 48, visible = true} --DOC_HIDE
--DOC_NEWLINE
-- A notification popup using the default widget_template.
naughty.connect_signal("request::display", function(n)
naughty.layout.box {notification = n}
end)
--DOC_NEWLINE
-- Notifications as widgets for any `wibox`/`awful.wibar`/`awful.popup`
some_wibar.widget = naughty.list.notifications {}
--DOC_NEWLINE
for _, color in ipairs {"#ff0000", "#00ff00", "#0000ff"} do
naughty.notification {
title = "A ".. color .." notification",
bg = color,
}
end
require("gears.timer").run_delayed_calls_now()

View File

@ -0,0 +1,32 @@
--DOC_GEN_IMAGE --DOC_NO_USAGE
require("_default_look") --DOC_HIDE
local awful = {wibar = require("awful.wibar")} --DOC_HIDE
local naughty = require("naughty") --DOC_HIDE
screen[1]._resize {width = 640, height = 240} --DOC_HIDE
local some_wibar = awful.wibar {position = "bottom", height = 48, visible = true} --DOC_HIDE
--DOC_NEWLINE
-- A notification popup using the default widget_template.
naughty.connect_signal("request::display", function(n)
naughty.layout.box {notification = n}
end)
--DOC_NEWLINE
-- Notifications as widgets for any `wibox`/`awful.wibar`/`awful.popup`
some_wibar.widget = naughty.list.notifications {}
--DOC_NEWLINE
for bw, color in ipairs {"#ff0000", "#00ff00", "#0000ff"} do
naughty.notification {
title = "A ".. color .." notification",
border_color = color,
border_width = bw*2,
}
end
require("gears.timer").run_delayed_calls_now()

View File

@ -0,0 +1,37 @@
--DOC_HIDE --DOC_GEN_IMAGE --DOC_NO_USAGE
local naughty = require("naughty") --DOC_HIDE
screen[1]._resize {width = 640, height = 480} --DOC_HIDE
require("_date") --DOC_HIDE
require("_default_look") --DOC_HIDE
local function ever_longer_messages(iter) --DOC_HIDE
local ret = "content! " --DOC_HIDE
for _=1, iter do --DOC_HIDE
ret = ret.."more! " --DOC_HIDE
end --DOC_HIDE
return ret --DOC_HIDE
end --DOC_HIDE
--DOC_NEWLINE
naughty.connect_signal("request::display", function(n) --DOC_HIDE
naughty.layout.box {notification = n} --DOC_HIDE
end) --DOC_HIDE
--DOC_NEWLINE
for _, pos in ipairs {
"top_left" , "top_middle" , "top_right",
"bottom_left", "bottom_middle", "bottom_right",
} do
for i=1, 3 do
naughty.notification {
position = pos,
title = pos .. " " .. i,
message = ever_longer_messages(i)
}
end
end
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -0,0 +1,4 @@
====================VVVVVV table: 0x5602abbcedd0

View File

@ -1,4 +1,5 @@
--DOC_HIDE_ALL --DOC_HIDE_ALL
--DOC_GEN_IMAGE
local naughty = require("naughty") --DOC_HIDE local naughty = require("naughty") --DOC_HIDE
for _, pos in ipairs { for _, pos in ipairs {
@ -13,7 +14,7 @@ for _, pos in ipairs {
naughty.notify { naughty.notify {
title = pos, title = pos,
position = pos, position = pos,
text = "", message = "",
} }
end end

View File

@ -0,0 +1,32 @@
--DOC_GEN_IMAGE --DOC_NO_USAGE
require("_default_look") --DOC_HIDE
local awful = {wibar = require("awful.wibar")} --DOC_HIDE
local naughty = require("naughty") --DOC_HIDE
screen[1]._resize {width = 640, height = 240} --DOC_HIDE
local some_wibar = awful.wibar {position = "bottom", height = 48, visible = true} --DOC_HIDE
--DOC_NEWLINE
-- A notification popup using the default widget_template.
naughty.connect_signal("request::display", function(n)
naughty.layout.box {notification = n}
end)
--DOC_NEWLINE
-- Notifications as widgets for any `wibox`/`awful.wibar`/`awful.popup`
some_wibar.widget = naughty.list.notifications {}
--DOC_NEWLINE
for _, color in ipairs {"#ff0000", "#00ff00", "#0000ff"} do
naughty.notification {
title = "A ".. color .." notification",
message = "Message",
fg = color,
}
end
require("gears.timer").run_delayed_calls_now()

View File

@ -0,0 +1,30 @@
--DOC_HIDE --DOC_GEN_IMAGE --DOC_NO_USAGE
local naughty = require("naughty") --DOC_HIDE
screen[1]._resize {width = 640, height = 480} --DOC_HIDE
require("_date") --DOC_HIDE
require("_default_look") --DOC_HIDE
naughty.connect_signal("request::display", function(n) --DOC_HIDE
naughty.layout.box {notification = n} --DOC_HIDE
end) --DOC_HIDE
--DOC_NEWLINE
for _, pos in ipairs {
"top_left" , "top_middle" , "top_right",
"bottom_left", "bottom_middle", "bottom_right",
} do
for i=1, 2 do
naughty.notification {
position = pos,
title = pos .. " " .. i,
width = 50*i,
height = 50*i,
message = "This is a very, very, very, "..
"very, very very long message",
}
end
end
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -0,0 +1,40 @@
--DOC_GEN_IMAGE --DOC_NO_USAGE
require("_default_look") --DOC_HIDE
local awful = {wibar = require("awful.wibar")} --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local naughty = require("naughty") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
screen[1]._resize {width = 640, height = 240} --DOC_HIDE
local some_wibar = awful.wibar {position = "bottom", height = 48, visible = true} --DOC_HIDE
--DOC_NEWLINE
-- A notification popup using the default widget_template.
naughty.connect_signal("request::display", function(n)
naughty.layout.box {notification = n}
end)
--DOC_NEWLINE
-- Notifications as widgets for any `wibox`/`awful.wibar`/`awful.popup`
some_wibar.widget = naughty.list.notifications {
base_layout = wibox.widget {
spacing = beautiful.notification_spacing,
layout = wibox.layout.fixed.horizontal
},
}
--DOC_NEWLINE
for margin = 10, 20, 5 do
naughty.notification {
title = "A notification",
margin = margin,
border_width = 1,
border_color = "#ff0000",
}
end
require("gears.timer").run_delayed_calls_now()

View File

@ -0,0 +1,129 @@
--DOC_GEN_IMAGE
--DOC_NO_USAGE
require("_date") --DOC_HIDE
require("_default_look") --DOC_HIDE
local awful = require("awful") --DOC_HIDE
local gears = require("gears") --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
local naughty = require("naughty") --DOC_HIDE
screen[1]._resize {width = 640, height = 240} --DOC_HIDE
--DOC_HIDE Give some context, otherwise it doesn't look like a screen
local c = client.gen_fake {hide_first=true} --DOC_HIDE
c:geometry { x = 50, y = 45, height = 100, width = 250} --DOC_HIDE
c._old_geo = {c:geometry()} --DOC_HIDE
c:set_label("A client") --DOC_HIDE
c:emit_signal("request::titlebars", "rules", {})--DOC_HIDE
beautiful.notification_icon_size = 48 --DOC_HIDE
beautiful.notification_action_label_only = true --DOC_HIDE
--DOC_NEWLINE
-- This awful.wibar will be placed at the bottom and contain the notifications.
local notif_wb = awful.wibar {
position = "bottom",
height = 48,
visible = #naughty.active > 0,
}
--DOC_NEWLINE
notif_wb:setup {
nil,
{
base_layout = wibox.widget {
spacing_widget = wibox.widget {
orientation = "vertical",
span_ratio = 0.5,
widget = wibox.widget.separator,
},
forced_height = 30,
spacing = 3,
layout = wibox.layout.flex.horizontal
},
widget_template = {
{
naughty.widget.icon,
{
naughty.widget.title,
naughty.widget.message,
{
layout = wibox.widget {
-- Adding the `wibox.widget` allows to share a
-- single instance for all spacers.
spacing_widget = wibox.widget {
orientation = "vertical",
span_ratio = 0.9,
widget = wibox.widget.separator,
},
spacing = 3,
layout = wibox.layout.flex.horizontal
},
widget = naughty.list.widgets,
},
layout = wibox.layout.align.vertical
},
spacing = 10,
fill_space = true,
layout = wibox.layout.fixed.horizontal
},
margins = 5,
widget = wibox.container.margin
},
widget = naughty.list.notifications,
},
-- Add a button to dismiss all notifications, because why not.
{
{
text = "Dismiss all",
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
buttons = gears.table.join(
awful.button({ }, 1, function() naughty.destroy_all_notifications() end)
),
forced_width = 75,
shape = gears.shape.rounded_bar,
shape_border_width = 1,
shape_border_color = beautiful.bg_highlight,
widget = wibox.container.background
},
layout = wibox.layout.align.horizontal
}
--DOC_NEWLINE
-- We don't want to have that bar all the time, only when there is content.
naughty.connect_signal("property::active", function()
notif_wb.visible = #naughty.active > 0
end)
--DOC_HIDE The delayed make sure the legacy popup gets disabled in time
gears.timer.run_delayed_calls_now()--DOC_HIDE
for i=1, 3 do --DOC_HIDE
naughty.notification { --DOC_HIDE
title = "A notification "..i, --DOC_HIDE
text = "Be notified! "..i, --DOC_HIDE
icon = i%2 == 1 and beautiful.awesome_icon, --DOC_HIDE
timeout = 999, --DOC_HIDE
actions = { --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Accept "..i, --DOC_HIDE
icon = beautiful.awesome_icon, --DOC_HIDE
}, --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Refuse", --DOC_HIDE
icon = beautiful.awesome_icon, --DOC_HIDE
}, --DOC_HIDE
} --DOC_HIDE
} --DOC_HIDE
end --DOC_HIDE
require("gears.timer").run_delayed_calls_now()

View File

@ -0,0 +1,42 @@
--DOC_GEN_IMAGE --DOC_NO_USAGE
require("_default_look") --DOC_HIDE
local gears = {shape = require("gears.shape")} --DOC_HIDE
local awful = {wibar = require("awful.wibar")} --DOC_HIDE
local naughty = require("naughty") --DOC_HIDE
screen[1]._resize {width = 640, height = 240} --DOC_HIDE
local some_wibar = awful.wibar {position = "bottom", height = 48, visible = true} --DOC_HIDE
--DOC_NEWLINE
-- A notification popup using the default widget_template.
naughty.connect_signal("request::display", function(n)
naughty.layout.box {notification = n}
end)
--DOC_NEWLINE
-- Notifications as widgets for any `wibox`/`awful.wibar`/`awful.popup`
some_wibar.widget = naughty.list.notifications {}
--DOC_NEWLINE
local shapes = {
gears.shape.octogon,
gears.shape.rounded_rect,
gears.shape.rounded_bar
}
--DOC_NEWLINE
for idx=1, 3 do
naughty.notification {
title = "A notification",
border_color = "#0000ff",
border_width = idx*2,
shape = shapes[idx],
}
end
require("gears.timer").run_delayed_calls_now()

View File

@ -5,6 +5,7 @@
require("_date") require("_date")
local awful = require("awful") local awful = require("awful")
local gears = require("gears") local gears = require("gears")
local naughty = require("naughty")
local wibox = require("wibox") local wibox = require("wibox")
local beautiful = require("beautiful") --DOC_HIDE local beautiful = require("beautiful") --DOC_HIDE
local look = require("_default_look") local look = require("_default_look")
@ -136,6 +137,7 @@ local function create_info(text, x, y, width, height)
text = text, text = text,
align = "center", align = "center",
ellipsize = "none", ellipsize = "none",
wrap = "word",
widget = wibox.widget.textbox widget = wibox.widget.textbox
}, },
margins = 10, margins = 10,
@ -170,17 +172,29 @@ local function create_line(x1, y1, x2, y2)
}, {x=x1, y=y1}) }, {x=x1, y=y1})
end end
create_info("awful.wibar", 200, 50, 100, 30) naughty.connect_signal("request::display", function(n)
naughty.layout.box {notification = n}
end)
naughty.notification {
title = "A notification",
message = "With a message! ....",
position = "top_middle",
}
create_info("awful.wibar", 100, 50, 100, 30)
create_info("awful.titlebar", 250, 350, 100, 30) create_info("awful.titlebar", 250, 350, 100, 30)
create_info("awful.tooltip", 30, 130, 100, 30) create_info("awful.tooltip", 30, 130, 100, 30)
create_info("awful.popup", 450, 240, 100, 30) create_info("awful.popup", 450, 240, 100, 30)
create_info("naughty.layout.box", 255, 110, 130, 30)
create_info("Standard `wibox`", 420, 420, 130, 30) create_info("Standard `wibox`", 420, 420, 130, 30)
create_line(250, 10, 250, 55) create_line(150, 10, 150, 55)
create_line(75, 100, 75, 135) create_line(75, 100, 75, 135)
create_line(545, 432, 575, 432) create_line(545, 432, 575, 432)
create_line(500, 165, 500, 245) create_line(500, 165, 500, 245)
create_line(390, 250, 450, 250) create_line(390, 250, 450, 250)
create_line(190, 365, 255, 365) create_line(190, 365, 255, 365)
create_line(320, 60, 320, 110)
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 --DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -1,5 +1,6 @@
--DOC_NO_USAGE --DOC_NO_USAGE
--DOC_HIDE_ALL --DOC_HIDE_ALL
--DOC_GEN_IMAGE
-- local naughty = require("naughty") -- local naughty = require("naughty")
dbus.notify_send( dbus.notify_send(

View File

@ -1,3 +1,4 @@
--DOC_GEN_IMAGE
local beautiful = require("beautiful") --DOC_HIDE local beautiful = require("beautiful") --DOC_HIDE
@ -5,7 +6,9 @@ local text = [[An <b>important</b>
<i>notification</i> <i>notification</i>
]] ]]
require("naughty").notify { --DOC_NEWLINE
require("naughty").notification {
title = "Hello world!", title = "Hello world!",
text = text, text = text,
icon = beautiful.icon, icon = beautiful.icon,

View File

@ -1,4 +1,5 @@
--DOC_HIDE_ALL --DOC_HIDE_ALL
--DOC_GEN_IMAGE
-- local naughty = require("naughty") -- local naughty = require("naughty")
dbus.notify_send( dbus.notify_send(

View File

@ -1,31 +1,36 @@
--DOC_GEN_IMAGE --DOC_NO_USAGE
local beautiful = require("beautiful") --DOC_HIDE local beautiful = require("beautiful") --DOC_HIDE
local gears = {shape=require("gears.shape")} --DOC_HIDE local gears = {shape=require("gears.shape")} --DOC_HIDE
local naughty = require("naughty") --DOC_HIDE local naughty = require("naughty") --DOC_HIDE
local text = [[An <b>important</b> local text = [[An <b>important</b>
<i>notification</i> <i>notification</i>
]] ]]
local shapes = { --DOC_NEWLINE
gears.shape.rounded_rect,
gears.shape.hexagon,
gears.shape.octogon,
function(cr, w, h)
return gears.shape.infobubble(cr, w, h, 20, 10, w/2 - 10)
end
}
for _, s in ipairs(shapes) do local shapes = {
naughty.notify { gears.shape.rounded_rect,
title = "Hello world!", gears.shape.hexagon,
text = text, gears.shape.octogon,
icon = beautiful.icon, function(cr, w, h)
shape = s, return gears.shape.infobubble(cr, w, h, 20, 10, w/2 - 10)
border_width = 3, end
border_color = beautiful.bg_highlight, }
margin = 15,
} --DOC_NEWLINE
end
for _, s in ipairs(shapes) do
naughty.notify {
title = "Hello world!",
text = text,
icon = beautiful.icon,
shape = s,
border_width = 3,
border_color = beautiful.bg_highlight,
margin = 15,
}
end
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 --DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -1,3 +1,4 @@
--DOC_GEN_IMAGE
local file_path, image_path = ... local file_path, image_path = ...
require("_common_template")(...) require("_common_template")(...)
local wibox = require("wibox") local wibox = require("wibox")

View File

@ -0,0 +1,62 @@
--DOC_GEN_IMAGE
local parent = ... --DOC_HIDE --DOC_NO_USAGE
local naughty = { --DOC_HIDE
list = {actions = require("naughty.list.actions")}, --DOC_HIDE
notification = require("naughty.notification"), --DOC_HIDE
action = require("naughty.action") --DOC_HIDE
} --DOC_HIDE
local gears = {shape = require("gears.shape")} --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
local notif = naughty.notification { --DOC_HIDE
title = "A notification", --DOC_HIDE
message = "This notification has actions!", --DOC_HIDE
actions = { --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Accept", --DOC_HIDE
}, --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Refuse", --DOC_HIDE
}, --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Ignore", --DOC_HIDE
}, --DOC_HIDE
} --DOC_HIDE
} --DOC_HIDE
--DOC_NEWLINE
parent:add( wibox.container.background(--DOC_HIDE
wibox.widget {
notification = notif,
base_layout = wibox.widget {
spacing = 3,
spacing_widget = wibox.widget {
orientation = "horizontal",
widget = wibox.widget.separator,
},
layout = wibox.layout.fixed.vertical
},
widget_template = {
{
{
{
id = "text_role",
widget = wibox.widget.textbox
},
widget = wibox.container.place
},
shape = gears.shape.rounded_rect,
shape_border_width = 2,
shape_border_color = beautiful.bg_normal,
forced_height = 30,
widget = wibox.container.background,
},
margins = 4,
widget = wibox.container.margin,
},
forced_width = 100, --DOC_HIDE
widget = naughty.list.actions,
}
,beautiful.bg_normal)) --DOC_HIDE

View File

@ -0,0 +1,68 @@
--DOC_GEN_IMAGE
local parent = ... --DOC_HIDE --DOC_NO_USAGE
local naughty = { --DOC_HIDE
list = {actions = require("naughty.list.actions")}, --DOC_HIDE
notification = require("naughty.notification"), --DOC_HIDE
action = require("naughty.action") --DOC_HIDE
} --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
local notif = naughty.notification { --DOC_HIDE
title = "A notification", --DOC_HIDE
message = "This notification has actions!", --DOC_HIDE
actions = { --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Accept", --DOC_HIDE
icon = beautiful.awesome_icon, --DOC_HIDE
}, --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Refuse", --DOC_HIDE
icon = beautiful.awesome_icon, --DOC_HIDE
}, --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Ignore", --DOC_HIDE
icon = beautiful.awesome_icon, --DOC_HIDE
}, --DOC_HIDE
} --DOC_HIDE
} --DOC_HIDE
--DOC_NEWLINE
parent:add( wibox.container.background(--DOC_HIDE
wibox.widget {
notification = notif,
forced_width = 250, --DOC_HIDE
base_layout = wibox.widget {
spacing = 3,
spacing_widget = wibox.widget {
orientation = "vertical",
widget = wibox.widget.separator,
},
layout = wibox.layout.flex.horizontal
},
widget_template = {
{
{
{
id = "icon_role",
forced_height = 16,
forced_width = 16,
widget = wibox.widget.imagebox
},
{
id = "text_role",
widget = wibox.widget.textbox
},
spacing = 5,
layout = wibox.layout.fixed.horizontal
},
id = "background_role",
widget = wibox.container.background,
},
margins = 4,
widget = wibox.container.margin,
},
widget = naughty.list.actions,
}
,beautiful.bg_normal)) --DOC_HIDE

View File

@ -0,0 +1,34 @@
--DOC_GEN_IMAGE
local parent = ... --DOC_HIDE --DOC_NO_USAGE
local naughty = { --DOC_HIDE
list = {actions = require("naughty.list.actions")}, --DOC_HIDE
notification = require("naughty.notification"), --DOC_HIDE
action = require("naughty.action") --DOC_HIDE
} --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
local notif = naughty.notification {
title = "A notification",
message = "This notification has actions!",
actions = {
naughty.action {
name = "Accept",
},
naughty.action {
name = "Refuse",
},
naughty.action {
name = "Ignore",
},
}
}
--DOC_NEWLINE
parent:add( wibox.container.background(--DOC_HIDE
wibox.widget {
notification = notif,
widget = naughty.list.actions,
}
,beautiful.bg_normal)) --DOC_HIDE

View File

@ -0,0 +1,63 @@
--DOC_GEN_IMAGE
local parent = ... --DOC_HIDE --DOC_NO_USAGE
local naughty = { --DOC_HIDE
list = {actions = require("naughty.list.actions")}, --DOC_HIDE
notification = require("naughty.notification"), --DOC_HIDE
action = require("naughty.action") --DOC_HIDE
} --DOC_HIDE
local gears = {shape = require("gears.shape")} --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
local notif = naughty.notification { --DOC_HIDE
title = "A notification", --DOC_HIDE
message = "This notification has actions!", --DOC_HIDE
actions = { --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Accept", --DOC_HIDE
icon = beautiful.awesome_icon, --DOC_HIDE
}, --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Refuse", --DOC_HIDE
icon = beautiful.awesome_icon, --DOC_HIDE
selected = true, --DOC_HIDE
}, --DOC_HIDE
naughty.action { --DOC_HIDE
name = "Ignore", --DOC_HIDE
icon = beautiful.awesome_icon, --DOC_HIDE
}, --DOC_HIDE
} --DOC_HIDE
} --DOC_HIDE
--DOC_NEWLINE
parent:add( wibox.container.margin(--DOC_HIDE
wibox.widget {
notification = notif,
forced_width = 250, --DOC_HIDE
base_layout = wibox.widget {
spacing = 3,
spacing_widget = wibox.widget {
orientation = "vertical",
widget = wibox.widget.separator,
},
layout = wibox.layout.flex.horizontal
},
style = {
underline_normal = false,
underline_selected = true,
shape_normal = gears.shape.octogon,
shape_selected = gears.shape.hexagon,
shape_border_width_normal = 2,
shape_border_width_selected = 4,
icon_size_normal = 16,
icon_size_selected = 24,
shape_border_color_normal = "#0000ff",
shape_border_color_selected = "#ff0000",
bg_normal = "#ffff00",
bg_selected = "#00ff00",
},
forced_height = beautiful.get_font_height(beautiful.font) * 2.5,
widget = naughty.list.actions,
}
,0,0,5,5)) --DOC_HIDE

View File

@ -0,0 +1,107 @@
--DOC_GEN_IMAGE --DOC_HIDE_ALL
local parent = ...
local naughty = require("naughty")
local wibox = require("wibox")
local beautiful = require("beautiful")
local def = require("naughty.widget._default")
local acommon = require("awful.widget.common")
local aplace = require("awful.placement")
local gears = require("gears")
beautiful.notification_bg = beautiful.bg_normal
local notif = naughty.notification {
title = "A notification",
message = "This notification has actions!",
icon = beautiful.awesome_icon,
actions = {
naughty.action {
name = "Accept",
icon = beautiful.awesome_icon,
},
naughty.action {
name = "Refuse",
icon = beautiful.awesome_icon,
},
naughty.action {
name = "Ignore",
icon = beautiful.awesome_icon,
},
}
}
local default = wibox.widget(def)
acommon._set_common_property(default, "notification", notif)
local w, h = default:fit({dpi=96}, 9999, 9999)
default.forced_width = w + 25
default.forced_height = h
local canvas = wibox.layout.manual()
canvas.forced_width = w + 150
canvas.forced_height = h + 100
canvas:add_at(default, aplace.centered)
local function create_info(text, x, y, width, height)
canvas:add_at(wibox.widget {
{
{
text = text,
align = "center",
ellipsize = "none",
wrap = "word",
widget = wibox.widget.textbox
},
top = 2,
bottom = 2,
left = 10,
right = 10,
widget = wibox.container.margin
},
forced_width = width,
forced_height = height,
shape = gears.shape.rectangle,
shape_border_width = 1,
shape_border_color = beautiful.border_color,
bg = "#ffff0055",
widget = wibox.container.background
}, {x = x, y = y})
end
local function create_line(x1, y1, x2, y2)
return canvas:add_at(wibox.widget {
fit = function()
return x2-x1+6, y2-y1+6
end,
draw = function(_, _, cr)
cr:set_source_rgb(0,0,0)
cr:set_line_width(1)
cr:arc(1.5, 1.5, 1.5, 0, math.pi*2)
cr:arc(x2-x1+1.5, y2-y1+1.5, 1.5, 0, math.pi*2)
cr:fill()
cr:move_to(1.5,1.5)
cr:line_to(x2-x1+1.5, y2-y1+1.5)
cr:stroke()
end,
layout = wibox.widget.base.make_widget,
}, {x=x1, y=y1})
end
create_info("naughty.widget.background", 10, canvas.forced_height - 30, nil, nil)
create_line(80, canvas.forced_height-55, 80, canvas.forced_height - 30)
create_info("naughty.list.actions", 170, canvas.forced_height - 30, nil, nil)
create_line(200, canvas.forced_height-105, 200, canvas.forced_height - 30)
create_info("naughty.widget.icon", 20, 25, nil, nil)
create_line(80, 40, 80, 60)
create_info("naughty.widget.title", 90, 4, nil, nil)
create_line(140, 20, 140, 60)
create_info("naughty.widget.message", 150, 25, nil, nil)
create_line(210, 40, 210, 75)
parent:add(canvas)

View File

@ -0,0 +1,22 @@
--DOC_GEN_IMAGE
local parent = ... --DOC_HIDE
local naughty = { --DOC_HIDE
widget = { icon = require("naughty.widget.icon")}, --DOC_HIDE
notification = require("naughty.notification")} --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
local notif = naughty.notification {
title = "A notification",
message = "This notification has actions!",
icon = beautiful.awesome_icon,
}
--DOC_NEWLINE
parent:add( --DOC_HIDE
wibox.widget {
notification = notif,
widget = naughty.widget.icon,
}
) --DOC_HIDE

View File

@ -0,0 +1,62 @@
--DOC_GEN_IMAGE
local parent = ... --DOC_HIDE_ALL
local naughty = {
widget = { icon = require("naughty.widget.icon")},
notification = require("naughty.notification"),
}
local wibox = require("wibox")
local beautiful = require("beautiful")
local notif = naughty.notification {
title = "A notification",
text = "This notification has actions!",
icon = beautiful.awesome_icon,
actions = {
["Accept"] = function() end,
["Refuse"] = function() end,
["Ignore"] = function() end,
}
}
local icons = {}
for _, strategy in ipairs {"resize", "scale", "center" } do
table.insert(icons, wibox.widget {
{
{
resize_strategy = strategy,
notification = notif,
widget = naughty.widget.icon,
},
bg = beautiful.bg_normal,
widget = wibox.container.background
},
valign = "top",
halign = "left",
widget = wibox.container.place
})
end
parent:add(
wibox.widget {
{
markup = "<b>resize:</b>",
widget = wibox.widget.textbox,
},
{
markup = "<b>scale:</b>",
widget = wibox.widget.textbox,
},
{
markup = "<b>center:</b>",
widget = wibox.widget.textbox,
},
icons[1],
icons[2],
icons[3],
forced_num_rows = 2,
forced_num_cols = 3,
spacing = 5,
widget = wibox.layout.grid,
}
)

View File

@ -0,0 +1,22 @@
--DOC_GEN_IMAGE
local parent = ... --DOC_HIDE
local naughty = { --DOC_HIDE
widget = { message = require("naughty.widget.message")}, --DOC_HIDE
notification = require("naughty.notification")} --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
local notif = naughty.notification {
title = "A notification",
message = "This notification no actions!",
icon = beautiful.awesome_icon,
}
--DOC_NEWLINE
parent:add( --DOC_HIDE
wibox.widget {
notification = notif,
widget = naughty.widget.message,
}
) --DOC_HIDE

View File

@ -0,0 +1,22 @@
--DOC_GEN_IMAGE
local parent = ... --DOC_HIDE
local naughty = { --DOC_HIDE
widget = { title = require("naughty.widget.title")}, --DOC_HIDE
notification = require("naughty.notification")} --DOC_HIDE
local wibox = require("wibox") --DOC_HIDE
local beautiful = require("beautiful") --DOC_HIDE
local notif = naughty.notification {
title = "A notification",
message = "This notification no actions!",
icon = beautiful.awesome_icon,
}
--DOC_NEWLINE
parent:add( --DOC_HIDE
wibox.widget {
notification = notif,
widget = naughty.widget.title,
}
) --DOC_HIDE