]> git.madduck.net Git - etc/awesome.git/blob - .config/awesome/rc.lua

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:

6f9eae2200d09a620611aa98e333df2d218db03c
[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 -- }}}
18
19 -- {{{ Error handling
20 -- Check if awesome encountered an error during startup and fell back to
21 -- another config (This code will only ever execute for the fallback config)
22 if awesome.startup_errors then
23     naughty.notify({ preset = naughty.config.presets.critical,
24                      title = "Oops, there were errors during startup!",
25                      text = awesome.startup_errors })
26 end
27
28 -- Handle runtime errors after startup
29 do
30     local in_error = false
31     awesome.connect_signal("debug::error", function (err)
32         -- Make sure we don't go into an endless error loop
33         if in_error then return end
34         in_error = true
35
36         naughty.notify({ preset = naughty.config.presets.critical,
37                          title = "Oops, an error happened!",
38                          text = tostring(err) })
39         in_error = false
40     end)
41 end
42 -- }}}
43
44 -- {{{ Variable definitions
45 -- Themes define colours, icons, and wallpapers
46 beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua")
47
48 -- This is used later as the default terminal and editor to run.
49 terminal = "x-terminal-emulator"
50 editor = "sensible-editor"
51 editor_cmd = terminal .. " -e " .. editor
52
53 -- Default modkey.
54 -- Usually, Mod4 is the key with a logo between Control and Alt.
55 -- If you do not like this or do not have such a key,
56 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
57 -- However, you can use another modifier like Mod1, but it may interact with others.
58 modkey = "Mod4"
59 cmdkey = "Mod3"
60
61 -- Table of layouts to cover with awful.layout.inc, order matters.
62 awful.layout.layouts = {
63     awful.layout.suit.fair,
64     awful.layout.suit.tile,
65     -- awful.layout.suit.tile.left,
66     -- awful.layout.suit.tile.bottom,
67     awful.layout.suit.tile.top,
68     -- awful.layout.suit.spiral,
69     -- awful.layout.suit.spiral.dwindle,
70     awful.layout.suit.max,
71     -- awful.layout.suit.max.fullscreen,
72     -- awful.layout.suit.magnifier,
73     -- awful.layout.suit.corner.nw,
74     -- awful.layout.suit.corner.ne,
75     -- awful.layout.suit.corner.sw,
76     -- awful.layout.suit.corner.se,
77     awful.layout.suit.floating,
78 }
79
80 layout_default = awful.layout.layouts[1]
81 layout_tiled = awful.layout.layouts[2]
82 layout_maximised = awful.layout.layouts[4]
83 layout_floating = awful.layout.layouts[5]
84 -- }}}
85
86 -- {{{ Helper functions
87 local function client_menu_toggle_fn()
88     local instance = nil
89
90     return function ()
91         if instance and instance.wibox.visible then
92             instance:hide()
93             instance = nil
94         else
95             instance = awful.menu.clients({ theme = { width = 250 } })
96         end
97     end
98 end
99
100 local function sorted_pairs(t, f)
101     local a = {}
102     for n in pairs(t) do table.insert(a, n) end
103     table.sort(a, f)
104     local i = 0      -- iterator variable
105     local iter = function ()   -- iterator function
106         i = i + 1
107         if a[i] == nil then return nil
108         else return a[i], t[a[i]]
109         end
110     end
111     return iter
112 end
113
114 local function print_table(tbl, indent)
115     if not indent then indent = 0 end
116     for k, v in pairs(tbl) do
117         formatting = string.rep("  ", indent) .. k .. ": "
118         if type(v) == "table" then
119             print(formatting)
120             print_table(v, indent+1)
121         else
122             print(formatting .. tostring(v))
123         end
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 local function poloniex_price(output, pair, prec)
138     local xc, pos, err = dkjson.decode(output, 1, nil)
139     if not prec then prec = 4 end
140     val = (xc and xc[pair]["last"]) or 0
141     val = math.floor(val*10^prec+0.5)/10^prec
142     return (not err and val) or "n/a"
143 end
144
145 local eth_widget = lain.widget.watch({
146     cmd = "curl -m5 -s 'https://poloniex.com/public?command=returnTicker'",
147     timeout = 600,
148     settings = function()
149         widget:set_text(poloniex_price(output, 'BTC_ETH') .. " Ƀ/Ξ")
150     end
151 })
152
153 local function coindesk_price(output, base, prec)
154     local xc, pos, err = dkjson.decode(output, 1, nil)
155     if not prec then prec = 4 end
156     val = (xc and xc["bpi"][base]["rate_float"]) or 0
157     val = math.floor(val*10^prec+0.5)/10^prec
158     return (not err and val) or "n/a"
159 end
160
161 local btc_widget = lain.widget.watch({
162     cmd = "curl -m5 -Ls 'https://api.coindesk.com/v1/bpi/currentprice/EUR.json'",
163     timeout = 600,
164     settings = function()
165         widget:set_text(coindesk_price(output, "EUR", 2) .. " €/Ƀ")
166     end
167 })
168
169 -- }}}
170
171 -- {{{ Menu
172 -- Create a launcher widget and a main menu
173 myawesomemenu = {
174    { "hotkeys", function() return false, hotkeys_popup.show_help end},
175    { "manual", terminal .. " -e man awesome" },
176    { "edit config", editor_cmd .. " " .. awesome.conffile },
177    { "restart", awesome.restart },
178    { "quit", awesome.quit }
179 }
180
181 mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
182                                     { "open terminal", terminal }
183                                   }
184                         })
185
186 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
187                                      menu = mymainmenu })
188 -- }}}
189
190 -- {{{ Menubar configuration
191 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
192 -- }}}
193
194 -- {{{ Wibox
195 local spacer = wibox.widget.textbox()
196 spacer:set_text(' | ')
197 -- Create a textclock widget
198 mytextclock = wibox.widget.textclock("%a %d %b %H:%M:%S", 1)
199
200 -- Create a wibox for each screen and add it
201 mywibox = {}
202 mypromptbox = {}
203 mylayoutbox = {}
204 mytaglist = {}
205 mytaglist.buttons = awful.util.table.join(
206                     awful.button({ }, 1, function(t) t:view_only() end),
207                     awful.button({ modkey }, 1, function(t)
208                                               if client.focus then
209                                                   client.focus:move_to_tag(t)
210                                               end
211                                           end),
212                     awful.button({ }, 3, awful.tag.viewtoggle),
213                     awful.button({ modkey }, 3, function(t)
214                                               if client.focus then
215                                                   client.focus:toggle_tag(t)
216                                               end
217                                           end),
218                     awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
219                     awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
220                 )
221
222 mytasklist = {}
223 mytasklist.buttons = awful.util.table.join(
224                      awful.button({ }, 1, function (c)
225                                               if c == client.focus then
226                                                   -- I don't like click-minimising
227                                                   -- c.minimized = true
228                                               else
229                                                   -- Without this, the following
230                                                   -- :isvisible() makes no sense
231                                                   c.minimized = false
232                                                   if not c:isvisible() and c.first_tag then
233                                                       c.first_tag:view_only()
234                                                   end
235                                                   -- This will also un-minimize
236                                                   -- the client, if needed
237                                                   client.focus = c
238                                                   c:raise()
239                                               end
240                                           end),
241                      awful.button({ }, 3, client_menu_toggle_fn()),
242                      awful.button({ }, 4, function ()
243                                               awful.client.focus.byidx(1)
244                                           end),
245                      awful.button({ }, 5, function ()
246                                               awful.client.focus.byidx(-1)
247                                           end))
248 -- }}}
249
250 -- {{{ Tags
251 tags = {}
252 tags.config = {}
253 tags.config["main"] = {
254     t1 = { layout = layout_default, selected = true },
255     t2 = { layout = layout_default },
256     t3 = { layout = layout_tiled },
257     t4 = { layout = layout_tiled },
258     t5 = { layout = layout_tiled },
259     t6 = { layout = layout_floating },
260     t7 = { layout = layout_maximised },
261     t8 = { layout = layout_maximised },
262     t9 = { layout = layout_maximised },
263 }
264 tags.config["aux"] = {
265     t1 = { layout = layout_default, selected = true },
266     t2 = { layout = layout_default },
267     t3 = { layout = layout_tiled },
268     t4 = { layout = layout_floating },
269     t5 = { layout = layout_floating },
270     t6 = { layout = layout_floating },
271     t7 = { layout = layout_floating },
272     t8 = { layout = layout_floating },
273     t9 = { layout = layout_maximised },
274 }
275
276 screentags = {}
277 screentags[1] = tags.config["main"]
278 if screen.count() == 2 then -- aux screen is on the right
279   screentags[2] = tags.config["aux"]
280 elseif screen.count() == 3 then -- main screen is still #1 in the middle
281   screentags[2] = tags.config["aux"]
282   screentags[3] = tags.config["aux"]
283 end
284
285 awful.screen.connect_for_each_screen(function(s)
286     -- Wallpaper
287     --DISABLED--if beautiful.wallpaper then
288     --DISABLED--    local wallpaper = beautiful.wallpaper
289     --DISABLED--    -- If wallpaper is a function, call it with the screen
290     --DISABLED--    if type(wallpaper) == "function" then
291     --DISABLED--        wallpaper = wallpaper(s)
292     --DISABLED--    end
293     --DISABLED--    gears.wallpaper.maximized(wallpaper, s, true)
294     --DISABLED--end
295
296     if not tags[s.index] then
297         tags[s.index] = {}
298     end
299     for n,p in sorted_pairs(screentags[s.index]) do
300         p["screen"] = s
301         n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
302         table.insert(tags[s.index], awful.tag.add(n, p))
303     end
304
305     -- Create a promptbox for each screen
306     mypromptbox[s] = awful.widget.prompt()
307     -- Create an imagebox widget which will contains an icon indicating which layout we're using.
308     -- We need one layoutbox per screen.
309     mylayoutbox[s] = awful.widget.layoutbox(s)
310     mylayoutbox[s]:buttons(awful.util.table.join(
311                            awful.button({ }, 1, function () awful.layout.inc( 1) end),
312                            awful.button({ }, 3, function () awful.layout.inc(-1) end),
313                            awful.button({ }, 4, function () awful.layout.inc( 1) end),
314                            awful.button({ }, 5, function () awful.layout.inc(-1) end)))
315     -- Create a taglist widget
316     mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
317
318     -- Create a tasklist widget
319     mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
320
321     -- Create the wibox
322     mywibox[s] = awful.wibar({ position = "top", screen = s })
323
324     -- Add widgets to the wibox
325     mywibox[s]:setup {
326         layout = wibox.layout.align.horizontal,
327         { -- Left widgets
328             layout = wibox.layout.fixed.horizontal,
329             -- mylauncher,
330             mytaglist[s],
331             mypromptbox[s],
332         },
333         mytasklist[s], -- Middle widget
334         { -- Right widgets
335             layout = wibox.layout.fixed.horizontal,
336             mykeyboardlayout,
337             wibox.widget.systray(),
338             btc_widget,
339             spacer,
340             lain_bat.widget,
341             spacer,
342             mytextclock,
343             mylayoutbox[s],
344         },
345     }
346 end)
347 -- }}}
348
349 -- {{{ Mouse bindings
350 root.buttons(awful.util.table.join(
351     awful.button({ }, 3, function () mymainmenu:toggle() end),
352     awful.button({ }, 4, awful.tag.viewnext),
353     awful.button({ }, 5, awful.tag.viewprev)
354 ))
355 -- }}}
356
357 -- {{{ Key bindings
358 globalkeys = awful.util.table.join(
359     awful.key({ modkey,           }, "s",      hotkeys_popup.show_help,
360               {description="show help", group="awesome"}),
361     awful.key({ modkey,           }, "Left",   awful.tag.viewprev,
362               {description = "view previous", group = "tag"}),
363     awful.key({ modkey,           }, "Right",  awful.tag.viewnext,
364               {description = "view next", group = "tag"}),
365     awful.key({ modkey,           }, "Escape", awful.tag.history.restore,
366               {description = "go back", group = "tag"}),
367
368     awful.key({ modkey,           }, "k",
369         function ()
370             awful.client.focus.byidx( 1)
371         end,
372         {description = "focus next by index", group = "client"}
373     ),
374     awful.key({ modkey,           }, "j",
375         function ()
376             awful.client.focus.byidx(-1)
377         end,
378         {description = "focus previous by index", group = "client"}
379     ),
380     awful.key({ modkey,           }, "w", function () mymainmenu:show() end,
381               {description = "show main menu", group = "awesome"}),
382
383     -- Layout manipulation
384     awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx(  1)    end,
385               {description = "swap with next client by index", group = "client"}),
386     awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx( -1)    end,
387               {description = "swap with previous client by index", group = "client"}),
388     awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
389               {description = "focus the next screen", group = "screen"}),
390     awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
391               {description = "focus the previous screen", group = "screen"}),
392     awful.key({ modkey,           }, "u", awful.client.urgent.jumpto,
393               {description = "jump to urgent client", group = "client"}),
394     awful.key({ modkey,           }, "Tab",
395         function ()
396             awful.client.focus.history.previous()
397             if client.focus then
398                 client.focus:raise()
399             end
400         end,
401         {description = "go back", group = "client"}),
402
403     -- Standard program
404     awful.key({ modkey,           }, "Return", function () awful.spawn(terminal) end,
405               {description = "open a terminal", group = "launcher"}),
406     awful.key({ modkey, "Control" }, "r", awesome.restart,
407               {description = "reload awesome", group = "awesome"}),
408     awful.key({ modkey, "Shift"   }, "q", awesome.quit,
409               {description = "quit awesome", group = "awesome"}),
410
411     awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)          end,
412               {description = "increase master width factor", group = "layout"}),
413     awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)          end,
414               {description = "decrease master width factor", group = "layout"}),
415     awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1, nil, true) end,
416               {description = "increase the number of master clients", group = "layout"}),
417     awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1, nil, true) end,
418               {description = "decrease the number of master clients", group = "layout"}),
419     awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1, nil, true)    end,
420               {description = "increase the number of columns", group = "layout"}),
421     awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1, nil, true)    end,
422               {description = "decrease the number of columns", group = "layout"}),
423     awful.key({ modkey,           }, "space", function () awful.layout.inc( 1)                end,
424               {description = "select next", group = "layout"}),
425     awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(-1)                end,
426               {description = "select previous", group = "layout"}),
427
428     awful.key({ modkey, "Control" }, "n",
429               function ()
430                   local c = awful.client.restore()
431                   -- Focus restored client
432                   if c then
433                       client.focus = c
434                       c:raise()
435                   end
436               end,
437               {description = "restore minimized", group = "client"}),
438
439     -- Prompt
440     awful.key({ modkey },            "r",     function () mypromptbox[awful.screen.focused()]:run() end,
441               {description = "run prompt", group = "launcher"}),
442
443     awful.key({ modkey }, "x",
444               function ()
445                   awful.prompt.run({ prompt = "Run Lua code: " },
446                   mypromptbox[awful.screen.focused()].widget,
447                   awful.util.eval, nil,
448                   awful.util.get_cache_dir() .. "/history_eval")
449               end,
450               {description = "lua execute prompt", group = "awesome"}),
451     -- Menubar
452     awful.key({ modkey }, "p", function() menubar.show() end,
453               {description = "show the menubar", group = "launcher"})
454 )
455
456 clientkeys = awful.util.table.join(
457     awful.key({ modkey,           }, "f",
458         function (c)
459             c.fullscreen = not c.fullscreen
460             c:raise()
461         end,
462         {description = "toggle fullscreen", group = "client"}),
463     awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end,
464               {description = "close", group = "client"}),
465     awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ,
466               {description = "toggle floating", group = "client"}),
467     awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
468               {description = "move to master", group = "client"}),
469     awful.key({ modkey,           }, "o",      function (c) c:move_to_screen()               end,
470               {description = "move to screen", group = "client"}),
471     awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end,
472               {description = "toggle keep on top", group = "client"}),
473     awful.key({ modkey,           }, "n",
474         function (c)
475             -- The client currently has the input focus, so it cannot be
476             -- minimized, since minimized clients can't have the focus.
477             c.minimized = true
478         end ,
479         {description = "minimize", group = "client"}),
480     awful.key({ modkey,           }, "m",
481         function (c)
482             c.maximized = not c.maximized
483             c:raise()
484         end ,
485         {description = "maximize", group = "client"})
486 )
487
488 -- Bind all key numbers to tags.
489 -- Be careful: we use keycodes to make it works 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 = awful.util.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.
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 = awful.util.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 }
679 -- }}}
680
681 -- {{{ Signals
682 -- Signal function to execute when a new client appears.
683 client.connect_signal("manage", function (c)
684     -- Set the windows at the slave,
685     -- i.e. put it at the end of others instead of setting it master.
686     -- if not awesome.startup then awful.client.setslave(c) end
687
688     if awesome.startup and
689       not c.size_hints.user_position
690       and not c.size_hints.program_position then
691         -- Prevent clients from being unreachable after screen count changes.
692         awful.placement.no_offscreen(c)
693     end
694
695     c.maximized_horizontal = false
696     c.maximized_vertical = false
697 end)
698
699 -- Add a titlebar if titlebars_enabled is set to true in the rules.
700 client.connect_signal("request::titlebars", function(c)
701     -- buttons for the titlebar
702     local buttons = awful.util.table.join(
703         awful.button({ }, 1, function()
704             client.focus = c
705             c:raise()
706             awful.mouse.client.move(c)
707         end),
708         awful.button({ }, 3, function()
709             client.focus = c
710             c:raise()
711             awful.mouse.client.resize(c)
712         end)
713     )
714
715     awful.titlebar(c) : setup {
716         { -- Left
717             awful.titlebar.widget.iconwidget(c),
718             buttons = buttons,
719             layout  = wibox.layout.fixed.horizontal
720         },
721         { -- Middle
722             { -- Title
723                 align  = "center",
724                 widget = awful.titlebar.widget.titlewidget(c)
725             },
726             buttons = buttons,
727             layout  = wibox.layout.flex.horizontal
728         },
729         { -- Right
730             awful.titlebar.widget.floatingbutton (c),
731             awful.titlebar.widget.maximizedbutton(c),
732             awful.titlebar.widget.stickybutton   (c),
733             awful.titlebar.widget.ontopbutton    (c),
734             awful.titlebar.widget.closebutton    (c),
735             layout = wibox.layout.fixed.horizontal()
736         },
737         layout = wibox.layout.align.horizontal
738     }
739 end)
740
741 -- Enable sloppy focus
742 client.connect_signal("mouse::enter", function(c)
743     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
744         and awful.client.focus.filter(c) then
745         client.focus = c
746     end
747 end)
748
749 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
750 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
751
752 awful.ewmh.add_activate_filter(function(c, context, hints)
753     if context == "ewmh" and (c.class == "Firefox-esr" or c.class == "Firefox") then return false end
754 end)
755
756 -- vim:ft=lua:sw=4:sts=4:ts=4:et