How to Programmatically Rotate Displays in KDE Plasma on Wayland

Table of Contents

NOTE: This broke when updating to Plasma 6. I suspect it will still work on some older distributions, but I have not gotten around to fixing it for Plasma 6 quite yet

I recently bought an old Thinkpad x220t and installed Linux on it. I've been wanting to get into old Thinkpads for a while now – they just don't make laptops like they used to! – and I also needed something to take notes on in class. I came across an excellent guide with some tips on how to customize Linux to support some of the x220t's 2-in-1 capabilities, but the section about screen rotation assumed that the reader would use X11. That might have been a good assumption in 2020, but we're in 2023 now and it's becoming harder and harder to find distributions that don't default to Wayland, and I personally use it everywhere I can. Thus, I needed some way to rotate the screen programmatically in Wayland so that I could bind that to the "Rotate Screen" key. As with most things Wayland, this is compositor-dependent, so this guide only applies to kwin, which does a particularly bad job of documenting how to do this.

Rotating the display from the terminal

This may depend on the distribution, but a typical KDE install (with or without Wayland) includes the module kscreen, which is used to manage and remember display configurations (if you go into your display settings, it uses this module). Typically, the package that included kscreen will come with the command line program kscreen-doctor, which allows retrieval of display information and display customization from the command line. Assuming you have this program on your system, you should be good to go.

kscreen-doctor conveniently provides a way to view lots of screen-related info, including rotation, by calling kscreen-doctor -o. This will list info for all displays. Now, if you can, disconnect all displays other than the one you want to rotate, then call it again, and the second "word" after Output: should be a relatively-unchanging way of identifying the screen you want to rotate. It should look something like eDP-1, HDMI-1, LVDS-1, DP-1, etc. Once you have that name, you can rotate the screen from the command line by calling kscreen-doctor output.<screen identifier from last step>.rotation.<none | left | right | inverted>.

Turning this into a script

This is great, but it's not very useful alone. First of all, we don't want to have to type that long command every time we want to rotate the screen, and if we intend to make this a keybind, we'll need to put it in a bash script so that we can tell KDE to call it when it sees the keybind we want. That presents the additional problem that unless we want 4 different keybinds for orientations, we need to detect what the current rotation is and use that to choose a 90 degree rotation relative to the current rotation in our script.

Fortunately, kscreen-doctor -o actually provided us this information in its output, in the form of an integer between 1 and 4 after the word "Rotation:". That means we should be able to write a chain of pipes to isolate that in the output:

kscreen-doctor -o 2> /dev/null | grep <screen identifier from earlier> | tr " " \n | grep -A 1 "Rotation:" | tail -n 1

Which gives a number from 1 to 4 as an output and so looks like it'll work correctly for our purposes. However, kscreen-doctor uses colors by default, and there's no way to disable them that I could find (there's no manual for kscreen-doctor, anyway), so what seems like a one-character output actually has a bunch of garbage escape sequences at the beginning that make it not be an integer according to bash (actually, if you use shell substitution, you can end up with some pretty hilarious error messages trying to use it arithmetically, like bash saying $(( 1 + 1 )) is syntactically invalid). Surprisingly, there aren't many great solutions to this, so we have to add an ugly sed command to the end to strip these:

kscreen-doctor -o 2> /dev/null | grep <screen identifier from earlier> | tr " " \n | grep -A 1 "Rotation:" | tail -n 1 | sed 's/\x1B[@A-Z\\\]^_]\|\x1B\[[0-9:;<=>?]*[-!"#$%&'"'"'()*+,.\/]*[][\\@A-Z^_`a-z{|}~]//g'

But this should at least work as expected in a script. Now, we can just use some if statements to make it do what we want (this will be the right order of numbers):

#!/bin/sh

cur_rot=$(kscreen-doctor -o 2> /dev/null | grep <screen identifier from earlier> | tr " " \n | grep -A 1 "Rotation:" | tail -n 1 | sed 's/\x1B[@A-Z\\\]^_]\|\x1B\[[0-9:;<=>?]*[-!"#$%&'"'"'()*+,.\/]*[][\\@A-Z^_`a-z{|}~]//g')

# Sensible to default to no rotation in case something gets messed up
if [ $cur_rot = 1 ]; then
    new_rot="left"
elif [ $cur_rot = 2 ]; then
    new_rot="inverted"
elif [ $cur_rot = 4 ]; then
    new_rot="right"
else
    new_rot="none"
fi

kscreen-doctor output.<screen identifier from earlier>.rotation."$new_rot"

Change both <screen identifier from earlier> placeholders to what the screen identifier from earlier was, then save this in a file and do chmod +x <the file you saved it in>. You should now be able to run that file and it should rotate your screen by 90 degrees.

Turning the script into a shortcut

This part is by far the easiest. Go in to your System Settings and under "Workspace", select "Shortcuts". In the bottom left of the "Shortcuts" panel, click on "Add Command", and then paste in the name of the file you just saved. Now, under the sidebar menu within the "Shortcuts" panel, you should see the path to your script under "Commands". Clicking on it will allow you to "Add custom shortcut" to it as you would to add a shortcut to any other program. Choose your desired keybinding, click "Apply", and you should now be able to rotate the screen by pressing your shortcut.