local awful = require "awful" local beautiful = require "beautiful" local gshape = require "gears.shape" local naughty = require "naughty" local qanim = require "quarrel.animation" local qui = require "quarrel.ui" local qvars = require "quarrel.vars" local wibox = require "wibox" local rtimed = require("lib.rubato").timed local easing = require("lib.rubato").easing local gtimer = require "gears.timer" local qcolor = require "quarrel.color" local qmarkup = require "quarrel.markup" local M = require "ui.wicked.consts" function M.new(n) local intertext_margin = (n.title ~= "" or n.message ~= "") and qui.PADDING or 0 local title_height = n.title ~= "" and qui.CHAR_HEIGHT or 0 local message_height = n.message ~= "" and qui.CHAR_HEIGHT or 0 local app_name if n.app_name == "" then app_name = n._private._foreign and "Unknown" or "Awesome" else app_name = n.app_name end local notif = naughty.layout.box { notification = n, placement = function(d) return awful.placement.right(d, { margins = beautiful.useless_gap * 2, }) end, bg = qcolor.palette.transparent, border_width = 0, shape = gshape.rectangle, widget_template = { widget = wibox.container.constraint, height = qui.BIG_PADDING * 2 + qui.CHAR_HEIGHT + qui.BORDER_WIDTH + qui.BIG_PADDING * 2 -- + title_height -- + message_height -- + intertext_margin, + (n.icon and qui.CHAR_HEIGHT * 2 + qui.PADDING or (title_height + message_height + intertext_margin)), strategy = "exact", { qui.styled { widget = wibox.container.background, point = function(geo, args) return { x = args.parent.width, y = args.parent.height - geo.height, } end, { { widget = wibox.container.margin, margins = qui.BIG_PADDING, { { widget = wibox.widget.textbox, markup = qmarkup(app_name, { bold = true }), }, nil, { widget = wibox.container.radialprogressbar, max_value = M.NOTIF_TIMEOUT, border_color = qcolor.palette.bg.lowest, color = qcolor.palette.yellow(), border_width = qui.BORDER_WIDTH, forced_height = qui.CHAR_HEIGHT, forced_width = qui.CHAR_HEIGHT, id = "progress", }, layout = wibox.layout.align.horizontal, }, }, { widget = wibox.container.constraint, height = qui.BORDER_WIDTH, width = beautiful.notification_max_width, strategy = "exact", { widget = wibox.container.background, bg = qcolor.palette.border(), }, }, { widget = wibox.container.margin, margins = qui.BIG_PADDING, { widget = wibox.container.constraint, height = n.icon and qui.CHAR_HEIGHT * 2 + qui.PADDING or (title_height + message_height + intertext_margin), strategy = "exact", { { widget = wibox.container.background, { widget = naughty.widget.icon, shape = qui.shape, notification = n, }, }, { { widget = wibox.container.constraint, height = title_height, strategy = "exact", { widget = wibox.widget.textbox, text = n.title or "", }, }, { widget = wibox.container.constraint, height = message_height, strategy = "exact", { widget = wibox.widget.textbox, text = n.message or "", }, }, spacing = intertext_margin, layout = wibox.layout.fixed.vertical, }, fill_space = true, spacing = n.icon and qui.BIG_PADDING or nil, layout = wibox.layout.fixed.horizontal, }, }, }, layout = wibox.layout.fixed.vertical, }, id = "bg", }, layout = wibox.layout.manual, id = "manual", }, }, } local hiding = false local old_destroy = notif._private.destroy_callback local progress = rtimed { duration = n.timeout, pos = 0, easing = easing.none, clamp_position = true, subscribed = function(pos) notif.widget:get_children_by_id("progress")[1].value = pos end, } local position = qanim:new { duration = qvars.anim_duration, pos = 0, easing = qvars.easing, subscribed = function(pos) gtimer.delayed_call(function() notif.widget.widget:move(1, function(geo, args) if pos == 0 and hiding then old_destroy() end return { x = args.parent.width - pos, y = args.parent.height - geo.height, } end) end) end, } local opacity = rtimed { duration = qvars.anim_duration, intro = qvars.anim_intro, easing = easing.quadratic, pos = 0, clamp_position = true, subscribed = function(pos) notif.opacity = pos end, } n:disconnect_signal("destroyed", notif._private.destroy_callback) function notif._private.destroy_callback() opacity.target = 0 position:set(0) hiding = true end n:weak_connect_signal("destroyed", notif._private.destroy_callback) --- for some reason when urgency is critical, it somehow makes it not disappear --- why? dunno, FIXME opacity.target = 1 position:set(beautiful.notification_max_width) progress.target = M.NOTIF_TIMEOUT end return setmetatable(M, { __call = function(_, ...) return M.new(...) end, })