Repository navigation
feat: add floating PTT overlay button (closes #18) - #19
Merged
Merged
Conversation
Adds a small, frameless, always-on-top, draggable PTT button (GUI -> "Show PTT Overlay") that can be positioned over any other window - not just ZPTTLink's own. Requested for third-party PTT apps that have no VOX and only their own on-screen PTT button, so ZPTTLink's PTT can be triggered without switching focus away from that app. - OverlayControlServer (main.py): a loopback-only (127.0.0.1, never configurable elsewhere) TCP control channel started alongside the core, so a widget in the separate GUI process can trigger this process's PTTController. New "overlay" config block, --overlay-control / --overlay-control-port CLI flags. - PTTOverlayWindow + OverlaySocketClient (gui.py): the overlay widget itself. Left-click-hold to talk, right-click-drag to reposition (kept separate from the talk gesture so dragging never misfires a PTT), position persisted to config.json automatically, a small "x" to close. Closing mid-press still sends the release, so it can never leave PTT keyed. - Found and fixed a related pre-existing gap while wiring this up: the GUI's main PTT button only ever updated its own on-screen indicator - it never actually reached the running core process (GUI and core run as separate processes with no prior link between them). It now shares the same control channel as the overlay. - README: new Floating PTT Overlay Button section, Features bullet. - Version bump to 4.1.0. Verified with a real PySide6 install under an offscreen Qt platform (not available in the dev sandbox by default): OverlayControlServer protocol end-to-end (DOWN/UP, idempotency, shutdown safety net), the overlay widget's press/release/close-zone/drag/close-mid-press behavior against a real socket, and full MainWindow construction plus the overlay toggle button through the real widget tree. Claude-Session: https://claude.ai/code/session_01Wzg26kE95TKgW49ZuEYMBw
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #18 — a request for a transparent, positionable on-screen PTT button that can sit over any window (motivated by a third-party PTT app with no VOX, only its own on-screen PTT button).
OverlayControlServer(main.py): a loopback-only (127.0.0.1, never configurable elsewhere) TCP control channel started alongside the core process, so a widget living in the separate GUI process can trigger this process'sPTTController. Newoverlayconfig block,--overlay-control/--overlay-control-portCLI flags.PTTOverlayWindow+OverlaySocketClient(gui.py): the overlay itself — frameless, translucent, always-on-top. Left-click-hold to talk, right-click-drag to reposition (kept separate from the talk gesture on purpose, so dragging can never misfire a PTT), position persisted toconfig.jsonautomatically, a small "×" to close. Closing mid-press still sends the release so it can never leave PTT keyed.QProcess) with no prior link between them at all. It now shares the same control channel as the new overlay, so both buttons are equally real.Test plan
py_compileon all four changed Python filesOverlayControlServerprotocol exercised directly over a real socket: DOWN/UP toggling, idempotent duplicate DOWN, and the shutdown safety net (auto-releases PTT if the server stops mid-press)QT_QPA_PLATFORM=offscreen(not available in the dev sandbox by default) and exercisedPTTOverlayWindowend-to-end against a realOverlayControlServer: press/release triggers real core PTT, the close-zone click fireson_closewithout also triggering PTT, and closing the window mid-press still releases PTTMainWindowconstruction under the same offscreen setup, including toggling the overlay button through the real widget tree and the manual PTT button's send pathClaude-Session: https://claude.ai/code/session_01Wzg26kE95TKgW49ZuEYMBw