Skip to content

feat: add floating PTT overlay button (closes #18) - #19

Merged
maxhayim merged 1 commit into
mainfrom
feature/ptt-overlay-button
Sep 13, 2026
Merged

maxhayim merged 1 commit into
mainfrom
feature/ptt-overlay-button

Conversation

@maxhayim

Copy link
Copy Markdown
Owner

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's PTTController. New overlay config block, --overlay-control/--overlay-control-port CLI 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 to config.json automatically, a small "×" to close. Closing mid-press still sends the release so it can never leave PTT keyed.
  • Found and fixed an adjacent 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, since the GUI and core run as separate processes (the GUI launches the core via 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.
  • README: new Floating PTT Overlay Button section, a Features bullet.
  • Version bump to 4.1.0.

Test plan

  • py_compile on all four changed Python files
  • OverlayControlServer protocol 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)
  • Installed a real PySide6 under QT_QPA_PLATFORM=offscreen (not available in the dev sandbox by default) and exercised PTTOverlayWindow end-to-end against a real OverlayControlServer: press/release triggers real core PTT, the close-zone click fires on_close without also triggering PTT, and closing the window mid-press still releases PTT
  • Full MainWindow construction under the same offscreen setup, including toggling the overlay button through the real widget tree and the manual PTT button's send path
  • Not tested: a real on-screen display (no display in this environment) and the full end-to-end flow against a live Zello/third-party PTT app — flagging per the project's own "nothing tested on real hardware/live app" convention

Claude-Session: https://claude.ai/code/session_01Wzg26kE95TKgW49ZuEYMBw

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
@maxhayim
maxhayim merged commit ca2d09b into main Sep 13, 2026
6 of 24 checks passed
@maxhayim
maxhayim deleted the feature/ptt-overlay-button branch September 13, 2026 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

virtual button

1 participant