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.
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")
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 })
26 -- Handle runtime errors after startup
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
34 naughty.notify({ preset = naughty.config.presets.critical,
35 title = "Oops, an error happened!",
36 text = tostring(err) })
42 -- {{{ Variable definitions
43 -- Themes define colours, icons, and wallpapers
44 beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua")
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
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.
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,
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]
84 -- {{{ Helper functions
85 local function client_menu_toggle_fn()
89 if instance and instance.wibox.visible then
93 instance = awful.menu.clients({ theme = { width = 250 } })
98 local function sorted_pairs(t, f)
100 for n in pairs(t) do table.insert(a, n) end
102 local i = 0 -- iterator variable
103 local iter = function () -- iterator function
105 if a[i] == nil then return nil
106 else return a[i], t[a[i]]
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
118 print_table(v, indent+1)
120 print(formatting .. tostring(v))
125 local lain_bat = lain.widgets.bat({
126 batteries = {"BAT0", "BAT1"},
127 settings = function()
129 if bat_now.status == "1" then delim = "↑" end
130 widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
137 -- Create a launcher widget and a main menu
139 { "hotkeys", function() return false, hotkeys_popup.show_help end},
140 { "manual", terminal .. " -e man awesome" },
141 { "edit config", editor_cmd .. " " .. awesome.conffile },
142 { "restart", awesome.restart },
143 { "quit", awesome.quit }
146 mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
147 { "open terminal", terminal }
151 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
155 -- {{{ Menubar configuration
156 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
160 local spacer = wibox.widget.textbox()
161 spacer:set_text(' | ')
162 -- Create a textclock widget
163 mytextclock = wibox.widget.textclock("%a %d %b %H:%M:%S", 1)
165 -- Create a wibox for each screen and add it
170 mytaglist.buttons = awful.util.table.join(
171 awful.button({ }, 1, function(t) t:view_only() end),
172 awful.button({ modkey }, 1, function(t)
174 client.focus:move_to_tag(t)
177 awful.button({ }, 3, awful.tag.viewtoggle),
178 awful.button({ modkey }, 3, function(t)
180 client.focus:toggle_tag(t)
183 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
184 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
188 mytasklist.buttons = awful.util.table.join(
189 awful.button({ }, 1, function (c)
190 if c == client.focus then
191 -- I don't like click-minimising
192 -- c.minimized = true
194 -- Without this, the following
195 -- :isvisible() makes no sense
197 if not c:isvisible() and c.first_tag then
198 c.first_tag:view_only()
200 -- This will also un-minimize
201 -- the client, if needed
206 awful.button({ }, 3, client_menu_toggle_fn()),
207 awful.button({ }, 4, function ()
208 awful.client.focus.byidx(1)
210 awful.button({ }, 5, function ()
211 awful.client.focus.byidx(-1)
218 tags.config["main"] = {
219 t1 = { layout = layout_default, selected = true },
220 t2 = { layout = layout_default },
221 t3 = { layout = layout_tiled },
222 t4 = { layout = layout_tiled },
223 t5 = { layout = layout_tiled },
224 t6 = { layout = layout_floating },
225 t7 = { layout = layout_maximised },
226 t8 = { layout = layout_maximised },
227 t9 = { layout = layout_maximised },
229 tags.config["aux"] = {
230 t1 = { layout = layout_default, selected = true },
231 t2 = { layout = layout_default },
232 t3 = { layout = layout_tiled },
233 t4 = { layout = layout_floating },
234 t5 = { layout = layout_floating },
235 t6 = { layout = layout_floating },
236 t7 = { layout = layout_floating },
237 t8 = { layout = layout_floating },
238 t9 = { layout = layout_maximised },
242 screentags[1] = tags.config["main"]
243 if screen.count() == 2 then -- aux screen is on the right
244 screentags[2] = tags.config["aux"]
245 elseif screen.count() == 3 then -- main screen is still #1 in the middle
246 screentags[2] = tags.config["aux"]
247 screentags[3] = tags.config["aux"]
250 awful.screen.connect_for_each_screen(function(s)
252 --DISABLED--if beautiful.wallpaper then
253 --DISABLED-- local wallpaper = beautiful.wallpaper
254 --DISABLED-- -- If wallpaper is a function, call it with the screen
255 --DISABLED-- if type(wallpaper) == "function" then
256 --DISABLED-- wallpaper = wallpaper(s)
258 --DISABLED-- gears.wallpaper.maximized(wallpaper, s, true)
261 if not tags[s.index] then
264 for n,p in sorted_pairs(screentags[s.index]) do
266 n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
267 table.insert(tags[s.index], awful.tag.add(n, p))
270 -- Create a promptbox for each screen
271 mypromptbox[s] = awful.widget.prompt()
272 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
273 -- We need one layoutbox per screen.
274 mylayoutbox[s] = awful.widget.layoutbox(s)
275 mylayoutbox[s]:buttons(awful.util.table.join(
276 awful.button({ }, 1, function () awful.layout.inc( 1) end),
277 awful.button({ }, 3, function () awful.layout.inc(-1) end),
278 awful.button({ }, 4, function () awful.layout.inc( 1) end),
279 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
280 -- Create a taglist widget
281 mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
283 -- Create a tasklist widget
284 mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
287 mywibox[s] = awful.wibar({ position = "top", screen = s })
289 -- Add widgets to the wibox
291 layout = wibox.layout.align.horizontal,
293 layout = wibox.layout.fixed.horizontal,
298 mytasklist[s], -- Middle widget
300 layout = wibox.layout.fixed.horizontal,
302 wibox.widget.systray(),
312 -- {{{ Mouse bindings
313 root.buttons(awful.util.table.join(
314 awful.button({ }, 3, function () mymainmenu:toggle() end),
315 awful.button({ }, 4, awful.tag.viewnext),
316 awful.button({ }, 5, awful.tag.viewprev)
321 globalkeys = awful.util.table.join(
322 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
323 {description="show help", group="awesome"}),
324 awful.key({ modkey, }, "Left", awful.tag.viewprev,
325 {description = "view previous", group = "tag"}),
326 awful.key({ modkey, }, "Right", awful.tag.viewnext,
327 {description = "view next", group = "tag"}),
328 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
329 {description = "go back", group = "tag"}),
331 awful.key({ modkey, }, "k",
333 awful.client.focus.byidx( 1)
335 {description = "focus next by index", group = "client"}
337 awful.key({ modkey, }, "j",
339 awful.client.focus.byidx(-1)
341 {description = "focus previous by index", group = "client"}
343 awful.key({ modkey, }, "w", function () mymainmenu:show() end,
344 {description = "show main menu", group = "awesome"}),
346 -- Layout manipulation
347 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
348 {description = "swap with next client by index", group = "client"}),
349 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( -1) end,
350 {description = "swap with previous client by index", group = "client"}),
351 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
352 {description = "focus the next screen", group = "screen"}),
353 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
354 {description = "focus the previous screen", group = "screen"}),
355 awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
356 {description = "jump to urgent client", group = "client"}),
357 awful.key({ modkey, }, "Tab",
359 awful.client.focus.history.previous()
364 {description = "go back", group = "client"}),
367 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
368 {description = "open a terminal", group = "launcher"}),
369 awful.key({ modkey, "Control" }, "r", awesome.restart,
370 {description = "reload awesome", group = "awesome"}),
371 awful.key({ modkey, "Shift" }, "q", awesome.quit,
372 {description = "quit awesome", group = "awesome"}),
374 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
375 {description = "increase master width factor", group = "layout"}),
376 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
377 {description = "decrease master width factor", group = "layout"}),
378 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
379 {description = "increase the number of master clients", group = "layout"}),
380 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
381 {description = "decrease the number of master clients", group = "layout"}),
382 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
383 {description = "increase the number of columns", group = "layout"}),
384 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
385 {description = "decrease the number of columns", group = "layout"}),
386 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
387 {description = "select next", group = "layout"}),
388 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
389 {description = "select previous", group = "layout"}),
391 awful.key({ modkey, "Control" }, "n",
393 local c = awful.client.restore()
394 -- Focus restored client
400 {description = "restore minimized", group = "client"}),
403 awful.key({ modkey }, "r", function () mypromptbox[awful.screen.focused()]:run() end,
404 {description = "run prompt", group = "launcher"}),
406 awful.key({ modkey }, "x",
408 awful.prompt.run({ prompt = "Run Lua code: " },
409 mypromptbox[awful.screen.focused()].widget,
410 awful.util.eval, nil,
411 awful.util.get_cache_dir() .. "/history_eval")
413 {description = "lua execute prompt", group = "awesome"}),
415 awful.key({ modkey }, "p", function() menubar.show() end,
416 {description = "show the menubar", group = "launcher"})
419 clientkeys = awful.util.table.join(
420 awful.key({ modkey, }, "f",
422 c.fullscreen = not c.fullscreen
425 {description = "toggle fullscreen", group = "client"}),
426 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
427 {description = "close", group = "client"}),
428 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
429 {description = "toggle floating", group = "client"}),
430 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
431 {description = "move to master", group = "client"}),
432 awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
433 {description = "move to screen", group = "client"}),
434 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
435 {description = "toggle keep on top", group = "client"}),
436 awful.key({ modkey, }, "n",
438 -- The client currently has the input focus, so it cannot be
439 -- minimized, since minimized clients can't have the focus.
442 {description = "minimize", group = "client"}),
443 awful.key({ modkey, }, "m",
445 c.maximized = not c.maximized
448 {description = "maximize", group = "client"})
451 -- Bind all key numbers to tags.
452 -- Be careful: we use keycodes to make it works on any keyboard layout.
453 -- This should map on the top row of your keyboard, usually 1 to 9.
455 globalkeys = awful.util.table.join(globalkeys,
457 awful.key({ modkey }, "#" .. i + 9,
459 local screen = awful.screen.focused()
460 local tag = screen.tags[i]
465 {description = "view tag #"..i, group = "tag"}),
467 awful.key({ modkey, "Control" }, "#" .. i + 9,
469 local screen = awful.screen.focused()
470 local tag = screen.tags[i]
472 awful.tag.viewtoggle(tag)
475 {description = "toggle tag #" .. i, group = "tag"}),
476 -- Move client to tag.
477 awful.key({ modkey, "Shift" }, "#" .. i + 9,
480 local tag = client.focus.screen.tags[i]
482 client.focus:move_to_tag(tag)
486 {description = "move focused client to tag #"..i, group = "tag"}),
487 -- Toggle tag on focused client.
488 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
491 local tag = client.focus.screen.tags[i]
493 client.focus:toggle_tag(tag)
497 {description = "toggle focused client on tag #" .. i, group = "tag"})
501 clientbuttons = awful.util.table.join(
502 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
503 awful.button({ modkey }, 1, awful.mouse.client.move),
504 awful.button({ modkey }, 3, awful.mouse.client.resize))
507 globalkeys = awful.util.table.join(globalkeys,
508 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
509 awful.key({ cmdkey }, "m", function () awful.spawn("chromium") end),
510 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
511 awful.key({ cmdkey }, "c", function () awful.spawn("icedove") end),
512 awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
513 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
514 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
515 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
516 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
517 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),
518 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),
519 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
522 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
523 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
524 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
525 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
526 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
527 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
528 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
529 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
530 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
531 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
532 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
533 awful.key(nil, "XF86Display", function () awful.spawn("") end),
534 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
535 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
536 awful.key(nil, "XF86Search", function () awful.spawn("") end),
537 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
538 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
542 root.keys(globalkeys)
546 -- Rules to apply to new clients (through the "manage" signal).
548 local function move_to_tag(s, t)
550 c:move_to_tag(tags[s][t])
554 awful.rules.rules = {
555 -- All clients will match this rule.
557 properties = { border_width = beautiful.border_width,
558 border_color = beautiful.border_normal,
559 focus = awful.client.focus.filter,
562 buttons = clientbuttons,
563 screen = awful.screen.preferred,
564 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
569 -- Add titlebars to normal clients and dialogs
570 --DISABLED-- { rule_any = {type = { "normal", "dialog" }
571 --DISABLED-- }, properties = { titlebars_enabled = true }
574 { rule = { type = "dialog" },
575 properties = { placement = awful.placement.centered }},
577 { rule = { class = "URxvt" },
580 size_hints_honor = false
582 { rule = { class = "URxvt", instance = "irc" },
586 callback = move_to_tag(screen.count(), screen.count() == 1 and 2 or 1)
588 { rule = { class = "Firefox", instance = "Navigator" },
592 callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
594 { rule = { class = "Icedove", instance = "Mail" },
598 callback = move_to_tag(screen.count() == 1 and 1 or 2, 8)
600 { rule = { class = "Chromium", instance = "chromium" },
604 callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
606 { rule = { class = "Gscan2pdf" },
610 callback = move_to_tag(1, 5)
612 { rule = { name = "gscan2pdf .*" },
617 { rule = { class = "Thunar", type = "normal" },
626 -- Signal function to execute when a new client appears.
627 client.connect_signal("manage", function (c)
628 -- Set the windows at the slave,
629 -- i.e. put it at the end of others instead of setting it master.
630 -- if not awesome.startup then awful.client.setslave(c) end
632 if awesome.startup and
633 not c.size_hints.user_position
634 and not c.size_hints.program_position then
635 -- Prevent clients from being unreachable after screen count changes.
636 awful.placement.no_offscreen(c)
640 -- Add a titlebar if titlebars_enabled is set to true in the rules.
641 client.connect_signal("request::titlebars", function(c)
642 -- buttons for the titlebar
643 local buttons = awful.util.table.join(
644 awful.button({ }, 1, function()
647 awful.mouse.client.move(c)
649 awful.button({ }, 3, function()
652 awful.mouse.client.resize(c)
656 awful.titlebar(c) : setup {
658 awful.titlebar.widget.iconwidget(c),
660 layout = wibox.layout.fixed.horizontal
665 widget = awful.titlebar.widget.titlewidget(c)
668 layout = wibox.layout.flex.horizontal
671 awful.titlebar.widget.floatingbutton (c),
672 awful.titlebar.widget.maximizedbutton(c),
673 awful.titlebar.widget.stickybutton (c),
674 awful.titlebar.widget.ontopbutton (c),
675 awful.titlebar.widget.closebutton (c),
676 layout = wibox.layout.fixed.horizontal()
678 layout = wibox.layout.align.horizontal
682 -- Enable sloppy focus
683 client.connect_signal("mouse::enter", function(c)
684 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
685 and awful.client.focus.filter(c) then
690 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
691 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
693 awful.ewmh.add_activate_filter(function(c, context, hints)
694 if context == "ewmh" and c.class == "Firefox" then return false end
697 -- vim:ft=lua:sw=4:sts=4:ts=4:et