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:

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