Building the package found two things reading the tree did not. dpkg refused it outright: plasma-workspace already owns /etc/xdg/plasmanotifyrc and friends, and two packages cannot own one path. The room's settings move to a directory of their own with /etc/environment.d putting it in front of /etc/xdg, which is KConfig's own cascade rather than a file fight. The postinst then failed on a chmod for a command that no longer exists. It now walks what the package installed instead of naming files, removes the login shell that used to start sway on tty1, and enables SDDM and the audio service. Verified by installing the built package on a fresh machine and starting the session from it: restrictions in force, palette applied, audio service enabled and running, panel supervision unconditional. Co-Authored-By: Claude Opus 5 <[email protected]>
221 lines
7.2 KiB
Bash
Executable File
221 lines
7.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# Classroom v2 test lab driver.
|
|
#
|
|
# The development host is a VM with no /dev/kvm, so the desktop under test
|
|
# runs inside a systemd container instead of a virtual machine. Nothing this
|
|
# script does touches the host outside Docker.
|
|
#
|
|
# The session is nested: an outer headless sway exists only to give the
|
|
# desktop under test a display that grim can capture and that sway's IPC can
|
|
# aim a real pointer at. The outer compositor is lab equipment, not part of
|
|
# the classroom design.
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
NAME="${LAB_NAME:-classroom-v2-lab}"
|
|
IMAGE="${LAB_IMAGE:-classroom-v2-lab:plasma}"
|
|
DOCKERFILE="${LAB_DOCKERFILE:-tools/lab/Dockerfile.plasma}"
|
|
SHOTS="${LAB_SHOTS:-$ROOT/docs/screenshots}"
|
|
|
|
OUTER=wayland-1
|
|
|
|
session_env() {
|
|
docker exec -u classroom \
|
|
-e XDG_RUNTIME_DIR=/run/user/1000 \
|
|
-e HOME=/home/classroom \
|
|
-e LANG=C.UTF-8 \
|
|
-e DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
|
|
"$@"
|
|
}
|
|
|
|
# Talk to the outer lab compositor: grim, swaymsg.
|
|
outer() {
|
|
local sock
|
|
sock=$(docker exec "$NAME" sh -c 'ls /run/user/1000/sway-ipc.* 2>/dev/null | head -1')
|
|
session_env -e WAYLAND_DISPLAY="$OUTER" -e SWAYSOCK="$sock" "$NAME" "$@"
|
|
}
|
|
|
|
# Talk to the Plasma session under test.
|
|
inner() {
|
|
session_env -e WAYLAND_DISPLAY=wayland-0 -e XDG_CURRENT_DESKTOP=KDE \
|
|
-e QT_QPA_PLATFORM=wayland "$NAME" "$@"
|
|
}
|
|
|
|
case "${1:-}" in
|
|
build)
|
|
shift
|
|
exec docker build -f "$ROOT/$DOCKERFILE" -t "$IMAGE" "$@" "$ROOT"
|
|
;;
|
|
|
|
up)
|
|
docker rm -f "$NAME" >/dev/null 2>&1 || true
|
|
docker run -d --name "$NAME" \
|
|
--privileged --cgroupns=private \
|
|
--tmpfs /run --tmpfs /run/lock \
|
|
--shm-size=1g \
|
|
-v "$ROOT:/srv/classroom:ro" \
|
|
"$IMAGE" >/dev/null
|
|
for _ in $(seq 1 90); do
|
|
state=$(docker exec "$NAME" systemctl is-system-running 2>/dev/null || true)
|
|
[[ "$state" == running || "$state" == degraded ]] && break
|
|
sleep 1
|
|
done
|
|
for _ in $(seq 1 30); do
|
|
docker exec "$NAME" test -S /run/user/1000/bus && break
|
|
sleep 1
|
|
done
|
|
# startplasma looks for `qdbus`; Debian ships it as qdbus6.
|
|
docker exec "$NAME" ln -sf /usr/bin/qdbus6 /usr/local/bin/qdbus
|
|
echo "lab $NAME is up ($(docker exec "$NAME" systemctl is-system-running 2>/dev/null))"
|
|
;;
|
|
|
|
down)
|
|
docker rm -f "$NAME" >/dev/null 2>&1 || true
|
|
echo "lab $NAME is down"
|
|
;;
|
|
|
|
outer-up)
|
|
# A headless compositor has no input devices, and a wl_seat with no
|
|
# pointer capability never gives the session under test a pointer to
|
|
# click with — sway's cursor commands then report success and move
|
|
# nothing. So the lab runs wlroots' libinput backend as well, over the
|
|
# devices the privileged container inherits, with seatd standing in for
|
|
# the login session it does not have. Clicks in this experiment are
|
|
# real pointer events arriving through libinput.
|
|
docker exec "$NAME" sh -c 'pgrep -x seatd >/dev/null || \
|
|
(SEATD_VTBOUND=0 setsid seatd -g input > /tmp/seatd.log 2>&1 &)'
|
|
docker exec "$NAME" usermod -aG input classroom 2>/dev/null || true
|
|
sleep 2
|
|
session_env \
|
|
-e WLR_BACKENDS=headless,libinput -e LIBSEAT_BACKEND=seatd \
|
|
-e WLR_RENDERER=pixman -e LIBGL_ALWAYS_SOFTWARE=1 \
|
|
-d "$NAME" sh -c 'exec sway -c /srv/classroom/tools/lab/outer-sway.conf \
|
|
> /tmp/outer-sway.log 2>&1'
|
|
for _ in $(seq 1 30); do
|
|
docker exec "$NAME" test -S "/run/user/1000/$OUTER" && break
|
|
sleep 1
|
|
done
|
|
echo "outer compositor on $OUTER"
|
|
;;
|
|
|
|
plasma-up)
|
|
session_env \
|
|
-e WAYLAND_DISPLAY="$OUTER" -e XDG_SESSION_TYPE=wayland \
|
|
-e XDG_CURRENT_DESKTOP=KDE -e LIBGL_ALWAYS_SOFTWARE=1 \
|
|
-e QT_LOGGING_RULES="kwin_scripting.debug=true" \
|
|
-e XDG_CONFIG_DIRS=/etc/ekklesia-classroom/xdg:/etc/xdg \
|
|
-d "$NAME" sh -c 'exec startplasma-wayland > /tmp/plasma.log 2>&1'
|
|
for _ in $(seq 1 60); do
|
|
docker exec "$NAME" pgrep -x plasmashell >/dev/null 2>&1 && break
|
|
sleep 1
|
|
done
|
|
sleep 5
|
|
echo "plasma session up"
|
|
;;
|
|
|
|
plasma-down)
|
|
docker exec "$NAME" pkill -u classroom -f startplasma-wayland || true
|
|
docker exec "$NAME" pkill -u classroom -x plasmashell || true
|
|
docker exec "$NAME" pkill -u classroom -x kwin_wayland || true
|
|
sleep 2
|
|
echo "plasma session down"
|
|
;;
|
|
|
|
session)
|
|
"$0" outer-up
|
|
"$0" plasma-up
|
|
;;
|
|
|
|
shot)
|
|
# shot NAME [GEOMETRY] — geometry as grim wants it, e.g. "0,980 1920x100"
|
|
name="${2:?usage: lab shot NAME}"
|
|
if [[ -n "${3:-}" ]]; then
|
|
outer grim -g "$3" /tmp/lab-shot.png >/dev/null
|
|
else
|
|
outer grim /tmp/lab-shot.png >/dev/null
|
|
fi
|
|
mkdir -p "$SHOTS"
|
|
docker exec "$NAME" cat /tmp/lab-shot.png > "$SHOTS/$name.png"
|
|
echo "$SHOTS/$name.png"
|
|
;;
|
|
|
|
click)
|
|
# Absolute, through sway's own seat. This only works because the seat
|
|
# has a pointer capability at all, which is what the uinput device in
|
|
# `outer-up` is for.
|
|
outer swaymsg seat - cursor set "$2" "$3" >/dev/null
|
|
sleep 0.4
|
|
outer swaymsg seat - cursor press button1 >/dev/null
|
|
sleep 0.15
|
|
outer swaymsg seat - cursor release button1 >/dev/null
|
|
sleep 0.5
|
|
;;
|
|
|
|
rclick)
|
|
outer swaymsg seat - cursor set "$2" "$3" >/dev/null
|
|
sleep 0.4
|
|
outer swaymsg seat - cursor press button3 >/dev/null
|
|
sleep 0.15
|
|
outer swaymsg seat - cursor release button3 >/dev/null
|
|
sleep 0.5
|
|
;;
|
|
|
|
move)
|
|
outer swaymsg seat - cursor set "$2" "$3" >/dev/null
|
|
;;
|
|
|
|
drag)
|
|
outer swaymsg seat - cursor set "$2" "$3" >/dev/null
|
|
sleep 0.3
|
|
outer swaymsg seat - cursor press button1 >/dev/null
|
|
sleep 0.3
|
|
outer swaymsg seat - cursor set "$4" "$5" >/dev/null
|
|
sleep 0.3
|
|
outer swaymsg seat - cursor release button1 >/dev/null
|
|
sleep 0.4
|
|
;;
|
|
|
|
key)
|
|
shift
|
|
outer wtype "$@"
|
|
;;
|
|
|
|
sh)
|
|
shift
|
|
exec docker exec -it "$NAME" bash "$@"
|
|
;;
|
|
|
|
run) shift; session_env "$NAME" "$@" ;;
|
|
irun) shift; session_env -it "$NAME" "$@" ;;
|
|
inner) shift; inner "$@" ;;
|
|
inner-d) shift; session_env -d -e WAYLAND_DISPLAY=wayland-0 -e XDG_CURRENT_DESKTOP=KDE \
|
|
-e QT_QPA_PLATFORM=wayland "$NAME" "$@" ;;
|
|
inner-it) shift; session_env -it -e WAYLAND_DISPLAY=wayland-0 -e XDG_CURRENT_DESKTOP=KDE "$NAME" "$@" ;;
|
|
outer) shift; outer "$@" ;;
|
|
|
|
*)
|
|
cat <<USAGE
|
|
usage: tools/lab/lab COMMAND
|
|
|
|
build build the lab image
|
|
up start the lab container (systemd inside)
|
|
down remove it
|
|
session outer compositor + a Plasma session on top of it
|
|
outer-up just the outer compositor
|
|
plasma-up just the Plasma session
|
|
plasma-down stop the Plasma session
|
|
shot NAME capture the screen to docs/screenshots/NAME.png
|
|
click X Y press the pointer at a screen position
|
|
drag X1 Y1 X2 Y2 drag from one position to another
|
|
move X Y move the pointer
|
|
key ARGS... wtype, aimed at the session
|
|
inner CMD... run CMD as a client of the Plasma session
|
|
inner-d CMD... the same, detached
|
|
outer CMD... run CMD against the lab compositor
|
|
run CMD... run CMD as the classroom user, no display
|
|
sh root shell in the lab
|
|
USAGE
|
|
exit 1
|
|
;;
|
|
esac
|