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 centre_mouse_on_area(a)
121 y = a.y + a.height/2,
128 -- Create a launcher widget and a main menu
130 { "hotkeys", function() return false, hotkeys_popup.show_help end},
131 { "manual", terminal .. " -e man awesome" },
132 { "edit config", editor_cmd .. " " .. awesome.conffile },
133 { "restart", awesome.restart },
134 { "quit", function() awesome.quit() end}
137 local menu_awesome = { "awesome", myawesomemenu, beautiful.awesome_icon }
138 local menu_terminal = { "open terminal", terminal }
141 mymainmenu = freedesktop.menu.build({
142 before = { menu_awesome },
143 after = { menu_terminal }
146 mymainmenu = awful.menu({
149 { "Debian", debian.menu.Debian_menu.Debian },
156 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
159 -- Menubar configuration
160 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
164 --local spacer = wibox.widget {
165 -- color = beautiful.bg_minimize,
167 -- widget = wibox.widget.separator
169 local spacer = wibox.widget.textbox()
170 spacer:set_text(" │ ")
172 -- Keyboard map indicator and switcher
173 mykeyboardlayout = awful.widget.keyboardlayout()
175 local lain_bat = lain.widget.bat({
176 batteries = {"BAT0", "BAT1"},
177 settings = function()
179 if bat_now.status == "Charging" then delim = "↑"
180 elseif bat_now.status == "Unknown" then delim = "٭" end
181 widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
185 -- Create a textclock widget
186 clocksarray = clocksarray.get_clocksarray("%a %d %b %H:%M:%S %Z", {
187 ["NZ"] = "Pacific/Auckland",
188 ["DE"] = "Europe/Berlin"
191 -- Create a wibox for each screen and add it
192 local taglist_buttons = gears.table.join(
193 awful.button({ }, 1, function(t) t:view_only() end),
194 awful.button({ modkey }, 1, function(t)
196 client.focus:move_to_tag(t)
199 awful.button({ }, 3, awful.tag.viewtoggle),
200 awful.button({ modkey }, 3, function(t)
202 client.focus:toggle_tag(t)
205 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
206 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
209 local tasklist_buttons = gears.table.join(
210 awful.button({ }, 1, function (c)
211 if c == client.focus then
212 -- I don't like click-minimising
213 -- c.minimized = true
215 -- Without this, the following
216 -- :isvisible() makes no sense
218 if not c:isvisible() and c.first_tag then
219 c.first_tag:view_only()
221 -- This will also un-minimize
222 -- the client, if needed
227 awful.button({ }, 3, client_menu_toggle_fn()),
228 awful.button({ }, 4, function ()
229 awful.client.focus.byidx(1)
231 awful.button({ }, 5, function ()
232 awful.client.focus.byidx(-1)
238 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
239 screen.connect_signal("property::geometry", set_wallpaper)
241 -- {{{ Basic setup for screens
242 local function screen_set_profile(s, profile)
244 s.outputstr = table.concat(gears.table.keys(s.outputs), "+")
245 s.name = s.profile .. "/" .. s.outputstr
248 awful.screen.connect_for_each_screen(function(s)
250 s.set_profile = screen_set_profile
255 -- Create a text widget to display screen name
256 s.namebox = wibox.container.background(wibox.widget.textbox(s.name),
257 beautiful.bg_minimize)
259 -- Create a promptbox for each screen
260 s.mypromptbox = 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 s.mylayoutbox = awful.widget.layoutbox(s)
264 s.mylayoutbox: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 s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
272 -- Create a tasklist widget
273 s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
275 -- Create the wibox, but only if there isn't one yet
276 if not s.mywibox then
277 s.mywibox = awful.wibar({ position = "top", screen = s })
280 -- Add widgets to the wibox
281 local right_widgets = gears.table.join(clocksarray, {
284 --spacing_widget = spacer,
286 layout = wibox.layout.fixed.horizontal,
289 if s == screen.primary then
290 right_widgets = gears.table.join({
291 wibox.widget.systray(),
293 ccwidgets.btc_widget,
295 ccwidgets.eth_widget,
303 layout = wibox.layout.align.horizontal,
306 spacing_widget = spacer,
307 layout = wibox.layout.fixed.horizontal,
312 s.mytasklist, -- Middle widget
317 -- {{{ autorandr integration
318 local function find_screen_by_name(name)
320 if s.name == name then
326 local function get_target_screen_for_tag(tag)
327 local function primary_screen(reason)
328 local s = screen.primary
329 local msg = " → primary screen \"" .. s.name .. "\""
330 if reason then msg = msg .. " (" .. reason .. ")" end
335 print("Figuring out target screen for tag " .. tag.name .. "…")
337 if type(tag.targets) == "table" then
338 for _,target in ipairs(tag.targets) do
339 local s = find_screen_by_name(target)
341 print(" → screen " .. s.name)
345 elseif tag.targets == "primary" then
346 return primary_screen("explicit request")
348 return primary_screen("no matching target in " .. table.concat(tag.targets, ","))
350 return primary_screen("no targets specified")
354 local function move_tag_to_target_screen(tag)
355 tag.screen = get_target_screen_for_tag(tag)
358 local function move_tags_to_target_screens()
359 for _,tag in ipairs(root.tags()) do
360 move_tag_to_target_screen(tag)
364 tag.connect_signal("request::screen", function(t)
365 -- throw the tag onto any other screen, it'll get reassigned later when
366 -- a new profile has been processed.
368 if s ~= t.screen then
375 title = "Screen removed",
376 text = "Salvaged tab " .. t.name .. " onto screen " .. t.screen.name,
380 function handle_new_autorandr_profile(newprofile)
381 -- The main idea here is that autorandr invokes this via awesome-client
382 -- after switching to a new profile. Awesome will have already set up all
383 -- the screens long before this function is called. Therefore, we just do
384 -- the necessary modifications to the existing screens, and move tags
387 if not newprofile then
388 error("Missing new profile name")
392 preset = naughty.config.presets.low,
393 title = "New autorandr profile",
394 text = "Reconfiguring for profile <b>" .. newprofile .. "</b>",
398 s:set_profile(newprofile)
400 move_tags_to_target_screens()
403 local function initialise_to_autorandr_profile()
406 local function process_line(line)
407 if profile then return end
408 local match = string.match(line, "^([^%s]+) %(detected%)$")
414 local function output_done()
416 error("autorandr detected no profile")
419 handle_new_autorandr_profile(profile)
422 local function handle_exit(reason, code)
423 if not (reason == "exit" and code == 0) then
424 error("autorandr error: " .. reason .. ": " .. tostring(code))
428 awful.spawn.with_line_callback('autorandr', {
429 stderr = process_line,
430 output_done = output_done,
434 awesome.connect_signal("startup", initialise_to_autorandr_profile)
441 local default_tag = {
444 layout = layouts.default,
448 local default_tags = {}
451 for k,v in pairs(default_tag) do
452 default_tags[i][k] = v
454 default_tags[i].name = tostring(i)
456 default_tags[1].selected = true
458 default_tags = gears.table.join(default_tags, {
463 master_width_factor = 0.33,
464 layout = layouts.tiled,
466 exec_once = { terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi" },
467 instance = { "irc" },
468 targets = { "catalyst/eDP1", "mtvic/eDP1" },
474 master_width_factor = 0.67,
475 layout = layouts.tiled,
477 exec_once = { "revolt" },
478 instance = { "Revolt" },
479 targets = { "catalyst/eDP1", "mtvic/eDP1" },
485 layout = layouts.floating,
493 layout = layouts.default,
494 exec_once = { "thunderbird" },
495 class = { "Thunderbird" },
496 targets = { "catalyst/HDMI1", "mtvic/eDP1" },
502 layout = layouts.default,
503 exec_once = { "chromium" },
504 class = { "Chromium" },
505 targets = { "catalyst/HDMI1", "mtvic/eDP1" },
511 layout = layouts.default,
512 exec_once = { "firefox" },
513 class = { "Firefox" },
514 targets = { "catalyst/HDMI1", "mtvic/eDP1" },
518 if not tyrannical then
520 for _,t in ipairs(default_tags) do
522 t.screen = t.screen or screen.primary
523 t.layout = t.layout or layouts.default
524 local newt = th.add_tag(t.name, t, false)
528 else -- {{{ tyrannical is loaded
529 tyrannical.settings.default_layout = layouts.default
530 tyrannical.settings.master_width_factor = 0.5
531 tyrannical.settings.block_children_focus_stealing = true
532 tyrannical.settings.group_children = true
534 tyrannical.tags = default_tags
536 tyrannical.properties.size_hints_honor = { URxvt = false }
538 --XX---- Ignore the tag "exclusive" property for the following clients (matched by classes)
539 --XX--tyrannical.properties.intrusive = {
540 --XX-- "ksnapshot" , "pinentry" , "gtksu" , "kcalc" , "xcalc" ,
541 --XX-- "feh" , "Gradient editor", "About KDE" , "Paste Special", "Background color" ,
542 --XX-- "kcolorchooser" , "plasmoidviewer" , "Xephyr" , "kruler" , "plasmaengineexplorer",
545 --XX---- Ignore the tiled layout for the matching clients
546 --XX--tyrannical.properties.floating = {
547 --XX-- "MPlayer" , "pinentry" , "ksnapshot" , "pinentry" , "gtksu" ,
548 --XX-- "xine" , "feh" , "kmix" , "kcalc" , "xcalc" ,
549 --XX-- "yakuake" , "Select Color$" , "kruler" , "kcolorchooser", "Paste Special" ,
550 --XX-- "New Form" , "Insert Picture" , "kcharselect", "mythfrontend" , "plasmoidviewer"
553 --XX---- Make the matching clients (by classes) on top of the default layout
554 --XX--tyrannical.properties.ontop = {
555 --XX-- "Xephyr" , "ksnapshot" , "kruler"
558 --XX---- Force the matching clients (by classes) to be centered on the screen on init
559 --XX--tyrannical.properties.centered = {
566 -- {{{ Mouse bindings
567 root.buttons(gears.table.join(
568 awful.button({ }, 3, function () mymainmenu:toggle() end),
569 awful.button({ }, 4, awful.tag.viewnext),
570 awful.button({ }, 5, awful.tag.viewprev)
576 local function toggle_tag_by_name(tagname, exclusive)
578 local t = awful.tag.find_by_name(nil, tagname)
583 awful.tag.viewtoggle(t)
585 cf = awful.client.getmaster(t.screen)
593 globalkeys = gears.table.join(
594 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
595 {description="show help", group="awesome"}),
596 awful.key({ modkey, }, "Left", awful.tag.viewprev,
597 {description = "view previous", group = "tag"}),
598 awful.key({ modkey, }, "Right", awful.tag.viewnext,
599 {description = "view next", group = "tag"}),
600 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
601 {description = "go back", group = "tag"}),
603 awful.key({ modkey, }, "k",
605 awful.client.focus.byidx( 1)
607 {description = "focus next by index", group = "client"}
609 awful.key({ modkey, }, "j",
611 awful.client.focus.byidx(-1)
613 {description = "focus previous by index", group = "client"}
616 -- Layout manipulation
617 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
618 {description = "swap with next client by index", group = "client"}),
619 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( -1) end,
620 {description = "swap with previous client by index", group = "client"}),
621 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
622 {description = "focus the next screen", group = "screen"}),
623 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
624 {description = "focus the previous screen", group = "screen"}),
625 awful.key({ modkey, "Shift" }, "Return", awful.client.urgent.jumpto,
626 {description = "jump to urgent client", group = "client"}),
627 awful.key({ modkey, }, "Tab",
629 awful.client.focus.history.previous()
634 {description = "go back", group = "client"}),
637 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
638 {description = "open a terminal", group = "launcher"}),
639 awful.key({ modkey, }, "r", function()
640 package.loaded.rc = nil
643 {description = "reload rc.lua", group = "awesome"}),
644 awful.key({ modkey, "Control" }, "r", awesome.restart,
645 {description = "reload awesome", group = "awesome"}),
646 awful.key({ modkey, "Shift" }, "q", awesome.quit,
647 {description = "quit awesome", group = "awesome"}),
649 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
650 {description = "increase master width factor", group = "layout"}),
651 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
652 {description = "decrease master width factor", group = "layout"}),
653 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
654 {description = "increase the number of master clients", group = "layout"}),
655 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
656 {description = "decrease the number of master clients", group = "layout"}),
657 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
658 {description = "increase the number of columns", group = "layout"}),
659 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
660 {description = "decrease the number of columns", group = "layout"}),
661 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
662 {description = "select next", group = "layout"}),
663 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
664 {description = "select previous", group = "layout"}),
666 awful.key({ modkey, "Control" }, "n",
668 local c = awful.client.restore()
669 -- Focus restored client
675 {description = "restore minimized", group = "client"}),
678 awful.key({ cmdkey }, "r",
680 local widget = awful.screen.focused().mypromptbox.widget
681 local function spawn(command, args)
682 gears.debug.dump(args)
683 awful.spawn(command, args)
688 bg_cursor = '#ff0000',
690 history_path = awful.util.get_cache_dir() .. "/history",
692 -- Replace the 'normal' Return with a custom one
693 {{ }, 'Return', function(command)
696 -- Spawn method to spawn in the current tag
697 {{'Mod1' }, 'Return', function(command)
700 tag = mouse.screen.selected_tag
703 -- Spawn in the current tag as floating and on top
704 {{'Shift' }, 'Return', function(command)
708 tag = mouse.screen.selected_tag
711 -- Spawn in a new tag
712 {{'Control'}, 'Return', function(command)
715 layout = layouts.default,
720 {{ }, 'Escape', function(_) return end},
724 {description = "run prompt", group = "launcher"}),
726 awful.key({ modkey }, "x",
730 bg_cursor = '#ff0000',
731 textbox = awful.screen.focused().mypromptbox.widget,
732 exe_callback = awful.util.eval,
733 history_path = awful.util.get_cache_dir() .. "/history_eval"
736 {description = "lua execute prompt", group = "awesome"}),
738 awful.key({ modkey }, "w", function() menubar.show() end,
739 {description = "show the menubar", group = "launcher"}),
742 awful.key({ modkey, }, "a", function()
743 th.add_tag(nil, {layout=layouts.default} ,true)
745 {description = "add a tag", group = "tag"}),
746 awful.key({ modkey, }, "d", th.delete_tag,
747 {description = "delete the current tag", group = "tag"}),
748 awful.key({ modkey, "Shift", }, "a", function()
749 move_to_new_tag(nil,nil,true,true,true)
751 {description = "add a volatile tag with the focused client", group = "tag"}),
752 awful.key({ modkey, "Shift", "Control" }, "a", function()
753 move_to_new_tag(nil,nil,false,true,true)
755 {description = "add a permanent tag with the focused client", group = "tag"}),
756 awful.key({ modkey, "Mod1" }, "a", th.copy_tag,
757 {description = "create a copy of the current tag", group = "tag"}),
758 awful.key({ modkey, "Control" }, "a", th.rename_tag,
759 {description = "rename the current tag", group = "tag"}),
760 awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
761 {description = "collect all orphaned clients", group = "client"}),
763 awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
764 {description = "view tag 'irc'", group = "tag"}),
765 awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
766 {description = "toggle tag 'irc'", group = "tag"}),
767 awful.key({ modkey }, "u", toggle_tag_by_name("[m]", true),
768 {description = "view tag '[m]'", group = "tag"}),
769 awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[m]"),
770 {description = "toggle tag '[m]'", group = "tag"}),
771 awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
772 {description = "view tag 'cal'", group = "tag"}),
773 awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
774 {description = "toggle tag 'cal'", group = "tag"}),
775 awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
776 {description = "view tag 'chr'", group = "tag"}),
777 awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
778 {description = "toggle tag 'chr'", group = "tag"}),
779 awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
780 {description = "view tag 'ff'", group = "tag"}),
781 awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
782 {description = "toggle tag 'ff'", group = "tag"}),
785 clientkeys = gears.table.join(
786 awful.key({ modkey, }, "f",
788 c.fullscreen = not c.fullscreen
791 {description = "toggle fullscreen", group = "client"}),
792 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
793 {description = "close", group = "client"}),
794 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
795 {description = "toggle floating", group = "client"}),
796 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
797 {description = "move to master", group = "client"}),
798 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
799 {description = "toggle keep on top", group = "client"}),
800 awful.key({ modkey, }, "n",
802 -- The client currently has the input focus, so it cannot be
803 -- minimized, since minimized clients can't have the focus.
806 {description = "minimize", group = "client"}),
807 awful.key({ modkey, }, "m",
809 c.maximized = not c.maximized
810 c.maximized_horizontal = false
811 c.maximized_vertical = false
814 {description = "(un)maximize", group = "client"}),
815 awful.key({ modkey, "Control" }, "m",
817 c.maximized_vertical = not c.maximized_vertical
820 {description = "(un)maximize vertically", group = "client"}),
821 awful.key({ modkey, "Shift" }, "m",
823 c.maximized_horizontal = not c.maximized_horizontal
826 {description = "(un)maximize horizontally", group = "client"})
829 -- Bind all key numbers to tags.
830 -- Be careful: we use keycodes to make it work on any keyboard layout.
831 -- This should map on the top row of your keyboard, usually 1 to 9.
833 globalkeys = gears.table.join(globalkeys,
835 awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
836 {description = "view tag #"..i, group = "tag"}),
837 -- Toggle tag display.
838 awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
839 {description = "toggle tag #" .. i, group = "tag"}),
840 -- Move client to tag.
841 awful.key({ modkey, "Shift" }, "#" .. i + 9,
844 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
846 client.focus:move_to_tag(tag)
850 {description = "move focused client to tag #"..i, group = "tag"}),
851 -- Toggle tag on focused client.
852 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
855 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
857 client.focus:toggle_tag(tag)
861 {description = "toggle focused client on tag #" .. i, group = "tag"})
865 clientbuttons = gears.table.join(
866 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
867 awful.button({ modkey }, 1, awful.mouse.client.move),
868 awful.button({ modkey }, 3, awful.mouse.client.resize))
871 globalkeys = awful.util.table.join(globalkeys,
872 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
873 awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
874 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
875 awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
876 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
877 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
878 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
879 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
880 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),
881 awful.key({ cmdkey }, "x", function ()
882 awful.spawn("/usr/bin/xscreensaver -no-capture-stderr")
883 os.execute("sleep 5")
884 awful.spawn("xscreensaver-command -lock")
886 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
889 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
890 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
891 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
892 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
893 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
894 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
895 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
896 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
897 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
898 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
899 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
900 awful.key(nil, "XF86Display", function () awful.spawn("") end),
901 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
902 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
903 awful.key(nil, "XF86Search", function () awful.spawn("") end),
904 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
905 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
909 root.keys(globalkeys)
913 -- Rules to apply to new clients (through the "manage" signal).
915 local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
916 local wa = client.screen.workarea
918 client.y = wa.y + topbottom
919 client.height = wa.height - 2*topbottom
921 client.y = wa.y + (wa.height - client.height)/2
924 client.x = wa.x + leftright
925 client.width = wa.width - 2*leftright
927 client.x = wa.x + (wa.width - client.width)/2
931 local function move_to_tag_by_name(s, tagname)
933 local t = awful.tag.find_by_name(s, tagname)
935 error("No tag by the name of " .. tagname)
942 awful.rules.rules = {
943 -- All clients will match this rule.
945 properties = { border_width = beautiful.border_width,
946 border_color = beautiful.border_normal,
947 focus = awful.client.focus.filter,
950 buttons = clientbuttons,
951 screen = awful.screen.preferred,
952 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
956 { rule = { type = "dialog" },
957 properties = { floating = true,
962 --switchtotag = true,
963 placement = awful.placement.centered
966 { rule = { class = "URxvt" },
967 properties = { size_hints_honor = false, }
969 { rule = { instance = "irc" },
970 callback = move_to_tag_by_name(nil, "irc"),
972 { rule = { class = "Revolt" },
973 callback = move_to_tag_by_name(nil, "[m]"),
975 { rule = { class = "Firefox" },
976 callback = move_to_tag_by_name(nil, "ffx"),
978 { rule = { class = "Chromium" },
979 callback = move_to_tag_by_name(nil, "chr"),
981 { rule = { class = "Thunderbird" },
982 callback = move_to_tag_by_name(nil, "cal"),
984 { rule_any = { class = {
988 properties = { floating = true,
990 placement = function(c)
991 float_client_in_the_middle_with_margins(c, 50, 25)
995 { rule_any = { class = {
1003 properties = { new_tag = {
1004 layout = layouts.maximised,
1011 --XX-- { rule = { class = "Gscan2pdf" },
1012 --XX-- properties = {
1013 --XX-- switchtotag = true
1015 --XX-- callback = move_to_tag(1, 5)
1017 --XX-- { rule = { name = "gscan2pdf .*" },
1018 --XX-- properties = {
1019 --XX-- floating = false,
1022 --XX-- { rule = { class = "Thunar", type = "normal" },
1023 --XX-- properties = {
1024 --XX-- floating = false,
1027 --XX-- { rule = { class = "Pinentry", instance = "pinentry" },
1028 --XX-- properties = {
1029 --XX-- floating = true,
1032 --XX-- { rule = { class = "Gxmessage" },
1033 --XX-- properties = {
1034 --XX-- floating = true,
1042 -- Signal function to execute when a new client appears.
1043 client.connect_signal("manage", function (c)
1044 -- Set the windows at the slave,
1045 -- i.e. put it at the end of others instead of setting it master.
1046 -- if not awesome.startup then awful.client.setslave(c) end
1048 if awesome.startup and
1049 not c.size_hints.user_position
1050 and not c.size_hints.program_position then
1051 -- Prevent clients from being unreachable after screen count changes.
1052 awful.placement.no_offscreen(c)
1055 c.maximized_horizontal = false
1056 c.maximized_vertical = false
1059 -- Add a titlebar if titlebars_enabled is set to true in the rules.
1060 client.connect_signal("request::titlebars", function(c)
1061 -- buttons for the titlebar
1062 local buttons = gears.table.join(
1063 awful.button({ }, 1, function()
1066 awful.mouse.client.move(c)
1068 awful.button({ }, 3, function()
1071 awful.mouse.client.resize(c)
1075 awful.titlebar(c) : setup {
1077 awful.titlebar.widget.iconwidget(c),
1079 layout = wibox.layout.fixed.horizontal
1084 widget = awful.titlebar.widget.titlewidget(c)
1087 layout = wibox.layout.flex.horizontal
1090 awful.titlebar.widget.floatingbutton (c),
1091 awful.titlebar.widget.maximizedbutton(c),
1092 awful.titlebar.widget.stickybutton (c),
1093 awful.titlebar.widget.ontopbutton (c),
1094 awful.titlebar.widget.closebutton (c),
1095 layout = wibox.layout.fixed.horizontal()
1097 layout = wibox.layout.align.horizontal
1101 -- Enable sloppy focus, so that focus follows mouse.
1102 client.connect_signal("mouse::enter", function(c)
1103 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
1104 and awful.client.focus.filter(c) then
1109 client.connect_signal("focus", function(c)
1110 c.border_color = beautiful.border_focus
1112 client.connect_signal("unfocus", function(c)
1113 c.border_color = beautiful.border_normal
1116 awful.ewmh.add_activate_filter(function(c, context, hints)
1117 if context == "ewmh" then
1118 if (c.class == "Firefox-esr" or c.class == "Firefox") then
1124 client.connect_signal("request::activate", function(c, context, hints)
1125 if gears.table.hasitem({
1126 "client.focus.byidx",
1128 "autofocus.check_focus",
1132 gears.timer.delayed_call(function()
1133 -- we need a delayed call so that we execute *after layout changes
1134 centre_mouse_on_area(client.focus)
1137 dbg.dump(c, context, hints)
1141 -- vim:ft=lua:sw=4:sts=4:ts=4:et