Hi guys.
Because i struggeled to get tablet mode working with my old 2in1 Lenovo Yoga 900-13isk, i thought posting this, will maybe help others out to get it working.
What was working and not:
- after flipping the device to tablet mode, touchpad disabling autoamtically, but not enables it itself
- no tablet mode (bigger taskbar / window icons)
- no virtual keyboard
- no auto rotation
What i have done to fix those issues:
Touchpad key on keyboard
Used this fix from here to get the touchpad button fixed in hwdb https://wiki.archlinux.org/title/Lenovo_IdeaPad_Yoga_900
Maybe your keycode differs, you can check them with various tools listed in the documentation, like: libinput debug-events
sudo nano /etc/udev/hwdb.d/90-lenovo-yoga.hwdb
Contents:
#Lenovo YOGA 900-13IS
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrLenovoYOGA900*
KEYBOARD_KEY_bf=f21 # Fn+F6 Disable Touchpad
After a reboot, the touchpad key was working.
Auto rotation
To get auto rotation working as described in the link above, i had to install iio-sensor-proxy with:
sudo pacman -S iio-sensor-proxy
After a reboot it was enabled under Settings → Display → Auto rotate
I disabled “Just in tablet mode“, because i wanted to have rotation working all the time.
I had to use older 3.5-2 version and ignore updates (like newest one 3.8-1) because of an bug that it doesnt work after standby.
Virtual keyboard
To be able to switch virtual keyboard on/off automatically with the following script (see Tablet mode) you have to set virtual keyboard to “plasma” under Settings → keyboard → virtual keyboard
Tablet mode
Tablet mode is currently not supported in kernel for my device, so switching was not working.
I had to write a script which monitors the accelerometer sensor, like so:
[user@eos-yoga900 ~]$ monitor-sensor
Waiting for iio-sensor-proxy to appear
+++ iio-sensor-proxy appeared
=== Has accelerometer (orientation: normal)
=== Has ambient light sensor (value: 10,000000, unit: lux)
=== No proximity sensor
Accelerometer orientation changed: bottom-up
Light changed: 5,000000 (lux)
Light changed: 1,000000 (lux)
Accelerometer orientation changed: normal
Light changed: 10,000000 (lux)
Where bottom-up is flipped and normal = not flipped.
And switch tablet mode, touch pad and virtual keyboard accordingly.
You have todo the following for every user and it does not require root/sudo after setting this up.
They needed to be two seperate scripts, otherwise it would not work correctly and i could not figure out why.
mkdir ~scripts/tablet_mode/
nano ~scripts/tablet_mode/tablet_mode_monitor.py
#!/usr/bin/env python3
import subprocess
import sys
import shlex
from pathlib import Path
TABLET_ON_ORIENTATIONS = {
"bottom-up",
"left-up",
"right-up",
"top-up",
}
SCRIPT_DIR = Path(__file__).resolve().parent
SETTER = SCRIPT_DIR / "tablet_mode_set.py"
def set_virtual_keyboard(enabled: bool):
value = "true" if enabled else "false"
subprocess.run([
"qdbus6",
"org.kde.KWin",
"/VirtualKeyboard",
"org.freedesktop.DBus.Properties.Set",
"org.kde.kwin.VirtualKeyboard",
"enabled",
value
], check=False)
def set_touchpad(enabled: bool):
print(f"[touchpad] requested -> {'ON' if enabled else 'OFF'}")
try:
res = subprocess.run(
[
"qdbus6",
"org.kde.KWin",
"/org/kde/KWin/InputDevice",
"org.freedesktop.DBus.Properties.Get",
"org.kde.KWin.InputDeviceManager",
"devicesSysNames",
],
capture_output=True,
text=True,
)
devices = [l.strip() for l in res.stdout.splitlines() if l.strip()]
print(f"[touchpad] devices: {devices}")
for d in devices:
print(f"[touchpad] checking {d}")
name_res = subprocess.run(
[
"qdbus6",
"org.kde.KWin",
f"/org/kde/KWin/InputDevice/{d}",
"org.freedesktop.DBus.Properties.Get",
"org.kde.KWin.InputDevice",
"name",
],
capture_output=True,
text=True,
)
name = name_res.stdout.strip()
print(f"[touchpad] name: {name}")
if any(x in name for x in ("Touchpad", "Synaptics", "ELAN", "MSFT")):
print(f"[touchpad] MATCH -> {name}")
subprocess.run(
[
"qdbus6",
"org.kde.KWin",
f"/org/kde/KWin/InputDevice/{d}",
"org.freedesktop.DBus.Properties.Set",
"org.kde.KWin.InputDevice",
"enabled",
"true" if enabled else "false",
],
check=False,
)
print(f"[touchpad] set {d} -> {'true' if enabled else 'false'}")
except Exception as e:
print(f"[touchpad] EXCEPTION: {e}")
def main():
current_state = None
subprocess.call([str(SETTER), "off"])
set_virtual_keyboard(False)
set_touchpad(True)
proc = subprocess.Popen(
["monitor-sensor"],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
text=True,
bufsize=1,
)
for line in proc.stdout:
if "Accelerometer orientation changed:" not in line:
continue
orientation = line.split(":")[-1].strip()
desired = "on" if orientation in TABLET_ON_ORIENTATIONS else "off"
if desired != current_state:
subprocess.call([str(SETTER), desired])
if orientation == "bottom-up":
set_virtual_keyboard(True)
elif orientation == "normal":
set_virtual_keyboard(False)
set_touchpad(True)
print(f"TabletMode -> {desired} ({orientation})")
current_state = desired
if __name__ == "__main__":
main()
Save it with CTRL-X →Y →Enter
nano scripts/tablet_mode/tablet_mode_set.py
#!/usr/bin/env python3
import sys
import subprocess
import gi
gi.require_version('Gio', '2.0')
from gi.repository import Gio, GLib
KDE_VERSION = 6
OBJECT_PATH = '/kwinrc'
INTERFACE_NAME = 'org.kde.kconfig.notify'
SIGNAL_NAME = 'ConfigChanged'
if len(sys.argv) != 2 or sys.argv[1] not in ("on", "off"):
print("Usage: set_tablet_mode.py on|off", file=sys.stderr)
sys.exit(1)
mode = sys.argv[1]
current_mode = subprocess.check_output(
[
f"kreadconfig{KDE_VERSION}",
"--file", "kwinrc",
"--group", "Input",
"--key", "TabletMode",
"--default", "auto",
],
text=True
).strip()
if current_mode == mode:
sys.exit(0)
subprocess.check_call(
[
f"kwriteconfig{KDE_VERSION}",
"--file", "kwinrc",
"--group", "Input",
"--key", "TabletMode",
mode,
]
)
connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
Gio.DBusConnection.emit_signal(
connection,
None,
OBJECT_PATH,
INTERFACE_NAME,
SIGNAL_NAME,
GLib.Variant.new_tuple(
GLib.Variant('a{saay}', {'Input': [b'TabletMode']})
)
)
Save it with CTRL-X →Y →Enter
Make it executable:
sudo chmod +x ~/scripts/tablet_mode/*.py
Test it manually with:
scripts/tablet_mode/tablet_mode_set.py on
scripts/tablet_mode/tablet_mode_set.py off
If that works, install it as service.
Optional, for other users (ex.: otheruser):
sudo cp /home/myuser/scripts/tablet_mode/tablet_mode_monitor.py
/home/otheruser/scripts/tablet_mode/tablet_mode_monitor.pysudo chown otheruser:otheruser
/home/otheruser/scripts/tablet_mode/*.py
Make it exeutable for all users:
sudo chmod +x /home/*/scripts/tablet_mode/tablet_mode_monitor.py
login with every user and do:
mkdir -p /home/julian/.config/systemd/user
nano ~/.config/systemd/user/tablet_mode.service
[Unit]
Description=Tablet Mode Monitor Service
After=graphical.target
[Service]
Type=simple
ExecStart=/home/%u/scripts/tablet_mode/tablet_mode_monitor.py
Restart=always
RestartSec=5
WorkingDirectory=/home/%u/scripts/tablet_mode
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=default.target
Replace %u with actual user name.
Save it with CTRL-X →Y →Enter
# reload systemd
systemctl --user daemon-reload
# start service
systemctl --user start tablet_mode.service
# check if it runs
systemctl --user status tablet_mode.service
# run automatically on login
systemctl --user enable tablet_mode.service
Now all should work.
P.S.: if not maybe you have to adapt the scripts to your hardware
Hope this helps