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:

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