Skip to content

Instantly share code, notes, and snippets.

@jsommr
Created November 22, 2024 11:29
Show Gist options
  • Save jsommr/6f15156999f086e277d57d58bb778bda to your computer and use it in GitHub Desktop.
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.
#!/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
@Samy879
Copy link

Samy879 commented Jul 9, 2025

Thanks :)

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