mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 10:00:11 +02:00
13198bc203f9bca83da16f705a952bebd2a85b9a
276
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
13198bc203 |
Pages: the hand recorder works without the colour module now
The known-issue notice becomes a fixed notice: the fix ( |
||
|
|
42a26753d3 |
Merge main into experimental: get.sh --branch and the hand recorder page
PR #29 was squash-merged, so main and experimental last shared history at |
||
|
|
0f0674ff36 |
Merge branch gaze-double-cal (the first calibration no longer runs twice) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
3a796b5013 |
Gaze: the first calibration no longer runs twice
Turning gaze mode on wakes our tracker, so its eyes come back just as the first calibration opens. DON_DELAY later, "the headset went on" re-armed the automatic calibration while it was still open, and when it ended, ft-eyes' status was still a moment old (not calibrated), so a second one opened at once. Seen live on 2026-10-05: 26 of 27 dots, then 27 more. The headset going on re-arms it only when no check is open. first-calibration-test.py now has the headset go on mid-calibration and checks that only one opens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
67a3c02e31 |
ft-camd: map a camera whose dark frames are all zeros
Through the ISP (no colour module), the near-black exposures come out
all zeros, identical every time, so their dequeues change no buffer and
ft-camd never finished learning the side cameras' buffers ("can't tell
which buffers are this camera's yet"): the side pair published nothing.
Such an index is now left unmapped and its frames counted as dark.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit
|
||
|
|
662919babf |
camcheck: no nested parentheses in the missing cameras' message
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit
|
||
|
|
98bd6ce21c |
Hand recorder: headsets without the colour module
Without the Arcturus module, XRService runs the side cameras through the
ISP ("ISP enabled for tracking cameras (main VFE available)"): NV12 on
vfe0 and vfe1, pitch 1152. ft-camd published only grey cameras, so it
dropped them, and the recorder stopped at "ft-camd publishes only 2 of 4
mono cameras" whatever was restarted.
- ft-camd reads a tracking camera's NV12 luma as its grey image.
- ft-hands and check_sides name the cameras by XRService's numbering in
its log (TrackingCameraInit index 0-3), not by capture pipe, which
moves with the module; a camera whose size isn't its calibration's is
left out. sides.json says which device each camera was.
- camcheck reports the camera map, the ISP routing and which cameras
ft-camd is missing; the recorder says so instead of "restart it",
restarts its own ft-camd once when that's the only problem, and keeps
the map in session.json.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit
|
||
|
|
608ad6034a |
get.sh: --branch NAME, to test a fix before it's released
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
336a60ce32 |
Pages: hand recorder needs the color module until the fix
Headsets without the Arcturus color passthrough module stop at the camera check (ft-camd publishes only 2 of 4 mono cameras). Say so on the install page, with the fix due by October 6. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
e1f27958ca | Merge remote-tracking branch 'origin/experimental' into experimental | ||
|
|
c969963b83 |
A one-command uninstaller that keeps the headset usable
uninstall.sh replaces the README's thirteen uninstall commands. Run from a Frametop desktop, those commands stopped the input relay second, which took the keyboard and mouse away before the rest could be typed. And deleting ~/frametop first left Launch a program -> Desktop pointing at a missing script. The script works in two steps. Step 1 stops Frametop from starting: the launcher entry, the user services (disabled, not stopped), the SteamVR driver, the menu entries, and the eye grabber and Bluetooth fixes under /etc (one sudo). Everything running keeps running until the headset restarts, and the script offers to restart it. Step 2 runs once none of Frametop's programs run. It deletes the code, and asks before deleting the settings, recordings, and the dev container. It doesn't use the rest of the repo, so the Pages one-liner works even when ~/frametop is gone. --dry-run shows each command without running it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
9f2ee5ad68 |
A one-command uninstaller that keeps the headset usable
uninstall.sh replaces the README's thirteen uninstall commands. Run from a Frametop desktop, those commands stopped the input relay second, which took the keyboard and mouse away before the rest could be typed. And deleting ~/frametop first left Launch a program -> Desktop pointing at a missing script. The script works in two steps. Step 1 stops Frametop from starting: the launcher entry, the user services (disabled, not stopped), the SteamVR driver, the menu entries, and the eye grabber and Bluetooth fixes under /etc (one sudo). Everything running keeps running until the headset restarts, and the script offers to restart it. Step 2 runs once none of Frametop's programs run. It deletes the code, and asks before deleting the settings, recordings, and the dev container. It doesn't use the rest of the repo, so the Pages one-liner works even when ~/frametop is gone. --dry-run shows each command without running it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
dfc8e6eb5f |
Merge branch fresh-install (our eye tracker's first calibration; SteamVR's tools from a terminal in the desktop; gaze in the report) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1037d4e125 |
Report: the gaze service, our eye tracker, and their logs
A gaze problem couldn't be told from a report: it had no gaze section. A user's report of 2026-10-05 showed only that the gaze service ran and our tracker was picked. The report now has a Gaze section: whether the gaze service and our tracker's frame grabber are enabled and running, when SteamVR's correction and our tracker's calibration were made (or "none"), and the service's status (ft-gazectl status, on one line: the tracker in use, whether it's awake and why not, checks.problem). Then the last 10 checks and calibration dots (checks.jsonl: each dot's reply and whether it was taken), the gaze service's last 60 lines without podman's exec lines, and the frame grabber's last 20. Nothing in them is an eye image. Tested on this Frame: each section fills in, and the status is one line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
307e2b7308 |
SteamVR's tools find SteamVR from a terminal in the Frametop desktop
The desktop has its own XDG_CONFIG_HOME (~/.config/frametop), and SteamVR's tools and OpenVR read their path registry from there. So from a terminal in the desktop: - pointer/driver/install.sh (install.sh step 4, every reinstall or update from Konsole) wrote a new registry, ~/.config/frametop/openvr/openvrpaths.vrpath, with only our driver and "runtime": null, and never registered the driver with SteamVR. That stray file then hid SteamVR from every OpenVR program started in the desktop. - scripts/update-check.py (and so doctor.sh and report.sh) reported OpenVR "can't connect to SteamVR as a background app" (VRInitError_Init_PathRegistryNotFound, or InstallationNotFound with the stray file) and "vrcmd --overlays lists no overlays". A user's report of 2026-10-05 showed both, with SteamVR and Frametop's services fine. - ft-layout's vrcmd calls (the gamescope backend) found no overlays. They now run with XDG_CONFIG_HOME=~/.config: the driver installer (install, uninstall, probe, aimhere), update-check.py (for all its checks: nothing there reads the desktop's own config), report.sh's vrpathreg show, and ft-layout's vrcmd. report.sh doesn't set it for the whole report, since session/fix-panels.py --check reads the desktop's Plasma config through it. The driver installer also removes the stray registry (only vrpathreg's, with no runtime), and update-check.py warns about one. And vrpathreg runs `xdg-open vrmonitor://driverinstalled` to tell SteamVR's desktop monitor, which the Frame doesn't have: in the desktop that showed "could not read file vrmonitor://driverinstalled" on every install. A stand-in xdg-open on its PATH takes it, so install.sh no longer filters the step's output. Tested in a fake HOME with a copy of SteamVR's registry, a stray one, and the desktop's XDG_CONFIG_HOME: the new installer removes the stray file, registers the driver in the copy, and never reaches xdg-open; the old one wrote the stray file, left the copy alone, and ran xdg-open. update-check.py from that environment: OpenVR and vrcmd ok (the old one fails both); its stray-registry warning fires on a seeded file. ft-layout's vrcmd: 119 overlays (was 0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
d39fbb9146 |
Gaze: our eye tracker can take its first calibration
A fresh install that chose our tracker (the installer's default since
|
||
|
|
7fe5d8c0dd |
Merge branch nested-atspi (PR #28: the desktop starts an accessibility (AT-SPI) registry, #27) into experimental
JakeGreen2145's PR plus our fix
|
||
|
|
6df6f97937 |
Session: AT-SPI watcher checks its buses every 5 seconds
Each check starts two gdbus processes (about 5.5 ms of CPU each on the Frame), so checking once a second cost about 1% of a core for as long as the desktop ran. On SteamOS 0.3.0 native activation fails, so the watcher always runs. A registry left behind now goes within 5 seconds instead of 1. design.md also says where the watcher matters: started from the VR launcher, the desktop runs in steam.service, which doesn't stop with it, so keep-apps.sh and the unit's stop don't clean up there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ca9492be00 |
Pages: link the Frametop Discord at the top and bottom of the hand recorder page
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
41b5b68a41 |
Pages: hand recorder install page
hand-recorder.md, served at deejanuz.github.io/frametop/hand-recorder.html: the Konsole commands to install, update and uninstall the Hand Recorder, who can take part, and what it needs. Frametop comes first for now, since the recorder runs in its desktop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
9d7c8a0b91 |
Experimental (#29)
* Input relay: typing with the pointer helper down no longer ends the relay Typing on a pass-through keyboard tells the helper "typing". With the helper not running (SteamVR off), that send raised ConnectionRefusedError and the relay exited, dropping every grab until systemd restarted it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ft-steam: open Steam's menu through Steam's own UI steam/ft-steam menu opens the SteamVR dashboard on Steam's menu, or closes the dashboard if it's up, without pointer mode: it asks Steam's UI over its debugging port to show its dashboard overlay (ShowVROverlay, what Steam calls itself) and focus the Steam frame's left menu (MenuStore.OpenMainMenu). ft-steam check says whether those calls still exist, and update-check.py runs it, since a Steam client update can rename them. The CDP client moves from display-settings/steam_settings.py to steam/steamui.py, so both use it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shortcuts: Steam menu, commands, and modifier taps Key combinations (and mouse and controller buttons) get two new actions: - steam_menu: Open Steam menu / close dashboard (steam/ft-steam menu). - command:CMD: run CMD with sh -c, as the relay's service, with layout/, float/ and steam/ on its PATH. Input Settings offers it for key combinations as Run a command... Both work without pointer mode. A modifier on its own is now a key combination too: a tap, pressed and released with no other key, mouse button, or scroll in between. A bound tap sends the desktop F24 before the release, so Plasma's launcher stays shut. The defaults gain a Meta tap for the Steam menu; this replaces META_DASHBOARD, which only worked in pointer mode. input/test/keys-test.py runs the relay against fake devices with every outgoing socket renamed, so it's safe next to the live relay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Relay: share a key combination's Meta release with frame-voice A Meta+key combination (Meta+J for gaze_left, say) hides Meta's release from the desktop, and the relay skipped share_key for it too. frame-voice saw Meta go down on @frametop_keys and never come up, so it held all dictated text back, waiting for that release. Keys of grabbed keyboards are now shared as pressed, before key_binding() decides what the desktop gets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hands: ft-cutouts, the hand cutouts without pinches and grips hands/ft-cutouts on|off|status starts ft-camd and ft-hands as transient user units with ft-hands' new --no-gestures: hands are published for ft-screens' cutouts, but no pinch or grip is detected, so nothing clicks or drags and a closing hand doesn't raise the tracking rate. It needs a build and ft-camd's capabilities, not hands/run.sh install. Its units conflict with ft-handsctl's, so each stops the other, and they stop with SteamVR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ft-cutouts status: only the current run's tracker lines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Gaze: say why gaze mode can't work yet, and open the calibration whenever it's missing Turning gaze mode on without a calibration opened Calibrate only on the off-to-on change, and only if it could open right then. With the headset off, the eye tracker silent, or the panel not built, or with gaze mode already on when the gaze service started, nothing opened and nothing said why: the pointer just stayed a mouse. - The gaze service now checks every second: gaze mode on, no calibration for the tracker in use, eyes seen -> the full calibration opens. One that closes unfinished opens again only after the headset comes off and on, gaze mode off and on, or Calibrate, so it doesn't loop. A start that fails retries every 10 s. - Its status says why gaze mode can't work yet (checks.problem): not calibrated and opening, open, closed unfinished, or can't open and why. - Input Settings shows that under the Gaze pointer switch, along with the gaze service not installed or not running and our tracker missing its frame grabber. - ft-gazectl on notes a missing calibration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Gaze: install our eye tracker, prefer it, and say why a calibration dot wasn't taken A user on a fresh install got "Calibration failed: only 0 of 21 dots" with no reason. The installer never installed our tracker, so gaze used SteamVR's, and the only way SteamVR's tracker rejects a dot is losing an eye for most of the look. The panel just showed a red ring. - install.sh: step 9/10 installs our tracker (gaze/tracker/install.sh) after gaze mode, yes by default; it needs sudo, so --yes runs it only when sudo won't prompt. If it fails, gaze keeps SteamVR's tracker. Configs that still say GAZE_TRACKER=steam (the old template) are asked whether to switch. - GAZE_TRACKER=auto, the new default: ours when it's installed (the frame grabber, its unit, and ft-eyes' Python), else SteamVR's. ft-gazed rechecks every second, so installing it switches over. Input Settings lists Own tracker first as recommended, and says how to install it when it's missing (checking the host's /etc through /run/host from the dev container). - The calibration panel has a note line, orange over the instructions: why a dot wasn't taken (an eye lost, a blink, the eyes disagreeing for SteamVR's tracker, from steady_samples' new drop counts; ft-eyes' reply for ours), what a click is still waiting for after 1.5 s, and a failed calibration's most common reason, which the Gaze page shows too. steady_samples keeps the same samples as before (checked on 2037 windows of recordings); a lost eye is named before a blink, since its openness reads 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * README: link the Frametop Discord Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Wait for a new container to finish setting up before entering it container-up.sh starts the dev container in a scope of its own, so distrobox enter finds it running and skips its wait for distrobox-init. On a fresh install, init was still setting up passwordless sudo when dev-container.sh ran sudo dnf install, and sudo asked for a password with no terminal to read it from. container-up.sh now waits for container_setup_done itself, and the container's sudo calls use -n, so a password prompt fails at once with a clear message. Fixes #9 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Prevent small desktop overlay pointer movements from starting a drag * Clear reported drag state on controller release * Click stability: only a hand controller's press starts it The 3D mouse drives SteamVR's laser through the ft_pointer virtual controller, so its events reach the screens the same way a controller's do. The filter held every press, which turned the mouse's short drags (selecting a character or two, nudging a slider) into clicks. Mark button events from hand controllers and start the filter only on those. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Input relay: retry a new device until udev gives it to the input group A new /dev/input node is root:root 0600 until udev applies GROUP=input. The scan probed each new node once and marked it seen even when the open failed, so a node caught in that gap was never opened. Behind a KVM, a switch brings back a hub of devices at once: on the Frame, four nodes failed with EACCES in one switch, the keyboard was never grabbed, and its keys went to gamescope instead of the desktop screens. A node that isn't readable yet now waits for the next scan. * Screens: take a screen's overlays from one copy in the catcher While a button pressed on a screen is held, UpdateCatcher checks every tick whether the laser is still on one of the screen's overlays. It built that list from s.All().begin() and s.All().end(), but All() returns a std::array by value: iterators into two different temporaries, which is undefined behaviour. A clang build of ft-screens got a garbage length, threw std::length_error, and aborted on the first click, taking KWin and the desktop with it. * Gaze: leave SteamVR's gaze action alone during VR games From curiousjtuber's PR #13: with the gaze service running, SteamVR restarted its eye tracker every 10 to 13 s of Beat Saber, as if the headset came off, and each restart took input focus from the game. The PR stopped every read in a game. Only the action path reaches SteamVR (UpdateActionState on the gaze set at overlay-global priority, then GetEyeTrackingDataRelativeToNow); the mmap and our tracker are read-only files. So only the action is skipped while a scene app runs, and gaze keeps moving the pointer over the dashboard in a game. The action source is only used with --source action. Co-Authored-By: CuriousJ <curious.j.tuber@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hands: --record-hz, and the hand recorder's design (hands/rec/DESIGN.md) ft-hands --record-hz N records at most N frame sets a second, for the hand recorder (10). DESIGN.md lays out the recorder: the headset panel, the session runner and its script, the files, review and export, consent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hands: ft-handpanel, the hand recorder's headset panel A head-locked SteamVR overlay for the hand recorder (hands/rec/DESIGN.md): 1.2 m ahead, 12 degrees up, 36 degrees wide, drawn with stb_truetype into three shared DMA-BUFs as ft-gazepanel does. It shows the title, step, wrapped instruction, note, countdown, hand chips, near/far bar and a "Paused" cover, driven over @ft_handpanel. It also places the touch target, a 2 cm dot in its own overlay fixed in the room where the head was at the first command for that point, and logs head and controller poses to poses.jsonl at 250 Hz from a thread of its own. Both threads take one lock around OpenVR calls. --no-vr prints each picture's state to stdout (and --dump writes the pictures), for testing without a headset. hands/rec/build.sh builds it in the dev container. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hands: the recorder's worn check goes by the panel's backlight, as frame-job does Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hands: the hand recorder's session runner and guided script hands/rec/session.py runs a recording session from script.json: it starts ft-camd and a tracking ft-hands as transient units only if they aren't running, records each section as one take (ft-hands --record-only at 10 sets/s, a new sets-N.bin after each pause), drives ft-handpanel, and writes session.json, calibration.json (identifying fields removed), prompts.jsonl and take.json. Feedback comes from the live hands file and, in the controller sections, from the panel's device poll. It also runs from the command line (--dry-run, --speed, --ring, --no-start). hands/rec/script.json: 11 sections, about 9 minutes without the object and controller sections. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hands: the hand recorder's window, review and export hands/rec/ft_handrec.py + main.qml (Kirigami, dev container; host launcher hands/rec/ft-handrec): consent (CONSENT.md, asked again when its version changes; profile.json with a random contributor id), the before-you-start checklist with the lighting and free-space checks, the session controls (Space pauses, Esc stops), review with a frame-set viewer that deletes ranges, takes and sessions, export with progress and cancel (warns while the headset is worn), and the upload page (UPLOAD.md, the huggingface-cli command; HF_DATASET is a placeholder). --dry-run runs sessions without processes, for testing. hands/rec/takes.py (standard library): indexes sets.bin and sets-N.bin without reading pixels, reads one set's cameras, keeps deleted ranges in take.json, and exports: deleted sets left out, zstd -10 -T2 at nice 19, manifest.json and SHA256SUMS, nothing left behind on cancel. CONSENT.md and UPLOAD.md are drafts pending a legal review; the window says contributions aren't open yet. The dev container gains zstd. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hands: upload from the hand recorder's window, export checks, a rehearsal hands/rec/validate.py (standard library; Linux and Windows, Python 3.12+) checks an export before upload and when it's received: SHA256SUMS, an allow-list of files, the manifest's schema and keys, the consent version, a uuid4 contributor, no identifying fields in calibration.json or device.json, every sets.bin.zst decompressed to its end as a stream with each FHSET01 header checked against the manifest, jsonl lines, the total size. It decompresses with compression.zstd, zstandard or the zstd program. validate.py DIR [--json]. hands/rec/hub.py uploads an export with huggingface_hub, as a pull request to contributions/<contributor>/<session>: validate first, refuse a repeat of the same export, check the login (whoami) and access (auth_check), upload_folder(create_pr=True) with the manifest summary as the description, then record the PR under "uploads" in session.json. Errors are explained (terms not accepted, not found, 401/403, network). --dry-run makes no network calls. FT_HANDREC_DATASET overrides HF_DATASET (DeeJanuz/frametop-hands); while the texts are drafts a real upload needs FT_HANDREC_ALLOW_UPLOAD=1. The Upload page shows the login with "Check again" and how to run hf auth login in a terminal (the token never enters the window), then Upload with a phase, progress and Cancel (hub.py as a child process), the PR link, and a warning for an export uploaded before. The manual command stays as the fallback. ft-handrec --hub-dry-run. session.py also saves device.json: cv.cad_from_cal and head from /persist/device_config.json, the labeller's shape, nothing identifying; export copies it. Session ids with a -N suffix are accepted everywhere. hands/rec/rehearse.sh runs it all without the headset: ft-ringplay plays 30 s of a capture into a ring, session.py records a short test script with ft-handpanel --no-vr and a tracker, then export, validate and a dry-run upload (--repo ID uploads for real). It runs in one frame-job scope, deletes its data and stops its processes, also on Ctrl+C. hands/rec/tests/test_validate.py covers good and broken exports and hub.py without the network. The dev container gains python3-huggingface-hub. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * README: Frametop doesn't work on the SteamOS beta yet Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit |
||
|
|
5e3323c188 | [verified] merge experimental into nested AT-SPI fix | ||
|
|
25504e0ed4 | [verified] fix(session): start nested AT-SPI registry | ||
|
|
ec870d2d7a |
Merge branch laser-release (release a held button that can't come up on a screen: the game kept losing its controllers) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
80797c98b9 |
Screens: release a held button that can't come up on a screen
Pausing, or hiding the screen a button went down on, took the laser off
it mid-click; the pause gesture's second thumbstick click does that.
SteamVR's laser mouse then forgot the button ("Mouse down count is 1 but
states are all false"), no release came, and the catcher kept showing
whenever the pressing laser was off the panels, even while paused. Being
interactive, it kept the VR game's controllers from it until the
desktop restarted (2026-10-04, Beat Saber).
ft-screens now releases a held button when it's paused, when the screen
it went down on is hidden, or, during VR games, when the pressing hand
controller has held nothing for a second. GetControllerState answers
overlay apps only while a game runs; outside games a hold is never cut.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
2fadbbe148 |
Merge branch orphan-panel (bring back a taskbar saved on a screen the desktop doesn't have, #18) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5ee07f99a8 |
Merge branch menu-entry-programs (Hide/Show Screens no longer launches Reset Screen Layout) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f0b93b79d3 |
Menu entries: own programs for Reset Screen Layout and Hide/Show Screens
Reset Screen Layout and Hide/Show Screens both ran ft-layout. Steam lists entries by program, so Hide/Show launched Reset. Each gets a wrapper. From PR #17 (only this part of 9618be8; its host_command change is for the Nix packages). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
13a530d829 |
Merge branch mute-key (PR #24: the mute key toggles the default output's mute) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f260a6a9e4 |
Merge branch lazy-susan (PR #22: Meta+Alt+Tab spins the panels around you) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2e09cf9efe |
Merge PR #24 (SuperTuxii: the mute key toggles the default output's mute) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
9a4b66ff50 |
keys-test: the spin bindings (Meta+Alt+Tab, Meta+Alt+Shift+Tab), not while paused
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
17269134ce |
Merge PR #22 (ehippy: lazy susan, Meta+Alt+Tab spins the panels around you) into experimental
Conflicts with experimental's pause_toggle, steam_menu and command: actions and its AnnounceOverlay: both kept. The spin bindings join the Meta tap in the defaults, spinning doesn't need pointer mode, and like other actions it does nothing while Frametop is paused. AnnounceOverlay now sends through the PR's SendPointer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
d995b815f8 |
Session: bring back a taskbar saved on a screen the desktop doesn't have
Plasma 6.2.5 keeps a panel on a screen number and never moves one whose number is past the screen count, so a taskbar saved on a spare output (#18, lastScreen=8 with three screens) or on a screen a smaller layout dropped stayed hidden. Before Plasma starts, session/fix-panels.py moves such a panel and its tray's containment to screen 0 (the primary), keeping its widgets, unless screen 0 already has a panel on that edge. doctor.sh checks the panels' screens, and report.sh lists them with the live outputs and panels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f18918f781 |
input-relay: Add mute key as volume key
Add KEY_MUTE as volume key. It will be mapped to KEY_MACRO28 and use wpctl to toggle the mute of the default audio sink. The toggle of the mute state will be done once when the key is pressed instead of continuously toggling it when it is held down. This allows the mute button on keyboards to work properly. Signed-off-by: SuperTuxii <123881249+SuperTuxii@users.noreply.github.com> |
||
|
|
e0208687b6 |
Merge branch tip-in-games (controller laser tip found during VR games) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c699e13104 |
Screens: find the controllers' laser tip during VR games too
GetComponentStateForDevicePath with no input source handle fails for every render model component while a VR game runs (checked 2026-10-03 with a game up: all 21 components of frame_controller_right). TipOffset then fell back to the controller's pose, which aims 40 degrees above the Frame controller's laser. In games, pointing at a screen's middle missed it and pointing below it hit, so the new aim-to-laser only worked from the bottom; the controls' reveal and pin/roll aim were off the same way. GetComponentState still answers then, with the same tip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
9b12b7d74e |
Merge branch aim-lasers (in games, pointing a controller at a Frametop panel turns its laser on) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c7c7c1f772 |
Screens: in games, pointing a controller at a panel turns its laser on
SteamVR's own floating windows take the laser while a controller points at them in a game and give it back when it points away. Frametop's panels didn't: with the controllers left to the game (outside_games, the default, or dashboard), they couldn't be clicked without the dashboard. ft-screens now sets MakeOverlaysInteractiveIfVisible on a screen or floating window while a hand controller's laser pose meets it, its controls, or its popups (UpdateAim; curved screens hit on their cylinder), and clears it 0.3 s after the aim leaves a wider margin. A drag or a held button keeps it on. The keyboard, one overlay, uses ComputeOverlayIntersection and now follows the mode when a game starts or ends while it's open. This replaces the reset button's own aim zone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2486a601e3 |
Merge branch click-threshold (controller click zone 32 px by default) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
de25633f87 |
Click stability: 32 logical pixels by default, not 8
8 is about 0.2 degrees on a 3.4 m wide 3440-pixel screen 2 m away, so a trigger press turned into a drag unless the hand was very still. 32 (about 0.9 degrees) felt much better in the headset (2026-10-03). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
53a1836dbb |
Merge branch reset-button (a reset button next to each screen's grab bar, clickable in VR games) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
73bd0ea28f |
Screens: a reset button next to the grab bar, clickable in VR games
Each desktop screen gets a reset button left of its bar (a reticle). It puts every screen back in its layout around where you are now, like Meta+Shift+R (ft-layout apply). In a VR game the screens leave the controllers to the game (the outside_games and dashboard modes), so a controller couldn't click any of their controls. Aiming a hand controller at the reset button now sets MakeOverlaysInteractiveIfVisible on that button's overlay alone, so the trigger clicks it; the flag clears half a second after the aim leaves a zone twice as wide, and the game gets the controllers back. The aim comes from the laser poses ft-screens already reads to show the controls. The ft-layout spawn is now RunLayout(cmd), shared with the arrange. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
519c623ea9 |
Merge branch perf (dynamic per-screen frame rates, idle pointer, remote on demand, lighter gaze) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8b1327fe1a |
Merge branch hand-recorder (the hand dataset recorder) into experimental
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2351cec310 |
hand recorder: final consent text (2026-10-03), residency check, installer
Consent 2026-10-03, after a non-lawyer review: who runs this and how to reach them, the dataset is public (Hugging Face, possibly abroad), the Hugging Face username shows next to the contributor id, purposes (no identification), safety, the maintainer grant passes to whoever maintains Frametop next, withdrawal before and after merge, rights such as the GDPR's, and what a new version means. Residents of Illinois, Texas and Washington can't take part for now (biometric privacy laws): a third checkbox, profile consent.region_ok, checked by validate.py from this consent version on. The DRAFT banners are gone, so uploads no longer need FT_HANDREC_ALLOW_UPLOAD. hands/rec/install.sh installs the recorder on a Frame with Frametop: container packages, hand tracking and panel builds, ft-camd's capabilities, menu entry. test_qml_backend also checks each call's argument count against the slots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1eb120e6b1 |
hand recorder export: no controller poses without controllers, nothing in deleted ranges
When the checklist says no controllers, exported poses.jsonl has left and right null and feedback lines carry no controller state: controllers left switched on still get tracked (one wandered 2 m in a real session) and would read as the hands' ground truth. Poses and live-tracker feedback inside deleted ranges are left out too, as the images there are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8321a99121 |
hand recorder: take.json keeps camera clock samples
sets.bin's capture_ns is CLOCK_MONOTONIC_RAW; poses.jsonl and prompts.jsonl are CLOCK_MONOTONIC. On 2026-10-03 the two were 0.80 s apart during a session and 1.11 s apart five hours later, so images can't be paired with poses by capture_ns. take.json now samples RAW minus MONOTONIC as each recording part starts and stops (as ft-hands' raw_minus_mono_ns), so readers can put each exposure on the poses' clock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ea483f7ce3 |
hand recorder: log in from the Upload page, three-step page, no terminal
The Upload page is now three numbered steps: choose the export, log in to Hugging Face, upload. Log in runs hub.py login, huggingface_hub's browser login (OAuth device code, as hf auth login does): the link opens in the browser and the page shows the code to enter, with Copy code and Cancel. hub.py saves the token; the window never sees one, and nobody pastes one. The terminal upload and the login command are gone from the page, and UPLOAD.md is now a short 'About uploading' under the steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
e62ebb8669 |
hand recorder: login command works from Frametop's Konsole
Frametop's Konsole sets XDG_RUNTIME_DIR=/run/user/UID/frametop, where podman finds no container state, so 'distrobox enter dev -- hf auth login' failed with a crun error. The command the Upload page shows now sets the real runtime folder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |