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:

4b3ae6b43a521a83124fc4061526c3c746f460bb
[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 clocksarray = require("clocksarray")
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 clocksarray = clocksarray.get_clocksarray("%a %d %b %H:%M:%S %Z", {
183         ["NZ"] = "Pacific/Auckland",
184         ["DE"] = "Europe/Berlin"
185     }, spacer)
186
187 -- Create a wibox for each screen and add it
188 local taglist_buttons = gears.table.join(
189                     awful.button({ }, 1, function(t) t:view_only() end),
190                     awful.button({ modkey }, 1, function(t)
191                                               if client.focus then
192                                                   client.focus:move_to_tag(t)
193                                               end
194                                           end),
195                     awful.button({ }, 3, awful.tag.viewtoggle),
196                     awful.button({ modkey }, 3, function(t)
197                                               if client.focus then
198                                                   client.focus:toggle_tag(t)
199                                               end
200                                           end),
201                     awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
202                     awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
203                 )
204
205 local tasklist_buttons = gears.table.join(
206                      awful.button({ }, 1, function (c)
207                                               if c == client.focus then
208                                                   -- I don't like click-minimising
209                                                   -- c.minimized = true
210                                               else
211                                                   -- Without this, the following
212                                                   -- :isvisible() makes no sense
213                                                   c.minimized = false
214                                                   if not c:isvisible() and c.first_tag then
215                                                       c.first_tag:view_only()
216                                                   end
217                                                   -- This will also un-minimize
218                                                   -- the client, if needed
219                                                   client.focus = c
220                                                   c:raise()
221                                               end
222                                           end),
223                      awful.button({ }, 3, client_menu_toggle_fn()),
224                      awful.button({ }, 4, function ()
225                                               awful.client.focus.byidx(1)
226                                           end),
227                      awful.button({ }, 5, function ()
228                                               awful.client.focus.byidx(-1)
229                                           end))
230 -- }}}
231
232 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
233 screen.connect_signal("property::geometry", set_wallpaper)
234
235 -- {{{ Tags
236 tags = {}
237 tags.config = {}
238 tags.config["main"] = {
239     t1 = { layout = layout_default, selected = true },
240     t2 = { layout = layout_default },
241     t3 = { layout = layout_tiled },
242     t4 = { layout = layout_tiled },
243     t5 = { layout = layout_tiled },
244     t6 = { layout = layout_floating },
245     t7 = { layout = layout_maximised },
246     t8 = { layout = layout_maximised },
247     t9 = { layout = layout_maximised },
248 }
249 tags.config["aux"] = {
250     t1 = { layout = layout_default, selected = true },
251     t2 = { layout = layout_default },
252     t3 = { layout = layout_tiled },
253     t4 = { layout = layout_floating },
254     t5 = { layout = layout_floating },
255     t6 = { layout = layout_floating },
256     t7 = { layout = layout_floating },
257     t8 = { layout = layout_floating },
258     t9 = { layout = layout_maximised },
259 }
260
261 screentags = {}
262 screentags[1] = tags.config["main"]
263 if screen.count() == 2 then -- aux screen is on the right
264   screentags[2] = tags.config["aux"]
265 elseif screen.count() == 3 then -- main screen is still #1 in the middle
266   screentags[2] = tags.config["aux"]
267   screentags[3] = tags.config["aux"]
268 end
269
270 awful.screen.connect_for_each_screen(function(s)
271     -- local fontsize = math.floor(250 * xrdb.get_dpi(s)/s.geometry.width)
272     -- beautiful.font = "Sans " .. tostring(fontsize)
273
274     if not tags[s.index] then
275         tags[s.index] = {}
276     end
277     for n,p in tblutils.sorted_pairs(screentags[s.index]) do
278         p["screen"] = s
279         n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
280         table.insert(tags[s.index], awful.tag.add(n, p))
281     end
282
283     -- Create a promptbox for each screen
284     mypromptbox[s] = awful.widget.prompt()
285     -- Create an imagebox widget which will contains an icon indicating which layout we're using.
286     -- We need one layoutbox per screen.
287     mylayoutbox[s] = awful.widget.layoutbox(s)
288     mylayoutbox[s]:buttons(awful.util.table.join(
289                            awful.button({ }, 1, function () awful.layout.inc( 1) end),
290                            awful.button({ }, 3, function () awful.layout.inc(-1) end),
291                            awful.button({ }, 4, function () awful.layout.inc( 1) end),
292                            awful.button({ }, 5, function () awful.layout.inc(-1) end)))
293     -- Create a taglist widget
294     mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
295
296     -- Create a tasklist widget
297     mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
298
299     -- Create the wibox
300     mywibox[s] = awful.wibar({ position = "top", screen = s })
301
302     -- Add widgets to the wibox
303     mywibox[s]:setup {
304         layout = wibox.layout.align.horizontal,
305         { -- Left widgets
306             layout = wibox.layout.fixed.horizontal,
307             -- mylauncher,
308             mytaglist[s],
309             mypromptbox[s],
310         },
311         mytasklist[s], -- Middle widget
312         awful.util.table.join( -- Right widgets
313             {
314                 layout = wibox.layout.fixed.horizontal,
315                 mykeyboardlayout,
316                 wibox.widget.systray(),
317                 ccwidgets.btc_widget,
318                 spacer,
319                 ccwidgets.eth_widget,
320                 spacer,
321                 lain_bat.widget,
322                 spacer,
323             },
324             clocksarray,
325             {
326                 mylayoutbox[s],
327             }
328         ),
329     }
330 end)
331 -- }}}
332
333 -- {{{ Mouse bindings
334 root.buttons(gears.table.join(
335     awful.button({ }, 3, function () mymainmenu:toggle() end),
336     awful.button({ }, 4, awful.tag.viewnext),
337     awful.button({ }, 5, awful.tag.viewprev)
338 ))
339 -- }}}
340
341 -- {{{ Key bindings
342 globalkeys = gears.table.join(
343     awful.key({ modkey,           }, "s",      hotkeys_popup.show_help,
344               {description="show help", group="awesome"}),
345     awful.key({ modkey,           }, "Left",   awful.tag.viewprev,
346               {description = "view previous", group = "tag"}),
347     awful.key({ modkey,           }, "Right",  awful.tag.viewnext,
348               {description = "view next", group = "tag"}),
349     awful.key({ modkey,           }, "Escape", awful.tag.history.restore,
350               {description = "go back", group = "tag"}),
351
352     awful.key({ modkey,           }, "k",
353         function ()
354             awful.client.focus.byidx( 1)
355         end,
356         {description = "focus next by index", group = "client"}
357     ),
358     awful.key({ modkey,           }, "j",
359         function ()
360             awful.client.focus.byidx(-1)
361         end,
362         {description = "focus previous by index", group = "client"}
363     ),
364     awful.key({ modkey,           }, "w", function () mymainmenu:show() end,
365               {description = "show main menu", group = "awesome"}),
366
367     -- Layout manipulation
368     awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx(  1)    end,
369               {description = "swap with next client by index", group = "client"}),
370     awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx( -1)    end,
371               {description = "swap with previous client by index", group = "client"}),
372     awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
373               {description = "focus the next screen", group = "screen"}),
374     awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
375               {description = "focus the previous screen", group = "screen"}),
376     awful.key({ modkey,           }, "u", awful.client.urgent.jumpto,
377               {description = "jump to urgent client", group = "client"}),
378     awful.key({ modkey,           }, "Tab",
379         function ()
380             awful.client.focus.history.previous()
381             if client.focus then
382                 client.focus:raise()
383             end
384         end,
385         {description = "go back", group = "client"}),
386
387     -- Standard program
388     awful.key({ modkey,           }, "Return", function () awful.spawn(terminal) end,
389               {description = "open a terminal", group = "launcher"}),
390     awful.key({ modkey, "Control" }, "r", awesome.restart,
391               {description = "reload awesome", group = "awesome"}),
392     awful.key({ modkey, "Shift"   }, "q", awesome.quit,
393               {description = "quit awesome", group = "awesome"}),
394
395     awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)          end,
396               {description = "increase master width factor", group = "layout"}),
397     awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)          end,
398               {description = "decrease master width factor", group = "layout"}),
399     awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1, nil, true) end,
400               {description = "increase the number of master clients", group = "layout"}),
401     awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1, nil, true) end,
402               {description = "decrease the number of master clients", group = "layout"}),
403     awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1, nil, true)    end,
404               {description = "increase the number of columns", group = "layout"}),
405     awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1, nil, true)    end,
406               {description = "decrease the number of columns", group = "layout"}),
407     awful.key({ modkey,           }, "space", function () awful.layout.inc( 1)                end,
408               {description = "select next", group = "layout"}),
409     awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(-1)                end,
410               {description = "select previous", group = "layout"}),
411
412     awful.key({ modkey, "Control" }, "n",
413               function ()
414                   local c = awful.client.restore()
415                   -- Focus restored client
416                   if c then
417                       client.focus = c
418                       c:raise()
419                   end
420               end,
421               {description = "restore minimized", group = "client"}),
422
423     -- Prompt
424     awful.key({ modkey },            "r",     function () awful.screen.focused().mypromptbox:run() end,
425               {description = "run prompt", group = "launcher"}),
426
427     awful.key({ modkey }, "x",
428               function ()
429                   awful.prompt.run {
430                     prompt       = "Run Lua code: ",
431                     textbox      = awful.screen.focused().mypromptbox.widget,
432                     exe_callback = awful.util.eval,
433                     history_path = awful.util.get_cache_dir() .. "/history_eval"
434                   }
435               end,
436               {description = "lua execute prompt", group = "awesome"}),
437     -- Menubar
438     awful.key({ modkey }, "p", function() menubar.show() end,
439               {description = "show the menubar", group = "launcher"})
440 )
441
442 clientkeys = gears.table.join(
443     awful.key({ modkey,           }, "f",
444         function (c)
445             c.fullscreen = not c.fullscreen
446             c:raise()
447         end,
448         {description = "toggle fullscreen", group = "client"}),
449     awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end,
450               {description = "close", group = "client"}),
451     awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ,
452               {description = "toggle floating", group = "client"}),
453     awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
454               {description = "move to master", group = "client"}),
455     awful.key({ modkey,           }, "o",      function (c) c:move_to_screen()               end,
456               {description = "move to screen", group = "client"}),
457     awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end,
458               {description = "toggle keep on top", group = "client"}),
459     awful.key({ modkey,           }, "n",
460         function (c)
461             -- The client currently has the input focus, so it cannot be
462             -- minimized, since minimized clients can't have the focus.
463             c.minimized = true
464         end ,
465         {description = "minimize", group = "client"}),
466     awful.key({ modkey,           }, "m",
467         function (c)
468             c.maximized = not c.maximized
469             c.maximized_horizontal = false
470             c.maximized_vertical = false
471             c:raise()
472         end ,
473         {description = "(un)maximize", group = "client"}),
474     awful.key({ modkey, "Control" }, "m",
475         function (c)
476             c.maximized_vertical = not c.maximized_vertical
477             c:raise()
478         end ,
479         {description = "(un)maximize vertically", group = "client"}),
480     awful.key({ modkey, "Shift"   }, "m",
481         function (c)
482             c.maximized_horizontal = not c.maximized_horizontal
483             c:raise()
484         end ,
485         {description = "(un)maximize horizontally", group = "client"})
486 )
487
488 -- Bind all key numbers to tags.
489 -- Be careful: we use keycodes to make it work on any keyboard layout.
490 -- This should map on the top row of your keyboard, usually 1 to 9.
491 for i = 1, 9 do
492     globalkeys = gears.table.join(globalkeys,
493         -- View tag only.
494         awful.key({ modkey }, "#" .. i + 9,
495                   function ()
496                         local screen = awful.screen.focused()
497                         local tag = screen.tags[i]
498                         if tag then
499                            tag:view_only()
500                         end
501                   end,
502                   {description = "view tag #"..i, group = "tag"}),
503         -- Toggle tag display.
504         awful.key({ modkey, "Control" }, "#" .. i + 9,
505                   function ()
506                       local screen = awful.screen.focused()
507                       local tag = screen.tags[i]
508                       if tag then
509                          awful.tag.viewtoggle(tag)
510                       end
511                   end,
512                   {description = "toggle tag #" .. i, group = "tag"}),
513         -- Move client to tag.
514         awful.key({ modkey, "Shift" }, "#" .. i + 9,
515                   function ()
516                       if client.focus then
517                           local tag = client.focus.screen.tags[i]
518                           if tag then
519                               client.focus:move_to_tag(tag)
520                           end
521                      end
522                   end,
523                   {description = "move focused client to tag #"..i, group = "tag"}),
524         -- Toggle tag on focused client.
525         awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
526                   function ()
527                       if client.focus then
528                           local tag = client.focus.screen.tags[i]
529                           if tag then
530                               client.focus:toggle_tag(tag)
531                           end
532                       end
533                   end,
534                   {description = "toggle focused client on tag #" .. i, group = "tag"})
535     )
536 end
537
538 clientbuttons = gears.table.join(
539     awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
540     awful.button({ modkey }, 1, awful.mouse.client.move),
541     awful.button({ modkey }, 3, awful.mouse.client.resize))
542
543 -- misc apps
544 globalkeys = awful.util.table.join(globalkeys,
545 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
546 awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
547 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
548 awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
549 awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
550 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
551 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
552 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
553 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
554 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),
555 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),
556 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
557
558 -- function keys
559 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
560 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
561 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
562 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
563 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
564 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
565 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
566 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
567 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
568 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
569 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
570 awful.key(nil, "XF86Display", function () awful.spawn("") end),
571 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
572 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
573 awful.key(nil, "XF86Search", function () awful.spawn("") end),
574 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
575 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
576 )
577
578 -- Set keys
579 root.keys(globalkeys)
580 -- }}}
581
582 -- {{{ Rules
583 -- Rules to apply to new clients (through the "manage" signal).
584
585 local function move_to_tag(s, t)
586     return function(c)
587         c:move_to_tag(tags[s][t])
588     end
589 end
590
591 awful.rules.rules = {
592     -- All clients will match this rule.
593     { rule = { },
594       properties = { border_width = beautiful.border_width,
595                      border_color = beautiful.border_normal,
596                      focus = awful.client.focus.filter,
597                      raise = true,
598                      keys = clientkeys,
599                      buttons = clientbuttons,
600                      screen = awful.screen.preferred,
601                      placement = awful.placement.no_overlap+awful.placement.no_offscreen,
602                      floating = false
603                  },
604     },
605
606     -- Add titlebars to normal clients and dialogs
607     --DISABLED-- { rule_any = {type = { "normal", "dialog" }
608     --DISABLED--  }, properties = { titlebars_enabled = true }
609     --DISABLED-- },
610
611     { rule = { type = "dialog" },
612       properties = { floating = true,
613                      placement = awful.placement.centered
614                  }
615     },
616
617     { rule = { class = "URxvt" },
618                properties = {
619                    -- floating = false,
620                    size_hints_honor = false
621                } },
622     { rule = { class = "URxvt", instance = "irc" },
623                properties = {
624                    switchtotag = true
625                },
626                callback = move_to_tag(screen.count(), screen.count() == 1 and 2 or 1)
627            },
628     { rule = { class = "Firefox", instance = "Navigator" },
629                properties = {
630                    floating = false,
631                },
632                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
633            },
634     { rule = { class = "Firefox-esr", instance = "Navigator" },
635                properties = {
636                    floating = false,
637                },
638                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
639            },
640     { rule = { class = "Thunderbird", instance = "Mail" },
641                properties = {
642                    floating = false,
643                },
644                callback = move_to_tag(screen.count() == 1 and 1 or 2, 8)
645            },
646     { rule = { class = "Chromium", instance = "chromium" },
647                properties = {
648                    floating = false,
649                },
650                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
651            },
652     { rule = { class = "Gscan2pdf" },
653                properties = {
654                    switchtotag = true
655                },
656                callback = move_to_tag(1, 5)
657            },
658     { rule = { name = "gscan2pdf .*" },
659                properties = {
660                    floating = false,
661                },
662            },
663     { rule = { class = "Thunar", type = "normal" },
664                properties = {
665                    floating = false,
666                },
667            },
668     { rule = { class = "MuPDF", instance = "mupdf" },
669                properties = {
670                    floating = true,
671                },
672            },
673     { rule = { class = "Pinentry", instance = "pinentry" },
674                properties = {
675                    floating = true,
676                },
677            },
678     { rule = { class = "Gxmessage" },
679                properties = {
680                    floating = true,
681                },
682            },
683 }
684 -- }}}
685
686 -- {{{ Signals
687 -- Signal function to execute when a new client appears.
688 client.connect_signal("manage", function (c)
689     -- Set the windows at the slave,
690     -- i.e. put it at the end of others instead of setting it master.
691     if not awesome.startup then awful.client.setslave(c) end
692
693     if awesome.startup and
694       not c.size_hints.user_position
695       and not c.size_hints.program_position then
696         -- Prevent clients from being unreachable after screen count changes.
697         awful.placement.no_offscreen(c)
698     end
699
700     c.maximized_horizontal = false
701     c.maximized_vertical = false
702 end)
703
704 -- Add a titlebar if titlebars_enabled is set to true in the rules.
705 client.connect_signal("request::titlebars", function(c)
706     -- buttons for the titlebar
707     local buttons = gears.table.join(
708         awful.button({ }, 1, function()
709             client.focus = c
710             c:raise()
711             awful.mouse.client.move(c)
712         end),
713         awful.button({ }, 3, function()
714             client.focus = c
715             c:raise()
716             awful.mouse.client.resize(c)
717         end)
718     )
719
720     awful.titlebar(c) : setup {
721         { -- Left
722             awful.titlebar.widget.iconwidget(c),
723             buttons = buttons,
724             layout  = wibox.layout.fixed.horizontal
725         },
726         { -- Middle
727             { -- Title
728                 align  = "center",
729                 widget = awful.titlebar.widget.titlewidget(c)
730             },
731             buttons = buttons,
732             layout  = wibox.layout.flex.horizontal
733         },
734         { -- Right
735             awful.titlebar.widget.floatingbutton (c),
736             awful.titlebar.widget.maximizedbutton(c),
737             awful.titlebar.widget.stickybutton   (c),
738             awful.titlebar.widget.ontopbutton    (c),
739             awful.titlebar.widget.closebutton    (c),
740             layout = wibox.layout.fixed.horizontal()
741         },
742         layout = wibox.layout.align.horizontal
743     }
744 end)
745
746 -- Enable sloppy focus, so that focus follows mouse.
747 client.connect_signal("mouse::enter", function(c)
748     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
749         and awful.client.focus.filter(c) then
750         client.focus = c
751     end
752 end)
753
754 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
755 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
756
757 awful.ewmh.add_activate_filter(function(c, context, hints)
758     if context == "ewmh" and (c.class == "Firefox-esr" or c.class == "Firefox") then return false end
759 end)
760
761 -- vim:ft=lua:sw=4:sts=4:ts=4:et