Skip to content

Frameless main window with title-bar drag, min/max/close, and size grip#1926

Merged
ten9876 merged 1 commit into
mainfrom
claude/frameless-mainwindow
Apr 25, 2026
Merged

Frameless main window with title-bar drag, min/max/close, and size grip#1926
ten9876 merged 1 commit into
mainfrom
claude/frameless-mainwindow

Conversation

@ten9876

@ten9876 ten9876 commented Apr 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Make the whole app frameless by default — no more OS title bar. TitleBar gains drag-to-move, double-click-to-maximize, and a min/max/close trio at the far right. A QSizeGrip in the bottom-right corner provides resize.

What's in

  • One-shot `FramelessMigratedV0823` AppSettings migration flips existing installs from the prior opt-in (`FramelessWindow=False`) default. View → Frameless Window keeps the toggle as an escape hatch.
  • TitleBar drag → `window()->windowHandle()->startSystemMove()` (Qt 6 cross-platform compositor primitive). Children intercept their own clicks; drag only fires on truly empty areas.
  • Double-click to toggle maximize / restore.
  • Three flat QLabels at the far right (—, □/❐, ✕) styled to match the rest of the bar. Cyan hover for min/max, red hover for close. Click via eventFilter.
  • Maximize icon auto-swaps via WindowStateChange event filter on the host window.
  • QSizeGrip anchored as a direct child of MainWindow (not parented into the styled QStatusBar, which suppresses the dotted-texture paint). Repositioned in resizeEvent. Same approach pop-out windows already use.

Test plan

  • Linux: drag from bare title-bar areas, double-click to maximize, min/max/close all work, size grip resizes
  • Windows: confirm Qt-on-Windows quirk (constructor flag bitmask) doesn't bite — `setWindowFlags()` is already used for the Frameless toggle path
  • macOS: confirm chrome behavior

🤖 Generated with Claude Code

…ze grip

The whole app is now frameless by default.  A one-shot AppSettings
migration (FramelessMigratedV0823) flips existing installs from the
prior opt-in default; View → Frameless Window stays as a toggle for
users on broken Wayland compositors etc.

TitleBar gains:

* Drag-to-move on bare-background mouse press → window()->windowHandle()
  ->startSystemMove() (Qt 6 cross-platform compositor primitive).  Menu
  items, buttons, and sliders intercept their own clicks so drag only
  fires on truly empty areas.
* Double-click to toggle maximize / restore.
* Three flat QLabels at the far right — — (em-dash, minimize),
  □ / ❐ (maximize / restore), ✕ (close).  Same flat aesthetic as the
  rest of the bar; cyan hover for min/max, red hover for close.  Click
  is wired via eventFilter so the labels stay simple.
* Window-state-change event filter on the host window keeps the
  maximize icon swapped between □ and ❐ without explicit signal
  plumbing.

A QSizeGrip is anchored to the bottom-right of MainWindow as a direct
child (not parented into the heavily-styled QStatusBar, which was
suppressing the dotted-texture paint), repositioned in resizeEvent.
Mirrors how FloatingContainerWindow / PanFloatingWindow already do it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ten9876 ten9876 enabled auto-merge (squash) April 25, 2026 05:17
@ten9876 ten9876 merged commit cfdd7b8 into main Apr 25, 2026
4 checks passed
@ten9876 ten9876 deleted the claude/frameless-mainwindow branch April 25, 2026 05:28
ten9876 added a commit that referenced this pull request May 2, 2026
Bundles seven independently-verified maintainer-reviewed fixes:

- #2027 TitleBar headline now shows running version number — regressed
  with frameless-window mode (#1926). Restored via the same
  applicationVersion() pattern used by setWindowTitle().

- #2263 FlexControl knob press tokens are bare S/C/L (not X4S/X4C/X4L).
  Verified against hardware capture from LB2EG: side buttons emit
  X1S/X1C/X1L/X2S/.../X3L (parsed correctly today), knob press emits
  bare S/C/L. Adds a new branch in processCommand() mapping the bare
  tokens to buttonPressed(4, action), keeping the X-prefix path for
  the side buttons. Dead X4S path retained as defense in depth.

- #2264 ggmorse Å sequence corrected from 01110 to 01101 per
  ITU-R M.1677-1. Confirmed Æ (0101) and Ø (1110) on the same lines
  are unaffected.

- #1564 K/SFI/WNB/RF Gain/WIDE indicator strip click suppression. New
  m_indicatorStripRect tracks the full strip in both paint paths;
  mouseReleaseEvent guards skip the frequency emit when single-click
  tune lands inside the strip. Existing m_propClickRect dialog click
  is unaffected.

- #1576 Slice record (⏺) and play (▶) button visibility. Roughly
  doubled alpha values across all four stylesheet locations and
  brightened the inactive icon colors so the buttons are legible
  against the #0a0a14 spectrum background.

- #1581 + the close (✕) and lock (🔓) buttons on each slice header
  now share a single sliceBtnStyle base with record/play, ensuring
  identical 20px circles. Status indicators (TNF/CWX/DVK/FDX) all
  use cyan #00b4d8 for active and #404858 for off; TNF init colour
  fixed (was rgba(255,255,255,128)). updateKeyerAvailability() and
  the CWX/DVK click handlers now use #404858 instead of
  rgba(255,255,255,40) for the off-state, so DVK in voice mode
  matches the rest of the indicator strip when not in use.

- #1583 Status-bar time stack reduced from 3 rows to 2 (date + UTC
  time) by removing the grid-square label, matching every other
  telemetry stack. m_gridLabel removed from MainWindow.h.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant