Created
November 22, 2024 11:29
-
-
Save jsommr/6f15156999f086e277d57d58bb778bda to your computer and use it in GitHub Desktop.
Waydroid on KDE: True fullscreen (KDE gestures and "reveal panel" edges disabled) and screen rotation support.
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
#!/bin/env bash | |
# Makes `waydroid show-full-ui` integrate nicely with KDE by disabling KDE gestures and | |
# reacting to screen rotation. Not tested with multi_windows. | |
# | |
# Run this script when signed into a wayland session, and not as root (don't use sudo). | |
# Re-run every time you change resolution or scaling. | |
# | |
# The Lineage OS boot animation will no longer be centered as a result of this script. | |
# | |
# IMPORTANT | |
# Mouse support in Waydroid gets broken by this. I believe it's because I'm marking the | |
# window fullscreen in KDE and re-positioning it. Touch works as expected. | |
# Find `waydroid.fullScreen = true` in this script and remove it if this is an issue for | |
# you. I haven't tried it since I only use the touch screen for Waydroid. No fullscreen | |
# means that KDE gestures will react to swipes, and panels are revealed when the cursor | |
# touches the edges of the screen. | |
if ! [[ -x $(command -v jq) ]]; then | |
echo "This command requires jq." | |
exit 1 | |
fi | |
# No reason to let the user wait for granting sudo permission | |
sudo true | |
echo | |
echo "Fullscreen Waydroid on KDE" | |
echo | |
MONITORS=$(kscreen-doctor --json) | |
if [[ -z $MONITORS ]]; then | |
echo | |
echo "kscreen-doctor failed. This is usually a temporary thing, try running this program again a few times." | |
echo | |
exit 1 | |
fi | |
MONITORS_COUNT=$(echo "$MONITORS" | jq '.outputs | length') | |
SELECTED_MONITOR_ID=1 | |
if [[ $MONITORS_COUNT > 1 ]]; then | |
kscreen-doctor -o | sed G | |
echo | |
echo "What monitor is going to render Waydroid? Enter its \"Output: {number}\"" | |
while true; do | |
read -p "Output: " SELECTED_MONITOR_ID | |
if [[ $SELECTED_MONITOR_ID -gt 0 && $SELECTED_MONITOR_ID -le $MONITORS_COUNT ]]; then | |
break | |
fi | |
echo "That output doesn't exist." | |
done | |
fi | |
SELECTED_MONITOR=$(echo "$MONITORS" | jq '.outputs[] | select(.id == $monitorId)' --argjson monitorId $SELECTED_MONITOR_ID) | |
WIDTH=$(echo "$SELECTED_MONITOR" | jq '.size.width') | |
HEIGHT=$(echo "$SELECTED_MONITOR" | jq '.size.height') | |
SCALE=$(echo "$SELECTED_MONITOR" | jq '.scale') | |
MAX_SIZE=$(($WIDTH > $HEIGHT ? $WIDTH : $HEIGHT)) | |
WINDOW_SIZE=$(awk "BEGIN {print int(($MAX_SIZE/$SCALE) + 0.5)}") | |
echo | |
echo "Starting Waydroid and setting props. Expect a few retries." | |
echo | |
waydroid session start & | |
sleep 2 | |
# This prop is necessary for KDE fullscreen. Something prevents the Waydroid UI from rendering without it. | |
waydroid prop set persist.waydroid.use_subsurface true | |
waydroid prop set persist.waydroid.width $WINDOW_SIZE | |
waydroid prop set persist.waydroid.height $WINDOW_SIZE | |
echo | |
echo "Writing script that reacts to device orientation and sets Waydroid's resolution accordingly." | |
echo | |
sudo tee /sbin/waydroid-set-resolution << EOF | |
#!/bin/env bash | |
set -e | |
WIDTH=$WIDTH | |
HEIGHT=$HEIGHT | |
function set_resolution { | |
if ! waydroid status | grep -q "Session:.*RUNNING"; then | |
return | |
fi | |
case \$1 in | |
normal|bottom-up) | |
waydroid shell wm size \${WIDTH}x\${HEIGHT};; | |
left-up|right-up) | |
waydroid shell wm size \${HEIGHT}x\${WIDTH};; | |
esac | |
} | |
while IFS='$\n' read -r line; do | |
rotation="\$(echo \$line | sed -En "s/.*(normal|left-up|right-up|bottom-up).*/\1/p")" | |
[[ ! -z \$rotation ]] && set_resolution \$rotation | |
done < <(stdbuf -oL monitor-sensor --accel) | |
EOF | |
sudo chmod +x /sbin/waydroid-set-resolution | |
echo | |
echo "Creating systemd service that starts the script above." | |
echo | |
sudo tee /etc/systemd/system/waydroid-set-resolution.service << EOF | |
[Unit] | |
Description=Change Waydroid resolution when device is rotated. | |
After=iio-sensor-proxy.service waydroid-container.service | |
[Service] | |
ExecStart=/sbin/waydroid-set-resolution | |
Restart=always | |
[Install] | |
WantedBy=graphical.target | |
EOF | |
sudo systemctl enable waydroid-set-resolution | |
sudo systemctl start waydroid-set-resolution | |
echo | |
echo "Writing KWin script that re-positions the Waydroid window when orientation is changed." | |
echo | |
sudo mkdir -p /usr/share/kwin/scripts/waydroid-fullscreen/contents | |
sudo tee /usr/share/kwin/scripts/waydroid-fullscreen/metadata.json << EOF | |
{ | |
"KPackageStructure": "KWin/Script", | |
"KPlugin": { | |
"Authors": [{ "Name": "Jan Sommer" }], | |
"Description": "Run Waydroid in fullscreen (to disable KDE edge gestures). Requires waydroid-set-resolution.", | |
"Icon": "waydroid", | |
"Id": "waydroid-fullscreen", | |
"License": "Public Domain", | |
"Name": "Waydroid Fullscreen" | |
}, | |
"X-Plasma-API": "javascript", | |
"X-Plasma-MainScript": "main.js" | |
} | |
EOF | |
echo | |
sudo tee /usr/share/kwin/scripts/waydroid-fullscreen/contents/main.js << EOF | |
let waydroid = undefined | |
function reposition() { | |
if (!waydroid) | |
return | |
const ps = workspace.clientArea(KWin.PrimaryScreenArea, workspace.activeScreen, 0) | |
const orientation = ps.width > ps.height ? "landscape" : "portrait" | |
const geom = Object.assign({}, waydroid.frameGeometry) | |
if (orientation === "landscape") { | |
geom.y = -Math.round((waydroid.height - ps.height) / 2) | |
geom.x = 0 | |
} else { | |
geom.y = 0 | |
geom.x = -Math.round((waydroid.width - ps.width) / 2) | |
} | |
waydroid.frameGeometry = geom | |
} | |
workspace.clientAdded.connect(client => { | |
if (client.caption !== "Waydroid") | |
return | |
waydroid = client | |
waydroid.fullScreen = true | |
reposition() | |
workspace.virtualScreenGeometryChanged.connect(reposition) | |
}) | |
workspace.clientRemoved.connect(client => { | |
if (client.caption !== "Waydroid") | |
return | |
workspace.virtualScreenGeometryChanged.disconnect(reposition) | |
waydroid = undefined | |
}) | |
EOF | |
waydroid session stop | |
echo | |
echo "Done." | |
echo "Remember to enable the Waydroid Fullscreen KWin script in settings." | |
echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment