I finally made the switch from X11/i3 to Wayland/Sway, and things are, for the most part, better on Wayland. I’ve managed to replicate almost everything from my setup, albeit with different tools, but there are exceptions and I thought I’d write about one that I have not managed to replicate on Sway.

The efficiency that a tiling window manager like i3 brings has enabled me to move away from multi-monitor setups. However, there’s one scenario where I find having two separate displays more useful: giving presentations online. It’s quite handy to share one monitor with a single workspace whilst navigating other workspaces on the other display.

This alone isn’t enough for me to switch to two monitors. Instead, I use(d) a nifty feature of xrandr that lets you split a monitor into multiple virtual ones. These virtual displays are, for all intents and purposes, treated as independent monitors by the rest of the system. This is particularly useful on my beloved LG DualUp monitor, which has a rather uncommon 16:18 aspect ratio (i.e. two typical 16:9 monitors stacked on top of each other).

How to create (and destroy) virtual monitors

I use the script below to split my vertical 2560x2880 monitor into two stacked 2560x1440 virtual ones:

  • DP-virtUp: Upper half (positioned at +0+0, at the top)
  • DP-virtDown: Lower half (positioned 1440 pixels down)
#!/usr/bin/env bash

if [[ ! $(xrandr --listmonitors) =~ virt ]]
then
    DISPLAY_NAME=$(xrandr --listmonitors | grep -E "2560/465x2880/523" | awk '{print $4}')
    xrandr --setmonitor DP-virtDown 2560/470x1440/260+0+1440 "$DISPLAY_NAME"
    xrandr --setmonitor DP-virtUp 2560/470x1440/260+0+0 none
else
    xrandr --delmonitor DP-virtUp
    xrandr --delmonitor DP-virtDown
fi

The syntax of xrandr --setmonitor is a bit difficult to read at first but it’s not complicated:

{width_px}/{width_mm} x {height_px}/{height_mm} + {x_offset}+{y_offset}

i3 integration

This setup can be made a bit more seamless by leveraging i3’s ability to automatically assign workspaces to specific screens. The syntax is:

workspace <workspace> output <output1> [output2]

You can specify multiple outputs, and the first available one will be used.

I have the following in my config:

workspace 1 output DP-virtDown primary nonprimary
workspace 2 output DP-virtDown primary nonprimary
workspace 3 output DP-virtDown primary nonprimary
workspace 4 output DP-virtDown primary nonprimary
workspace 5 output DP-virtDown primary nonprimary
workspace 6 output DP-virtDown primary nonprimary
workspace 7 output DP-virtDown primary nonprimary
workspace 8 output DP-virtDown primary nonprimary
workspace 9 output DP-virtUp nonprimary primary

As soon as I create virtual monitors, all my workspaces except workspace 9 (which is usually empty) go to one display, and workspace 9 goes to the other. This allows me to use one virtual monitor as the main one and the other for a special purpose — usually sharing over Zoom, Google Meet, or similar.

What about Wayland?

There are efforts in Sway and possibly wlroots to add this functionality, and I hope it arrives soon. Hyprland appears to support “fake outputs”, but I’ve never used Hyprland and don’t know if they can achieve the same thing.