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 -- Tyrannical tab handling
9 --local tyrannical = require("tyrannical")
10 -- Theme handling library
11 local beautiful = require("beautiful")
12 local xrdb = beautiful.xresources
13 -- Notification library
14 local naughty = require("naughty")
15 local menubar = require("menubar")
16 local hotkeys_popup = require("awful.hotkeys_popup").widget
17 -- Enable hotkeys help widget for VIM and other apps
18 -- when client with a matching name is opened:
19 require("awful.hotkeys_popup.keys")
21 -- Load Debian menu entries
22 local debian = require("debian.menu")
23 local has_fdo, freedesktop = pcall(require, "freedesktop")
25 local lain = require("lain")
26 local ccwidgets = require("cryptocoin_widgets")
27 local clocksarray = require("clocksarray")
28 local dbg = require("debugfunc")
29 local th = require("taghelpers")
33 -- Check if awesome encountered an error during startup and fell back to
34 -- another config (This code will only ever execute for the fallback config)
35 if awesome.startup_errors then
36 naughty.notify({ preset = naughty.config.presets.critical,
37 title = "Oops, there were errors during startup!",
38 text = awesome.startup_errors })
41 -- Handle runtime errors after startup
43 local in_error = false
44 awesome.connect_signal("debug::error", function (err)
45 -- Make sure we don't go into an endless error loop
46 if in_error then return end
49 naughty.notify({ preset = naughty.config.presets.critical,
50 title = "Oops, an error happened!",
51 text = tostring(err) })
57 -- {{{ Variable definitions
58 --xrdb.set_dpi(95, screen[1])
59 --xrdb.set_dpi(120, screen[2])
61 -- Themes define colours, icons, font and wallpapers.
62 beautiful.init(gears.filesystem.get_configuration_dir () .. "theme/theme.lua")
64 -- This is used later as the default terminal and editor to run.
65 terminal = "rxvt-unicode"
66 editor = os.getenv("EDITOR") or "editor"
67 editor_cmd = terminal .. " -e " .. editor
70 -- Usually, Mod4 is the key with a logo between Control and Alt.
71 -- If you do not like this or do not have such a key,
72 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
73 -- However, you can use another modifier like Mod1, but it may interact with others.
77 -- Table of layouts to cover with awful.layout.inc, order matters.
79 default = awful.layout.suit.fair,
80 default_horiz = awful.layout.suit.fair.horizontal,
81 tiled = awful.layout.suit.tile,
82 tiled_horiz = awful.layout.suit.tile.top,
83 floating = awful.layout.suit.floating,
84 maximised = awful.layout.suit.max
86 awful.layout.layouts = {
91 layouts.default_horiz,
96 -- {{{ Helper functions
97 local function client_menu_toggle_fn()
101 if instance and instance.wibox.visible then
105 instance = awful.menu.clients({ theme = { width = 250 } })
110 local function set_wallpaper(s)
112 if beautiful.wallpaper then
113 local wallpaper = beautiful.wallpaper
114 -- If wallpaper is a function, call it with the screen
115 if type(wallpaper) == "function" then
116 wallpaper = wallpaper(s)
118 gears.wallpaper.maximized(wallpaper, s, true)
122 local function move_mouse_to_area(a)
123 local coords = mouse.coords()
124 if (coords.x < a.x or
125 coords.x > (a.x+a.width) or
127 coords.y > (a.y+a.height)) then
131 y = a.y + a.height/2,
139 -- Create a launcher widget and a main menu
141 { "hotkeys", function() return false, hotkeys_popup.show_help end},
142 { "manual", terminal .. " -e man awesome" },
143 { "edit config", editor_cmd .. " " .. awesome.conffile },
144 { "restart", awesome.restart },
145 { "quit", function() awesome.quit() end}
148 local menu_awesome = { "awesome", myawesomemenu, beautiful.awesome_icon }
149 local menu_terminal = { "open terminal", terminal }
152 mymainmenu = freedesktop.menu.build({
153 before = { menu_awesome },
154 after = { menu_terminal }
157 mymainmenu = awful.menu({
160 { "Debian", debian.menu.Debian_menu.Debian },
167 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
170 -- Menubar configuration
171 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
175 --local spacer = wibox.widget {
176 -- color = beautiful.bg_minimize,
178 -- widget = wibox.widget.separator
180 local function make_spacer(text)
181 local spacer = wibox.widget.textbox()
182 spacer:set_text(text or " │ ")
186 -- Keyboard map indicator and switcher
187 mykeyboardlayout = awful.widget.keyboardlayout()
189 local lain_bat = lain.widget.bat({
190 batteries = {"BAT0", "BAT1"},
191 settings = function()
193 if bat_now.status == "Charging" then delim = "↑"
194 elseif bat_now.status == "Unknown" then delim = "٭" end
195 widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
199 -- Create a textclock widget
200 clocksarray = clocksarray.get_clocksarray("%a %d %b %H:%M:%S %Z", {
201 ["NZ"] = "Pacific/Auckland",
202 ["DE"] = "Europe/Berlin"
205 -- Create a wibox for each screen and add it
206 local taglist_buttons = gears.table.join(
207 awful.button({ }, 1, function(t) t:view_only() end),
208 awful.button({ modkey }, 1, function(t)
210 client.focus:move_to_tag(t)
213 awful.button({ }, 3, awful.tag.viewtoggle),
214 awful.button({ modkey }, 3, function(t)
216 client.focus:toggle_tag(t)
219 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
220 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
223 local tasklist_buttons = gears.table.join(
224 awful.button({ }, 1, function (c)
225 if c == client.focus then
226 -- I don't like click-minimising
227 -- c.minimized = true
229 -- Without this, the following
230 -- :isvisible() makes no sense
232 if not c:isvisible() and c.first_tag then
233 c.first_tag:view_only()
235 -- This will also un-minimize
236 -- the client, if needed
241 awful.button({ }, 3, client_menu_toggle_fn()),
242 awful.button({ }, 4, function ()
243 awful.client.focus.byidx(1)
245 awful.button({ }, 5, function ()
246 awful.client.focus.byidx(-1)
252 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
253 screen.connect_signal("property::geometry", set_wallpaper)
255 -- {{{ Basic setup for screens
256 local function screen_set_profile(s, profile)
258 s.outputstr = table.concat(gears.table.keys(s.outputs), "+")
259 s.name = s.profile .. "/" .. s.outputstr
262 awful.screen.connect_for_each_screen(function(s)
264 s.set_profile = screen_set_profile
269 -- Create a text widget to display screen name
270 s.namebox = wibox.container.background(wibox.widget.textbox(s.name),
271 beautiful.bg_minimize)
273 -- Create a promptbox for each screen
274 s.mypromptbox = awful.widget.prompt()
275 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
276 -- We need one layoutbox per screen.
277 s.mylayoutbox = awful.widget.layoutbox(s)
278 s.mylayoutbox:buttons(awful.util.table.join(
279 awful.button({ }, 1, function () awful.layout.inc( 1) end),
280 awful.button({ }, 3, function () awful.layout.inc(-1) end),
281 awful.button({ }, 4, function () awful.layout.inc( 1) end),
282 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
283 -- Create a taglist widget
284 s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
286 -- Create a tasklist widget
287 s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
289 -- Create the wibox, but only if there isn't one yet
290 if not s.mywibox then
291 s.mywibox = awful.wibar({ position = "top", screen = s })
294 -- Add widgets to the wibox
295 local right_widgets = gears.table.join(clocksarray, {
297 wibox.widget.systray(),
299 layout = wibox.layout.fixed.horizontal,
302 if s == screen.primary then
303 right_widgets = gears.table.join({
305 ccwidgets.btc_widget,
307 ccwidgets.eth_widget,
315 layout = wibox.layout.align.horizontal,
317 layout = wibox.layout.fixed.horizontal,
323 s.mytasklist, -- Middle widget
328 -- {{{ autorandr integration
329 local function find_screen_by_name(name)
331 if s.name == name then
337 local function get_target_screen_for_tag(tag)
338 local function primary_screen(reason)
339 local s = screen.primary
340 local msg = " → primary screen \"" .. s.name .. "\""
341 if reason then msg = msg .. " (" .. reason .. ")" end
346 print("Figuring out target screen for tag " .. tag.name .. "…")
348 if type(tag.targets) == "table" then
349 for _,target in ipairs(tag.targets) do
350 local s = find_screen_by_name(target)
352 print(" → screen " .. s.name)
356 elseif tag.targets == "primary" then
357 return primary_screen("explicit request")
359 return primary_screen("no matching target in " .. table.concat(tag.targets, ","))
361 return primary_screen("no targets specified")
365 local function move_tag_to_target_screen(tag)
366 tag.screen = get_target_screen_for_tag(tag)
369 local function move_tags_to_target_screens()
370 for _,tag in ipairs(root.tags()) do
371 move_tag_to_target_screen(tag)
375 tag.connect_signal("request::screen", function(t)
376 -- throw the tag onto any other screen, it'll get reassigned later when
377 -- a new profile has been processed.
379 if s ~= t.screen then
386 title = "Screen removed",
387 text = "Salvaged tab " .. t.name .. " onto screen " .. t.screen.name,
391 function handle_new_autorandr_profile(newprofile)
392 -- The main idea here is that autorandr invokes this via awesome-client
393 -- after switching to a new profile. Awesome will have already set up all
394 -- the screens long before this function is called. Therefore, we just do
395 -- the necessary modifications to the existing screens, and move tags
398 if not newprofile then
399 error("Missing new profile name")
403 preset = naughty.config.presets.low,
404 title = "New autorandr profile",
405 text = "Reconfiguring for profile <b>" .. newprofile .. "</b>",
409 s:set_profile(newprofile)
411 move_tags_to_target_screens()
414 local function initialise_to_autorandr_profile()
418 local function process_line(line)
419 if profile then return end
420 local match = string.match(line, "^([^%s]+) %(detected%)")
426 local function output_done()
428 error("autorandr detected no profile")
431 handle_new_autorandr_profile(profile)
434 local function handle_exit(reason, code)
435 if not (reason == "exit" and code == 0) then
436 error("autorandr error: " .. reason .. ": " .. tostring(code))
440 awful.spawn.with_line_callback('autorandr', {
441 stdout = process_line,
442 output_done = output_done,
446 awesome.connect_signal("startup", initialise_to_autorandr_profile)
453 local default_tag = {
456 layout = layouts.default,
460 local default_tags = {}
463 for k,v in pairs(default_tag) do
464 default_tags[i][k] = v
466 default_tags[i].name = tostring(i)
468 default_tags[1].selected = true
470 default_tags = gears.table.join(default_tags, {
475 master_width_factor = 0.33,
476 layout = layouts.tiled,
478 exec_once = { terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi" },
479 instance = { "irc" },
480 targets = { "catalyst/eDP1", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-2" },
486 master_width_factor = 0.67,
487 layout = layouts.tiled,
489 exec_once = { "revolt" },
490 instance = { "Revolt" },
491 targets = { "catalyst/eDP1", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-2" },
497 layout = layouts.floating,
505 layout = layouts.default,
506 exec_once = { "thunderbird" },
507 class = { "Thunderbird" },
508 targets = { "catalyst/HDMI1", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-1" },
514 layout = layouts.default,
515 exec_once = { "chromium" },
516 class = { "Chromium" },
517 targets = { "catalyst/HDMI1", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-1" },
523 layout = layouts.default,
524 exec_once = { "firefox" },
525 class = { "Firefox" },
526 targets = { "catalyst/HDMI1", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-1" },
530 if not tyrannical then
532 for _,t in ipairs(default_tags) do
534 t.screen = t.screen or screen.primary
535 t.layout = t.layout or layouts.default
536 local newt = th.add_tag(t.name, t, false)
540 else -- {{{ tyrannical is loaded
541 tyrannical.settings.default_layout = layouts.default
542 tyrannical.settings.master_width_factor = 0.5
543 tyrannical.settings.block_children_focus_stealing = true
544 tyrannical.settings.group_children = true
546 tyrannical.tags = default_tags
548 tyrannical.properties.size_hints_honor = { URxvt = false }
550 --XX---- Ignore the tag "exclusive" property for the following clients (matched by classes)
551 --XX--tyrannical.properties.intrusive = {
552 --XX-- "ksnapshot" , "pinentry" , "gtksu" , "kcalc" , "xcalc" ,
553 --XX-- "feh" , "Gradient editor", "About KDE" , "Paste Special", "Background color" ,
554 --XX-- "kcolorchooser" , "plasmoidviewer" , "Xephyr" , "kruler" , "plasmaengineexplorer",
557 --XX---- Ignore the tiled layout for the matching clients
558 --XX--tyrannical.properties.floating = {
559 --XX-- "MPlayer" , "pinentry" , "ksnapshot" , "pinentry" , "gtksu" ,
560 --XX-- "xine" , "feh" , "kmix" , "kcalc" , "xcalc" ,
561 --XX-- "yakuake" , "Select Color$" , "kruler" , "kcolorchooser", "Paste Special" ,
562 --XX-- "New Form" , "Insert Picture" , "kcharselect", "mythfrontend" , "plasmoidviewer"
565 --XX---- Make the matching clients (by classes) on top of the default layout
566 --XX--tyrannical.properties.ontop = {
567 --XX-- "Xephyr" , "ksnapshot" , "kruler"
570 --XX---- Force the matching clients (by classes) to be centered on the screen on init
571 --XX--tyrannical.properties.centered = {
578 -- {{{ Mouse bindings
579 root.buttons(gears.table.join(
580 awful.button({ }, 3, function () mymainmenu:toggle() end),
581 awful.button({ }, 4, awful.tag.viewnext),
582 awful.button({ }, 5, awful.tag.viewprev)
588 local function toggle_tag_by_name(tagname, exclusive)
590 local t = awful.tag.find_by_name(nil, tagname)
595 awful.tag.viewtoggle(t)
597 cf = awful.client.getmaster(t.screen)
605 globalkeys = gears.table.join(
606 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
607 {description="show help", group="awesome"}),
608 awful.key({ modkey, }, "Left", awful.tag.viewprev,
609 {description = "view previous", group = "tag"}),
610 awful.key({ modkey, }, "Right", awful.tag.viewnext,
611 {description = "view next", group = "tag"}),
612 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
613 {description = "go back", group = "tag"}),
615 awful.key({ modkey, }, "k",
617 awful.client.focus.byidx( 1)
619 {description = "focus next by index", group = "client"}
621 awful.key({ modkey, }, "j",
623 awful.client.focus.byidx(-1)
625 {description = "focus previous by index", group = "client"}
628 -- Layout manipulation
629 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
630 {description = "swap with next client by index", group = "client"}),
631 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( -1) end,
632 {description = "swap with previous client by index", group = "client"}),
633 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
634 {description = "focus the next screen", group = "screen"}),
635 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
636 {description = "focus the previous screen", group = "screen"}),
637 awful.key({ modkey, "Shift" }, "Return", awful.client.urgent.jumpto,
638 {description = "jump to urgent client", group = "client"}),
639 awful.key({ modkey, }, "Tab",
641 awful.client.focus.history.previous()
646 {description = "go back", group = "client"}),
649 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
650 {description = "open a terminal", group = "launcher"}),
651 awful.key({ modkey, }, "r", function()
652 package.loaded.rc = nil
655 {description = "reload rc.lua", group = "awesome"}),
656 awful.key({ modkey, "Control" }, "r", awesome.restart,
657 {description = "reload awesome", group = "awesome"}),
658 awful.key({ modkey, "Shift" }, "q", awesome.quit,
659 {description = "quit awesome", group = "awesome"}),
661 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
662 {description = "increase master width factor", group = "layout"}),
663 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
664 {description = "decrease master width factor", group = "layout"}),
665 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
666 {description = "increase the number of master clients", group = "layout"}),
667 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
668 {description = "decrease the number of master clients", group = "layout"}),
669 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
670 {description = "increase the number of columns", group = "layout"}),
671 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
672 {description = "decrease the number of columns", group = "layout"}),
673 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
674 {description = "select next", group = "layout"}),
675 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
676 {description = "select previous", group = "layout"}),
678 awful.key({ modkey, "Control" }, "n",
680 local c = awful.client.restore()
681 -- Focus restored client
687 {description = "restore minimized", group = "client"}),
690 awful.key({ cmdkey }, "r",
692 local widget = awful.screen.focused().mypromptbox.widget
693 local function spawn(command, args)
694 gears.debug.dump(args)
695 awful.spawn(command, args)
700 bg_cursor = '#ff0000',
702 history_path = awful.util.get_cache_dir() .. "/history",
703 completion_callback = awful.completion.shell,
705 -- Replace the 'normal' Return with a custom one
706 {{ }, 'Return', function(command)
709 -- Spawn method to spawn in the current tag
710 {{'Mod1' }, 'Return', function(command)
713 tag = mouse.screen.selected_tag
716 -- Spawn in the current tag as floating and on top
717 {{'Shift' }, 'Return', function(command)
721 tag = mouse.screen.selected_tag
724 -- Spawn in a new tag
725 {{'Control'}, 'Return', function(command)
728 layout = layouts.default,
733 {{ }, 'Escape', function(_) return end},
737 {description = "run prompt", group = "launcher"}),
739 awful.key({ modkey }, "x",
743 bg_cursor = '#ff0000',
744 textbox = awful.screen.focused().mypromptbox.widget,
745 exe_callback = awful.util.eval,
746 history_path = awful.util.get_cache_dir() .. "/history_eval"
749 {description = "lua execute prompt", group = "awesome"}),
751 awful.key({ modkey }, "w", function() menubar.show() end,
752 {description = "show the menubar", group = "launcher"}),
755 awful.key({ modkey, }, "a", function()
756 th.add_tag(nil, {layout=layouts.default} ,true)
758 {description = "add a tag", group = "tag"}),
759 awful.key({ modkey, }, "d", th.delete_tag,
760 {description = "delete the current tag", group = "tag"}),
761 awful.key({ modkey, "Shift", }, "a", function()
762 th.move_to_new_tag(nil,nil,true,true,true)
764 {description = "add a volatile tag with the focused client", group = "tag"}),
765 awful.key({ modkey, "Shift", "Control" }, "a", function()
766 th.move_to_new_tag(nil,nil,false,true,true)
768 {description = "add a permanent tag with the focused client", group = "tag"}),
769 awful.key({ modkey, "Mod1" }, "a", th.copy_tag,
770 {description = "create a copy of the current tag", group = "tag"}),
771 awful.key({ modkey, "Control" }, "a", th.rename_tag,
772 {description = "rename the current tag", group = "tag"}),
773 awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
774 {description = "collect all orphaned clients", group = "client"}),
776 awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
777 {description = "view tag 'irc'", group = "tag"}),
778 awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
779 {description = "toggle tag 'irc'", group = "tag"}),
780 awful.key({ modkey }, "u", toggle_tag_by_name("[m]", true),
781 {description = "view tag '[m]'", group = "tag"}),
782 awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[m]"),
783 {description = "toggle tag '[m]'", group = "tag"}),
784 awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
785 {description = "view tag 'cal'", group = "tag"}),
786 awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
787 {description = "toggle tag 'cal'", group = "tag"}),
788 awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
789 {description = "view tag 'chr'", group = "tag"}),
790 awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
791 {description = "toggle tag 'chr'", group = "tag"}),
792 awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
793 {description = "view tag 'ff'", group = "tag"}),
794 awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
795 {description = "toggle tag 'ff'", group = "tag"}),
798 clientkeys = gears.table.join(
799 awful.key({ modkey, }, "f",
801 c.fullscreen = not c.fullscreen
804 {description = "toggle fullscreen", group = "client"}),
805 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
806 {description = "close", group = "client"}),
807 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
808 {description = "toggle floating", group = "client"}),
809 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
810 {description = "move to master", group = "client"}),
811 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
812 {description = "toggle keep on top", group = "client"}),
813 awful.key({ modkey, }, "n",
815 -- The client currently has the input focus, so it cannot be
816 -- minimized, since minimized clients can't have the focus.
819 {description = "minimize", group = "client"}),
820 awful.key({ modkey, }, "m",
822 c.maximized = not c.maximized
823 c.maximized_horizontal = false
824 c.maximized_vertical = false
827 {description = "(un)maximize", group = "client"}),
828 awful.key({ modkey, "Control" }, "m",
830 c.maximized_vertical = not c.maximized_vertical
833 {description = "(un)maximize vertically", group = "client"}),
834 awful.key({ modkey, "Shift" }, "m",
836 c.maximized_horizontal = not c.maximized_horizontal
839 {description = "(un)maximize horizontally", group = "client"})
842 -- Bind all key numbers to tags.
843 -- Be careful: we use keycodes to make it work on any keyboard layout.
844 -- This should map on the top row of your keyboard, usually 1 to 9.
846 globalkeys = gears.table.join(globalkeys,
848 awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
849 {description = "view tag #"..i, group = "tag"}),
850 -- Toggle tag display.
851 awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
852 {description = "toggle tag #" .. i, group = "tag"}),
853 -- Move client to tag.
854 awful.key({ modkey, "Shift" }, "#" .. i + 9,
857 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
859 client.focus:move_to_tag(tag)
863 {description = "move focused client to tag #"..i, group = "tag"}),
864 -- Toggle tag on focused client.
865 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
868 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
870 client.focus:toggle_tag(tag)
874 {description = "toggle focused client on tag #" .. i, group = "tag"})
878 clientbuttons = gears.table.join(
879 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
880 awful.button({ modkey }, 1, awful.mouse.client.move),
881 awful.button({ modkey }, 3, awful.mouse.client.resize))
884 globalkeys = awful.util.table.join(globalkeys,
885 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
886 awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
887 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
888 awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
889 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
890 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
891 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
892 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
893 awful.key({ cmdkey }, "i", function () awful.spawn(terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi") end),
894 awful.key({ cmdkey }, "x", function ()
895 awful.spawn("/usr/bin/xscreensaver -no-capture-stderr")
896 os.execute("sleep 5")
897 awful.spawn("xscreensaver-command -lock")
899 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
902 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
903 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
904 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
905 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
906 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
907 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
908 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
909 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
910 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
911 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
912 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
913 awful.key(nil, "XF86Display", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
914 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
915 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
916 awful.key(nil, "XF86Search", function () awful.spawn("") end),
917 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
918 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
922 root.keys(globalkeys)
926 -- Rules to apply to new clients (through the "manage" signal).
928 local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
929 local wa = client.screen.workarea
931 client.y = wa.y + topbottom
932 client.height = wa.height - 2*topbottom
934 client.y = wa.y + (wa.height - client.height)/2
937 client.x = wa.x + leftright
938 client.width = wa.width - 2*leftright
940 client.x = wa.x + (wa.width - client.width)/2
944 local function move_to_tag_by_name(s, tagname)
946 local t = awful.tag.find_by_name(s, tagname)
948 error("No tag by the name of " .. tagname)
955 awful.rules.rules = {
956 -- All clients will match this rule.
958 properties = { border_width = beautiful.border_width,
959 border_color = beautiful.border_normal,
960 focus = awful.client.focus.filter,
963 buttons = clientbuttons,
964 screen = awful.screen.preferred,
965 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
969 { rule = { type = "dialog" },
970 properties = { floating = true,
975 --switchtotag = true,
976 placement = awful.placement.centered
979 { rule = { class = "URxvt" },
980 properties = { size_hints_honor = false, }
982 { rule = { instance = "irc" },
983 callback = move_to_tag_by_name(nil, "irc"),
985 { rule = { class = "Revolt" },
986 callback = move_to_tag_by_name(nil, "[m]"),
988 { rule = { class = "Firefox" },
989 callback = move_to_tag_by_name(nil, "ffx"),
991 { rule = { class = "Chromium" },
992 callback = move_to_tag_by_name(nil, "chr"),
994 { rule = { class = "Thunderbird" },
995 callback = move_to_tag_by_name(nil, "cal"),
997 { rule_any = { class = {
1003 properties = { floating = true,
1006 placement = awful.placement.centered,
1009 { rule_any = { instance = {
1013 properties = { floating = true,
1016 placement = awful.placement.centered,
1019 -- { rule_any = { class = {
1027 -- properties = { new_tag = {
1028 -- layout = layouts.maximised,
1031 -- switchtotag = true,
1035 --XX-- { rule = { class = "Gscan2pdf" },
1036 --XX-- properties = {
1037 --XX-- switchtotag = true
1039 --XX-- callback = move_to_tag(1, 5)
1041 --XX-- { rule = { name = "gscan2pdf .*" },
1042 --XX-- properties = {
1043 --XX-- floating = false,
1046 --XX-- { rule = { class = "Thunar", type = "normal" },
1047 --XX-- properties = {
1048 --XX-- floating = false,
1051 --XX-- { rule = { class = "Pinentry", instance = "pinentry" },
1052 --XX-- properties = {
1053 --XX-- floating = true,
1056 --XX-- { rule = { class = "Gxmessage" },
1057 --XX-- properties = {
1058 --XX-- floating = true,
1066 -- Signal function to execute when a new client appears.
1067 client.connect_signal("manage", function (c)
1068 -- Set the windows at the slave,
1069 -- i.e. put it at the end of others instead of setting it master.
1070 -- if not awesome.startup then awful.client.setslave(c) end
1072 if awesome.startup and
1073 not c.size_hints.user_position
1074 and not c.size_hints.program_position then
1075 -- Prevent clients from being unreachable after screen count changes.
1076 awful.placement.no_offscreen(c)
1079 c.maximized_horizontal = false
1080 c.maximized_vertical = false
1083 -- Add a titlebar if titlebars_enabled is set to true in the rules.
1084 client.connect_signal("request::titlebars", function(c)
1085 -- buttons for the titlebar
1086 local buttons = gears.table.join(
1087 awful.button({ }, 1, function()
1090 awful.mouse.client.move(c)
1092 awful.button({ }, 3, function()
1095 awful.mouse.client.resize(c)
1099 awful.titlebar(c) : setup {
1101 awful.titlebar.widget.iconwidget(c),
1103 layout = wibox.layout.fixed.horizontal
1108 widget = awful.titlebar.widget.titlewidget(c)
1111 layout = wibox.layout.flex.horizontal
1114 awful.titlebar.widget.floatingbutton (c),
1115 awful.titlebar.widget.maximizedbutton(c),
1116 awful.titlebar.widget.stickybutton (c),
1117 awful.titlebar.widget.ontopbutton (c),
1118 awful.titlebar.widget.closebutton (c),
1119 layout = wibox.layout.fixed.horizontal()
1121 layout = wibox.layout.align.horizontal
1125 -- Enable sloppy focus, so that focus follows mouse.
1126 client.connect_signal("mouse::enter", function(c)
1127 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
1128 and awful.client.focus.filter(c) then
1133 client.connect_signal("focus", function(c)
1134 c.border_color = beautiful.border_focus
1136 client.connect_signal("unfocus", function(c)
1137 c.border_color = beautiful.border_normal
1140 awful.ewmh.add_activate_filter(function(c, context, hints)
1141 if context == "ewmh" then
1142 if (c.class == "Firefox-esr" or c.class == "Firefox") then
1148 client.connect_signal("request::activate", function(c, context, hints)
1149 if gears.table.hasitem({
1150 "client.focus.byidx",
1152 "autofocus.check_focus",
1156 gears.timer.delayed_call(function()
1157 -- we need a delayed call so that we execute *after layout changes
1158 if hints.raise and c == client.focus and client.focus:isvisible() then
1159 move_mouse_to_area(client.focus)
1165 -- vim:ft=lua:sw=4:sts=4:ts=4:et