Skip to content

ms5 window state machine#25

Merged
Charliechen114514 merged 8 commits into
mainfrom
feat/ms5-window-state-machine
Jul 7, 2026
Merged

ms5 window state machine#25
Charliechen114514 merged 8 commits into
mainfrom
feat/ms5-window-state-machine

Conversation

@Charliechen114514

Copy link
Copy Markdown
Member

No description provided.

Stage A of MS5 (window management). Pure data + math layer, no backend
dependency, fully unit-tested in isolation.

- WindowInfo: add icon_hint, z_index, is_always_on_top, created_at fields;
  update WindowState doc to note Minimized/Maximized now exercised.
- FloatingPolicy: pure-math initial-geometry policy (mirror
  WindowPlacementPolicy). Centers a new floating window in the work area,
  shrinks-to-fit when larger (aspect preserved), nudges by a 24px cascade
  offset per consecutive window, and clamps the result to stay fully inside
  the work area. Reuses WindowPlacementPolicy::centerInWorkArea for the
  shrink/center math.
- 13-case FloatingPolicy unit test (cascadeOffset / clampToMinimum /
  initialGeometry); also fix the stale include path in the placement test
  CMakeLists (desktop/ui -> ui, post-restructure).
Stage B of MS5. Adds the platform state-operation seam the WindowManager
state machine will drive.

- IWindow: add non-pure virtual minimize/maximize/restore with default
  no-op bodies (mirror pid()'s pattern), so existing/future backends are
  not forced to implement all three.
- WindowsWindow: override all three via ShowWindow(SW_MINIMIZE/SW_MAXIMIZE/
  SW_RESTORE).
- WSLX11Window: override minimize/restore by sending the ICCCM 4.1.4
  WM_CHANGE_STATE ClientMessage to the root window with
  SubstructureRedirectMask|SubstructureNotifyMask (the XIconifyWindow /
  xdotool path, honored by XWayland on WSL). Maximize stays the default
  no-op on X11 because the EWMH _NET_WM_STATE hint is unreliable under
  XWayland; intern a new wm_change_state atom alongside the existing
  cached atoms.
Stage C of MS5. The WindowManager now drives minimize/maximize/restore
through a state machine and exposes queries the taskbar toggle will use.

- WindowManager: add minimizeWindow/maximizeWindow/restoreWindow (validated
  via isValidTransition: Normal<->Minimized, Normal<->Maximized; rejects
  Maximized<->Minimized direct jumps, Closed is terminal), getWindowInfo /
  getAllWindowInfos / findWindowByPid queries, and windowStateChanged /
  windowInfoUpdated signals. applyState dispatches the IWindow op, updates
  the stored info, and emits both signals.
- onWindowCame: populate the new WindowInfo fields (created_at etc.) and
  also index the weak reference in windows_ so externally-arrived windows
  are resolvable by find_window (previously windows_ was only filled by
  create_window, leaving the lookup dead for tracked external windows).
- destroyed lambda: emit the Closed transition + windowInfoUpdated BEFORE
  erasing so subscribers observe the final state; also erase windows_.
- 14-case unit test (FakeWindow + QSignalSpy when Qt6::Test is available)
  covering happy paths, rejected transitions, queries, and the destroyed
  Closed emission.
Stage D of MS5. The window_came handler now uses FloatingPolicy for the
initial geometry instead of WindowPlacementPolicy.computeConstrain.

On each external window appearance the window is centered in the work area,
shrunk to fit when larger, and nudged by a 24px cascade offset per
consecutive window so a burst of launches does not stack exactly on top of
each other. The cascade index is a monotonic per-entity counter (no
dependence on slot execution order). The window's current size is passed as
the desired size so the app's chosen geometry is respected and only the
position (plus shrink/center) changes.

WindowPlacementPolicy still runs on work-area changes (reconstrain_windows)
to pull existing windows back inside when the desktop is resized. Same
config toggle (window_management/constrain_to_workarea, default on).
Stage E of MS5. Clicking a running app's taskbar icon no longer spawns a
second instance; it toggles the existing tracked window.

launch_app (used by both the taskbar click and the launcher popup) now
checks app_pid + WindowManager::findWindowByPid before launching: if the
clicked app has a live tracked window it toggles state — Normal minimizes,
Minimized restores + raises, any other state (Maximized etc.) just raises.
A stale app_pid entry whose window already died falls through to a normal
relaunch because findWindowByPid returns nullopt once the window is gone.

BuiltinPanel apps are unaffected (they still pop up in-process).
…oration

Stage F of MS5. Reflects the code reality in the status docs.

- milestone_05: status line updated (state machine + taskbar raise/minimize +
  FloatingPolicy landed 2026-07-05); acceptance criteria checkboxes updated
  (all but the two decoration items now met); new section documents the
  decoration DEFERRED decision and its three reasons (WSL X11/Win32 native
  title bars clash, EGLFS will own decoration natively, overlay would be
  rewritten); bottom date bumped.
- current.md: MS5 line rewritten with the 2026-07-05 landing summary and the
  DEFERRED note; new 2026-07 MS5 entry under recent milestones; calibration
  date bumped to 2026-07-05.
TaskbarIcon painted nothing when icon_mask_ was null, and the mask only
resolves from a loadable file/qrc path — manifest apps ship no icon,
.desktop Icon= is a freedesktop theme name (not a path), and builtin
panels set none — so every such tile rendered as an identical blank
rounded rectangle. Add a display-name initial fallback in paintEvent
(mirroring LauncherTile) so every tile is identifiable. Default apps
that ship qrc masks still render them; the tooltip (display_name) was
already set.
…face

The frosted-glass backdrop (blur the live wallpaper strip + tint + cache)
caused two problems on the bars:
- Stale blur after a wallpaper rotation (the panels were never repainted,
  so the cached blur held the previous wallpaper).
- A visible color snap when the blur was eventually rebuilt on settle.

Drop the wallpaper-dependent blur entirely. The taskbar and status bar now
paint a fixed-alpha surface (0.82) that lets the wallpaper composite through
it directly — no per-wallpaper computation, no stale cache, no transition
snap, and zero blur cost on every repaint (important on i.MX6ULL, which has
no GPU and would pay a CPU box-blur otherwise).

Removed per bar: FrostedBackdrop usage, frosted_params_, backdrop_source_,
reblur_debounce_, backdrop_null_warned_, resizeEvent, setBackdropSource,
and WA_OpaquePaintEvent (its removal is what lets the wallpaper composite
through). CFDesktopEntity no longer calls setBackdropSource. The
FrostedBackdrop utility class itself is retained (still unit-tested) for a
future backend that can blurs cheaply (e.g. EGLFS with PXP).
@Charliechen114514 Charliechen114514 merged commit 7416953 into main Jul 7, 2026
6 checks passed
@Charliechen114514 Charliechen114514 deleted the feat/ms5-window-state-machine branch July 7, 2026 04:52
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