1 ----------------------------------------------------------------------------
2 -- @author koniu <gkusnierz@gmail.com>
3 -- @copyright 2008 koniu
4 -- @release @AWESOME_VERSION@
5 ----------------------------------------------------------------------------
10 -- naughty.notify({ text = "notification",
12 -- position = "top_left"|"top_right"|"bottom_left"|"bottom_right",
14 -- icon="/path/to/image",
19 -- Package environment
24 local hooks
= require("awful.hooks")
28 local capi
= { screen
= screen
}
29 local bt
= require("awful.beautiful")
30 local beautiful
= bt
.get()
32 --- Notification library
35 --- Naughty configuration - a table containing common/default popup settings.
36 -- You can override some of these for individual popups using args to notify().
38 -- @field timeout Number of seconds after which popups disappear.
39 -- Set to 0 for no timeout. Default: 5
40 -- @field screen Screen on which the popups will appear number. Default: 1
41 -- @field position Corner of the workarea the popups will appear.
42 -- Valid values: 'top_right', 'top_left', 'bottom_right', 'bottom_left'.
43 -- Default: 'top_right'
44 -- @field margin Space between popups and edge of the workarea. Default: 4
45 -- @field height Height of a single-line popup. Default: 16
46 -- @field width Width of a popup. Default: 300
47 -- @field gap Spacing between popups. Default: 1
48 -- @field ontop Boolean forcing popups to display on top. Default: true
49 -- @field font Popup font. Default: beautiful.font or "Verdana 8"
50 -- @field icon Popup icon. Default: nil
51 -- @field fg Foreground color. Default: beautiful.fg_focus or '#ffffff'
52 -- @field bg Background color. Default: beautiful.bg_focus or '#535d6c'
53 -- @field border_color Border color.
54 -- Default: beautiful.border_focus or '#535d6c'
55 -- @field border_width Border width. Default: 1
61 config
.position
= "top_right"
67 config
.font
= beautiful
.font
or "Verdana 8"
69 config
.fg
= beautiful
.fg_focus
or '#ffffff'
70 config
.bg
= beautiful
.bg_focus
or '#535d6c'
71 config
.border_color
= beautiful
.border_focus
or '#535d6c'
72 config
.border_width
= 1
74 --- Index of notifications. See config table for valid 'position' values.
75 -- Each element is a table consisting of:
76 -- @field box Wibox object containing the popup
77 -- @field lines Number of lines in title..text
78 -- @field timer Function to be executed on timeout
79 -- @name notifications[position]
89 local ws
= capi
.screen
[config
.screen
].workarea
90 local ss
= capi
.screen
[config
.screen
].geometry
92 --- Evaluate desired position of the notification by index - internal
93 -- @param idx Index of the notification
94 -- @param position top_right | top_left | bottom_right | bottom_left
95 -- @param lines Number of text lines in the notification
96 -- @return Absolute position in {x, y} dictionary
98 local function get_offset(idx
, position
, lines
)
102 if position
:match("left") then
103 v
.x
= ws
.x
+ config
.margin
105 v
.x
= ws
.x
+ ws
.width
- (config
.width
+ config
.border_width
*2 + config
.margin
)
108 -- calculate existing popups' height
110 for i
= 1, idx
-1, 1 do
111 existing
= existing
+ config
.height
*notifications
[position
][i
].lines
+ config
.gap
+ config
.border_width
*2
115 if position
:match("top") then
116 v
.y
= ws
.y
+ config
.margin
+ existing
118 v
.y
= ws
.y
+ ws
.height
- (config
.margin
+ config
.border_width
+ config
.height
*lines
+ existing
)
124 --- Re-arrange notifications according to their position and index - internal
126 local function arrange()
127 for p
,pos
in pairs(notifications
) do
128 for i
,notification
in pairs(notifications
[p
]) do
129 local offset
= get_offset(i
, p
, notification
.lines
)
130 notification
.box
:geometry({ x
= offset
.x
, y
= offset
.y
, width
= config
.width
, height
= notification
.lines
* config
.height
})
136 --- Destroy notification by index
137 -- @param idx Index of the notification
138 -- @param position One of 4 keys in notification dictionary: top_right, top_left, bottom_right, bottom_left
139 -- @return True if the popup was successfully destroyed, nil otherwise
140 function destroy(notification
)
142 notification
.box
.screen
= nil
143 hooks
.timer
.unregister(notification
.timer
)
144 table.remove(notifications
[notification
.position
], notification
.idx
)
150 --- Create notification. args is a dictionary of optional arguments. For more information and defaults see respective fields in config table.
151 -- @param text Text of the notification
152 -- @param timeout Time in seconds after which popup expires
153 -- @param title Title of the notification
154 -- @param position Corner of the workarea the popups will appear
155 -- @param icon Path to icon
156 -- @param fg Foreground color
157 -- @param bg Background color
158 -- @param screen Target screen for the notification
159 -- @param ontop Target screen for the notification
160 -- @usage naughty.notify({ title = 'Achtung!', text = 'You\'re idling', timeout = 0 })
161 function notify(args
)
162 -- gather settings together
163 local timeout
= args
.timeout
or config
.timeout
164 local position
= args
.position
or config
.position
165 local icon
= args
.icon
or config
.icon
166 local text
= args
.text
or ""
167 local screen
= args
.screen
or config
.screen
168 local ontop
= args
.ontop
or config
.ontop
172 title
= " " .. args
.title
.. "\n"
176 for i
in string.gmatch(title
..text
, "\n") do
180 -- create the container wibox
181 local idx
= #notifications
[position
] + 1
182 local box
= wibox({ name
= "not" .. idx
,
183 position
= "floating",
184 fg
= args
.fg
or config
.fg
,
185 bg
= args
.bg
or config
.bg
,
186 border_color
= config
.border_color
,
187 border_width
= config
.border_width
})
189 -- position the wibox
190 local offset
= get_offset(idx
, position
, lines
)
191 box
:geometry({ width
= config
.width
,
192 height
= config
.height
* lines
,
199 local notification
= {
206 -- populate the wibox with widgets
207 local textbox
= widget({ type = "textbox", name
= "text", align
= "flex" })
208 textbox
:buttons({ button({ }, 1, function () destroy(notification
) end) })
209 textbox
.text
= string.format('<span font_desc="%s"><b>%s</b> %s</span>',
210 config
.font
, title
, text
)
214 iconbox
= widget({ type = "imagebox", name
= "icon", align
= "left" })
215 iconbox
:buttons({ button({ }, 1, function () destroy(notification
) end) })
216 iconbox
.image
= image(icon
)
220 box
.widgets
= { iconbox
, textbox
}
222 local timer
= function () destroy(notification
) end
223 hooks
.timer
.register(timeout
, timer
)
224 notification
.timer
= timer
226 -- insert the notification to the table
227 table.insert(notifications
[position
],notification
)
230 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80