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.maximised,
482 exec_once = { "remmina" },
483 instance = { "Remmina" },
488 "krafftwerk/DP-?1-1-5",
489 "krafftwerk/DisplayPort-2",
497 layout = layouts.tiled,
499 exec_once = { terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh --family=all -- irc-host tmux new -As irc irssi" },
500 instance = { "irc" },
505 "krafftwerk/DP-?1-1-5",
506 "krafftwerk/DisplayPort-2",
516 layout = layouts.tiled,
522 "krafftwerk/DP-?1-1-5",
523 "krafftwerk/DisplayPort-2",
531 layout = layouts.floating,
539 layout = layouts.default,
540 exec_once = { "thunderbird" },
541 class = { "thunderbird" },
546 "krafftwerk/DP-?1-1-6",
547 "krafftwerk/DisplayPort-0",
555 layout = layouts.default,
556 exec_once = { "chromium" },
557 class = { "Chromium" },
562 "krafftwerk/DP-?1-1-6",
563 "krafftwerk/DisplayPort-0",
572 layout = layouts.default,
573 exec_once = { "firefox" },
574 class = { "Firefox" },
579 "krafftwerk/DP-?1-1-6",
580 "krafftwerk/DisplayPort-0",
587 if not tyrannical then
589 for _,t in ipairs(default_tags) do
591 t.screen = t.screen or screen.primary
592 t.layout = t.layout or layouts.default
593 local newt = th.add_tag(t.name, t, false)
597 else -- {{{ tyrannical is loaded
598 tyrannical.settings.default_layout = layouts.default
599 tyrannical.settings.master_width_factor = 0.5
600 tyrannical.settings.block_children_focus_stealing = true
601 tyrannical.settings.group_children = true
603 tyrannical.tags = default_tags
605 tyrannical.properties.size_hints_honor = { URxvt = false }
607 --XX---- Ignore the tag "exclusive" property for the following clients (matched by classes)
608 --XX--tyrannical.properties.intrusive = {
609 --XX-- "ksnapshot" , "pinentry" , "gtksu" , "kcalc" , "xcalc" ,
610 --XX-- "feh" , "Gradient editor", "About KDE" , "Paste Special", "Background color" ,
611 --XX-- "kcolorchooser" , "plasmoidviewer" , "Xephyr" , "kruler" , "plasmaengineexplorer",
614 --XX---- Ignore the tiled layout for the matching clients
615 --XX--tyrannical.properties.floating = {
616 --XX-- "MPlayer" , "pinentry" , "ksnapshot" , "pinentry" , "gtksu" ,
617 --XX-- "xine" , "feh" , "kmix" , "kcalc" , "xcalc" ,
618 --XX-- "yakuake" , "Select Color$" , "kruler" , "kcolorchooser", "Paste Special" ,
619 --XX-- "New Form" , "Insert Picture" , "kcharselect", "mythfrontend" , "plasmoidviewer"
622 --XX---- Make the matching clients (by classes) on top of the default layout
623 --XX--tyrannical.properties.ontop = {
624 --XX-- "Xephyr" , "ksnapshot" , "kruler"
627 --XX---- Force the matching clients (by classes) to be centered on the screen on init
628 --XX--tyrannical.properties.centered = {
635 -- {{{ Mouse bindings
636 root.buttons(gears.table.join(
637 awful.button({ }, 3, function () mymainmenu:toggle() end),
638 awful.button({ }, 4, awful.tag.viewnext),
639 awful.button({ }, 5, awful.tag.viewprev)
645 local function toggle_tag_by_name(tagname, exclusive)
647 local t = awful.tag.find_by_name(nil, tagname)
652 awful.tag.viewtoggle(t)
654 cf = awful.client.getmaster(t.screen)
662 local function move_tags_to_screen_relative(direction)
663 local s = awful.screen.focused()
664 for _,tag in ipairs(s.selected_tags) do
665 print("index: " .. s.index .. " count: " .. screen:count())
666 tag.screen = screen[(s.index + screen:count() + direction) % screen.count()]
670 globalkeys = gears.table.join(
671 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
672 {description="show help", group="awesome"}),
673 awful.key({ modkey, }, "Left", awful.tag.viewprev,
674 {description = "view previous", group = "tag"}),
675 awful.key({ modkey, }, "Right", awful.tag.viewnext,
676 {description = "view next", group = "tag"}),
677 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
678 {description = "go back", group = "tag"}),
680 awful.key({ modkey, }, "k",
682 awful.client.focus.byidx( 1)
684 {description = "focus next by index", group = "client"}
686 awful.key({ modkey, }, "j",
688 awful.client.focus.byidx(-1)
690 {description = "focus previous by index", group = "client"}
693 -- Layout manipulation
694 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
695 {description = "swap with next client by index", group = "client"}),
696 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx(-1) end,
697 {description = "swap with previous client by index", group = "client"}),
698 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
699 {description = "focus the next screen", group = "screen"}),
700 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
701 {description = "focus the previous screen", group = "screen"}),
702 awful.key({ modkey, "Shift", "Control" }, "k", function () move_tags_to_screen_relative( 1) end,
703 {description = "move tags to the next screen", group = "screen"}),
704 awful.key({ modkey, "Shift", "Control" }, "j", function () move_tags_to_screen_relative(-1) end,
705 {description = "move tags to the previous screen", group = "screen"}),
706 awful.key({ modkey, "Shift" }, "Return", awful.client.urgent.jumpto,
707 {description = "jump to urgent client", group = "client"}),
708 awful.key({ modkey, }, "Tab",
710 awful.client.focus.history.previous()
715 {description = "go back", group = "client"}),
718 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
719 {description = "open a terminal", group = "launcher"}),
720 awful.key({ modkey, }, "r", function()
721 package.loaded.rc = nil
724 {description = "reload rc.lua", group = "awesome"}),
725 awful.key({ modkey, "Control" }, "r", awesome.restart,
726 {description = "reload awesome", group = "awesome"}),
727 awful.key({ modkey, "Shift" }, "q", awesome.quit,
728 {description = "quit awesome", group = "awesome"}),
730 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
731 {description = "increase master width factor", group = "layout"}),
732 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
733 {description = "decrease master width factor", group = "layout"}),
734 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
735 {description = "increase the number of master clients", group = "layout"}),
736 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
737 {description = "decrease the number of master clients", group = "layout"}),
738 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
739 {description = "increase the number of columns", group = "layout"}),
740 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
741 {description = "decrease the number of columns", group = "layout"}),
742 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
743 {description = "select next", group = "layout"}),
744 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
745 {description = "select previous", group = "layout"}),
747 awful.key({ modkey, "Control" }, "n",
749 local c = awful.client.restore()
750 -- Focus restored client
756 {description = "restore minimized", group = "client"}),
759 awful.key({ cmdkey }, "r",
761 local widget = awful.screen.focused().mypromptbox.widget
762 local function spawn(command, args)
763 gears.debug.dump(args)
764 awful.spawn(command, args)
769 bg_cursor = '#ff0000',
771 history_path = awful.util.get_cache_dir() .. "/history",
772 completion_callback = awful.completion.shell,
774 -- Replace the 'normal' Return with a custom one
775 {{ }, 'Return', function(command)
778 -- Spawn method to spawn in the current tag
779 {{'Mod1' }, 'Return', function(command)
782 tag = mouse.screen.selected_tag
785 -- Spawn in the current tag as floating and on top
786 {{'Shift' }, 'Return', function(command)
790 tag = mouse.screen.selected_tag
793 -- Spawn in a new tag
794 {{'Control'}, 'Return', function(command)
797 layout = layouts.default,
802 {{ }, 'Escape', function(_) return end},
806 {description = "run prompt", group = "launcher"}),
808 awful.key({ modkey }, "x",
812 bg_cursor = '#ff0000',
813 textbox = awful.screen.focused().mypromptbox.widget,
814 exe_callback = awful.util.eval,
815 history_path = awful.util.get_cache_dir() .. "/history_eval"
818 {description = "lua execute prompt", group = "awesome"}),
820 awful.key({ modkey }, "w", function() menubar.show() end,
821 {description = "show the menubar", group = "launcher"}),
824 awful.key({ modkey, }, "a", function()
825 th.add_tag(nil, {layout=layouts.default} ,true)
827 {description = "add a tag", group = "tag"}),
828 awful.key({ modkey, }, "d", th.delete_tag,
829 {description = "delete the current tag", group = "tag"}),
830 awful.key({ modkey, "Shift", }, "a", function()
831 th.move_to_new_tag(nil, nil, { layout = layouts.maximised },true,true,true)
833 {description = "add a volatile tag with the focused client", group = "tag"}),
834 awful.key({ modkey, "Shift", "Control" }, "a", function()
835 th.move_to_new_tag(nil, nil, { layout = layouts.maximised },false,true,true)
837 {description = "add a permanent tag with the focused client", group = "tag"}),
838 awful.key({ modkey, "Mod1" }, "a", th.copy_tag,
839 {description = "create a copy of the current tag", group = "tag"}),
840 awful.key({ modkey, "Control" }, "a", th.rename_tag,
841 {description = "rename the current tag", group = "tag"}),
842 awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
843 {description = "collect all orphaned clients", group = "client"}),
845 awful.key({ modkey }, "t", toggle_tag_by_name("vrt", true),
846 {description = "view tag 'vrt'", group = "tag"}),
847 awful.key({ modkey, "Control" }, "t", toggle_tag_by_name("vrt"),
848 {description = "toggle tag 'vrt'", group = "tag"}),
849 awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
850 {description = "view tag 'irc'", group = "tag"}),
851 awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
852 {description = "toggle tag 'irc'", group = "tag"}),
853 awful.key({ modkey }, "u", toggle_tag_by_name("[]", true),
854 {description = "view tag '[]'", group = "tag"}),
855 awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[]"),
856 {description = "toggle tag '[]'", group = "tag"}),
857 awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
858 {description = "view tag 'cal'", group = "tag"}),
859 awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
860 {description = "toggle tag 'cal'", group = "tag"}),
861 awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
862 {description = "view tag 'chr'", group = "tag"}),
863 awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
864 {description = "toggle tag 'chr'", group = "tag"}),
865 awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
866 {description = "view tag 'ff'", group = "tag"}),
867 awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
868 {description = "toggle tag 'ff'", group = "tag"}),
871 clientkeys = gears.table.join(
872 awful.key({ modkey, }, "f",
874 c.fullscreen = not c.fullscreen
877 {description = "toggle fullscreen", group = "client"}),
878 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
879 {description = "close", group = "client"}),
880 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
881 {description = "toggle floating", group = "client"}),
882 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
883 {description = "move to master", group = "client"}),
884 awful.key({ modkey, }, "z", function (c) c:move_to_screen() end,
885 {description = "move to screen", group = "client"}),
886 --awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
887 -- {description = "toggle keep on top", group = "client"}),
888 awful.key({ modkey, }, "n",
890 -- The client currently has the input focus, so it cannot be
891 -- minimized, since minimized clients can't have the focus.
894 {description = "minimize", group = "client"}),
895 awful.key({ modkey, }, "m",
897 c.maximized = not c.maximized
898 c.maximized_horizontal = false
899 c.maximized_vertical = false
902 {description = "(un)maximize", group = "client"}),
903 awful.key({ modkey, "Control" }, "m",
905 c.maximized_vertical = not c.maximized_vertical
908 {description = "(un)maximize vertically", group = "client"}),
909 awful.key({ modkey, "Shift" }, "m",
911 c.maximized_horizontal = not c.maximized_horizontal
914 {description = "(un)maximize horizontally", group = "client"})
917 -- Bind all key numbers to tags.
918 -- Be careful: we use keycodes to make it work on any keyboard layout.
919 -- This should map on the top row of your keyboard, usually 1 to 9.
921 globalkeys = gears.table.join(globalkeys,
923 awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
924 {description = "view tag #"..i, group = "tag"}),
925 -- Toggle tag display.
926 awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
927 {description = "toggle tag #" .. i, group = "tag"}),
928 -- Move client to tag.
929 awful.key({ modkey, "Shift" }, "#" .. i + 9,
932 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
934 client.focus:move_to_tag(tag)
938 {description = "move focused client to tag #"..i, group = "tag"}),
939 -- Toggle tag on focused client.
940 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
943 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
945 client.focus:toggle_tag(tag)
949 {description = "toggle focused client on tag #" .. i, group = "tag"})
953 clientbuttons = gears.table.join(
954 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
955 awful.button({ modkey }, 1, awful.mouse.client.move),
956 awful.button({ modkey }, 3, awful.mouse.client.resize))
959 globalkeys = awful.util.table.join(globalkeys,
960 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
961 awful.key({ cmdkey }, "c", function () awful.spawn("chromium --enable-remote-extensions") end),
962 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e ipython3") end),
963 awful.key({ cmdkey }, "m", function () awful.spawn(terminal .. " -name mutt -e mutt") end),
964 awful.key({ cmdkey }, "t", function () awful.spawn("thunderbird") end),
965 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
966 awful.key({ cmdkey, "Shift" }, "v", function () awful.spawn("virt-manager") end),
967 awful.key({ cmdkey, "Shift" }, "r", function () awful.spawn("remmina") end),
968 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
969 awful.key({ cmdkey }, "v", function () awful.spawn("virt-viewer") end),
970 awful.key({ cmdkey }, "p", function () awful.spawn("pavucontrol") end),
971 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),
972 awful.key({ cmdkey }, "x", function ()
973 run_output_notify("sh -c '. ~/.xsession.d/10-xautolock; echo \"Locking…\"; sleep 1; xautolock -locknow'", "Enabling xautolock")
975 awful.key({ cmdkey, "Shift" }, "x", function () run_output_notify("pkill -e xautolock", "Disabling xautolock") end),
977 awful.key({ cmdkey }, "BackSpace", function () awful.spawn("pkill -USR1 offlineimap") end),
980 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
981 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
982 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
983 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
984 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
985 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
986 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
987 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
988 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
989 awful.key({ cmdkey }, "Insert", function () awful.spawn("pa_cycle_default source") end),
990 awful.key({ cmdkey }, "Delete", function () awful.spawn("pa_cycle_default sink") end),
991 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("light -U 10") end),
992 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("light -A 10") end),
993 awful.key(nil, "XF86Display", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
994 awful.key(nil, "XF86AudioStop", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
995 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
996 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
997 awful.key(nil, "XF86Search", function () awful.spawn("") end),
998 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
999 awful.key(nil, "XF86Explorer", function () awful.spawn("") end),
1000 awful.key(nil, "XF86Calculator", function () awful.spawn(terminal .. " -e ipython3 --profile=calc") end),
1001 awful.key(nil, "XF86Favorites", function () awful.spawn("systemctl suspend") end),
1003 awful.key({ cmdkey }, "Multi_key", function () run_output_notify("flameshot gui", "Output") end),
1004 awful.key({ cmdkey, "Shift" }, "Multi_key", function () run_output_notify("flameshot full --delay 2000 --clipboard", "Output") end),
1006 awful.key({ cmdkey }, "Up", function () awful.spawn("pap prev") end),
1007 awful.key({ cmdkey }, "Left", function () awful.spawn("pap seek -10") end),
1008 awful.key({ cmdkey, "Shift" }, "Left", function () awful.spawn("pap seek -60") end),
1009 awful.key({ cmdkey }, "Down", function () awful.spawn("pap next") end),
1010 awful.key({ cmdkey }, "Right", function () awful.spawn("pap seek +10") end),
1011 awful.key({ cmdkey, "Shift" }, "Right", function () awful.spawn("pap seek +60") end),
1012 awful.key({ cmdkey }, "space", function () awful.spawn("pap pause") end),
1013 awful.key({ cmdkey }, "\\", function () run_output_notify("pap info", "Track info") end),
1014 awful.key({ cmdkey }, "]", function () run_output_notify("pap list", "Playlist") end)
1017 function run_output_notify(cmd, title)
1018 awful.spawn.easy_async(cmd, function(stdout, stderr, reason, exit_code)
1021 preset = naughty.config.presets.low,
1029 root.keys(globalkeys)
1033 -- Rules to apply to new clients (through the "manage" signal).
1035 local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
1036 local wa = client.screen.workarea
1038 client.y = wa.y + topbottom
1039 client.height = wa.height - 2*topbottom
1041 client.y = wa.y + (wa.height - client.height)/2
1044 client.x = wa.x + leftright
1045 client.width = wa.width - 2*leftright
1047 client.x = wa.x + (wa.width - client.width)/2
1051 local function move_to_tag_by_name(s, tagname)
1053 local t = awful.tag.find_by_name(s, tagname)
1055 error("No tag by the name of " .. tagname)
1062 local function move_to_tag_or_create_volatile(s, tagname)
1064 local t = awful.tag.find_by_name(s, tagname)
1068 th.move_to_new_tag(c, tagname, {}, true, true, true)
1073 awful.rules.rules = {
1074 -- All clients will match this rule.
1076 properties = { border_width = beautiful.border_width,
1077 border_color = beautiful.border_normal,
1078 focus = awful.client.focus.filter,
1081 buttons = clientbuttons,
1082 screen = awful.screen.preferred,
1083 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
1088 { rule = { type = "dialog" },
1089 properties = { floating = true,
1091 skip_taskbar = true,
1094 --switchtotag = true,
1095 placement = awful.placement.centered
1098 { rule = { class = "URxvt" },
1099 properties = { size_hints_honor = false, }
1101 { rule = { instance = "irc" },
1102 callback = move_to_tag_by_name(nil, "irc"),
1104 { rule = { class = "scrcpy" },
1105 callback = move_to_tag_by_name(nil, "[]"),
1107 { rule_any = { class = { "Firefox", "firefox" } },
1108 callback = move_to_tag_by_name(nil, "ffx"),
1110 { rule_any = { class = { "org.remmina.Remmina",
1115 callback = move_to_tag_by_name(nil, "vrt"),
1117 { rule = { class = "Chromium" },
1118 callback = move_to_tag_by_name(nil, "chr"),
1120 { rule_any = { class = { "thunderbird", "Thunderbird" } },
1121 callback = move_to_tag_by_name(nil, "cal"),
1123 { rule = { instance = "mutt" },
1127 layout = awful.layout.suit.fair.horizontal,
1133 { rule_any = { class = { "zoom" } },
1134 callback = move_to_tag_or_create_volatile(nil, "Zoom"),
1136 { rule_any = { class = { "Ssvnc.tcl" },
1137 class = { "Ssvnc" },
1138 name = { "SSL/SSH VNC Viewer.-" },
1140 callback = move_to_tag_or_create_volatile(nil, "SSVNC"),
1142 { rule_any = { class = {
1146 properties = { floating = true,
1149 placement = awful.placement.centered,
1152 { rule_any = { instance = {
1158 properties = { floating = true,
1161 placement = awful.placement.centered,
1164 { rule_any = { class = {
1174 except_any = { type = { "dialog" } },
1175 properties = { new_tag = {
1176 layout = layouts.maximised,
1183 { rule_any = { class = {
1187 except_any = { type = { "dialog" } },
1188 properties = { new_tag = {
1189 layout = layouts.default,
1195 placement = awful.placement.centered,
1200 --XX-- { rule = { class = "Gscan2pdf" },
1201 --XX-- properties = {
1202 --XX-- switchtotag = true
1204 --XX-- callback = move_to_tag(1, 5)
1206 --XX-- { rule = { name = "gscan2pdf .*" },
1207 --XX-- properties = {
1208 --XX-- floating = false,
1211 --XX-- { rule = { class = "Thunar", type = "normal" },
1212 --XX-- properties = {
1213 --XX-- floating = false,
1216 --XX-- { rule = { class = "Pinentry", instance = "pinentry" },
1217 --XX-- properties = {
1218 --XX-- floating = true,
1221 --XX-- { rule = { class = "Gxmessage" },
1222 --XX-- properties = {
1223 --XX-- floating = true,
1231 -- Signal function to execute when a new client appears.
1232 client.connect_signal("manage", function (c)
1233 -- Set the windows at the slave,
1234 -- i.e. put it at the end of others instead of setting it master.
1235 -- if not awesome.startup then awful.client.setslave(c) end
1236 --if not awesome.startup then
1237 -- local t = awful.screen.focused().selected_tag
1238 -- if t.name == "xmutt" then
1239 -- awful.client.setslave(c)
1243 if awesome.startup and
1244 not c.size_hints.user_position
1245 and not c.size_hints.program_position then
1246 -- Prevent clients from being unreachable after screen count changes.
1247 awful.placement.no_offscreen(c)
1250 c.maximized_horizontal = false
1251 c.maximized_vertical = false
1254 -- Add a titlebar if titlebars_enabled is set to true in the rules.
1255 client.connect_signal("request::titlebars", function(c)
1256 -- buttons for the titlebar
1257 local buttons = gears.table.join(
1258 awful.button({ }, 1, function()
1261 awful.mouse.client.move(c)
1263 awful.button({ }, 3, function()
1266 awful.mouse.client.resize(c)
1270 awful.titlebar(c) : setup {
1272 awful.titlebar.widget.iconwidget(c),
1274 layout = wibox.layout.fixed.horizontal
1279 widget = awful.titlebar.widget.titlewidget(c)
1282 layout = wibox.layout.flex.horizontal
1285 awful.titlebar.widget.floatingbutton (c),
1286 awful.titlebar.widget.maximizedbutton(c),
1287 awful.titlebar.widget.stickybutton (c),
1288 awful.titlebar.widget.ontopbutton (c),
1289 awful.titlebar.widget.closebutton (c),
1290 layout = wibox.layout.fixed.horizontal()
1292 layout = wibox.layout.align.horizontal
1296 -- Enable sloppy focus, so that focus follows mouse.
1297 client.connect_signal("mouse::enter", function(c)
1298 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
1299 and awful.client.focus.filter(c) then
1302 --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
1303 -- something like this
1306 client.connect_signal("focus", function(c)
1307 c.border_color = beautiful.border_focus
1309 client.connect_signal("unfocus", function(c)
1310 c.border_color = beautiful.border_normal
1313 awful.ewmh.add_activate_filter(function(c, context, hints)
1314 if context == "ewmh" then
1315 if (c.class == "Firefox-esr" or c.class == "Firefox") then
1321 client.connect_signal("request::activate", function(c, context, hints)
1322 if gears.table.hasitem({
1323 "client.focus.byidx",
1325 "autofocus.check_focus",
1329 gears.timer.delayed_call(function()
1330 -- we need a delayed call so that we execute *after layout changes
1331 if hints.raise and c == client.focus and client.focus:isvisible() then
1332 move_mouse_to_area(client.focus)
1338 -- vim:ft=lua:sw=4:sts=4:ts=4:et