From 59cb48c6c051c3c49ff69bb16bd90bd50b402131 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 15 Nov 2021 09:10:55 +0100 Subject: rc: add a systray widget showing desktops with urgent windows --- rc.lua | 6 ++- urgent_wgt.lua | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 urgent_wgt.lua diff --git a/rc.lua b/rc.lua index e1d23c2..d479ca5 100644 --- a/rc.lua +++ b/rc.lua @@ -12,6 +12,7 @@ local naughty = require("naughty") local bindings = require("bindings") local commondefs = require("commondefs") local pager = require("pager") +local urgent_wgt = require("urgent_wgt") local utils = require("utils") local workspace = require("workspace") @@ -97,8 +98,11 @@ awful.screen.connect_for_each_screen(function(s) awful.button({ }, 5, function () awful.layout.inc(layouts, -1) end))) local layoutbox_container = wibox.container.constraint(layoutbox, 'max', beautiful.xresources.apply_dpi(tray_icon_size)) - local layout_utils = wibox.layout.flex.horizontal() + local u_wgt = urgent_wgt.UrgentWidget:new() + + local layout_utils = wibox.layout.fixed.horizontal() layout_utils:add(layoutbox_container) + layout_utils:add(u_wgt.widget) -- Create a tasklist widget local pgr = pager.Pager:new(wsp, s) diff --git a/urgent_wgt.lua b/urgent_wgt.lua new file mode 100644 index 0000000..1b2f60c --- /dev/null +++ b/urgent_wgt.lua @@ -0,0 +1,147 @@ +local awful = require("awful") +local beautiful = require("beautiful") +local shape = require("gears.shape") +local wibox = require("wibox") + +local M = {} + +local function client_get_desk_idx(c) + if c.first_tag then + local desk_idx = tonumber('0x' .. c.first_tag.name:sub(1, 2)) + if desk_idx ~= nil and desk_idx >= 0 then + return desk_idx + else + print('cannot get desk idx: ' .. c.first_tag.name) + end + end + return false +end + +local function urgent_widget_create(name) + local textbox = wibox.widget.textbox(' ' .. name .. ' ') + local cont_bg = wibox.container.background(textbox) + cont_bg.bg = beautiful.bg_urgent + cont_bg.fg = beautiful.fg_urgent + + cont_bg:set_shape(shape.rounded_rect, 5) + cont_bg.shape_border_width = 1 + cont_bg.shape_border_color = beautiful.border_focus + + return cont_bg +end + +local UrgentWidget = {} + +function UrgentWidget:_desk_client_add(desk_idx, c) + -- create the client list, if it does not exist already + if self._desktops[desk_idx] == nil then + self._desktops[desk_idx] = {} + end + + self._desktops[desk_idx][c] = true + + if self._desktop_widgets[desk_idx] == nil then + self._desktop_widgets[desk_idx] = urgent_widget_create(desk_idx) + end + + for k, w in pairs(self._layout:get_children()) do + if w == self._desktop_widgets[desk_idx] then + return + end + end + self._layout:add(self._desktop_widgets[desk_idx]) +end + +function UrgentWidget:_desk_client_remove(desk_idx, c) + self._desktops[desk_idx][c] = nil + + -- remove the widget if there are no clients left + local count = 0 + for c, v in pairs(self._desktops[desk_idx]) do + if v then + count = count + 1 + end + end + if count == 0 then + self._layout:remove_widgets(self._desktop_widgets[desk_idx]) + end +end + +function UrgentWidget:_client_remove(c) + if self._clients[c] then + self:_desk_client_remove(self._clients[c], c) + end + self._clients[c] = nil +end + +function UrgentWidget:_client_add(c) + local desk_idx = client_get_desk_idx(c) + self._clients[c] = desk_idx + + if desk_idx then + self:_desk_client_add(desk_idx, c) + end + + -- handle client state changes: + -- lose the urgency flag + c:connect_signal('property::urgent', + function (c) + if not c.urgent then + self:_client_remove(c) + end + end) + -- client destroyed + c:connect_signal('unmanage', + function (c) + self:_client_remove(c) + end) + -- client moved + c:connect_signal('untagged', + function(c, t) + local desk_idx = self._clients[c] + if desk_idx then + self:_desk_client_remove(desk_idx, c) + end + self._clients[c] = false + end) + c:connect_signal('tagged', + function(c, t) + local desk_idx = client_get_desk_idx(c) + self._clients[c] = desk_idx + + if desk_idx then + self:_desk_client_add(desk_idx, c) + end + end) +end + +function UrgentWidget:new() + local ret = setmetatable({}, self) + self.__index = self + + ret._layout = wibox.layout.fixed.horizontal() + ret.widget = awful.widget.only_on_screen(ret._layout, "primary") + + -- maps from clients to their desk num (or false, when no desk num + -- can be determined) + ret._clients = {} + -- contains a table of urgent clients per each desktop number + ret._desktops = {} + ret._desktop_widgets = {} + + -- signal handler for adding new clients + client.connect_signal('property::urgent', + function (c) + -- only do something when urgency flag is on + if c.urgent then + ret:_client_add(c) + end + end) + + return ret +end + +M.UrgentWidget = UrgentWidget + +return M + -- cgit v1.2.3