Migrating from i3wm to Sway
i3 will never support Wayland due to a difference between Xorg and Wayland architecture. Sway is a i3 compatible Wayland server implementation.
Long story short - Wayland is a just protocol, which must be implementend in a compositor/window manager, where Xorg is a X11 display server which can run different window managers top of it.
There is no single common Wayland server like Xorg
Motivation
X11 is being quite old and unsafe protocol, and Xorg is the implementation based on multiple extensions and hacks. Almost nobody wants to support it, and all major desktop environments are slowly switching to Wayland .
I am using i3 top of XFCE , sometimes on Gnome on Xorg , because I like to have some features of modern desktop environments, but I don’t like their window managers. This is not doable with Wayland-based window manager, because there is no commong display server. It may be possible when XFCE will add full support for Wayland (starting from XFCE 4.20), but for now I can’t check this.
For now ,I will try switching to my custom desktop environment based on Sway as a Wayland-based window manager.
Migration
Wayland support is currently pretty limited for Nvidia GPUs
- Copy
~/.config/i3/config
to~/.config/sway/config
- Run
sway
, read errors, and remove/comment unsupported config commands (liketiling_drag
) - Rename
restart
command toreload
, if you’re using bindsym for restarting i3 - Install Wayland-compatible login manager (like GDM ), enable it and run Sway session.
Multiple monitors
- List names of supported monitors:
swaymsg -t get_outputs
- Configure them in the config file, like this:
output DP-1 scale 1
output DP-2 scale 1
For handling windows movement and screen switching you must tune your config a little bit. There is a little incompatibility in output direction names:
bindsym $mod+Shift+o move container to output right, focus output right
bindsym $mod+Shift+p move workspace to output right
bindsym $mod+o focus output right
Keyboard layout
Add input section to the config file, like this:
input * {
xkb_layout "pl",
xkb_variant "pl"
}
Authentication in apps
- Install
polkit-gnome
- Add to the Sway config file:
exec --no-startup-id /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
- Restart Sway.
SSH Agent
- Install Gnome/Keyring
- Enable GCR SSH Agent
systemctl --user enable gcr-ssh-agent.socket
systemctl --user start gcr-ssh-agent.socket
More info: https://wiki.archlinux.org/title/GNOME/Keyring
ROFI

Recommended method
- Install
rofi-wayland
, a fork of Rofi that works in Wayland - In i3
config add
-x11
option to therofi
call - this will preserve a compatibility for i3/Xorg
Alternative method - ROFI through Xwayland
- Install Xwayland
- Wrap
rofi
in a script, then tune up your config to use it
#!/bin/bash
monitor="$(swaymsg --raw -t get_outputs | jq '.[] | select(.focused) | .name' -r)"
rofi -monitor "$monitor" $@
This wrapper will open x11-based rofi
on a focused monitor.
It is recommended to use rofi-wayland fork, though
Autostart
Add/uncomment the line in the config file:
exec --no-startup-id dex --autostart --environment sway
Note that there is no “sway” desktop environment - you’re creating the one. The value provided for
--environment
will be used to filter out.desktop
entries (OnlyShowIn/NotShowIn). See: Desktop Entries
Review your autostart entries in
~/.config/autostart
and addOnlyShowIn
orNotShowIn
if needed.
More info: https://wiki.archlinux.org/title/XDG_Autostart
Quake terminal (Guake)

- Install Xwayland and Guake
- Add these lines to your config file:
for_window [instance="guake"] floating enable, move position 0 0
bindsym Control+Grave exec "guake-toggle"
Making screenshots
- Install
slurp
,grim
,wl-clipboard
andlibnotify
- Create an executable bash script
sway-screenshot
somewhere on your PATH
#!/bin/bash
winname=$(swaymsg --raw -t get_tree | jq -r '.. | (.nodes? // empty)[] | select(.focused) | .name')
output=$(xdg-user-dir PICTURES)/$(date +'screenshot_%Y%m%d_%H%M%S.png')
case $1 in
"window-clipboard")
grim -g \
"$(swaymsg --raw -t get_tree | jq -r '.. | (.nodes? // empty)[] | select(.focused) | .rect | "\(.x),\(.y) \(.width)x\(.height)"')" \
- | wl-copy \
&& notify-send -t 3000 "Screenshot taken" "Screenshot of the $winname window copied to the clipboard"
;;
"window")
grim -g \
"$(swaymsg --raw -t get_tree | jq -r '.. | (.nodes? // empty)[] | select(.focused) | .rect | "\(.x),\(.y) \(.width)x\(.height)"')" \
-o "$output" \
&& notify-send -t 3000 "Screenshot taken" "Screenshot of the $winname window saved to $output"
;;
"area-clipboard")
(slurp | grim -g - - | wl-copy) \
&& notify-send -t 3000 "Screenshot taken" "Screenshot of the area copied to the clipboard"
;;
"area")
(slurp | grim -g - -o "$output") \
&& notify-send -t 3000 "Screenshot taken" "Screenshot of the area saved to $output"
;;
"screen"|*)
grim -o \
$(swaymsg --raw -t get_outputs | jq -r '.[] | select(.focused) | .name') \
"$output" \
&& notify-send -t 3000 "Screenshot taken" "Screenshot of the current screen saved to $output"
esac
- Configure shortcuts in the config file.
bindsym Print exec "/bin/sway-screenshot area-clipboard"
bindsym Control+Print exec "~/bin/sway-screenshot window-clipboard"
bindsym Shift+Print exec "~/bin/sway-screenshot"
bindsym Shift+Control+Print exec "~/bin/sway-screenshot window"
Volume control
I highly recommend to switch from PulseAudio to PipeWire , and use WirePlumber to control the volume
bindsym XF86AudioRaiseVolume exec --no-startup-id wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 10%+ && $refresh_i3status
bindsym XF86AudioLowerVolume exec --no-startup-id wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 10%- && $refresh_i3status
bindsym XF86AudioMute exec --no-startup-id wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle && $refresh_i3status
bindsym XF86AudioMicMute exec --no-startup-id wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle && $refresh_i3status
Backgrounds
Instead of using feh
you can setup backgrounds directly for each
output:
output DP-1 scale 1 bg ~/.config/i3/wallpaper1 fill
output DP-2 scale 1 bg ~/.config/i3/wallpaper2 fill
Tray / D-BUS Menu
Swaybar has limited support for tray icons. D-Bus menu patches, like RMB menu of nm-applet, aren’t merged for years due to some stability issues. For example, networkManager’s icon will be shown, but you will not be able to interact with it.
Network Manager applet
Because tray icon support is limited, an alternative approach is needed to manage network connections.
For CLI you can use nmcli
and wrap it with Sway shortcuts. Also, there is
ncurses-based GUI tool nmtui
(together with nmtui-connect
and nmtui-edit
commands).

For example as a workaround, you can open nmtui-connect
in a floating
window by hitting a keyboard shortcut (using foot
terminal here):
# NetworkManager config
for_window [title="nmtui-connect"] floating enable
bindsym $mod+F4 exec foot -T nmtui-connect -f monospace:size=12 -e nmtui-connect
Final notes
Sway with Xwayland should provide an almost comfortable and safe working environment. Not all apps could be compatible with Xwayland, so in case of troubles leave your original i3 config for handling such exceptions by switching to clean Xorg .
Sway cannot be used as a window manager for XFCE or Gnome , so some apps, tool or services may not work. Sway is not a direct replacement for i3 top of desktop environment.
I will update this post if I make any significant changes to my setup.
More info: https://wiki.archlinux.org/title/Sway
