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 tiled = awful.layout.suit.tile,
81 floating = awful.layout.suit.floating,
82 maximised = awful.layout.suit.max
84 awful.layout.layouts = {
92 -- {{{ Helper functions
93 local function client_menu_toggle_fn()
97 if instance and instance.wibox.visible then
101 instance = awful.menu.clients({ theme = { width = 250 } })
106 local function set_wallpaper(s)
108 if beautiful.wallpaper then
109 local wallpaper = beautiful.wallpaper
110 -- If wallpaper is a function, call it with the screen
111 if type(wallpaper) == "function" then
112 wallpaper = wallpaper(s)
114 gears.wallpaper.maximized(wallpaper, s, true)
118 local function move_mouse_to_area(a)
119 local coords = mouse.coords()
120 if (coords.x < a.x or
121 coords.x > (a.x+a.width) or
123 coords.y > (a.y+a.height)) then
127 y = a.y + a.height/2,
135 -- Create a launcher widget and a main menu
137 { "hotkeys", function() return false, hotkeys_popup.show_help end},
138 { "manual", terminal .. " -e man awesome" },
139 { "edit config", editor_cmd .. " " .. awesome.conffile },
140 { "restart", awesome.restart },
141 { "quit", function() awesome.quit() end}
144 local menu_awesome = { "awesome", myawesomemenu, beautiful.awesome_icon }
145 local menu_terminal = { "open terminal", terminal }
148 mymainmenu = freedesktop.menu.build({
149 before = { menu_awesome },
150 after = { menu_terminal }
153 mymainmenu = awful.menu({
156 { "Debian", debian.menu.Debian_menu.Debian },
163 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
166 -- Menubar configuration
167 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
171 --local spacer = wibox.widget {
172 -- color = beautiful.bg_minimize,
174 -- widget = wibox.widget.separator
176 local function make_spacer(text)
177 local spacer = wibox.widget.textbox()
178 spacer:set_text(text or " │ ")
182 -- Keyboard map indicator and switcher
183 mykeyboardlayout = awful.widget.keyboardlayout()
185 local lain_bat = lain.widget.bat({
186 batteries = {"BAT0", "BAT1"},
187 settings = function()
189 if bat_now.status == "Charging" then delim = "↑"
190 elseif bat_now.status == "Unknown" then delim = "٭" end
191 widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
195 -- Create a textclock widget
196 clocksarray = clocksarray.get_clocksarray("%a %d %b %H:%M:%S %Z", {
197 ["NZ"] = "Pacific/Auckland",
198 ["DE"] = "Europe/Berlin"
201 -- Create a wibox for each screen and add it
202 local taglist_buttons = gears.table.join(
203 awful.button({ }, 1, function(t) t:view_only() end),
204 awful.button({ modkey }, 1, function(t)
206 client.focus:move_to_tag(t)
209 awful.button({ }, 3, awful.tag.viewtoggle),
210 awful.button({ modkey }, 3, function(t)
212 client.focus:toggle_tag(t)
215 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
216 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
219 local tasklist_buttons = gears.table.join(
220 awful.button({ }, 1, function (c)
221 if c == client.focus then
222 -- I don't like click-minimising
223 -- c.minimized = true
225 -- Without this, the following
226 -- :isvisible() makes no sense
228 if not c:isvisible() and c.first_tag then
229 c.first_tag:view_only()
231 -- This will also un-minimize
232 -- the client, if needed
237 awful.button({ }, 3, client_menu_toggle_fn()),
238 awful.button({ }, 4, function ()
239 awful.client.focus.byidx(1)
241 awful.button({ }, 5, function ()
242 awful.client.focus.byidx(-1)
248 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
249 screen.connect_signal("property::geometry", set_wallpaper)
251 -- {{{ Basic setup for screens
252 local function screen_set_profile(s, profile)
254 s.outputstr = table.concat(gears.table.keys(s.outputs), "+")
255 s.name = s.profile .. "/" .. s.outputstr
258 awful.screen.connect_for_each_screen(function(s)
260 s.set_profile = screen_set_profile
265 -- Create a text widget to display screen name
266 s.namebox = wibox.container.background(wibox.widget.textbox(s.name),
267 beautiful.bg_minimize)
269 -- Create a promptbox for each screen
270 s.mypromptbox = awful.widget.prompt()
271 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
272 -- We need one layoutbox per screen.
273 s.mylayoutbox = awful.widget.layoutbox(s)
274 s.mylayoutbox:buttons(awful.util.table.join(
275 awful.button({ }, 1, function () awful.layout.inc( 1) end),
276 awful.button({ }, 3, function () awful.layout.inc(-1) end),
277 awful.button({ }, 4, function () awful.layout.inc( 1) end),
278 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
279 -- Create a taglist widget
280 s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
282 -- Create a tasklist widget
283 s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
285 -- Create the wibox, but only if there isn't one yet
286 if not s.mywibox then
287 s.mywibox = awful.wibar({ position = "top", screen = s })
290 -- Add widgets to the wibox
291 local right_widgets = gears.table.join(clocksarray, {
293 wibox.widget.systray(),
295 layout = wibox.layout.fixed.horizontal,
298 if s == screen.primary then
299 right_widgets = gears.table.join({
301 ccwidgets.btc_widget,
303 ccwidgets.eth_widget,
311 layout = wibox.layout.align.horizontal,
313 layout = wibox.layout.fixed.horizontal,
319 s.mytasklist, -- Middle widget
324 -- {{{ autorandr integration
325 local function find_screen_by_name(name)
327 if s.name == name then
333 local function get_target_screen_for_tag(tag)
334 local function primary_screen(reason)
335 local s = screen.primary
336 local msg = " → primary screen \"" .. s.name .. "\""
337 if reason then msg = msg .. " (" .. reason .. ")" end
342 print("Figuring out target screen for tag " .. tag.name .. "…")
344 if type(tag.targets) == "table" then
345 for _,target in ipairs(tag.targets) do
346 local s = find_screen_by_name(target)
348 print(" → screen " .. s.name)
352 elseif tag.targets == "primary" then
353 return primary_screen("explicit request")
355 return primary_screen("no matching target in " .. table.concat(tag.targets, ","))
357 return primary_screen("no targets specified")
361 local function move_tag_to_target_screen(tag)
362 tag.screen = get_target_screen_for_tag(tag)
365 local function move_tags_to_target_screens()
366 for _,tag in ipairs(root.tags()) do
367 move_tag_to_target_screen(tag)
371 tag.connect_signal("request::screen", function(t)
372 -- throw the tag onto any other screen, it'll get reassigned later when
373 -- a new profile has been processed.
375 if s ~= t.screen then
382 title = "Screen removed",
383 text = "Salvaged tab " .. t.name .. " onto screen " .. t.screen.name,
387 function handle_new_autorandr_profile(newprofile)
388 -- The main idea here is that autorandr invokes this via awesome-client
389 -- after switching to a new profile. Awesome will have already set up all
390 -- the screens long before this function is called. Therefore, we just do
391 -- the necessary modifications to the existing screens, and move tags
394 if not newprofile then
395 error("Missing new profile name")
399 preset = naughty.config.presets.low,
400 title = "New autorandr profile",
401 text = "Reconfiguring for profile <b>" .. newprofile .. "</b>",
405 s:set_profile(newprofile)
407 move_tags_to_target_screens()
410 local function initialise_to_autorandr_profile()
413 local function process_line(line)
414 if profile then return end
415 local match = string.match(line, "^([^%s]+) %(detected%)$")
421 local function output_done()
423 error("autorandr detected no profile")
426 handle_new_autorandr_profile(profile)
429 local function handle_exit(reason, code)
430 if not (reason == "exit" and code == 0) then
431 error("autorandr error: " .. reason .. ": " .. tostring(code))
435 awful.spawn.with_line_callback('autorandr', {
436 stderr = process_line,
437 output_done = output_done,
441 awesome.connect_signal("startup", initialise_to_autorandr_profile)
448 local default_tag = {
451 layout = layouts.default,
455 local default_tags = {}
458 for k,v in pairs(default_tag) do
459 default_tags[i][k] = v
461 default_tags[i].name = tostring(i)
463 default_tags[1].selected = true
465 default_tags = gears.table.join(default_tags, {
470 master_width_factor = 0.33,
471 layout = layouts.tiled,
473 exec_once = { terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi" },
474 instance = { "irc" },
475 targets = { "catalyst/eDP1", "mtvic/eDP1" },
481 master_width_factor = 0.67,
482 layout = layouts.tiled,
484 exec_once = { "revolt" },
485 instance = { "Revolt" },
486 targets = { "catalyst/eDP1", "mtvic/eDP1" },
492 layout = layouts.floating,
500 layout = layouts.default,
501 exec_once = { "thunderbird" },
502 class = { "Thunderbird" },
503 targets = { "catalyst/HDMI1", "mtvic/eDP1" },
509 layout = layouts.default,
510 exec_once = { "chromium" },
511 class = { "Chromium" },
512 targets = { "catalyst/HDMI1", "mtvic/eDP1" },
518 layout = layouts.default,
519 exec_once = { "firefox" },
520 class = { "Firefox" },
521 targets = { "catalyst/HDMI1", "mtvic/eDP1" },
525 if not tyrannical then
527 for _,t in ipairs(default_tags) do
529 t.screen = t.screen or screen.primary
530 t.layout = t.layout or layouts.default
531 local newt = th.add_tag(t.name, t, false)
535 else -- {{{ tyrannical is loaded
536 tyrannical.settings.default_layout = layouts.default
537 tyrannical.settings.master_width_factor = 0.5
538 tyrannical.settings.block_children_focus_stealing = true
539 tyrannical.settings.group_children = true
541 tyrannical.tags = default_tags
543 tyrannical.properties.size_hints_honor = { URxvt = false }
545 --XX---- Ignore the tag "exclusive" property for the following clients (matched by classes)
546 --XX--tyrannical.properties.intrusive = {
547 --XX-- "ksnapshot" , "pinentry" , "gtksu" , "kcalc" , "xcalc" ,
548 --XX-- "feh" , "Gradient editor", "About KDE" , "Paste Special", "Background color" ,
549 --XX-- "kcolorchooser" , "plasmoidviewer" , "Xephyr" , "kruler" , "plasmaengineexplorer",
552 --XX---- Ignore the tiled layout for the matching clients
553 --XX--tyrannical.properties.floating = {
554 --XX-- "MPlayer" , "pinentry" , "ksnapshot" , "pinentry" , "gtksu" ,
555 --XX-- "xine" , "feh" , "kmix" , "kcalc" , "xcalc" ,
556 --XX-- "yakuake" , "Select Color$" , "kruler" , "kcolorchooser", "Paste Special" ,
557 --XX-- "New Form" , "Insert Picture" , "kcharselect", "mythfrontend" , "plasmoidviewer"
560 --XX---- Make the matching clients (by classes) on top of the default layout
561 --XX--tyrannical.properties.ontop = {
562 --XX-- "Xephyr" , "ksnapshot" , "kruler"
565 --XX---- Force the matching clients (by classes) to be centered on the screen on init
566 --XX--tyrannical.properties.centered = {
573 -- {{{ Mouse bindings
574 root.buttons(gears.table.join(
575 awful.button({ }, 3, function () mymainmenu:toggle() end),
576 awful.button({ }, 4, awful.tag.viewnext),
577 awful.button({ }, 5, awful.tag.viewprev)
583 local function toggle_tag_by_name(tagname, exclusive)
585 local t = awful.tag.find_by_name(nil, tagname)
590 awful.tag.viewtoggle(t)
592 cf = awful.client.getmaster(t.screen)
600 globalkeys = gears.table.join(
601 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
602 {description="show help", group="awesome"}),
603 awful.key({ modkey, }, "Left", awful.tag.viewprev,
604 {description = "view previous", group = "tag"}),
605 awful.key({ modkey, }, "Right", awful.tag.viewnext,
606 {description = "view next", group = "tag"}),
607 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
608 {description = "go back", group = "tag"}),
610 awful.key({ modkey, }, "k",
612 awful.client.focus.byidx( 1)
614 {description = "focus next by index", group = "client"}
616 awful.key({ modkey, }, "j",
618 awful.client.focus.byidx(-1)
620 {description = "focus previous by index", group = "client"}
623 -- Layout manipulation
624 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
625 {description = "swap with next client by index", group = "client"}),
626 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( -1) end,
627 {description = "swap with previous client by index", group = "client"}),
628 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
629 {description = "focus the next screen", group = "screen"}),
630 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
631 {description = "focus the previous screen", group = "screen"}),
632 awful.key({ modkey, "Shift" }, "Return", awful.client.urgent.jumpto,
633 {description = "jump to urgent client", group = "client"}),
634 awful.key({ modkey, }, "Tab",
636 awful.client.focus.history.previous()
641 {description = "go back", group = "client"}),
644 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
645 {description = "open a terminal", group = "launcher"}),
646 awful.key({ modkey, }, "r", function()
647 package.loaded.rc = nil
650 {description = "reload rc.lua", group = "awesome"}),
651 awful.key({ modkey, "Control" }, "r", awesome.restart,
652 {description = "reload awesome", group = "awesome"}),
653 awful.key({ modkey, "Shift" }, "q", awesome.quit,
654 {description = "quit awesome", group = "awesome"}),
656 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
657 {description = "increase master width factor", group = "layout"}),
658 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
659 {description = "decrease master width factor", group = "layout"}),
660 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
661 {description = "increase the number of master clients", group = "layout"}),
662 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
663 {description = "decrease the number of master clients", group = "layout"}),
664 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
665 {description = "increase the number of columns", group = "layout"}),
666 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
667 {description = "decrease the number of columns", group = "layout"}),
668 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
669 {description = "select next", group = "layout"}),
670 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
671 {description = "select previous", group = "layout"}),
673 awful.key({ modkey, "Control" }, "n",
675 local c = awful.client.restore()
676 -- Focus restored client
682 {description = "restore minimized", group = "client"}),
685 awful.key({ cmdkey }, "r",
687 local widget = awful.screen.focused().mypromptbox.widget
688 local function spawn(command, args)
689 gears.debug.dump(args)
690 awful.spawn(command, args)
695 bg_cursor = '#ff0000',
697 history_path = awful.util.get_cache_dir() .. "/history",
699 -- Replace the 'normal' Return with a custom one
700 {{ }, 'Return', function(command)
703 -- Spawn method to spawn in the current tag
704 {{'Mod1' }, 'Return', function(command)
707 tag = mouse.screen.selected_tag
710 -- Spawn in the current tag as floating and on top
711 {{'Shift' }, 'Return', function(command)
715 tag = mouse.screen.selected_tag
718 -- Spawn in a new tag
719 {{'Control'}, 'Return', function(command)
722 layout = layouts.default,
727 {{ }, 'Escape', function(_) return end},
731 {description = "run prompt", group = "launcher"}),
733 awful.key({ modkey }, "x",
737 bg_cursor = '#ff0000',
738 textbox = awful.screen.focused().mypromptbox.widget,
739 exe_callback = awful.util.eval,
740 history_path = awful.util.get_cache_dir() .. "/history_eval"
743 {description = "lua execute prompt", group = "awesome"}),
745 awful.key({ modkey }, "w", function() menubar.show() end,
746 {description = "show the menubar", group = "launcher"}),
749 awful.key({ modkey, }, "a", function()
750 th.add_tag(nil, {layout=layouts.default} ,true)
752 {description = "add a tag", group = "tag"}),
753 awful.key({ modkey, }, "d", th.delete_tag,
754 {description = "delete the current tag", group = "tag"}),
755 awful.key({ modkey, "Shift", }, "a", function()
756 th.move_to_new_tag(nil,nil,true,true,true)
758 {description = "add a volatile tag with the focused client", group = "tag"}),
759 awful.key({ modkey, "Shift", "Control" }, "a", function()
760 th.move_to_new_tag(nil,nil,false,true,true)
762 {description = "add a permanent tag with the focused client", group = "tag"}),
763 awful.key({ modkey, "Mod1" }, "a", th.copy_tag,
764 {description = "create a copy of the current tag", group = "tag"}),
765 awful.key({ modkey, "Control" }, "a", th.rename_tag,
766 {description = "rename the current tag", group = "tag"}),
767 awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
768 {description = "collect all orphaned clients", group = "client"}),
770 awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
771 {description = "view tag 'irc'", group = "tag"}),
772 awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
773 {description = "toggle tag 'irc'", group = "tag"}),
774 awful.key({ modkey }, "u", toggle_tag_by_name("[m]", true),
775 {description = "view tag '[m]'", group = "tag"}),
776 awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[m]"),
777 {description = "toggle tag '[m]'", group = "tag"}),
778 awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
779 {description = "view tag 'cal'", group = "tag"}),
780 awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
781 {description = "toggle tag 'cal'", group = "tag"}),
782 awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
783 {description = "view tag 'chr'", group = "tag"}),
784 awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
785 {description = "toggle tag 'chr'", group = "tag"}),
786 awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
787 {description = "view tag 'ff'", group = "tag"}),
788 awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
789 {description = "toggle tag 'ff'", group = "tag"}),
792 clientkeys = gears.table.join(
793 awful.key({ modkey, }, "f",
795 c.fullscreen = not c.fullscreen
798 {description = "toggle fullscreen", group = "client"}),
799 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
800 {description = "close", group = "client"}),
801 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
802 {description = "toggle floating", group = "client"}),
803 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
804 {description = "move to master", group = "client"}),
805 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
806 {description = "toggle keep on top", group = "client"}),
807 awful.key({ modkey, }, "n",
809 -- The client currently has the input focus, so it cannot be
810 -- minimized, since minimized clients can't have the focus.
813 {description = "minimize", group = "client"}),
814 awful.key({ modkey, }, "m",
816 c.maximized = not c.maximized
817 c.maximized_horizontal = false
818 c.maximized_vertical = false
821 {description = "(un)maximize", group = "client"}),
822 awful.key({ modkey, "Control" }, "m",
824 c.maximized_vertical = not c.maximized_vertical
827 {description = "(un)maximize vertically", group = "client"}),
828 awful.key({ modkey, "Shift" }, "m",
830 c.maximized_horizontal = not c.maximized_horizontal
833 {description = "(un)maximize horizontally", group = "client"})
836 -- Bind all key numbers to tags.
837 -- Be careful: we use keycodes to make it work on any keyboard layout.
838 -- This should map on the top row of your keyboard, usually 1 to 9.
840 globalkeys = gears.table.join(globalkeys,
842 awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
843 {description = "view tag #"..i, group = "tag"}),
844 -- Toggle tag display.
845 awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
846 {description = "toggle tag #" .. i, group = "tag"}),
847 -- Move client to tag.
848 awful.key({ modkey, "Shift" }, "#" .. i + 9,
851 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
853 client.focus:move_to_tag(tag)
857 {description = "move focused client to tag #"..i, group = "tag"}),
858 -- Toggle tag on focused client.
859 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
862 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
864 client.focus:toggle_tag(tag)
868 {description = "toggle focused client on tag #" .. i, group = "tag"})
872 clientbuttons = gears.table.join(
873 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
874 awful.button({ modkey }, 1, awful.mouse.client.move),
875 awful.button({ modkey }, 3, awful.mouse.client.resize))
878 globalkeys = awful.util.table.join(globalkeys,
879 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
880 awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
881 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
882 awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
883 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
884 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
885 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
886 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
887 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),
888 awful.key({ cmdkey }, "x", function ()
889 awful.spawn("/usr/bin/xscreensaver -no-capture-stderr")
890 os.execute("sleep 5")
891 awful.spawn("xscreensaver-command -lock")
893 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
896 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
897 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
898 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
899 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
900 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
901 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
902 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
903 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
904 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
905 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
906 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
907 awful.key(nil, "XF86Display", function () awful.spawn("") end),
908 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
909 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
910 awful.key(nil, "XF86Search", function () awful.spawn("") end),
911 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
912 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
916 root.keys(globalkeys)
920 -- Rules to apply to new clients (through the "manage" signal).
922 local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
923 local wa = client.screen.workarea
925 client.y = wa.y + topbottom
926 client.height = wa.height - 2*topbottom
928 client.y = wa.y + (wa.height - client.height)/2
931 client.x = wa.x + leftright
932 client.width = wa.width - 2*leftright
934 client.x = wa.x + (wa.width - client.width)/2
938 local function move_to_tag_by_name(s, tagname)
940 local t = awful.tag.find_by_name(s, tagname)
942 error("No tag by the name of " .. tagname)
949 awful.rules.rules = {
950 -- All clients will match this rule.
952 properties = { border_width = beautiful.border_width,
953 border_color = beautiful.border_normal,
954 focus = awful.client.focus.filter,
957 buttons = clientbuttons,
958 screen = awful.screen.preferred,
959 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
963 { rule = { type = "dialog" },
964 properties = { floating = true,
969 --switchtotag = true,
970 placement = awful.placement.centered
973 { rule = { class = "URxvt" },
974 properties = { size_hints_honor = false, }
976 { rule = { instance = "irc" },
977 callback = move_to_tag_by_name(nil, "irc"),
979 { rule = { class = "Revolt" },
980 callback = move_to_tag_by_name(nil, "[m]"),
982 { rule = { class = "Firefox" },
983 callback = move_to_tag_by_name(nil, "ffx"),
985 { rule = { class = "Chromium" },
986 callback = move_to_tag_by_name(nil, "chr"),
988 { rule = { class = "Thunderbird" },
989 callback = move_to_tag_by_name(nil, "cal"),
991 { rule_any = { class = {
995 properties = { floating = true,
997 placement = function(c)
998 float_client_in_the_middle_with_margins(c, 50, 25)
1002 { rule_any = { class = {
1010 properties = { new_tag = {
1011 layout = layouts.maximised,
1018 --XX-- { rule = { class = "Gscan2pdf" },
1019 --XX-- properties = {
1020 --XX-- switchtotag = true
1022 --XX-- callback = move_to_tag(1, 5)
1024 --XX-- { rule = { name = "gscan2pdf .*" },
1025 --XX-- properties = {
1026 --XX-- floating = false,
1029 --XX-- { rule = { class = "Thunar", type = "normal" },
1030 --XX-- properties = {
1031 --XX-- floating = false,
1034 --XX-- { rule = { class = "Pinentry", instance = "pinentry" },
1035 --XX-- properties = {
1036 --XX-- floating = true,
1039 --XX-- { rule = { class = "Gxmessage" },
1040 --XX-- properties = {
1041 --XX-- floating = true,
1049 -- Signal function to execute when a new client appears.
1050 client.connect_signal("manage", function (c)
1051 -- Set the windows at the slave,
1052 -- i.e. put it at the end of others instead of setting it master.
1053 -- if not awesome.startup then awful.client.setslave(c) end
1055 if awesome.startup and
1056 not c.size_hints.user_position
1057 and not c.size_hints.program_position then
1058 -- Prevent clients from being unreachable after screen count changes.
1059 awful.placement.no_offscreen(c)
1062 c.maximized_horizontal = false
1063 c.maximized_vertical = false
1066 -- Add a titlebar if titlebars_enabled is set to true in the rules.
1067 client.connect_signal("request::titlebars", function(c)
1068 -- buttons for the titlebar
1069 local buttons = gears.table.join(
1070 awful.button({ }, 1, function()
1073 awful.mouse.client.move(c)
1075 awful.button({ }, 3, function()
1078 awful.mouse.client.resize(c)
1082 awful.titlebar(c) : setup {
1084 awful.titlebar.widget.iconwidget(c),
1086 layout = wibox.layout.fixed.horizontal
1091 widget = awful.titlebar.widget.titlewidget(c)
1094 layout = wibox.layout.flex.horizontal
1097 awful.titlebar.widget.floatingbutton (c),
1098 awful.titlebar.widget.maximizedbutton(c),
1099 awful.titlebar.widget.stickybutton (c),
1100 awful.titlebar.widget.ontopbutton (c),
1101 awful.titlebar.widget.closebutton (c),
1102 layout = wibox.layout.fixed.horizontal()
1104 layout = wibox.layout.align.horizontal
1108 -- Enable sloppy focus, so that focus follows mouse.
1109 client.connect_signal("mouse::enter", function(c)
1110 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
1111 and awful.client.focus.filter(c) then
1116 client.connect_signal("focus", function(c)
1117 c.border_color = beautiful.border_focus
1119 client.connect_signal("unfocus", function(c)
1120 c.border_color = beautiful.border_normal
1123 awful.ewmh.add_activate_filter(function(c, context, hints)
1124 if context == "ewmh" then
1125 if (c.class == "Firefox-esr" or c.class == "Firefox") then
1131 client.connect_signal("request::activate", function(c, context, hints)
1132 if gears.table.hasitem({
1133 "client.focus.byidx",
1135 "autofocus.check_focus",
1139 gears.timer.delayed_call(function()
1140 -- we need a delayed call so that we execute *after layout changes
1141 centre_mouse_on_area(client.focus)
1144 dbg.dump(c, context, hints)
1148 -- vim:ft=lua:sw=4:sts=4:ts=4:et