Migrate from i3 to sway
I recently changed from the Linux display server protocol X.org Server to Wayland on one of my machines. My favorite window manager i3 is not compatible with Wayland though, so I had to search for an alternative. Luckily there is a drop-in replacement for i3 available which is named Sway.
Sway is very similar to i3, it even uses the same syntax for the config, so the change required only a few tweaks which I will now talk about. I can also recommend to read the Sway article on the Arch Wiki.
At this let's take a brief moment to say "Thank you" to all contributors of Sway and Wayland and maintainers of the corresponding packages in the various distros out there. ♥
# Installation
Installation of sway under Arch Linux is easy. It's as simple as:
yay -S sway
# Copy configuration
Sway searches it's configuration in ~/.config/sway/config
so I copied my i3 config there.
All changes go into this config file.
# Adjust configuration
After the configuration has been copied use a separate TTY to try our sway and its configuration.
Remember that <SUPER> + SHIFT + c
does reload your configuration which is quite handy for trying things out.
Also swaymsg
can be used to send messages to sway, so for example the following command would set the scaling 2 for all output devices.
swaymsg output "*" scale 2
# Screen output resolution
I'm working with a HiDPI screen which was detected correctly in Sway. But I found the scaling factor of 2, which is the default in HiDPI screens, too much. Although it's not recommended to use float values here, I found a scaling factor of 1.3 to fit my needs, so I added this line to my config:
# Screen scaling (default is 2)
output eDP-1 scale 1.3
To list connected displays use swaymsg -t get_outputs
which in my case now (after the change) shows as:
$ swaymsg -t get_outputs
Output eDP-1 'Apple Computer Inc Color LCD 0x00000000' (focused)
Current mode: 2560x1600 @ 59.972000 Hz
Position: 0,0
Scale factor: 1.300000
Scale filter: linear
Subpixel hinting: unknown
Transform: normal
Workspace: 4
Max render time: off
Adaptive sync: disabled
Available modes:
2560x1600 @ 59.972000 Hz
# Background images with automatic rotation
I like to have randomly chosen background images that change every now and then. Sway makes it easy to implement this. I added the following line to my config which executes a script during start.
exec --no-startup-id ~/.local/scripts/sway-rotate-bg-image.sh
The script itself doesn't do much.
It lists all files in a certain folder, shuffles the names and selects one of them.
It updates the background on all attached displays image via swaymsg
and then pauses for 300 seconds (=5min) before the next iteration.
#!/usr/bin/env bash
IMG_DIR=~/wallpapers
while true;
do
IMG=`ls -t1 $IMG_DIR/* | shuf | head -n 1`
swaymsg output "*" bg $IMG fill; sleep 300
done
# Detect idle state and lock screen
To automatically lock the screen there are luckily two programs available that do the heavy-lifting. They are called swayidle and swaylock and can be installed in Arch via:
yay -S swayidle swaylock
The following script is taken from the swayidle
manpage:
This will lock your screen after 300 seconds of inactivity, then turn off your displays after another 300 seconds, and turn your screens back on when resumed. It will also lock your screen before your computer goes to sleep.
To make sure swayidle waits for swaylock to lock the screen before it releases the inhibition lock, the -w options is used in swayidle, and -f in swaylock.
exec --no-startup-id swayidle -w \
timeout 300 'swaylock -f -c 000000' \
timeout 600 'swaymsg "output * dpms off"' \
resume 'swaymsg "output * dpms on"' \
before-sleep 'swaylock -f -c 000000'
# Screen backlight keys
In my i3 setup I used xbacklight
to change the backlight of my screen.
bindsym XF86MonBrightnessUp exec xbacklight +10
bindsym XF86MonBrightnessDown exec xbacklight -10
This of course won't work anymore in Wayland, so I replaced the old configuration with brightnessctl
which needs to be installed first:
yay -S brightnessctl
The syntax of brightnessctrl
differs slightly:
bindsym XF86MonBrightnessDown exec brightnessctl set 5%-
bindsym XF86MonBrightnessUp exec brightnessctl set +5%
# Keyboard bindings
For me one key on the keyboard is completely superfluous: capslock. In my systems I either deactivate this key or map it to ESC if possible. Having ESC closer to the home row is benefitial to me - especially when working a lot with vim. This can done with xkb_options.
Another interesting setting is the key repeat delay and rate, which can be tuned also quite easily.
input "type:keyboard" {
# Capslock key should work as escape key
xkb_options caps:escape
repeat_delay 350
repeat_rate 45
}
# SSH Agent
To automatically start the SSH agent I use a systemd service which is placed in ~/.config/systemd/user/ssh-agent.service
:
[Unit]
Description=SSH key agent
[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
# DISPLAY required for ssh-askpass to work
Environment=DISPLAY=:0
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK
[Install]
WantedBy=default.target
Also configure the pam environment in ~/.pam_environment
:
SSH_AUTH_SOCK DEFAULT="${XDG_RUNTIME_DIR}/ssh-agent.socket"
Then start the service and enable it for future system starts: systemctl --user enable --now ssh-agent.service
.
# Exit script
Finally I updated my exit script that allows me to lock my screen, suspend, shutdown or reboot my machine, etc.
The Sway configuration looks as this
set $mode_system System (1) lock, (e) logout, (s) suspend, (h) hibernate, (r) reboot, (d) shutdown
mode "$mode_system" {
bindsym l exec --no-startup-id ~/.local/scripts/sway-exit.sh lock, mode "default"
bindsym e exec --no-startup-id ~/.local/scripts/sway-exit.sh logout, mode "default"
bindsym s exec --no-startup-id ~/.local/scripts/sway-exit.sh suspend, mode "default"
bindsym h exec --no-startup-id ~/.local/scripts/sway-exit.sh hibernate, mode "default"
bindsym r exec --no-startup-id ~/.local/scripts/sway-exit.sh reboot, mode "default"
bindsym d exec --no-startup-id ~/.local/scripts/sway-exit.sh shutdown, mode "default"
# back to normal: Enter or Escape
bindsym Return mode "default"
bindsym Escape mode "default"
}
which utilizes the script located in ~/.local/scripts/sway-exit.sh
#!/bin/sh
lock() {
swaylock -f -c 000000
}
case "$1" in
lock)
lock
;;
logout)
swaymsg exit
;;
suspend)
lock && systemctl suspend
;;
hibernate)
lock && systemctl hibernate
;;
reboot)
systemctl reboot
;;
shutdown)
systemctl poweroff
;;
*)
echo "Usage: $0 {lock|logout|suspend|hibernate|reboot|shutdown}"
exit 2
esac
exit 0
# Notifications
In i3 I used dunst to handle notifications.
Unfortunately it's not yet ready to work with wayland.
I found mako to be a good replacement.
Using mako
is dead simple.
After installation an additional line exec mako
in the sway config file does the job.
# Printer
CUPS was not properly started after the switch.
What helped was to create the following configuration in /etc/systemd/system/cups.socket
:
[Unit]
Description=CUPS Printing Service Sockets
[Socket]
ListenStream=/var/run/cups/cups.sock
ListenStream=0.0.0.0:631
ListenDatagram=0.0.0.0:631
BindIPv6Only=ipv6-only
[Install]
WantedBy=multi-user.target
Then enable/start the service with systemctl enable --now cups.service
and make sure it started properly:
$ systemctl status cups.service
● cups.service - CUPS Scheduler
Loaded: loaded (/usr/lib/systemd/system/cups.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2020-11-28 21:21:45 CET; 4min 31s ago
TriggeredBy: ● cups.socket
● cups.path
Docs: man:cupsd(8)
Main PID: 55543 (cupsd)
Status: "Scheduler is running..."
Tasks: 1 (limit: 19070)
Memory: 5.2M
CGroup: /system.slice/cups.service
└─55543 /usr/bin/cupsd -l
Nov 28 21:21:45 mali systemd[1]: Starting CUPS Scheduler...
Nov 28 21:21:45 mali systemd[1]: Started CUPS Scheduler.