Skip to content

Instantly share code, notes, and snippets.

@rakslice
Created September 24, 2021 06:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rakslice/fcc62babb7a7062328e3899decc7ef24 to your computer and use it in GitHub Desktop.
Save rakslice/fcc62babb7a7062328e3899decc7ef24 to your computer and use it in GitHub Desktop.
A script to watch dbus for kde monitor configuration changes, and update given xinput touchscreen rotation for monitor rotation
#!/usr/bin/python3
import dbus
import sys
import subprocess
from gi.repository import GLib
from dbus.mainloop.glib import DBusGMainLoop
touchscreen_id = int(sys.argv[1])
DEBUG_ENABLED = False
def debug(*args):
if DEBUG_ENABLED:
print(*args)
def tm(matrix_str):
args = ["xinput", "set-prop", str(touchscreen_id), "--type=float", "Coordinate Transformation Matrix"] + matrix_str.split(" ")
subprocess.check_call(args)
def config_changed_callback(*args):
debug("Got signal; num of args", len(args))
params_dict = args[0]
outputs = params_dict["outputs"]
debug("num outputs", len(outputs))
z = outputs[0]
for key, val in z.items():
debug(key, val)
rot = z["rotation"]
debug("rotation", repr(rot))
debug("")
debug("")
if not isinstance(rot, dbus.Int64):
return
rot = int(rot)
# Guess:
# 1 - None
# 2 - Left
# 8 - Right
# 4 - Inv
if rot == 1:
tm("1 0 0 0 1 0 0 0 1")
elif rot == 2:
tm("0 -1 1 1 0 0 0 0 1")
elif rot == 8:
tm("0 1 0 -1 0 1 0 0 1")
elif rot == 4:
tm("-1 0 1 0 -1 1 0 0 1")
else:
tm("1 0 0 0 1 0 0 0 1")
def main():
# set up main loop
# (https://stackoverflow.com/questions/4125393/python-and-d-bus-how-to-set-up-main-loop)
DBusGMainLoop(set_as_default=True)
loop = GLib.MainLoop()
session_bus = dbus.SessionBus()
# set up to receive async signal
# (https://dbus.freedesktop.org/doc/dbus-python/tutorial.html#receiving-signals)
session_bus.add_signal_receiver(config_changed_callback, dbus_interface="org.kde.kscreen.Backend", path="/backend")
# run forever
loop.run()
if __name__ == "__main__":
main()
@rakslice
Copy link
Author

rakslice commented Sep 24, 2021

I use this script with lxqt in Alpine Linux on an HP Stream 7, a bay trail tablet with a "Goodix Capacitive TouchScreen". I have a small wrapper script that figures out the xinput device id for the touchscreen to pass in.

#!/bin/bash 
set -e -x

script_path="$(dirname "$0")"

touchpad_id=$(xinput | grep pointer | grep "Goodix" | egrep -o 'id=[0-9]+' | cut -d'=' -f2)

"$script_path"/touchpad_rotation.py $touchpad_id

I run this script as my regular user on lxqt login by having it configured as an auto-start item in the lxqt session preferences GUI.

Note that the Coordinate Transformation Matrix parameter containing 9 floating point values is a 3x3 matrix in top-to-bottom left-to-right order, and it specifies, for coordinates on the range 0 to 1, how to transform the touchscreen coordinates to get screen coordinates. Both of these sets of coordinates are coordinate pairs in two dimensions, so why a 3x3 matrix? Well, the third element implied by the matrix is not a coordinate but is an additional placeholder value used as part of what are called "homogeneous coordinates". It is a 1 for a point, and 0 for a vector/distance, and basically allows us to do transformations that include a translation of points as a matrix multiplication.

For the purpose of 90 degree rotations and flips we are dealing with for a monitor and a touch screen, this third coordinate is basically used when you need to swap the direction around. For instance, when rotated "left", the matrix

0 1 0
1 0 0
0 0 1

gets us close -- the length and width of the touchscreen are swapped so that they each match with the corresponding side of the monitor -- but the length is the wrong way around (moving left on the touchscreen moves the cursor right, and vice versa). To fix this, instead we use

0 -1 1
1 0 0
0 0 1

Here the -1 subtracts the position along the touch screen from the screen coordinate instead of adding it, but we need to get a positive value for the screen coordinate otherwise the cursor will be stuck at the left (0) side of the screen, so we put a 1 in the third column which adds a constant 1 to the value between -1 and 0, which gives the screen position we actually want.

See https://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations for the idea of this math in general and https://wiki.ubuntu.com/X/InputCoordinateTransformation for specific instructions about this setting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment