11 KiB
AwesomeWM Customizations
This page focuses on AwesomeWM customizations specific to Qubes OS. For generic AwesomeWM customizations you might want to have a look at the AwesomeWM website.
Customizations for AwesomeWM are usually done at ~/.config/awesome/rc.lua
. The default file can be found at /etc/xdg/awesome/rc.lua
.
Application menu
Starting from Qubes 4.0 application menu entries specific to AwesomeWM can be put into ~/.config/awesome/xdg-menu/
following the freedesktop standard. The folder might have to be created.
Focus steal hardening
The default Qubes OS AwesomeWM installation comes with the defaults set by the AwesomeWM developers for focus changes. Some users may want more tight control over window focus changes - especially since focus changes can have security implications when sensitive data is provided to an incorrect application or even Qube.
Definition
For the below example we'll define wanted focus changes as one of the below:
- mouse move & click afterwards
- workspace/tag change
- pre-defined key combinations for focus changes (e.g. Mod-j & Mod-k)
- focused window moved to other tag 1
- focused window closed 1
- new window created in a workspace with only unfocused windows or in an empty workspace
(1 These are allowed to cause a focus switch to another window according to a predefined algorithm as otherwise no window would be focused.)
Everything else is considered an unwanted focus steal.
In particular the following events are not meant to cause a focus change:
- new window created in a workspace with a focused window
- unfocused window closed
- unfocused window moved to another tag/workspace
- application request
- mouse move without click (sloppy focus)
For the below example other requests from applications to the window manager are meant to be ignored in general as well, e.g.:
- windows shouldn't be able to maximize themselves without the user giving a respective command to the WM (simple test: Firefox F11 next to another window)
- windows shouldn't be able to change their size themselves
- windows shouldn't be able to modify their borders in any way
Users may want to adjust their definitions and respective implementations according to their needs.
Implementation
The implementation may be specific to the AwesomeWM version you're running. This guide refers to AwesomeWM version 4.3 which is available to Qubes 4.1 users.
Please keep in mind that this guide may not be conclusive. Your mileage may vary.
Remove unwanted focus changing key bindings
The mouse bindings
awful.button({ }, 4, awful.tag.viewnext),
awful.button({ }, 5, awful.tag.viewprev)
in the default rc.lua may cause tag and thus focus changes without keyboard interaction and tend to happen accidentally. This doesn't suit our definition from above and should therefore be removed or commented out.
Adjust rules for new windows
The default window/client rule allows certain focus changes whenever new windows are created via focus = awful.client.focus.filter
. These changes can be prevented entirely by setting focus = false
.
Alternatively users may provide their own focus filter functions.
Never hide borders
By default AwesomeWM may hide window borders incl. the Qubes colors for fullscreen or maximized windows. In order to prevent that, put the following two lines at the bottom of your rc.lua:
beautiful.fullscreen_hide_border = false
beautiful.maximized_hide_border = false
Disable sloppy focus
In your rc.lua you'll find a section such as
-- Enable sloppy focus, so that focus follows mouse.
client.connect_signal("mouse::enter", function(c)
c:emit_signal("request::activate", "mouse_enter", {raise = false})
end)
These enable sloppy focus aka focus changes on mouse movements (without clicking) and should be removed or commented out to disable that behaviour.
Enable right-click focus changes
In your rc.lua you should find a section which enables left-click focus changes such as
awful.button({ }, 1, function (c)
c:emit_signal("request::activate", "mouse_click", {raise = true})
end),
Add the following section below to enable focus changes on right mouse clicks:
awful.button({ }, 3, function (c)
c:emit_signal("request::activate", "mouse_click", {raise = true})
end),
If you want other mouse buttons to change the focus as well, feel free to add further entries (0 = all mouse buttons).
Ignore requests from applications to the window manager
Applications and running Qube windows may request from AwesomeWM to become focused.
Handling of such requests is currently mostly implemented by AwesomeWM in the file /usr/share/awesome/lib/awful/ewmh.lua
. You can either comment out the respective client.connect_singal()
lines in that file (it will change back after each AwesomeWM update though) or disconnect the signals in your rc.lua as well as use the built-in filter functionality.
To do the latter, add the following lines to the end of your rc.lua:
local ewmh = require("awful.ewmh")
ewmh.add_activate_filter(function(c, context, hints) return false end, "ewmh") --ignore client requests to become focused
client.disconnect_signal("request::urgent", ewmh.urgent) --ignore client requests to become an "urgent" window
client.disconnect_signal("request::geometry", ewmh.merge_maximization) --ignore client maximization requests
client.disconnect_signal("request::geometry", ewmh.client_geometry_requests) --ignore clients requesting to move themselves
Change the autofocus implementation
The line require("awful.autofocus")
in your rc.lua loads a module that moves the focus to another window whenever a window is moved to another workspace or closed. In the AwesomeWM default implementation, this module keeps track of the order in which windows were focused and sets the focus to the last focused one whenever the currently focused window disappears.
Some users may want to modify that default behaviour.
In order to do that, you can copy the file /usr/share/awesome/lib/awful/autofocus.lua
to e.g. ~/.config/awesome/autofocus_custom.lua
and replace the line mentioned above with require("autofocus_custom")
.
Then you can customise the focus behavior.
For example, the following will make the focus move to the window under the mouse cursor whenever focus is lost and only use the history on tag switches:
---------------------------------------------------------------------------
--- Autofocus functions.
--
-- 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.
--
-- @author Julien Danjou <julien@danjou.info>
-- @copyright 2009 Julien Danjou
-- @module awful.autofocus
---------------------------------------------------------------------------
local client = client
local aclient = require("awful.client")
local ascreen = require("awful.screen")
local timer = require("gears.timer")
local function filter_sticky(c)
return not c.sticky and aclient.focus.filter(c)
end
--- Give focus when clients appear/disappear.
--
-- @param obj An object that should have a .screen property.
function check_focus(obj)
if obj.screen == nil then return end
if not obj.screen.valid then return end
-- When no visible client has the focus...
if not client.focus or not client.focus:isvisible() then
local c = aclient.focus.history.get(screen[obj.screen], 0, filter_sticky)
if not c then
c = aclient.focus.history.get(screen[obj.screen], 0, aclient.focus.filter)
end
if c then
c:emit_signal("request::activate", "autofocus.check_focus",
{raise=false})
end
end
end
--- Check client focus (delayed).
-- @param obj An object that should have a .screen property.
local function check_focus_delayed(obj)
timer.delayed_call(check_focus, {screen = obj.screen})
end
--- Give focus on tag selection change.
--
-- @param tag A tag object
function check_focus_tag(t)
local s = t.screen
if (not s) or (not s.valid) then return end
s = screen[s]
check_focus({ screen = s })
if client.focus and screen[client.focus.screen] ~= s then
local c = aclient.focus.history.get(s, 0, filter_sticky)
if not c then
c = aclient.focus.history.get(s, 0, aclient.focus.filter)
end
if c then
c:emit_signal("request::activate", "autofocus.check_focus_tag",
{raise=false})
end
end
end
-- Clear any focus.
function clear_focus()
client.focus = nil
end
local pending = false
local glib = require("lgi").GLib
--focus the window under the mouse, if nothing is focused
--idea from https://github.com/awesomeWM/awesome/issues/2433
--fallback: true|false - fall back to the focus history, if the mouse points
-- nowhere (recommended default: false)
function check_focus_mouse(fallback)
if not pending then
pending = true
glib.idle_add(glib.PRIORITY_DEFAULT_IDLE, function()
pending = false
if not client.focus then
local c = mouse.current_client
if c then
client.focus = c
else
if fallback then
local t = ascreen.focused().selected_tag
if t then
check_focus_tag(t)
end
end
end
end
return false
end)
end
end
--further delayed variant of check_focus_mouse(), required for just created windows
local function check_focus_mouse_delayed()
timer.delayed_call(check_focus_mouse)
end
--make the focus follow the mouse on the below events, if nothing else is focused
client.connect_signal("manage", check_focus_mouse_delayed) --for empty workspaces or workspace without focused window
client.connect_signal("unmanage", check_focus_mouse_delayed)
client.connect_signal("tagged", check_focus_mouse_delayed)
client.connect_signal("untagged", check_focus_mouse_delayed)
client.connect_signal("property::hidden", check_focus_mouse_delayed)
client.connect_signal("property::minimized", check_focus_mouse_delayed)
client.connect_signal("property::sticky", check_focus_mouse_delayed)
--use history on tag switch:
tag.connect_signal("property::selected", function (t)
timer.delayed_call(check_focus_tag, t)
end)
You might also want to add the check_focus_mouse()
function to your Mod-j and Mod-k implementations to be able to obtain a focused window even if no window happens to be focused.
Troubleshooting
Issues with e.g. your rc.lua
configuration can be identified in dom0 from the ~/.xsession-errors
log.
If AwesomeWM encounters an error, it'll also either display a red notification or return you to the display manager (usually the login screen).