Skip to content

feat(v3/macos): isolate private macOS APIs behind an appstore build tag - #6060

Draft
leaanthony wants to merge 2 commits into
masterfrom
claude/wails-120fps-public-apis-h3bnby
Draft

feat(v3/macos): isolate private macOS APIs behind an appstore build tag#6060
leaanthony wants to merge 2 commits into
masterfrom
claude/wails-120fps-public-apis-h3bnby

Conversation

@leaanthony

Copy link
Copy Markdown
Member

Description

Every undocumented WebKit and AppKit call Wails makes on macOS now lives in a single file, v3/pkg/application/mac_private_api_darwin.go, behind a small set of wailsPrivate* functions. Building with -tags appstore selects mac_private_api_appstore_darwin.go instead, which implements the same functions with public APIs or documented no-ops. The Go API is identical in both builds; only the visual result differs where macOS offers no public equivalent.

Isolated surfaces:

Surface Default build With -tags appstore
WKWebView transparency (drawsBackground, backgroundColor) Unchanged The window effect is still configured, but the webview stays opaque; the documented underPageBackgroundColor is set instead
Web Inspector (_inspector, developerExtrasEnabled) Unchanged OpenDevTools() is a no-op; the window is still inspectable from Safari's Develop menu on macOS 13.3+
NSGlassEffectView cross-window grouping and undocumented style values Unchanged Grouping is ignored; only the documented regular and clear styles are used, with light/dark expressed through NSAppearance

Two related changes come with it:

  • MacWebviewPreferences.PreferPageRenderingUpdatesNear60FPS toggles WebKit's feature flag of the same name. WebKit enables it by default, and it rounds the display's refresh rate down to the nearest whole multiple of 60 (framesPerSecondNearestFullSpeed in AnimationFrameRate.cpp), so a 120Hz ProMotion display drives the page at 60fps and a 165Hz display at 55fps. Setting it to application.Disabled lets the webview render at the display's native rate. There is no public API for this, so it is ignored under -tags appstore.
  • On macOS 13.3+ the Web Inspector is now enabled through the public WKWebView.inspectable property, keeping the private developerExtrasEnabled preference only as a fallback for older systems. This shrinks the private surface of default builds too.

Refs #6056

Supersedes #5955, which took the same approach under the name noprivateapis; that branch has since fallen behind master. Happy to close this instead if you would rather land that one.

Type of change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

  • Windows
  • macOS
  • Linux

Not yet built or run on a Mac — this was developed in a Linux container, so the Objective-C has been reviewed but not compiled. It needs a macOS build of both variants before it leaves draft.

What has been verified, on Linux:

  • go list for GOOS=darwin selects exactly one variant per configuration: the private files by default, the appstore files with -tags appstore, and only the always-on appstore file with -tags appstore,production.
  • Three new tests in mac_private_api_test.go, all platform-independent:
    • TestPrivateMacAPIsAreIsolated — no private selector or key may appear in any other Apple-platform source. Verified to fail when one is reintroduced.
    • TestPrivateMacAPIBuildVariantsAreExclusive — the variants never compile together.
    • TestPrivateMacAPIVariantsImplementTheSameFunctions — every declared seam function is implemented by both variants, so a missing no-op fails on Linux rather than at link time on a Mac.

Still to check on hardware:

  1. Both variants build, and the default build behaves exactly as before for transparent, translucent, Liquid Glass and notch windows.
  2. PreferPageRenderingUpdatesNear60FPS: application.Disabled reaches ~120fps on a ProMotion display via the requestAnimationFrame counter from [v3/macOS] WKWebView capped at 60 FPS on ProMotion display #6056.
  3. An -tags appstore binary is free of the private symbols.

Test Configuration

Linux container; no macOS toolchain available.

Checklist:

  • My code follows the general coding style of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings — not verifiable without a macOS compiler
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes — the new tests pass; the rest of pkg/application cannot be built in this container (no GTK)

Generated by Claude Code

Every undocumented WebKit and AppKit call Wails makes on macOS now lives in
mac_private_api_darwin.go, behind a small set of wailsPrivate* functions.
Building with -tags appstore selects mac_private_api_appstore_darwin.go
instead, which implements the same functions with public APIs or documented
no-ops. The Go API is identical in both builds; only the visual result differs
where macOS offers no public equivalent.

Isolated surfaces:

- WKWebView transparency (drawsBackground, backgroundColor)
- Web Inspector (_inspector, developerExtrasEnabled)
- NSGlassEffectView cross-window grouping and undocumented style values

Also adds MacWebviewPreferences.PreferPageRenderingUpdatesNear60FPS, which
toggles WebKit's PreferPageRenderingUpdatesNear60FPSEnabled feature flag.
WebKit enables it by default and it rounds the display refresh rate down to
the nearest multiple of 60, so a 120Hz ProMotion display drives the page at
60fps. Setting it to application.Disabled lets the webview render at the
display's native rate. Ignored under -tags appstore.

On macOS 13.3+ the Web Inspector is now enabled through the public
WKWebView.inspectable property, keeping the private preference only as a
fallback for older systems.

Three tests keep the seam honest, and all run on any platform: private
references may not appear outside the guarded files, the build variants must
be mutually exclusive, and both variants must implement the same functions.

Refs #6056
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation Improvements or additions to documentation MacOS v3

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants