summaryrefslogtreecommitdiff
path: root/urgent_wgt.lua
blob: a50bd4771f935c02f20704bb5c0b1f8835816984 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
local awful     = require("awful")
local beautiful = require("beautiful")
local shape     = require("gears.shape")
local wibox     = require("wibox")
local utils     = require("utils")

local M = {}

local function client_get_desk_idx(c)
    if c.first_tag then
        local desk_idx = utils.tag_desk_idx(c.first_tag)
        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