Add poppable applets — float/dock with persistent geometry#916
Merged
Conversation
Each applet in the AppletPanel can now be detached into its own floating
window and re-docked at any time. Position and size persist across sessions
and survive dock/undock cycles.
## What's new
**FloatingAppletWindow** (new class, src/gui/FloatingAppletWindow.h/.cpp)
- Qt::Window | Qt::Tool widget hosting a single detached applet
- Custom title bar with "↩ Dock" button; closing the window re-docks
rather than losing the applet
- Geometry saved to AppSettings using screen name + screen-relative
coordinates (more resilient than QWidget::saveGeometry() binary blob):
FloatingApplet_<ID>_Screen — screen name, stable across reboots
FloatingApplet_<ID>_X/Y — screen-relative position
FloatingApplet_<ID>_W/H — window size
- 400 ms debounce timer saves geometry on every resize/move without
hammering AppSettings on each pixel
- Explicit save on dock and on app shutdown (main-window close path)
- Wayland guard: position restore is skipped on Wayland compositors that
own window placement; size is always restored
- Off-screen clamp: if the saved monitor is disconnected, the window is
clamped to the nearest available screen geometry
**AppletPanel changes**
- AppletEntry gains a `floating` bool
- floatApplet(id): reparents applet widget into FloatingAppletWindow,
hides panel wrapper, persists IsFloating = True
- dockApplet(id): reparents applet widget back into wrapper,
destroys floating window, persists IsFloating = False
- isAppletFloating(id): public helper used by AppletTitleBar context menu
- AppletTitleBar: right-click context menu ("Pop out" / "↩ Dock") using
QMenu::popup() — no nested event loop
- Toggle button while floating: raises/hides the floating window instead
of the docked wrapper
- Floating state restored at startup via QTimer::singleShot(0) so the
window system is ready before windows are shown
- setTunerVisible(false), setAmpVisible(false), setAgVisible(false) each
call dockApplet() first to prevent orphaned floating windows when a
conditional device (TGXL, amp, Antenna Genius) disconnects
- FloatingAppletWindow created with AppletPanel as Qt parent so Qt's
shouldQuit() correctly ignores tool windows when the last real window
closes — fixes app not exiting when floating windows were open
- show() before restoreGeometry() (with 50 ms singleShot delay) so the
window manager maps the window before position hints are applied
**CMakeLists.txt**
- Added src/gui/FloatingAppletWindow.cpp to GUI_SOURCES
## Cross-platform notes
- Windows / macOS / Linux X11: full position + size persistence
- Linux Wayland / WSL2 (WSLg): size persists; position is compositor-
controlled. Use QT_QPA_PLATFORM=xcb on WSL2 for full behaviour via
XWayland.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AetherClaude
added a commit
to AetherClaude/AetherSDR
that referenced
this pull request
Apr 7, 2026
Right-click a panadapter title bar or click the arrow button to pop out a panadapter into its own floating window. Dock returns it to the PanadapterStack splitter at its original position. - Add popOutRequested/dockRequested signals and pop-out button to PanadapterApplet title bar with context menu support - Add floatPanadapter/dockPanadapter/dockAll methods to PanadapterStack using FloatingAppletWindow (reused from PR aethersdr#916) - Auto-dock all floating pans before layout rearrange or pan removal - Persist float state per-pan via AppSettings; restore on reconnect - Splitter re-insertion tracks original index for correct dock position Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
10 tasks
boydsoftprez
pushed a commit
to boydsoftprez/AetherSDR
that referenced
this pull request
Apr 7, 2026
…#916) Each applet in the AppletPanel can now be detached into its own floating window and re-docked at any time. Position and size persist across sessions and survive dock/undock cycles. ## What's new **FloatingAppletWindow** (new class, src/gui/FloatingAppletWindow.h/.cpp) - Qt::Window | Qt::Tool widget hosting a single detached applet - Custom title bar with "↩ Dock" button; closing the window re-docks rather than losing the applet - Geometry saved to AppSettings using screen name + screen-relative coordinates (more resilient than QWidget::saveGeometry() binary blob): FloatingApplet_<ID>_Screen — screen name, stable across reboots FloatingApplet_<ID>_X/Y — screen-relative position FloatingApplet_<ID>_W/H — window size - 400 ms debounce timer saves geometry on every resize/move without hammering AppSettings on each pixel - Explicit save on dock and on app shutdown (main-window close path) - Wayland guard: position restore is skipped on Wayland compositors that own window placement; size is always restored - Off-screen clamp: if the saved monitor is disconnected, the window is clamped to the nearest available screen geometry **AppletPanel changes** - AppletEntry gains a `floating` bool - floatApplet(id): reparents applet widget into FloatingAppletWindow, hides panel wrapper, persists IsFloating = True - dockApplet(id): reparents applet widget back into wrapper, destroys floating window, persists IsFloating = False - isAppletFloating(id): public helper used by AppletTitleBar context menu - AppletTitleBar: right-click context menu ("Pop out" / "↩ Dock") using QMenu::popup() — no nested event loop - Toggle button while floating: raises/hides the floating window instead of the docked wrapper - Floating state restored at startup via QTimer::singleShot(0) so the window system is ready before windows are shown - setTunerVisible(false), setAmpVisible(false), setAgVisible(false) each call dockApplet() first to prevent orphaned floating windows when a conditional device (TGXL, amp, Antenna Genius) disconnects - FloatingAppletWindow created with AppletPanel as Qt parent so Qt's shouldQuit() correctly ignores tool windows when the last real window closes — fixes app not exiting when floating windows were open - show() before restoreGeometry() (with 50 ms singleShot delay) so the window manager maps the window before position hints are applied **CMakeLists.txt** - Added src/gui/FloatingAppletWindow.cpp to GUI_SOURCES ## Cross-platform notes - Windows / macOS / Linux X11: full position + size persistence - Linux Wayland / WSL2 (WSLg): size persists; position is compositor- controlled. Use QT_QPA_PLATFORM=xcb on WSL2 for full behaviour via XWayland. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
chibondking
added a commit
to chibondking/AetherSDR
that referenced
this pull request
Apr 10, 2026
The S-Meter section can now be detached into a floating window and re-docked exactly like all other applets — using the same FloatingAppletWindow infrastructure, AppSettings geometry persistence, and PR aethersdr#916 / aethersdr#985 bug fixes (drift, WM centering, shutdown race). ## What changed ### src/gui/AppletPanel.h - Added `QWidget* m_sMeterContent` — the floatable content container (SMeterWidget + TX/RX select row + Peak Hold row), analogous to the applet widget held at layout index 1 in every other wrapper. - Added private `floatSMeter()` and `dockSMeter()` methods. ### src/gui/AppletPanel.cpp **S-Meter construction:** - `AppletTitleBar("S-Meter", "VU", this)` — passes the panel pointer so the right-click context menu ("⬈ Pop out" / "↩ Dock") is active. - Introduced `m_sMeterContent` QWidget with its own QVBoxLayout as layout index 1 of `m_sMeterSection` (after the title bar), so the extractor logic in `floatSMeter()` / `dockSMeter()` is identical to every other applet. **ANLG toggle button:** - Updated to the float-aware pattern used by TUN / AMP / AG: raises/hides the floating window when VU is floating, re-floats via `QTimer::singleShot(0)` when IsFloating is persisted but no window is open yet (toggle-off → toggle-on cycle fix from aethersdr#985). **`isAppletFloating()`:** - Added early return for `"VU"`: checks `m_floatingWindows.contains("VU")` directly (VU is not in `m_appletOrder`). **`floatApplet()` / `dockApplet()`:** - Added `if (id == "VU")` dispatch at the top of each, delegating to `floatSMeter()` / `dockSMeter()`. **`floatSMeter()` / `dockSMeter()`:** - Mirror `floatApplet()` / `dockApplet()` exactly: reparent content out of/back into `m_sMeterSection`, create/destroy `FloatingAppletWindow`, persist `FloatingApplet_VU_IsFloating`, save geometry on dock. **Startup restore:** - After the existing `m_appletOrder` restore loop, added a `QTimer::singleShot(0)` restore for `"VU"` so the S-Meter reopens floating if it was floating when the app last closed. Closes aethersdr#993 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chibondking
added a commit
to chibondking/AetherSDR
that referenced
this pull request
Apr 11, 2026
The S-Meter section can now be detached into a floating window and re-docked exactly like all other applets — using the same FloatingAppletWindow infrastructure, AppSettings geometry persistence, and PR aethersdr#916 / aethersdr#985 bug fixes (drift, WM centering, shutdown race). ## What changed ### src/gui/AppletPanel.h - Added `QWidget* m_sMeterContent` — the floatable content container (SMeterWidget + TX/RX select row + Peak Hold row), analogous to the applet widget held at layout index 1 in every other wrapper. - Added private `floatSMeter()` and `dockSMeter()` methods. ### src/gui/AppletPanel.cpp **S-Meter construction:** - `AppletTitleBar("S-Meter", "VU", this)` — passes the panel pointer so the right-click context menu ("⬈ Pop out" / "↩ Dock") is active. - Introduced `m_sMeterContent` QWidget with its own QVBoxLayout as layout index 1 of `m_sMeterSection` (after the title bar), so the extractor logic in `floatSMeter()` / `dockSMeter()` is identical to every other applet. **ANLG toggle button:** - Updated to the float-aware pattern used by TUN / AMP / AG: raises/hides the floating window when VU is floating, re-floats via `QTimer::singleShot(0)` when IsFloating is persisted but no window is open yet (toggle-off → toggle-on cycle fix from aethersdr#985). **`isAppletFloating()`:** - Added early return for `"VU"`: checks `m_floatingWindows.contains("VU")` directly (VU is not in `m_appletOrder`). **`floatApplet()` / `dockApplet()`:** - Added `if (id == "VU")` dispatch at the top of each, delegating to `floatSMeter()` / `dockSMeter()`. **`floatSMeter()` / `dockSMeter()`:** - Mirror `floatApplet()` / `dockApplet()` exactly: reparent content out of/back into `m_sMeterSection`, create/destroy `FloatingAppletWindow`, persist `FloatingApplet_VU_IsFloating`, save geometry on dock. **Startup restore:** - After the existing `m_appletOrder` restore loop, added a `QTimer::singleShot(0)` restore for `"VU"` so the S-Meter reopens floating if it was floating when the app last closed. **dockSMeter() — use m_sMeterContent directly (agent review fix)** The original used a fragile layout-walk to recover m_sMeterContent from FloatingAppletWindow's internal layout. If any itemAt() returned null, appletWidget would be null while the code still called win->deleteLater(), destroying m_sMeterContent and all its children (m_sMeter, m_txSelect, m_rxSelect, peak-hold widgets) — crash on next signal-level update. Fix: use the named member directly. Reparent m_sMeterContent into m_sMeterSection before deleteLater() so Qt's parent-chain destruction cannot reach it. **.gitignore — drop Visual Studio artifacts (agent review fix)** /.vs and /out/install/x64-Debug are Windows VS IDE artifacts; they belong in ~/.gitignore_global, not the project-wide .gitignore. Closes aethersdr#993 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chibondking
added a commit
to chibondking/AetherSDR
that referenced
this pull request
Apr 11, 2026
The S-Meter section can now be detached into a floating window and re-docked exactly like all other applets — using the same FloatingAppletWindow infrastructure, AppSettings geometry persistence, and PR aethersdr#916 / aethersdr#985 bug fixes (drift, WM centering, shutdown race). ## What changed ### src/gui/AppletPanel.h - Added `QWidget* m_sMeterContent` — the floatable content container (SMeterWidget + TX/RX select row + Peak Hold row), analogous to the applet widget held at layout index 1 in every other wrapper. - Added private `floatSMeter()` and `dockSMeter()` methods. ### src/gui/AppletPanel.cpp **S-Meter construction:** - `AppletTitleBar("S-Meter", "VU", this)` — passes the panel pointer so the right-click context menu ("⬈ Pop out" / "↩ Dock") is active. - Introduced `m_sMeterContent` QWidget with its own QVBoxLayout as layout index 1 of `m_sMeterSection` (after the title bar), so the extractor logic in `floatSMeter()` / `dockSMeter()` is identical to every other applet. **ANLG toggle button:** - Updated to the float-aware pattern used by TUN / AMP / AG: raises/hides the floating window when VU is floating, re-floats via `QTimer::singleShot(0)` when IsFloating is persisted but no window is open yet (toggle-off → toggle-on cycle fix from aethersdr#985). **`isAppletFloating()`:** - Added early return for `"VU"`: checks `m_floatingWindows.contains("VU")` directly (VU is not in `m_appletOrder`). **`floatApplet()` / `dockApplet()`:** - Added `if (id == "VU")` dispatch at the top of each, delegating to `floatSMeter()` / `dockSMeter()`. **`floatSMeter()` / `dockSMeter()`:** - Mirror `floatApplet()` / `dockApplet()` exactly: reparent content out of/back into `m_sMeterSection`, create/destroy `FloatingAppletWindow`, persist `FloatingApplet_VU_IsFloating`, save geometry on dock. **Startup restore:** - After the existing `m_appletOrder` restore loop, added a `QTimer::singleShot(0)` restore for `"VU"` so the S-Meter reopens floating if it was floating when the app last closed. **dockSMeter() — use m_sMeterContent directly (agent review fix)** The original used a fragile layout-walk to recover m_sMeterContent from FloatingAppletWindow's internal layout. If any itemAt() returned null, appletWidget would be null while the code still called win->deleteLater(), destroying m_sMeterContent and all its children (m_sMeter, m_txSelect, m_rxSelect, peak-hold widgets) — crash on next signal-level update. Fix: use the named member directly. Reparent m_sMeterContent into m_sMeterSection before deleteLater() so Qt's parent-chain destruction cannot reach it. **.gitignore — drop Visual Studio artifacts (agent review fix)** /.vs and /out/install/x64-Debug are Windows VS IDE artifacts; they belong in ~/.gitignore_global, not the project-wide .gitignore. Closes aethersdr#993 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ten9876
pushed a commit
that referenced
this pull request
Apr 11, 2026
* Updated for vscode and visual studio ignore patterns for local windows development. * Add pop-out/pop-in support for the S-Meter (VU) applet (#993) The S-Meter section can now be detached into a floating window and re-docked exactly like all other applets — using the same FloatingAppletWindow infrastructure, AppSettings geometry persistence, and PR #916 / #985 bug fixes (drift, WM centering, shutdown race). ## What changed ### src/gui/AppletPanel.h - Added `QWidget* m_sMeterContent` — the floatable content container (SMeterWidget + TX/RX select row + Peak Hold row), analogous to the applet widget held at layout index 1 in every other wrapper. - Added private `floatSMeter()` and `dockSMeter()` methods. ### src/gui/AppletPanel.cpp **S-Meter construction:** - `AppletTitleBar("S-Meter", "VU", this)` — passes the panel pointer so the right-click context menu ("⬈ Pop out" / "↩ Dock") is active. - Introduced `m_sMeterContent` QWidget with its own QVBoxLayout as layout index 1 of `m_sMeterSection` (after the title bar), so the extractor logic in `floatSMeter()` / `dockSMeter()` is identical to every other applet. **ANLG toggle button:** - Updated to the float-aware pattern used by TUN / AMP / AG: raises/hides the floating window when VU is floating, re-floats via `QTimer::singleShot(0)` when IsFloating is persisted but no window is open yet (toggle-off → toggle-on cycle fix from #985). **`isAppletFloating()`:** - Added early return for `"VU"`: checks `m_floatingWindows.contains("VU")` directly (VU is not in `m_appletOrder`). **`floatApplet()` / `dockApplet()`:** - Added `if (id == "VU")` dispatch at the top of each, delegating to `floatSMeter()` / `dockSMeter()`. **`floatSMeter()` / `dockSMeter()`:** - Mirror `floatApplet()` / `dockApplet()` exactly: reparent content out of/back into `m_sMeterSection`, create/destroy `FloatingAppletWindow`, persist `FloatingApplet_VU_IsFloating`, save geometry on dock. **Startup restore:** - After the existing `m_appletOrder` restore loop, added a `QTimer::singleShot(0)` restore for `"VU"` so the S-Meter reopens floating if it was floating when the app last closed. Closes #993 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add pop-out/pop-in support for the S-Meter (VU) applet (#993) The S-Meter section can now be detached into a floating window and re-docked exactly like all other applets — using the same FloatingAppletWindow infrastructure, AppSettings geometry persistence, and PR #916 / #985 bug fixes (drift, WM centering, shutdown race). ## What changed ### src/gui/AppletPanel.h - Added `QWidget* m_sMeterContent` — the floatable content container (SMeterWidget + TX/RX select row + Peak Hold row), analogous to the applet widget held at layout index 1 in every other wrapper. - Added private `floatSMeter()` and `dockSMeter()` methods. ### src/gui/AppletPanel.cpp **S-Meter construction:** - `AppletTitleBar("S-Meter", "VU", this)` — passes the panel pointer so the right-click context menu ("⬈ Pop out" / "↩ Dock") is active. - Introduced `m_sMeterContent` QWidget with its own QVBoxLayout as layout index 1 of `m_sMeterSection` (after the title bar), so the extractor logic in `floatSMeter()` / `dockSMeter()` is identical to every other applet. **ANLG toggle button:** - Updated to the float-aware pattern used by TUN / AMP / AG: raises/hides the floating window when VU is floating, re-floats via `QTimer::singleShot(0)` when IsFloating is persisted but no window is open yet (toggle-off → toggle-on cycle fix from #985). **`isAppletFloating()`:** - Added early return for `"VU"`: checks `m_floatingWindows.contains("VU")` directly (VU is not in `m_appletOrder`). **`floatApplet()` / `dockApplet()`:** - Added `if (id == "VU")` dispatch at the top of each, delegating to `floatSMeter()` / `dockSMeter()`. **`floatSMeter()` / `dockSMeter()`:** - Mirror `floatApplet()` / `dockApplet()` exactly: reparent content out of/back into `m_sMeterSection`, create/destroy `FloatingAppletWindow`, persist `FloatingApplet_VU_IsFloating`, save geometry on dock. **Startup restore:** - After the existing `m_appletOrder` restore loop, added a `QTimer::singleShot(0)` restore for `"VU"` so the S-Meter reopens floating if it was floating when the app last closed. **dockSMeter() — use m_sMeterContent directly (agent review fix)** The original used a fragile layout-walk to recover m_sMeterContent from FloatingAppletWindow's internal layout. If any itemAt() returned null, appletWidget would be null while the code still called win->deleteLater(), destroying m_sMeterContent and all its children (m_sMeter, m_txSelect, m_rxSelect, peak-hold widgets) — crash on next signal-level update. Fix: use the named member directly. Reparent m_sMeterContent into m_sMeterSection before deleteLater() so Qt's parent-chain destruction cannot reach it. **.gitignore — drop Visual Studio artifacts (agent review fix)** /.vs and /out/install/x64-Debug are Windows VS IDE artifacts; they belong in ~/.gitignore_global, not the project-wide .gitignore. Closes #993 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add pop-out/pop-in support for the S-Meter (VU) applet (#993) The S-Meter section can now be detached into a floating window and re-docked exactly like all other applets — using the same FloatingAppletWindow infrastructure, AppSettings geometry persistence, and PR #916 / #985 bug fixes (drift, WM centering, shutdown race). ## What changed ### src/gui/AppletPanel.h - Added `QWidget* m_sMeterContent` — the floatable content container (SMeterWidget + TX/RX select row + Peak Hold row), analogous to the applet widget held at layout index 1 in every other wrapper. - Added private `floatSMeter()` and `dockSMeter()` methods. ### src/gui/AppletPanel.cpp **S-Meter construction:** - `AppletTitleBar("S-Meter", "VU", this)` — passes the panel pointer so the right-click context menu ("⬈ Pop out" / "↩ Dock") is active. - Introduced `m_sMeterContent` QWidget with its own QVBoxLayout as layout index 1 of `m_sMeterSection` (after the title bar), so the extractor logic in `floatSMeter()` / `dockSMeter()` is identical to every other applet. **ANLG toggle button:** - Updated to the float-aware pattern used by TUN / AMP / AG: raises/hides the floating window when VU is floating, re-floats via `QTimer::singleShot(0)` when IsFloating is persisted but no window is open yet (toggle-off → toggle-on cycle fix from #985). **`isAppletFloating()`:** - Added early return for `"VU"`: checks `m_floatingWindows.contains("VU")` directly (VU is not in `m_appletOrder`). **`floatApplet()` / `dockApplet()`:** - Added `if (id == "VU")` dispatch at the top of each, delegating to `floatSMeter()` / `dockSMeter()`. **`floatSMeter()` / `dockSMeter()`:** - Mirror `floatApplet()` / `dockApplet()` exactly: reparent content out of/back into `m_sMeterSection`, create/destroy `FloatingAppletWindow`, persist `FloatingApplet_VU_IsFloating`, save geometry on dock. **Startup restore:** - After the existing `m_appletOrder` restore loop, added a `QTimer::singleShot(0)` restore for `"VU"` so the S-Meter reopens floating if it was floating when the app last closed. **dockSMeter() — use m_sMeterContent directly (agent review fix)** The original used a fragile layout-walk to recover m_sMeterContent from FloatingAppletWindow's internal layout. If any itemAt() returned null, appletWidget would be null while the code still called win->deleteLater(), destroying m_sMeterContent and all its children (m_sMeter, m_txSelect, m_rxSelect, peak-hold widgets) — crash on next signal-level update. Fix: use the named member directly. Reparent m_sMeterContent into m_sMeterSection before deleteLater() so Qt's parent-chain destruction cannot reach it. **.gitignore — drop Visual Studio artifacts (agent review fix)** /.vs and /out/install/x64-Debug are Windows VS IDE artifacts; they belong in ~/.gitignore_global, not the project-wide .gitignore. Closes #993 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Each applet in the AppletPanel can now be detached into its own floating window and re-docked at any time. Position and size persist across sessions and survive dock/undock cycles.
What's new
FloatingAppletWindow (new class, src/gui/FloatingAppletWindow.h/.cpp)
FloatingAppletX/Y — screen-relative position
FloatingApplet_W/H — window size
hammering AppSettings on each pixel
own window placement; size is always restored
clamped to the nearest available screen geometry
AppletPanel changes
floatingboolCMakeLists.txt
Cross-platform notes
This possibly could address #811 - Not the entire panel, but each individual Applet. "Popped-out" applets are still displayed even if the side control panel is visible/not visible.
Testing Notes — Poppable Applets
Setup
Core Float / Dock
Toggle Button Behaviour While Floating
Geometry Persistence
App Shutdown With Floating Windows
Drag Reorder Compatibility
Conditional Applets (TUN / AMP / AG)
** These were not tested due to WT2P hardware version not supporting it (3.8.19)
RX / TX Functionality While Floating
Edge Cases
Qt::ToolwindowsPlatform Notes
QT_QPA_PLATFORM=xcbfor full position restore