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 fxwidgets = require("forex_widgets")
28 local clocksarray = require("clocksarray")
29 local dbg = require("debugfunc")
30 local th = require("taghelpers")
34 -- Check if awesome encountered an error during startup and fell back to
35 -- another config (This code will only ever execute for the fallback config)
36 if awesome.startup_errors then
37 naughty.notify({ preset = naughty.config.presets.critical,
38 title = "Oops, there were errors during startup!",
39 text = awesome.startup_errors })
42 -- Handle runtime errors after startup
44 local in_error = false
45 awesome.connect_signal("debug::error", function (err)
46 -- Make sure we don't go into an endless error loop
47 if in_error then return end
50 naughty.notify({ preset = naughty.config.presets.critical,
51 title = "Oops, an error happened!",
52 text = tostring(err) })
58 -- {{{ Variable definitions
59 --xrdb.set_dpi(95, screen[1])
60 --xrdb.set_dpi(120, screen[2])
62 -- Themes define colours, icons, font and wallpapers.
63 beautiful.init(gears.filesystem.get_configuration_dir () .. "theme/theme.lua")
65 -- This is used later as the default terminal and editor to run.
66 terminal = "rxvt-unicode"
67 editor = os.getenv("EDITOR") or "editor"
68 editor_cmd = terminal .. " -e " .. editor
71 -- Usually, Mod4 is the key with a logo between Control and Alt.
72 -- If you do not like this or do not have such a key,
73 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
74 -- However, you can use another modifier like Mod1, but it may interact with others.
78 -- Table of layouts to cover with awful.layout.inc, order matters.
80 default = awful.layout.suit.fair,
81 default_horiz = awful.layout.suit.fair.horizontal,
82 tiled = awful.layout.suit.tile,
83 tiled_horiz = awful.layout.suit.tile.top,
84 floating = awful.layout.suit.floating,
85 maximised = awful.layout.suit.max
87 awful.layout.layouts = {
92 layouts.default_horiz,
97 -- {{{ Helper functions
98 local function client_menu_toggle_fn()
102 if instance and instance.wibox.visible then
106 instance = awful.menu.clients({ theme = { width = 250 } })
111 local function set_wallpaper(s)
113 if beautiful.wallpaper then
114 local wallpaper = beautiful.wallpaper
115 -- If wallpaper is a function, call it with the screen
116 if type(wallpaper) == "function" then
117 wallpaper = wallpaper(s)
119 gears.wallpaper.maximized(wallpaper, s, true)
123 local function move_mouse_to_area(a)
124 local coords = mouse.coords()
125 if (coords.x < a.x or
126 coords.x > (a.x+a.width) or
128 coords.y > (a.y+a.height)) then
132 y = a.y + a.height/2,
140 -- Create a launcher widget and a main menu
142 { "hotkeys", function() return false, hotkeys_popup.show_help end},
143 { "manual", terminal .. " -e man awesome" },
144 { "edit config", editor_cmd .. " " .. awesome.conffile },
145 { "restart", awesome.restart },
146 { "quit", function() awesome.quit() end}
149 local menu_awesome = { "awesome", myawesomemenu, beautiful.awesome_icon }
150 local menu_terminal = { "open terminal", terminal }
153 mymainmenu = freedesktop.menu.build({
154 before = { menu_awesome },
155 after = { menu_terminal }
158 mymainmenu = awful.menu({
161 { "Debian", debian.menu.Debian_menu.Debian },
168 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
171 -- Menubar configuration
172 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
176 --local spacer = wibox.widget {
177 -- color = beautiful.bg_minimize,
179 -- widget = wibox.widget.separator
181 local function make_spacer(text)
182 local spacer = wibox.widget.textbox()
183 spacer:set_text(text or " │ ")
187 -- Keyboard map indicator and switcher
188 mykeyboardlayout = awful.widget.keyboardlayout()
190 local lain_bat = lain.widget.bat({
191 batteries = {"BAT0", "BAT1"},
192 settings = function()
194 if bat_now.status == "Charging" then delim = "↑"
195 elseif bat_now.status == "Unknown" then delim = "٭" end
196 widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
200 -- Create a textclock widget
201 clocksarray = clocksarray.get_clocksarray("%a %d %b %H:%M:%S %Z", {
202 ["NZ"] = "Pacific/Auckland",
203 ["DE"] = "Europe/Berlin"
206 -- Create a wibox for each screen and add it
207 local taglist_buttons = gears.table.join(
208 awful.button({ }, 1, function(t) t:view_only() end),
209 awful.button({ modkey }, 1, function(t)
211 client.focus:move_to_tag(t)
214 awful.button({ }, 3, awful.tag.viewtoggle),
215 awful.button({ modkey }, 3, function(t)
217 client.focus:toggle_tag(t)
220 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
221 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
224 local tasklist_buttons = gears.table.join(
225 awful.button({ }, 1, function (c)
226 if c == client.focus then
227 -- I don't like click-minimising
228 -- c.minimized = true
230 -- Without this, the following
231 -- :isvisible() makes no sense
233 if not c:isvisible() and c.first_tag then
234 c.first_tag:view_only()
236 -- This will also un-minimize
237 -- the client, if needed
242 awful.button({ }, 3, client_menu_toggle_fn()),
243 awful.button({ }, 4, function ()
244 awful.client.focus.byidx(1)
246 awful.button({ }, 5, function ()
247 awful.client.focus.byidx(-1)
253 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
254 screen.connect_signal("property::geometry", set_wallpaper)
256 -- {{{ Basic setup for screens
257 local function screen_set_profile(s, profile)
259 s.outputstr = table.concat(gears.table.keys(s.outputs), "+")
260 s.name = s.profile .. "/" .. s.outputstr
263 awful.screen.connect_for_each_screen(function(s)
265 s.set_profile = screen_set_profile
270 -- Create a text widget to display screen name
271 s.namebox = wibox.container.background(wibox.widget.textbox(s.name),
272 beautiful.bg_minimize)
274 -- Create a promptbox for each screen
275 s.mypromptbox = awful.widget.prompt()
276 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
277 -- We need one layoutbox per screen.
278 s.mylayoutbox = awful.widget.layoutbox(s)
279 s.mylayoutbox:buttons(awful.util.table.join(
280 awful.button({ }, 1, function () awful.layout.inc( 1) end),
281 awful.button({ }, 3, function () awful.layout.inc(-1) end),
282 awful.button({ }, 4, function () awful.layout.inc( 1) end),
283 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
284 -- Create a taglist widget
285 s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
287 -- Create a tasklist widget
288 s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
290 -- Create the wibox, but only if there isn't one yet
291 if not s.mywibox then
292 s.mywibox = awful.wibar({ position = "top", screen = s })
295 -- Add widgets to the wibox
296 local right_widgets = gears.table.join(clocksarray, {
298 wibox.widget.systray(),
300 layout = wibox.layout.fixed.horizontal,
303 -- if s == screen.primary then
304 right_widgets = gears.table.join({
306 ccwidgets.btc_widget,
308 ccwidgets.eth_widget,
310 fxwidgets.ecb_widget,
318 layout = wibox.layout.align.horizontal,
320 layout = wibox.layout.fixed.horizontal,
326 s.mytasklist, -- Middle widget
331 -- {{{ autorandr integration
332 local function find_screen_by_name(name)
334 if s.name == name then
340 local function get_target_screen_for_tag(tag)
341 local function primary_screen(reason)
342 local s = screen.primary
343 local msg = " → primary screen \"" .. s.name .. "\""
344 if reason then msg = msg .. " (" .. reason .. ")" end
349 print("Figuring out target screen for tag " .. tag.name .. "…")
351 if type(tag.targets) == "table" then
352 for _,target in ipairs(tag.targets) do
353 local s = find_screen_by_name(target)
355 print(" → screen " .. s.name)
359 elseif tag.targets == "primary" then
360 return primary_screen("explicit request")
362 return primary_screen("no matching target in " .. table.concat(tag.targets, ","))
364 return primary_screen("no targets specified")
368 local function move_tag_to_target_screen(tag)
369 tag.screen = get_target_screen_for_tag(tag)
372 local function move_tags_to_target_screens()
373 for _,tag in ipairs(root.tags()) do
374 move_tag_to_target_screen(tag)
378 tag.connect_signal("request::screen", function(t)
379 -- throw the tag onto any other screen, it'll get reassigned later when
380 -- a new profile has been processed.
382 if s ~= t.screen then
389 title = "Screen removed",
390 text = "Salvaged tab " .. t.name,
394 function handle_new_autorandr_profile(newprofile)
395 -- The main idea here is that autorandr invokes this via awesome-client
396 -- after switching to a new profile. Awesome will have already set up all
397 -- the screens long before this function is called. Therefore, we just do
398 -- the necessary modifications to the existing screens, and move tags
401 if not newprofile then
402 error("Missing new profile name")
406 preset = naughty.config.presets.low,
407 title = "New autorandr profile",
408 text = "Reconfiguring for profile <b>" .. newprofile .. "</b>",
412 s:set_profile(newprofile)
414 move_tags_to_target_screens()
417 local function initialise_to_autorandr_profile()
421 local function process_line(line)
422 if profile then return end
423 local match = string.match(line, "^([^%s]+) %(detected%)")
429 local function output_done()
431 error("autorandr detected no profile")
434 handle_new_autorandr_profile(profile)
437 local function handle_exit(reason, code)
438 if not (reason == "exit" and code == 0) then
439 error("autorandr error: " .. reason .. ": " .. tostring(code))
443 awful.spawn.with_line_callback('autorandr', {
444 stdout = process_line,
445 output_done = output_done,
449 awesome.connect_signal("startup", initialise_to_autorandr_profile)
456 local default_tag = {
459 layout = layouts.default,
463 local default_tags = {}
466 for k,v in pairs(default_tag) do
467 default_tags[i][k] = v
469 default_tags[i].name = tostring(i)
471 default_tags[1].selected = true
473 default_tags = gears.table.join(default_tags, {
478 master_width_factor = 0.33,
479 layout = layouts.tiled,
481 exec_once = { terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi" },
482 instance = { "irc" },
483 targets = { "catalyst/eDP1", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-2" },
489 master_width_factor = 0.67,
490 layout = layouts.tiled,
492 exec_once = { "revolt" },
493 instance = { "Revolt" },
494 targets = { "catalyst/eDP1", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-2" },
500 layout = layouts.floating,
508 layout = layouts.default,
509 exec_once = { "thunderbird" },
510 class = { "Thunderbird" },
511 targets = { "catalyst/DP2-2", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-1" },
517 layout = layouts.default,
518 exec_once = { "chromium" },
519 class = { "Chromium" },
520 targets = { "catalyst/DP2-2", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-1", "present/HDMI1" },
526 layout = layouts.default,
527 exec_once = { "firefox" },
528 class = { "Firefox" },
529 targets = { "catalyst/DP2-2", "mtvic/eDP1", "gauting/eDP1", "lehel/DisplayPort-1", "present/HDMI1" },
533 if not tyrannical then
535 for _,t in ipairs(default_tags) do
537 t.screen = t.screen or screen.primary
538 t.layout = t.layout or layouts.default
539 local newt = th.add_tag(t.name, t, false)
543 else -- {{{ tyrannical is loaded
544 tyrannical.settings.default_layout = layouts.default
545 tyrannical.settings.master_width_factor = 0.5
546 tyrannical.settings.block_children_focus_stealing = true
547 tyrannical.settings.group_children = true
549 tyrannical.tags = default_tags
551 tyrannical.properties.size_hints_honor = { URxvt = false }
553 --XX---- Ignore the tag "exclusive" property for the following clients (matched by classes)
554 --XX--tyrannical.properties.intrusive = {
555 --XX-- "ksnapshot" , "pinentry" , "gtksu" , "kcalc" , "xcalc" ,
556 --XX-- "feh" , "Gradient editor", "About KDE" , "Paste Special", "Background color" ,
557 --XX-- "kcolorchooser" , "plasmoidviewer" , "Xephyr" , "kruler" , "plasmaengineexplorer",
560 --XX---- Ignore the tiled layout for the matching clients
561 --XX--tyrannical.properties.floating = {
562 --XX-- "MPlayer" , "pinentry" , "ksnapshot" , "pinentry" , "gtksu" ,
563 --XX-- "xine" , "feh" , "kmix" , "kcalc" , "xcalc" ,
564 --XX-- "yakuake" , "Select Color$" , "kruler" , "kcolorchooser", "Paste Special" ,
565 --XX-- "New Form" , "Insert Picture" , "kcharselect", "mythfrontend" , "plasmoidviewer"
568 --XX---- Make the matching clients (by classes) on top of the default layout
569 --XX--tyrannical.properties.ontop = {
570 --XX-- "Xephyr" , "ksnapshot" , "kruler"
573 --XX---- Force the matching clients (by classes) to be centered on the screen on init
574 --XX--tyrannical.properties.centered = {
581 -- {{{ Mouse bindings
582 root.buttons(gears.table.join(
583 awful.button({ }, 3, function () mymainmenu:toggle() end),
584 awful.button({ }, 4, awful.tag.viewnext),
585 awful.button({ }, 5, awful.tag.viewprev)
591 local function toggle_tag_by_name(tagname, exclusive)
593 local t = awful.tag.find_by_name(nil, tagname)
598 awful.tag.viewtoggle(t)
600 cf = awful.client.getmaster(t.screen)
608 globalkeys = gears.table.join(
609 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
610 {description="show help", group="awesome"}),
611 awful.key({ modkey, }, "Left", awful.tag.viewprev,
612 {description = "view previous", group = "tag"}),
613 awful.key({ modkey, }, "Right", awful.tag.viewnext,
614 {description = "view next", group = "tag"}),
615 awful.key({ modkey, "Shift" }, "Left", function () awful.screen.focus_relative( 1) end,
616 {description = "focus the next screen", group = "screen"}),
617 awful.key({ modkey, "Shift" }, "Right", function () awful.screen.focus_relative(-1) end,
618 {description = "focus the previous screen", group = "screen"}),
619 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
620 {description = "go back", group = "tag"}),
622 awful.key({ modkey, }, "k",
624 awful.client.focus.byidx( 1)
626 {description = "focus next by index", group = "client"}
628 awful.key({ modkey, }, "j",
630 awful.client.focus.byidx(-1)
632 {description = "focus previous by index", group = "client"}
635 -- Layout manipulation
636 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
637 {description = "swap with next client by index", group = "client"}),
638 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( -1) end,
639 {description = "swap with previous client by index", group = "client"}),
640 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
641 {description = "focus the next screen", group = "screen"}),
642 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
643 {description = "focus the previous screen", group = "screen"}),
644 awful.key({ modkey, "Shift" }, "Return", awful.client.urgent.jumpto,
645 {description = "jump to urgent client", group = "client"}),
646 awful.key({ modkey, }, "Tab",
648 awful.client.focus.history.previous()
653 {description = "go back", group = "client"}),
656 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
657 {description = "open a terminal", group = "launcher"}),
658 awful.key({ modkey, }, "r", function()
659 package.loaded.rc = nil
662 {description = "reload rc.lua", group = "awesome"}),
663 awful.key({ modkey, "Control" }, "r", awesome.restart,
664 {description = "reload awesome", group = "awesome"}),
665 awful.key({ modkey, "Shift" }, "q", awesome.quit,
666 {description = "quit awesome", group = "awesome"}),
668 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
669 {description = "increase master width factor", group = "layout"}),
670 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
671 {description = "decrease master width factor", group = "layout"}),
672 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
673 {description = "increase the number of master clients", group = "layout"}),
674 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
675 {description = "decrease the number of master clients", group = "layout"}),
676 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
677 {description = "increase the number of columns", group = "layout"}),
678 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
679 {description = "decrease the number of columns", group = "layout"}),
680 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
681 {description = "select next", group = "layout"}),
682 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
683 {description = "select previous", group = "layout"}),
685 awful.key({ modkey, "Control" }, "n",
687 local c = awful.client.restore()
688 -- Focus restored client
694 {description = "restore minimized", group = "client"}),
697 awful.key({ cmdkey }, "r",
699 local widget = awful.screen.focused().mypromptbox.widget
700 local function spawn(command, args)
701 gears.debug.dump(args)
702 awful.spawn(command, args)
707 bg_cursor = '#ff0000',
709 history_path = awful.util.get_cache_dir() .. "/history",
710 completion_callback = awful.completion.shell,
712 -- Replace the 'normal' Return with a custom one
713 {{ }, 'Return', function(command)
716 -- Spawn method to spawn in the current tag
717 {{'Mod1' }, 'Return', function(command)
720 tag = mouse.screen.selected_tag
723 -- Spawn in the current tag as floating and on top
724 {{'Shift' }, 'Return', function(command)
728 tag = mouse.screen.selected_tag
731 -- Spawn in a new tag
732 {{'Control'}, 'Return', function(command)
735 layout = layouts.default,
740 {{ }, 'Escape', function(_) return end},
744 {description = "run prompt", group = "launcher"}),
746 awful.key({ modkey }, "x",
750 bg_cursor = '#ff0000',
751 textbox = awful.screen.focused().mypromptbox.widget,
752 exe_callback = awful.util.eval,
753 history_path = awful.util.get_cache_dir() .. "/history_eval"
756 {description = "lua execute prompt", group = "awesome"}),
758 awful.key({ modkey }, "w", function() menubar.show() end,
759 {description = "show the menubar", group = "launcher"}),
762 awful.key({ modkey, }, "a", function()
763 th.add_tag(nil, {layout=layouts.default} ,true)
765 {description = "add a tag", group = "tag"}),
766 awful.key({ modkey, }, "d", th.delete_tag,
767 {description = "delete the current tag", group = "tag"}),
768 awful.key({ modkey, "Shift", }, "a", function()
769 th.move_to_new_tag(nil,nil,true,true,true)
771 {description = "add a volatile tag with the focused client", group = "tag"}),
772 awful.key({ modkey, "Shift", "Control" }, "a", function()
773 th.move_to_new_tag(nil,nil,false,true,true)
775 {description = "add a permanent tag with the focused client", group = "tag"}),
776 awful.key({ modkey, "Mod1" }, "a", th.copy_tag,
777 {description = "create a copy of the current tag", group = "tag"}),
778 awful.key({ modkey, "Control" }, "a", th.rename_tag,
779 {description = "rename the current tag", group = "tag"}),
780 awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
781 {description = "collect all orphaned clients", group = "client"}),
783 awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
784 {description = "view tag 'irc'", group = "tag"}),
785 awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
786 {description = "toggle tag 'irc'", group = "tag"}),
787 awful.key({ modkey }, "u", toggle_tag_by_name("[m]", true),
788 {description = "view tag '[m]'", group = "tag"}),
789 awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[m]"),
790 {description = "toggle tag '[m]'", group = "tag"}),
791 awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
792 {description = "view tag 'cal'", group = "tag"}),
793 awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
794 {description = "toggle tag 'cal'", group = "tag"}),
795 awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
796 {description = "view tag 'chr'", group = "tag"}),
797 awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
798 {description = "toggle tag 'chr'", group = "tag"}),
799 awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
800 {description = "view tag 'ff'", group = "tag"}),
801 awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
802 {description = "toggle tag 'ff'", group = "tag"}),
805 clientkeys = gears.table.join(
806 awful.key({ modkey, }, "f",
808 c.fullscreen = not c.fullscreen
811 {description = "toggle fullscreen", group = "client"}),
812 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
813 {description = "close", group = "client"}),
814 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
815 {description = "toggle floating", group = "client"}),
816 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
817 {description = "move to master", group = "client"}),
818 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
819 {description = "toggle keep on top", group = "client"}),
820 awful.key({ modkey, }, "n",
822 -- The client currently has the input focus, so it cannot be
823 -- minimized, since minimized clients can't have the focus.
826 {description = "minimize", group = "client"}),
827 awful.key({ modkey, }, "m",
829 c.maximized = not c.maximized
830 c.maximized_horizontal = false
831 c.maximized_vertical = false
834 {description = "(un)maximize", group = "client"}),
835 awful.key({ modkey, "Control" }, "m",
837 c.maximized_vertical = not c.maximized_vertical
840 {description = "(un)maximize vertically", group = "client"}),
841 awful.key({ modkey, "Shift" }, "m",
843 c.maximized_horizontal = not c.maximized_horizontal
846 {description = "(un)maximize horizontally", group = "client"})
849 -- Bind all key numbers to tags.
850 -- Be careful: we use keycodes to make it work on any keyboard layout.
851 -- This should map on the top row of your keyboard, usually 1 to 9.
853 globalkeys = gears.table.join(globalkeys,
855 awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
856 {description = "view tag #"..i, group = "tag"}),
857 -- Toggle tag display.
858 awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
859 {description = "toggle tag #" .. i, group = "tag"}),
860 -- Move client to tag.
861 awful.key({ modkey, "Shift" }, "#" .. i + 9,
864 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
866 client.focus:move_to_tag(tag)
870 {description = "move focused client to tag #"..i, group = "tag"}),
871 -- Toggle tag on focused client.
872 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
875 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
877 client.focus:toggle_tag(tag)
881 {description = "toggle focused client on tag #" .. i, group = "tag"})
885 clientbuttons = gears.table.join(
886 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
887 awful.button({ modkey }, 1, awful.mouse.client.move),
888 awful.button({ modkey }, 3, awful.mouse.client.resize))
891 globalkeys = awful.util.table.join(globalkeys,
892 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
893 awful.key({ cmdkey }, "c", function () awful.spawn("chromium --enable-remote-extensions") end),
894 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
895 awful.key({ cmdkey }, "m", function () awful.spawn(terminal .. " -name mutt -e mutt") end),
896 awful.key({ cmdkey }, "t", function () awful.spawn("thunderbird") end),
897 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
898 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
899 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
900 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
901 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),
902 awful.key({ cmdkey }, "x", function ()
903 awful.spawn("/usr/bin/xscreensaver -no-capture-stderr")
904 os.execute("sleep 5")
905 awful.spawn("xscreensaver-command -lock")
907 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
909 awful.key({ cmdkey }, "BackSpace", function () awful.spawn("pkill -USR1 offlineimap") end),
912 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
913 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
914 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
915 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
916 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
917 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
918 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
919 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
920 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
921 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
922 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
923 awful.key(nil, "XF86Display", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
924 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
925 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
926 awful.key(nil, "XF86Search", function () awful.spawn("") end),
927 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
928 awful.key(nil, "XF86Explorer", function () awful.spawn("") end),
930 awful.key({ cmdkey }, "Left", function () awful.spawn("xmms2 prev") end),
931 awful.key({ cmdkey }, "Right", function () awful.spawn("xmms2 next") end),
932 awful.key({ cmdkey }, "space", function () awful.spawn("xmms2 toggle") end),
933 awful.key({ cmdkey }, "\\", function () run_output_notify("xmms2 list") end)
936 function run_output_notify(cmd)
937 awful.spawn.easy_async(cmd, function(stdout, stderr, reason, exit_code)
939 preset = naughty.config.presets.low,
940 title = "XMMS2 playlist",
946 root.keys(globalkeys)
950 -- Rules to apply to new clients (through the "manage" signal).
952 local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
953 local wa = client.screen.workarea
955 client.y = wa.y + topbottom
956 client.height = wa.height - 2*topbottom
958 client.y = wa.y + (wa.height - client.height)/2
961 client.x = wa.x + leftright
962 client.width = wa.width - 2*leftright
964 client.x = wa.x + (wa.width - client.width)/2
968 local function move_to_tag_by_name(s, tagname)
970 local t = awful.tag.find_by_name(s, tagname)
972 error("No tag by the name of " .. tagname)
979 awful.rules.rules = {
980 -- All clients will match this rule.
982 properties = { border_width = beautiful.border_width,
983 border_color = beautiful.border_normal,
984 focus = awful.client.focus.filter,
987 buttons = clientbuttons,
988 screen = awful.screen.preferred,
989 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
993 { rule = { type = "dialog" },
994 properties = { floating = true,
999 --switchtotag = true,
1000 placement = awful.placement.centered
1003 { rule = { class = "URxvt" },
1004 properties = { size_hints_honor = false, }
1006 { rule = { instance = "irc" },
1007 callback = move_to_tag_by_name(nil, "irc"),
1009 { rule = { class = "Revolt" },
1010 callback = move_to_tag_by_name(nil, "[m]"),
1012 { rule = { class = "Firefox" },
1013 callback = move_to_tag_by_name(nil, "ffx"),
1015 { rule = { class = "Chromium" },
1016 callback = move_to_tag_by_name(nil, "chr"),
1018 { rule = { class = "Thunderbird" },
1019 callback = move_to_tag_by_name(nil, "cal"),
1021 { rule = { instance = "mutt" },
1025 layout = awful.layout.suit.fair.horizontal,
1031 { rule_any = { class = {
1036 properties = { floating = true,
1039 placement = awful.placement.centered,
1042 { rule_any = { instance = {
1047 properties = { floating = true,
1050 placement = awful.placement.centered,
1053 -- { rule_any = { class = {
1061 -- properties = { new_tag = {
1062 -- layout = layouts.maximised,
1065 -- switchtotag = true,
1069 --XX-- { rule = { class = "Gscan2pdf" },
1070 --XX-- properties = {
1071 --XX-- switchtotag = true
1073 --XX-- callback = move_to_tag(1, 5)
1075 --XX-- { rule = { name = "gscan2pdf .*" },
1076 --XX-- properties = {
1077 --XX-- floating = false,
1080 --XX-- { rule = { class = "Thunar", type = "normal" },
1081 --XX-- properties = {
1082 --XX-- floating = false,
1085 --XX-- { rule = { class = "Pinentry", instance = "pinentry" },
1086 --XX-- properties = {
1087 --XX-- floating = true,
1090 --XX-- { rule = { class = "Gxmessage" },
1091 --XX-- properties = {
1092 --XX-- floating = true,
1100 -- Signal function to execute when a new client appears.
1101 client.connect_signal("manage", function (c)
1102 -- Set the windows at the slave,
1103 -- i.e. put it at the end of others instead of setting it master.
1104 -- if not awesome.startup then awful.client.setslave(c) end
1105 if not awesome.startup then
1106 local t = awful.screen.focused().selected_tag
1107 if t.name == "xmutt" then
1108 awful.client.setslave(c)
1112 if awesome.startup and
1113 not c.size_hints.user_position
1114 and not c.size_hints.program_position then
1115 -- Prevent clients from being unreachable after screen count changes.
1116 awful.placement.no_offscreen(c)
1119 c.maximized_horizontal = false
1120 c.maximized_vertical = false
1123 -- Add a titlebar if titlebars_enabled is set to true in the rules.
1124 client.connect_signal("request::titlebars", function(c)
1125 -- buttons for the titlebar
1126 local buttons = gears.table.join(
1127 awful.button({ }, 1, function()
1130 awful.mouse.client.move(c)
1132 awful.button({ }, 3, function()
1135 awful.mouse.client.resize(c)
1139 awful.titlebar(c) : setup {
1141 awful.titlebar.widget.iconwidget(c),
1143 layout = wibox.layout.fixed.horizontal
1148 widget = awful.titlebar.widget.titlewidget(c)
1151 layout = wibox.layout.flex.horizontal
1154 awful.titlebar.widget.floatingbutton (c),
1155 awful.titlebar.widget.maximizedbutton(c),
1156 awful.titlebar.widget.stickybutton (c),
1157 awful.titlebar.widget.ontopbutton (c),
1158 awful.titlebar.widget.closebutton (c),
1159 layout = wibox.layout.fixed.horizontal()
1161 layout = wibox.layout.align.horizontal
1165 -- Enable sloppy focus, so that focus follows mouse.
1166 client.connect_signal("mouse::enter", function(c)
1167 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
1168 and awful.client.focus.filter(c) then
1173 client.connect_signal("focus", function(c)
1174 c.border_color = beautiful.border_focus
1176 client.connect_signal("unfocus", function(c)
1177 c.border_color = beautiful.border_normal
1180 awful.ewmh.add_activate_filter(function(c, context, hints)
1181 if context == "ewmh" then
1182 if (c.class == "Firefox-esr" or c.class == "Firefox") then
1188 client.connect_signal("request::activate", function(c, context, hints)
1189 if gears.table.hasitem({
1190 "client.focus.byidx",
1192 "autofocus.check_focus",
1196 gears.timer.delayed_call(function()
1197 -- we need a delayed call so that we execute *after layout changes
1198 if hints.raise and c == client.focus and client.focus:isvisible() then
1199 move_mouse_to_area(client.focus)
1205 -- vim:ft=lua:sw=4:sts=4:ts=4:et