have one cpu "icon" per CPU + one global.
[~madcoder/dotfiles.git] / config / awesome / rc.lua
1 -- awesome 3 configuration file
2
3 -- Include awesome library, with lots of useful function!
4 require("awful")
5 require("awful.autofocus")
6 require("awful.rules")
7 require("vicious")
8 require("beautiful")
9
10 terminal = "x-terminal-emulator"
11 lock     = 'xscreensaver-command -lock'
12 beautiful.init(awful.util.getdir("config").."/theme")
13
14 -- {{{ Modkeys
15 modkey = "Mod4"
16 shift = "Shift"
17 alt = "Mod1"
18 control = "Control"
19
20 k_n   = {}
21 k_m   = {modkey}
22 k_ms  = {modkey, shift}
23 k_ma  = {modkey, alt}
24 k_mc  = {modkey, control}
25 k_mcs = {modkey, control, shift}
26 k_a   = {alt}
27 k_ac  = {alt, control}
28 k_c   = {control}
29 k_cs  = {control, shift}
30 k_s   = {shift}
31
32 -- }}}
33 -- {{{ Markup helper functions
34 -- Inline markup is a tad ugly, so use these functions
35 -- to dynamically create markup.
36 function fg(color, text)
37     return '<span color="'..color..'">'..text..'</span>'
38 end
39
40 -- }}}
41
42 -- {{{ Tags
43
44 tags = {}
45 for s = 1, screen.count() do
46     -- Each screen has its own tag table.
47     local p = {}
48     for i = 1, 10 do
49         table.insert(p, "work-"..i)
50     end
51     tags[s] = awful.tag(p, s, awful.layout.suit.tile)
52 end
53
54 -- Get the screen number we're on
55 local mtag = { }
56 function mtag.getn(idx, s)
57     return tags[s or mouse.screen][idx]
58 end
59 function mtag.viewonly (idx, s)
60     local t = mtag.getn(idx, s)
61     if t then awful.tag.viewonly(t) end
62 end
63 function mtag.viewtoggle (idx, s)
64     local t = mtag.getn(idx, s)
65     if t then awful.tag.viewtoggle(t) end
66 end
67 function mtag.isoccupied(s, t)
68     local clients = (t and t:clients()) or {}
69     return #clients > 0
70 end
71 function mtag.occupied(s)
72     local p = {}
73
74     if not s then s = mouse.screen end
75     for t in pairs(tags[s]) do
76         t = tags[s][t]
77         if mtag.isoccupied(s, t) then table.insert(p, t) end
78     end
79     return p
80 end
81 function mtag.getnext(s)
82     if s == nil then s = mouse.screen end
83
84     local p = mtag.occupied(s)
85     local curtag = awful.tag.selected()
86
87     local t = 0
88
89     -- Get tag #
90     if mtag.isoccupied(s, curtag) then
91         for x in pairs(p) do
92             if curtag == p[x] then t = x end
93         end
94     end
95
96     local lasto = 1
97     local o = 0
98
99     for x in pairs(tags[s]) do
100         if curtag == tags[s][x] then o = x end
101         if mtag.isoccupied(s, tags[s][x]) then lasto = x end
102     end
103
104     -- Now: t is # in non-empty, o is # in all
105     if o == table.maxn(tags[s]) then
106         -- We're the last tag, create a new one
107         if t == 0 then
108             -- We're empty, go to first
109             return tags[s][1]
110         else
111             -- We're occupied, create new
112             return newtag()
113         end
114     else
115         if t == 0 then
116             -- We're empty, check if we're last
117             if o > lasto then
118                 -- We're also later than the last non-empty
119                 -- Wrap to first
120                 return tags[s][1]
121             else
122                 -- Nevermind, get the next
123                 return tags[s][o+1]
124             end
125         else
126             -- Return next tag
127             return tags[s][o+1]
128         end
129     end
130 end
131 function mtag.next(s)
132     awful.tag.viewonly(mtag.getnext(s))
133 end
134 function mtag.movetonext(s)
135     local t = mtag.getnext(s)
136     awful.client.movetotag(t)
137     awful.tag.viewonly(t)
138 end
139 function mtag.getprev(s)
140     if s == nil then s = mouse.screen end
141
142     local p = mtag.occupied(s)
143     local curtag = awful.tag.selected()
144
145     local t = 0
146
147     -- Get tag #
148     if mtag.isoccupied(s, curtag) then
149         for x in pairs(p) do
150             if curtag == p[x] then t = x end
151         end
152     end
153
154     local lasto = 1
155     local o = 0
156
157     for x in pairs(tags[s]) do
158         if curtag == tags[s][x] then o = x end
159         if mtag.isoccupied(s, tags[s][x]) then lasto = x end
160     end
161
162     -- Now: t is # in non-empty, o is # in all
163     if o == 1 then
164         -- We're the very first tag, wrap around
165         return p[ table.maxn(p) ]
166     else
167         -- We're not first, just go prev
168         return tags[s][o-1]
169     end
170 end
171 function mtag.prev(s)
172     awful.tag.viewonly(mtag.getprev(s))
173 end
174 function mtag.movetoprev(s)
175     local t = mtag.getprev(s)
176     awful.client.movetotag(t)
177     awful.tag.viewonly(t)
178 end
179
180
181 -- }}}
182 -- {{{ Widgets
183
184 local icondir = awful.util.getdir("config").."/icons/"
185
186 function make_icon(fname, left, right, h, bg)
187     local icon = image(icondir..fname)
188     local ib   = widget { type = 'imagebox' }
189     local w    = left + icon.width + right
190     local i    = image.argb32(w, h, nil)
191
192     i:draw_rectangle(0, 0, w, h, true, beautiful.bg_normal)
193     i:insert(icon, left, math.floor((h - icon.height) / 2))
194
195     ib.image = i
196     return ib
197 end
198
199 function draw_dashes_h(img, x, y, on, off, len, color)
200     for i = 0, len, on + off do
201         img:draw_line(x + i, y, x + i + on - 1, y, color)
202     end
203 end
204
205 function draw_dashes_v(img, x, y, on, off, len, color)
206     for i = 0, len, on + off do
207         img:draw_line(x, y + i, x, y + i + on - 1, color)
208     end
209 end
210
211
212 local mywidgets = {}
213
214 -- {{{ Taglist
215
216 maintaglist = {}
217 maintaglist.buttons = awful.util.table.join(
218     awful.button(k_n, 1, awful.tag.viewonly),
219     awful.button(k_s, 1, awful.client.toggletag)
220 )
221 maintaglist.label = awful.widget.taglist.label.noempty
222
223 -- }}}
224 -- {{{ Prompt box
225
226 mypromptbox = awful.widget.prompt{
227     layout = awful.widget.layout.horizontal.leftright
228 }
229
230 -- }}}
231 -- {{{ CPU Widgets
232
233 local cpuwidgets = {}
234 for i = 1, io.popen("grep -c ^cpu /proc/stat"):read("*n") do
235     local cpu = {}
236
237     cpu.widget = widget{ type = 'imagebox' }
238     cpu.update = function(cpu, value)
239         local color
240
241         if value < 25 then
242             color = beautiful.fg_focus
243         elseif value < 50 then
244             color = 'yellow'
245         elseif value < 75 then
246             color = 'orange'
247         else
248             color = 'red'
249         end
250
251         if cpu.color == color then return end
252         local img = image.argb32(11, 16, nil)
253         draw_dashes_h(img, 0,  4, 2, 1, 7, color)
254         draw_dashes_h(img, 0, 11, 2, 1, 7, color)
255         draw_dashes_v(img, 0,  4, 2, 1, 7, color)
256         draw_dashes_v(img, 7,  4, 2, 1, 7, color)
257         img:draw_rectangle(2, 6, 4, 4, true, color)
258         cpu.widget.image = img
259         cpu.percent = value
260     end
261     table.insert(mywidgets, cpu.widget)
262     cpuwidgets[i] = cpu
263 end
264
265 cputextwidget = widget{ type = 'textbox' }
266
267 vicious.register(cputextwidget, vicious.widgets.cpu,
268 function (widget, args)
269     local r = tonumber(args[1])
270     local percent = args[1]..'%'
271
272     for i = 1, #args do
273         cpuwidgets[i]:update(args[i])
274     end
275
276     if r < 10 then
277         percent = '0'..percent
278     end
279     if r < 25 then
280         percent = fg(beautiful.fg_focus, percent)
281     elseif r < 50 then
282         percent = fg('yellow', percent)
283     elseif r < 75 then
284         percent = fg('orange', percent)
285     else
286         percent = fg('red', percent)
287     end
288     return percent..' '
289 end, 2)
290
291 table.insert(mywidgets, cputextwidget)
292
293 -- }}}
294 -- {{{ Memory Usage Widget
295
296 table.insert(mywidgets, make_icon('mem.png', 16, 4, 16))
297
298 memtextwidget = widget{ type = 'textbox' }
299
300 vicious.register(memtextwidget, vicious.widgets.mem, function (widget, args)
301     -- Add extra preceding zeroes when needed
302     local r = tonumber(args[1])
303     local percent = args[1]..'%'
304     if r < 10 then
305         percent = '0'..percent
306     end
307     if r < 50 then
308         percent = fg(beautiful.fg_focus, percent)
309     elseif r < 80 then
310         percent = fg('orange', percent)
311     else
312         percent = fg('red', percent)
313     end
314     return percent..' '..args[2]..'M'
315 end, 2)
316
317 table.insert(mywidgets, memtextwidget)
318
319 -- }}}
320 -- {{{ Clock
321
322 table.insert(mywidgets, make_icon('clock.png', 16, 4, 16))
323
324 clockwidget = widget{ type = "textbox" }
325 vicious.register(clockwidget, vicious.widgets.date,
326                  fg(theme.fg_focus, "%H:%M") .. " %a %d %b  ", 10)
327
328 table.insert(mywidgets, clockwidget)
329
330 -- }}}
331 -- {{{ Statusbar
332
333 for s = 1, screen.count() do
334     local tab = {
335         {
336             awful.widget.taglist(s, maintaglist.label, maintaglist.buttons),
337             mypromptbox.widget,
338             layout = awful.widget.layout.horizontal.leftright
339         },
340     }
341
342     if (s == 1) then
343         table.insert(tab, widget{ type = 'systray' })
344     end
345     for i = #mywidgets, 1, -1 do
346         table.insert(tab, mywidgets[i])
347     end
348     tab["layout"] = awful.widget.layout.horizontal.rightleft
349     awful.wibox{ position = "top", height = 16, screen = s }.widgets = tab
350 end
351
352 -- }}}
353 -- }}}
354 -- {{{ Keys
355 ---- {{{ Global keys
356
357 globalkeys = awful.util.table.join(
358     -- Mod+{A/S}: Switch to prev/next tag
359     awful.key(k_m, "Left",  mtag.prev),
360     awful.key(k_m, "Right", mtag.next),
361
362     -- Mod+Shift+{A/S}: Move window to Prev/Next tag
363     awful.key(k_ms, "Left",  mtag.movetoprev),
364     awful.key(k_ms, "Right", mtag.movetonext),
365
366     -- Mod+Shift_{E/D}: move window to next/prev screen
367     awful.key(k_mc, "Right", function()
368        client.focus.screen = awful.util.cycle(screen.count(), mouse.screen + 1)
369     end),
370     awful.key(k_mc, "Left", function()
371        client.focus.screen = awful.util.cycle(screen.count(), mouse.screen - 1)
372     end),
373
374
375     -- Focus Prev/Next window
376     awful.key(k_m, "j",
377         function ()
378             awful.client.focus.byidx(1)
379             if client.focus then client.focus:raise() end
380         end),
381     awful.key(k_m, "k",
382         function ()
383             awful.client.focus.byidx(-1)
384             if client.focus then client.focus:raise() end
385         end),
386
387     -- Swap window with the Prev/Next one
388     awful.key(k_ms, "j", function () awful.client.swap.byidx(1) end),
389     awful.key(k_ms, "k", function () awful.client.swap.byidx(-1) end),
390
391     -- Mod+{E/D}: Switch to next/previous screen
392     awful.key(k_m, "Tab",  function () awful.screen.focus_relative(1) end),
393     awful.key(k_ms, "Tab", function () awful.screen.focus_relative(-1) end),
394
395     -- Mod+Enter: Launch a new terminal
396     awful.key(k_m,  "e",      function() awful.util.spawn("firefox") end),
397     awful.key(k_m,  "Return", function() awful.util.spawn(terminal) end),
398     awful.key(k_ac, "r", awesome.restart),
399     awful.key(k_m, "F12", function() awful.util.spawn(lock) end),
400     awful.key({}, "#148", function() awful.util.spawn("kcalc") end),
401
402     -- Layout manipulation
403     awful.key(k_m,  "l", function () awful.tag.incmwfact(0.05) end),
404     awful.key(k_m,  "h", function () awful.tag.incmwfact(-0.05) end),
405     awful.key(k_ms, "h", function () awful.tag.incnmaster(1) end),
406     awful.key(k_ms, "l", function () awful.tag.incnmaster(-1) end),
407     awful.key(k_mc, "h", function () awful.tag.incncol(1) end),
408     awful.key(k_mc, "l", function () awful.tag.incncol(-1) end),
409
410     -- Menu
411     awful.key(k_m, "r", function () mypromptbox:run() end),
412     awful.key(k_m, "F4",
413         function ()
414             awful.prompt.run({ prompt = "Run Lua code: " },
415                              mypromptbox.widget,
416                              awful.util.eval, nil,
417                              awful.util.getdir("cache").."/lua_commands")
418     end),
419
420     awful.key({}, "#192", function() mtag.viewonly(1) end),
421     awful.key({}, "#193", function() mtag.viewonly(2) end),
422     awful.key({}, "#194", function() mtag.viewonly(3) end),
423     awful.key({}, "#195", function() mtag.viewonly(4) end),
424     awful.key({}, "#196", function() mtag.viewonly(5) end)
425 )
426
427 -- Mod+#: Switch to tag
428 -- Mod+Shift+#: Toggle tag display
429 -- Mod+Control+#: Move client to tag
430 -- Mod+Alt+#: Toggle client on tag
431
432 for i = 1, 10 do
433     globalkeys = awful.util.table.join(
434         globalkeys,
435         awful.key(k_m,  i % 10, function() mtag.viewonly(i)   end),
436         awful.key(k_ms, i % 10, function() mtag.viewtoggle(i) end),
437         awful.key(k_mc, i % 10,
438                   function ()
439                       if client.focus and tags[client.focus.screen][i] then
440                           awful.client.movetotag(tags[client.focus.screen][i])
441                       end
442                   end),
443         awful.key(k_mcs, i % 10,
444                   function ()
445                       if client.focus and tags[client.focus.screen][i] then
446                           awful.client.toggletag(tags[client.focus.screen][i])
447                       end
448                   end)
449     )
450 end
451
452 ---- }}}
453 ---- {{{ Client hotkeys / buttons
454
455 local clientkeys = awful.util.table.join(
456     awful.key(k_m, "i", function (c)
457         if mypromptbox.widget.text then
458             mypromptbox.widget.text = ""
459         else
460             mypromptbox.widget.text = "Class: " .. c.class .. " Instance: ".. c.instance
461         end
462     end),
463
464     -- Client manipulation
465     awful.key(k_m, "c", function (c) c:kill() end),
466     awful.key(k_m, "o", awful.client.floating.toggle),
467     awful.key(k_m, "F11", function (c) c.fullscreen = not c.fullscreen end)
468 )
469
470 local clientbuttons = awful.util.table.join(
471     awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
472     awful.button(k_a, 1, awful.mouse.client.move),
473     awful.button(k_a, 3, awful.mouse.client.resize)
474 )
475
476 ---- }}}
477
478 root.keys(globalkeys)
479 -- }}}
480 -- {{{ Rules
481
482 awful.rules.rules = {
483     -- All clients will match this rule.
484     {
485         rule = { },
486         properties = {
487             border_width = beautiful.border_width,
488             border_color = beautiful.border_normal,
489             focus   = true,
490             keys    = clientkeys,
491             buttons = clientbuttons,
492             size_hints_honor = false,
493         }
494     },
495     { rule = { class = "MPlayer" },  properties = { floating = true } },
496     { rule = { class = "pinentry" }, properties = { floating = true } },
497     -- Set Firefox to always map on tags number 2 of screen 1.
498     -- { rule = { class = "Firefox" },
499     --   properties = { tag = tags[1][2] } },
500 }
501
502 -- }}}
503 -- {{{ Signals
504
505 function warp_mouse(c)
506     local o = awful.mouse.client_under_pointer()
507     if not o or o ~= c then
508         local g = c:geometry()
509         mouse.coords({ x = g.x + 5, y = g.y + 5 }, true)
510     end
511 end
512
513 client.add_signal("focus", function (c)
514     if not awful.client.ismarked(c) then
515         c.border_color = beautiful.border_focus
516     end
517     warp_mouse(c)
518 end)
519
520 client.add_signal("unfocus", function (c)
521     if not awful.client.ismarked(c) then
522         c.border_color = beautiful.border_normal
523     end
524 end)
525
526 client.add_signal("manage", function (c, startup)
527     c:add_signal("mouse::enter", function(c) client.focus = c end)
528 end)
529
530 for s = 1, screen.count() do
531     screen[s]:add_signal("arrange", function ()
532         if client.focus and client.focus.screen == s then
533             warp_mouse(client.focus)
534         end
535     end)
536 end
537
538 -- }}}
539
540 awful.util.spawn("xkbcomp -w 0 -R/usr/share/X11/xkb /home/madcoder/.Xkeyboard :0")
541 awful.util.spawn("xsetroot -cursor_name left_ptr")