Skip to content

fix(capture): liquid glass self-capture, fallback spectrum, and Windows 10 support - #248

Merged
FoOcean merged 3 commits into
masterfrom
fix/capture-feedback
Oct 20, 2026
Merged

FoOcean merged 3 commits into
masterfrom
fix/capture-feedback

Conversation

@FoOcean

@FoOcean FoOcean commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator

Pre-submission checklist

  • I have read CONTRIBUTING.md and completed the required checks
  • Local and CI checks pass
  • I have completed a self-review
  • I confirm that I haven't read the checkboxes and just ticked them all

Change type (select one)

  • feat New feature
  • fix Bug fix
  • docs Documentation or templates
  • style Formatting with no behavior change
  • refactor Code change that neither fixes a bug nor adds a feature
  • perf Performance improvement
  • test Test-related change
  • chore Build, CI, dependency, or tooling change
  • revert Revert
  • security Security fix

Scope (select all that apply)

  • Application core
  • UI style or layout
  • Application behavior
  • Dependency changes
  • Plugin API
  • CI/CD configuration
  • Documentation
  • Other (describe below)

Other: Windows capture backend (winisland-platform-windows liquid glass backdrop). No new dependencies or crate features.

Related issues

  • Refs: user feedback after v1.5.3 (no tracked issue)

Description

Summary

Fixes liquid glass sometimes showing its own texture in compatibility mode, stops the fallback spectrum from failing after an output switch, and makes liquid glass work on Windows 10.

Motivation and context

  • Self-capture: in compatibility (magnifier) mode, the backdrop sometimes contained the island's own glass layered on top of itself. DWM can drop a window's magnifier exclusion after the window is hidden and shown again or after the magnifier resizes, and the filter list was only re-sent when the set of window handles changed.
  • Fallback spectrum: after an output switch, the fallback capture logged RPC_E_CHANGED_MODE every second. cpal activates the virtual default output asynchronously, and that activation keeps failing after a switch.
  • Windows 10 (reported on Windows 10 IoT Enterprise LTSC 21H2, build 19044): liquid glass had no backdrop in either mode.
    • Normal mode: SetWindowDisplayAffinity(WDA_EXCLUDEFROMCAPTURE) fails for the DirectComposition island windows with 0x80070008.
    • Compatibility mode: Windows.Graphics.Capture cannot capture the cloaked magnifier host (0x80070057).

Changes

Commits are self-contained and build in order.

  • fix(capture): the magnifier re-sends its exclusion list when the window set or visibility changes, after every resize, and every 500 ms. It warns once when MagSetWindowFilterList starts failing.
  • fix(audio): the fallback capture resolves the default output to its concrete endpoint, which activates synchronously. The device-change and missing-config logs are emitted once per device.
  • feat(capture):
    • When capture exclusion fails, normal mode falls back to the magnifier instead of failing.
    • When the magnifier host cannot be captured, the magnifier runs from a hidden, uncloaked host and delivers frames through MagSetImageScalingCallback.
      • Frames are copied into BGRA buffers (the header says RGBA, but the bytes are BGRA) and uploaded to a D3D11 texture that feeds the existing copy path.
      • The rate is capped at 60 Hz and identical frames are skipped.
    • The callback validates the image header against the buffer size before reading, and the source rect is clamped to the island's monitor.

Testing

  • cargo fmt --all -- --check and cargo clippy --workspace -- -D warnings pass. The first commit also passes cargo check on its own.
  • Windows 11:
    • Compatibility mode no longer picks up the island's own glass across expand/collapse, hide/show and resize.
    • The image-callback path was forced on and renders the same backdrop as window capture.
  • Windows 10 (19044), from a user log:
    • An earlier build reached the image-callback path ("reading magnifier frames directly"), then crashed natively with no panic log.
    • The header bounds check and the monitor clamp were added in response. The current build has not been run on Windows 10 yet.
  • To verify manually:
    1. Turn on liquid glass in compatibility mode, expand and collapse the island repeatedly, and check that the glass never shows its own texture.
    2. Play music without a supported player session and switch the output device. The spectrum should resume, and the log should not repeat RPC_E_CHANGED_MODE.
    3. On Windows 10, enable liquid glass in both modes. The backdrop should render, and the log should show the magnifier fallback without a crash.

UI changes

None beyond liquid glass now rendering on Windows 10.

Known limitation on Windows 10: the island stays visible in screenshots, because exclusion is unavailable there.

🤖 Generated with Claude Code

FoOcean and others added 3 commits October 19, 2026 10:18
DWM can drop a window's magnifier exclusion when the window is hidden and
shown again or when the magnifier resizes, so the backdrop sometimes
showed the island's own glass. Re-send the exclusion list whenever the
window set or visibility changes, after every resize, and every 500 ms,
and warn once when the call starts failing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fallback spectrum opened the virtual default output, which cpal
activates asynchronously; after an output switch that kept failing with
RPC_E_CHANGED_MODE and logged an error every second. Resolve the default
to its concrete endpoint, which activates synchronously, and log the
device change and missing-config warning only once per device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mage callback

On Windows 10, SetWindowDisplayAffinity rejects the DirectComposition
island windows (0x80070008) and Windows.Graphics.Capture cannot capture
the cloaked magnifier host (0x80070057), so liquid glass had no backdrop
in either mode.

- When capture exclusion fails, normal mode falls back to the magnifier
  instead of failing.
- When the magnifier host cannot be captured, the magnifier runs from a
  hidden, uncloaked host and delivers frames through
  MagSetImageScalingCallback. Frames are copied into BGRA buffers,
  uploaded to a D3D11 texture, and fed into the existing copy path.
  The rate is capped at 60 Hz and identical frames are skipped.
- The callback validates the image header against the buffer size, and
  the source rect is clamped to the island's monitor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@FoOcean
FoOcean merged commit 820fa14 into master Oct 20, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from Needs Review to Merge in Winisland Pull Requests Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant