new post: moving to wayland river #10

Merged
fr merged 5 commits from dev into master 2025-11-09 23:57:12 +01:00
Showing only changes of commit 872b30cf2a - Show all commits

139
content/posts/wayland.md Normal file
View File

@@ -0,0 +1,139 @@
+++
title = "Friendship ended with dwm, now River is my best friend"
date = 2025-10-21
description = "Moving from X11 with dwm to River on Wayland"
+++
After years with dwm on X11, I started hitting the limits of Xorg — especially screen tearing, smoothness, and missing Wayland-only features. I decided it was time to switch.
## Weapon of choice - river
I wanted an experience as close as possible to my existing X11/dwm/dwmblocks setup. Before i jumped into `river`, I looked at `dwl`, `sway`, and `Qtile`.
`dwl` sounded like the best choice for me since it aims to replicate dwm on Wayland. But development is slow, many protocols are still missing, and adding them takes time.
Sway wasn't bad, but it's closer to i3 than dwm, so not ideal for me.
Qtile looked good, but I didn't like configuring it in Python.
Then my friend [Emil](https://em.0x45.cz/) told me about his `river` setup. He was happy with it, so I gave it a shot.
What I really like about river is that i can configure it on the fly. The whole configuration is a single Bash script that sends commands to river live - no recompiling or restarting required.
As a layout manager I chose [Filtile](https://github.com/pkulak/filtile) as it's very similar to dwm behavior.
## Bar dwmblocks => waybar
As an alternative to `dwmblock`, I found Waybar to be the best fit for me.
It has plenty of modules for displaying almost anything on my bar, including my IP address, speaker/headphones state and battery status.
Besides using built-in modules, it's also possible to create custom ones using scripts. I've made my own module for displaying speaker/headphones volume with possibility to mute or change the default audio output on mouse click.
- `~/.config/waybar/config.jsonc`
```jsonc
...
"custom/audio": {
"exec": "~/.local/bin/waybar_audio.sh",
"return-type": "json",
"format": "{icon} {text}",
"format-icons": {
"speaker": ["", "", " "],
"speaker-muted": "󰖁",
"headphones": "󰋋",
"headphones-muted": "󰟎"
},
"interval": 2,
"on-click": "pamixer --toggle-mute",
"on-click-right": "~/.local/bin/toggle_audio",
"on-scroll-up": "pamixer --increase 5",
"on-scroll-down": "pamixer --decrease 5"
},
...
```
Where `waybar_audio.sh` and `toggle_audio` are my custom Bash scripts both available in my [dotfiles repository](https://git.filiprojek.cz/fr/dotfiles/src/branch/master/.local/bin)
## Application starter dmenu => Wmenu
I found Wmenu to be the most similar app laucher to dmenu and I don't like changes, so i picked it.
I was able to customize it to my liking - vertical list of apps.
The only thing that didn't work and I missed that feature so much was fuzzy search. Wmenu doesn't support it and there was no patch available. So I've decided to create my own version of wmenu with fuzzy search support with help of chatgpt codex :D. As much as I hate AI, Codex was actually able to modify that C code in just single prompt. My modified version of wmenu is available in [this github repository](https://github.com/filiprojek/wmenu).
## passmenu integration to wmenu
For my password manager GUI I like to use passmenu - an dmenu script that helps me pick my password anywhere I am. But there was a problem. Passmenu was written only for dmenu. That's where chatgpt helped me again and together we created [this rewrite of passmenu](https://github.com/filiprojek/passmenu-wmenu) for wmenu.
Passmenu is an excellent example of where I use the fuzzy search feature the most.
## Terminal alacritty => foot
Since Alacritty sucks at displaying images inside the terminal, I moved to foot as an alternative. It supports displaying images natively.
There was an issue with spawning new terminal inside the current working directory. I was used to Alacritty's <CTRL+Shift+Enter> shortcut. I fixed that with the following addition to my `.bashrc`:
```bash
osc7_cwd() {
local strlen=${#PWD}
local encoded=""
local pos c o
for (( pos=0; pos<strlen; pos++ )); do
c=${PWD:$pos:1}
case "$c" in
[-/:_.!\'\(\)~[:alnum:]] ) o="${c}" ;;
* ) printf -v o '%%%02X' "'${c}" ;;
esac
encoded+="${o}"
done
printf '\e]7;file://%s%s\e\\' "${HOSTNAME}" "${encoded}"
}
PROMPT_COMMAND=${PROMPT_COMMAND:+${PROMPT_COMMAND%;}; }osc7_cwd
```
And this keybind in `foot.ini`:
```ini
[key-bindings]
spawn-terminal=Control+Shift+Return
```
## Screenshare
Once I had my setup ready, one of the first issues after using it for some time was screen sharing. I dug into the issue and found a solution.
I had to add this to my River init file:
```bash
# Fix screen share
export XDG_CURRENT_DESKTOP=river
export XDG_SESSION_TYPE=wayland
## Start portals
dbus-update-activation-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
xdg-desktop-portal-wlr &
xdg-desktop-portal &
```
## Screenshots
On my X.org setup I was using screenshots with `shotgun` and `slop` based on my friend's tutorial: [Taking screenshots with shotgun and slop](https://em.0x45.cz/posts/taking-screenshots-with-shotgun-and-slop/)
Fortunately he already wrote a guide for wayland alternative: [Taking screenshots on Wayland with Grim and Slurp](https://em.0x45.cz/posts/taking-screenshots-on-wayland-with-grim-and-slurp/)
But I had issues with the combination of `grim` and `slurp`. While pasting an image from clipboard to telegram, it pasted raw PNG data instead of a file. This was the fix:
```bash
riverctl map normal None Print spawn 'file="/home/$USER/Pictures/Screenshots/$(date +%F_%T).png"; grim -g "$(slurp -d)" "$file" && wl-copy --type text/uri-list "file://$file"'
```
## Other alternatives
This is a list of other software that I used on X.org and their alternatives on Wayland:
- `xclip` => `wl-copy`
- `ranger` => `yazi`
- `slock` => `waylock`
## Final thoughts
After a few weeks with River, I dont miss Xorg much. The setup feels lighter, screenshots and screen sharing work fine now, and I can still keep my DWM-like workflow.
There's just one thing I didn't get working and that is the indication of how many windows are open in monocle layout. Dwm used `[X]` where `X` was the number of open windows on that tag.
River feels more responsive overall, and I havent run into any crashes so far.
![My current river setup](/public/river_foot_waybar_setup.png)
## References
- [River - dynamic tiling Wayland compositor](https://codeberg.org/river/river-classic)
- [Filtile](https://github.com/pkulak/filtile)
- [Waybar](https://github.com/Alexays/Waybar)
- [Wmenu](https://codeberg.org/adnano/wmenu)
- [My fork of Wmenu with Fuzzy search support](https://github.com/filiprojek/wmenu)
- [Passmenu for wmenu](https://github.com/filiprojek/passmenu-wmenu)
- [Foot - Wayland terminal emulator](https://codeberg.org/dnkl/foot)