diff --git a/lib/naughty.lua.in b/lib/naughty.lua.in index fb7b7d36c..269eb627a 100644 --- a/lib/naughty.lua.in +++ b/lib/naughty.lua.in @@ -30,7 +30,7 @@ module("naughty") -- Valid values: 'top_right', 'top_left', 'bottom_right', 'bottom_left'. -- Default: 'top_right' -- @field margin Space between popups and edge of the workarea. Default: 4 --- @field height Height of a single-line popup. Default: 16 +-- @field height Height of a single line of text. Default: 16 -- @field width Width of a popup. Default: 300 -- @field gap Spacing between popups. Default: 1 -- @field ontop Boolean forcing popups to display on top. Default: true @@ -67,8 +67,8 @@ config.hover_timeout = nil --- Index of notifications. See config table for valid 'position' values. -- Each element is a table consisting of: -- @field box Wibox object containing the popup --- @field lines Number of lines in title..text --- @field timer Function to be executed on timeout +-- @field height Popup height +-- @field die Function to be executed on timeout -- @name notifications[position] -- @class table @@ -79,14 +79,13 @@ notifications = { bottom_right = {}, } - --- Evaluate desired position of the notification by index - internal -- @param idx Index of the notification -- @param position top_right | top_left | bottom_right | bottom_left --- @param lines Number of text lines in the notification +-- @param height Popup height -- @return Absolute position in {x, y} dictionary -local function get_offset(idx, position, lines) +local function get_offset(idx, position, height) local ws = capi.screen[config.screen].workarea local v = {} @@ -100,21 +99,21 @@ local function get_offset(idx, position, lines) -- calculate existing popups' height local existing = 0 for i = 1, idx-1, 1 do - existing = existing + config.height*notifications[position][i].lines + config.gap + config.border_width*2 + existing = existing + notifications[position][i].height + config.gap + config.border_width*2 end -- calculate y if position:match("top") then v.y = ws.y + config.margin + existing else - v.y = ws.y + ws.height - (config.margin + config.border_width + config.height*lines + existing) + v.y = ws.y + ws.height - (config.margin + config.border_width + height + existing) end -- if positioned outside workarea, destroy oldest popup and recalculate - if v.y + config.height*lines > ws.y + ws.height or v.y < ws.y then + if v.y + height > ws.y + ws.height or v.y < ws.y then idx = idx - 1 destroy(notifications[position][1]) - v = get_offset(idx, position, lines) + v = get_offset(idx, position, height) end return v @@ -125,8 +124,8 @@ end local function arrange() for p,pos in pairs(notifications) do for i,notification in pairs(notifications[p]) do - local offset = get_offset(i, p, notification.lines) - notification.box:geometry({ x = offset.x, y = offset.y, width = config.width, height = notification.lines * config.height }) + local offset = get_offset(i, p, notification.height) + notification.box:geometry({ x = offset.x, y = offset.y, width = config.width, height = notification.height }) notification.idx = i end end @@ -160,51 +159,22 @@ end -- @param run Function to run on left click -- @usage naughty.notify({ title = 'Achtung!', text = 'You\'re idling', timeout = 0 }) function notify(args) - -- gather settings together + -- gather variables together local timeout = args.timeout or config.timeout - local position = args.position or config.position local icon = args.icon or config.icon local icon_size = args.icon_size or config.icon_size local text = args.text or "" local screen = args.screen or config.screen local ontop = args.ontop or config.ontop + local notification = {} + notification.position = args.position or config.position + notification.idx = #notifications[notification.position] + 1 + local title = "" - if args.title then - title = " " .. args.title .. "\n" - end - - local lines = 1 - for i in string.gmatch(title..text, "\n") do - lines = lines + 1 - end - - -- create the container wibox - local idx = #notifications[position] + 1 - local box = wibox({ name = "not" .. idx, - position = "floating", - fg = args.fg or config.fg, - bg = args.bg or config.bg, - border_color = config.border_color, - border_width = config.border_width }) - - -- position the wibox - local offset = get_offset(idx, position, lines) - box:geometry({ width = config.width, - height = config.height * lines, - x = offset.x, - y = offset.y }) - - box.ontop = ontop - box.screen = screen - - local notification = { - box = box, - lines = lines, - position = position, - idx = idx - } + if args.title then title = " " .. args.title .. "\n" end + -- hook destroy local die = function () destroy(notification) end hooks.timer.register(timeout, die) notification.die = die @@ -216,7 +186,7 @@ function notify(args) else hooks.timer.register(config.hover_timeout, die) end end - -- populate the wibox with widgets + -- create textbox local textbox = widget({ type = "textbox", name = "text", align = "flex" }) textbox:buttons({ button({ }, 1, run), button({ }, 3, die) }) @@ -224,6 +194,7 @@ function notify(args) config.font, title, text) if config.hover_timeout then textbox.mouse_enter = hover_destroy end + -- create iconbox local iconbox = nil if icon then iconbox = widget({ type = "imagebox", name = "icon", align = "left" }) @@ -238,10 +209,33 @@ function notify(args) if config.hover_timeout then iconbox.mouse_enter = hover_destroy end end - box.widgets = { iconbox, textbox } + -- create container wibox + notification.box = wibox({ name = "not" .. notification.idx, + position = "floating", + fg = args.fg or config.fg, + bg = args.bg or config.bg, + border_color = config.border_color, + border_width = config.border_width }) + + -- position the wibox + local lines = 1; for i in string.gmatch(title..text, "\n") do lines = lines + 1 end + if iconbox and iconbox.image.height > lines * config.height then + notification.height = iconbox.image.height + else + notification.height = lines * config.height end + local offset = get_offset(notification.idx, notification.position, notification.height) + notification.box:geometry({ width = config.width, + height = notification.height, + x = offset.x, + y = offset.y }) + notification.box.ontop = ontop + notification.box.screen = screen + + -- populate widgets + notification.box.widgets = { iconbox, textbox } -- insert the notification to the table - table.insert(notifications[position],notification) + table.insert(notifications[notification.position],notification) end -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80