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_pattern(pattern)
334 print(s.name .. " :: " .. pattern)
335 if s.name:match(pattern) then
341 local function get_target_screen_for_tag(tag)
342 local function primary_screen(reason)
343 local s = screen.primary
344 local msg = " → primary screen \"" .. s.name .. "\""
345 if reason then msg = msg .. " (" .. reason .. ")" end
350 print("Figuring out target screen for tag " .. tag.name .. "…")
352 if type(tag.targets) == "table" then
353 for _,target in ipairs(tag.targets) do
354 local s = find_screen_by_pattern(target:gsub('%-', '%%-'))
356 print(" → screen " .. s.name)
360 elseif tag.targets == "primary" then
361 return primary_screen("explicit request")
363 return primary_screen("no matching target in " .. table.concat(tag.targets, ","))
365 return primary_screen("no targets specified")
369 local function move_tag_to_target_screen(tag)
370 tag.screen = get_target_screen_for_tag(tag)
373 local function move_tags_to_target_screens()
374 for _,tag in ipairs(root.tags()) do
375 move_tag_to_target_screen(tag)
379 tag.connect_signal("request::screen", function(t)
380 -- throw the tag onto any other screen, it'll get reassigned later when
381 -- a new profile has been processed.
383 if s ~= t.screen then
390 title = "Screen removed",
391 text = "Salvaged tab " .. t.name,
395 function handle_new_autorandr_profile(newprofile)
396 -- The main idea here is that autorandr invokes this via awesome-client
397 -- after switching to a new profile. Awesome will have already set up all
398 -- the screens long before this function is called. Therefore, we just do
399 -- the necessary modifications to the existing screens, and move tags
402 if not newprofile then
403 error("Missing new profile name")
407 preset = naughty.config.presets.low,
408 title = "New autorandr profile",
409 text = "Reconfiguring for profile <b>" .. newprofile .. "</b>",
413 s:set_profile(newprofile)
415 move_tags_to_target_screens()
418 local function initialise_to_autorandr_profile()
422 local function process_line(line)
423 if profile then return end
424 local match = string.match(line, "^([^%s]+) %(detected%)")
430 local function output_done()
432 error("autorandr detected no profile")
435 handle_new_autorandr_profile(profile)
438 local function handle_exit(reason, code)
439 if not (reason == "exit" and code == 0) then
440 error("autorandr error: " .. reason .. ": " .. tostring(code))
444 awful.spawn.with_line_callback('autorandr', {
445 stdout = process_line,
446 output_done = output_done,
450 awesome.connect_signal("startup", initialise_to_autorandr_profile)
457 local default_tag = {
460 layout = layouts.default,
464 local default_tags = {}
467 for k,v in pairs(default_tag) do
468 default_tags[i][k] = v
470 default_tags[i].name = tostring(i)
472 default_tags[1].selected = true
474 default_tags = gears.table.join(default_tags, {
479 master_width_factor = 0.33,
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" },
484 targets = { "gauting/eDP-?1", "lehel/DisplayPort-2" },
490 master_width_factor = 0.67,
491 layout = layouts.tiled,
493 exec_once = { "revolt" },
494 instance = { "Revolt" },
495 targets = { "gauting/eDP-?1", "lehel/DisplayPort-2" },
501 layout = layouts.floating,
509 layout = layouts.default,
510 exec_once = { "thunderbird" },
511 class = { "thunderbird" },
512 targets = { "gauting/eDP-?1", "lehel/DisplayPort-1" },
518 layout = layouts.default,
519 exec_once = { "chromium" },
520 class = { "Chromium" },
521 targets = { "gauting/eDP-?1", "lehel/DisplayPort-1", "present/HDMI.*" },
527 layout = layouts.default,
528 exec_once = { "firefox" },
529 class = { "Firefox" },
530 targets = { "gauting/eDP-?1", "lehel/DisplayPort-1", "present/HDMI.*" },
534 if not tyrannical then
536 for _,t in ipairs(default_tags) do
538 t.screen = t.screen or screen.primary
539 t.layout = t.layout or layouts.default
540 local newt = th.add_tag(t.name, t, false)
544 else -- {{{ tyrannical is loaded
545 tyrannical.settings.default_layout = layouts.default
546 tyrannical.settings.master_width_factor = 0.5
547 tyrannical.settings.block_children_focus_stealing = true
548 tyrannical.settings.group_children = true
550 tyrannical.tags = default_tags
552 tyrannical.properties.size_hints_honor = { URxvt = false }
554 --XX---- Ignore the tag "exclusive" property for the following clients (matched by classes)
555 --XX--tyrannical.properties.intrusive = {
556 --XX-- "ksnapshot" , "pinentry" , "gtksu" , "kcalc" , "xcalc" ,
557 --XX-- "feh" , "Gradient editor", "About KDE" , "Paste Special", "Background color" ,
558 --XX-- "kcolorchooser" , "plasmoidviewer" , "Xephyr" , "kruler" , "plasmaengineexplorer",
561 --XX---- Ignore the tiled layout for the matching clients
562 --XX--tyrannical.properties.floating = {
563 --XX-- "MPlayer" , "pinentry" , "ksnapshot" , "pinentry" , "gtksu" ,
564 --XX-- "xine" , "feh" , "kmix" , "kcalc" , "xcalc" ,
565 --XX-- "yakuake" , "Select Color$" , "kruler" , "kcolorchooser", "Paste Special" ,
566 --XX-- "New Form" , "Insert Picture" , "kcharselect", "mythfrontend" , "plasmoidviewer"
569 --XX---- Make the matching clients (by classes) on top of the default layout
570 --XX--tyrannical.properties.ontop = {
571 --XX-- "Xephyr" , "ksnapshot" , "kruler"
574 --XX---- Force the matching clients (by classes) to be centered on the screen on init
575 --XX--tyrannical.properties.centered = {
582 -- {{{ Mouse bindings
583 root.buttons(gears.table.join(
584 awful.button({ }, 3, function () mymainmenu:toggle() end),
585 awful.button({ }, 4, awful.tag.viewnext),
586 awful.button({ }, 5, awful.tag.viewprev)
592 local function toggle_tag_by_name(tagname, exclusive)
594 local t = awful.tag.find_by_name(nil, tagname)
599 awful.tag.viewtoggle(t)
601 cf = awful.client.getmaster(t.screen)
609 globalkeys = gears.table.join(
610 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
611 {description="show help", group="awesome"}),
612 awful.key({ modkey, }, "Left", awful.tag.viewprev,
613 {description = "view previous", group = "tag"}),
614 awful.key({ modkey, }, "Right", awful.tag.viewnext,
615 {description = "view next", group = "tag"}),
616 awful.key({ modkey, "Shift" }, "Left", function () awful.screen.focus_relative( 1) end,
617 {description = "focus the next screen", group = "screen"}),
618 awful.key({ modkey, "Shift" }, "Right", function () awful.screen.focus_relative(-1) end,
619 {description = "focus the previous screen", group = "screen"}),
620 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
621 {description = "go back", group = "tag"}),
623 awful.key({ modkey, }, "k",
625 awful.client.focus.byidx( 1)
627 {description = "focus next by index", group = "client"}
629 awful.key({ modkey, }, "j",
631 awful.client.focus.byidx(-1)
633 {description = "focus previous by index", group = "client"}
636 -- Layout manipulation
637 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
638 {description = "swap with next client by index", group = "client"}),
639 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( -1) end,
640 {description = "swap with previous client by index", group = "client"}),
641 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
642 {description = "focus the next screen", group = "screen"}),
643 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
644 {description = "focus the previous screen", group = "screen"}),
645 awful.key({ modkey, "Shift" }, "Return", awful.client.urgent.jumpto,
646 {description = "jump to urgent client", group = "client"}),
647 awful.key({ modkey, }, "Tab",
649 awful.client.focus.history.previous()
654 {description = "go back", group = "client"}),
657 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
658 {description = "open a terminal", group = "launcher"}),
659 awful.key({ modkey, }, "r", function()
660 package.loaded.rc = nil
663 {description = "reload rc.lua", group = "awesome"}),
664 awful.key({ modkey, "Control" }, "r", awesome.restart,
665 {description = "reload awesome", group = "awesome"}),
666 awful.key({ modkey, "Shift" }, "q", awesome.quit,
667 {description = "quit awesome", group = "awesome"}),
669 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
670 {description = "increase master width factor", group = "layout"}),
671 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
672 {description = "decrease master width factor", group = "layout"}),
673 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
674 {description = "increase the number of master clients", group = "layout"}),
675 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
676 {description = "decrease the number of master clients", group = "layout"}),
677 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
678 {description = "increase the number of columns", group = "layout"}),
679 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
680 {description = "decrease the number of columns", group = "layout"}),
681 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
682 {description = "select next", group = "layout"}),
683 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
684 {description = "select previous", group = "layout"}),
686 awful.key({ modkey, "Control" }, "n",
688 local c = awful.client.restore()
689 -- Focus restored client
695 {description = "restore minimized", group = "client"}),
698 awful.key({ cmdkey }, "r",
700 local widget = awful.screen.focused().mypromptbox.widget
701 local function spawn(command, args)
702 gears.debug.dump(args)
703 awful.spawn(command, args)
708 bg_cursor = '#ff0000',
710 history_path = awful.util.get_cache_dir() .. "/history",
711 completion_callback = awful.completion.shell,
713 -- Replace the 'normal' Return with a custom one
714 {{ }, 'Return', function(command)
717 -- Spawn method to spawn in the current tag
718 {{'Mod1' }, 'Return', function(command)
721 tag = mouse.screen.selected_tag
724 -- Spawn in the current tag as floating and on top
725 {{'Shift' }, 'Return', function(command)
729 tag = mouse.screen.selected_tag
732 -- Spawn in a new tag
733 {{'Control'}, 'Return', function(command)
736 layout = layouts.default,
741 {{ }, 'Escape', function(_) return end},
745 {description = "run prompt", group = "launcher"}),
747 awful.key({ modkey }, "x",
751 bg_cursor = '#ff0000',
752 textbox = awful.screen.focused().mypromptbox.widget,
753 exe_callback = awful.util.eval,
754 history_path = awful.util.get_cache_dir() .. "/history_eval"
757 {description = "lua execute prompt", group = "awesome"}),
759 awful.key({ modkey }, "w", function() menubar.show() end,
760 {description = "show the menubar", group = "launcher"}),
763 awful.key({ modkey, }, "a", function()
764 th.add_tag(nil, {layout=layouts.default} ,true)
766 {description = "add a tag", group = "tag"}),
767 awful.key({ modkey, }, "d", th.delete_tag,
768 {description = "delete the current tag", group = "tag"}),
769 awful.key({ modkey, "Shift", }, "a", function()
770 th.move_to_new_tag(nil, nil, { layout = layouts.maximised },true,true,true)
772 {description = "add a volatile tag with the focused client", group = "tag"}),
773 awful.key({ modkey, "Shift", "Control" }, "a", function()
774 th.move_to_new_tag(nil, nil, { layout = layouts.maximised },false,true,true)
776 {description = "add a permanent tag with the focused client", group = "tag"}),
777 awful.key({ modkey, "Mod1" }, "a", th.copy_tag,
778 {description = "create a copy of the current tag", group = "tag"}),
779 awful.key({ modkey, "Control" }, "a", th.rename_tag,
780 {description = "rename the current tag", group = "tag"}),
781 awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
782 {description = "collect all orphaned clients", group = "client"}),
784 awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
785 {description = "view tag 'irc'", group = "tag"}),
786 awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
787 {description = "toggle tag 'irc'", group = "tag"}),
788 awful.key({ modkey }, "u", toggle_tag_by_name("[m]", true),
789 {description = "view tag '[m]'", group = "tag"}),
790 awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[m]"),
791 {description = "toggle tag '[m]'", group = "tag"}),
792 awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
793 {description = "view tag 'cal'", group = "tag"}),
794 awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
795 {description = "toggle tag 'cal'", group = "tag"}),
796 awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
797 {description = "view tag 'chr'", group = "tag"}),
798 awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
799 {description = "toggle tag 'chr'", group = "tag"}),
800 awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
801 {description = "view tag 'ff'", group = "tag"}),
802 awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
803 {description = "toggle tag 'ff'", group = "tag"}),
806 clientkeys = gears.table.join(
807 awful.key({ modkey, }, "f",
809 c.fullscreen = not c.fullscreen
812 {description = "toggle fullscreen", group = "client"}),
813 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
814 {description = "close", group = "client"}),
815 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
816 {description = "toggle floating", group = "client"}),
817 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
818 {description = "move to master", group = "client"}),
819 awful.key({ modkey, }, "z", function (c) c:move_to_screen() end,
820 {description = "move to screen", group = "client"}),
821 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
822 {description = "toggle keep on top", group = "client"}),
823 awful.key({ modkey, }, "n",
825 -- The client currently has the input focus, so it cannot be
826 -- minimized, since minimized clients can't have the focus.
829 {description = "minimize", group = "client"}),
830 awful.key({ modkey, }, "m",
832 c.maximized = not c.maximized
833 c.maximized_horizontal = false
834 c.maximized_vertical = false
837 {description = "(un)maximize", group = "client"}),
838 awful.key({ modkey, "Control" }, "m",
840 c.maximized_vertical = not c.maximized_vertical
843 {description = "(un)maximize vertically", group = "client"}),
844 awful.key({ modkey, "Shift" }, "m",
846 c.maximized_horizontal = not c.maximized_horizontal
849 {description = "(un)maximize horizontally", group = "client"})
852 -- Bind all key numbers to tags.
853 -- Be careful: we use keycodes to make it work on any keyboard layout.
854 -- This should map on the top row of your keyboard, usually 1 to 9.
856 globalkeys = gears.table.join(globalkeys,
858 awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
859 {description = "view tag #"..i, group = "tag"}),
860 -- Toggle tag display.
861 awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
862 {description = "toggle tag #" .. i, group = "tag"}),
863 -- Move client to tag.
864 awful.key({ modkey, "Shift" }, "#" .. i + 9,
867 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
869 client.focus:move_to_tag(tag)
873 {description = "move focused client to tag #"..i, group = "tag"}),
874 -- Toggle tag on focused client.
875 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
878 local tag = awful.tag.find_by_name(screen.primary, tostring(i))
880 client.focus:toggle_tag(tag)
884 {description = "toggle focused client on tag #" .. i, group = "tag"})
888 clientbuttons = gears.table.join(
889 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
890 awful.button({ modkey }, 1, awful.mouse.client.move),
891 awful.button({ modkey }, 3, awful.mouse.client.resize))
894 globalkeys = awful.util.table.join(globalkeys,
895 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
896 awful.key({ cmdkey }, "c", function () awful.spawn("chromium --enable-remote-extensions") end),
897 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e ipython3") end),
898 awful.key({ cmdkey }, "m", function () awful.spawn(terminal .. " -name mutt -e mutt") end),
899 awful.key({ cmdkey }, "t", function () awful.spawn("thunderbird") end),
900 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
901 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
902 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
903 awful.key({ cmdkey }, "p", function () awful.spawn("pavucontrol") end),
904 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),
905 awful.key({ cmdkey }, "x", function ()
906 awful.spawn("/usr/bin/xscreensaver -no-capture-stderr")
907 os.execute("sleep 5")
908 awful.spawn("xscreensaver-command -lock")
910 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
912 awful.key({ cmdkey }, "BackSpace", function () awful.spawn("pkill -USR1 offlineimap") end),
915 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
916 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
917 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
918 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
919 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
920 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
921 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
922 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
923 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
924 awful.key({ cmdkey }, "Insert", function () awful.spawn("pa_cycle_default source") end),
925 awful.key({ cmdkey }, "Delete", function () awful.spawn("pa_cycle_default sink") end),
926 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
927 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
928 awful.key(nil, "XF86Display", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
929 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
930 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
931 awful.key(nil, "XF86Search", function () awful.spawn("") end),
932 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
933 awful.key(nil, "XF86Explorer", function () awful.spawn("") end),
934 awful.key(nil, "XF86Favorites", function () awful.spawn("systemctl suspend") end),
936 awful.key({ cmdkey }, "Multi_key", function () run_output_notify("flameshot gui", "Output") end),
937 awful.key({ cmdkey, "Shift" }, "Multi_key", function () run_output_notify("flameshot full --delay 2000 --clipboard", "Output") end),
939 awful.key({ cmdkey }, "Up", function () awful.spawn("pap prev") end),
940 awful.key({ cmdkey }, "Left", function () awful.spawn("pap seek -10") end),
941 awful.key({ cmdkey, "Shift" }, "Left", function () awful.spawn("pap seek -60") end),
942 awful.key({ cmdkey }, "Down", function () awful.spawn("pap next") end),
943 awful.key({ cmdkey }, "Right", function () awful.spawn("pap seek +10") end),
944 awful.key({ cmdkey, "Shift" }, "Right", function () awful.spawn("pap seek +60") end),
945 awful.key({ cmdkey }, "space", function () awful.spawn("pap pause") end),
946 awful.key({ cmdkey }, "\\", function () run_output_notify("pap info", "Track info") end),
947 awful.key({ cmdkey }, "]", function () run_output_notify("pap list", "Playlist") end)
950 function run_output_notify(cmd, title)
951 awful.spawn.easy_async(cmd, function(stdout, stderr, reason, exit_code)
954 preset = naughty.config.presets.low,
962 root.keys(globalkeys)
966 -- Rules to apply to new clients (through the "manage" signal).
968 local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
969 local wa = client.screen.workarea
971 client.y = wa.y + topbottom
972 client.height = wa.height - 2*topbottom
974 client.y = wa.y + (wa.height - client.height)/2
977 client.x = wa.x + leftright
978 client.width = wa.width - 2*leftright
980 client.x = wa.x + (wa.width - client.width)/2
984 local function move_to_tag_by_name(s, tagname)
986 local t = awful.tag.find_by_name(s, tagname)
988 error("No tag by the name of " .. tagname)
995 local function move_to_tag_or_create_volatile(s, tagname)
997 local t = awful.tag.find_by_name(s, tagname)
1001 th.move_to_new_tag(c, tagname, {}, true, true, true)
1006 awful.rules.rules = {
1007 -- All clients will match this rule.
1009 properties = { border_width = beautiful.border_width,
1010 border_color = beautiful.border_normal,
1011 focus = awful.client.focus.filter,
1014 buttons = clientbuttons,
1015 screen = awful.screen.preferred,
1016 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
1021 { rule = { type = "dialog" },
1022 properties = { floating = true,
1024 skip_taskbar = true,
1027 --switchtotag = true,
1028 placement = awful.placement.centered
1031 { rule = { class = "URxvt" },
1032 properties = { size_hints_honor = false, }
1034 { rule = { instance = "irc" },
1035 callback = move_to_tag_by_name(nil, "irc"),
1037 { rule_any = { class = { "Firefox", "firefox" } },
1038 callback = move_to_tag_by_name(nil, "ffx"),
1040 { rule = { class = "Chromium" },
1041 callback = move_to_tag_by_name(nil, "chr"),
1043 { rule_any = { class = { "thunderbird", "Thunderbird" } },
1044 callback = move_to_tag_by_name(nil, "cal"),
1046 { rule = { instance = "mutt" },
1050 layout = awful.layout.suit.fair.horizontal,
1056 { rule_any = { class = { "zoom" } },
1057 callback = move_to_tag_or_create_volatile(nil, "Zoom"),
1059 { rule_any = { class = { "Ssvnc.tcl" },
1060 class = { "Ssvnc" },
1061 name = { "SSL/SSH VNC Viewer.-" },
1063 callback = move_to_tag_or_create_volatile(nil, "SSVNC"),
1065 { rule_any = { class = {
1069 properties = { floating = true,
1072 placement = awful.placement.centered,
1075 { rule_any = { instance = {
1081 properties = { floating = true,
1084 placement = awful.placement.centered,
1087 { rule_any = { class = {
1093 "Microsoft Teams - Preview",
1099 except_any = { type = { "dialog" } },
1100 properties = { new_tag = {
1101 layout = layouts.maximised,
1104 --switchtotag = true,
1108 --XX-- { rule = { class = "Gscan2pdf" },
1109 --XX-- properties = {
1110 --XX-- switchtotag = true
1112 --XX-- callback = move_to_tag(1, 5)
1114 --XX-- { rule = { name = "gscan2pdf .*" },
1115 --XX-- properties = {
1116 --XX-- floating = false,
1119 --XX-- { rule = { class = "Thunar", type = "normal" },
1120 --XX-- properties = {
1121 --XX-- floating = false,
1124 --XX-- { rule = { class = "Pinentry", instance = "pinentry" },
1125 --XX-- properties = {
1126 --XX-- floating = true,
1129 --XX-- { rule = { class = "Gxmessage" },
1130 --XX-- properties = {
1131 --XX-- floating = true,
1139 -- Signal function to execute when a new client appears.
1140 client.connect_signal("manage", function (c)
1141 -- Set the windows at the slave,
1142 -- i.e. put it at the end of others instead of setting it master.
1143 -- if not awesome.startup then awful.client.setslave(c) end
1144 --if not awesome.startup then
1145 -- local t = awful.screen.focused().selected_tag
1146 -- if t.name == "xmutt" then
1147 -- awful.client.setslave(c)
1151 if awesome.startup and
1152 not c.size_hints.user_position
1153 and not c.size_hints.program_position then
1154 -- Prevent clients from being unreachable after screen count changes.
1155 awful.placement.no_offscreen(c)
1158 c.maximized_horizontal = false
1159 c.maximized_vertical = false
1162 -- Add a titlebar if titlebars_enabled is set to true in the rules.
1163 client.connect_signal("request::titlebars", function(c)
1164 -- buttons for the titlebar
1165 local buttons = gears.table.join(
1166 awful.button({ }, 1, function()
1169 awful.mouse.client.move(c)
1171 awful.button({ }, 3, function()
1174 awful.mouse.client.resize(c)
1178 awful.titlebar(c) : setup {
1180 awful.titlebar.widget.iconwidget(c),
1182 layout = wibox.layout.fixed.horizontal
1187 widget = awful.titlebar.widget.titlewidget(c)
1190 layout = wibox.layout.flex.horizontal
1193 awful.titlebar.widget.floatingbutton (c),
1194 awful.titlebar.widget.maximizedbutton(c),
1195 awful.titlebar.widget.stickybutton (c),
1196 awful.titlebar.widget.ontopbutton (c),
1197 awful.titlebar.widget.closebutton (c),
1198 layout = wibox.layout.fixed.horizontal()
1200 layout = wibox.layout.align.horizontal
1204 -- Enable sloppy focus, so that focus follows mouse.
1205 client.connect_signal("mouse::enter", function(c)
1206 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
1207 and awful.client.focus.filter(c) then
1212 client.connect_signal("focus", function(c)
1213 c.border_color = beautiful.border_focus
1215 client.connect_signal("unfocus", function(c)
1216 c.border_color = beautiful.border_normal
1219 awful.ewmh.add_activate_filter(function(c, context, hints)
1220 if context == "ewmh" then
1221 if (c.class == "Firefox-esr" or c.class == "Firefox") then
1227 client.connect_signal("request::activate", function(c, context, hints)
1228 if gears.table.hasitem({
1229 "client.focus.byidx",
1231 "autofocus.check_focus",
1235 gears.timer.delayed_call(function()
1236 -- we need a delayed call so that we execute *after layout changes
1237 if hints.raise and c == client.focus and client.focus:isvisible() then
1238 move_mouse_to_area(client.focus)
1244 -- vim:ft=lua:sw=4:sts=4:ts=4:et