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
17 -- Check if awesome encountered an error during startup and fell back to
18 -- another config (This code will only ever execute for the fallback config)
19 if awesome.startup_errors then
20 naughty.notify({ preset = naughty.config.presets.critical,
21 title = "Oops, there were errors during startup!",
22 text = awesome.startup_errors })
25 -- Handle runtime errors after startup
27 local in_error = false
28 awesome.connect_signal("debug::error", function (err)
29 -- Make sure we don't go into an endless error loop
30 if in_error then return end
33 naughty.notify({ preset = naughty.config.presets.critical,
34 title = "Oops, an error happened!",
35 text = tostring(err) })
41 -- {{{ Variable definitions
42 -- Themes define colours, icons, and wallpapers
43 beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua")
45 -- This is used later as the default terminal and editor to run.
46 terminal = "x-terminal-emulator"
47 editor = "sensible-editor"
48 editor_cmd = terminal .. " -e " .. editor
51 -- Usually, Mod4 is the key with a logo between Control and Alt.
52 -- If you do not like this or do not have such a key,
53 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
54 -- However, you can use another modifier like Mod1, but it may interact with others.
58 -- Table of layouts to cover with awful.layout.inc, order matters.
59 awful.layout.layouts = {
60 awful.layout.suit.fair,
61 awful.layout.suit.tile,
62 -- awful.layout.suit.tile.left,
63 -- awful.layout.suit.tile.bottom,
64 awful.layout.suit.tile.top,
65 -- awful.layout.suit.spiral,
66 -- awful.layout.suit.spiral.dwindle,
67 awful.layout.suit.max,
68 -- awful.layout.suit.max.fullscreen,
69 -- awful.layout.suit.magnifier,
70 -- awful.layout.suit.corner.nw,
71 -- awful.layout.suit.corner.ne,
72 -- awful.layout.suit.corner.sw,
73 -- awful.layout.suit.corner.se,
74 awful.layout.suit.floating,
77 layout_default = awful.layout.layouts[1]
78 layout_tiled = awful.layout.layouts[2]
79 layout_maximised = awful.layout.layouts[4]
80 layout_floating = awful.layout.layouts[5]
83 -- {{{ Helper functions
84 local function client_menu_toggle_fn()
88 if instance and instance.wibox.visible then
92 instance = awful.menu.clients({ theme = { width = 250 } })
97 local function sorted_pairs(t, f)
99 for n in pairs(t) do table.insert(a, n) end
101 local i = 0 -- iterator variable
102 local iter = function () -- iterator function
104 if a[i] == nil then return nil
105 else return a[i], t[a[i]]
111 local function print_table(tbl, indent)
112 if not indent then indent = 0 end
113 for k, v in pairs(tbl) do
114 formatting = string.rep(" ", indent) .. k .. ": "
115 if type(v) == "table" then
117 print_table(v, indent+1)
119 print(formatting .. tostring(v))
126 -- Create a launcher widget and a main menu
128 { "hotkeys", function() return false, hotkeys_popup.show_help end},
129 { "manual", terminal .. " -e man awesome" },
130 { "edit config", editor_cmd .. " " .. awesome.conffile },
131 { "restart", awesome.restart },
132 { "quit", awesome.quit }
135 mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
136 { "open terminal", terminal }
140 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
144 -- {{{ Menubar configuration
145 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
149 -- Create a textclock widget
150 mytextclock = wibox.widget.textclock("%a %d %b %H:%M:%S", 1)
152 -- Create a wibox for each screen and add it
157 mytaglist.buttons = awful.util.table.join(
158 awful.button({ }, 1, function(t) t:view_only() end),
159 awful.button({ modkey }, 1, function(t)
161 client.focus:move_to_tag(t)
164 awful.button({ }, 3, awful.tag.viewtoggle),
165 awful.button({ modkey }, 3, function(t)
167 client.focus:toggle_tag(t)
170 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
171 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
175 mytasklist.buttons = awful.util.table.join(
176 awful.button({ }, 1, function (c)
177 if c == client.focus then
178 -- I don't like click-minimising
179 -- c.minimized = true
181 -- Without this, the following
182 -- :isvisible() makes no sense
184 if not c:isvisible() and c.first_tag then
185 c.first_tag:view_only()
187 -- This will also un-minimize
188 -- the client, if needed
193 awful.button({ }, 3, client_menu_toggle_fn()),
194 awful.button({ }, 4, function ()
195 awful.client.focus.byidx(1)
197 awful.button({ }, 5, function ()
198 awful.client.focus.byidx(-1)
205 tags.config["main"] = {
206 t1 = { layout = layout_default, selected = true },
207 t2 = { layout = layout_default },
208 t3 = { layout = layout_tiled },
209 t4 = { layout = layout_tiled },
210 t5 = { layout = layout_tiled },
211 t6 = { layout = layout_floating },
212 t7 = { layout = layout_maximised },
213 t8 = { layout = layout_maximised },
214 t9 = { layout = layout_maximised },
216 tags.config["aux"] = {
217 t1 = { layout = layout_default, selected = true },
218 t2 = { layout = layout_default },
219 t3 = { layout = layout_tiled },
220 t4 = { layout = layout_floating },
221 t5 = { layout = layout_floating },
222 t6 = { layout = layout_floating },
223 t7 = { layout = layout_floating },
224 t8 = { layout = layout_floating },
225 t9 = { layout = layout_maximised },
229 screentags[1] = tags.config["main"]
230 if screen.count() == 2 then -- aux screen is on the right
231 screentags[2] = tags.config["aux"]
232 elseif screen.count() == 3 then -- main screen is still #1 in the middle
233 screentags[2] = tags.config["aux"]
234 screentags[3] = tags.config["aux"]
237 awful.screen.connect_for_each_screen(function(s)
239 --DISABLED--if beautiful.wallpaper then
240 --DISABLED-- local wallpaper = beautiful.wallpaper
241 --DISABLED-- -- If wallpaper is a function, call it with the screen
242 --DISABLED-- if type(wallpaper) == "function" then
243 --DISABLED-- wallpaper = wallpaper(s)
245 --DISABLED-- gears.wallpaper.maximized(wallpaper, s, true)
248 if not tags[s.index] then
251 for n,p in sorted_pairs(screentags[s.index]) do
253 n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
254 table.insert(tags[s.index], awful.tag.add(n, p))
257 -- Create a promptbox for each screen
258 mypromptbox[s] = awful.widget.prompt()
259 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
260 -- We need one layoutbox per screen.
261 mylayoutbox[s] = awful.widget.layoutbox(s)
262 mylayoutbox[s]:buttons(awful.util.table.join(
263 awful.button({ }, 1, function () awful.layout.inc( 1) end),
264 awful.button({ }, 3, function () awful.layout.inc(-1) end),
265 awful.button({ }, 4, function () awful.layout.inc( 1) end),
266 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
267 -- Create a taglist widget
268 mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
270 -- Create a tasklist widget
271 mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
274 mywibox[s] = awful.wibar({ position = "top", screen = s })
276 -- Add widgets to the wibox
278 layout = wibox.layout.align.horizontal,
280 layout = wibox.layout.fixed.horizontal,
285 mytasklist[s], -- Middle widget
287 layout = wibox.layout.fixed.horizontal,
289 wibox.widget.systray(),
297 -- {{{ Mouse bindings
298 root.buttons(awful.util.table.join(
299 awful.button({ }, 3, function () mymainmenu:toggle() end),
300 awful.button({ }, 4, awful.tag.viewnext),
301 awful.button({ }, 5, awful.tag.viewprev)
306 globalkeys = awful.util.table.join(
307 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
308 {description="show help", group="awesome"}),
309 awful.key({ modkey, }, "Left", awful.tag.viewprev,
310 {description = "view previous", group = "tag"}),
311 awful.key({ modkey, }, "Right", awful.tag.viewnext,
312 {description = "view next", group = "tag"}),
313 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
314 {description = "go back", group = "tag"}),
316 awful.key({ modkey, }, "k",
318 awful.client.focus.byidx( 1)
320 {description = "focus next by index", group = "client"}
322 awful.key({ modkey, }, "j",
324 awful.client.focus.byidx(-1)
326 {description = "focus previous by index", group = "client"}
328 awful.key({ modkey, }, "w", function () mymainmenu:show() end,
329 {description = "show main menu", group = "awesome"}),
331 -- Layout manipulation
332 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
333 {description = "swap with next client by index", group = "client"}),
334 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( -1) end,
335 {description = "swap with previous client by index", group = "client"}),
336 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
337 {description = "focus the next screen", group = "screen"}),
338 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
339 {description = "focus the previous screen", group = "screen"}),
340 awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
341 {description = "jump to urgent client", group = "client"}),
342 awful.key({ modkey, }, "Tab",
344 awful.client.focus.history.previous()
349 {description = "go back", group = "client"}),
352 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
353 {description = "open a terminal", group = "launcher"}),
354 awful.key({ modkey, "Control" }, "r", awesome.restart,
355 {description = "reload awesome", group = "awesome"}),
356 awful.key({ modkey, "Shift" }, "q", awesome.quit,
357 {description = "quit awesome", group = "awesome"}),
359 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
360 {description = "increase master width factor", group = "layout"}),
361 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
362 {description = "decrease master width factor", group = "layout"}),
363 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
364 {description = "increase the number of master clients", group = "layout"}),
365 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
366 {description = "decrease the number of master clients", group = "layout"}),
367 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
368 {description = "increase the number of columns", group = "layout"}),
369 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
370 {description = "decrease the number of columns", group = "layout"}),
371 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
372 {description = "select next", group = "layout"}),
373 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
374 {description = "select previous", group = "layout"}),
376 awful.key({ modkey, "Control" }, "n",
378 local c = awful.client.restore()
379 -- Focus restored client
385 {description = "restore minimized", group = "client"}),
388 awful.key({ modkey }, "r", function () mypromptbox[awful.screen.focused()]:run() end,
389 {description = "run prompt", group = "launcher"}),
391 awful.key({ modkey }, "x",
393 awful.prompt.run({ prompt = "Run Lua code: " },
394 mypromptbox[awful.screen.focused()].widget,
395 awful.util.eval, nil,
396 awful.util.get_cache_dir() .. "/history_eval")
398 {description = "lua execute prompt", group = "awesome"}),
400 awful.key({ modkey }, "p", function() menubar.show() end,
401 {description = "show the menubar", group = "launcher"})
404 clientkeys = awful.util.table.join(
405 awful.key({ modkey, }, "f",
407 c.fullscreen = not c.fullscreen
410 {description = "toggle fullscreen", group = "client"}),
411 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
412 {description = "close", group = "client"}),
413 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
414 {description = "toggle floating", group = "client"}),
415 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
416 {description = "move to master", group = "client"}),
417 awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
418 {description = "move to screen", group = "client"}),
419 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
420 {description = "toggle keep on top", group = "client"}),
421 awful.key({ modkey, }, "n",
423 -- The client currently has the input focus, so it cannot be
424 -- minimized, since minimized clients can't have the focus.
427 {description = "minimize", group = "client"}),
428 awful.key({ modkey, }, "m",
430 c.maximized = not c.maximized
433 {description = "maximize", group = "client"})
436 -- Bind all key numbers to tags.
437 -- Be careful: we use keycodes to make it works on any keyboard layout.
438 -- This should map on the top row of your keyboard, usually 1 to 9.
440 globalkeys = awful.util.table.join(globalkeys,
442 awful.key({ modkey }, "#" .. i + 9,
444 local screen = awful.screen.focused()
445 local tag = screen.tags[i]
450 {description = "view tag #"..i, group = "tag"}),
452 awful.key({ modkey, "Control" }, "#" .. i + 9,
454 local screen = awful.screen.focused()
455 local tag = screen.tags[i]
457 awful.tag.viewtoggle(tag)
460 {description = "toggle tag #" .. i, group = "tag"}),
461 -- Move client to tag.
462 awful.key({ modkey, "Shift" }, "#" .. i + 9,
465 local tag = client.focus.screen.tags[i]
467 client.focus:move_to_tag(tag)
471 {description = "move focused client to tag #"..i, group = "tag"}),
472 -- Toggle tag on focused client.
473 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
476 local tag = client.focus.screen.tags[i]
478 client.focus:toggle_tag(tag)
482 {description = "toggle focused client on tag #" .. i, group = "tag"})
486 clientbuttons = awful.util.table.join(
487 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
488 awful.button({ modkey }, 1, awful.mouse.client.move),
489 awful.button({ modkey }, 3, awful.mouse.client.resize))
492 globalkeys = awful.util.table.join(globalkeys,
493 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
494 awful.key({ cmdkey }, "m", function () awful.spawn("chromium") end),
495 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
496 awful.key({ cmdkey }, "c", function () awful.spawn("icedove") end),
497 awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
498 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
499 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
500 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
501 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
502 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),
503 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),
504 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
507 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
508 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
509 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
510 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
511 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
512 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
513 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
514 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
515 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
516 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
517 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
518 awful.key(nil, "XF86Display", function () awful.spawn("") end),
519 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
520 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
521 awful.key(nil, "XF86Search", function () awful.spawn("") end),
522 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
523 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
527 root.keys(globalkeys)
531 -- Rules to apply to new clients (through the "manage" signal).
533 local function move_to_tag(s, t)
535 c:move_to_tag(tags[s][t])
539 awful.rules.rules = {
540 -- All clients will match this rule.
542 properties = { border_width = beautiful.border_width,
543 border_color = beautiful.border_normal,
544 focus = awful.client.focus.filter,
547 buttons = clientbuttons,
548 screen = awful.screen.preferred,
549 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
554 -- Add titlebars to normal clients and dialogs
555 --DISABLED-- { rule_any = {type = { "normal", "dialog" }
556 --DISABLED-- }, properties = { titlebars_enabled = true }
559 { rule = { type = "dialog" },
560 properties = { placement = awful.placement.centered }},
562 { rule = { class = "URxvt" },
565 size_hints_honor = false
567 { rule = { class = "URxvt", instance = "irc" },
571 callback = move_to_tag(screen.count(), screen.count() == 1 and 2 or 1)
573 { rule = { class = "Firefox", instance = "Navigator" },
577 callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
579 { rule = { class = "Icedove", instance = "Mail" },
583 callback = move_to_tag(screen.count() == 1 and 1 or 2, 8)
585 { rule = { class = "Chromium", instance = "chromium" },
589 callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
591 { rule = { class = "Gscan2pdf" },
595 callback = move_to_tag(1, 5)
597 { rule = { name = "gscan2pdf .*" },
602 { rule = { class = "Thunar", type = "normal" },
611 -- Signal function to execute when a new client appears.
612 client.connect_signal("manage", function (c)
613 -- Set the windows at the slave,
614 -- i.e. put it at the end of others instead of setting it master.
615 -- if not awesome.startup then awful.client.setslave(c) end
617 if awesome.startup and
618 not c.size_hints.user_position
619 and not c.size_hints.program_position then
620 -- Prevent clients from being unreachable after screen count changes.
621 awful.placement.no_offscreen(c)
625 -- Add a titlebar if titlebars_enabled is set to true in the rules.
626 client.connect_signal("request::titlebars", function(c)
627 -- buttons for the titlebar
628 local buttons = awful.util.table.join(
629 awful.button({ }, 1, function()
632 awful.mouse.client.move(c)
634 awful.button({ }, 3, function()
637 awful.mouse.client.resize(c)
641 awful.titlebar(c) : setup {
643 awful.titlebar.widget.iconwidget(c),
645 layout = wibox.layout.fixed.horizontal
650 widget = awful.titlebar.widget.titlewidget(c)
653 layout = wibox.layout.flex.horizontal
656 awful.titlebar.widget.floatingbutton (c),
657 awful.titlebar.widget.maximizedbutton(c),
658 awful.titlebar.widget.stickybutton (c),
659 awful.titlebar.widget.ontopbutton (c),
660 awful.titlebar.widget.closebutton (c),
661 layout = wibox.layout.fixed.horizontal()
663 layout = wibox.layout.align.horizontal
667 -- Enable sloppy focus
668 client.connect_signal("mouse::enter", function(c)
669 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
670 and awful.client.focus.filter(c) then
675 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
676 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
678 awful.ewmh.add_activate_filter(function(c, context, hints)
679 if context == "ewmh" and c.class == "Firefox" then return false end
682 -- vim:ft=lua:sw=4:sts=4:ts=4:et