madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Remove clocks printf debugging
[etc/awesome.git] / .config / awesome / rc.lua
1 -- {{{ Imports
2 -- Standard awesome library
3 local gears = require("gears")
4 local awful = require("awful")
5 require("awful.autofocus")
6 -- Widget and layout library
7 local wibox = require("wibox")
8 -- Theme handling library
9 local beautiful = require("beautiful")
10 -- Notification library
11 local naughty = require("naughty")
12 local menubar = require("menubar")
13 local hotkeys_popup = require("awful.hotkeys_popup").widget
14 local lain = require("lain")
15 local dkjson = require("lain.util").dkjson
16 local math = require("math")
17 local freedesktop = require("freedesktop")
18 local luatz = require("luatz")
19 -- }}}
20
21 -- {{{ Error handling
22 -- Check if awesome encountered an error during startup and fell back to
23 -- another config (This code will only ever execute for the fallback config)
24 if awesome.startup_errors then
25     naughty.notify({ preset = naughty.config.presets.critical,
26                      title = "Oops, there were errors during startup!",
27                      text = awesome.startup_errors })
28 end
29
30 -- Handle runtime errors after startup
31 do
32     local in_error = false
33     awesome.connect_signal("debug::error", function (err)
34         -- Make sure we don't go into an endless error loop
35         if in_error then return end
36         in_error = true
37
38         naughty.notify({ preset = naughty.config.presets.critical,
39                          title = "Oops, an error happened!",
40                          text = tostring(err) })
41         in_error = false
42     end)
43 end
44 -- }}}
45
46 -- {{{ Variable definitions
47 -- Themes define colours, icons, and wallpapers
48 beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua")
49
50 -- This is used later as the default terminal and editor to run.
51 terminal = "x-terminal-emulator"
52 editor = "sensible-editor"
53 editor_cmd = terminal .. " -e " .. editor
54
55 -- Default modkey.
56 -- Usually, Mod4 is the key with a logo between Control and Alt.
57 -- If you do not like this or do not have such a key,
58 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
59 -- However, you can use another modifier like Mod1, but it may interact with others.
60 modkey = "Mod4"
61 cmdkey = "Mod3"
62
63 -- Table of layouts to cover with awful.layout.inc, order matters.
64 awful.layout.layouts = {
65     awful.layout.suit.fair,
66     awful.layout.suit.tile,
67     -- awful.layout.suit.tile.left,
68     -- awful.layout.suit.tile.bottom,
69     awful.layout.suit.tile.top,
70     -- awful.layout.suit.spiral,
71     -- awful.layout.suit.spiral.dwindle,
72     awful.layout.suit.max,
73     -- awful.layout.suit.max.fullscreen,
74     -- awful.layout.suit.magnifier,
75     -- awful.layout.suit.corner.nw,
76     -- awful.layout.suit.corner.ne,
77     -- awful.layout.suit.corner.sw,
78     -- awful.layout.suit.corner.se,
79     awful.layout.suit.floating,
80 }
81
82 layout_default = awful.layout.layouts[1]
83 layout_tiled = awful.layout.layouts[2]
84 layout_maximised = awful.layout.layouts[4]
85 layout_floating = awful.layout.layouts[5]
86 -- }}}
87
88 -- {{{ Helper functions
89 local function client_menu_toggle_fn()
90     local instance = nil
91
92     return function ()
93         if instance and instance.wibox.visible then
94             instance:hide()
95             instance = nil
96         else
97             instance = awful.menu.clients({ theme = { width = 250 } })
98         end
99     end
100 end
101
102 local function sorted_pairs(t, f)
103     local a = {}
104     for n in pairs(t) do table.insert(a, n) end
105     table.sort(a, f)
106     local i = 0      -- iterator variable
107     local iter = function ()   -- iterator function
108         i = i + 1
109         if a[i] == nil then return nil
110         else return a[i], t[a[i]]
111         end
112     end
113     return iter
114 end
115
116 local function print_table(tbl, indent)
117     if not indent then indent = 0 end
118     for k, v in pairs(tbl) do
119         formatting = string.rep("  ", indent) .. k .. ": "
120         if type(v) == "table" then
121             print(formatting)
122             print_table(v, indent+1)
123         else
124             print(formatting .. tostring(v))
125         end
126     end
127 end
128
129 local lain_bat = lain.widget.bat({
130     batteries = {"BAT0", "BAT1"},
131     settings = function()
132         local delim = "↓"
133         if bat_now.status == "Charging" then delim = "↑"
134         elseif bat_now.status == "Unknown" then delim = "٭" end
135         widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
136     end,
137 })
138
139 local function poloniex_price(output, pair, prec)
140     local xc, pos, err = dkjson.decode(output, 1, nil)
141     if not prec then prec = 4 end
142     val = (xc and xc[pair]["last"]) or 0
143     val = math.floor(val*10^prec+0.5)/10^prec
144     return (not err and val) or "n/a"
145 end
146
147 local eth_widget = lain.widget.watch({
148     cmd = "curl -m5 -s 'https://poloniex.com/public?command=returnTicker'",
149     timeout = 600,
150     settings = function()
151         widget:set_text(poloniex_price(output, 'BTC_ETH') .. " Ƀ/Ξ")
152     end
153 })
154
155 local function coindesk_price(output, base, prec)
156     local xc, pos, err = dkjson.decode(output, 1, nil)
157     if not prec then prec = 4 end
158     val = (xc and xc["bpi"][base]["rate_float"]) or 0
159     val = math.floor(val*10^prec+0.5)/10^prec
160     return (not err and val) or "n/a"
161 end
162
163 local btc_widget = lain.widget.watch({
164     cmd = "curl -m5 -Ls 'https://api.coindesk.com/v1/bpi/currentprice/EUR.json'",
165     timeout = 600,
166     settings = function()
167         widget:set_text(coindesk_price(output, "EUR", 2) .. " €/Ƀ")
168     end
169 })
170
171 -- }}}
172
173 -- {{{ Menu
174 -- Create a launcher widget and a main menu
175 myawesomemenu = {
176    { "hotkeys", function() return false, hotkeys_popup.show_help end},
177    { "manual", terminal .. " -e man awesome" },
178    { "edit config", editor_cmd .. " " .. awesome.conffile },
179    { "restart", awesome.restart },
180    { "quit", awesome.quit }
181 }
182
183 mymainmenu = freedesktop.menu.build({
184     before = {
185         { "awesome", myawesomemenu, beautiful.awesome_icon },
186         { "terminal", terminal },
187     },
188     after = {
189     }
190 })
191
192 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
193                                      menu = mymainmenu })
194 -- }}}
195
196 -- {{{ Menubar configuration
197 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
198 -- }}}
199
200 -- {{{ Wibox
201 local spacer = wibox.widget.textbox()
202 spacer:set_text(' │ ')
203 -- Create a textclock widget
204 clocks = { wibox.widget.textclock("%a %d %b %H:%M:%S", 1) }
205
206 ZONES = {
207   ["NZ"] = "Pacific/Auckland",
208   ["DE"] = "Europe/Berlin"
209 }
210
211 now = luatz.time_in(nil)
212 for c, tz in sorted_pairs(ZONES) do
213     t = luatz.time_in(tz)
214     if math.abs(os.difftime(t, now)) > 10 then
215         local widget = wibox.widget.textclock(c .. ": %H:%M (%a)", 60, tz)
216         table.insert(clocks, spacer)
217         table.insert(clocks, widget)
218     end
219 end
220
221 -- Create a wibox for each screen and add it
222 mywibox = {}
223 mypromptbox = {}
224 mylayoutbox = {}
225 mytaglist = {}
226 mytaglist.buttons = awful.util.table.join(
227                     awful.button({ }, 1, function(t) t:view_only() end),
228                     awful.button({ modkey }, 1, function(t)
229                                               if client.focus then
230                                                   client.focus:move_to_tag(t)
231                                               end
232                                           end),
233                     awful.button({ }, 3, awful.tag.viewtoggle),
234                     awful.button({ modkey }, 3, function(t)
235                                               if client.focus then
236                                                   client.focus:toggle_tag(t)
237                                               end
238                                           end),
239                     awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
240                     awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
241                 )
242
243 mytasklist = {}
244 mytasklist.buttons = awful.util.table.join(
245                      awful.button({ }, 1, function (c)
246                                               if c == client.focus then
247                                                   -- I don't like click-minimising
248                                                   -- c.minimized = true
249                                               else
250                                                   -- Without this, the following
251                                                   -- :isvisible() makes no sense
252                                                   c.minimized = false
253                                                   if not c:isvisible() and c.first_tag then
254                                                       c.first_tag:view_only()
255                                                   end
256                                                   -- This will also un-minimize
257                                                   -- the client, if needed
258                                                   client.focus = c
259                                                   c:raise()
260                                               end
261                                           end),
262                      awful.button({ }, 3, client_menu_toggle_fn()),
263                      awful.button({ }, 4, function ()
264                                               awful.client.focus.byidx(1)
265                                           end),
266                      awful.button({ }, 5, function ()
267                                               awful.client.focus.byidx(-1)
268                                           end))
269 -- }}}
270
271 -- {{{ Tags
272 tags = {}
273 tags.config = {}
274 tags.config["main"] = {
275     t1 = { layout = layout_default, selected = true },
276     t2 = { layout = layout_default },
277     t3 = { layout = layout_tiled },
278     t4 = { layout = layout_tiled },
279     t5 = { layout = layout_tiled },
280     t6 = { layout = layout_floating },
281     t7 = { layout = layout_maximised },
282     t8 = { layout = layout_maximised },
283     t9 = { layout = layout_maximised },
284 }
285 tags.config["aux"] = {
286     t1 = { layout = layout_default, selected = true },
287     t2 = { layout = layout_default },
288     t3 = { layout = layout_tiled },
289     t4 = { layout = layout_floating },
290     t5 = { layout = layout_floating },
291     t6 = { layout = layout_floating },
292     t7 = { layout = layout_floating },
293     t8 = { layout = layout_floating },
294     t9 = { layout = layout_maximised },
295 }
296
297 screentags = {}
298 screentags[1] = tags.config["main"]
299 if screen.count() == 2 then -- aux screen is on the right
300   screentags[2] = tags.config["aux"]
301 elseif screen.count() == 3 then -- main screen is still #1 in the middle
302   screentags[2] = tags.config["aux"]
303   screentags[3] = tags.config["aux"]
304 end
305
306 awful.screen.connect_for_each_screen(function(s)
307     -- Wallpaper
308     --DISABLED--if beautiful.wallpaper then
309     --DISABLED--    local wallpaper = beautiful.wallpaper
310     --DISABLED--    -- If wallpaper is a function, call it with the screen
311     --DISABLED--    if type(wallpaper) == "function" then
312     --DISABLED--        wallpaper = wallpaper(s)
313     --DISABLED--    end
314     --DISABLED--    gears.wallpaper.maximized(wallpaper, s, true)
315     --DISABLED--end
316
317     if not tags[s.index] then
318         tags[s.index] = {}
319     end
320     for n,p in sorted_pairs(screentags[s.index]) do
321         p["screen"] = s
322         n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
323         table.insert(tags[s.index], awful.tag.add(n, p))
324     end
325
326     -- Create a promptbox for each screen
327     mypromptbox[s] = awful.widget.prompt()
328     -- Create an imagebox widget which will contains an icon indicating which layout we're using.
329     -- We need one layoutbox per screen.
330     mylayoutbox[s] = awful.widget.layoutbox(s)
331     mylayoutbox[s]:buttons(awful.util.table.join(
332                            awful.button({ }, 1, function () awful.layout.inc( 1) end),
333                            awful.button({ }, 3, function () awful.layout.inc(-1) end),
334                            awful.button({ }, 4, function () awful.layout.inc( 1) end),
335                            awful.button({ }, 5, function () awful.layout.inc(-1) end)))
336     -- Create a taglist widget
337     mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
338
339     -- Create a tasklist widget
340     mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
341
342     -- Create the wibox
343     mywibox[s] = awful.wibar({ position = "top", screen = s })
344
345     -- Add widgets to the wibox
346     mywibox[s]:setup {
347         layout = wibox.layout.align.horizontal,
348         { -- Left widgets
349             layout = wibox.layout.fixed.horizontal,
350             -- mylauncher,
351             mytaglist[s],
352             mypromptbox[s],
353         },
354         mytasklist[s], -- Middle widget
355         awful.util.table.join( -- Right widgets
356             {
357                 layout = wibox.layout.fixed.horizontal,
358                 mykeyboardlayout,
359                 wibox.widget.systray(),
360                 btc_widget,
361                 spacer,
362                 lain_bat.widget,
363                 spacer,
364             },
365             clocks,
366             {
367                 mylayoutbox[s],
368             }
369         ),
370     }
371 end)
372 -- }}}
373
374 -- {{{ Mouse bindings
375 root.buttons(awful.util.table.join(
376     awful.button({ }, 3, function () mymainmenu:toggle() end),
377     awful.button({ }, 4, awful.tag.viewnext),
378     awful.button({ }, 5, awful.tag.viewprev)
379 ))
380 -- }}}
381
382 -- {{{ Key bindings
383 globalkeys = awful.util.table.join(
384     awful.key({ modkey,           }, "s",      hotkeys_popup.show_help,
385               {description="show help", group="awesome"}),
386     awful.key({ modkey,           }, "Left",   awful.tag.viewprev,
387               {description = "view previous", group = "tag"}),
388     awful.key({ modkey,           }, "Right",  awful.tag.viewnext,
389               {description = "view next", group = "tag"}),
390     awful.key({ modkey,           }, "Escape", awful.tag.history.restore,
391               {description = "go back", group = "tag"}),
392
393     awful.key({ modkey,           }, "k",
394         function ()
395             awful.client.focus.byidx( 1)
396         end,
397         {description = "focus next by index", group = "client"}
398     ),
399     awful.key({ modkey,           }, "j",
400         function ()
401             awful.client.focus.byidx(-1)
402         end,
403         {description = "focus previous by index", group = "client"}
404     ),
405     awful.key({ modkey,           }, "w", function () mymainmenu:show() end,
406               {description = "show main menu", group = "awesome"}),
407
408     -- Layout manipulation
409     awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx(  1)    end,
410               {description = "swap with next client by index", group = "client"}),
411     awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx( -1)    end,
412               {description = "swap with previous client by index", group = "client"}),
413     awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
414               {description = "focus the next screen", group = "screen"}),
415     awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
416               {description = "focus the previous screen", group = "screen"}),
417     awful.key({ modkey,           }, "u", awful.client.urgent.jumpto,
418               {description = "jump to urgent client", group = "client"}),
419     awful.key({ modkey,           }, "Tab",
420         function ()
421             awful.client.focus.history.previous()
422             if client.focus then
423                 client.focus:raise()
424             end
425         end,
426         {description = "go back", group = "client"}),
427
428     -- Standard program
429     awful.key({ modkey,           }, "Return", function () awful.spawn(terminal) end,
430               {description = "open a terminal", group = "launcher"}),
431     awful.key({ modkey, "Control" }, "r", awesome.restart,
432               {description = "reload awesome", group = "awesome"}),
433     awful.key({ modkey, "Shift"   }, "q", awesome.quit,
434               {description = "quit awesome", group = "awesome"}),
435
436     awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)          end,
437               {description = "increase master width factor", group = "layout"}),
438     awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)          end,
439               {description = "decrease master width factor", group = "layout"}),
440     awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1, nil, true) end,
441               {description = "increase the number of master clients", group = "layout"}),
442     awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1, nil, true) end,
443               {description = "decrease the number of master clients", group = "layout"}),
444     awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1, nil, true)    end,
445               {description = "increase the number of columns", group = "layout"}),
446     awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1, nil, true)    end,
447               {description = "decrease the number of columns", group = "layout"}),
448     awful.key({ modkey,           }, "space", function () awful.layout.inc( 1)                end,
449               {description = "select next", group = "layout"}),
450     awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(-1)                end,
451               {description = "select previous", group = "layout"}),
452
453     awful.key({ modkey, "Control" }, "n",
454               function ()
455                   local c = awful.client.restore()
456                   -- Focus restored client
457                   if c then
458                       client.focus = c
459                       c:raise()
460                   end
461               end,
462               {description = "restore minimized", group = "client"}),
463
464     -- Prompt
465     awful.key({ modkey },            "r",     function () mypromptbox[awful.screen.focused()]:run() end,
466               {description = "run prompt", group = "launcher"}),
467
468     awful.key({ modkey }, "x",
469               function ()
470                   awful.prompt.run({ prompt = "Run Lua code: " },
471                   mypromptbox[awful.screen.focused()].widget,
472                   awful.util.eval, nil,
473                   awful.util.get_cache_dir() .. "/history_eval")
474               end,
475               {description = "lua execute prompt", group = "awesome"}),
476     -- Menubar
477     awful.key({ modkey }, "p", function() menubar.show() end,
478               {description = "show the menubar", group = "launcher"})
479 )
480
481 clientkeys = awful.util.table.join(
482     awful.key({ modkey,           }, "f",
483         function (c)
484             c.fullscreen = not c.fullscreen
485             c:raise()
486         end,
487         {description = "toggle fullscreen", group = "client"}),
488     awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end,
489               {description = "close", group = "client"}),
490     awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ,
491               {description = "toggle floating", group = "client"}),
492     awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
493               {description = "move to master", group = "client"}),
494     awful.key({ modkey,           }, "o",      function (c) c:move_to_screen()               end,
495               {description = "move to screen", group = "client"}),
496     awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end,
497               {description = "toggle keep on top", group = "client"}),
498     awful.key({ modkey,           }, "n",
499         function (c)
500             -- The client currently has the input focus, so it cannot be
501             -- minimized, since minimized clients can't have the focus.
502             c.minimized = true
503         end ,
504         {description = "minimize", group = "client"}),
505     awful.key({ modkey,           }, "m",
506         function (c)
507             c.maximized = not c.maximized
508             c.maximized_horizontal = false
509             c.maximized_vertical = false
510             c:raise()
511         end ,
512         {description = "maximize", group = "client"})
513 )
514
515 -- Bind all key numbers to tags.
516 -- Be careful: we use keycodes to make it works on any keyboard layout.
517 -- This should map on the top row of your keyboard, usually 1 to 9.
518 for i = 1, 9 do
519     globalkeys = awful.util.table.join(globalkeys,
520         -- View tag only.
521         awful.key({ modkey }, "#" .. i + 9,
522                   function ()
523                         local screen = awful.screen.focused()
524                         local tag = screen.tags[i]
525                         if tag then
526                            tag:view_only()
527                         end
528                   end,
529                   {description = "view tag #"..i, group = "tag"}),
530         -- Toggle tag.
531         awful.key({ modkey, "Control" }, "#" .. i + 9,
532                   function ()
533                       local screen = awful.screen.focused()
534                       local tag = screen.tags[i]
535                       if tag then
536                          awful.tag.viewtoggle(tag)
537                       end
538                   end,
539                   {description = "toggle tag #" .. i, group = "tag"}),
540         -- Move client to tag.
541         awful.key({ modkey, "Shift" }, "#" .. i + 9,
542                   function ()
543                       if client.focus then
544                           local tag = client.focus.screen.tags[i]
545                           if tag then
546                               client.focus:move_to_tag(tag)
547                           end
548                      end
549                   end,
550                   {description = "move focused client to tag #"..i, group = "tag"}),
551         -- Toggle tag on focused client.
552         awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
553                   function ()
554                       if client.focus then
555                           local tag = client.focus.screen.tags[i]
556                           if tag then
557                               client.focus:toggle_tag(tag)
558                           end
559                       end
560                   end,
561                   {description = "toggle focused client on tag #" .. i, group = "tag"})
562     )
563 end
564
565 clientbuttons = awful.util.table.join(
566     awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
567     awful.button({ modkey }, 1, awful.mouse.client.move),
568     awful.button({ modkey }, 3, awful.mouse.client.resize))
569
570 -- misc apps
571 globalkeys = awful.util.table.join(globalkeys,
572 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
573 awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
574 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
575 awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
576 awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
577 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
578 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
579 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
580 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
581 awful.key({ cmdkey }, "i", function () awful.spawn(terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi") end),
582 awful.key({ cmdkey }, "x", function () awful.spawn.with_shell("/sbin/start-stop-daemon --start --background --exec /usr/bin/xscreensaver -- -no-capture-stderr; sleep 2; xscreensaver-command -lock") end),
583 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
584
585 -- function keys
586 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
587 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
588 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
589 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
590 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
591 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
592 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
593 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
594 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
595 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
596 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
597 awful.key(nil, "XF86Display", function () awful.spawn("") end),
598 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
599 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
600 awful.key(nil, "XF86Search", function () awful.spawn("") end),
601 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
602 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
603 )
604
605 -- Set keys
606 root.keys(globalkeys)
607 -- }}}
608
609 -- {{{ Rules
610 -- Rules to apply to new clients (through the "manage" signal).
611
612 local function move_to_tag(s, t)
613     return function(c)
614         c:move_to_tag(tags[s][t])
615     end
616 end
617
618 awful.rules.rules = {
619     -- All clients will match this rule.
620     { rule = { },
621       properties = { border_width = beautiful.border_width,
622                      border_color = beautiful.border_normal,
623                      focus = awful.client.focus.filter,
624                      raise = true,
625                      keys = clientkeys,
626                      buttons = clientbuttons,
627                      screen = awful.screen.preferred,
628                      placement = awful.placement.no_overlap+awful.placement.no_offscreen,
629                      floating = false
630                  },
631     },
632
633     -- Add titlebars to normal clients and dialogs
634     --DISABLED-- { rule_any = {type = { "normal", "dialog" }
635     --DISABLED--  }, properties = { titlebars_enabled = true }
636     --DISABLED-- },
637
638     { rule = { type = "dialog" },
639       properties = { floating = true,
640                      placement = awful.placement.centered
641                  }
642     },
643
644     { rule = { class = "URxvt" },
645                properties = {
646                    -- floating = false,
647                    size_hints_honor = false
648                } },
649     { rule = { class = "URxvt", instance = "irc" },
650                properties = {
651                    switchtotag = true
652                },
653                callback = move_to_tag(screen.count(), screen.count() == 1 and 2 or 1)
654            },
655     { rule = { class = "Firefox", instance = "Navigator" },
656                properties = {
657                    floating = false,
658                },
659                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
660            },
661     { rule = { class = "Firefox-esr", instance = "Navigator" },
662                properties = {
663                    floating = false,
664                },
665                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
666            },
667     { rule = { class = "Thunderbird", instance = "Mail" },
668                properties = {
669                    floating = false,
670                },
671                callback = move_to_tag(screen.count() == 1 and 1 or 2, 8)
672            },
673     { rule = { class = "Chromium", instance = "chromium" },
674                properties = {
675                    floating = false,
676                },
677                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
678            },
679     { rule = { class = "Gscan2pdf" },
680                properties = {
681                    switchtotag = true
682                },
683                callback = move_to_tag(1, 5)
684            },
685     { rule = { name = "gscan2pdf .*" },
686                properties = {
687                    floating = false,
688                },
689            },
690     { rule = { class = "Thunar", type = "normal" },
691                properties = {
692                    floating = false,
693                },
694            },
695     { rule = { class = "MuPDF", instance = "mupdf" },
696                properties = {
697                    floating = true,
698                },
699            },
700     { rule = { class = "Pinentry", instance = "pinentry" },
701                properties = {
702                    floating = true,
703                },
704            },
705     { rule = { class = "Gxmessage" },
706                properties = {
707                    floating = true,
708                },
709            },
710 }
711 -- }}}
712
713 -- {{{ Signals
714 -- Signal function to execute when a new client appears.
715 client.connect_signal("manage", function (c)
716     -- Set the windows at the slave,
717     -- i.e. put it at the end of others instead of setting it master.
718     if not awesome.startup then awful.client.setslave(c) end
719
720     if awesome.startup and
721       not c.size_hints.user_position
722       and not c.size_hints.program_position then
723         -- Prevent clients from being unreachable after screen count changes.
724         awful.placement.no_offscreen(c)
725     end
726
727     c.maximized_horizontal = false
728     c.maximized_vertical = false
729 end)
730
731 -- Add a titlebar if titlebars_enabled is set to true in the rules.
732 client.connect_signal("request::titlebars", function(c)
733     -- buttons for the titlebar
734     local buttons = awful.util.table.join(
735         awful.button({ }, 1, function()
736             client.focus = c
737             c:raise()
738             awful.mouse.client.move(c)
739         end),
740         awful.button({ }, 3, function()
741             client.focus = c
742             c:raise()
743             awful.mouse.client.resize(c)
744         end)
745     )
746
747     awful.titlebar(c) : setup {
748         { -- Left
749             awful.titlebar.widget.iconwidget(c),
750             buttons = buttons,
751             layout  = wibox.layout.fixed.horizontal
752         },
753         { -- Middle
754             { -- Title
755                 align  = "center",
756                 widget = awful.titlebar.widget.titlewidget(c)
757             },
758             buttons = buttons,
759             layout  = wibox.layout.flex.horizontal
760         },
761         { -- Right
762             awful.titlebar.widget.floatingbutton (c),
763             awful.titlebar.widget.maximizedbutton(c),
764             awful.titlebar.widget.stickybutton   (c),
765             awful.titlebar.widget.ontopbutton    (c),
766             awful.titlebar.widget.closebutton    (c),
767             layout = wibox.layout.fixed.horizontal()
768         },
769         layout = wibox.layout.align.horizontal
770     }
771 end)
772
773 -- Enable sloppy focus
774 client.connect_signal("mouse::enter", function(c)
775     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
776         and awful.client.focus.filter(c) then
777         client.focus = c
778     end
779 end)
780
781 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
782 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
783
784 awful.ewmh.add_activate_filter(function(c, context, hints)
785     if context == "ewmh" and (c.class == "Firefox-esr" or c.class == "Firefox") then return false end
786 end)
787
788 -- vim:ft=lua:sw=4:sts=4:ts=4:et