iio-rotated: Add Wayland support

master
Taeyeon Mori 4 years ago
parent 7c0cd9ca95
commit d18bc0c94c
  1. 137
      bin/iio-rotated

@ -1,27 +1,69 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os
import subprocess import subprocess
from PyQt5 import QtCore, QtDBus, QtWidgets from PyQt5 import QtCore, QtGui, QtDBus, QtWidgets
from PyQt5.QtCore import pyqtSignal as Signal, pyqtSlot as Slot, pyqtProperty as Property, Q_CLASSINFO from PyQt5.QtCore import pyqtSignal as Signal, pyqtSlot as Slot, pyqtProperty as Property, Q_CLASSINFO
if "WAYLAND_DISPLAY" in os.environ:
IS_WAYLAND = True
KSCREEN_OUTPUT = "unknown DSI-1-unknown"
else:
IS_WAYLAND = False
KSCREEN_OUTPUT = "DSI-1" KSCREEN_OUTPUT = "DSI-1"
XINPUT_TOUCH = "silead_ts"
XINPUT_TOUCH = "silead_ts"
IIO_BUSNAME = "net.hadess.SensorProxy"
IIO_OBJPATH = "/net/hadess/SensorProxy"
IIO_TO_KSCREEN = { IIO_TO_KSCREEN = {
"normal": "none", "normal": "none",
"right-up": "right", "right-up": "left" if IS_WAYLAND else "right",
"left-up": "left", "left-up": "right" if IS_WAYLAND else "left",
"bottom-up": "inverted" "bottom-up": "inverted"
} }
KEYBOARD_ORIENTATION = IIO_TO_KSCREEN["right-up"]
IIO_BUSNAME = "net.hadess.SensorProxy"
IIO_OBJPATH = "/net/hadess/SensorProxy"
KWIN_BUSNAME = "org.kde.KWin"
KWIN_OBJPATH = "/org/kde/KWin"
# DBus # DBus
class DIKWinTabletModeManager(QtDBus.QDBusAbstractInterface):
tabletModeAvailableChanged = Signal(bool)
@Property(bool, notify=tabletModeAvailableChanged)
def tabletModeAvailable(self):
return self.property("tabletModeAvailable")
tabletModeChanged = Signal(bool)
@Property(bool, notify=tabletModeChanged)
def tabletMode(self):
return self.property("tabletMode")
@Slot(QtDBus.QDBusMessage)
def _on_properties_changed(self, msg):
intf, updated, invald = msg.arguments()
updated = dict(updated)
if "tabletModeAvailable" in updated:
self.tabletModeAvailableChanged.emit(updated["tabletModeAvailable"])
if "tabletMode" in updated:
self.tabletModeChanged.emit(updated["tabletMode"])
def __init__(self, service, path, connection, parent=None):
super().__init__(service, path, "org.kde.KWin.TabletModeManager", connection, parent)
if not connection.connect(service, path, "org.freedesktop.DBus.Properties",
"PropertiesChanged", ["org.kde.KWin.TabletModeManager"], "sa{sv}as",
self._on_properties_changed):
raise RuntimeError("Could not connect to PropertiesChanged")
class DISensorProxy(QtDBus.QDBusAbstractInterface): class DISensorProxy(QtDBus.QDBusAbstractInterface):
HasAccelerometerChanged = Signal(bool) HasAccelerometerChanged = Signal(bool)
@Property(bool, notify=HasAccelerometerChanged) @Property(bool, notify=HasAccelerometerChanged)
@ -33,7 +75,6 @@ class DISensorProxy(QtDBus.QDBusAbstractInterface):
def AccelerometerOrientation(self) -> str: def AccelerometerOrientation(self) -> str:
return self.property("AccelerometerOrientation") return self.property("AccelerometerOrientation")
def ClaimAccelerometer(self): def ClaimAccelerometer(self):
self.call("ClaimAccelerometer") self.call("ClaimAccelerometer")
@ -82,6 +123,18 @@ class DARotated(QtDBus.QDBusAbstractAdaptor):
def AutoTurn(self, val): def AutoTurn(self, val):
self.app.set_turn_enabled(val) self.app.set_turn_enabled(val)
@Property(bool)
def TabletModeManager(self):
return self.app.tmm_enabled
@TabletModeManager.write
def TabletModeManager(self, val):
self.app.set_tmm_enabled(val)
@Property(bool)
def TabletModeManagerAvailable(self):
return self.app.tmm is not None
@Slot(str, result=bool) @Slot(str, result=bool)
def Turn(self, orientation): def Turn(self, orientation):
if orientation in ("none", "right", "left", "inverted"): if orientation in ("none", "right", "left", "inverted"):
@ -106,6 +159,8 @@ class Main(QtCore.QObject):
# TODO: Figure out initial orientation # TODO: Figure out initial orientation
self.orientation = None self.orientation = None
self.turn_enabled = True self.turn_enabled = True
self.tmm_enabled = IS_WAYLAND
self.tablet_mode = None
# Turning # Turning
orientationChanged = Signal(str) orientationChanged = Signal(str)
@ -115,8 +170,14 @@ class Main(QtCore.QObject):
Turn the Display into a different orientation Turn the Display into a different orientation
@param orientation The KScreen orientation (none|right|left|inverted) @param orientation The KScreen orientation (none|right|left|inverted)
""" """
try:
subprocess.check_call(["kscreen-doctor", "output.%s.rotation.%s" % (KSCREEN_OUTPUT, orientation)]) subprocess.check_call(["kscreen-doctor", "output.%s.rotation.%s" % (KSCREEN_OUTPUT, orientation)])
if not IS_WAYLAND:
subprocess.check_call(["xinput", "--map-to-output", XINPUT_TOUCH, KSCREEN_OUTPUT]) subprocess.check_call(["xinput", "--map-to-output", XINPUT_TOUCH, KSCREEN_OUTPUT])
except:
import traceback
traceback.print_exc()
else:
self.orientation = orientation self.orientation = orientation
self.orientationChanged.emit(orientation) self.orientationChanged.emit(orientation)
@ -130,13 +191,28 @@ class Main(QtCore.QObject):
self.turn_enabled = v self.turn_enabled = v
self.turn_enabled_changed.emit(v) self.turn_enabled_changed.emit(v)
def set_tmm_enabled(self, v):
self.tmm_enabled = v
self.tmm_enabled_changed.emit(v)
turn_enabled_changed = Signal(bool) turn_enabled_changed = Signal(bool)
tmm_enabled_changed = Signal(bool)
def on_systray_clicked(self, reason): def on_systray_clicked(self, reason):
print("Activated", reason) print("Activated", reason)
# TODO: this should change the Icon if reason == QtWidgets.QSystemTrayIcon.Trigger:
#if reason == QtWidgets.QSystemTrayIcon.Trigger: if not self.tmm_enabled:
# self.set_turn_enabled(not self.turn_enabled) self.set_turn_enabled(not self.turn_enabled)
def on_tabletmode(self, v):
if self.tmm_enabled:
self.set_turn_enabled(v)
if v:
print("Entered Tablet Mode")
#self.turn_screen(IIO_TO_KSCREEN[self.iio.AccelerometerOrientation])
else:
print("Left Tablet Mode")
self.turn_screen(KEYBOARD_ORIENTATION)
# Main # Main
def main(self): def main(self):
@ -152,6 +228,15 @@ class Main(QtCore.QObject):
self.adaptor = DARotated(self) self.adaptor = DARotated(self)
self.session_bus.registerObject("/Rotated", self) self.session_bus.registerObject("/Rotated", self)
try:
self.tmm = DIKWinTabletModeManager(KWIN_BUSNAME, KWIN_OBJPATH, self.session_bus)
except:
print("Could not connect to KWin TabletModeManager")
import traceback
traceback.print_exc()
self.tmm_enabled = False
self.tmm = None
# Connect to System Bus # Connect to System Bus
self.system_bus = QtDBus.QDBusConnection.systemBus() self.system_bus = QtDBus.QDBusConnection.systemBus()
@ -159,23 +244,39 @@ class Main(QtCore.QObject):
raise RuntimeError("Not connected to System Bus") raise RuntimeError("Not connected to System Bus")
# Look for iio-sensor-proxy # Look for iio-sensor-proxy
iio = DISensorProxy(IIO_BUSNAME, IIO_OBJPATH, self.system_bus) self.iio = iio = DISensorProxy(IIO_BUSNAME, IIO_OBJPATH, self.system_bus)
if not iio.HasAccelerometer: if not iio.HasAccelerometer:
raise RuntimeError("No accelerometer reported") raise RuntimeError("No accelerometer reported")
# Set up System Tray Icon # Set up System Tray Icon
self.icon_lock = QtGui.QIcon.fromTheme("emblem-locked")
self.icon_turn = QtGui.QIcon.fromTheme("emblem-unlocked")
# TODO: Directly work with StatusNotifierItem API? # TODO: Directly work with StatusNotifierItem API?
self.systray = QtWidgets.QSystemTrayIcon(self) self.systray = QtWidgets.QSystemTrayIcon(self.icon_turn, self)
#self.systray.setToolTip("Screen Orientation") #self.systray.setToolTip("Screen Orientation")
self.turn_enabled_changed.connect(lambda v: self.systray.setIcon(self.icon_turn if v else self.icon_lock))
self.menu = QtWidgets.QMenu() self.menu = QtWidgets.QMenu()
# Tablet Mode detection enable
action = self.menu.addAction("Detect Tablet Mode")
action.setEnabled(self.tmm is not None)
action.setCheckable(True)
action.setChecked(self.tmm_enabled)
action.triggered.connect(lambda c: self.set_tmm_enabled(c))
self.tmm_enabled_changed.connect(lambda c, action=action: action.setChecked(c))
# Auto turn enable
action = self.menu.addAction("Auto-Turn") action = self.menu.addAction("Auto-Turn")
action.setCheckable(True) action.setCheckable(True)
action.setChecked(self.turn_enabled) action.setChecked(self.turn_enabled)
self.turn_enabled_changed.connect(lambda v, action=action: action.setChecked(v)) action.setEnabled(not self.tmm_enabled)
action.triggered.connect(lambda c: self.set_turn_enabled(c)) action.triggered.connect(lambda c: self.set_turn_enabled(c))
self.tmm_enabled_changed.connect(lambda v, action=action: action.setEnabled(not v))
self.turn_enabled_changed.connect(lambda v, action=action: action.setChecked(v))
self.menu.addSeparator() self.menu.addSeparator()
# Manual turning
for label, direction in (("Normal", "none"), for label, direction in (("Normal", "none"),
("Anti-CW", "right"), ("Anti-CW", "right"),
("Clockwise", "left"), ("Clockwise", "left"),
@ -184,7 +285,9 @@ class Main(QtCore.QObject):
action.triggered.connect(lambda *a, d=direction: self.turn_screen(d)) action.triggered.connect(lambda *a, d=direction: self.turn_screen(d))
action.setEnabled(not self.turn_enabled) action.setEnabled(not self.turn_enabled)
self.turn_enabled_changed.connect(lambda v, action=action: action.setEnabled(not v)) self.turn_enabled_changed.connect(lambda v, action=action: action.setEnabled(not v))
self.menu.addSeparator() self.menu.addSeparator()
# Quit
action = self.menu.addAction("Quit") action = self.menu.addAction("Quit")
action.triggered.connect(self.qapp.quit) action.triggered.connect(self.qapp.quit)
self.systray.setContextMenu(self.menu) self.systray.setContextMenu(self.menu)
@ -192,6 +295,12 @@ class Main(QtCore.QObject):
self.systray.activated.connect(self.on_systray_clicked) self.systray.activated.connect(self.on_systray_clicked)
self.systray.show() self.systray.show()
if self.tmm is not None:
#self.tmm.tabletModeAvailableChanged.connect(self.updateTabletModeAvailable)
#self.updateTabletModeAvailable(self.tmm.tabletModeAvailable)
self.tmm.tabletModeChanged.connect(self.on_tabletmode)
self.on_tabletmode(self.tmm.tabletMode)
# Run # Run
iio.ClaimAccelerometer() iio.ClaimAccelerometer()

Loading…
Cancel
Save