Dear users,I was annoyed by some unwanted focus changes whilst using awesome and thus created the attached config that should prevent most of them. Maybe it'll be useful to some of you (I noticed some threads on this mailing list about focus steal stuff after all).
The code should be rather self-explanatory for anyone interested. @Devs: Not sure whether you'd be interested to push parts of that upstream. Kind Regards David -- You received this message because you are subscribed to the Google Groups "qubes-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to qubes-devel+unsubscr...@googlegroups.com. To post to this group, send email to qubes-devel@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/qubes-devel/582a6bf5-0d93-b63c-2e3f-a1ba65400deb%40hackingthe.net. For more options, visit https://groups.google.com/d/optout.
-- focus changes only on the following events: -- - mouse move & click afterwards -- works, last tested 2017-05-01 -- - workspace/tag change -- works, last tested 2017-05-01 -- - pre-defined key combinations for focus changes (Mod-j & Mod-k) -- works, last tested 2017-05-01 -- - tag assignments and unassignments -- works, last tested 2017-05-01 -- Everything else is considered an unwanted "focus steal". In particular the following events must never cause a focus change: -- - new window created -- works, last tested 2017-05-01 (start e.g. gnome-calculator from console) -- - window closed -- focus changes to another window, i.e. currently does *NOT* work (pending on https://github.com/awesomeWM/awesome/issues/164 ?), last tested 2017-05-01 -- - application request -- seems to work (hard to test; done: thunderbird password prompt does not receive focus), last tested 2017-05-01 -- - mouse move without click/sloppy focus -- works, last tested 2017-05-01 -- -- use Meta + Ctrl + r to reload the config -- Standard awesome library local gears = require("gears") local awful = require("awful") awful.rules = require("awful.rules") --make sure focus changes on tag changes, assignments and unassignments work require("autofocus_custom") -- Widget and layout library local wibox = require("wibox") -- Theme handling library local beautiful = require("beautiful") -- Notification library local naughty = require("naughty") local menubar = require("menubar") local qubes = require("qubes") -- {{{ Error handling -- Check if awesome encountered an error during startup and fell back to -- another config (This code will only ever execute for the fallback config) if awesome.startup_errors then naughty.notify({ preset = naughty.config.presets.critical, title = "Oops, there were errors during startup!", text = awesome.startup_errors }) end -- Handle runtime errors after startup do local in_error = false awesome.connect_signal("debug::error", function (err) -- Make sure we don't go into an endless error loop if in_error then return end in_error = true naughty.notify({ preset = naughty.config.presets.critical, title = "Oops, an error happened!", text = err }) in_error = false end) end -- }}} -- {{{ Variable definitions -- Themes define colours, icons, font and wallpapers. beautiful.init("/usr/share/awesome/themes/default/theme.lua") -- This is used later as the default terminal and editor to run. terminal = "xterm" editor = os.getenv("EDITOR") or "vi" editor_cmd = terminal .. " -e " .. editor -- Default modkey. -- Usually, Mod4 is the key with a logo between Control and Alt. -- If you do not like this or do not have such a key, -- I suggest you to remap Mod4 to another key using xmodmap or other tools. -- However, you can use another modifier like Mod1, but it may interact with others. modkey = "Mod4" -- Table of layouts to cover with awful.layout.inc, order matters. local 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 } -- }}} -- {{{ Wallpaper if beautiful.wallpaper then for s = 1, screen.count() do gears.wallpaper.maximized(beautiful.wallpaper, s, true) end end -- }}} -- {{{ Tags -- Define a tag table which hold all screen tags. tags = {} for s = 1, screen.count() do -- Each screen has its own tag table. tags[s] = awful.tag({ 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s, layouts[2]) end -- }}} -- {{{ Menu -- Create a laucher widget and a main menu mymainmenu = awful.menu({ items = qubes.make_menu(), theme = { width = 300, height = 24 } }) mylauncher = awful.widget.launcher({ image = '/usr/share/icons/hicolor/16x16/apps/qubes-logo-icon.png', menu = mymainmenu }) -- Menubar configuration menubar.utils.terminal = terminal -- Set the terminal for applications that require it -- }}} -- {{{ Wibox -- Create a textclock widget mytextclock = awful.widget.textclock() -- Create a wibox for each screen and add it mywibox = {} mypromptbox = {} mylayoutbox = {} mytaglist = {} mytaglist.buttons = awful.util.table.join( awful.button({ }, 1, awful.tag.viewonly), awful.button({ modkey }, 1, awful.client.movetotag), awful.button({ }, 3, awful.tag.viewtoggle), awful.button({ modkey }, 3, awful.client.toggletag), awful.button({ }, 4, function(t) awful.tag.viewnext(awful.tag.getscreen(t)) end), awful.button({ }, 5, function(t) awful.tag.viewprev(awful.tag.getscreen(t)) end) ) mytasklist = {} mytasklist.buttons = awful.util.table.join( awful.button({ }, 1, function (c) if c == client.focus then c.minimized = true else -- Without this, the following -- :isvisible() makes no sense c.minimized = false if not c:isvisible() then awful.tag.viewonly(c:tags()[1]) end -- This will also un-minimize -- the client, if needed client.focus = c c:raise() end end), awful.button({ }, 3, function () if instance then instance:hide() instance = nil else instance = awful.menu.clients({ theme = { width = 250 } }) end end), awful.button({ }, 4, function () awful.client.focus.byidx(1) if client.focus then client.focus:raise() end end), awful.button({ }, 5, function () awful.client.focus.byidx(-1) if client.focus then client.focus:raise() end end)) for s = 1, screen.count() do -- Create a promptbox for each screen mypromptbox[s] = awful.widget.prompt() -- 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( awful.button({ }, 1, function () awful.layout.inc(layouts, 1) end), awful.button({ }, 3, function () awful.layout.inc(layouts, -1) end), awful.button({ }, 4, function () awful.layout.inc(layouts, 1) end), awful.button({ }, 5, function () awful.layout.inc(layouts, -1) end))) -- Create a taglist widget mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons) -- Create a tasklist widget mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons) -- Create the wibox mywibox[s] = awful.wibox({ position = "top", screen = s }) -- Widgets that are aligned to the left local left_layout = wibox.layout.fixed.horizontal() left_layout:add(mylauncher) left_layout:add(mytaglist[s]) left_layout:add(mypromptbox[s]) -- Widgets that are aligned to the right local right_layout = wibox.layout.fixed.horizontal() if s == 1 then right_layout:add(wibox.widget.systray()) end right_layout:add(mytextclock) right_layout:add(mylayoutbox[s]) -- Now bring it all together (with the tasklist in the middle) local layout = wibox.layout.align.horizontal() layout:set_left(left_layout) layout:set_middle(mytasklist[s]) layout:set_right(right_layout) mywibox[s]:set_widget(layout) end -- }}} -- {{{ Mouse bindings root.buttons(awful.util.table.join( awful.button({ }, 3, function () mymainmenu:toggle() end) --next 2 lines commented out as they may cause accidental tag and thus focus switches --awful.button({ }, 4, awful.tag.viewnext), --awful.button({ }, 5, awful.tag.viewprev) )) -- }}} -- {{{ Key bindings globalkeys = awful.util.table.join( awful.key({ modkey, }, "Left", awful.tag.viewprev ), awful.key({ modkey, }, "Right", awful.tag.viewnext ), awful.key({ modkey, }, "Escape", awful.tag.history.restore), awful.key({ modkey, }, "j", function () awful.client.focus.byidx( 1) if client.focus then client.focus:raise() end --if still no focus --> focus some window on the screen with the mouse check_focus(awful.mouse) end), awful.key({ modkey, }, "k", function () awful.client.focus.byidx(-1) if client.focus then client.focus:raise() end end), awful.key({ modkey, }, "w", function () mymainmenu:show() end), -- Layout manipulation awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end), awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end), awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end), awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end), awful.key({ modkey, }, "u", awful.client.urgent.jumpto), awful.key({ modkey, }, "Tab", function () awful.client.focus.history.previous() if client.focus then client.focus:raise() end end), -- Standard program awful.key({ modkey, }, "Return", function () awful.util.spawn(terminal) end), awful.key({ modkey, "Control" }, "r", awesome.restart), awful.key({ modkey, "Shift" }, "q", awesome.quit), awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end), awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end), awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1) end), awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end), awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1) end), awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end), awful.key({ modkey, }, "space", function () awful.layout.inc(layouts, 1) end), awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, -1) end), awful.key({ modkey, "Control" }, "n", awful.client.restore), -- Prompt awful.key({ modkey }, "r", function () mypromptbox[mouse.screen]:run() end), awful.key({ modkey }, "x", function () awful.prompt.run({ prompt = "Run Lua code: " }, mypromptbox[mouse.screen].widget, awful.util.eval, nil, awful.util.getdir("cache") .. "/history_eval") end), -- Menubar awful.key({ modkey }, "p", function() menubar.show() end) --, --custom shortcuts --lock screen -- awful.key({ modkey }, "q", function () awful.util.spawn("xscreensaver-command -lock") end), --take screenshot (requires scrot installed in dom0) --small note: bash -c only works with " here as it is not executed inside another bash... -- awful.key({ modkey }, "F4", function () awful.util.spawn("bash -c \"mkdir -p /home/user/screenshots && scrot -e 'mv $f /home/user/screenshots'\"") end), --raise & lower volume, mute -- awful.key({ modkey }, "F7", function () awful.util.spawn("amixer sset Master toggle") end), -- awful.key({ modkey }, "F8", function () awful.util.spawn("amixer set Master 1%-") end), -- awful.key({ modkey }, "F9", function () awful.util.spawn("amixer set Master 1%+") end), --adjust brightness (requires xbacklight in dom0) -- awful.key({ modkey }, "F1", function () awful.util.spawn("xbacklight -dec 2") end), -- awful.key({ modkey }, "F2", function () awful.util.spawn("xbacklight -inc 2") end) ) clientkeys = awful.util.table.join( awful.key({ modkey, }, "f", function (c) c.fullscreen = not c.fullscreen end), awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end), awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ), awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end), awful.key({ modkey, }, "o", awful.client.movetoscreen ), awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end), awful.key({ modkey, }, "n", function (c) -- The client currently has the input focus, so it cannot be -- minimized, since minimized clients can't have the focus. c.minimized = true end), awful.key({ modkey, }, "m", function (c) c.maximized_horizontal = not c.maximized_horizontal c.maximized_vertical = not c.maximized_vertical end) ) -- Bind all key numbers to tags. -- Be careful: we use keycodes to make it works on any keyboard layout. -- This should map on the top row of your keyboard, usually 1 to 9. for i = 1, 9 do globalkeys = awful.util.table.join(globalkeys, -- View tag only. awful.key({ modkey }, "#" .. i + 9, function () local screen = mouse.screen local tag = awful.tag.gettags(screen)[i] if tag then awful.tag.viewonly(tag) end end), -- Toggle tag. awful.key({ modkey, "Control" }, "#" .. i + 9, function () local screen = mouse.screen local tag = awful.tag.gettags(screen)[i] if tag then awful.tag.viewtoggle(tag) end end), -- Move client to tag. awful.key({ modkey, "Shift" }, "#" .. i + 9, function () if client.focus then local tag = awful.tag.gettags(client.focus.screen)[i] if tag then awful.client.movetotag(tag) end end end), -- Toggle tag. awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, function () if client.focus then local tag = awful.tag.gettags(client.focus.screen)[i] if tag then awful.client.toggletag(tag) end end end)) end clientbuttons = awful.util.table.join( --left click --> focus change awful.button({ }, 1, function (c) client.focus = c; c:raise() end), --some further buttons awful.button({ modkey }, 1, awful.mouse.client.move), awful.button({ modkey }, 3, awful.mouse.client.resize)) -- Set keys root.keys(globalkeys) -- }}} -- {{{ Rules -- Rules to apply to new clients (through the "manage" signal). awful.rules.rules = { -- All clients will match this rule. { rule = { }, properties = { --make the colored Qubes borders quite visible (important on high-res screens) border_width = 7, border_color = beautiful.border_normal, --this will prevent some focus steals, old: focus = awful.client.focus.filter focus = false, raise = true, keys = clientkeys, buttons = clientbuttons } }, -- Set Qubes Manager to always be displayed in tag 9 of screen 1. --{ rule = { name = "Qubes VM Manager" }, properties = { tag = tags[1][9] } }, { rule = { class = "MPlayer" }, properties = { floating = true } }, { rule = { class = "pinentry" }, properties = { floating = true } }, { rule = { class = "gimp" }, properties = { floating = true } }, } -- }}} -- {{{ Signals -- Signal function to execute when a new client appears. client.connect_signal("manage", function (c, startup) -- sloppy focus can cause some trouble (focus changes on mouse movement) --> currently commented out --c:connect_signal("mouse::enter", function(c) --if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier and awful.client.focus.filter(c) then --client.focus = c --end --end) if not startup then -- Set the windows at the slave, -- i.e. put it at the end of others instead of setting it master. -- awful.client.setslave(c) -- Put windows in a smart way, only if they do not set an initial position. if not c.size_hints.user_position and not c.size_hints.program_position then awful.placement.no_overlap(c) awful.placement.no_offscreen(c) end end local titlebars_enabled = false if titlebars_enabled and (c.type == "normal" or c.type == "dialog") then -- buttons for the titlebar local buttons = awful.util.table.join( awful.button({ }, 1, function() client.focus = c c:raise() awful.mouse.client.move(c) end), awful.button({ }, 3, function() client.focus = c c:raise() awful.mouse.client.resize(c) end) ) -- Widgets that are aligned to the left local left_layout = wibox.layout.fixed.horizontal() left_layout:add(awful.titlebar.widget.iconwidget(c)) left_layout:buttons(buttons) -- Widgets that are aligned to the right local right_layout = wibox.layout.fixed.horizontal() right_layout:add(awful.titlebar.widget.floatingbutton(c)) right_layout:add(awful.titlebar.widget.maximizedbutton(c)) right_layout:add(awful.titlebar.widget.stickybutton(c)) right_layout:add(awful.titlebar.widget.ontopbutton(c)) right_layout:add(awful.titlebar.widget.closebutton(c)) -- The title goes in the middle local middle_layout = wibox.layout.flex.horizontal() local title = awful.titlebar.widget.titlewidget(c) title:set_align("center") middle_layout:add(title) middle_layout:buttons(buttons) -- Now bring it all together local layout = wibox.layout.align.horizontal() layout:set_left(left_layout) layout:set_right(right_layout) layout:set_middle(middle_layout) awful.titlebar(c):set_widget(layout) end end) --qubes.get_colour_focus(c) must _not_ be identical to qubes.get_colour(c) to achieve visible changes on focus/unfocus --TODO: unfortunately it is currently identical for black (dom0 + mostly vault VMs) --> qubes issue #2780 client.connect_signal("focus", function(c) c.border_color = qubes.get_colour_focus(c) end) client.connect_signal("unfocus", function(c) c.border_color = qubes.get_colour(c) end) --set some qubes-specific X-window properties client.connect_signal("manage", qubes.manage) --make sure the correct window color is set upon creation of a window (qubes.manage always sets the focused color, but windows may startup unfocused) client.connect_signal("manage", function (c, startup) if (c == client.focus) then c.border_color = qubes.get_colour_focus(c) else c.border_color = qubes.get_colour(c) end end) -- disable startup-notifications globally (disables the annoying loading cursor) --local oldspawn = awful.util.spawn --awful.util.spawn = function (s) -- oldspawn(s, false) --end -- }}}
--------------------------------------------------------------------------- -- @author Julien Danjou <jul...@danjou.info> -- @copyright 2009 Julien Danjou -- @release v3.5.9 --------------------------------------------------------------------------- --tripleh: slightly modified version of /usr/share/awesome/lib/awful/autofocus.lua local client = client local screen = screen local aclient = require("awful.client") local atag = require("awful.tag") --- When loaded, this module makes sure that there's always a client that will have focus -- on events such as tag switching, client unmanaging, etc. -- awful.autofocus -- Give focus when clients appear/disappear and no one else has focus. -- @param obj An object that should have a .screen property. function check_focus(obj) -- When no visible client has the focus... if not client.focus or not client.focus:isvisible() then local c = aclient.focus.history.get(obj.screen, 0) if c then client.focus = c end end end -- Give focus on tag selection change. -- @param tag A tag object function check_focus_tag(t) local s = atag.getscreen(t) if not s then return end check_focus({ screen = s }) if client.focus and client.focus.screen ~= s then local c = aclient.focus.history.get(s, 0) if c then client.focus = c end end end --clear any focus function clear_focus() --this doesn't work atm -_- --https://github.com/awesomeWM/awesome/issues/164 --(apparently Qubes uses an older awesome version) --client.focus = nil end --tripleh: made above functions global & removed some focus switches below (user interaction required instead) atag.attached_connect_signal(nil, "property::selected", check_focus_tag) client.connect_signal("unmanage", clear_focus) client.connect_signal("tagged", check_focus) client.connect_signal("untagged", check_focus) client.connect_signal("property::hidden", clear_focus) client.connect_signal("property::minimized", clear_focus) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
smime.p7s
Description: S/MIME Cryptographic Signature