Skip to content

windows: menus and dialogs in windows of their own, as Acrylic popups - #238

Merged
foxnne merged 1 commit into
mainfrom
windows/acrylic-menus
Oct 8, 2026
Merged

foxnne merged 1 commit into
mainfrom
windows/acrylic-menus

Conversation

@foxnne

@foxnne foxnne commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #226 (docs/NATIVE_WINDOWS_PLAN.md); step 3 of docs/WINDOWS_LINUX_GLASS_PLAN.md (#236).

What changes

With floats as windows (FIZZY_POPOUT=1 on Windows), menus and dialogs now leave the main window as they do on macOS (viewports.menus). Each one is a borderless window owned by the window it opens from, never activated, and dressed by DWM (win32_titlebar.viewportMenuChrome):

  • Acrylic (DWMSBT_TRANSIENTWINDOW, the material of Windows 11's own menus);
  • DWM's rounded corners and shadow;
  • no border, no system menu, no DWM transitions.

DWM draws a never-activated window's backdrop as its solid fallback, so the menu's window is kept looking active (WM_NCACTIVATE). An owned window isn't carried when its owner moves, so a menu's window rides on nothing and is placed each frame.

SDK impact

  • None

Verified

Windows 11 ARM VM (fizzy-win11, WARP, aarch64-windows-gnu Debug), driven with real input (SendInput) and checked against the window list (EnumWindows plus DWM attributes) and screenshots:

  • The File and Help menus and the "Unsaved changes" dialog each open in a window of their own:
    • owned by the main window and directly above it in the z-order;
    • WS_EX_NOACTIVATE, no WS_SYSMENU;
    • backdrop type Acrylic (3), corner preference round;
    • the main window stays the foreground window.
  • The first click on an item acts: New File opens untitled-1, and Open Files opens the Open dialog. A temporary log showed the press arriving on the menu's window and mapping into the menu's dvui subwindow, not what lies under it.
  • The dialog's window hides when the main window is minimized and comes back on restore.
  • Gates: zig build, test, test-integration, check-web, test-sdk-version, and the Windows and Linux cross-builds.
  • The look on a hardware GPU. The VM's DWM draws every backdrop as its fallback, so these need a real machine:
    • Acrylic rather than a solid colour;
    • rounded corners and a shadow;
    • whether the WM_NCACTIVATE trick keeps the Acrylic.
  • A menu opened over a float's window. Not exercised; creating a float needs a view drag.
  • macOS / Linux / Web: unchanged (viewports.menus was already on for macOS, and this is the Windows branch).

Seen while testing, not caused by this change:

  • A menu closes when fizzy is deactivated. My harness's own process start deactivated it, which made a later click fall through to the main window.
  • A dialog drifts a few pixels left over each minimize/restore. It does the same drawn in-window (FIZZY_NATIVE_DIALOGS=0).

Follow-ups

  • NATIVE_WINDOWS_PLAN's Phase 1 on Windows: the slider along DWM's backdrop types, one activation group, and a policy probe.
  • Caption buttons in a Windows float's header (in app/layout/Floats.zig).

🤖 Generated with Claude Code

Base automatically changed from docs/windows-linux-glass to main October 8, 2026 15:08
@foxnne
foxnne force-pushed the windows/acrylic-menus branch from 59108bb to 4051437 Compare October 8, 2026 16:03
With floats as windows (`FIZZY_POPOUT=1` on Windows), a menu or dialog now leaves the main window
as it does on macOS (`viewports.menus`): a borderless window owned by the window it opens from,
never activated, dressed by DWM (`win32_titlebar.viewportMenuChrome`) with Acrylic
(DWMSBT_TRANSIENTWINDOW, the material of Windows 11's menus and flyouts), DWM's rounded corners and
shadow, no border, no system menu and no DWM transitions. The window's base is drawn under the
menu at the window opacity, as over the main window's Acrylic. Step 3 of
docs/WINDOWS_LINUX_GLASS_PLAN.md.

An owned window is not carried when its owner moves, so on Windows a menu's window rides on
nothing and is placed each frame (`viewportPlaceRiding`); a dialog of a float that is out is owned
by that float's window, for its stacking. DWM draws a never-activated window's backdrop as its
solid fallback, so the menu's window is kept looking active to it (`WM_NCACTIVATE`).

Checked in the Windows 11 ARM VM (WARP, aarch64-windows-gnu Debug), with real input
(`SendInput`) and the window list (`EnumWindows`, DWM attributes):
- File and Help menus, and the "Unsaved changes" dialog, each open in a window of their own:
  owned by the main window, directly above it, `WS_EX_NOACTIVATE`, no `WS_SYSMENU`, backdrop type
  Acrylic, corner preference round. The main window stays the foreground window.
- The first click on an item acts (New File, Open Files), and lands on the menu, not on what is
  under it: a temporary log showed the press arriving on the menu's window and mapping into the
  menu's subwindow.
- The dialog's window hides with a minimized main window and comes back on restore.
Not checked: the look, since the VM's DWM draws every backdrop as its solid fallback; the
kept-active trick, for the same reason; a menu over a float's window. Those need a hardware GPU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@foxnne
foxnne force-pushed the windows/acrylic-menus branch from 4051437 to 8d66910 Compare October 8, 2026 18:01
@foxnne
foxnne marked this pull request as ready for review October 8, 2026 18:02
@foxnne
foxnne merged commit b81c3d1 into main Oct 8, 2026
10 of 11 checks passed
@foxnne
foxnne deleted the windows/acrylic-menus branch October 8, 2026 18:19
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.

2 participants