Created
September 24, 2021 06:48
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
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.