Skip to content

Instantly share code, notes, and snippets.

Last active Aug 17, 2021
What would you like to do?


  • You have a laptop with a 13" screen and 1920x1080 resolution and a 4K external monitor.
  • You run the laptop at 1x scale.
  • You run the 4K screen at 2x scale (pixel doubled).
  • You’re running elementary OS 5.x (Hera) or elementary OS 6 (Odin)

Which means that text scale should be 1x when the 4K monitor is plugged in but it should be larger than that (at least ~1.5x) to be legible on the laptop’s screen. (Yes, the manufacturer of the laptop chose the wrong resolution for the screen. It should have been QHD (2560 × 1440) or at most QHD+ (3200×1800) so that you could run it confortably pixel doubled.)

Anyway, it’s not and you’ve already bought it (and it’s otherwise an excellent laptop) but you don’t want to change the text scale every time you plug it into and unplug it from your external monitor.


You need to add a udev rule that gets triggered whenever your screen setup changes (fun fact: you listen for the drm event – sigh – the state of things!) and then run a script that sets the text-scaling-factor accordingly.

  1. Configure the 80-personal.rules script (see instructions in script) and then place it in /etc/udev/rules.d/
  2. Configure the auto-text-scale.shscript (see instructions in script) and save it somewhere. Make sure you set it as executable: chmod +x
  3. Reload your udev rules: sudo udevadm control --reload

You can also test your rules (they will not run but it will show you if they would run were this not a test). Again, customise for your own device:

udevadm test --action="change" /devices/pci0000:00/0000:00:02.0/drm/card0

# Rule for executing commands when an external screen is plugged in.
# Credits go to:$
# Via
# Update the path to your home directory and the path to the script file according to your own setup.
ACTION=="change" \
, KERNEL=="card0" \
, SUBSYSTEM=="drm" \
, ENV{DISPLAY}=":0" \
, ENV{XAUTHORITY}="/home/aral/.Xauthority" \
, RUN+="/home/aral/"
# Get the actual account id as gsettings needs to be set for my account.
# Thanks to:
RUID=$(who | awk 'FNR == 1 {print $1}')
RUSER_UID="$(id -u ${RUID})"
# Get the status of my external monitor.
# (Your device details will vary. Use sudo udevadm monitor to find it.)
# Thanks to:
if [[ $(</sys/class/drm/card0/card0-DP-1/status) == "connected" ]]; then
# echo `date` '- External 4K screen connected. Setting text scale factor to 1.0.' >> /tmp/monitor-log.txt
sudo -u ${RUID} DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/${RUSER_UID}/bus" /usr/bin/gsettings set org.gnome.desktop.interface text-scaling-factor 1.0
# echo `date` '- External screen not connected. Setting text scale factor to 1.75.' >> /tmp/monitor-log.txt
sudo -u ${RUID} DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/${RUSER_UID}/bus" /usr/bin/gsettings set org.gnome.desktop.interface text-scaling-factor 1.75
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment