Skip to content

[v3/macOS] WKWebView capped at 60 FPS on ProMotion display #6056

Description

@0versquare

Wails version family

v3

Exact Wails version

v3.0.0-beta.1

Operating System

macOS

Description

On a MacBook Pro with a 120 Hz ProMotion display, a Wails v3 WKWebView is capped at approximately 60 FPS even though the same WebKit version is capable of rendering at 120 FPS.

Environment:

  • macOS 26.5.2 (Build 25F84)
  • MacBook Pro with 120 Hz ProMotion display
  • macOS SDK 26.5
  • Application binary:
    • minos 12.0
    • sdk 26.5

A simple requestAnimationFrame counter consistently reports approximately 60 FPS inside Wails.

Safari also defaults to approximately 60 FPS, but disabling Safari's "Prefer Page Rendering Updates near 60fps" feature flag immediately allows the same test to run at approximately 120 FPS.

More importantly, applying the equivalent WebKit preference directly to the WKWebView created by Wails also immediately changes the Wails application from approximately 60 FPS to approximately 120 FPS.

The preference is:

PreferPageRenderingUpdatesNear60FPSEnabled

I tested this by modifying v3/pkg/application/webview_window_darwin.go and disabling the preference through the private WKPreferences feature API immediately after the WKWebView is created.

Before:

requestAnimationFrame ≈ 60 FPS

After disabling PreferPageRenderingUpdatesNear60FPSEnabled:

requestAnimationFrame ≈ 120 FPS

This appears particularly interesting on macOS 26 because the related Tauri investigation reports that the 60 FPS cap no longer applies to WKWebView on Tahoe and that this private preference should effectively be a no-op there.

However, with Wails v3 on macOS 26.5.2, the preference clearly still affects rendering cadence: disabling it changes the WebView from 60 Hz to 120 Hz.

Related investigation:

https://github.com/userFRM/tauri-plugin-macos-fps

Their compatibility notes currently state that on macOS 26 Tahoe, WKWebView runs at native refresh rate without the plugin. That does not appear to be the case for the WKWebView created by Wails v3 on my system.

To Reproduce

  1. Run a Wails v3 application on a MacBook Pro with a 120 Hz ProMotion display.

  2. Run this code in the frontend:

let frames = 0;
let start = performance.now();

function frame(now) {
    frames++;

    if (now - start >= 1000) {
        console.log(
            (frames * 1000 / (now - start)).toFixed(1),
            "FPS"
        );

        frames = 0;
        start = now;
    }

    requestAnimationFrame(frame);
}

requestAnimationFrame(frame);
  1. Observe approximately 60 FPS.

For comparison, in Safari 26 on the same machine:

  1. Enable the Develop features.
  2. Disable "Prefer Page Rendering Updates near 60fps".
  3. Run the same test.
  4. Observe approximately 120 FPS.

I then modified Wails' macOS WebView creation code to disable the equivalent private WebKit feature immediately after WKWebView creation.

After rebuilding, the same requestAnimationFrame test reports approximately 120 FPS.

Expected behaviour

On a 120 Hz ProMotion display, a Wails WKWebView should be capable of receiving rendering updates at the display's native refresh rate rather than being limited to approximately 60 Hz.

Ideally this should work without relying on private WebKit APIs.

I am not necessarily suggesting that Wails should ship the private _features / _setEnabled:forFeature: workaround, since those APIs are undocumented.

The main issue is that Wails' WKWebView appears to remain in WebKit's 60 FPS mode on macOS 26, whereas other investigation suggests that normal WKWebView instances on Tahoe should no longer be capped.

Screenshots

No response

Attempted Fixes

  • Confirmed the MacBook display is running ProMotion.
  • Confirmed requestAnimationFrame is approximately 60 FPS in Wails.
  • Confirmed Safari is initially approximately 60 FPS.
  • Disabled Safari's "Prefer Page Rendering Updates near 60fps" feature flag and confirmed Safari immediately reaches approximately 120 FPS.
  • Tested loading the Wails frontend over normal http://localhost rather than the Wails custom URL scheme. Wails remained at approximately 60 FPS.
  • Changed WKWebViewConfiguration.suppressesIncrementalRendering from true to false. No effect; Wails remained approximately 60 FPS.
  • Confirmed the application is being built against the macOS 26.5 SDK:
cmd LC_BUILD_VERSION
cmdsize 32
platform 1
minos 12.0
sdk 26.5
ntools 1
tool 3
  • I then modified v3/pkg/application/webview_window_darwin.go to disable WebKit's private PreferPageRenderingUpdatesNear60FPSEnabled feature on the WKWebView.

I added:

#import <objc/message.h>

static void disableWebKit60FPSCap(WKWebView *webView) {
    WKPreferences *preferences = webView.configuration.preferences;

    Class preferencesClass = NSClassFromString(@"WKPreferences");
    SEL featuresSelector = NSSelectorFromString(@"_features");
    SEL setEnabledSelector = NSSelectorFromString(@"_setEnabled:forFeature:");

    if (preferencesClass == nil ||
        ![preferencesClass respondsToSelector:featuresSelector] ||
        ![preferences respondsToSelector:setEnabledSelector]) {
        return;
    }

    typedef NSArray *(*FeaturesFn)(id, SEL);
    NSArray *features =
        ((FeaturesFn)objc_msgSend)(preferencesClass, featuresSelector);

    for (id feature in features) {
        NSString *key = [feature valueForKey:@"key"];

        if ([key isEqualToString:@"PreferPageRenderingUpdatesNear60FPSEnabled"]) {
            typedef void (*SetEnabledFn)(id, SEL, BOOL, id);

            ((SetEnabledFn)objc_msgSend)(
                preferences,
                setEnabledSelector,
                NO,
                feature
            );

            return;
        }
    }
}

and called it immediately after the WKWebView is created:

WKWebView* webView =
    [[WKWebView alloc] initWithFrame:frame configuration:config];

disableWebKit60FPSCap(webView);

After rebuilding, the same requestAnimationFrame test changed from approximately 60 FPS to approximately 120 FPS.

Removing this patch and rebuilding immediately brings the rendering FPS back to 60.

So the private WebKit preference workaround is confirmed to affect the Wails WebView on macOS 26.5.2.

System Details

# System
        
┌──────────────────────────────┐
| Name          | MacOS        |
| Version       | 26.5.2       |
| ID            | 25F84        |
| Branding      | MacOS 26.5.2 |
| Platform      | darwin       |
| Architecture  | arm64        |
| Apple Silicon | true         |
| CPU           | Apple M1 Pro |
| CPU           | Apple M1 Pro |
| GPU           | 16 cores     |
| Memory        | 16 GB        |
└──────────────────────────────┘
                   
# Build Environment
                   
┌──────────────────────────────┐
| Wails CLI    | v3.0.0-beta.1 |
| Go Version   | go1.25.0      |
| -buildmode   | exe           |
| -compiler    | gc            |
| CGO_CFLAGS   |               |
| CGO_CPPFLAGS |               |
| CGO_CXXFLAGS |               |
| CGO_ENABLED  | 1             |
| CGO_LDFLAGS  |               |
| GOARCH       | arm64         |
| GOARM64      | v8.0          |
| GOOS         | darwin        |
└──────────────────────────────┘
              
# Dependencies
              
┌──────────────────────────────────────────────────────────────────────────────────────┐
| *Android NDK            | /Users/nam/Library/Android/sdk/ndk/28.2.13676358           |
| *Android SDK            | /Users/nam/Library/Android/sdk                             |
| *Android platform-tools | Installed                                                  |
| *Java (Android)         | openjdk version "21.0.3" 2024-04-16 LTS                    |
| *NSIS                   | Not Installed. Install with `brew install makensis`.       |
| *Xcode (iOS)            | Xcode 26.6, Build version 17F113                           |
| *iOS Device SDK         | 26.5                                                       |
| *iOS Simulator SDK      | 26.5                                                       |
| Xcode cli tools         | 2416                                                       |
| npm                     | 11.17.0                                                    |
| docker                  | *Docker version 29.5.3, build d1c06ef (daemon not running) |
|                                                                                      |
└────────────────────────────── * - Optional Dependency ───────────────────────────────┘
         
# Signing
         
┌────────────────────────────────────────┐
| macOS Signing   | Not configured       |
| Windows Signing | Not configured       |
| Linux Signing   | Not configured (GPG) |
└────────────────────────────────────────┘
                     
# Checking for issues
                     
 SUCCESS  No issues found
           
# Diagnosis
           
 SUCCESS  Your system is ready for Wails development!

Additional context

There is an existing investigation/workaround for the same WebKit preference in:

https://github.com/userFRM/tauri-plugin-macos-fps

Its current macOS compatibility documentation reports:

  • macOS 13 Ventura: 60 FPS cap exists
  • macOS 14 Sonoma: 60 FPS cap exists
  • macOS 15 Sequoia: 60 FPS cap exists
  • macOS 26 Tahoe: cap removed

It specifically reports testing WKWebView on macOS 26.3.1 with both a 120 Hz ProMotion display and a 165 Hz external display, with both reaching native refresh rate regardless of whether the private preference was changed.

That makes the Wails result unexpected.

On macOS 26.5.2, the Wails v3 WebView remains at approximately 60 FPS, and explicitly disabling PreferPageRenderingUpdatesNear60FPSEnabled still causes it to jump to approximately 120 FPS.

This may indicate some difference in how the Wails WKWebView is configured or instantiated, or some WebKit compatibility behaviour specific to the Wails application.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions