Skip to content

feat: add color scheme support for desktop WebViews - #67

Open
martinkade wants to merge 1 commit into
NucleusFramework:mainfrom
martinkade:feature/jvm-dark-mode
Open

martinkade wants to merge 1 commit into
NucleusFramework:mainfrom
martinkade:feature/jvm-dark-mode

Conversation

@martinkade

Copy link
Copy Markdown

Add desktop color-scheme control for WebView content

Rationale

None of the three desktop backends previously exposed any way to influence whether loaded content
renders light or dark:

  • macOS: the WKWebView was created with no appearance parameter and nothing could change it
    afterward. WKWebView resolves prefers-color-scheme/color-scheme partly from the hosting
    NSView's effective appearance, so content relying on the UA's own default dark colors (rather
    than setting every color explicitly) never reliably rendered dark.
  • Windows: WebView2 has a real, documented API for this -
    ICoreWebView2Profile::put_PreferredColorScheme (Auto/Light/Dark) - but nothing reached it.
  • Linux: no per-WebKitWebView API exists upstream either; the only lever is the
    process/display-wide GtkSettings:gtk-application-prefer-dark-theme property, which WebKitGTK
    consults when deciding what to report for prefers-color-scheme.

DesktopWebSettings had no field for this at all. Practical effect: a consuming app's dark theme
toggle had no way to also darken loaded HTML content (a mail body viewer, a rich-text editor, ...)
on desktop - unlike Android, where WebSettingsCompat.setAlgorithmicDarkeningAllowed already
covers exactly this case.

What changed

  • New WebViewColorScheme enum (SYSTEM / LIGHT / DARK), commonMain.
  • DesktopWebSettings.colorScheme - applied once at WebView creation, like every other field on
    that settings class. Defaults to SYSTEM, so no behavior change for existing callers.
  • IWebView.setColorScheme(scheme) - new method to change it afterward without recreating the
    WebView. Default no-op on the interface; only the desktop DesktopWebView overrides it. Android/
    iOS/Wasm don't need it - their engines already resolve prefers-color-scheme from the system
    theme correctly on their own.
  • Per-OS native implementation, each reached via a new JNI method on the existing bridge object and
    a new setColorScheme on the concrete NativeWebView subclass:
    • macOS (navigation.m, WebKitMacOsBridge.nativeSetAppearance): sets the WKWebView's own
      NSAppearance (.aqua / .darkAqua / nil for system).
    • Windows (navigation.cpp, WebView2WindowsBridge.nativeSetPreferredColorScheme): calls
      ICoreWebView2Profile::put_PreferredColorScheme via ICoreWebView2_13::get_Profile.
    • Linux (navigation.c, WebKitLinuxBridge.nativeSetPreferDarkTheme): sets
      gtk-application-prefer-dark-theme on the widget's own GtkSettings. This is display-wide,
      not per-WebView - there is no narrower API upstream, so it also affects other GTK widgets'
      theme rendering on that display. Called out in the native implementation's own doc comment.

Testing / verification status

  • macOS: built and linked successfully for both arm64 and x86_64 via
    ./gradlew :webview-compose:buildNativeMacos. Not yet exercised in a running app window (no
    visual e2e case added for this yet - see below).
  • Windows: written against the documented WebView2 API (ICoreWebView2_13/
    ICoreWebView2Profile, available since SDK 1.0.1264.42, well below the 1.0.2210.55 this project
    vendors) but not locally compiled - no Windows/MSVC toolchain available where this was
    written. Needs a real Windows build (CI matrix or manual) before merging.
  • Linux: not locally compiled either - no GTK dev environment available. Needs a real Linux
    build before merging.
  • Existing dev.nucleusframework.webview.setting.* / dev.nucleusframework.webview.web.* unit
    tests pass unaffected (./gradlew :webview-compose:jvmTest).

Steps to verify

  1. ./gradlew :webview-compose:buildNativeLinux / buildNativeMacos / buildNativeWindows on
    each OS.
  2. ./gradlew :e2e-desktop:run on each OS, with a manual check that a WebView loading plain HTML
    with no color-scheme of its own switches between light/dark for each WebViewColorScheme
    value (no automated visual case added yet - worth a follow-up in e2e-shared's
    visualsuite/* catalog).

Known limitations / follow-ups

  • Linux's effect is display-wide, not per-WebView (see above) - acceptable for a single-window
    desktop app, but worth documenting prominently in the public API doc if this ships.
  • No automated e2e coverage yet for the new behavior - only manual verification steps above.
  • Windows and Linux native changes are unverified by a real build in this PR; please don't merge
    until CI (or a manual build) confirms both.

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