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.
3 -- Standard awesome library
4 local gears = require("gears")
5 local awful = require("awful")
6 require("awful.autofocus")
7 -- Widget and layout library
8 local wibox = require("wibox")
9 -- Tyrannical tab handling
10 --local tyrannical = require("tyrannical")
11 -- Theme handling library
12 local beautiful = require("beautiful")
13 local xrdb = beautiful.xresources
14 -- Notification library
15 local naughty = require("naughty")
16 local menubar = require("menubar")
17 local hotkeys_popup = require("awful.hotkeys_popup").widget
18 -- Enable hotkeys help widget for VIM and other apps
19 -- when client with a matching name is opened:
20 require("awful.hotkeys_popup.keys")
22 -- Load Debian menu entries
23 local debian = require("debian.menu")
24 local has_fdo, freedesktop = pcall(require, "freedesktop")
26 local lain = require("lain")
27 local ccwidgets = require("cryptocoin_widgets")
28 local fxwidgets = require("forex_widgets")
29 local clocksarray = require("clocksarray")
30 local dbg = require("debugfunc")
31 local th = require("taghelpers")
35 -- Check if awesome encountered an error during startup and fell back to
36 -- another config (This code will only ever execute for the fallback config)
37 if awesome.startup_errors then
38 naughty.notify({ preset = naughty.config.presets.critical,
39 title = "Oops, there were errors during startup!",
40 text = awesome.startup_errors })
43 -- Handle runtime errors after startup
45 local in_error = false
46 awesome.connect_signal("debug::error", function (err)
47 -- Make sure we don't go into an endless error loop
48 if in_error then return end
51 naughty.notify({ preset = naughty.config.presets.critical,
52 title = "Oops, an error happened!",
53 text = tostring(err) })
59 -- {{{ Variable definitions
60 --xrdb.set_dpi(95, screen[1])
61 --xrdb.set_dpi(120, screen[2])
63 -- Themes define colours, icons, font and wallpapers.
64 beautiful.init(gears.filesystem.get_configuration_dir () .. "theme/theme.lua")
66 -- This is used later as the default terminal and editor to run.
67 terminal = "rxvt-unicode"
68 editor = os.getenv("EDITOR") or "editor"
69 editor_cmd = terminal .. " -e " .. editor
72 -- Usually, Mod4 is the key with a logo between Control and Alt.
73 -- If you do not like this or do not have such a key,
74 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
75 -- However, you can use another modifier like Mod1, but it may interact with others.
79 -- Table of layouts to cover with awful.layout.inc, order matters.
81 default = awful.layout.suit.fair,
82 default_horiz = awful.layout.suit.fair.horizontal,
83 tiled = awful.layout.suit.tile,
84 tiled_horiz = awful.layout.suit.tile.top,
85 floating = awful.layout.suit.floating,
86 maximised = awful.layout.suit.max
88 awful.layout.layouts = {
93 layouts.default_horiz,
98 -- {{{ Helper functions
99 local function client_menu_toggle_fn()
103 if instance and instance.wibox.visible then
107 instance = awful.menu.clients({ theme = { width = 250 } })
112 local function set_wallpaper(s)
114 if beautiful.wallpaper then
115 local wallpaper = beautiful.wallpaper
116 -- If wallpaper is a function, call it with the screen
117 if type(wallpaper) == "function" then
118 wallpaper = wallpaper(s)
120 gears.wallpaper.maximized(wallpaper, s, true)
124 local function move_mouse_to_area(a)
125 local coords = mouse.coords()
126 if (coords.x < a.x or
127 coords.x > (a.x+a.width) or
129 coords.y > (a.y+a.height)) then
133 y = a.y + a.height/2,
141 -- Create a launcher widget and a main menu
143 { "hotkeys", function() return false, hotkeys_popup.show_help end},
144 { "manual", terminal .. " -e man awesome" },
145 { "edit config", editor_cmd .. " " .. awesome.conffile },
146 { "restart", awesome.restart },
147 { "quit", function() awesome.quit() end}
150 local menu_awesome = { "awesome", myawesomemenu, beautiful.awesome_icon }
151 local menu_terminal = { "open terminal", terminal }
154 mymainmenu = freedesktop.menu.build({
155 before = { menu_awesome },
156 after = { menu_terminal }
159 mymainmenu = awful.menu({
162 { "Debian", debian.menu.Debian_menu.Debian },
169 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
172 -- Menubar configuration
173 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
177 --local spacer = wibox.widget {
178 -- color = beautiful.bg_minimize,
180 -- widget = wibox.widget.separator
182 local function make_spacer(text)
183 local spacer = wibox.widget.textbox()
184 spacer:set_text(text or " │ ")
188 -- Keyboard map indicator and switcher
189 mykeyboardlayout = awful.widget.keyboardlayout()
191 local lain_bat = lain.widget.bat({
192 batteries = {"BAT0", "BAT1"},
193 settings = function()
195 if bat_now.status == "Charging" then delim = "↑"
196 elseif bat_now.status == "Unknown" then delim = "٭" end
197 widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
201 -- Create a textclock widget
202 clocksarray = clocksarray.get_clocksarray("%a %d %b %H:%M:%S %Z", {
203 -- ["NZ"] = "Pacific/Auckland",
204 ["DE"] = "Europe/Berlin"
207 -- Create a wibox for each screen and add it
208 local taglist_buttons = gears.table.join(
209 awful.button({ }, 1, function(t) t:view_only() end),
210 awful.button({ modkey }, 1, function(t)
212 client.focus:move_to_tag(t)
215 awful.button({ }, 3, awful.tag.viewtoggle),
216 awful.button({ modkey }, 3, function(t)
218 client.focus:toggle_tag(t)
221 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
222 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
225 local tasklist_buttons = gears.table.join(
226 awful.button({ }, 1, function (c)
227 if c == client.focus then
228 -- I don't like click-minimising
229 -- c.minimized = true
231 -- Without this, the following
232 -- :isvisible() makes no sense
234 if not c:isvisible() and c.first_tag then
235 c.first_tag:view_only()
237 -- This will also un-minimize
238 -- the client, if needed
243 awful.button({ }, 3, client_menu_toggle_fn()),
244 awful.button({ }, 4, function ()
245 awful.client.focus.byidx(1)
247 awful.button({ }, 5, function ()
248 awful.client.focus.byidx(-1)
254 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
255 screen.connect_signal("property::geometry", set_wallpaper)
257 -- {{{ Basic setup for screens
258 local function screen_set_profile(s, profile)
260 s.outputstr = table.concat(gears.table.keys(s.outputs), "+")
261 s.name = s.profile .. "/" .. s.outputstr
264 awful.screen.connect_for_each_screen(function(s)
266 s.set_profile = screen_set_profile
271 -- Create a text widget to display screen name
272 s.namebox = wibox.container.background(wibox.widget.textbox(s.name),
273 beautiful.bg_minimize)
275 -- Create a promptbox for each screen
276 s.mypromptbox = awful.widget.prompt()
277 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
278 -- We need one layoutbox per screen.
279 s.mylayoutbox = awful.widget.layoutbox(s)
280 s.mylayoutbox:buttons(awful.util.table.join(
281 awful.button({ }, 1, function () awful.layout.inc( 1) end),
282 awful.button({ }, 3, function () awful.layout.inc(-1) end),
283 awful.button({ }, 4, function () awful.layout.inc( 1) end),
284 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
285 -- Create a taglist widget
286 s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
288 -- Create a tasklist widget
289 s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
291 -- Create the wibox, but only if there isn't one yet
292 if not s.mywibox then
293 s.mywibox = awful.wibar({ position = "top", screen = s })
296 -- Add widgets to the wibox
297 local right_widgets = gears.table.join(clocksarray, {
299 wibox.widget.systray(),
301 layout = wibox.layout.fixed.horizontal,
304 -- if s == screen.primary then
305 right_widgets = gears.table.join({
307 ccwidgets.btc_widget,
309 ccwidgets.eth_widget,
311 fxwidgets.ecb_widget,
319 layout = wibox.layout.align.horizontal,
321 layout = wibox.layout.fixed.horizontal,
327 s.mytasklist, -- Middle widget
332 -- {{{ autorandr integration
333 local function find_screen_by_pattern(pattern)
335 print(s.name .. " :: " .. pattern)
336 if s.name:match(pattern) then
342 local function get_target_screen_for_tag(tag)
343 local function primary_screen(reason)
344 local s = screen.primary
345 local msg = " → primary screen \"" .. s.name .. "\""
346 if reason then msg = msg .. " (" .. reason .. ")" end
351 print("Figuring out target screen for tag " .. tag.name .. "…")
353 if type(tag.targets) == "table" then
354 for _,target in ipairs(tag.targets) do
355 local s = find_screen_by_pattern(target:gsub('%-', '%%-'))
357 print(" → screen " .. s.name)
361 elseif tag.targets == "primary" then
362 return primary_screen("explicit request")
364 return primary_screen("no matching target in " .. table.concat(tag.targets, ","))
366 return primary_screen("no targets specified")
370 local function move_tag_to_target_screen(tag)
371 tag.screen = get_target_screen_for_tag(tag)
374 local function move_tags_to_target_screens()
375 for _,tag in ipairs(root.tags()) do
376 move_tag_to_target_screen(tag)
380 tag.connect_signal("request::screen", function(t)
381 -- throw the tag onto any other screen, it'll get reassigned later when
382 -- a new profile has been processed.
384 if s ~= t.screen then
391 title = "Screen removed",
392 text = "Salvaged tab " .. t.name,
396 function handle_new_autorandr_profile(newprofile)
397 -- The main idea here is that autorandr invokes this via awesome-client
398 -- after switching to a new profile. Awesome will have already set up all
399 -- the screens long before this function is called. Therefore, we just do
400 -- the necessary modifications to the existing screens, and move tags
403 if not newprofile then
404 error("Missing new profile name")
408 preset = naughty.config.presets.low,
409 title = "New autorandr profile",
410 text = "Reconfiguring for profile <b>" .. newprofile .. "</b>",
414 s:set_profile(newprofile)
416 move_tags_to_target_screens()
419 local function initialise_to_autorandr_profile()
423 local function process_line(line)
424 if profile then return end
425 local match = string.match(line, "^([^%s]+) %(detected%)")
431 local function output_done()
433 error("autorandr detected no profile")
436 handle_new_autorandr_profile(profile)
439 local function handle_exit(reason, code)
440 if not (reason == "exit" and code == 0) then
441 error("autorandr error: " .. reason .. ": " .. tostring(code))
445 awful.spawn.with_line_callback('autorandr', {
446 stdout = process_line,
447 output_done = output_done,
451 awesome.connect_signal("startup", initialise_to_autorandr_profile)
458 local default_tag = {
461 layout = layouts.default,
465 local default_tags = {}
468 for k,v in pairs(default_tag) do
469 default_tags[i][k] = v
471 default_tags[i].name = tostring(i)
473 default_tags[1].selected = true
475 default_tags = gears.table.join(default_tags, {
480 layout = layouts.tiled,
482 exec_once = { terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh --family=all -- irc-host tmux new -As irc irssi" },
483 instance = { "irc" },
488 "krafftwerk/DP-?1-1-5",
489 "krafftwerk/DisplayPort-2",
499 layout = layouts.tiled,
505 "krafftwerk/DP-?1-1-5",
506 "krafftwerk/DisplayPort-2",
514 layout = layouts.floating,
522 layout = layouts.default,
523 exec_once = { "thunderbird" },
524 class = { "thunderbird" },
529 "krafftwerk/DP-?1-1-6",
530 "krafftwerk/DisplayPort-0",
538 layout = layouts.default,
539 exec_once = { "chromium" },
540 class = { "Chromium" },
545 "krafftwerk/DP-?1-1-6",
546 "krafftwerk/DisplayPort-0",
555 layout = layouts.default,
556 exec_once = { "firefox" },
557 class = { "Firefox" },
562 "krafftwerk/DP-?1-1-6",
563 "krafftwerk/DisplayPort-0",
570 if not tyrannical then
572 for _,t in ipairs(default_tags) do
574 t.screen = t.screen or screen.primary
575 t.layout = t.layout or layouts.default
576 local newt = th.add_tag(t.name, t, false)
580 else -- {{{ tyrannical is loaded
581 tyrannical.settings.default_layout = layouts.default
582 tyrannical.settings.master_width_factor = 0.5
583 tyrannical.settings.block_children_focus_stealing = true
584 tyrannical.settings.group_children = true
586 tyrannical.tags = default_tags
588 tyrannical.properties.size_hints_honor = { URxvt = false }
590 --XX---- Ignore the tag "exclusive" property for the following clients (matched by classes)
591 --XX--tyrannical.properties.intrusive = {
592 --XX-- "ksnapshot" , "pinentry" , "gtksu" , "kcalc" , "xcalc" ,
593 --XX-- "feh" , "Gradient editor", "About KDE" , "Paste Special", "Background color" ,
594 --XX-- "kcolorchooser" , "plasmoidviewer" , "Xephyr" , "kruler" , "plasmaengineexplorer",
597 --XX---- Ignore the tiled layout for the matching clients
598 --XX--tyrannical.properties.floating = {
599 --XX-- "MPlayer" , "pinentry" , "ksnapshot" , "pinentry" , "gtksu" ,
600 --XX-- "xine" , "feh" , "kmix" , "kcalc" , "xcalc" ,
601 --XX-- "yakuake" , "Select Color$" , "kruler" , "kcolorchooser", "Paste Special" ,
602 --XX-- "New Form" , "Insert Picture" , "kcharselect", "mythfrontend" , "plasmoidviewer"
605 --XX---- Make the matching clients (by classes) on top of the default layout
606 --XX--tyrannical.properties.ontop = {
607 --XX-- "Xephyr" , "ksnapshot" , "kruler"
610 --XX---- Force the matching clients (by classes) to be centered on the screen on init
611 --XX--tyrannical.properties.centered = {
618 -- {{{ Mouse bindings
619 root.buttons(gears.table.join(
620 awful.button({ }, 3, function () mymainmenu:toggle() end),
621 awful.button({ }, 4, awful.tag.viewnext),
622 awful.button({ }, 5, awful.tag.viewprev)
628 local function toggle_tag_by_name(tagname, exclusive)
630 local t = awful.tag.find_by_name(nil, tagname)
635 awful.tag.viewtoggle(t)
637 cf = awful.client.getmaster(t.screen)
645 local function move_tags_to_screen_relative(direction)
646 local s = awful.screen.focused()
647 for _,tag in ipairs(s.selected_tags) do
648 print("index: " .. s.index .. " count: " .. screen:count())
649 tag.screen = screen[(s.index + screen:count() + direction) % screen.count()]
653 globalkeys = gears.table.join(
654 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
655 {description="show help", group="awesome"}),
656 awful.key({ modkey, }, "Left", awful.tag.viewprev,
657 {description = "view previous", group = "tag"}),
658 awful.key({ modkey, }, "Right", awful.tag.viewnext,
659 {description = "view next", group = "tag"}),
660 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
661 {description = "go back", group = "tag"}),
663 awful.key({ modkey, }, "k",
665 awful.client.focus.byidx( 1)
667 {description = "focus next by index", group = "client"}
669 awful.key({ modkey, }, "j",
671 awful.client.focus.byidx(-1)
673 {description = "focus previous by index", group = "client"}
676 -- Layout manipulation
677 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
678 {description = "swap with next client by index", group = "client"}),
679 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx(-1) end,
680 {description = "swap with previous client by index", group = "client"}),
681 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
682 {description = "focus the next screen", group = "screen"}),
683 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
684 {description = "focus the previous screen", group = "screen"}),
685 awful.key({ modkey, "Shift", "Control" }, "k", function () move_tags_to_screen_relative( 1) end,
686 {description = "move tags to the next screen", group = "screen"}),
687 awful.key({ modkey, "Shift", "Control" }, "j", function () move_tags_to_screen_relative(-1) end,
688 {description = "move tags to the previous screen", group = "screen"}),
689 awful.key({ modkey, "Shift" }, "Return", awful.client.urgent.jumpto,
690 {description = "jump to urgent client", group = "client"}),
691 awful.key({ modkey, }, "Tab",
693 awful.client.focus.history.previous()
698 {description = "go back", group = "client"}),
701 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
702 {description = "open a terminal", group = "launcher"}),
703 awful.key({ modkey, }, "r", function()
704 package.loaded.rc = nil
707 {description = "reload rc.lua", group = "awesome"}),
708 awful.key({ modkey, "Control" }, "r", awesome.restart,
709 {description = "reload awesome", group = "awesome"}),
710 awful.key({ modkey, "Shift" }, "q", awesome.quit,
711 {description = "quit awesome", group = "awesome"}),
713 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
714 {description = "increase master width factor", group = "layout"}),
715 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
716 {description = "decrease master width factor", group = "layout"}),
717 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
718 {description = "increase the number of master clients", group = "layout"}),
719 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
720 {description = "decrease the number of master clients", group = "layout"}),
721 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
722 {description = "increase the number of columns", group = "layout"}),
723 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
724 {description = "decrease the number of columns", group = "layout"}),
725 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
726 {description = "select next", group = "layout"}),
727 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
728 {description = "select previous", group = "layout"}),
730 awful.key({ modkey, "Control" }, "n",
732 local c = awful.client.restore()
733 -- Focus restored client
739 {description = "restore minimized", group = "client"}),
742 awful.key({ cmdkey }, "r",
744 local widget = awful.screen.focused().mypromptbox.widget
745 local function spawn(command, args)
746 gears.debug.dump(args)
747 awful.spawn(command, args)
752 bg_cursor = '#ff0000',
754 history_path = awful.util.get_cache_dir() .. "/history",
755 completion_callback = awful.completion.shell,
757 -- Replace the 'normal' Return with a custom one
758 {{ }, 'Return', function(command)
761 -- Spawn method to spawn in the current tag
762 {{'Mod1' }, 'Return', function(command)
765 tag = mouse.screen.selected_tag
768 -- Spawn in the current tag as floating and on top
769 {{'Shift' }, 'Return', function(command)
773 tag = mouse.screen.selected_tag
776 -- Spawn in a new tag
777 {{'Control'}, 'Return', function(command)
780 layout = layouts.default,
785 {{ }, 'Escape', function(_) return end},
789 {description = "run prompt", group = "launcher"}),
791 awful.key({ modkey }, "x",
795 bg_cursor = '#ff0000',
796 textbox = awful.screen.focused().mypromptbox.widget,
797 exe_callback = awful.util.eval,
798 history_path = awful.util.get_cache_dir() .. "/history_eval"
801 {description = "lua execute prompt", group = "awesome"}),
803 awful.key({ modkey }, "w", function() menubar.show() end,
804 {description = "show the menubar", group = "launcher"}),
807 awful.key({ modkey, }, "a", function()
808 th.add_tag(nil, {layout=layouts.default} ,true)
810 {description = "add a tag", group = "tag"}),
811 awful.key({ modkey, }, "d", th.delete_tag,
812 {description = "delete the current tag", group = "tag"}),
813 awful.key({ modkey, "Shift", }, "a", function()
814 th.move_to_new_tag(nil, nil, { layout = layouts.maximised },true,true,true)
816 {description = "add a volatile tag with the focused client", group = "tag"}),
817 awful.key({ modkey, "Shift", "Control" }, "a", function()
818 th.move_to_new_tag(nil, nil, { layout = layouts.maximised },false,true,true)
820 {description = "add a permanent tag with the focused client", group = "tag"}),
821 awful.key({ modkey, "Mod1" }, "a", th.copy_tag,
822 {description = "create a copy of the current tag", group = "tag"}),
823 awful.key({ modkey, "Control" }, "a", th.rename_tag,
824 {description = "rename the current tag", group = "tag"}),
825 awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
826 {description = "collect all orphaned clients", group = "client"}),
828 awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
829 {description = "view tag 'irc'", group = "tag"}),
830 awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
831 {description = "toggle tag 'irc'", group = "tag"}),
832 awful.key({ modkey }, "u", toggle_tag_by_name("[]", true),
833 {description = "view tag '[]'", group = "tag"}),
834 awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[]"),
835 {description = "toggle tag '[]'", group = "tag"}),
836 awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
837 {description = "view tag 'cal'", group = "tag"}),
838 awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
839 {description = "toggle tag 'cal'", group = "tag"}),
840 awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
841 {description = "view tag 'chr'", group = "tag"}),
842 awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
843 {description = "toggle tag 'chr'", group = "tag"}),
844 awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
845 {description = "view tag 'ff'", group = "tag"}),
846 awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
847 {description = "toggle tag 'ff'", group = "tag"}),
850 clientkeys = gears.table.join(
851 awful.key({ modkey, }, "f",
853 c.fullscreen = not c.fullscreen
856 {description = "toggle fullscreen", group = "client"}),
857 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
858 {description = "close", group = "client"}),
859 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
860 {description = "toggle floating", group = "client"}),
861 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
862 {description = "move to master", group = "client"}),
863 awful.key({ modkey, }, "z", function (c) c:move_to_screen() end,
864 {description = "move to screen", group = "client"}),
865 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
866 {description = "toggle keep on top", group = "client"}),
867 awful.key({ modkey, }, "n",
869 -- The client currently has the input focus, so it cannot be
870 -- minimized, since minimized clients can't have the focus.
873 {description = "minimize", group = "client"}),
874 awful.key({ modkey, }, "m",
876 c.maximized = not c.maximized
877 c.maximized_horizontal = false
878 c.maximized_vertical = false
881 {description = "(un)maximize", group = "client"}),
882 awful.key({ modkey, "Control" }, "m",
884 c.maximized_vertical = not c.maximized_vertical
887 {description = "(un)maximize vertically", group = "client"}),
888 awful.key({ modkey, "Shift" }, "m",
890 c.maximized_horizontal = not c.maximized_horizontal
893 {description = "(un)maximize horizontally", group = "client"})
896 -- Bind all key numbers to tags.
897 -- Be careful: we use keycodes to make it work on any keyboard layout.
898 -- This should map on the top row of your keyboard, usually 1 to 9.
900 globalkeys = gears.table.join(globalkeys,
902 awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
903 {description = "view tag #"..i, group = "tag"}),
904 -- Toggle tag display.
905 awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
906 {description = "toggle tag #" .. i, group = "tag"}),
907 -- Move client to tag.
908 awful.key({ modkey, "Shift" }, "#" .. i + 9,
911 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
913 client.focus:move_to_tag(tag)
917 {description = "move focused client to tag #"..i, group = "tag"}),
918 -- Toggle tag on focused client.
919 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
922 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
924 client.focus:toggle_tag(tag)
928 {description = "toggle focused client on tag #" .. i, group = "tag"})
932 clientbuttons = gears.table.join(
933 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
934 awful.button({ modkey }, 1, awful.mouse.client.move),
935 awful.button({ modkey }, 3, awful.mouse.client.resize))
938 globalkeys = awful.util.table.join(globalkeys,
939 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
940 awful.key({ cmdkey }, "c", function () awful.spawn("chromium --enable-remote-extensions") end),
941 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e ipython3") end),
942 awful.key({ cmdkey }, "m", function () awful.spawn(terminal .. " -name mutt -e mutt") end),
943 awful.key({ cmdkey }, "t", function () awful.spawn("thunderbird") end),
944 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
945 awful.key({ cmdkey, "Shift" }, "v", function () awful.spawn("virt-manager") end),
946 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
947 awful.key({ cmdkey }, "v", function () awful.spawn("remmina") end),
948 awful.key({ cmdkey }, "p", function () awful.spawn("pavucontrol") end),
949 awful.key({ cmdkey }, "i", function () awful.spawn(terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh --family=all -- irc-host tmux new -As irc irssi") end),
950 awful.key({ cmdkey }, "x", function ()
951 awful.spawn("xautolock -enable")
952 awful.spawn("xautolock -locknow")
954 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xautolock -disable") end),
956 awful.key({ cmdkey }, "BackSpace", function () awful.spawn("pkill -USR1 offlineimap") end),
959 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
960 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
961 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
962 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
963 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
964 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
965 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
966 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
967 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
968 awful.key({ cmdkey }, "Insert", function () awful.spawn("pa_cycle_default source") end),
969 awful.key({ cmdkey }, "Delete", function () awful.spawn("pa_cycle_default sink") end),
970 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("light -U 10") end),
971 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("light -A 10") end),
972 awful.key(nil, "XF86Display", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
973 awful.key(nil, "XF86AudioStop", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
974 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
975 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
976 awful.key(nil, "XF86Search", function () awful.spawn("") end),
977 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
978 awful.key(nil, "XF86Explorer", function () awful.spawn("") end),
979 awful.key(nil, "XF86Calculator", function () awful.spawn(terminal .. " -e ipython3 --profile=calc") end),
980 awful.key(nil, "XF86Favorites", function () awful.spawn("systemctl suspend") end),
982 awful.key({ cmdkey }, "Multi_key", function () run_output_notify("flameshot gui", "Output") end),
983 awful.key({ cmdkey, "Shift" }, "Multi_key", function () run_output_notify("flameshot full --delay 2000 --clipboard", "Output") end),
985 awful.key({ cmdkey }, "Up", function () awful.spawn("pap prev") end),
986 awful.key({ cmdkey }, "Left", function () awful.spawn("pap seek -10") end),
987 awful.key({ cmdkey, "Shift" }, "Left", function () awful.spawn("pap seek -60") end),
988 awful.key({ cmdkey }, "Down", function () awful.spawn("pap next") end),
989 awful.key({ cmdkey }, "Right", function () awful.spawn("pap seek +10") end),
990 awful.key({ cmdkey, "Shift" }, "Right", function () awful.spawn("pap seek +60") end),
991 awful.key({ cmdkey }, "space", function () awful.spawn("pap pause") end),
992 awful.key({ cmdkey }, "\\", function () run_output_notify("pap info", "Track info") end),
993 awful.key({ cmdkey }, "]", function () run_output_notify("pap list", "Playlist") end)
996 function run_output_notify(cmd, title)
997 awful.spawn.easy_async(cmd, function(stdout, stderr, reason, exit_code)
1000 preset = naughty.config.presets.low,
1008 root.keys(globalkeys)
1012 -- Rules to apply to new clients (through the "manage" signal).
1014 local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
1015 local wa = client.screen.workarea
1017 client.y = wa.y + topbottom
1018 client.height = wa.height - 2*topbottom
1020 client.y = wa.y + (wa.height - client.height)/2
1023 client.x = wa.x + leftright
1024 client.width = wa.width - 2*leftright
1026 client.x = wa.x + (wa.width - client.width)/2
1030 local function move_to_tag_by_name(s, tagname)
1032 local t = awful.tag.find_by_name(s, tagname)
1034 error("No tag by the name of " .. tagname)
1041 local function move_to_tag_or_create_volatile(s, tagname)
1043 local t = awful.tag.find_by_name(s, tagname)
1047 th.move_to_new_tag(c, tagname, {}, true, true, true)
1052 awful.rules.rules = {
1053 -- All clients will match this rule.
1055 properties = { border_width = beautiful.border_width,
1056 border_color = beautiful.border_normal,
1057 focus = awful.client.focus.filter,
1060 buttons = clientbuttons,
1061 screen = awful.screen.preferred,
1062 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
1067 { rule = { type = "dialog" },
1068 properties = { floating = true,
1070 skip_taskbar = true,
1073 --switchtotag = true,
1074 placement = awful.placement.centered
1077 { rule = { class = "URxvt" },
1078 properties = { size_hints_honor = false, }
1080 { rule = { instance = "irc" },
1081 callback = move_to_tag_by_name(nil, "irc"),
1083 { rule = { class = "scrcpy" },
1084 callback = move_to_tag_by_name(nil, "[]"),
1086 { rule_any = { class = { "Firefox", "firefox" } },
1087 callback = move_to_tag_by_name(nil, "ffx"),
1089 { rule = { class = "Chromium" },
1090 callback = move_to_tag_by_name(nil, "chr"),
1092 { rule_any = { class = { "thunderbird", "Thunderbird" } },
1093 callback = move_to_tag_by_name(nil, "cal"),
1095 { rule = { instance = "mutt" },
1099 layout = awful.layout.suit.fair.horizontal,
1105 { rule_any = { class = { "zoom" } },
1106 callback = move_to_tag_or_create_volatile(nil, "Zoom"),
1108 { rule_any = { class = { "Ssvnc.tcl" },
1109 class = { "Ssvnc" },
1110 name = { "SSL/SSH VNC Viewer.-" },
1112 callback = move_to_tag_or_create_volatile(nil, "SSVNC"),
1114 { rule_any = { class = {
1118 properties = { floating = true,
1121 placement = awful.placement.centered,
1124 { rule_any = { instance = {
1130 properties = { floating = true,
1133 placement = awful.placement.centered,
1136 { rule_any = { class = {
1141 "Microsoft Teams - Preview",
1142 "org.remmina.Remmina",
1148 except_any = { type = { "dialog" } },
1149 properties = { new_tag = {
1150 layout = layouts.maximised,
1153 --switchtotag = true,
1157 { rule_any = { class = {
1161 except_any = { type = { "dialog" } },
1162 properties = { new_tag = {
1163 layout = layouts.default,
1169 placement = awful.placement.centered,
1174 --XX-- { rule = { class = "Gscan2pdf" },
1175 --XX-- properties = {
1176 --XX-- switchtotag = true
1178 --XX-- callback = move_to_tag(1, 5)
1180 --XX-- { rule = { name = "gscan2pdf .*" },
1181 --XX-- properties = {
1182 --XX-- floating = false,
1185 --XX-- { rule = { class = "Thunar", type = "normal" },
1186 --XX-- properties = {
1187 --XX-- floating = false,
1190 --XX-- { rule = { class = "Pinentry", instance = "pinentry" },
1191 --XX-- properties = {
1192 --XX-- floating = true,
1195 --XX-- { rule = { class = "Gxmessage" },
1196 --XX-- properties = {
1197 --XX-- floating = true,
1205 -- Signal function to execute when a new client appears.
1206 client.connect_signal("manage", function (c)
1207 -- Set the windows at the slave,
1208 -- i.e. put it at the end of others instead of setting it master.
1209 -- if not awesome.startup then awful.client.setslave(c) end
1210 --if not awesome.startup then
1211 -- local t = awful.screen.focused().selected_tag
1212 -- if t.name == "xmutt" then
1213 -- awful.client.setslave(c)
1217 if awesome.startup and
1218 not c.size_hints.user_position
1219 and not c.size_hints.program_position then
1220 -- Prevent clients from being unreachable after screen count changes.
1221 awful.placement.no_offscreen(c)
1224 c.maximized_horizontal = false
1225 c.maximized_vertical = false
1228 -- Add a titlebar if titlebars_enabled is set to true in the rules.
1229 client.connect_signal("request::titlebars", function(c)
1230 -- buttons for the titlebar
1231 local buttons = gears.table.join(
1232 awful.button({ }, 1, function()
1235 awful.mouse.client.move(c)
1237 awful.button({ }, 3, function()
1240 awful.mouse.client.resize(c)
1244 awful.titlebar(c) : setup {
1246 awful.titlebar.widget.iconwidget(c),
1248 layout = wibox.layout.fixed.horizontal
1253 widget = awful.titlebar.widget.titlewidget(c)
1256 layout = wibox.layout.flex.horizontal
1259 awful.titlebar.widget.floatingbutton (c),
1260 awful.titlebar.widget.maximizedbutton(c),
1261 awful.titlebar.widget.stickybutton (c),
1262 awful.titlebar.widget.ontopbutton (c),
1263 awful.titlebar.widget.closebutton (c),
1264 layout = wibox.layout.fixed.horizontal()
1266 layout = wibox.layout.align.horizontal
1270 -- Enable sloppy focus, so that focus follows mouse.
1271 client.connect_signal("mouse::enter", function(c)
1272 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
1273 and awful.client.focus.filter(c) then
1276 --17 18:03 < psychon> madduck: yes. In the default config at the very end there is code that actives a client on mouse::enter. Just add if c.class == "whatever virt-viewer uses" then return end to that, or
1277 -- something like this
1280 client.connect_signal("focus", function(c)
1281 c.border_color = beautiful.border_focus
1283 client.connect_signal("unfocus", function(c)
1284 c.border_color = beautiful.border_normal
1287 awful.ewmh.add_activate_filter(function(c, context, hints)
1288 if context == "ewmh" then
1289 if (c.class == "Firefox-esr" or c.class == "Firefox") then
1295 client.connect_signal("request::activate", function(c, context, hints)
1296 if gears.table.hasitem({
1297 "client.focus.byidx",
1299 "autofocus.check_focus",
1303 gears.timer.delayed_call(function()
1304 -- we need a delayed call so that we execute *after layout changes
1305 if hints.raise and c == client.focus and client.focus:isvisible() then
1306 move_mouse_to_area(client.focus)
1312 -- vim:ft=lua:sw=4:sts=4:ts=4:et