summaryrefslogtreecommitdiffstats
path: root/.config/awesome/infoline.lua
blob: 2b8e00c97f59cde62e1523273bc3bc278e5b78e5 (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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
-- -*- coding: utf-8 -*-
--------------------------------------------------------------------------------
-- @author Nicolas Berthier <nberthier@gmail.com>
-- @copyright 2010 Nicolas Berthier
--------------------------------------------------------------------------------
--
-- This is a module for defining infolines in awesome. An infoline is a wibox
-- attached to a region (typically, a client or the root window).
--
-- Remarks:
--
-- - It has not been tested with multiple screens yet.
--
-- Example usage: (TODO --- read the comments for now, there are not many
-- functions)
--
--------------------------------------------------------------------------------

--{{{ Grab environment (mostly aliases)
local setmetatable = setmetatable
local ipairs = ipairs
local type = type
local pairs = pairs
local string = string
local print = print
local error = error
local io = io

local client = client
local awesome = awesome
local wibox = wibox
local widget = widget
local root  = root
local screen  = screen
local mouse  = mouse
--}}}

module ("infoline")

-- Privata data: we use weak keys in order to allow collection of private data
-- if keys (clients) are collected (i.e., no longer used, after having been
-- killed for instance).
-- 
-- XXX: For now, we have at most one infoline per client, but it could be
-- interesting to create several types of infolines (identified by indexes to be
-- allocated by this module), and associated to, e.g., different configuration
-- flags and positioning routine...
local data = setmetatable ({}, { __mode = 'k' })

--{{{ Infoline positioning

-- XXX: this is a hack that positions an infoline at the bottom of a given area.
local function setup_position (wb, geom)
    local b = wb:geometry ()
    b.x = geom.x
    b.width = geom.width
    b.y = geom.y + geom.height - awesome.font_height
    b.height = awesome.font_height
    wb:geometry (b)
end

--}}}

--{{{ Configurations:

-- When true, this flag indicates that an infoline is hidden if its attached
-- client loses its focus. Otherwise, it remains always visible.
follow_focus = true

--}}}

--{{{ Infoline updates

function get_text (il) return il.wb.widgets[1].text end
function set_text (il, text) il.wb.widgets[1].text = text end

-- Forces a refresh of the given infoline.
function update (il)
    local wb = il.wb
    local c = il.cli

    if il.enabled then
        -- XXX: Note this could be much better if we had some sort of root and
        -- client interface unification: the following involves a priori useless
        -- code duplication...
        if c == root then
            wb.screen = mouse.screen -- XXX: is this the behavior we need?
            wb.visible = true
            setup_position (wb, screen[mouse.screen].workarea)
        else
            if c:isvisible () and (not follow_focus or client.focus == c) then
                wb.screen = c.screen
                wb.visible = true
                setup_position (wb, c:geometry ())
            else                    -- do we have to hide it?
                wb.visible = false
            end
        end
    elseif wb.visible then      --otherwise we need to hide it.
        wb.visible = false
    end
end

local function update_from_client (c)
    -- Note that we may not have an infoline for this client, hence the
    -- conditional...
    if data[c] then update (data[c]) end
end

-- Force execution of the above function on client state modification.
client.add_signal ("focus", update_from_client)
client.add_signal ("unfocus", update_from_client)
client.add_signal ("unmanage", update_from_client)

--}}}

--{{{ Infoline management

--- Creates a new infoline, with the given initial text. Note it is not visible
--- by default, and not attached to any client.
function new (text)
    local il = {
        wb = wibox ({
                        ontop = true, -- XXX: setting a depth when attaching to
                                      --a client would be much better
                        widgets = {
                            widget ({ type = "textbox", align="left" })
                        },
                    })
    }
    -- these will remain false until the infoline is attached to a client.
    il.wb.visible = false
    il.enabled = false
    set_text (il, text or "")
    return il
end

-- Attached infolines will react to the following client-related signals, and
-- automatically setup their position according to the client's geometry.
local csignals = { "property::geometry", "property::minimized",
    "property::visible", "property::focus", "property::screen", }

-- Attaches an infoline to a client. Note the infoline becomes visible at that
-- time, if the client is currently visible (and if it has focus, when
-- `follow_focus' holds).
function attach (il, c)
    data[c] = il
    il.cli = c
    il.enabled = true
    update (il)
    if c ~= root then
        -- subscribe to client-related signals
        for _, s in ipairs (csignals) do
            c:add_signal (s, update_from_client)
        end
    end
end

--- Detach the given infoline from its client, if any.
function dispose (il)
    local c = il.cli
    if c then -- note c can be nil here, if the given infoline has not been
              --attached to any client...
        il.enabled = false
        update (il)         -- a shortcut here would be: `il.wb.visible = false'
        data[c] = nil
        if c ~= root then
            -- unsubscribe from client-related signals
            for _, s in ipairs (csignals) do
                c:remove_signal (s, update_from_client)
            end
        end
    end
end

--}}}

-- Local variables:
-- indent-tabs-mode: nil
-- fill-column: 80
-- lua-indent-level: 4
-- End:
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80