]> git.madduck.net Git - etc/awesome.git/blobdiff - .config/awesome/rc.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

autorandr unification across machines
[etc/awesome.git] / .config / awesome / rc.lua
index 5176f4de51c4458fbcb4cafb1cd836f6a09ad0fc..74f7bd9b3874632168ac52ecb1a55fc1c7bb9f1b 100644 (file)
@@ -1,10 +1,13 @@
 -- {{{ Imports
 -- {{{ Imports
+
 -- Standard awesome library
 local gears = require("gears")
 local awful = require("awful")
 require("awful.autofocus")
 -- Widget and layout library
 local wibox = require("wibox")
 -- Standard awesome library
 local gears = require("gears")
 local awful = require("awful")
 require("awful.autofocus")
 -- Widget and layout library
 local wibox = require("wibox")
+-- Tyrannical tab handling
+--local tyrannical = require("tyrannical")
 -- Theme handling library
 local beautiful = require("beautiful")
 local xrdb = beautiful.xresources
 -- Theme handling library
 local beautiful = require("beautiful")
 local xrdb = beautiful.xresources
@@ -20,11 +23,12 @@ require("awful.hotkeys_popup.keys")
 local debian = require("debian.menu")
 local has_fdo, freedesktop = pcall(require, "freedesktop")
 -- Other libraries
 local debian = require("debian.menu")
 local has_fdo, freedesktop = pcall(require, "freedesktop")
 -- Other libraries
-local tblutils = require("tblutils")
 local lain = require("lain")
 local lain = require("lain")
-local dkjson = require("lain.util").dkjson
-local math = require("math")
-local luatz = require("luatz")
+local ccwidgets = require("cryptocoin_widgets")
+local fxwidgets = require("forex_widgets")
+local clocksarray = require("clocksarray")
+local dbg = require("debugfunc")
+local th = require("taghelpers")
 -- }}}
 
 -- {{{ Error handling
 -- }}}
 
 -- {{{ Error handling
@@ -57,11 +61,10 @@ end
 --xrdb.set_dpi(120, screen[2])
 
 -- Themes define colours, icons, font and wallpapers.
 --xrdb.set_dpi(120, screen[2])
 
 -- Themes define colours, icons, font and wallpapers.
-beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
-beautiful.font = 'Sans 10'
+beautiful.init(gears.filesystem.get_configuration_dir () .. "theme/theme.lua")
 
 -- This is used later as the default terminal and editor to run.
 
 -- This is used later as the default terminal and editor to run.
-terminal = "x-terminal-emulator"
+terminal = "rxvt-unicode"
 editor = os.getenv("EDITOR") or "editor"
 editor_cmd = terminal .. " -e " .. editor
 
 editor = os.getenv("EDITOR") or "editor"
 editor_cmd = terminal .. " -e " .. editor
 
@@ -74,29 +77,22 @@ modkey = "Mod4"
 cmdkey = "Mod3"
 
 -- Table of layouts to cover with awful.layout.inc, order matters.
 cmdkey = "Mod3"
 
 -- Table of layouts to cover with awful.layout.inc, order matters.
+local layouts = {
+    default = awful.layout.suit.fair,
+    default_horiz = awful.layout.suit.fair.horizontal,
+    tiled = awful.layout.suit.tile,
+    tiled_horiz = awful.layout.suit.tile.top,
+    floating = awful.layout.suit.floating,
+    maximised = awful.layout.suit.max
+}
 awful.layout.layouts = {
 awful.layout.layouts = {
-    awful.layout.suit.floating,
-    awful.layout.suit.tile,
-    awful.layout.suit.tile.left,
-    awful.layout.suit.tile.bottom,
-    awful.layout.suit.tile.top,
-    awful.layout.suit.fair,
-    awful.layout.suit.fair.horizontal,
-    awful.layout.suit.spiral,
-    awful.layout.suit.spiral.dwindle,
-    awful.layout.suit.max,
-    awful.layout.suit.max.fullscreen,
-    awful.layout.suit.magnifier,
-    awful.layout.suit.corner.nw,
-    -- awful.layout.suit.corner.ne,
-    -- awful.layout.suit.corner.sw,
-    -- awful.layout.suit.corner.se,
+    layouts.default,
+    layouts.tiled,
+    layouts.maximised,
+    layouts.floating,
+    layouts.default_horiz,
+    layouts.tiled_horiz,
 }
 }
-
-layout_default = awful.layout.layouts[6]
-layout_tiled = awful.layout.layouts[2]
-layout_maximised = awful.layout.layouts[10]
-layout_floating = awful.layout.layouts[1]
 -- }}}
 
 -- {{{ Helper functions
 -- }}}
 
 -- {{{ Helper functions
@@ -125,47 +121,20 @@ local function set_wallpaper(s)
     end
 end
 
     end
 end
 
-local lain_bat = lain.widget.bat({
-    batteries = {"BAT0", "BAT1"},
-    settings = function()
-        local delim = "↓"
-        if bat_now.status == "Charging" then delim = "↑"
-        elseif bat_now.status == "Unknown" then delim = "٭" end
-        widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
-    end,
-})
-
-local function poloniex_price(output, pair, prec)
-    local xc, pos, err = dkjson.decode(output, 1, nil)
-    if not prec then prec = 4 end
-    val = (xc and xc[pair]["last"]) or 0
-    val = math.floor(val*10^prec+0.5)/10^prec
-    return (not err and val) or "n/a"
-end
-
-local eth_widget = lain.widget.watch({
-    cmd = "curl -m5 -s 'https://poloniex.com/public?command=returnTicker'",
-    timeout = 600,
-    settings = function()
-        widget:set_text(poloniex_price(output, 'BTC_ETH') .. " Ƀ/Ξ")
+local function move_mouse_to_area(a)
+    local coords = mouse.coords()
+    if (coords.x < a.x or
+        coords.x > (a.x+a.width) or
+        coords.y < a.y or
+        coords.y > (a.y+a.height)) then
+
+        mouse.coords({
+            x = a.x + a.width/2,
+            y = a.y + a.height/2,
+        }, true)
     end
     end
-})
-
-local function coindesk_price(output, base, prec)
-    local xc, pos, err = dkjson.decode(output, 1, nil)
-    if not prec then prec = 4 end
-    val = (xc and xc["bpi"][base]["rate_float"]) or 0
-    val = math.floor(val*10^prec+0.5)/10^prec
-    return (not err and val) or "n/a"
 end
 
 end
 
-local btc_widget = lain.widget.watch({
-    cmd = "curl -m5 -Ls 'https://api.coindesk.com/v1/bpi/currentprice/EUR.json'",
-    timeout = 600,
-    settings = function()
-        widget:set_text(coindesk_price(output, "EUR", 2) .. " €/Ƀ")
-    end
-})
 -- }}}
 
 -- {{{ Menu
 -- }}}
 
 -- {{{ Menu
@@ -205,28 +174,35 @@ menubar.utils.terminal = terminal -- Set the terminal for applications that requ
 -- }}}
 
 -- {{{ Wibar
 -- }}}
 
 -- {{{ Wibar
-local spacer = wibox.widget.textbox()
-spacer:set_text(' │ ')
+--local spacer = wibox.widget {
+--    color = beautiful.bg_minimize,
+--    forced_width = 4,
+--    widget = wibox.widget.separator
+--}
+local function make_spacer(text)
+    local spacer = wibox.widget.textbox()
+    spacer:set_text(text or " │ ")
+    return spacer
+end
 
 -- Keyboard map indicator and switcher
 mykeyboardlayout = awful.widget.keyboardlayout()
 
 
 -- Keyboard map indicator and switcher
 mykeyboardlayout = awful.widget.keyboardlayout()
 
--- Create a textclock widget
-clocks = { wibox.widget.textclock("%a %d %b %H:%M:%S %Z", 1) }
+local lain_bat = lain.widget.bat({
+    batteries = {"BAT0", "BAT1"},
+    settings = function()
+        local delim = "↓"
+        if bat_now.status == "Charging" then delim = "↑"
+        elseif bat_now.status == "Unknown" then delim = "٭" end
+        widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
+    end,
+})
 
 
-ZONES = {
-  ["NZ"] = "Pacific/Auckland",
-  ["DE"] = "Europe/Berlin"
-}
-local now = luatz.time_in(nil)
-for c, tz in tblutils.sorted_pairs(ZONES) do
-    local t = luatz.time_in(tz)
-    if math.abs(os.difftime(t, now)) > 10 then
-        local widget = wibox.widget.textclock(c .. ": %H:%M (%a)", 60, tz)
-        table.insert(clocks, 1, spacer)
-        table.insert(clocks, 1, widget)
-    end
-end
+-- Create a textclock widget
+clocksarray = clocksarray.get_clocksarray("%a %d %b %H:%M:%S %Z", {
+--        ["NZ"] = "Pacific/Auckland",
+        ["DE"] = "Europe/Berlin"
+    }, make_spacer())
 
 -- Create a wibox for each screen and add it
 local taglist_buttons = gears.table.join(
 
 -- Create a wibox for each screen and add it
 local taglist_buttons = gears.table.join(
@@ -273,103 +249,370 @@ local tasklist_buttons = gears.table.join(
                                           end))
 -- }}}
 
                                           end))
 -- }}}
 
+-- {{{ Screens
+
 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
 screen.connect_signal("property::geometry", set_wallpaper)
 
 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
 screen.connect_signal("property::geometry", set_wallpaper)
 
--- {{{ Tags
-tags = {}
-tags.config = {}
-tags.config["main"] = {
-    t1 = { layout = layout_default, selected = true },
-    t2 = { layout = layout_default },
-    t3 = { layout = layout_tiled },
-    t4 = { layout = layout_tiled },
-    t5 = { layout = layout_tiled },
-    t6 = { layout = layout_floating },
-    t7 = { layout = layout_maximised },
-    t8 = { layout = layout_maximised },
-    t9 = { layout = layout_maximised },
-}
-tags.config["aux"] = {
-    t1 = { layout = layout_default, selected = true },
-    t2 = { layout = layout_default },
-    t3 = { layout = layout_tiled },
-    t4 = { layout = layout_floating },
-    t5 = { layout = layout_floating },
-    t6 = { layout = layout_floating },
-    t7 = { layout = layout_floating },
-    t8 = { layout = layout_floating },
-    t9 = { layout = layout_maximised },
-}
-
-screentags = {}
-screentags[1] = tags.config["main"]
-if screen.count() == 2 then -- aux screen is on the right
-  screentags[2] = tags.config["aux"]
-elseif screen.count() == 3 then -- main screen is still #1 in the middle
-  screentags[2] = tags.config["aux"]
-  screentags[3] = tags.config["aux"]
+-- {{{ Basic setup for screens
+local function screen_set_profile(s, profile)
+    s.profile = profile
+    s.outputstr = table.concat(gears.table.keys(s.outputs), "+")
+    s.name = s.profile .. "/" .. s.outputstr
 end
 
 awful.screen.connect_for_each_screen(function(s)
 end
 
 awful.screen.connect_for_each_screen(function(s)
-    -- local fontsize = math.floor(250 * xrdb.get_dpi(s)/s.geometry.width)
-    -- beautiful.font = "Sans " .. tostring(fontsize)
 
 
-    if not tags[s.index] then
-        tags[s.index] = {}
-    end
-    for n,p in tblutils.sorted_pairs(screentags[s.index]) do
-        p["screen"] = s
-        n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
-        table.insert(tags[s.index], awful.tag.add(n, p))
-    end
+    s.set_profile = screen_set_profile
+
+    -- Wallpaper
+    set_wallpaper(s)
+
+    -- Create a text widget to display screen name
+    s.namebox = wibox.container.background(wibox.widget.textbox(s.name),
+      beautiful.bg_minimize)
 
     -- Create a promptbox for each screen
 
     -- Create a promptbox for each screen
-    mypromptbox[s] = awful.widget.prompt()
+    s.mypromptbox = awful.widget.prompt()
     -- Create an imagebox widget which will contains an icon indicating which layout we're using.
     -- We need one layoutbox per screen.
     -- Create an imagebox widget which will contains an icon indicating which layout we're using.
     -- We need one layoutbox per screen.
-    mylayoutbox[s] = awful.widget.layoutbox(s)
-    mylayoutbox[s]:buttons(awful.util.table.join(
+    s.mylayoutbox = awful.widget.layoutbox(s)
+    s.mylayoutbox:buttons(awful.util.table.join(
                            awful.button({ }, 1, function () awful.layout.inc( 1) end),
                            awful.button({ }, 3, function () awful.layout.inc(-1) end),
                            awful.button({ }, 4, function () awful.layout.inc( 1) end),
                            awful.button({ }, 5, function () awful.layout.inc(-1) end)))
     -- Create a taglist widget
                            awful.button({ }, 1, function () awful.layout.inc( 1) end),
                            awful.button({ }, 3, function () awful.layout.inc(-1) end),
                            awful.button({ }, 4, function () awful.layout.inc( 1) end),
                            awful.button({ }, 5, function () awful.layout.inc(-1) end)))
     -- Create a taglist widget
-    mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
+    s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
 
     -- Create a tasklist widget
 
     -- Create a tasklist widget
-    mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
+    s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
 
 
-    -- Create the wibox
-    mywibox[s] = awful.wibar({ position = "top", screen = s })
+    -- Create the wibox, but only if there isn't one yet
+    if not s.mywibox then
+        s.mywibox = awful.wibar({ position = "top", screen = s })
+    end
 
     -- Add widgets to the wibox
 
     -- Add widgets to the wibox
-    mywibox[s]:setup {
+    local right_widgets = gears.table.join(clocksarray, {
+        make_spacer(" "),
+        wibox.widget.systray(),
+        s.mylayoutbox,
+        layout = wibox.layout.fixed.horizontal,
+    })
+
+--    if s == screen.primary then
+        right_widgets = gears.table.join({
+            make_spacer(" "),
+            ccwidgets.btc_widget,
+            make_spacer(),
+            ccwidgets.eth_widget,
+            make_spacer(),
+            fxwidgets.ecb_widget,
+            make_spacer(),
+            lain_bat.widget,
+            make_spacer(),
+        }, right_widgets)
+--    end
+
+    s.mywibox:setup {
         layout = wibox.layout.align.horizontal,
         { -- Left widgets
             layout = wibox.layout.fixed.horizontal,
         layout = wibox.layout.align.horizontal,
         { -- Left widgets
             layout = wibox.layout.fixed.horizontal,
-            -- mylauncher,
-            mytaglist[s],
-            mypromptbox[s],
+            --s.namebox,
+            s.mytaglist,
+            make_spacer(" "),
+            s.mypromptbox,
         },
         },
-        mytasklist[s], -- Middle widget
-        awful.util.table.join( -- Right widgets
-            {
-                layout = wibox.layout.fixed.horizontal,
-                mykeyboardlayout,
-                wibox.widget.systray(),
-                btc_widget,
-                spacer,
-                lain_bat.widget,
-                spacer,
-            },
-            clocks,
-            {
-                mylayoutbox[s],
-            }
-        ),
+        s.mytasklist, -- Middle widget
+        right_widgets,
     }
     }
+end) -- }}}
+
+-- {{{ autorandr integration
+local function find_screen_by_pattern(pattern)
+    for s in screen do
+        print(s.name .. " :: " .. pattern)
+        if s.name:match(pattern) then
+            return s
+        end
+    end
+end
+
+local function get_target_screen_for_tag(tag)
+    local function primary_screen(reason)
+        local s = screen.primary
+        local msg = "  → primary screen \"" .. s.name .. "\""
+        if reason then msg = msg .. " (" .. reason .. ")" end
+        print(msg)
+        return s
+    end
+
+    print("Figuring out target screen for tag " .. tag.name .. "…")
+    if tag.targets then
+        if type(tag.targets) == "table" then
+            for _,target in ipairs(tag.targets) do
+                local s = find_screen_by_pattern(target:gsub('%-', '%%-'))
+                if s then
+                    print("  → screen " .. s.name)
+                    return s
+                end
+            end
+        elseif tag.targets == "primary" then
+            return primary_screen("explicit request")
+        end
+        return primary_screen("no matching target in " .. table.concat(tag.targets, ","))
+    else
+        return primary_screen("no targets specified")
+    end
+end
+
+local function move_tag_to_target_screen(tag)
+    tag.screen = get_target_screen_for_tag(tag)
+end
+
+local function move_tags_to_target_screens()
+    for _,tag in ipairs(root.tags()) do
+        move_tag_to_target_screen(tag)
+    end
+end
+
+tag.connect_signal("request::screen", function(t)
+    -- throw the tag onto any other screen, it'll get reassigned later when
+    -- a new profile has been processed.
+    for s in screen do
+        if s ~= t.screen then
+            t.screen = s
+            t.selected = false
+            break
+        end
+    end
+    naughty.notify({
+        title = "Screen removed",
+        text = "Salvaged tab " .. t.name,
+    })
 end)
 end)
+
+function handle_new_autorandr_profile(newprofile)
+    -- The main idea here is that autorandr invokes this via awesome-client
+    -- after switching to a new profile. Awesome will have already set up all
+    -- the screens long before this function is called. Therefore, we just do
+    -- the necessary modifications to the existing screens, and move tags
+    -- around.
+
+    if not newprofile then
+        error("Missing new profile name")
+    end
+
+    naughty.notify({
+        preset = naughty.config.presets.low,
+        title = "New autorandr profile",
+        text = "Reconfiguring for profile <b>" .. newprofile .. "</b>",
+    })
+
+    for s in screen do
+        s:set_profile(newprofile)
+    end
+    move_tags_to_target_screens()
+end
+
+local function initialise_to_autorandr_profile()
+    local profile
+    profile = nil
+
+    local function process_line(line)
+        if profile then return end
+        local match = string.match(line, "^([^%s]+) %(detected%)")
+        if match then
+            profile = match
+        end
+    end
+
+    local function output_done()
+        if not profile then
+            error("autorandr detected no profile")
+            profile = "awesome"
+        end
+        handle_new_autorandr_profile(profile)
+    end
+
+    local function handle_exit(reason, code)
+        if not (reason == "exit" and code == 0) then
+            error("autorandr error: " .. reason .. ": " .. tostring(code))
+        end
+    end
+
+    awful.spawn.with_line_callback('autorandr', {
+        stdout = process_line,
+        output_done = output_done,
+        exit = handle_exit
+    })
+end
+awesome.connect_signal("startup", initialise_to_autorandr_profile)
+-- }}}
+
+-- }}}
+
+-- {{{ Tags
+
+local default_tag = {
+    name        = nil,
+    init        = true,
+    layout      = layouts.default,
+    fallback    = true,
+    targets     = "primary",
+}
+local default_tags = {}
+for i = 1, 9 do
+    default_tags[i] = {}
+    for k,v in pairs(default_tag) do
+        default_tags[i][k] = v
+    end
+    default_tags[i].name = tostring(i)
+end
+default_tags[1].selected = true
+
+default_tags = gears.table.join(default_tags, {
+  {
+    name        = "irc",
+    init        = true,
+    exclusive   = true,
+    layout      = layouts.tiled,
+    selected    = true,
+    exec_once   = { terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh --family=all -- irc-host tmux new -As irc irssi" },
+    instance    = { "irc" },
+    targets     = {
+                    "gern/DP-?[12]-1",
+                    "gauting/eDP-?1",
+                    "toni/eDP-?1",
+                    "krafftwerk/DP-?1-1-5",
+                    "krafftwerk/DisplayPort-2",
+                    "cafe/eDP-?1"
+                },
+  },
+  {
+    name        = "[]",
+    init        = true,
+    exclusive   = true,
+    master_count = 0,
+    column_count = 4,
+    layout      = layouts.tiled,
+    selected    = false,
+    targets     = {
+                    "gern/DP-?[12]-1",
+                    "gauting/eDP-?1",
+                    "toni/eDP-?1",
+                    "krafftwerk/DP-?1-1-5",
+                    "krafftwerk/DisplayPort-2",
+                    "cafe/eDP-?1"
+                },
+  },
+  {
+    name        = "dflt",
+    init        = false,
+    fallback    = true,
+    layout      = layouts.floating,
+    volatile    = true,
+    selected    = true,
+  },
+  {
+    name        = "cal",
+    init        = true,
+    exclusive   = true,
+    layout      = layouts.default,
+    exec_once   = { "thunderbird" },
+    class       = { "thunderbird" },
+    targets     = {
+                    "gern/DP-?[12]-1",
+                    "gauting/eDP-?1",
+                    "toni/eDP-?1",
+                    "krafftwerk/DP-?1-1-6",
+                    "krafftwerk/DisplayPort-0",
+                    "cafe/eDP-?1"
+                },
+  },
+  {
+    name        = "chr",
+    init        = true,
+    exclusive   = true,
+    layout      = layouts.default,
+    exec_once   = { "chromium" },
+    class       = { "Chromium" },
+    targets     = {
+                    "gern/DP-?[12]-1",
+                    "gauting/eDP-?1",
+                    "toni/DP-?2-2",
+                    "krafftwerk/DP-?1-1-6",
+                    "krafftwerk/DisplayPort-0",
+                    "present/HDMI.*",
+                    "cafe/eDP-?1"
+                },
+  },
+  {
+    name        = "ffx",
+    init        = true,
+    exclusive   = true,
+    layout      = layouts.default,
+    exec_once   = { "firefox" },
+    class       = { "Firefox" },
+    targets     = {
+                    "gern/DP-?[12]-1",
+                    "gauting/eDP-?1",
+                    "toni/DP-?2-2",
+                    "krafftwerk/DP-?1-1-6",
+                    "krafftwerk/DisplayPort-0",
+                    "present/HDMI.*",
+                    "cafe/eDP-?1"
+                },
+  },
+})
+
+if not tyrannical then
+
+for _,t in ipairs(default_tags) do
+    if t.init then
+        t.screen = t.screen or screen.primary
+        t.layout = t.layout or layouts.default
+        local newt = th.add_tag(t.name, t, false)
+    end
+end
+
+else -- {{{ tyrannical is loaded
+tyrannical.settings.default_layout = layouts.default
+tyrannical.settings.master_width_factor = 0.5
+tyrannical.settings.block_children_focus_stealing = true
+tyrannical.settings.group_children = true
+
+tyrannical.tags = default_tags
+
+tyrannical.properties.size_hints_honor = { URxvt = false }
+
+--XX---- Ignore the tag "exclusive" property for the following clients (matched by classes)
+--XX--tyrannical.properties.intrusive = {
+--XX--  "ksnapshot"     , "pinentry"       , "gtksu"     , "kcalc"        , "xcalc"               ,
+--XX--  "feh"           , "Gradient editor", "About KDE" , "Paste Special", "Background color"    ,
+--XX--  "kcolorchooser" , "plasmoidviewer" , "Xephyr"    , "kruler"       , "plasmaengineexplorer",
+--XX--}
+--XX--
+--XX---- Ignore the tiled layout for the matching clients
+--XX--tyrannical.properties.floating = {
+--XX--  "MPlayer"      , "pinentry"        , "ksnapshot"  , "pinentry"     , "gtksu"          ,
+--XX--  "xine"         , "feh"             , "kmix"       , "kcalc"        , "xcalc"          ,
+--XX--  "yakuake"      , "Select Color$"   , "kruler"     , "kcolorchooser", "Paste Special"  ,
+--XX--  "New Form"     , "Insert Picture"  , "kcharselect", "mythfrontend" , "plasmoidviewer"
+--XX--}
+--XX--
+--XX---- Make the matching clients (by classes) on top of the default layout
+--XX--tyrannical.properties.ontop = {
+--XX--  "Xephyr"       , "ksnapshot"       , "kruler"
+--XX--}
+--XX--
+--XX---- Force the matching clients (by classes) to be centered on the screen on init
+--XX--tyrannical.properties.centered = {
+--XX--  "kcalc"
+--XX--}
+end -- }}}
+
 -- }}}
 
 -- {{{ Mouse bindings
 -- }}}
 
 -- {{{ Mouse bindings
@@ -381,6 +624,32 @@ root.buttons(gears.table.join(
 -- }}}
 
 -- {{{ Key bindings
 -- }}}
 
 -- {{{ Key bindings
+
+local function toggle_tag_by_name(tagname, exclusive)
+    return function()
+        local t = awful.tag.find_by_name(nil, tagname)
+        if t then
+            if exclusive then
+                t:view_only()
+            else
+                awful.tag.viewtoggle(t)
+            end
+            cf = awful.client.getmaster(t.screen)
+            if cf then
+                cf:jump_to()
+            end
+        end
+    end
+end
+
+local function move_tags_to_screen_relative(direction)
+    local s = awful.screen.focused()
+    for _,tag in ipairs(s.selected_tags) do
+        print("index: " .. s.index .. " count: " .. screen:count())
+        tag.screen = screen[(s.index + screen:count() + direction) % screen.count()]
+    end
+end
+
 globalkeys = gears.table.join(
     awful.key({ modkey,           }, "s",      hotkeys_popup.show_help,
               {description="show help", group="awesome"}),
 globalkeys = gears.table.join(
     awful.key({ modkey,           }, "s",      hotkeys_popup.show_help,
               {description="show help", group="awesome"}),
@@ -403,19 +672,21 @@ globalkeys = gears.table.join(
         end,
         {description = "focus previous by index", group = "client"}
     ),
         end,
         {description = "focus previous by index", group = "client"}
     ),
-    awful.key({ modkey,           }, "w", function () mymainmenu:show() end,
-              {description = "show main menu", group = "awesome"}),
 
     -- Layout manipulation
 
     -- Layout manipulation
-    awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx(  1)    end,
+    awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx( 1)    end,
               {description = "swap with next client by index", group = "client"}),
               {description = "swap with next client by index", group = "client"}),
-    awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx( -1)    end,
+    awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx(-1)    end,
               {description = "swap with previous client by index", group = "client"}),
     awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
               {description = "focus the next screen", group = "screen"}),
     awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
               {description = "focus the previous screen", group = "screen"}),
               {description = "swap with previous client by index", group = "client"}),
     awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
               {description = "focus the next screen", group = "screen"}),
     awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
               {description = "focus the previous screen", group = "screen"}),
-    awful.key({ modkey,           }, "u", awful.client.urgent.jumpto,
+    awful.key({ modkey, "Shift", "Control" }, "k", function () move_tags_to_screen_relative( 1) end,
+              {description = "move tags to the next screen", group = "screen"}),
+    awful.key({ modkey, "Shift", "Control" }, "j", function () move_tags_to_screen_relative(-1) end,
+              {description = "move tags to the previous screen", group = "screen"}),
+    awful.key({ modkey, "Shift"   }, "Return", awful.client.urgent.jumpto,
               {description = "jump to urgent client", group = "client"}),
     awful.key({ modkey,           }, "Tab",
         function ()
               {description = "jump to urgent client", group = "client"}),
     awful.key({ modkey,           }, "Tab",
         function ()
@@ -429,6 +700,11 @@ globalkeys = gears.table.join(
     -- Standard program
     awful.key({ modkey,           }, "Return", function () awful.spawn(terminal) end,
               {description = "open a terminal", group = "launcher"}),
     -- Standard program
     awful.key({ modkey,           }, "Return", function () awful.spawn(terminal) end,
               {description = "open a terminal", group = "launcher"}),
+    awful.key({ modkey,           }, "r", function()
+        package.loaded.rc = nil
+        require("rc")
+    end,
+              {description = "reload rc.lua", group = "awesome"}),
     awful.key({ modkey, "Control" }, "r", awesome.restart,
               {description = "reload awesome", group = "awesome"}),
     awful.key({ modkey, "Shift"   }, "q", awesome.quit,
     awful.key({ modkey, "Control" }, "r", awesome.restart,
               {description = "reload awesome", group = "awesome"}),
     awful.key({ modkey, "Shift"   }, "q", awesome.quit,
@@ -463,13 +739,60 @@ globalkeys = gears.table.join(
               {description = "restore minimized", group = "client"}),
 
     -- Prompt
               {description = "restore minimized", group = "client"}),
 
     -- Prompt
-    awful.key({ modkey },            "r",     function () awful.screen.focused().mypromptbox:run() end,
+    awful.key({ cmdkey },            "r",
+              function ()
+                  local widget = awful.screen.focused().mypromptbox.widget
+                  local function spawn(command, args)
+                      gears.debug.dump(args)
+                      awful.spawn(command, args)
+                  end
+
+                  awful.prompt.run {
+                    prompt       = "Exec: ",
+                    bg_cursor    = '#ff0000',
+                    textbox      = widget,
+                    history_path = awful.util.get_cache_dir() .. "/history",
+                    completion_callback = awful.completion.shell,
+                    hooks = {
+                        -- Replace the 'normal' Return with a custom one
+                        {{         }, 'Return', function(command)
+                            spawn(command)
+                        end},
+                        -- Spawn method to spawn in the current tag
+                        {{'Mod1'   }, 'Return', function(command)
+                            spawn(command,{
+                                intrusive = true,
+                                tag       = mouse.screen.selected_tag
+                            })
+                        end},
+                        -- Spawn in the current tag as floating and on top
+                        {{'Shift'  }, 'Return', function(command)
+                            spawn(command,{
+                                ontop     = true,
+                                floating  = true,
+                                tag       = mouse.screen.selected_tag
+                            })
+                        end},
+                        -- Spawn in a new tag
+                        {{'Control'}, 'Return', function(command)
+                            spawn(command,{
+                                new_tag = true,
+                                layout = layouts.default,
+                                volatile = true,
+                            })
+                        end},
+                        -- Cancel
+                        {{         }, 'Escape', function(_) return end},
+                    },
+                }
+        end,
               {description = "run prompt", group = "launcher"}),
 
     awful.key({ modkey }, "x",
               function ()
                   awful.prompt.run {
               {description = "run prompt", group = "launcher"}),
 
     awful.key({ modkey }, "x",
               function ()
                   awful.prompt.run {
-                    prompt       = "Run Lua code: ",
+                    prompt       = "Eval: ",
+                    bg_cursor    = '#ff0000',
                     textbox      = awful.screen.focused().mypromptbox.widget,
                     exe_callback = awful.util.eval,
                     history_path = awful.util.get_cache_dir() .. "/history_eval"
                     textbox      = awful.screen.focused().mypromptbox.widget,
                     exe_callback = awful.util.eval,
                     history_path = awful.util.get_cache_dir() .. "/history_eval"
@@ -477,9 +800,52 @@ globalkeys = gears.table.join(
               end,
               {description = "lua execute prompt", group = "awesome"}),
     -- Menubar
               end,
               {description = "lua execute prompt", group = "awesome"}),
     -- Menubar
-    awful.key({ modkey }, "p", function() menubar.show() end,
-              {description = "show the menubar", group = "launcher"})
-)
+    awful.key({ modkey }, "w", function() menubar.show() end,
+              {description = "show the menubar", group = "launcher"}),
+
+    -- Tag helpers
+    awful.key({ modkey,           }, "a", function()
+        th.add_tag(nil, {layout=layouts.default} ,true)
+    end,
+    {description = "add a tag", group = "tag"}),
+    awful.key({ modkey,           }, "d", th.delete_tag,
+              {description = "delete the current tag", group = "tag"}),
+    awful.key({ modkey, "Shift",           }, "a", function()
+        th.move_to_new_tag(nil, nil, { layout = layouts.maximised },true,true,true)
+    end,
+              {description = "add a volatile tag with the focused client", group = "tag"}),
+    awful.key({ modkey, "Shift", "Control" }, "a", function()
+        th.move_to_new_tag(nil, nil, { layout = layouts.maximised },false,true,true)
+    end,
+              {description = "add a permanent tag with the focused client", group = "tag"}),
+    awful.key({ modkey, "Mod1"   }, "a", th.copy_tag,
+              {description = "create a copy of the current tag", group = "tag"}),
+    awful.key({ modkey, "Control"   }, "a", th.rename_tag,
+              {description = "rename the current tag", group = "tag"}),
+    awful.key({ modkey, "Control", "Shift", "Mod1" }, "a", th.collect_orphan_clients_to_tag,
+              {description = "collect all orphaned clients", group = "client"}),
+
+    awful.key({ modkey }, "y", toggle_tag_by_name("irc", true),
+              {description = "view tag 'irc'", group = "tag"}),
+    awful.key({ modkey, "Control" }, "y", toggle_tag_by_name("irc"),
+              {description = "toggle tag 'irc'", group = "tag"}),
+    awful.key({ modkey }, "u", toggle_tag_by_name("[]", true),
+              {description = "view tag '[]'", group = "tag"}),
+    awful.key({ modkey, "Control" }, "u", toggle_tag_by_name("[]"),
+              {description = "toggle tag '[]'", group = "tag"}),
+    awful.key({ modkey }, "i", toggle_tag_by_name("cal", true),
+              {description = "view tag 'cal'", group = "tag"}),
+    awful.key({ modkey, "Control" }, "i", toggle_tag_by_name("cal"),
+              {description = "toggle tag 'cal'", group = "tag"}),
+    awful.key({ modkey }, "o", toggle_tag_by_name("chr", true),
+              {description = "view tag 'chr'", group = "tag"}),
+    awful.key({ modkey, "Control" }, "o", toggle_tag_by_name("chr"),
+              {description = "toggle tag 'chr'", group = "tag"}),
+    awful.key({ modkey }, "p", toggle_tag_by_name("ffx", true),
+              {description = "view tag 'ff'", group = "tag"}),
+    awful.key({ modkey, "Control" }, "p", toggle_tag_by_name("ffx"),
+              {description = "toggle tag 'ff'", group = "tag"}),
+{})
 
 clientkeys = gears.table.join(
     awful.key({ modkey,           }, "f",
 
 clientkeys = gears.table.join(
     awful.key({ modkey,           }, "f",
@@ -494,7 +860,7 @@ clientkeys = gears.table.join(
               {description = "toggle floating", group = "client"}),
     awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
               {description = "move to master", group = "client"}),
               {description = "toggle floating", group = "client"}),
     awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
               {description = "move to master", group = "client"}),
-    awful.key({ modkey,           }, "o",      function (c) c:move_to_screen()               end,
+    awful.key({ modkey,           }, "z",      function (c) c:move_to_screen() end,
               {description = "move to screen", group = "client"}),
     awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end,
               {description = "toggle keep on top", group = "client"}),
               {description = "move to screen", group = "client"}),
     awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end,
               {description = "toggle keep on top", group = "client"}),
@@ -533,30 +899,16 @@ clientkeys = gears.table.join(
 for i = 1, 9 do
     globalkeys = gears.table.join(globalkeys,
         -- View tag only.
 for i = 1, 9 do
     globalkeys = gears.table.join(globalkeys,
         -- View tag only.
-        awful.key({ modkey }, "#" .. i + 9,
-                  function ()
-                        local screen = awful.screen.focused()
-                        local tag = screen.tags[i]
-                        if tag then
-                           tag:view_only()
-                        end
-                  end,
+        awful.key({ modkey }, "#" .. i + 9, toggle_tag_by_name(tostring(i), true),
                   {description = "view tag #"..i, group = "tag"}),
         -- Toggle tag display.
                   {description = "view tag #"..i, group = "tag"}),
         -- Toggle tag display.
-        awful.key({ modkey, "Control" }, "#" .. i + 9,
-                  function ()
-                      local screen = awful.screen.focused()
-                      local tag = screen.tags[i]
-                      if tag then
-                         awful.tag.viewtoggle(tag)
-                      end
-                  end,
+        awful.key({ modkey, "Control" }, "#" .. i + 9, toggle_tag_by_name(tostring(i)),
                   {description = "toggle tag #" .. i, group = "tag"}),
         -- Move client to tag.
         awful.key({ modkey, "Shift" }, "#" .. i + 9,
                   function ()
                       if client.focus then
                   {description = "toggle tag #" .. i, group = "tag"}),
         -- Move client to tag.
         awful.key({ modkey, "Shift" }, "#" .. i + 9,
                   function ()
                       if client.focus then
-                          local tag = client.focus.screen.tags[i]
+                          local tag = awful.tag.find_by_name(screen.primary, tostring(i))
                           if tag then
                               client.focus:move_to_tag(tag)
                           end
                           if tag then
                               client.focus:move_to_tag(tag)
                           end
@@ -567,7 +919,7 @@ for i = 1, 9 do
         awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
                   function ()
                       if client.focus then
         awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
                   function ()
                       if client.focus then
-                          local tag = client.focus.screen.tags[i]
+                          local tag = awful.tag.find_by_name(screen.primary, tostring(i))
                           if tag then
                               client.focus:toggle_tag(tag)
                           end
                           if tag then
                               client.focus:toggle_tag(tag)
                           end
@@ -585,38 +937,73 @@ clientbuttons = gears.table.join(
 -- misc apps
 globalkeys = awful.util.table.join(globalkeys,
 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
 -- misc apps
 globalkeys = awful.util.table.join(globalkeys,
 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
-awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
-awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
-awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
-awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
+awful.key({ cmdkey }, "c", function () awful.spawn("chromium --enable-remote-extensions") end),
+awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e ipython3") end),
+awful.key({ cmdkey }, "m", function () awful.spawn(terminal .. " -name mutt -e mutt") end),
+awful.key({ cmdkey }, "t", function () awful.spawn("thunderbird") end),
 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
-awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
+awful.key({ cmdkey, "Shift" }, "v", function () awful.spawn("virt-manager") end),
 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
-awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
-awful.key({ cmdkey }, "i", function () awful.spawn(terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi") end),
-awful.key({ cmdkey }, "x", function () awful.spawn.with_shell("/sbin/start-stop-daemon --start --background --exec /usr/bin/xscreensaver -- -no-capture-stderr; sleep 2; xscreensaver-command -lock") end),
-awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
+awful.key({ cmdkey }, "v", function () awful.spawn("remmina") end),
+awful.key({ cmdkey }, "p", function () awful.spawn("pavucontrol") end),
+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),
+awful.key({ cmdkey }, "x", function ()
+    awful.spawn("xautolock -enable")
+    awful.spawn("xautolock -locknow")
+end),
+awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xautolock -disable") end),
+
+awful.key({ cmdkey }, "BackSpace", function () awful.spawn("pkill -USR1 offlineimap") end),
 
 -- function keys
 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
 
 -- function keys
 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
-awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
-awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
-awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
-awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
-awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
-awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
-awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
-awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
-awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
-awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
-awful.key(nil, "XF86Display", function () awful.spawn("") end),
+awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
+awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") end),
+awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
+awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -2%") end),
+awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
+awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +2%") end),
+awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
+awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute @DEFAULT_SOURCE@ toggle") end),
+awful.key({ cmdkey }, "Insert", function () awful.spawn("pa_cycle_default source") end),
+awful.key({ cmdkey }, "Delete", function () awful.spawn("pa_cycle_default sink") end),
+awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("light -U 10") end),
+awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("light -A 10") end),
+awful.key(nil, "XF86Display", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
+awful.key(nil, "XF86AudioStop", function () awful.spawn("autorandr --change --force"); initialise_to_autorandr_profile() end),
 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
 awful.key(nil, "XF86Search", function () awful.spawn("") end),
 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
 awful.key(nil, "XF86Search", function () awful.spawn("") end),
 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
-awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
+awful.key(nil, "XF86Explorer", function () awful.spawn("") end),
+awful.key(nil, "XF86Calculator", function () awful.spawn(terminal .. " -e ipython3 --profile=calc") end),
+awful.key(nil, "XF86Favorites", function () awful.spawn("systemctl suspend") end),
+
+awful.key({ cmdkey }, "Multi_key", function () run_output_notify("flameshot gui", "Output") end),
+awful.key({ cmdkey, "Shift" }, "Multi_key", function () run_output_notify("flameshot full --delay 2000 --clipboard", "Output") end),
+
+awful.key({ cmdkey }, "Up", function () awful.spawn("pap prev") end),
+awful.key({ cmdkey }, "Left", function () awful.spawn("pap seek -10") end),
+awful.key({ cmdkey, "Shift" }, "Left", function () awful.spawn("pap seek -60") end),
+awful.key({ cmdkey }, "Down", function () awful.spawn("pap next") end),
+awful.key({ cmdkey }, "Right", function () awful.spawn("pap seek +10") end),
+awful.key({ cmdkey, "Shift" }, "Right", function () awful.spawn("pap seek +60") end),
+awful.key({ cmdkey }, "space", function () awful.spawn("pap pause") end),
+awful.key({ cmdkey }, "\\", function () run_output_notify("pap info", "Track info") end),
+awful.key({ cmdkey }, "]", function () run_output_notify("pap list", "Playlist") end)
 )
 
 )
 
+function run_output_notify(cmd, title)
+    awful.spawn.easy_async(cmd, function(stdout, stderr, reason, exit_code)
+        if #stdout > 1 then
+            naughty.notify({
+                preset = naughty.config.presets.low,
+                title = title,
+                text = stdout})
+            end
+        end)
+end
+
 -- Set keys
 root.keys(globalkeys)
 -- }}}
 -- Set keys
 root.keys(globalkeys)
 -- }}}
@@ -624,9 +1011,41 @@ root.keys(globalkeys)
 -- {{{ Rules
 -- Rules to apply to new clients (through the "manage" signal).
 
 -- {{{ Rules
 -- Rules to apply to new clients (through the "manage" signal).
 
-local function move_to_tag(s, t)
+local function float_client_in_the_middle_with_margins(client, leftright, topbottom)
+    local wa = client.screen.workarea
+    if topbottom then
+        client.y = wa.y + topbottom
+        client.height = wa.height - 2*topbottom
+    else
+        client.y = wa.y + (wa.height - client.height)/2
+    end
+    if leftright then
+        client.x = wa.x + leftright
+        client.width = wa.width - 2*leftright
+    else
+        client.x = wa.x + (wa.width - client.width)/2
+    end
+end
+
+local function move_to_tag_by_name(s, tagname)
+    return function(c)
+        local t = awful.tag.find_by_name(s, tagname)
+        if not t then
+            error("No tag by the name of " .. tagname)
+            return
+        end
+        c:move_to_tag(t)
+    end
+end
+
+local function move_to_tag_or_create_volatile(s, tagname)
     return function(c)
     return function(c)
-        c:move_to_tag(tags[s][t])
+        local t = awful.tag.find_by_name(s, tagname)
+        if t then
+            c:move_to_tag(t)
+        else
+            th.move_to_new_tag(c, tagname, {}, true, true, true)
+        end
     end
 end
 
     end
 end
 
@@ -641,87 +1060,144 @@ awful.rules.rules = {
                      buttons = clientbuttons,
                      screen = awful.screen.preferred,
                      placement = awful.placement.no_overlap+awful.placement.no_offscreen,
                      buttons = clientbuttons,
                      screen = awful.screen.preferred,
                      placement = awful.placement.no_overlap+awful.placement.no_offscreen,
-                     floating = false
+                     floating = false,
+                     maximized = false,
                  },
     },
                  },
     },
-
-    -- Add titlebars to normal clients and dialogs
-    --DISABLED-- { rule_any = {type = { "normal", "dialog" }
-    --DISABLED--  }, properties = { titlebars_enabled = true }
-    --DISABLED-- },
-
     { rule = { type = "dialog" },
       properties = { floating = true,
     { rule = { type = "dialog" },
       properties = { floating = true,
+                     ontop = true,
+                     skip_taskbar = true,
+                     urgent = true,
+                     --new_tag = true,
+                     --switchtotag = true,
                      placement = awful.placement.centered
                      placement = awful.placement.centered
-                 }
+                   }
     },
     },
-
     { rule = { class = "URxvt" },
     { rule = { class = "URxvt" },
-               properties = {
-                   -- floating = false,
-                   size_hints_honor = false
-               } },
-    { rule = { class = "URxvt", instance = "irc" },
-               properties = {
-                   switchtotag = true
-               },
-               callback = move_to_tag(screen.count(), screen.count() == 1 and 2 or 1)
-           },
-    { rule = { class = "Firefox", instance = "Navigator" },
-               properties = {
-                   floating = false,
-               },
-               callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
-           },
-    { rule = { class = "Firefox-esr", instance = "Navigator" },
-               properties = {
-                   floating = false,
-               },
-               callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
-           },
-    { rule = { class = "Thunderbird", instance = "Mail" },
-               properties = {
-                   floating = false,
-               },
-               callback = move_to_tag(screen.count() == 1 and 1 or 2, 8)
-           },
-    { rule = { class = "Chromium", instance = "chromium" },
-               properties = {
-                   floating = false,
-               },
-               callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
-           },
-    { rule = { class = "Gscan2pdf" },
-               properties = {
-                   switchtotag = true
-               },
-               callback = move_to_tag(1, 5)
-           },
-    { rule = { name = "gscan2pdf .*" },
-               properties = {
-                   floating = false,
-               },
-           },
-    { rule = { class = "Thunar", type = "normal" },
-               properties = {
-                   floating = false,
-               },
-           },
-    { rule = { class = "MuPDF", instance = "mupdf" },
-               properties = {
-                   floating = true,
-               },
-           },
-    { rule = { class = "Pinentry", instance = "pinentry" },
-               properties = {
-                   floating = true,
+      properties = { size_hints_honor = false, }
+    },
+    { rule = { instance = "irc" },
+      callback = move_to_tag_by_name(nil, "irc"),
+    },
+    { rule = { class = "scrcpy" },
+      callback = move_to_tag_by_name(nil, "[]"),
+    },
+    { rule_any = { class = { "Firefox", "firefox" } },
+      callback = move_to_tag_by_name(nil, "ffx"),
+    },
+    { rule = { class = "Chromium" },
+      callback = move_to_tag_by_name(nil, "chr"),
+    },
+    { rule_any = { class = { "thunderbird", "Thunderbird" } },
+      callback = move_to_tag_by_name(nil, "cal"),
+    },
+    { rule = { instance = "mutt" },
+      properties = {
+          new_tag = {
+              name = "mutt",
+              layout = awful.layout.suit.fair.horizontal,
+              volatile = true
+          },
+          switchtotag = true,
+      },
+    },
+    { rule_any = { class = { "zoom" } },
+      callback = move_to_tag_or_create_volatile(nil, "Zoom"),
+    },
+    { rule_any = { class = { "Ssvnc.tcl" },
+                   class = { "Ssvnc" },
+                   name = { "SSL/SSH VNC Viewer.-" },
+                 },
+      callback = move_to_tag_or_create_volatile(nil, "SSVNC"),
+    },
+    { rule_any = { class = {
+        "Gxmessage",
+        "Pinentry"
+    }},
+      properties = { floating = true,
+                     maximized = false,
+                     focus = true,
+                     placement = awful.placement.centered,
+                   },
+    },
+    { rule_any = { instance = {
+        "tridactyl-edit",
+        "pdfshuffler",
+        "vlc",
+        "pavucontrol"
+    }},
+      properties = { floating = true,
+                     maximized = false,
+                     focus = true,
+                     placement = awful.placement.centered,
+                   },
+    },
+    { rule_any = { class = {
+                        "Gimp",
+                        "Inkscape",
+                        "Pitivi",
+                        "Audacity",
+                        "Microsoft Teams - Preview",
+                        "org.remmina.Remmina",
+                    },
+                    instance = {
+                        "libreoffice",
+                    }
+                },
+      except_any = { type = { "dialog" } },
+      properties = { new_tag = {
+                        layout = layouts.maximised,
+                        volatile = true,
+                    },
+                     --switchtotag = true,
+                     focus = true,
+                   },
                },
                },
-           },
-    { rule = { class = "Gxmessage" },
-               properties = {
-                   floating = true,
+    { rule_any = { class = {
+                        "Gscan2pdf",
+                    },
+                },
+      except_any = { type = { "dialog" } },
+      properties = { new_tag = {
+                        layout = layouts.default,
+                        volatile = true,
+                    },
+                    floating = true,
+                    maximized = false,
+                    focus = true,
+                    placement = awful.placement.centered,
+                    switchtotag = true,
+                    focus = true,
+                   },
                },
                },
-           },
+--XX--    { rule = { class = "Gscan2pdf" },
+--XX--               properties = {
+--XX--                   switchtotag = true
+--XX--               },
+--XX--               callback = move_to_tag(1, 5)
+--XX--           },
+--XX--    { rule = { name = "gscan2pdf .*" },
+--XX--               properties = {
+--XX--                   floating = false,
+--XX--               },
+--XX--           },
+--XX--    { rule = { class = "Thunar", type = "normal" },
+--XX--               properties = {
+--XX--                   floating = false,
+--XX--               },
+--XX--           },
+--XX--    { rule = { class = "Pinentry", instance = "pinentry" },
+--XX--               properties = {
+--XX--                   floating = true,
+--XX--               },
+--XX--           },
+--XX--    { rule = { class = "Gxmessage" },
+--XX--               properties = {
+--XX--                   floating = true,
+--XX--               },
+--XX--           },
+--XX--}
 }
 -- }}}
 
 }
 -- }}}
 
@@ -730,7 +1206,13 @@ awful.rules.rules = {
 client.connect_signal("manage", function (c)
     -- Set the windows at the slave,
     -- i.e. put it at the end of others instead of setting it master.
 client.connect_signal("manage", function (c)
     -- Set the windows at the slave,
     -- i.e. put it at the end of others instead of setting it master.
-    if not awesome.startup then awful.client.setslave(c) end
+    -- if not awesome.startup then awful.client.setslave(c) end
+    --if not awesome.startup then
+    --    local t = awful.screen.focused().selected_tag
+    --    if t.name == "xmutt" then
+    --        awful.client.setslave(c)
+    --    end
+    --end
 
     if awesome.startup and
       not c.size_hints.user_position
 
     if awesome.startup and
       not c.size_hints.user_position
@@ -791,13 +1273,40 @@ client.connect_signal("mouse::enter", function(c)
         and awful.client.focus.filter(c) then
         client.focus = c
     end
         and awful.client.focus.filter(c) then
         client.focus = c
     end
+--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 
+--                    something like this
 end)
 
 end)
 
-client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
-client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
+client.connect_signal("focus", function(c)
+    c.border_color = beautiful.border_focus
+end)
+client.connect_signal("unfocus", function(c)
+    c.border_color = beautiful.border_normal
+end)
 
 awful.ewmh.add_activate_filter(function(c, context, hints)
 
 awful.ewmh.add_activate_filter(function(c, context, hints)
-    if context == "ewmh" and (c.class == "Firefox-esr" or c.class == "Firefox") then return false end
+    if context == "ewmh" then
+        if (c.class == "Firefox-esr" or c.class == "Firefox") then
+            return false
+        end
+    end
+end)
+
+client.connect_signal("request::activate", function(c, context, hints)
+    if gears.table.hasitem({
+        "client.focus.byidx",
+        "client.jumpto",
+        "autofocus.check_focus",
+        "rules",
+        "ewmh",
+    }, context) then
+        gears.timer.delayed_call(function()
+            -- we need a delayed call so that we execute *after layout changes
+            if hints.raise and c == client.focus and client.focus:isvisible() then
+                move_mouse_to_area(client.focus)
+            end
+        end)
+    end
 end)
 
 -- vim:ft=lua:sw=4:sts=4:ts=4:et
 end)
 
 -- vim:ft=lua:sw=4:sts=4:ts=4:et