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 -- Keyboard map indicator and switcher
153 mykeyboardlayout = awful.widget.keyboardlayout()
155 -- Create a wibox for each screen and add it
160 mytaglist.buttons = awful.util.table.join(
161 awful.button({ }, 1, function(t) t:view_only() end),
162 awful.button({ modkey }, 1, function(t)
164 client.focus:move_to_tag(t)
167 awful.button({ }, 3, awful.tag.viewtoggle),
168 awful.button({ modkey }, 3, function(t)
170 client.focus:toggle_tag(t)
173 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
174 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
178 mytasklist.buttons = awful.util.table.join(
179 awful.button({ }, 1, function (c)
180 if c == client.focus then
183 -- Without this, the following
184 -- :isvisible() makes no sense
186 if not c:isvisible() and c.first_tag then
187 c.first_tag:view_only()
189 -- This will also un-minimize
190 -- the client, if needed
195 awful.button({ }, 3, client_menu_toggle_fn()),
196 awful.button({ }, 4, function ()
197 awful.client.focus.byidx(1)
199 awful.button({ }, 5, function ()
200 awful.client.focus.byidx(-1)
207 tags.config["main"] = {
208 t1 = { layout = layout_default, selected = true },
209 t2 = { layout = layout_default },
210 t3 = { layout = layout_tiled },
211 t4 = { layout = layout_tiled },
212 t5 = { layout = layout_tiled },
213 t6 = { layout = layout_floating },
214 t7 = { layout = layout_maximised },
215 t8 = { layout = layout_maximised },
216 t9 = { layout = layout_maximised },
218 tags.config["aux"] = {
219 t1 = { layout = layout_default, selected = true },
220 t2 = { layout = layout_default },
221 t3 = { layout = layout_tiled },
222 t4 = { layout = layout_floating },
223 t5 = { layout = layout_floating },
224 t6 = { layout = layout_floating },
225 t7 = { layout = layout_floating },
226 t8 = { layout = layout_floating },
227 t9 = { layout = layout_maximised },
231 screentags[1] = tags.config["main"]
232 if screen.count() == 2 then -- aux screen is on the right
233 screentags[2] = tags.config["aux"]
234 elseif screen.count() == 3 then -- main screen is still #1 in the middle
235 screentags[2] = tags.config["aux"]
236 screentags[3] = tags.config["aux"]
239 awful.screen.connect_for_each_screen(function(s)
241 --DISABLED--if beautiful.wallpaper then
242 --DISABLED-- local wallpaper = beautiful.wallpaper
243 --DISABLED-- -- If wallpaper is a function, call it with the screen
244 --DISABLED-- if type(wallpaper) == "function" then
245 --DISABLED-- wallpaper = wallpaper(s)
247 --DISABLED-- gears.wallpaper.maximized(wallpaper, s, true)
250 if not tags[s.index] then
253 for n,p in sorted_pairs(screentags[s.index]) do
255 n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
256 table.insert(tags[s.index], awful.tag.add(n, p))
259 -- Create a promptbox for each screen
260 mypromptbox[s] = awful.widget.prompt()
261 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
262 -- We need one layoutbox per screen.
263 mylayoutbox[s] = awful.widget.layoutbox(s)
264 mylayoutbox[s]:buttons(awful.util.table.join(
265 awful.button({ }, 1, function () awful.layout.inc( 1) end),
266 awful.button({ }, 3, function () awful.layout.inc(-1) end),
267 awful.button({ }, 4, function () awful.layout.inc( 1) end),
268 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
269 -- Create a taglist widget
270 mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
272 -- Create a tasklist widget
273 mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
276 mywibox[s] = awful.wibar({ position = "top", screen = s })
278 -- Add widgets to the wibox
280 layout = wibox.layout.align.horizontal,
282 layout = wibox.layout.fixed.horizontal,
287 mytasklist[s], -- Middle widget
289 layout = wibox.layout.fixed.horizontal,
291 wibox.widget.systray(),
299 -- {{{ Mouse bindings
300 root.buttons(awful.util.table.join(
301 awful.button({ }, 3, function () mymainmenu:toggle() end),
302 awful.button({ }, 4, awful.tag.viewnext),
303 awful.button({ }, 5, awful.tag.viewprev)
308 globalkeys = awful.util.table.join(
309 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
310 {description="show help", group="awesome"}),
311 awful.key({ modkey, }, "Left", awful.tag.viewprev,
312 {description = "view previous", group = "tag"}),
313 awful.key({ modkey, }, "Right", awful.tag.viewnext,
314 {description = "view next", group = "tag"}),
315 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
316 {description = "go back", group = "tag"}),
318 awful.key({ modkey, }, "j",
320 awful.client.focus.byidx( 1)
322 {description = "focus next by index", group = "client"}
324 awful.key({ modkey, }, "k",
326 awful.client.focus.byidx(-1)
328 {description = "focus previous by index", group = "client"}
330 awful.key({ modkey, }, "w", function () mymainmenu:show() end,
331 {description = "show main menu", group = "awesome"}),
333 -- Layout manipulation
334 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
335 {description = "swap with next client by index", group = "client"}),
336 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
337 {description = "swap with previous client by index", group = "client"}),
338 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
339 {description = "focus the next screen", group = "screen"}),
340 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
341 {description = "focus the previous screen", group = "screen"}),
342 awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
343 {description = "jump to urgent client", group = "client"}),
344 awful.key({ modkey, }, "Tab",
346 awful.client.focus.history.previous()
351 {description = "go back", group = "client"}),
354 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
355 {description = "open a terminal", group = "launcher"}),
356 awful.key({ modkey, "Control" }, "r", awesome.restart,
357 {description = "reload awesome", group = "awesome"}),
358 awful.key({ modkey, "Shift" }, "q", awesome.quit,
359 {description = "quit awesome", group = "awesome"}),
361 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
362 {description = "increase master width factor", group = "layout"}),
363 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
364 {description = "decrease master width factor", group = "layout"}),
365 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
366 {description = "increase the number of master clients", group = "layout"}),
367 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
368 {description = "decrease the number of master clients", group = "layout"}),
369 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
370 {description = "increase the number of columns", group = "layout"}),
371 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
372 {description = "decrease the number of columns", group = "layout"}),
373 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
374 {description = "select next", group = "layout"}),
375 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
376 {description = "select previous", group = "layout"}),
378 awful.key({ modkey, "Control" }, "n",
380 local c = awful.client.restore()
381 -- Focus restored client
387 {description = "restore minimized", group = "client"}),
390 awful.key({ modkey }, "r", function () mypromptbox[awful.screen.focused()]:run() end,
391 {description = "run prompt", group = "launcher"}),
393 awful.key({ modkey }, "x",
395 awful.prompt.run({ prompt = "Run Lua code: " },
396 mypromptbox[awful.screen.focused()].widget,
397 awful.util.eval, nil,
398 awful.util.get_cache_dir() .. "/history_eval")
400 {description = "lua execute prompt", group = "awesome"}),
402 awful.key({ modkey }, "p", function() menubar.show() end,
403 {description = "show the menubar", group = "launcher"})
406 clientkeys = awful.util.table.join(
407 awful.key({ modkey, }, "f",
409 c.fullscreen = not c.fullscreen
412 {description = "toggle fullscreen", group = "client"}),
413 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
414 {description = "close", group = "client"}),
415 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
416 {description = "toggle floating", group = "client"}),
417 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
418 {description = "move to master", group = "client"}),
419 awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
420 {description = "move to screen", group = "client"}),
421 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
422 {description = "toggle keep on top", group = "client"}),
423 awful.key({ modkey, }, "n",
425 -- The client currently has the input focus, so it cannot be
426 -- minimized, since minimized clients can't have the focus.
429 {description = "minimize", group = "client"}),
430 awful.key({ modkey, }, "m",
432 c.maximized = not c.maximized
435 {description = "maximize", group = "client"})
438 -- Bind all key numbers to tags.
439 -- Be careful: we use keycodes to make it works on any keyboard layout.
440 -- This should map on the top row of your keyboard, usually 1 to 9.
442 globalkeys = awful.util.table.join(globalkeys,
444 awful.key({ modkey }, "#" .. i + 9,
446 local screen = awful.screen.focused()
447 local tag = screen.tags[i]
452 {description = "view tag #"..i, group = "tag"}),
454 awful.key({ modkey, "Control" }, "#" .. i + 9,
456 local screen = awful.screen.focused()
457 local tag = screen.tags[i]
459 awful.tag.viewtoggle(tag)
462 {description = "toggle tag #" .. i, group = "tag"}),
463 -- Move client to tag.
464 awful.key({ modkey, "Shift" }, "#" .. i + 9,
467 local tag = client.focus.screen.tags[i]
469 client.focus:move_to_tag(tag)
473 {description = "move focused client to tag #"..i, group = "tag"}),
474 -- Toggle tag on focused client.
475 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
478 local tag = client.focus.screen.tags[i]
480 client.focus:toggle_tag(tag)
484 {description = "toggle focused client on tag #" .. i, group = "tag"})
488 clientbuttons = awful.util.table.join(
489 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
490 awful.button({ modkey }, 1, awful.mouse.client.move),
491 awful.button({ modkey }, 3, awful.mouse.client.resize))
494 globalkeys = awful.util.table.join(globalkeys,
495 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
496 awful.key({ cmdkey }, "m", function () awful.spawn("chromium") end),
497 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
498 awful.key({ cmdkey }, "c", function () awful.spawn("icedove") end),
499 awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
500 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
501 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
502 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
503 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),
504 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),
505 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
508 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
509 awful.key(nil, "XF86AudioMute", 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(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
512 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
513 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
514 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
515 awful.key(nil, "XF86Display", function () awful.spawn("") end),
516 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
517 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
518 awful.key(nil, "XF86Search", function () awful.spawn("") end),
519 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
520 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
524 root.keys(globalkeys)
528 -- Rules to apply to new clients (through the "manage" signal).
529 awful.rules.rules = {
530 -- All clients will match this rule.
532 properties = { border_width = beautiful.border_width,
533 border_color = beautiful.border_normal,
534 focus = awful.client.focus.filter,
535 size_hints_honor = false,
538 buttons = clientbuttons,
539 placement = awful.placement.no_overlap+awful.placement.no_offscreen
546 "DTA", -- Firefox addon DownThemAll.
547 "copyq", -- Includes session name in class.
553 "MessageWin", -- kalarm.
561 "Event Tester", -- xev.
564 "AlarmWindow", -- Thunderbird's calendar.
565 "pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
567 }, properties = { floating = true }},
569 -- Add titlebars to normal clients and dialogs
570 { rule_any = {type = { "normal", "dialog" }
571 }, properties = { titlebars_enabled = false }
574 { rule = { class = "URxvt" },
575 properties = { floating = false } },
576 { rule = { class = "URxvt", instance = "irc" },
577 properties = { tag = tags[screen.count()][screen.count() == 1 and 2 or 1] } },
578 { rule = { class = "Firefox", instance = "Navigator" },
579 properties = { tag = tags[screen.count() == 3 and 2 or screen.count()][9] } },
580 { rule = { class = "Icedove", instance = "Mail" },
581 properties = { tag = tags[screen.count() == 3 and 2 or screen.count()][8] } },
582 { rule = { class = "chromium" },
583 properties = { tag = tags[screen.count() == 3 and 2 or screen.count()][9] } }
588 -- Signal function to execute when a new client appears.
589 client.connect_signal("manage", function (c)
590 -- Set the windows at the slave,
591 -- i.e. put it at the end of others instead of setting it master.
592 -- if not awesome.startup then awful.client.setslave(c) end
594 if awesome.startup and
595 not c.size_hints.user_position
596 and not c.size_hints.program_position then
597 -- Prevent clients from being unreachable after screen count changes.
598 awful.placement.no_offscreen(c)
602 -- Add a titlebar if titlebars_enabled is set to true in the rules.
603 client.connect_signal("request::titlebars", function(c)
604 -- buttons for the titlebar
605 local buttons = awful.util.table.join(
606 awful.button({ }, 1, function()
609 awful.mouse.client.move(c)
611 awful.button({ }, 3, function()
614 awful.mouse.client.resize(c)
618 awful.titlebar(c) : setup {
620 awful.titlebar.widget.iconwidget(c),
622 layout = wibox.layout.fixed.horizontal
627 widget = awful.titlebar.widget.titlewidget(c)
630 layout = wibox.layout.flex.horizontal
633 awful.titlebar.widget.floatingbutton (c),
634 awful.titlebar.widget.maximizedbutton(c),
635 awful.titlebar.widget.stickybutton (c),
636 awful.titlebar.widget.ontopbutton (c),
637 awful.titlebar.widget.closebutton (c),
638 layout = wibox.layout.fixed.horizontal()
640 layout = wibox.layout.align.horizontal
644 -- Enable sloppy focus
645 client.connect_signal("mouse::enter", function(c)
646 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
647 and awful.client.focus.filter(c) then
652 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
653 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
656 -- vim:ft=lua:sw=4:sts=4:ts=4:et