💾 Archived View for lieba.ch › log › ubuntu-setup.gmi captured on 2024-03-21 at 14:45:46. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
I have just set up my trusty old ThinkPad X1 Carbon 3rd gen (2015 vintage) with Ubuntu 22.04 LTS. I have run OpenBSD on it for a long while, but emacs, among other things, play better with Linux, and Linux perform better on this laptop than OpenBSD. Ubuntu is the Linux distribution I am most at home with, so it's a perfectly boring choice for me, in the most positive way.
First up is my super duper comfortable Suckless Desktop Environment™ and dotfiles.
Suckless Desktop Environment git repo @ Sourcehut
My dotfiles git repo @ Sourcehut
Get a real Firefox, not a snap, Ploum have the technical solution, followed by a software-theological rant I completely agree with:
The Theological Problem Behind Firefox in Ubuntu 22.04
Add kelleyk's emacs PPA and install Emacs 28 with native compilation and fetch my emacs setup from git.
Kevin Kelley's Emacs stable releases PPA
My emacs setup git repo @ Sourcehut
Then I can install and configure nextcloud and start downloading all my stuff. It takes a while, but I have my window manager, shell and editor set up right, and I feel happy.
Less than one hour from having nothing to a completely usable computer that sparks joy. This is not bad.
Frustratingly some things don't work so well when you stray from the default GNOME desktop, things like adjusting the backlight with the buttons on the keyboard. This is something that Just Work™ on OpenBSD, regardless of desktop environment or window manager.
This is handled through ACPI.
Start acpi_listen(8) in a terminal, and hit the brightness up/down keys. This will produce output like this:
video/brightnessdown BRTDN 00000087 00000000 video/brightnessup BRTUP 00000086 00000000
Pretty simple. This is an event that can be handled by writing a little file in /etc/acpi/events. Let's do the brightness up key as an example:
Create /etc/acpi/events/backlight-up containing this:
event=video/brightnessup BRTUP 00000086 00000000 action=/etc/acpi/backlight-up.sh
The event in the first line, the action in the second line. Simple.
Then create the /etc/acpi/backlight-up.sh script:
#!/bin/sh device="/sys/class/backlight/intel_backlight/brightness" echo "$(($(cat $device)+50))" > $device
This script is run as root, so you are free to do whatever you want, nothing will stop you. This is good, because only root can write to /sys/class/backlight/intel_backlight/brightness, which contain just a number. This number go from 0 to some arbitrary upper limit that is set in
/sys/class/backlight/intel_backlight/max_brightness, 852 on my laptop. So you want to increment that in suitable steps for the range. I chose to increment by 50.
Pulseaudio is commanded through pactl(1) or, if you need to go a bit deeper, pacmd(1). So Volume for sink 0 can be incremented 5% like this, and then toggle mute:
pactl set-sink-volume 0 +5% pactl set-sink-mute 0 toggle
You can use xev(1) to see the keycodes the media keys send.
The problem is to somehow intercept the keys and send the event to a script. This can be done in dwm quite easily. Look at config.def.h, first some sommands you want to run is defined, here it's termcmd to launch the st terminal, and a bit later it's set to be launched with Modkey+Shift+Return.
static const char *termcmd[] = { "st", NULL }; ... { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
Let's do the mute key as an example:
static const char *dwm_audio_mute[] = { "dwm-keys.sh", "XF86AudioMute", NULL }; ... { 0, XF86XK_AudioMute, spawn, {.v = dwm_audio_mute } },
So every time I hit the mute key it will run the command "dwm-keys.sh XF86AudioMute". This way I have a simple shell script somewhere in my path that just have to handle the different arguments I send it. A bit easier than to do it in C and recompile dwm every time. So, to toggle mute:
On Ubuntu the keysymbols, like XF86XK_AudioMute, are defined in /usr/include/X11/XF86keysym.h, part of the x11proto-dev package. These names are not the same you see with xev(1), although they're close, just to make everything more annoying, exciting and non-grep-able.
#!/bin/sh getPulseAudioSinks() { pacmd list-sinks | grep -F 'index: ' | cut -d: -f2 } volToggleMute() { for sink in $(getPulseAudioSinks); do pactl set-sink-mute $sink toggle done } case "$1" in XF86AudioMute) volToggleMute ;; esac
First I find the numbers of the PulseAudio sinks with the getPulseAudioSinks() function (I call it in the volume up/down functions too), and then toggle mute for each sink in volToggleMute(). I could have done it in-line in the case statement, but I find it much easier to read and edit code like this.
It should be pretty easy to solve the problem for any magical keys you have on your keyboard in a similar manner.
I run xidle(1) on login, a simple little program that execute a program of my choice after a certain idle time have elapsed, or it get a SIGUSR1 signal. I use a 10 minute idle-time, and have it execute a screensaver.sh script, a thin wrapper around slock(1), the suckless screensaver.
So the challenge is to send xidle a SIGUSR1 on suspend.
In /usr/lib/systemd/system-sleep there's a few scripts that get run when you suspend the laptop. Create an xidle script:
#!/bin/sh pkill -USR1 xidle # Make xidle launch screensaver.
That was pretty easy.
There's a proper package repository so you can avoid snapd, but the official instructions are wrong for the GnuPG key, they use a deprecated method to install it. Here's the right way:
$ sudo curl -o /etc/apt/trusted.gpg.d/spotify.asc \ https://download.spotify.com/debian/pubkey_5E3C45D7B312C643.gpg $ echo "deb http://repository.spotify.com stable non-free" \ | sudo tee /etc/apt/sources.list.d/spotify.list $ sudo apt update $ sudo apt install spotify-client
Look at the full code in my Sourcehut repos. The dwm-keys.sh script is in my dotfiles, the dwm code to send the keys to it is in the Linux/dwm.diff patch in the Suckless desktop Environment repo.
I'm kind of glad I fixed the screen brightness thing first via acpid(8), because that works the same whether I am in the console og X.org. It is really rare I use the console, but it's nice to be able to adjust brightness there too. Then later I thought about the generic way to handle keyboard shortcuts in dwm(1), and got some help with the PulseAudio commands from Tomáš on Mastodon.