seninha.org
2022-04-12
In this post, I document how I set up my X11 desktop (mostly for myself
for future reference). This is basically a tour through my
~/.xsession
file.
The first interaction with X11 in my OpenBSD system is the display
manager, Xenodm(1), which prompts
for my name and password for logging in. I've done just the following
few changes in /etc/X11/xenodm/Xsetup_0
:
xconsole(1)
.
xset b off
.
xsetroot(1)
.
xkbcomp(1)
.
#!/bin/sh
# $OpenBSD: Xsetup_0,v 1.8 2020/07/04 13:32:50 matthieu Exp $
xsetroot -bg "#000000" -fg "#121212" -mod 3 3
#xconsole -geometry 480x130-0-0 -daemon -notify -verbose -fn fixed -exitOnFail
xset b off
xkbcomp /etc/X11/xenodm/xkeymap $DISPLAY
# install package openbsd-backgrounds
# then uncomment:
#
# if test -x /usr/local/bin/openbsd-wallpaper
# then
# /usr/local/bin/openbsd-wallpaper
# fi
# sxpm OpenBSD.xpm &
My Xenodm is the standard one, I have not riced it. But if you want to customize Xenodm, check out this, and this.
After logging in as my user, Xenodm(1) runs /etc/X11/xenodm/Xsession
as my user (not as root). The main job of this system-wide script is to
call the user-specific
~/.xsession
script. But it does some other things before so:
~/.xsession-errors
. This file is
very useful to check why a X11 program has malfunctioned.
~/.ssh/
directory and, if found
one, runs ssh-agent, which prompts for my SSH password and hold my SSH
private keys. Thus, I only need to type my SSH password once, and the
keys will be hold through the entire X11 session, this is very handy.
~/.xsession
exists, and
calls it if it exists (or call fvwm(1) if it does not).
From now on, I will document what my ~/.xsession
does. To read it at
the time of this writing, check it
here.
My ~/.xsession
is a POSIX sh(1)
script. The first thing it does is
to enable sh's monitor mode (enable job control) on the script. It then
traps the EXIT
special signal to call the atexit
function when the
script exits. This function just kills the processes in the same process
group as the shell itself and in the process groups of the shell's
background jobs.
Here is the snipped of my ~/.xsession
that preparates the shell
process:
#!/bin/sh
set -m
atexit() {
kill -TERM -- -$$ $(printf "-%s " $(jobs -p))
}
trap 'atexit' EXIT
In OpenBSD 7.0, it may be necessary to fix a problem caused by the update of Xenocara to version 21.1.1. So the following line may be necessary:
xrandr --dpi 96
I set my environment variables in ~/.profile
. This file is then
sourced by ~/.xsession
for my X11 programs to have access to those
variables.
My X11 programs also need access to the X resources (which are basically
environment variables, but for X11 programs). I use xrdb(1)
to load
the file ~/rules/Xresources
, which define them. However, this file
uses some environment variables, which have been defined before, but
xrdb
does not expand environment variables in the file it reads. To
solve this, I created an awk script called
expenv
to expand environment variables in a file. I then pass the output of
expenv
to xrdb
.
# Load environment variables and xresources
. $HOME/.profile
expenv $HOME/rules/Xresources | xrdb -merge -load -
My X resources define the 16 basic terminal colors, the terminal background and foreground colors, and the look and feel of X11 programs (especially those based on Motif and Xaw/Athena). You can check my Xresources file here
The following image shows how my system looks like with those resources set:
The next command in ~/.xsession
uses xkbcomp
to set up my customized
keyboard layout, which is based on ABNT-2 keyboard layout (which is
itself a QWERTY-like layout). In particular, I moved Esc to the first
key and reorganized some symbols. The image below shows part of my
keyboard layout (there is much more to it, but I'm too lazy to edit the
image).
# Load keymap
xkbcomp $RULESDIR/xkeymap $DISPLAY 2>/dev/null
The following commands make the mouse pointer invisible after a brief period of time and make Thinkpad's trackpoint work as expected on X11.
# make mouse invisible after a brief period
unclutter &
# thinkpad trackpoint
xinput set-prop "/dev/wsmouse" "WS Pointer Wheel Emulation" 1
xinput set-prop "/dev/wsmouse" "WS Pointer Wheel Emulation Button" 2
xinput set-prop "/dev/wsmouse" "WS Pointer Wheel Emulation Axes" 6 7 4 5
synclient TapButton1=1
synclient TapButton2=2
synclient TapButton3=3
synclient AccelFactor=0
synclient HorizTwoFingerScroll=1
I use picom as my X11 compositor. I invoke it with a set of command-line arguments that creates a “blue aura” around the active window, as you can see in the image below.
# compositor
picom -c -l -15 -t -15 \
--shadow-radius 15 \
--shadow-green 1.0 \
--shadow-blue 1.0 \
--use-ewmh-active-win \
--shadow-exclude '!focused' &
I use xnotify for displaying
notifications on the screen. Xnotify reads notification strings from
the standard input and display each notification on a small window on
the screen. To be usable, it must read from a named pipe, which other
programs should write into. The commands below create the named pipe,
invoke xnotify
reading from it, and invoke some
notification daemons that write into it.
export XNOTIFYFIFO="$HOME/cache/xnotify$DISPLAY.fifo"
coverfile="$HOME/cache/cover.png"
rm -f "$XNOTIFYFIFO"
mkfifo "$XNOTIFYFIFO"
xnotify -ws 10 <"$XNOTIFYFIFO" &
notifycpu >"$XNOTIFYFIFO" &
notifymus >"$XNOTIFYFIFO" &
I currently use only two notifications, implemented as functions in my
~/.xsession
: notifycpu
, which reads the /var/log/daemon
log file
and checks for battery and CPU temperature, notifying when the battery
gets low and the CPU gets hot; and notifymus
which uses mpc
to
notify when the current song changes. Below is an image of one of such
notifications, which appear at the top right corner of my screen.
Xnotify can create notification windows in two different modes:
-w
option), xnotify
creates the notification window and expects that the window manager
manages it. It needs a compatible window manager. At the time of
this writing, the only window manager I know that manages notification
windows is shod
. The window manager places the notification on the
proper corner of the screen, and draws a decoration around it. This
is the mode I use.
Shod, the window manager I use, can swallow little windows called dockapps into a panel called dock. The usual dockapps are those used on the WindowMaker window manager, but shod also supports them. The dockapps I use are the following:
# dockapps
paginator -iw -g64x192 -l1x5 &
bubblemon &
wmapm &
wmclock &
WMmp &
The image below shows my dock and the dockapps in it.
There are a lot of ways to spawn an application. You can open a terminal and invoke it. Or you can use something like sxhkd to bind a key combination to a command. You can also use dmenu to spawn an application; or use the right-click context menu offered by some window managers, such as Openbox. I used to use all those methods, until I realized that I was specifying the same configuration twice (or three times): once for sxhkd, once for dmenu, and once for the right-click menu. After realizing that, I hacked my right click menu to support all those input methods.
xmenu -ew rules/control &
Xmenu is first of all a menu system. It can present itself as a dockapp which I dock on the dock. I can navigate through the menus and select an entry to be executed by the shell.
Each entry in the menu can be bound to a key press. For example, I bind
Alt+T
to open a terminal, and Alt+Shift+5
to move the active window
to the fifth virtual desktop. I also bind Alt+Space
to the run
entry, which is explained in the paragraph below. Xmenu grabs those key
combinations and runs the same command it would run when selecting those
entries in the menu.
One of the entries of xmenu is special. It is the runner. When it is entered (either through the menu or via a keypress) it opens an interactive filter (either dmenu or, in my case, xfilter) and pipes all the entries, one per line, to that filter. Then, I can type in an entry and select it, as you can see in the video below:
(There was a bug on my config... I opened the acme
manpage on section
3, and it opened the manpage on section 1.)
I use an alternative menu system, with way fewer entries, called
πmenu. I use it as a
right-click menu for the desktop. It only works on the plain desktop
(not on maximized or full-screen windows), although I can invoke it with
Super+Button1
click.
pmenu -ex Super-3 <rules/rootmenu &
Then, at the end of my ~/.xsession
, I call
shod, my window manager.
shod
The main feature of shod is the possibility to tile, and even tab, windows inside floating containers. The image below shows a floating container with some windows inside it.
This feature was inspired mainly on acme, Plan 9's text editor and general user interface. Acme can also tile windows (but it is limited to text windows only) inside a single main, floating major window.
I need to focus on other things. Ricing is not a normal-person hobby.