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
180 -- Without this, the following
181 -- :isvisible() makes no sense
183 if not c:isvisible() and c.first_tag then
184 c.first_tag:view_only()
186 -- This will also un-minimize
187 -- the client, if needed
192 awful.button({ }, 3, client_menu_toggle_fn()),
193 awful.button({ }, 4, function ()
194 awful.client.focus.byidx(1)
196 awful.button({ }, 5, function ()
197 awful.client.focus.byidx(-1)
204 tags.config["main"] = {
205 t1 = { layout = layout_default, selected = true },
206 t2 = { layout = layout_default },
207 t3 = { layout = layout_tiled },
208 t4 = { layout = layout_tiled },
209 t5 = { layout = layout_tiled },
210 t6 = { layout = layout_floating },
211 t7 = { layout = layout_maximised },
212 t8 = { layout = layout_maximised },
213 t9 = { layout = layout_maximised },
215 tags.config["aux"] = {
216 t1 = { layout = layout_default, selected = true },
217 t2 = { layout = layout_default },
218 t3 = { layout = layout_tiled },
219 t4 = { layout = layout_floating },
220 t5 = { layout = layout_floating },
221 t6 = { layout = layout_floating },
222 t7 = { layout = layout_floating },
223 t8 = { layout = layout_floating },
224 t9 = { layout = layout_maximised },
228 screentags[1] = tags.config["main"]
229 if screen.count() == 2 then -- aux screen is on the right
230 screentags[2] = tags.config["aux"]
231 elseif screen.count() == 3 then -- main screen is still #1 in the middle
232 screentags[2] = tags.config["aux"]
233 screentags[3] = tags.config["aux"]
236 awful.screen.connect_for_each_screen(function(s)
238 --DISABLED--if beautiful.wallpaper then
239 --DISABLED-- local wallpaper = beautiful.wallpaper
240 --DISABLED-- -- If wallpaper is a function, call it with the screen
241 --DISABLED-- if type(wallpaper) == "function" then
242 --DISABLED-- wallpaper = wallpaper(s)
244 --DISABLED-- gears.wallpaper.maximized(wallpaper, s, true)
247 if not tags[s.index] then
250 for n,p in sorted_pairs(screentags[s.index]) do
252 n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
253 table.insert(tags[s.index], awful.tag.add(n, p))
256 -- Create a promptbox for each screen
257 mypromptbox[s] = awful.widget.prompt()
258 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
259 -- We need one layoutbox per screen.
260 mylayoutbox[s] = awful.widget.layoutbox(s)
261 mylayoutbox[s]:buttons(awful.util.table.join(
262 awful.button({ }, 1, function () awful.layout.inc( 1) end),
263 awful.button({ }, 3, function () awful.layout.inc(-1) end),
264 awful.button({ }, 4, function () awful.layout.inc( 1) end),
265 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
266 -- Create a taglist widget
267 mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
269 -- Create a tasklist widget
270 mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
273 mywibox[s] = awful.wibar({ position = "top", screen = s })
275 -- Add widgets to the wibox
277 layout = wibox.layout.align.horizontal,
279 layout = wibox.layout.fixed.horizontal,
284 mytasklist[s], -- Middle widget
286 layout = wibox.layout.fixed.horizontal,
288 wibox.widget.systray(),
296 -- {{{ Mouse bindings
297 root.buttons(awful.util.table.join(
298 awful.button({ }, 3, function () mymainmenu:toggle() end),
299 awful.button({ }, 4, awful.tag.viewnext),
300 awful.button({ }, 5, awful.tag.viewprev)
305 globalkeys = awful.util.table.join(
306 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
307 {description="show help", group="awesome"}),
308 awful.key({ modkey, }, "Left", awful.tag.viewprev,
309 {description = "view previous", group = "tag"}),
310 awful.key({ modkey, }, "Right", awful.tag.viewnext,
311 {description = "view next", group = "tag"}),
312 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
313 {description = "go back", group = "tag"}),
315 awful.key({ modkey, }, "j",
317 awful.client.focus.byidx( 1)
319 {description = "focus next by index", group = "client"}
321 awful.key({ modkey, }, "k",
323 awful.client.focus.byidx(-1)
325 {description = "focus previous by index", group = "client"}
327 awful.key({ modkey, }, "w", function () mymainmenu:show() end,
328 {description = "show main menu", group = "awesome"}),
330 -- Layout manipulation
331 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
332 {description = "swap with next client by index", group = "client"}),
333 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
334 {description = "swap with previous client by index", group = "client"}),
335 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
336 {description = "focus the next screen", group = "screen"}),
337 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
338 {description = "focus the previous screen", group = "screen"}),
339 awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
340 {description = "jump to urgent client", group = "client"}),
341 awful.key({ modkey, }, "Tab",
343 awful.client.focus.history.previous()
348 {description = "go back", group = "client"}),
351 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
352 {description = "open a terminal", group = "launcher"}),
353 awful.key({ modkey, "Control" }, "r", awesome.restart,
354 {description = "reload awesome", group = "awesome"}),
355 awful.key({ modkey, "Shift" }, "q", awesome.quit,
356 {description = "quit awesome", group = "awesome"}),
358 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
359 {description = "increase master width factor", group = "layout"}),
360 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
361 {description = "decrease master width factor", group = "layout"}),
362 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
363 {description = "increase the number of master clients", group = "layout"}),
364 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
365 {description = "decrease the number of master clients", group = "layout"}),
366 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
367 {description = "increase the number of columns", group = "layout"}),
368 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
369 {description = "decrease the number of columns", group = "layout"}),
370 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
371 {description = "select next", group = "layout"}),
372 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
373 {description = "select previous", group = "layout"}),
375 awful.key({ modkey, "Control" }, "n",
377 local c = awful.client.restore()
378 -- Focus restored client
384 {description = "restore minimized", group = "client"}),
387 awful.key({ modkey }, "r", function () mypromptbox[awful.screen.focused()]:run() end,
388 {description = "run prompt", group = "launcher"}),
390 awful.key({ modkey }, "x",
392 awful.prompt.run({ prompt = "Run Lua code: " },
393 mypromptbox[awful.screen.focused()].widget,
394 awful.util.eval, nil,
395 awful.util.get_cache_dir() .. "/history_eval")
397 {description = "lua execute prompt", group = "awesome"}),
399 awful.key({ modkey }, "p", function() menubar.show() end,
400 {description = "show the menubar", group = "launcher"})
403 clientkeys = awful.util.table.join(
404 awful.key({ modkey, }, "f",
406 c.fullscreen = not c.fullscreen
409 {description = "toggle fullscreen", group = "client"}),
410 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
411 {description = "close", group = "client"}),
412 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
413 {description = "toggle floating", group = "client"}),
414 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
415 {description = "move to master", group = "client"}),
416 awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
417 {description = "move to screen", group = "client"}),
418 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
419 {description = "toggle keep on top", group = "client"}),
420 awful.key({ modkey, }, "n",
422 -- The client currently has the input focus, so it cannot be
423 -- minimized, since minimized clients can't have the focus.
426 {description = "minimize", group = "client"}),
427 awful.key({ modkey, }, "m",
429 c.maximized = not c.maximized
432 {description = "maximize", group = "client"})
435 -- Bind all key numbers to tags.
436 -- Be careful: we use keycodes to make it works on any keyboard layout.
437 -- This should map on the top row of your keyboard, usually 1 to 9.
439 globalkeys = awful.util.table.join(globalkeys,
441 awful.key({ modkey }, "#" .. i + 9,
443 local screen = awful.screen.focused()
444 local tag = screen.tags[i]
449 {description = "view tag #"..i, group = "tag"}),
451 awful.key({ modkey, "Control" }, "#" .. i + 9,
453 local screen = awful.screen.focused()
454 local tag = screen.tags[i]
456 awful.tag.viewtoggle(tag)
459 {description = "toggle tag #" .. i, group = "tag"}),
460 -- Move client to tag.
461 awful.key({ modkey, "Shift" }, "#" .. i + 9,
464 local tag = client.focus.screen.tags[i]
466 client.focus:move_to_tag(tag)
470 {description = "move focused client to tag #"..i, group = "tag"}),
471 -- Toggle tag on focused client.
472 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
475 local tag = client.focus.screen.tags[i]
477 client.focus:toggle_tag(tag)
481 {description = "toggle focused client on tag #" .. i, group = "tag"})
485 clientbuttons = awful.util.table.join(
486 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
487 awful.button({ modkey }, 1, awful.mouse.client.move),
488 awful.button({ modkey }, 3, awful.mouse.client.resize))
491 globalkeys = awful.util.table.join(globalkeys,
492 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
493 awful.key({ cmdkey }, "m", function () awful.spawn("chromium") end),
494 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
495 awful.key({ cmdkey }, "c", function () awful.spawn("icedove") end),
496 awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
497 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
498 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
499 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
500 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),
501 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),
502 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
505 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
506 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
507 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
508 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
509 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
510 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
511 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
512 awful.key(nil, "XF86Display", function () awful.spawn("") end),
513 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
514 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
515 awful.key(nil, "XF86Search", function () awful.spawn("") end),
516 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
517 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
521 root.keys(globalkeys)
525 -- Rules to apply to new clients (through the "manage" signal).
526 awful.rules.rules = {
527 -- All clients will match this rule.
529 properties = { border_width = beautiful.border_width,
530 border_color = beautiful.border_normal,
531 focus = awful.client.focus.filter,
532 size_hints_honor = false,
535 buttons = clientbuttons,
536 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
543 "DTA", -- Firefox addon DownThemAll.
544 "copyq", -- Includes session name in class.
550 "MessageWin", -- kalarm.
558 "Event Tester", -- xev.
561 "AlarmWindow", -- Thunderbird's calendar.
562 "pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
564 }, properties = { floating = true }},
566 -- Add titlebars to normal clients and dialogs
567 --DISABLED-- { rule_any = {type = { "normal", "dialog" }
568 --DISABLED-- }, properties = { titlebars_enabled = true }
571 { rule = { class = "URxvt", instance = "irc" },
572 properties = { screen = screen.count(), tag = screen.count() == 1 and "2" or "1" } },
573 { rule = { class = "Firefox", instance = "Navigator" },
574 properties = { screen = screen.count() == 3 and "2" or "3", tag = "9" } },
575 { rule = { class = "Icedove", instance = "Mail" },
576 properties = { screen = screen.count() == 3 and "2" or "3", tag = "8" } },
577 { rule = { class = "chromium" },
578 properties = { screen = screen.count() == 3 and "2" or "3", tag = "9" } },
579 { rule = { class = "Gscan2pdf", instance = "gscan2pdf" },
580 properties = { screen = 1, tag = "7" } },
585 -- Signal function to execute when a new client appears.
586 client.connect_signal("manage", function (c)
587 -- Set the windows at the slave,
588 -- i.e. put it at the end of others instead of setting it master.
589 -- if not awesome.startup then awful.client.setslave(c) end
591 if awesome.startup and
592 not c.size_hints.user_position
593 and not c.size_hints.program_position then
594 -- Prevent clients from being unreachable after screen count changes.
595 awful.placement.no_offscreen(c)
599 -- Add a titlebar if titlebars_enabled is set to true in the rules.
600 client.connect_signal("request::titlebars", function(c)
601 -- buttons for the titlebar
602 local buttons = awful.util.table.join(
603 awful.button({ }, 1, function()
606 awful.mouse.client.move(c)
608 awful.button({ }, 3, function()
611 awful.mouse.client.resize(c)
615 awful.titlebar(c) : setup {
617 awful.titlebar.widget.iconwidget(c),
619 layout = wibox.layout.fixed.horizontal
624 widget = awful.titlebar.widget.titlewidget(c)
627 layout = wibox.layout.flex.horizontal
630 awful.titlebar.widget.floatingbutton (c),
631 awful.titlebar.widget.maximizedbutton(c),
632 awful.titlebar.widget.stickybutton (c),
633 awful.titlebar.widget.ontopbutton (c),
634 awful.titlebar.widget.closebutton (c),
635 layout = wibox.layout.fixed.horizontal()
637 layout = wibox.layout.align.horizontal
641 -- Enable sloppy focus
642 client.connect_signal("mouse::enter", function(c)
643 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
644 and awful.client.focus.filter(c) then
649 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
650 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
653 -- vim:ft=lua:sw=4:sts=4:ts=4:et