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", "lehel/DisplayPort-2" },
481 master_width_factor = 0.67,
482 layout = layouts.tiled,
484 exec_once = { "revolt" },
485 instance = { "Revolt" },
486 targets = { "catalyst/eDP1", "mtvic/eDP1", "lehel/DisplayPort-2" },
492 layout = layouts.floating,
500 layout = layouts.default,
501 exec_once = { "thunderbird" },
502 class = { "Thunderbird" },
503 targets = { "catalyst/HDMI1", "mtvic/eDP1", "lehel/DisplayPort-1" },
509 layout = layouts.default,
510 exec_once = { "chromium" },
511 class = { "Chromium" },
512 targets = { "catalyst/HDMI1", "mtvic/eDP1", "lehel/DisplayPort-1" },
518 layout = layouts.default,
519 exec_once = { "firefox" },
520 class = { "Firefox" },
521 targets = { "catalyst/HDMI1", "mtvic/eDP1", "lehel/DisplayPort-1" },
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",
698 completion_callback = awful.completion.shell,
700 -- Replace the 'normal' Return with a custom one
701 {{ }, 'Return', function(command)
704 -- Spawn method to spawn in the current tag
705 {{'Mod1' }, 'Return', function(command)
708 tag = mouse.screen.selected_tag
711 -- Spawn in the current tag as floating and on top
712 {{'Shift' }, 'Return', function(command)
716 tag = mouse.screen.selected_tag
719 -- Spawn in a new tag
720 {{'Control'}, 'Return', function(command)
723 layout = layouts.default,
728 {{ }, 'Escape', function(_) return end},
732 {description = "run prompt", group = "launcher"}),
734 awful.key({ modkey }, "x",
738 bg_cursor = '#ff0000',
739 textbox = awful.screen.focused().mypromptbox.widget,
740 exe_callback = awful.util.eval,
741 history_path = awful.util.get_cache_dir() .. "/history_eval"
744 {description = "lua execute prompt", group = "awesome"}),
746 awful.key({ modkey }, "w", function() menubar.show() end,
747 {description = "show the menubar", group = "launcher"}),
750 awful.key({ modkey, }, "a", function()
751 th.add_tag(nil, {layout=layouts.default} ,true)
753 {description = "add a tag", group = "tag"}),
754 awful.key({ modkey, }, "d", th.delete_tag,
755 {description = "delete the current tag", group = "tag"}),
756 awful.key({ modkey, "Shift", }, "a", function()
757 th.move_to_new_tag(nil,nil,true,true,true)
759 {description = "add a volatile tag with the focused client", group = "tag"}),
760 awful.key({ modkey, "Shift", "Control" }, "a", function()
761 th.move_to_new_tag(nil,nil,false,true,true)
763 {description = "add a permanent tag with the focused client", group = "tag"}),
764 awful.key({ modkey, "Mod1" }, "a", th.copy_tag,
765 {description = "create a copy of the current tag", group = "tag"}),
766 awful.key({ modkey, "Control" }, "a", th.rename_tag,
767 {description = "rename the current tag", group = "tag"}),
768 awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
769 {description = "collect all orphaned clients", group = "client"}),
771 awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
772 {description = "view tag 'irc'", group = "tag"}),
773 awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
774 {description = "toggle tag 'irc'", group = "tag"}),
775 awful.key({ modkey }, "u", toggle_tag_by_name("[m]", true),
776 {description = "view tag '[m]'", group = "tag"}),
777 awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[m]"),
778 {description = "toggle tag '[m]'", group = "tag"}),
779 awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
780 {description = "view tag 'cal'", group = "tag"}),
781 awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
782 {description = "toggle tag 'cal'", group = "tag"}),
783 awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
784 {description = "view tag 'chr'", group = "tag"}),
785 awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
786 {description = "toggle tag 'chr'", group = "tag"}),
787 awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
788 {description = "view tag 'ff'", group = "tag"}),
789 awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
790 {description = "toggle tag 'ff'", group = "tag"}),
793 clientkeys = gears.table.join(
794 awful.key({ modkey, }, "f",
796 c.fullscreen = not c.fullscreen
799 {description = "toggle fullscreen", group = "client"}),
800 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
801 {description = "close", group = "client"}),
802 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
803 {description = "toggle floating", group = "client"}),
804 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
805 {description = "move to master", group = "client"}),
806 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
807 {description = "toggle keep on top", group = "client"}),
808 awful.key({ modkey, }, "n",
810 -- The client currently has the input focus, so it cannot be
811 -- minimized, since minimized clients can't have the focus.
814 {description = "minimize", group = "client"}),
815 awful.key({ modkey, }, "m",
817 c.maximized = not c.maximized
818 c.maximized_horizontal = false
819 c.maximized_vertical = false
822 {description = "(un)maximize", group = "client"}),
823 awful.key({ modkey, "Control" }, "m",
825 c.maximized_vertical = not c.maximized_vertical
828 {description = "(un)maximize vertically", group = "client"}),
829 awful.key({ modkey, "Shift" }, "m",
831 c.maximized_horizontal = not c.maximized_horizontal
834 {description = "(un)maximize horizontally", group = "client"})
837 -- Bind all key numbers to tags.
838 -- Be careful: we use keycodes to make it work on any keyboard layout.
839 -- This should map on the top row of your keyboard, usually 1 to 9.
841 globalkeys = gears.table.join(globalkeys,
843 awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
844 {description = "view tag #"..i, group = "tag"}),
845 -- Toggle tag display.
846 awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
847 {description = "toggle tag #" .. i, group = "tag"}),
848 -- Move client to tag.
849 awful.key({ modkey, "Shift" }, "#" .. i + 9,
852 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
854 client.focus:move_to_tag(tag)
858 {description = "move focused client to tag #"..i, group = "tag"}),
859 -- Toggle tag on focused client.
860 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
863 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
865 client.focus:toggle_tag(tag)
869 {description = "toggle focused client on tag #" .. i, group = "tag"})
873 clientbuttons = gears.table.join(
874 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
875 awful.button({ modkey }, 1, awful.mouse.client.move),
876 awful.button({ modkey }, 3, awful.mouse.client.resize))
879 globalkeys = awful.util.table.join(globalkeys,
880 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
881 awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
882 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
883 awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
884 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
885 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
886 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
887 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
888 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),
889 awful.key({ cmdkey }, "x", function ()
890 awful.spawn("/usr/bin/xscreensaver -no-capture-stderr")
891 os.execute("sleep 5")
892 awful.spawn("xscreensaver-command -lock")
894 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
897 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
898 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
899 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
900 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
901 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
902 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
903 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
904 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
905 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
906 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
907 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
908 awful.key(nil, "XF86Display", function () awful.spawn("") end),
909 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
910 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
911 awful.key(nil, "XF86Search", function () awful.spawn("") end),
912 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
913 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
917 root.keys(globalkeys)
921 -- Rules to apply to new clients (through the "manage" signal).
923 local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
924 local wa = client.screen.workarea
926 client.y = wa.y + topbottom
927 client.height = wa.height - 2*topbottom
929 client.y = wa.y + (wa.height - client.height)/2
932 client.x = wa.x + leftright
933 client.width = wa.width - 2*leftright
935 client.x = wa.x + (wa.width - client.width)/2
939 local function move_to_tag_by_name(s, tagname)
941 local t = awful.tag.find_by_name(s, tagname)
943 error("No tag by the name of " .. tagname)
950 awful.rules.rules = {
951 -- All clients will match this rule.
953 properties = { border_width = beautiful.border_width,
954 border_color = beautiful.border_normal,
955 focus = awful.client.focus.filter,
958 buttons = clientbuttons,
959 screen = awful.screen.preferred,
960 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
964 { rule = { type = "dialog" },
965 properties = { floating = true,
970 --switchtotag = true,
971 placement = awful.placement.centered
974 { rule = { class = "URxvt" },
975 properties = { size_hints_honor = false, }
977 { rule = { instance = "irc" },
978 callback = move_to_tag_by_name(nil, "irc"),
980 { rule = { class = "Revolt" },
981 callback = move_to_tag_by_name(nil, "[m]"),
983 { rule = { class = "Firefox" },
984 callback = move_to_tag_by_name(nil, "ffx"),
986 { rule = { class = "Chromium" },
987 callback = move_to_tag_by_name(nil, "chr"),
989 { rule = { class = "Thunderbird" },
990 callback = move_to_tag_by_name(nil, "cal"),
992 { rule_any = { class = {
996 properties = { floating = true,
998 placement = function(c)
999 float_client_in_the_middle_with_margins(c, 50, 25)
1003 -- { rule_any = { class = {
1011 -- properties = { new_tag = {
1012 -- layout = layouts.maximised,
1015 -- switchtotag = true,
1019 --XX-- { rule = { class = "Gscan2pdf" },
1020 --XX-- properties = {
1021 --XX-- switchtotag = true
1023 --XX-- callback = move_to_tag(1, 5)
1025 --XX-- { rule = { name = "gscan2pdf .*" },
1026 --XX-- properties = {
1027 --XX-- floating = false,
1030 --XX-- { rule = { class = "Thunar", type = "normal" },
1031 --XX-- properties = {
1032 --XX-- floating = false,
1035 --XX-- { rule = { class = "Pinentry", instance = "pinentry" },
1036 --XX-- properties = {
1037 --XX-- floating = true,
1040 --XX-- { rule = { class = "Gxmessage" },
1041 --XX-- properties = {
1042 --XX-- floating = true,
1050 -- Signal function to execute when a new client appears.
1051 client.connect_signal("manage", function (c)
1052 -- Set the windows at the slave,
1053 -- i.e. put it at the end of others instead of setting it master.
1054 -- if not awesome.startup then awful.client.setslave(c) end
1056 if awesome.startup and
1057 not c.size_hints.user_position
1058 and not c.size_hints.program_position then
1059 -- Prevent clients from being unreachable after screen count changes.
1060 awful.placement.no_offscreen(c)
1063 c.maximized_horizontal = false
1064 c.maximized_vertical = false
1067 -- Add a titlebar if titlebars_enabled is set to true in the rules.
1068 client.connect_signal("request::titlebars", function(c)
1069 -- buttons for the titlebar
1070 local buttons = gears.table.join(
1071 awful.button({ }, 1, function()
1074 awful.mouse.client.move(c)
1076 awful.button({ }, 3, function()
1079 awful.mouse.client.resize(c)
1083 awful.titlebar(c) : setup {
1085 awful.titlebar.widget.iconwidget(c),
1087 layout = wibox.layout.fixed.horizontal
1092 widget = awful.titlebar.widget.titlewidget(c)
1095 layout = wibox.layout.flex.horizontal
1098 awful.titlebar.widget.floatingbutton (c),
1099 awful.titlebar.widget.maximizedbutton(c),
1100 awful.titlebar.widget.stickybutton (c),
1101 awful.titlebar.widget.ontopbutton (c),
1102 awful.titlebar.widget.closebutton (c),
1103 layout = wibox.layout.fixed.horizontal()
1105 layout = wibox.layout.align.horizontal
1109 -- Enable sloppy focus, so that focus follows mouse.
1110 client.connect_signal("mouse::enter", function(c)
1111 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
1112 and awful.client.focus.filter(c) then
1117 client.connect_signal("focus", function(c)
1118 c.border_color = beautiful.border_focus
1120 client.connect_signal("unfocus", function(c)
1121 c.border_color = beautiful.border_normal
1124 awful.ewmh.add_activate_filter(function(c, context, hints)
1125 if context == "ewmh" then
1126 if (c.class == "Firefox-esr" or c.class == "Firefox") then
1132 client.connect_signal("request::activate", function(c, context, hints)
1133 if gears.table.hasitem({
1134 "client.focus.byidx",
1136 "autofocus.check_focus",
1140 gears.timer.delayed_call(function()
1141 -- we need a delayed call so that we execute *after layout changes
1142 if hints.raise and c == client.focus and client.focus:isvisible() then
1143 move_mouse_to_area(client.focus)
1149 -- vim:ft=lua:sw=4:sts=4:ts=4:et