mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 08:00:09 +02:00
Frametop: a multi-screen desktop and universal 3D mouse for the Steam Frame
Several KDE Plasma screens floating in SteamVR, each a real monitor of any resolution and shape, shown by our own compositor (ft-screens), with a layout, wrist pinning, and visibility modes; a Bluetooth mouse that drives all of SteamVR as a room-anchored 3D pointer (input relay, ft-pointer helper, ft_pointer SteamVR driver); two settings apps; and Bluetooth LE fixes. Installs on the headset with ./install.sh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
d439bc3f25
61 files changed
+8785
No files matched your search
Executable
+60
@@ -0,0 +1,60 @@
|
||||
# Sourced by the other scripts. Works out where the Steam Frame is and how to reach it.
|
||||
#
|
||||
# On the Frame itself (SteamOS, VR variant), FRAME_LOCAL=1: commands run locally, and the
|
||||
# Frame's copy of the repo (FRAME_REPO) is this checkout, wherever it was cloned.
|
||||
# On a PC, FRAME_LOCAL=0: commands run over SSH on $FRAME_HOST (default "frame"), and the
|
||||
# Frame's copy is the one scripts/sync.sh keeps at ~/dev/frametop.
|
||||
# FRAME_LOCAL, FRAME_HOST, FRAME_REPO, and FRAME_BOX (container, default "dev") can be
|
||||
# set in the environment to override.
|
||||
|
||||
REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
|
||||
if [ -z "${FRAME_LOCAL:-}" ]; then
|
||||
FRAME_LOCAL=0
|
||||
if grep -qx 'ID=steamos' /etc/os-release 2>/dev/null && grep -qE '^VARIANT_ID="?vr"?$' /etc/os-release; then
|
||||
FRAME_LOCAL=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$FRAME_LOCAL" = 1 ]; then
|
||||
FRAME_REPO=$REPO_ROOT
|
||||
# A terminal inside a Plasma session in VR (Frametop or the stock desktop) has that
|
||||
# session's private XDG_RUNTIME_DIR and D-Bus. systemctl --user and podman need the
|
||||
# real ones.
|
||||
export XDG_RUNTIME_DIR=/run/user/$(id -u)
|
||||
export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus
|
||||
else
|
||||
FRAME_REPO=${FRAME_REPO:-/home/steamos/dev/frametop}
|
||||
# Agent and IDE shells often inherit gpg-agent's socket while the keys are loaded
|
||||
# into keychain's ssh-agent at login. Use keychain's when the current one has no keys.
|
||||
if ! ssh-add -l >/dev/null 2>&1; then
|
||||
kc="$HOME/.keychain/$(hostname)-sh"
|
||||
# shellcheck disable=SC1090
|
||||
[ -f "$kc" ] && . "$kc" >/dev/null
|
||||
fi
|
||||
fi
|
||||
FRAME_HOST=${FRAME_HOST:-frame}
|
||||
FRAME_BOX=${FRAME_BOX:-dev}
|
||||
|
||||
# on_frame '<command>': run a shell command on the Frame host, in FRAME_REPO.
|
||||
on_frame() {
|
||||
if [ "$FRAME_LOCAL" = 1 ]; then
|
||||
(cd "$FRAME_REPO" && bash -c "$1")
|
||||
else
|
||||
ssh -o BatchMode=yes "$FRAME_HOST" "cd $(printf %q "$FRAME_REPO") && $1"
|
||||
fi
|
||||
}
|
||||
|
||||
# on_frame_script [args...] < script: run a bash script from stdin on the Frame host.
|
||||
on_frame_script() {
|
||||
if [ "$FRAME_LOCAL" = 1 ]; then
|
||||
bash -s -- "$@"
|
||||
else
|
||||
ssh -o BatchMode=yes "$FRAME_HOST" "bash -s -- $(printf '%q ' "$@")"
|
||||
fi
|
||||
}
|
||||
|
||||
# fill_template <file>: print a file with @REPO@ replaced by the Frame's repo path.
|
||||
fill_template() {
|
||||
sed "s|@REPO@|$FRAME_REPO|g" "$1"
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check that the Steam Frame is ready for these projects: reachable (from a PC), the
|
||||
# distrobox tool and the dev container present, and disk space. Works on the Frame too.
|
||||
set -uo pipefail
|
||||
|
||||
. "$(dirname "${BASH_SOURCE[0]}")/_env.sh"
|
||||
|
||||
fail=0
|
||||
check() {
|
||||
local label=$1; shift
|
||||
if out=$("$@" 2>&1); then
|
||||
printf 'ok %s%s\n' "$label" "${out:+: $out}"
|
||||
else
|
||||
printf 'FAIL %s%s\n' "$label" "${out:+: $out}"
|
||||
fail=1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$FRAME_LOCAL" = 1 ]; then
|
||||
echo "running on the Frame: $FRAME_REPO"
|
||||
else
|
||||
check "ssh key loaded" bash -c 'ssh-add -l | grep -c . | sed "s/$/ key(s)/"'
|
||||
check "ssh to $FRAME_HOST" ssh -o BatchMode=yes -o ConnectTimeout=8 "$FRAME_HOST" true
|
||||
if [ "$fail" = 1 ]; then
|
||||
echo "Skipping device checks. Is the headset on and awake, and on the network?"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
check "SteamOS" on_frame '. /etc/os-release; echo "$PRETTY_NAME $VERSION_ID build $BUILD_ID, $(uname -m)"'
|
||||
check "distrobox" on_frame 'test -x ~/.local/bin/distrobox && ~/.local/bin/distrobox version | head -1'
|
||||
check "container $FRAME_BOX" on_frame "podman ps -a --filter name=^$FRAME_BOX\$ --format '{{.Image}} {{.Status}}' | grep ."
|
||||
check "repo on the Frame" on_frame 'pwd'
|
||||
check "free space in ~" on_frame "df -h ~ | awk 'NR==2{print \$4\" free\"}'"
|
||||
exit "$fail"
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run a command on the Steam Frame, inside the "dev" distrobox by default.
|
||||
# On the Frame itself it runs locally in this checkout; from a PC it runs over SSH
|
||||
# in the synced copy (see scripts/_env.sh).
|
||||
# Usage: scripts/frame.sh [--host] [-C subdir] command [args...]
|
||||
# --host run on the SteamOS host instead of the container
|
||||
# -C subdir start in <repo>/<subdir> (default: the repo root)
|
||||
# The command is passed to a shell as one string, like ssh does.
|
||||
set -euo pipefail
|
||||
|
||||
. "$(dirname "${BASH_SOURCE[0]}")/_env.sh"
|
||||
|
||||
on_host=0
|
||||
sub=
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
--host) on_host=1; shift ;;
|
||||
-C) sub=$2; shift 2 ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
[ $# -gt 0 ] || { echo "usage: $0 [--host] [-C subdir] command [args...]" >&2; exit 2; }
|
||||
dir=$FRAME_REPO${sub:+/$sub}
|
||||
|
||||
# distrobox is called by its full path: ~/.bashrc on the Frame returns early for
|
||||
# non-interactive shells, so ~/.local/bin isn't on PATH. distrobox enter keeps the cwd.
|
||||
if [ "$FRAME_LOCAL" = 1 ]; then
|
||||
cd "$dir"
|
||||
if [ "$on_host" = 1 ]; then
|
||||
exec bash -c "$*"
|
||||
fi
|
||||
exec "$HOME/.local/bin/distrobox" enter "$FRAME_BOX" -- bash -lc "$*"
|
||||
fi
|
||||
|
||||
tty=()
|
||||
[ -t 0 ] && [ -t 1 ] && tty=(-t)
|
||||
if [ "$on_host" = 1 ]; then
|
||||
exec ssh "${tty[@]}" "$FRAME_HOST" "cd $(printf %q "$dir") && $*"
|
||||
else
|
||||
exec ssh "${tty[@]}" "$FRAME_HOST" \
|
||||
"cd $(printf %q "$dir") && ~/.local/bin/distrobox enter $(printf %q "$FRAME_BOX") -- bash -lc $(printf %q "$*")"
|
||||
fi
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# One-way sync of this repo from a PC to ~/dev/frametop on the Steam Frame.
|
||||
# Usage: scripts/sync.sh [extra rsync args, e.g. --dry-run]
|
||||
# Honors .gitignore files and skips .git (dirs, and the files submodules use), build outputs, and .env files.
|
||||
# --delete only removes files inside ~/dev/frametop on the headset.
|
||||
# On the Frame itself there's nothing to do: the checkout is used directly.
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
. "$root/scripts/_env.sh"
|
||||
if [ "$FRAME_LOCAL" = 1 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec rsync -az --delete --info=stats1 \
|
||||
--filter=':- .gitignore' \
|
||||
--exclude='.git' --exclude='target/' --exclude='build/' --exclude='.env' --exclude='.env.*' \
|
||||
"$@" "$root/" "$FRAME_HOST:${FRAME_REPO#/home/steamos/}/"
|
||||
Reference in new issue
Block a user