summaryrefslogtreecommitdiff
path: root/awesome/lib/naughty
diff options
context:
space:
mode:
Diffstat (limited to 'awesome/lib/naughty')
-rw-r--r--awesome/lib/naughty/core.lua688
-rw-r--r--awesome/lib/naughty/dbus.lua261
-rw-r--r--awesome/lib/naughty/init.lua14
3 files changed, 0 insertions, 963 deletions
diff --git a/awesome/lib/naughty/core.lua b/awesome/lib/naughty/core.lua
deleted file mode 100644
index 764afe2..0000000
--- a/awesome/lib/naughty/core.lua
+++ /dev/null
@@ -1,688 +0,0 @@
-----------------------------------------------------------------------------
---- Notification library
---
--- @author koniu <gkusnierz@gmail.com>
--- @copyright 2008 koniu
--- @module naughty
-----------------------------------------------------------------------------
-
--- Package environment
-local pairs = pairs
-local table = table
-local type = type
-local string = string
-local pcall = pcall
-local capi = { screen = screen,
- awesome = awesome }
-local timer = require("gears.timer")
-local button = require("awful.button")
-local screen = require("awful.screen")
-local util = require("awful.util")
-local bt = require("beautiful")
-local wibox = require("wibox")
-local surface = require("gears.surface")
-local cairo = require("lgi").cairo
-local dpi = require("beautiful").xresources.apply_dpi
-
-local function get_screen(s)
- return s and capi.screen[s]
-end
-
-local naughty = {}
-
---[[--
-Naughty configuration - a table containing common popup settings.
-
-@table naughty.config
-@tfield[opt=apply_dpi(4)] int padding Space between popups and edge of the
- workarea.
-@tfield[opt=apply_dpi(1)] int spacing Spacing between popups.
-@tfield[opt={"/usr/share/pixmaps/"}] table icon_dirs List of directories
- that will be checked by `getIcon()`.
-@tfield[opt={ "png", "gif" }] table icon_formats List of formats that will be
- checked by `getIcon()`.
-@tfield[opt] function notify_callback Callback used to modify or reject
-notifications, e.g.
- naughty.config.notify_callback = function(args)
- args.text = 'prefix: ' .. args.text
- return args
- end
-
-@tfield table presets Notification presets. See `config.presets`.
-
-@tfield table defaults Default values for the params to `notify()`. These can
- optionally be overridden by specifying a preset. See `config.defaults`.
-
---]]
---
-naughty.config = {
- padding = dpi(4),
- spacing = dpi(1),
- icon_dirs = { "/usr/share/pixmaps/", },
- icon_formats = { "png", "gif" },
- notify_callback = nil,
-}
-
---- Notification presets for `naughty.notify`.
--- This holds presets for different purposes. A preset is a table of any
--- parameters for `notify()`, overriding the default values
--- (`naughty.config.defaults`).
---
--- You have to pass a reference of a preset in your `notify()` as the `preset`
--- argument.
---
--- The presets `"low"`, `"normal"` and `"critical"` are used for notifications
--- over DBUS.
---
--- @table config.presets
--- @tfield table low The preset for notifications with low urgency level.
--- @tfield[opt=5] int low.timeout
--- @tfield[opt=empty] table normal The default preset for every notification without a
--- preset that will also be used for normal urgency level.
--- @tfield table critical The preset for notifications with a critical urgency
--- level.
--- @tfield[opt="#ff0000"] string critical.bg
--- @tfield[opt="#ffffff"] string critical.fg
--- @tfield[opt=0] string critical.timeout
-naughty.config.presets = {
- low = {
- timeout = 5
- },
- normal = {},
- critical = {
- bg = "#ff0000",
- fg = "#ffffff",
- timeout = 0,
- }
-}
-
---- Defaults for `naughty.notify`.
---
--- @table config.defaults
--- @tfield[opt=5] int timeout
--- @tfield[opt=""] string text
--- @tfield[opt] int screen Defaults to `awful.screen.focused`.
--- @tfield[opt=true] boolean ontop
--- @tfield[opt=apply_dpi(5)] int margin
--- @tfield[opt=apply_dpi(1)] int border_width
--- @tfield[opt="top_right"] string position
-naughty.config.defaults = {
- timeout = 5,
- text = "",
- screen = nil,
- ontop = true,
- margin = dpi(5),
- border_width = dpi(1),
- position = "top_right"
-}
-
-naughty.notificationClosedReason = {
- silent = -1,
- expired = 1,
- dismissedByUser = 2,
- dismissedByCommand = 3,
- undefined = 4
-}
-
--- Counter for the notifications
--- Required for later access via DBUS
-local counter = 1
-
--- True if notifying is suspended
-local suspended = false
-
---- Index of notifications per screen and position.
--- See config table for valid 'position' values.
--- Each element is a table consisting of:
---
--- @field box Wibox object containing the popup
--- @field height Popup height
--- @field width Popup width
--- @field die Function to be executed on timeout
--- @field id Unique notification id based on a counter
--- @table notifications
-naughty.notifications = { suspended = { } }
-screen.connect_for_each_screen(function(s)
- naughty.notifications[s] = {
- top_left = {},
- top_middle = {},
- top_right = {},
- bottom_left = {},
- bottom_middle = {},
- bottom_right = {},
- }
-end)
-
-capi.screen.connect_signal("removed", function(scr)
- -- Destroy all notifications on this screen
- for _, list in pairs(naughty.notifications[scr]) do
- while #list > 0 do
- naughty.destroy(list[1])
- end
- end
- naughty.notifications[scr] = nil
-end)
-
---- Notification state
-function naughty.is_suspended()
- return suspended
-end
-
---- Suspend notifications
-function naughty.suspend()
- suspended = true
-end
-
---- Resume notifications
-function naughty.resume()
- suspended = false
- for _, v in pairs(naughty.notifications.suspended) do
- v.box.visible = true
- if v.timer then v.timer:start() end
- end
- naughty.notifications.suspended = { }
-end
-
---- Toggle notification state
-function naughty.toggle()
- if suspended then
- naughty.resume()
- else
- naughty.suspend()
- end
-end
-
---- Evaluate desired position of the notification by index - internal
---
--- @param s Screen to use
--- @param position top_right | top_left | bottom_right | bottom_left
--- | top_middle | bottom_middle
--- @param idx Index of the notification
--- @param[opt] width Popup width.
--- @param height Popup height
--- @return Absolute position and index in { x = X, y = Y, idx = I } table
-local function get_offset(s, position, idx, width, height)
- s = get_screen(s)
- local ws = s.workarea
- local v = {}
- idx = idx or #naughty.notifications[s][position] + 1
- width = width or naughty.notifications[s][position][idx].width
-
- -- calculate x
- if position:match("left") then
- v.x = ws.x + naughty.config.padding
- elseif position:match("middle") then
- v.x = (ws.width / 2) - (width / 2)
- else
- v.x = ws.x + ws.width - (width + naughty.config.padding)
- end
-
- -- calculate existing popups' height
- local existing = 0
- for i = 1, idx-1, 1 do
- existing = existing + naughty.notifications[s][position][i].height + naughty.config.spacing
- end
-
- -- calculate y
- if position:match("top") then
- v.y = ws.y + naughty.config.padding + existing
- else
- v.y = ws.y + ws.height - (naughty.config.padding + height + existing)
- end
-
- -- Find old notification to replace in case there is not enough room.
- -- This tries to skip permanent notifications (without a timeout),
- -- e.g. critical ones.
- local find_old_to_replace = function()
- for i = 1, idx-1 do
- local n = naughty.notifications[s][position][i]
- if n.timeout > 0 then
- return n
- end
- end
- -- Fallback to first one.
- return naughty.notifications[s][position][1]
- end
-
- -- if positioned outside workarea, destroy oldest popup and recalculate
- if v.y + height > ws.y + ws.height or v.y < ws.y then
- naughty.destroy(find_old_to_replace())
- idx = idx - 1
- v = get_offset(s, position, idx, width, height)
- end
- if not v.idx then v.idx = idx end
-
- return v
-end
-
---- Re-arrange notifications according to their position and index - internal
---
--- @return None
-local function arrange(s)
- for p in pairs(naughty.notifications[s]) do
- for i,notification in pairs(naughty.notifications[s][p]) do
- local offset = get_offset(s, p, i, notification.width, notification.height)
- notification.box:geometry({ x = offset.x, y = offset.y })
- notification.idx = offset.idx
- end
- end
-end
-
---- Destroy notification by notification object
---
--- @param notification Notification object to be destroyed
--- @param reason One of the reasons from notificationClosedReason
--- @return True if the popup was successfully destroyed, nil otherwise
-function naughty.destroy(notification, reason)
- if notification and notification.box.visible then
- if suspended then
- for k, v in pairs(naughty.notifications.suspended) do
- if v.box == notification.box then
- table.remove(naughty.notifications.suspended, k)
- break
- end
- end
- end
- local scr = notification.screen
- table.remove(naughty.notifications[scr][notification.position], notification.idx)
- if notification.timer then
- notification.timer:stop()
- end
- notification.box.visible = false
- arrange(scr)
- if notification.destroy_cb and reason ~= naughty.notificationClosedReason.silent then
- notification.destroy_cb(reason or naughty.notificationClosedReason.undefined)
- end
- return true
- end
-end
-
---- Get notification by ID
---
--- @param id ID of the notification
--- @return notification object if it was found, nil otherwise
-function naughty.getById(id)
- -- iterate the notifications to get the notfications with the correct ID
- for s in pairs(naughty.notifications) do
- for p in pairs(naughty.notifications[s]) do
- for _, notification in pairs(naughty.notifications[s][p]) do
- if notification.id == id then
- return notification
- end
- end
- end
- end
-end
-
---- Install expiration timer for notification object.
--- @tparam notification notification Notification object.
--- @tparam number timeout Time in seconds to be set as expiration timeout.
-local function set_timeout(notification, timeout)
- local die = function (reason)
- naughty.destroy(notification, reason)
- end
- if timeout > 0 then
- local timer_die = timer { timeout = timeout }
- timer_die:connect_signal("timeout", function() die(naughty.notificationClosedReason.expired) end)
- if not suspended then
- timer_die:start()
- end
- notification.timer = timer_die
- end
- notification.die = die
-end
-
---- Set new notification timeout.
--- @tparam notification notification Notification object, which timer is to be reset.
--- @tparam number new_timeout Time in seconds after which notification disappears.
--- @return None.
-function naughty.reset_timeout(notification, new_timeout)
- if notification.timer then notification.timer:stop() end
-
- local timeout = new_timeout or notification.timeout
- set_timeout(notification, timeout)
- notification.timeout = timeout
-
- notification.timer:start()
-end
-
---- Escape and set title and text for notification object.
--- @tparam notification notification Notification object.
--- @tparam string title Title of notification.
--- @tparam string text Main text of notification.
--- @return None.
-local function set_text(notification, title, text)
- local escape_pattern = "[<>&]"
- local escape_subs = { ['<'] = "&lt;", ['>'] = "&gt;", ['&'] = "&amp;" }
-
- local textbox = notification.textbox
-
- local function setMarkup(pattern, replacements)
- return textbox:set_markup_silently(string.format('<b>%s</b>%s', title, text:gsub(pattern, replacements)))
- end
- local function setText()
- textbox:set_text(string.format('%s %s', title, text))
- end
-
- -- Since the title cannot contain markup, it must be escaped first so that
- -- it is not interpreted by Pango later.
- title = title:gsub(escape_pattern, escape_subs)
- -- Try to set the text while only interpreting <br>.
- if not setMarkup("<br.->", "\n") then
- -- That failed, escape everything which might cause an error from pango
- if not setMarkup(escape_pattern, escape_subs) then
- -- Ok, just ignore all pango markup. If this fails, we got some invalid utf8
- if not pcall(setText) then
- textbox:set_markup("<i>&lt;Invalid markup or UTF8, cannot display message&gt;</i>")
- end
- end
- end
-end
-
---- Replace title and text of an existing notification.
--- @tparam notification notification Notification object, which contents are to be replaced.
--- @tparam string new_title New title of notification. If not specified, old title remains unchanged.
--- @tparam string new_text New text of notification. If not specified, old text remains unchanged.
--- @return None.
-function naughty.replace_text(notification, new_title, new_text)
- local title = new_title
-
- if title then title = title .. "\n" else title = "" end
-
- set_text(notification, title, new_text)
-end
-
---- Create a notification.
---
--- @tab args The argument table containing any of the arguments below.
--- @string[opt=""] args.text Text of the notification.
--- @string[opt] args.title Title of the notification.
--- @int[opt=5] args.timeout Time in seconds after which popup expires.
--- Set 0 for no timeout.
--- @int[opt] args.hover_timeout Delay in seconds after which hovered popup disappears.
--- @tparam[opt=focused] integer|screen args.screen Target screen for the notification.
--- @string[opt="top_right"] args.position Corner of the workarea displaying the popups.
--- Values: `"top_right"`, `"top_left"`, `"bottom_left"`,
--- `"bottom_right"`, `"top_middle"`, `"bottom_middle"`.
--- @bool[opt=true] args.ontop Boolean forcing popups to display on top.
--- @int[opt=auto] args.height Popup height.
--- @int[opt=auto] args.width Popup width.
--- @string[opt=beautiful.font or awesome.font] args.font Notification font.
--- @string[opt] args.icon Path to icon.
--- @int[opt] args.icon_size Desired icon size in px.
--- @string[opt=`beautiful.fg_focus` or `'#ffffff'`] args.fg Foreground color.
--- @string[opt=`beautiful.bg_focus` or `'#535d6c'`] args.bg Background color.
--- @int[opt=1] args.border_width Border width.
--- @string[opt=`beautiful.border_focus` or `'#535d6c'`] args.border_color Border color.
--- @tparam[opt] func args.run Function to run on left click. The notification
--- object will be passed to it as an argument.
--- You need to call e.g.
--- `notification.die(naughty.notificationClosedReason.dismissedByUser)` from
--- there to dismiss the notification yourself.
--- @tparam[opt] func args.destroy Function to run when notification is destroyed.
--- @tparam[opt] table args.preset Table with any of the above parameters.
--- Note: Any parameters specified directly in args will override ones defined
--- in the preset.
--- @tparam[opt] int args.replaces_id Replace the notification with the given ID.
--- @tparam[opt] func args.callback Function that will be called with all arguments.
--- The notification will only be displayed if the function returns true.
--- Note: this function is only relevant to notifications sent via dbus.
--- @tparam[opt] table args.actions Mapping that maps a string to a callback when this
--- action is selected.
--- @usage naughty.notify({ title = "Achtung!", text = "You're idling", timeout = 0 })
--- @treturn ?table The notification object, or nil in case a notification was
--- not displayed.
-function naughty.notify(args)
- if naughty.config.notify_callback then
- args = naughty.config.notify_callback(args)
- if not args then return end
- end
-
- -- gather variables together
- local preset = util.table.join(naughty.config.defaults or {},
- args.preset or naughty.config.presets.normal or {})
- local timeout = args.timeout or preset.timeout
- local icon = args.icon or preset.icon
- local icon_size = args.icon_size or preset.icon_size
- local text = args.text or preset.text
- local title = args.title or preset.title
- local s = get_screen(args.screen or preset.screen or screen.focused())
- if not s then
- local err = "naughty.notify: there is no screen available to display the following notification:"
- err = string.format("%s title='%s' text='%s'", err, tostring(title or ""), tostring(text or ""))
- require("gears.debug").print_warning(err)
- return
- end
- local ontop = args.ontop or preset.ontop
- local width = args.width or preset.width
- local height = args.height or preset.height
- local hover_timeout = args.hover_timeout or preset.hover_timeout
- local opacity = args.opacity or preset.opacity
- local margin = args.margin or preset.margin
- local border_width = args.border_width or preset.border_width
- local position = args.position or preset.position
- local actions = args.actions
- local destroy_cb = args.destroy
-
- -- beautiful
- local beautiful = bt.get()
- local font = args.font or preset.font or beautiful.font or capi.awesome.font
- local fg = args.fg or preset.fg or beautiful.fg_normal or '#ffffff'
- local bg = args.bg or preset.bg or beautiful.bg_normal or '#535d6c'
- local border_color = args.border_color or preset.border_color or beautiful.bg_focus or '#535d6c'
- local notification = { screen = s, destroy_cb = destroy_cb, timeout = timeout }
-
- -- replace notification if needed
- if args.replaces_id then
- local obj = naughty.getById(args.replaces_id)
- if obj then
- -- destroy this and ...
- naughty.destroy(obj, naughty.notificationClosedReason.silent)
- end
- -- ... may use its ID
- if args.replaces_id <= counter then
- notification.id = args.replaces_id
- else
- counter = counter + 1
- notification.id = counter
- end
- else
- -- get a brand new ID
- counter = counter + 1
- notification.id = counter
- end
-
- notification.position = position
-
- if title then title = title .. "\n" else title = "" end
-
- -- hook destroy
- set_timeout(notification, timeout)
- local die = notification.die
-
- local run = function ()
- if args.run then
- args.run(notification)
- else
- die(naughty.notificationClosedReason.dismissedByUser)
- end
- end
-
- local hover_destroy = function ()
- if hover_timeout == 0 then
- die(naughty.notificationClosedReason.expired)
- else
- if notification.timer then notification.timer:stop() end
- notification.timer = timer { timeout = hover_timeout }
- notification.timer:connect_signal("timeout", function() die(naughty.notificationClosedReason.expired) end)
- notification.timer:start()
- end
- end
-
- -- create textbox
- local textbox = wibox.widget.textbox()
- local marginbox = wibox.container.margin()
- marginbox:set_margins(margin)
- marginbox:set_widget(textbox)
- textbox:set_valign("middle")
- textbox:set_font(font)
-
- notification.textbox = textbox
-
- set_text(notification, title, text)
-
- local actionslayout = wibox.layout.fixed.vertical()
- local actions_max_width = 0
- local actions_total_height = 0
- if actions then
- for action, callback in pairs(actions) do
- local actiontextbox = wibox.widget.textbox()
- local actionmarginbox = wibox.container.margin()
- actionmarginbox:set_margins(margin)
- actionmarginbox:set_widget(actiontextbox)
- actiontextbox:set_valign("middle")
- actiontextbox:set_font(font)
- actiontextbox:set_markup(string.format('☛ <u>%s</u>', action))
- -- calculate the height and width
- local w, h = actiontextbox:get_preferred_size(s)
- local action_height = h + 2 * margin
- local action_width = w + 2 * margin
-
- actionmarginbox:buttons(util.table.join(
- button({ }, 1, callback),
- button({ }, 3, callback)
- ))
- actionslayout:add(actionmarginbox)
-
- actions_total_height = actions_total_height + action_height
- if actions_max_width < action_width then
- actions_max_width = action_width
- end
- end
- end
-
- -- create iconbox
- local iconbox = nil
- local iconmargin = nil
- local icon_w, icon_h = 0, 0
- if icon then
- -- Is this really an URI instead of a path?
- if type(icon) == "string" and string.sub(icon, 1, 7) == "file://" then
- icon = string.sub(icon, 8)
- end
- -- try to guess icon if the provided one is non-existent/readable
- if type(icon) == "string" and not util.file_readable(icon) then
- icon = util.geticonpath(icon, naughty.config.icon_formats, naughty.config.icon_dirs, icon_size) or icon
- end
-
- -- is the icon file readable?
- icon = surface.load_uncached(icon)
-
- -- if we have an icon, use it
- if icon then
- iconbox = wibox.widget.imagebox()
- iconmargin = wibox.container.margin(iconbox, margin, margin, margin, margin)
- if icon_size then
- local scaled = cairo.ImageSurface(cairo.Format.ARGB32, icon_size, icon_size)
- local cr = cairo.Context(scaled)
- cr:scale(icon_size / icon:get_height(), icon_size / icon:get_width())
- cr:set_source_surface(icon, 0, 0)
- cr:paint()
- icon = scaled
- end
- iconbox:set_resize(false)
- iconbox:set_image(icon)
- icon_w = icon:get_width()
- icon_h = icon:get_height()
- end
- end
-
- -- create container wibox
- notification.box = wibox({ fg = fg,
- bg = bg,
- border_color = border_color,
- border_width = border_width,
- type = "notification" })
-
- if hover_timeout then notification.box:connect_signal("mouse::enter", hover_destroy) end
-
- -- calculate the width
- if not width then
- local w, _ = textbox:get_preferred_size(s)
- width = w + (iconbox and icon_w + 2 * margin or 0) + 2 * margin
- end
-
- if width < actions_max_width then
- width = actions_max_width
- end
-
- -- calculate the height
- if not height then
- local w = width - (iconbox and icon_w + 2 * margin or 0) - 2 * margin
- local h = textbox:get_height_for_width(w, s)
- if iconbox and icon_h + 2 * margin > h + 2 * margin then
- height = icon_h + 2 * margin
- else
- height = h + 2 * margin
- end
- end
-
- height = height + actions_total_height
-
- -- crop to workarea size if too big
- local workarea = s.workarea
- if width > workarea.width - 2 * (border_width or 0) - 2 * (naughty.config.padding or 0) then
- width = workarea.width - 2 * (border_width or 0) - 2 * (naughty.config.padding or 0)
- end
- if height > workarea.height - 2 * (border_width or 0) - 2 * (naughty.config.padding or 0) then
- height = workarea.height - 2 * (border_width or 0) - 2 * (naughty.config.padding or 0)
- end
-
- -- set size in notification object
- notification.height = height + 2 * (border_width or 0)
- notification.width = width + 2 * (border_width or 0)
-
- -- position the wibox
- local offset = get_offset(s, notification.position, nil, notification.width, notification.height)
- notification.box.ontop = ontop
- notification.box:geometry({ width = width,
- height = height,
- x = offset.x,
- y = offset.y })
- notification.box.opacity = opacity
- notification.box.visible = true
- notification.idx = offset.idx
-
- -- populate widgets
- local layout = wibox.layout.fixed.horizontal()
- if iconmargin then
- layout:add(iconmargin)
- end
- layout:add(marginbox)
-
- local completelayout = wibox.layout.fixed.vertical()
- completelayout:add(layout)
- completelayout:add(actionslayout)
- notification.box:set_widget(completelayout)
-
- -- Setup the mouse events
- layout:buttons(util.table.join(button({ }, 1, run),
- button({ }, 3, function()
- die(naughty.notificationClosedReason.dismissedByUser)
- end)))
-
- -- insert the notification to the table
- table.insert(naughty.notifications[s][notification.position], notification)
-
- if suspended then
- notification.box.visible = false
- table.insert(naughty.notifications.suspended, notification)
- end
-
- -- return the notification
- return notification
-end
-
-return naughty
-
--- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/awesome/lib/naughty/dbus.lua b/awesome/lib/naughty/dbus.lua
deleted file mode 100644
index c49dc7e..0000000
--- a/awesome/lib/naughty/dbus.lua
+++ /dev/null
@@ -1,261 +0,0 @@
----------------------------------------------------------------------------
--- DBUS/Notification support
--- Notify
---
--- @author koniu &lt;gkusnierz@gmail.com&gt;
--- @copyright 2008 koniu
--- @module naughty.dbus
----------------------------------------------------------------------------
-
-assert(dbus)
-
--- Package environment
-local pairs = pairs
-local type = type
-local string = string
-local capi = { awesome = awesome,
- dbus = dbus }
-local util = require("awful.util")
-local cairo = require("lgi").cairo
-
-local schar = string.char
-local sbyte = string.byte
-local tcat = table.concat
-local tins = table.insert
-local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
-local naughty = require("naughty.core")
-
---- Notification library, dbus bindings
-local dbus = { config = {} }
-
--- DBUS Notification constants
-local urgency = {
- low = "\0",
- normal = "\1",
- critical = "\2"
-}
-
---- DBUS notification to preset mapping.
--- The first element is an object containing the filter.
--- If the rules in the filter match, the associated preset will be applied.
--- The rules object can contain the following keys: urgency, category, appname.
--- The second element is the preset.
--- @tfield table 1 low urgency
--- @tfield table 2 normal urgency
--- @tfield table 3 critical urgency
--- @table config.mapping
-dbus.config.mapping = {
- {{urgency = urgency.low}, naughty.config.presets.low},
- {{urgency = urgency.normal}, naughty.config.presets.normal},
- {{urgency = urgency.critical}, naughty.config.presets.critical}
-}
-
-local function sendActionInvoked(notificationId, action)
- if capi.dbus then
- capi.dbus.emit_signal("session", "/org/freedesktop/Notifications",
- "org.freedesktop.Notifications", "ActionInvoked",
- "u", notificationId,
- "s", action)
- end
-end
-
-local function sendNotificationClosed(notificationId, reason)
- if capi.dbus then
- capi.dbus.emit_signal("session", "/org/freedesktop/Notifications",
- "org.freedesktop.Notifications", "NotificationClosed",
- "u", notificationId,
- "u", reason)
- end
-end
-
-local function convert_icon(w, h, rowstride, channels, data)
- -- Do the arguments look sane? (e.g. we have enough data)
- local expected_length = rowstride * (h - 1) + w * channels
- if w < 0 or h < 0 or rowstride < 0 or (channels ~= 3 and channels ~= 4) or
- string.len(data) < expected_length then
- w = 0
- h = 0
- end
-
- local format = cairo.Format[channels == 4 and 'ARGB32' or 'RGB24']
-
- -- Figure out some stride magic (cairo dictates rowstride)
- local stride = cairo.Format.stride_for_width(format, w)
- local append = schar(0):rep(stride - 4 * w)
- local offset = 0
-
- -- Now convert each row on its own
- local rows = {}
-
- for _ = 1, h do
- local this_row = {}
-
- for i = 1 + offset, w * channels + offset, channels do
- local R, G, B, A = sbyte(data, i, i + channels - 1)
- tins(this_row, schar(B, G, R, A or 255))
- end
-
- -- Handle rowstride, offset is stride for the input, append for output
- tins(this_row, append)
- tins(rows, tcat(this_row))
-
- offset = offset + rowstride
- end
-
- return cairo.ImageSurface.create_for_data(tcat(rows), format, w, h, stride)
-end
-
-capi.dbus.connect_signal("org.freedesktop.Notifications", function (data, appname, replaces_id, icon, title, text, actions, hints, expire)
- local args = { }
- if data.member == "Notify" then
- if text ~= "" then
- args.text = text
- if title ~= "" then
- args.title = title
- end
- else
- if title ~= "" then
- args.text = title
- else
- return
- end
- end
- if appname ~= "" then
- args.appname = appname
- end
- for _, obj in pairs(dbus.config.mapping) do
- local filter, preset = obj[1], obj[2]
- if (not filter.urgency or filter.urgency == hints.urgency) and
- (not filter.category or filter.category == hints.category) and
- (not filter.appname or filter.appname == appname) then
- args.preset = util.table.join(args.preset, preset)
- end
- end
- local preset = args.preset or naughty.config.defaults
- local notification
- if actions then
- args.actions = {}
-
- for i = 1,#actions,2 do
- local action_id = actions[i]
- local action_text = actions[i + 1]
-
- if action_id == "default" then
- args.run = function()
- sendActionInvoked(notification.id, "default")
- naughty.destroy(notification, naughty.notificationClosedReason.dismissedByUser)
- end
- elseif action_id ~= nil and action_text ~= nil then
- args.actions[action_text] = function()
- sendActionInvoked(notification.id, action_id)
- naughty.destroy(notification, naughty.notificationClosedReason.dismissedByUser)
- end
- end
- end
- end
- args.destroy = function(reason)
- sendNotificationClosed(notification.id, reason)
- end
- if not preset.callback or (type(preset.callback) == "function" and
- preset.callback(data, appname, replaces_id, icon, title, text, actions, hints, expire)) then
- if icon ~= "" then
- args.icon = icon
- elseif hints.icon_data or hints.image_data then
- if hints.icon_data == nil then hints.icon_data = hints.image_data end
-
- -- icon_data is an array:
- -- 1 -> width
- -- 2 -> height
- -- 3 -> rowstride
- -- 4 -> has alpha
- -- 5 -> bits per sample
- -- 6 -> channels
- -- 7 -> data
- local w, h, rowstride, _, _, channels, icon_data = unpack(hints.icon_data)
- args.icon = convert_icon(w, h, rowstride, channels, icon_data)
- end
- if replaces_id and replaces_id ~= "" and replaces_id ~= 0 then
- args.replaces_id = replaces_id
- end
- if expire and expire > -1 then
- args.timeout = expire / 1000
- end
- notification = naughty.notify(args)
- return "u", notification.id
- end
- return "u", "0"
- elseif data.member == "CloseNotification" then
- local obj = naughty.getById(appname)
- if obj then
- naughty.destroy(obj, naughty.notificationClosedReason.dismissedByCommand)
- end
- elseif data.member == "GetServerInfo" or data.member == "GetServerInformation" then
- -- name of notification app, name of vender, version, specification version
- return "s", "naughty", "s", "awesome", "s", capi.awesome.version, "s", "1.0"
- elseif data.member == "GetCapabilities" then
- -- We actually do display the body of the message, we support <b>, <i>
- -- and <u> in the body and we handle static (non-animated) icons.
- return "as", { "s", "body", "s", "body-markup", "s", "icon-static", "s", "actions" }
- end
-end)
-
-capi.dbus.connect_signal("org.freedesktop.DBus.Introspectable", function (data)
- if data.member == "Introspect" then
- local xml = [=[<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object
- Introspection 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
- <node>
- <interface name="org.freedesktop.DBus.Introspectable">
- <method name="Introspect">
- <arg name="data" direction="out" type="s"/>
- </method>
- </interface>
- <interface name="org.freedesktop.Notifications">
- <method name="GetCapabilities">
- <arg name="caps" type="as" direction="out"/>
- </method>
- <method name="CloseNotification">
- <arg name="id" type="u" direction="in"/>
- </method>
- <method name="Notify">
- <arg name="app_name" type="s" direction="in"/>
- <arg name="id" type="u" direction="in"/>
- <arg name="icon" type="s" direction="in"/>
- <arg name="summary" type="s" direction="in"/>
- <arg name="body" type="s" direction="in"/>
- <arg name="actions" type="as" direction="in"/>
- <arg name="hints" type="a{sv}" direction="in"/>
- <arg name="timeout" type="i" direction="in"/>
- <arg name="return_id" type="u" direction="out"/>
- </method>
- <method name="GetServerInformation">
- <arg name="return_name" type="s" direction="out"/>
- <arg name="return_vendor" type="s" direction="out"/>
- <arg name="return_version" type="s" direction="out"/>
- <arg name="return_spec_version" type="s" direction="out"/>
- </method>
- <method name="GetServerInfo">
- <arg name="return_name" type="s" direction="out"/>
- <arg name="return_vendor" type="s" direction="out"/>
- <arg name="return_version" type="s" direction="out"/>
- </method>
- <signal name="NotificationClosed">
- <arg name="id" type="u" direction="out"/>
- <arg name="reason" type="u" direction="out"/>
- </signal>
- <signal name="ActionInvoked">
- <arg name="id" type="u" direction="out"/>
- <arg name="action_key" type="s" direction="out"/>
- </signal>
- </interface>
- </node>]=]
- return "s", xml
- end
-end)
-
--- listen for dbus notification requests
-capi.dbus.request_name("session", "org.freedesktop.Notifications")
-
-return dbus
-
--- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/awesome/lib/naughty/init.lua b/awesome/lib/naughty/init.lua
deleted file mode 100644
index 71dee9f..0000000
--- a/awesome/lib/naughty/init.lua
+++ /dev/null
@@ -1,14 +0,0 @@
----------------------------------------------------------------------------
--- @author Uli Schlachter &lt;psychon@znc.in&gt;
--- @copyright 2014 Uli Schlachter
--- @module naughty
----------------------------------------------------------------------------
-
-local naughty = require("naughty.core")
-if dbus then
- naughty.dbus = require("naughty.dbus")
-end
-
-return naughty
-
--- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80