September 17, 2023

Splitting a single monitor into 2 virtual horizontal monitors in Linux

About 6 months ago I changed my job and nowadays I work mostly remotely. I have wanted to optimize home office but also keep it as simple as possible. In addition, I use the same equipments with the work computer and my own computer. Both computers are connected to power supply and either has USB-C cable connected to the docking station. When I’m at the desk, I don’t want to use either computer’s built-in monitor.

My employer provided me ThinkVision T34w-20 monitor with aspect ratio of 21:9 (3440x1440). In past, I’ve not been too keen on wide monitors, because I’ve feared it’d be inconvenient with a tiling window manager (i3). Curiosity won and I replaced my 2 x 27" ThinkVision monitors with the single 34" one. Soon I noticed tiling window manager is ok also on 21:9 monitor.

Unfortunately, I missed one thing from my dual monitor setup: A second monitor.

I’m often in video meetings. When I’m demonstrating something, I show multiple applications and hence screen sharing of the whole screen is the most practical approach. I like to have a second screen for my private stuff like meeting notes, private discussions, etc. Single monitor allowed me to either share a single application or everything.

The solution was the following script which splits one physical monitor into two virtual monitors. I have a shortcut in i3 to quickly activate either 1 or 2 monitor setup.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/env bash
# Split monitor vertically into 2 equal size virtual monitors.

set -euo pipefail

action=${1-}

current_resolution=$(xdpyinfo | grep dimension | awk '{print $2}')
IFS="x" read -r res_x res_y <<< "$current_resolution"
res_x=$((res_x / 2))

phys_size=$(xdpyinfo | grep dimension | awk '{print $4}' | tr -d '(')
IFS="x" read -r size_x size_y <<< "$phys_size"
size_x=$((size_x / 2))

vmon_1="my-monitor-1"
vmon_2="my-monitor-2"

case "$action" in
on)
    if xrandr --listmonitors | grep -q "$vmon_1"; then
        notify-send "Monitor is already split"
        exit 1
    fi
    vmon_1_config="${res_x}/${size_x}x${res_y}/${size_y}+0+0"
    vmon_2_config="${res_x}/${size_x}x${res_y}/${size_y}+${res_x}+0"
    xrandr --setmonitor "$vmon_1" "$vmon_1_config" none
    xrandr --setmonitor "$vmon_2" "$vmon_2_config" none
    notify-send "Virtual monitors were created" "${vmon_1_config}\n${vmon_2_config}"
    ;;
off)
    xrandr --delmonitor "$vmon_1"
    xrandr --delmonitor "$vmon_2"
    notify-send "Virtual monitors were deleted"
    ;;
*)
    echo "Usage: $0 on|off"
    exit 1
    ;;
esac

When monitor is split, both virtual monitors are like real individual monitors. For me it has the following benefits:

  • In a video meeting I can share whole virtual monitor and have my personal work on the second one
  • I can open any application in fullscreen mode on either virtual monitor
  • It brings i3’s fantastic multi-monitor support into use with a single monitor
  • Virtual monitors are completely independent and workspace changes affect only either virtual monitor