I started using Manjaro Linux (the community-maintained i3-based version) last week after decades of using Windows and macOS. One thing I found especially tricky to do was to set up my desktop environment to support two configurations:
- Laptop: when I’m using my laptop as a portable computer: the only display I have is the built-in HiDPI (QHD) one.
- Desktop: when I’m sitting at my desk with my main, Low-DPI QHD monitor in front of me and the laptop to its left.
The Laptop configuration
After I installed Manjaro i3, I needed to configure the built-in display to use
200% scaling because at 100%, everything was unreadably small. To achieve this,
I needed to change the Xft.dpi
setting in my ~/.Xresources
:
!! Before:
Xft.dpi: 96
!! After:
Xft.dpi: 192
DPI means Dots Per Inch. It is recommended to specify an integer multiple of 96, the default DPI value; in this case, 2*96 = 192. This way one logical pixel always corresponds to a square block of physical pixels so the image will be sharp.
You can test these changes by issuing the following command:
xrdb -merge ~/.Xresources
You must also make sure this comand is invoked when X starts - this is usually
achieved by adding it to ~/.xinitrc
or ~/.xprofile
(the latter if you use a
“desktop manager”, which is terrible Linux jargon for a GUI login screen). In my
case, I didn’t need to add anything to these files because the default scripts
already merged .Xresources
.
The Desktop configuration
If you have multiple displays, you can configure their position, resolution,
scaing, etc. using the xrandr
command (“randr” means Resize and Rotate, the
name of an X extension).
First we need to find out the names of the displays currently connected by
running xrandr
without parameters:
$ xrandr
Screen 0: minimum 8 x 8, current 7680 x 2880, maximum 32767 x 32767
eDP1 connected 2560x1440+0+0 (normal left inverted right x axis y axis) 310mm x 170mm
2560x1440 60.00*+ 48.00
1920x1440 60.00
1856x1392 60.01
1792x1344 60.01
2048x1152 60.00 59.90 59.91
1920x1200 59.88 59.95
1920x1080 59.96 60.00 59.93
1600x1200 60.00
1680x1050 59.95 59.88
1400x1050 59.98
1600x900 60.00 59.95 59.82
1280x1024 60.02
1400x900 59.96 59.88
1280x960 60.00
1368x768 60.00 59.88 59.85
1280x800 59.81 59.91
1280x720 59.86 60.00 59.74
1024x768 60.00
1024x576 60.00 59.90 59.82
960x540 60.00 59.63 59.82
800x600 60.32 56.25
864x486 60.00 59.92 59.57
640x480 59.94
720x405 59.51 60.00 58.99
640x360 59.84 59.32 60.00
DP1 disconnected (normal left inverted right x axis y axis)
DP2 disconnected (normal left inverted right x axis y axis)
HDMI1 connected primary 5120x2880+2560+0 (normal left inverted right x axis y axis) 600mm x 340mm
2560x1440 59.95*+ 74.97
1920x1080 60.00 50.00 59.94
1920x1080i 60.00 50.00 59.94
1280x1440 59.91
1680x1050 59.88
1280x1024 75.02 60.02
1440x900 59.90
1280x960 60.00
1280x720 60.00 50.00 59.94
1024x768 75.03 70.07 60.00
832x624 74.55
800x600 72.19 75.00 60.32 56.25
720x576 50.00
720x480 60.00 59.94
640x480 75.00 72.81 66.67 60.00 59.94
720x400 70.08
HDMI2 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
The list contains all possible outputs, whether they are connected or disconnected and all resolutions the connected displays support.
For my configuration, I first specified that my external display is to the right of my internal one and just to make sure everything is correct, I explicitly set the resolution and rotation:
xrandr \
--output eDP1 \
--mode 2560x1440 \
--pos 0x0 \
--rotate normal \
--output HDMI1 \
--primary \
--mode 2560x1440 \
--pos 2560x0 \
--rotate normal \
After running this command, my desktop was extended to the external display but
it was shown at 200% scaling (as configured earlier with the .Xresources
DPI
setting). What I needed to do was to tell xrandr
to resize the picture of this
output to be twice as large as the default. This results in X squeezing the
oversized picture inside the 2560x1440 resolution, which effectively result in
it being scaled at 100%.
xrandr \
--output eDP1 \
--mode 2560x1440 \
--pos 0x0 \
--rotate normal \
--output HDMI1 \
--primary \
--mode 2560x1440 \
--pos 2560x0 \
--rotate normal \
--scale 2x2
All I needed was to add --scale
to the HDMI output and this immediately worked
and solved all of my problems.
Defining i3 shortcuts to switch between configurations
The command above works perfectly but it is quite tedious to run every time
(even as a shell script) I sit down at my desk. So I configured the Mod+Alt+s
shortcut in i3 to offer a menu to switch screen layouts. This is what I added to
my ~/.i3/config
:
# Switch between screen layouts
bindsym $mod+Mod1+s mode "$mode_screenlayout"
set $mode_screenlayout Screen layout: (l)aptop, (d)esktop
mode "$mode_screenlayout" {
bindsym l exec --no-startup-id /home/myusername/scripts/xrandr-laptop.sh, mode "default"
bindsym d exec --no-startup-id /home/myusername/scripts/xrandr-desktop.sh, mode "default"
# exit screen layout mode: "Enter" or "Escape"
bindsym Return mode "default"
bindsym Escape mode "default"
}
This way, I can press Mod+Alt+s, the options are shown on the i3 status bar, and
I can select one by pressing either “l” or “d”. Of course you need to change
“myusername” to your user name and create the scripts/xrandr-*.sh
shell
scripts:
xrandr-laptop.sh:
#!/usr/bin/env bash
xrandr \
--output eDP1 \
--mode 2560x1440 \
--pos 0x0 \
--rotate normal \
--output HDMI1 \
--off
xrandr-desktop.sh:
#!/usr/bin/env bash
xrandr \
--output eDP1 \
--mode 2560x1440 \
--pos 0x0 \
--rotate normal \
--output HDMI1 \
--primary \
--mode 2560x1440 \
--pos 2560x0 \
--rotate normal \
--scale 2x2
I hope you’ve found this guide useful. If so, please consider sharing it with people who might like it too.