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:

fix maximisation
[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.maximized_horizontal = false
484             c.maximized_vertical = false
485             c:raise()
486         end ,
487         {description = "maximize", group = "client"})
488 )
489
490 -- Bind all key numbers to tags.
491 -- Be careful: we use keycodes to make it works on any keyboard layout.
492 -- This should map on the top row of your keyboard, usually 1 to 9.
493 for i = 1, 9 do
494     globalkeys = awful.util.table.join(globalkeys,
495         -- View tag only.
496         awful.key({ modkey }, "#" .. i + 9,
497                   function ()
498                         local screen = awful.screen.focused()
499                         local tag = screen.tags[i]
500                         if tag then
501                            tag:view_only()
502                         end
503                   end,
504                   {description = "view tag #"..i, group = "tag"}),
505         -- Toggle tag.
506         awful.key({ modkey, "Control" }, "#" .. i + 9,
507                   function ()
508                       local screen = awful.screen.focused()
509                       local tag = screen.tags[i]
510                       if tag then
511                          awful.tag.viewtoggle(tag)
512                       end
513                   end,
514                   {description = "toggle tag #" .. i, group = "tag"}),
515         -- Move client to tag.
516         awful.key({ modkey, "Shift" }, "#" .. i + 9,
517                   function ()
518                       if client.focus then
519                           local tag = client.focus.screen.tags[i]
520                           if tag then
521                               client.focus:move_to_tag(tag)
522                           end
523                      end
524                   end,
525                   {description = "move focused client to tag #"..i, group = "tag"}),
526         -- Toggle tag on focused client.
527         awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
528                   function ()
529                       if client.focus then
530                           local tag = client.focus.screen.tags[i]
531                           if tag then
532                               client.focus:toggle_tag(tag)
533                           end
534                       end
535                   end,
536                   {description = "toggle focused client on tag #" .. i, group = "tag"})
537     )
538 end
539
540 clientbuttons = awful.util.table.join(
541     awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
542     awful.button({ modkey }, 1, awful.mouse.client.move),
543     awful.button({ modkey }, 3, awful.mouse.client.resize))
544
545 -- misc apps
546 globalkeys = awful.util.table.join(globalkeys,
547 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
548 awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
549 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
550 awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
551 awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
552 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
553 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
554 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
555 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
556 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),
557 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),
558 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
559
560 -- function keys
561 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
562 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
563 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
564 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
565 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
566 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
567 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
568 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
569 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
570 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
571 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
572 awful.key(nil, "XF86Display", function () awful.spawn("") end),
573 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
574 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
575 awful.key(nil, "XF86Search", function () awful.spawn("") end),
576 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
577 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
578 )
579
580 -- Set keys
581 root.keys(globalkeys)
582 -- }}}
583
584 -- {{{ Rules
585 -- Rules to apply to new clients (through the "manage" signal).
586
587 local function move_to_tag(s, t)
588     return function(c)
589         c:move_to_tag(tags[s][t])
590     end
591 end
592
593 awful.rules.rules = {
594     -- All clients will match this rule.
595     { rule = { },
596       properties = { border_width = beautiful.border_width,
597                      border_color = beautiful.border_normal,
598                      focus = awful.client.focus.filter,
599                      raise = true,
600                      keys = clientkeys,
601                      buttons = clientbuttons,
602                      screen = awful.screen.preferred,
603                      placement = awful.placement.no_overlap+awful.placement.no_offscreen,
604                      floating = false
605                  },
606     },
607
608     -- Add titlebars to normal clients and dialogs
609     --DISABLED-- { rule_any = {type = { "normal", "dialog" }
610     --DISABLED--  }, properties = { titlebars_enabled = true }
611     --DISABLED-- },
612
613     { rule = { type = "dialog" },
614       properties = { floating = true,
615                      placement = awful.placement.centered
616                  }
617     },
618
619     { rule = { class = "URxvt" },
620                properties = {
621                    floating = false,
622                    size_hints_honor = false
623                } },
624     { rule = { class = "URxvt", instance = "irc" },
625                properties = {
626                    switchtotag = true
627                },
628                callback = move_to_tag(screen.count(), screen.count() == 1 and 2 or 1)
629            },
630     { rule = { class = "Firefox", instance = "Navigator" },
631                properties = {
632                    floating = false,
633                },
634                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
635            },
636     { rule = { class = "Firefox-esr", instance = "Navigator" },
637                properties = {
638                    floating = false,
639                },
640                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
641            },
642     { rule = { class = "Thunderbird", instance = "Mail" },
643                properties = {
644                    floating = false,
645                },
646                callback = move_to_tag(screen.count() == 1 and 1 or 2, 8)
647            },
648     { rule = { class = "Chromium", instance = "chromium" },
649                properties = {
650                    floating = false,
651                },
652                callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
653            },
654     { rule = { class = "Gscan2pdf" },
655                properties = {
656                    switchtotag = true
657                },
658                callback = move_to_tag(1, 5)
659            },
660     { rule = { name = "gscan2pdf .*" },
661                properties = {
662                    floating = false,
663                },
664            },
665     { rule = { class = "Thunar", type = "normal" },
666                properties = {
667                    floating = false,
668                },
669            },
670     { rule = { class = "MuPDF", instance = "mupdf" },
671                properties = {
672                    floating = true,
673                },
674            },
675     { rule = { class = "Pinentry", instance = "pinentry" },
676                properties = {
677                    floating = true,
678                },
679            },
680 }
681 -- }}}
682
683 -- {{{ Signals
684 -- Signal function to execute when a new client appears.
685 client.connect_signal("manage", function (c)
686     -- Set the windows at the slave,
687     -- i.e. put it at the end of others instead of setting it master.
688     -- if not awesome.startup then awful.client.setslave(c) end
689
690     if awesome.startup and
691       not c.size_hints.user_position
692       and not c.size_hints.program_position then
693         -- Prevent clients from being unreachable after screen count changes.
694         awful.placement.no_offscreen(c)
695     end
696
697     c.maximized_horizontal = false
698     c.maximized_vertical = false
699 end)
700
701 -- Add a titlebar if titlebars_enabled is set to true in the rules.
702 client.connect_signal("request::titlebars", function(c)
703     -- buttons for the titlebar
704     local buttons = awful.util.table.join(
705         awful.button({ }, 1, function()
706             client.focus = c
707             c:raise()
708             awful.mouse.client.move(c)
709         end),
710         awful.button({ }, 3, function()
711             client.focus = c
712             c:raise()
713             awful.mouse.client.resize(c)
714         end)
715     )
716
717     awful.titlebar(c) : setup {
718         { -- Left
719             awful.titlebar.widget.iconwidget(c),
720             buttons = buttons,
721             layout  = wibox.layout.fixed.horizontal
722         },
723         { -- Middle
724             { -- Title
725                 align  = "center",
726                 widget = awful.titlebar.widget.titlewidget(c)
727             },
728             buttons = buttons,
729             layout  = wibox.layout.flex.horizontal
730         },
731         { -- Right
732             awful.titlebar.widget.floatingbutton (c),
733             awful.titlebar.widget.maximizedbutton(c),
734             awful.titlebar.widget.stickybutton   (c),
735             awful.titlebar.widget.ontopbutton    (c),
736             awful.titlebar.widget.closebutton    (c),
737             layout = wibox.layout.fixed.horizontal()
738         },
739         layout = wibox.layout.align.horizontal
740     }
741 end)
742
743 -- Enable sloppy focus
744 client.connect_signal("mouse::enter", function(c)
745     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
746         and awful.client.focus.filter(c) then
747         client.focus = c
748     end
749 end)
750
751 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
752 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
753
754 awful.ewmh.add_activate_filter(function(c, context, hints)
755     if context == "ewmh" and (c.class == "Firefox-esr" or c.class == "Firefox") then return false end
756 end)
757
758 -- vim:ft=lua:sw=4:sts=4:ts=4:et