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:

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