Migrating to gtk4/webkit6 - #1767
Conversation
Resolves the unsoundness advisory GHSA-wrw7-89jp-8q8g (glib < 0.2) by replacing gtk 0.18 and webkit2gtk 4.1 with gtk4 0.11 and webkit6 0.6. - Cargo.toml: replace gtk, webkit2gtk, webkit2gtk-sys, javascriptcore-rs, gdkx11 with gtk4, webkit6, webkit6-sys, javascriptcore6, gdk4, gdk4-x11; remove tao dev-dependency; bump soup3 0.5→0.9 - src/webkitgtk/mod.rs: rewrite Linux backend against webkit6 API surface - src/webkitgtk/web_context.rs: update URI scheme registration for webkit6 - src/webkitgtk/drag_drop.rs: replace deprecated gtk3 drag signals with GtkDropTarget; rename Leaving→Dropped state to match new drop flow - src/webkitgtk/synthetic_mouse_events.rs: adapt to gtk4 event model - src/lib.rs: update public API (gtk::Container→gtk::Widget bounds, webkit2gtk→webkit6 types); replace tao+gtk doc examples with gtk4+winit; update GTK event loop pump to glib::MainContext::default().iteration() - src/error.rs: update glib error imports to webkit6::glib - examples: update all Linux examples from tao+gtk to winit+gtk4 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Permissions: - Wire up ClipboardPermissionRequest and MediaKeySystemPermissionRequest in the webkitgtk backend; update PermissionKind docs for webkit6 CI: - Replace libwebkit2gtk-4.1-dev with libwebkitgtk-6.0-dev + libgtk-4-dev - Add WEBKIT_DISABLE_DMABUF_RENDERER for headless Linux benchmark runs - Fix stale action versions: checkout v6->v4, setup-python v6->v5 Bench/Tests: - Migrate benchmark binaries from tao to winit 0.30 + gtk4 - Fix strace float parsing for European locales (strace >= 6.x) - Handle missing mprof gracefully; fix binary size key (libtao->libwinit) Docs: - Update all install commands, event loop idiom, and API refs for gtk4/webkit6 - Rewrite README code examples to use gtk4 directly Examples: - Rewrite gtk_multiwebview using GTK4 Application + Box layout; works on both X11 and Wayland via build_gtk without extra configuration - Fix gtk_opengl for webkit6 Layout: - Set hexpand/vexpand on webview when parented to a GtkBox
Linux additions --------------- - Add `with_enable_media_stream(bool)` and `with_enable_encrypted_media(bool)` to `WebViewBuilder`. On WebKitGTK6 both features are off by default; previously callers had to reach through `WebViewExtUnix::webview()` after construction. On Windows/macOS/Android/iOS the fields are accepted and ignored (those platforms enable both by default). - Enable `linux-body` in the default feature set. Without it, `request.body()` in custom protocol handlers was silently empty on Linux while Windows and macOS always provided the body. WebKitGTK 6.x satisfies the v2.40 version constraint unconditionally, so the guard is always met. Updated `with_custom_protocol` and `with_asynchronous_custom_protocol` rustdoc to document the feature requirement. - Add `WebViewBuilderExtUnix::with_hardware_acceleration_policy(policy)`. Allows forcing software rendering (`HardwareAccelerationPolicy::Never`) without the `WEBKIT_DISABLE_DMABUF_RENDERER=1` environment variable workaround. Useful in headless/CI environments where GPU compositing is unavailable. - Add `WebViewBuilderExtUnix::with_on_web_content_process_terminate_handler(fn)`. Wires up WebKitGTK6's `web-process-terminated` signal. Brings Linux to parity with the equivalent `WebViewBuilderExtDarwin` handler. - Add `WebViewBuilderExtUnix::with_theme(Theme)`. Sets GTK4's `gtk-application-prefer-dark-theme` display setting, which WebKitGTK reads to resolve the `prefers-color-scheme` CSS media feature. Mirrors `WebViewBuilderExtWindows::with_theme`. `Theme::Auto` is a no-op. - Add `WebViewBuilderExtUnix::with_data_directory(path)`. Creates an isolated WebKit `NetworkSession` with persistent data stored under `path` rather than the default system-wide WebKit directory. Linux equivalent of `with_profile_name` (Windows) and `with_data_store_identifier` (macOS). Ignored when an explicit `WebContext` is also supplied. - Add `WebViewExtUnix::data_directory() -> Option<PathBuf>`. Returns the base data directory from the underlying `NetworkSession`, giving callers a path for manual store management — the Linux equivalent of `fetch_data_store_identifiers` / `remove_data_store` on macOS. - Add `WebContext::set_cookie_accept_policy(policy)` (Linux only). Delegates to `CookieManager::set_accept_policy` on the `NetworkSession`. - Improve rustdoc on `with_hotkeys_zoom`, `with_accept_first_mouse`, `with_background_throttling`, and `with_general_autofill_enabled` to explicitly document their no-op status on unsupported platforms rather than silently discarding the value. Cross-platform fixes -------------------- - Fix `WebView::set_background_color` being a no-op on macOS without the `transparent` feature. `setUnderPageBackgroundColor` (public, macOS 12+) now runs unconditionally; `drawsBackground = false` (private KVC) remains behind `#[cfg(feature = "transparent")]`. Previously the entire block was gated on the feature, so the public setter never ran. - Fix `close_devtools()` and `is_devtools_open()` being silent no-ops on Windows. `open_devtools` / `close_devtools` now maintain an `AtomicBool`. `close_devtools` enumerates top-level windows belonging to the WebView2 browser process via `EnumWindows` and sends `WM_CLOSE` to any visible `Chrome_WidgetWin_1` window (the Chromium class used by the DevTools popup). - Expand macOS `permission_handler` to cover Geolocation and Sensors. `requestGeolocationPermissionForOrigin` (macOS 12+) and `requestDeviceOrientationAndMotionPermissionForOrigin` added to `WKUIDelegate`, dispatching to `PermissionKind::Geolocation` and `PermissionKind::Sensors`. Notifications, ClipboardRead, and PointerLock have no `WKUIDelegate` hook and remain unroutable on macOS. - Add `WebView::reparent<W: HasWindowHandle>(&self, window: &W) -> Result<()>` to the base `WebView` type. Replaces incompatible platform-specific signatures (`reparent(isize)` on Windows, `reparent(*mut NSWindow)` on macOS, `reparent(&W: IsA<Widget>)` on Linux). Implemented in all three backends; the Linux path uses `XReparentWindow` and updates the stored `x11_window` XID. `x11_window` is now a `Cell<c_ulong>` to allow mutation through a shared reference during reparent. Examples -------- - Add `examples/gtk_linux_features.rs`. Exercises the five new Linux-only builder APIs in a single GTK4 window: hardware acceleration policy (software rendering via `HardwareAccelerationPolicy::Never`), theme toggling (T key), web-process crash handler with auto-reload (C key), and isolated data directory via `with_data_directory` / `data_directory()` accessor. - Update `examples/gtk_cookies.rs`. Demonstrates the new `WebContext::set_cookie_accept_policy` API: a `CookieAcceptPolicy::Never` context blocks HTTP `Set-Cookie` headers (httpbin's redirect cookie is suppressed) while programmatic `set_cookie()` calls still work. - Update `examples/gtk_permission_handler.rs`. Removes the post-build workaround that reached into the raw webkit6 settings object to enable media stream and encrypted media APIs. Both are now set via the builder methods `with_enable_media_stream(true)` and `with_enable_encrypted_media(true)`. - Update `examples/reparent.rs`. Qualifies the `reparent` call with `WebViewExtUnix::reparent(...)` to resolve the method ambiguity introduced by the new unified `WebView::reparent` on the base type. Testing ------- All changes were developed and tested on Linux (GTK4 / WebKitGTK 6.x). The Windows and macOS cross-platform fixes (`set_background_color`, `close_devtools`, macOS permission handler, and unified `reparent`) could not be verified locally — Windows and macOS testing environments are not available.
Add `--features wayland` to embed WebViews in GTK4-owned Wayland windows via `RawWindowHandle::Wayland`. The backend locates the parent `GtkWindow` by comparing `wl_surface` pointers across GTK toplevels, attaches a `GtkFixed` (child mode) or `GtkBox` (full-window), and scales coordinates using `scale_factor_wayland()` from the GDK surface. Bug fixes bundled in this commit: - Replace busy-spin GLib loop in cookie methods with `iteration(true)` to eliminate full-CPU spin while awaiting async cookie callbacks - Remove direct `widget.size_allocate()` calls (GTK3-era API invalid in GTK4); use `GtkFixed::move_()` + `set_size_request()` instead - Replace string-based container type detection (`type_().name()`) with `dynamic_cast_ref::<gtk::Fixed>()`/`<gtk::Box>()` to correctly match subclasses - Fix `reparent_window()` for child-mode Wayland WebViews — now finds-or-creates a `GtkFixed` instead of always creating a `GtkBox` - Return `Error::WaylandNotSupported` (with actionable hint) when a Wayland handle is passed without the `wayland` feature enabled - Drop cleanup now clears the host `GtkWindow`'s child widget for reuse Add `gdk4-wayland` optional dep and `wayland` feature to `Cargo.toml`. Update `LINUX.md` and module docs to document the new embedding path, HiDPI/fractional-scale notes, and limitations.
New APIs:
- WebViewHandle opaque type (all platforms); WebViewHandleExtUnix/Windows/Darwin traits
- HardwareAccelerationPolicy Wry-owned enum; drops webkit6 dep from callers
- Focus, keyboard, motion, pointer enter/leave, scroll, drag-source,
monitors-changed handlers via GTK4 event controllers
- Clipboard read/write, primary clipboard read/write, set_cursor_from_name
Bug fixes:
- Cookie methods use block_on + _future() instead of mpsc + spin-loop
- DragDropEvent::Enter fires at hover on Wayland (DropTarget preload)
- New-window fallback to plain gtk::Window avoids panic
- Container dispatch via dynamic_cast_ref replaces type name strings
- Remove set_enable_preedit(false) workaround (fixed in WebKitGTK 2.44)
- Unified fractional scale helper (X11 + Wayland via gdk4/v4_12)
- AccessibleRole::None on GtkBox wrappers for AT-SPI passthrough
- size_allocate removed; GtkFixed::move_ + set_size_request used instead
- WaylandWindowNotFound error variant with actionable diagnostic message
BREAKING CHANGE: NewWindowOpener::webview and NewWindowResponse::Create { webview }
renamed to handle: WebViewHandle; with_related_view accepts WebViewHandle.
Increase gtk_simple default size to 1280×800. Set homogeneous on all Box containers in gtk_multiwebview so webviews share space equally in both axes, preventing one view from expanding on right-click.
- Rename `WebViewExtUnix::reparent` to `WebViewExtUnix::reparent_gtk` to avoid method collision with the inherent `WebView::reparent`. - Introduce `WebViewHandle::from_webkit_webview(webkit6::WebView) -> WebViewHandle` to allow wrapping externally created webviews. - Update documentation and examples to reflect these changes.
Pulls in 2 upstream doc-only commits (drag-drop handler platform notes).
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR migrates wry’s Linux backend from GTK3/WebKit2GTK (4.1) to GTK4/WebKitGTK (webkit6), updates supporting APIs/docs/CI, and adds new examples and benchmark adjustments to validate the new stack across X11 and Wayland.
Changes:
- Upgrade Linux dependencies and backend code to
gtk4+webkit6, including related platform glue (events, drag/drop, synthetic input, web context/session). - Introduce/extend cross-platform surface-level APIs (e.g., opaque
WebViewHandle, unified reparent helpers, permission routing updates). - Update examples, benchmarks, CI workflows, and changelog entries to match the new GTK4/WebKitGTK6 requirements and capabilities (incl. Wayland feature path).
Reviewed changes
Copilot reviewed 94 out of 96 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/wkwebview/mod.rs | macOS WKWebView background color behavior; add reparent_window helper |
| src/wkwebview/class/wry_web_view_ui_delegate.rs | Add macOS geolocation/sensors permission callbacks; adapt new-window plumbing to WebViewHandle |
| src/webview2/mod.rs | Track devtools state on Windows; implement best-effort devtools close; add reparent_window helper |
| src/webkitgtk/web_context.rs | Migrate context/session logic to webkit6 NetworkSession; update custom protocol plumbing; add cookie policy setter |
| src/webkitgtk/synthetic_mouse_events.rs | Port back/forward synthetic mouse events to GTK4 controllers/gesture APIs |
| src/webkitgtk/drag_drop.rs | Port drag/drop to GTK4 controllers; improve Wayland enter-path availability via preload |
| src/web_context.rs | Add Linux-only cookie accept policy API |
| src/permissions.rs | Update permission support documentation (macOS + webkit6 Linux additions) |
| src/error.rs | Switch GTK error types to webkit6 glib; add Wayland-specific error variants/messages |
| README.md | Update docs/examples for GTK4/WebKitGTK6, Wayland/X11 features, and event pumping helper |
| examples/winit.rs | Replace GTK3 event pumping with GTK4 main context iteration |
| examples/window_border.rs | Port example from tao to winit; update Linux event pumping; restructure app lifecycle |
| examples/wgpu.rs | Replace GTK3 event pumping with GTK4 main context iteration |
| examples/transparent.rs | Port example from tao to winit; add resize-driven bounds updates; GTK4 event pumping |
| examples/streaming/index.html | Improve streaming demo UI and add remote HTTPS test mode |
| examples/streaming.rs | Port from tao to winit; add resize handling; improve streaming MIME handling |
| examples/simple.rs | Port from tao to winit; add resize handling; update drag-drop logging for new event ordering |
| examples/reparent.rs | Restructure to separate non-Linux winit vs Linux GTK4 paths; update reparent calls |
| examples/permission_handler.rs | Port from tao to winit; add resize handling; GTK4 event pumping |
| examples/multiwindow.rs | Port from tao to winit; add resize handling; GTK4 event pumping |
| examples/multiwebview.rs | Replace GTK3 init/Wayland panic with GTK4 init; update X11 hook gating |
| examples/custom_titlebar.rs | Port from tao to winit; update cursor API usage; add resize handling + GTK4 pumping |
| examples/custom_protocol.rs | Port from tao to winit; add resize handling; GTK4 event pumping |
| examples/cookies.rs | Port from tao to winit; add resize handling; GTK4 event pumping |
| examples/async_custom_protocol.rs | Port from tao to winit; add resize handling; GTK4 event pumping |
| examples/gtk_window_border.rs | New GTK4-native (Wayland-capable) window border example |
| examples/gtk_transparent.rs | New GTK4-native transparent example |
| examples/gtk_streaming.rs | New GTK4-native streaming custom-protocol example |
| examples/gtk_simple.rs | New GTK4-native minimal example |
| examples/gtk_opengl.rs | Rework OpenGL example into GTK4-native implementation + non-Linux stub |
| examples/gtk_multiwindow.rs | New GTK4-native multiwindow example |
| examples/gtk_linux_features.rs | New GTK4-native demo covering new Linux-specific builder/runtime APIs |
| examples/gtk_custom_titlebar.rs | New GTK4-native custom titlebar example |
| examples/gtk_custom_protocol.rs | New GTK4-native custom protocol example |
| examples/gtk_cookies.rs | New GTK4-native cookie management example |
| examples/gtk_async_custom_protocol.rs | New GTK4-native async custom protocol example |
| Cargo.toml | Switch Linux deps to gtk4/webkit6/js core 6; add wayland feature; enable linux-body by default; drop tao dev-dep |
| bench/tests/src/hello_world.rs | Port bench harness from tao to winit; add GTK4 path for Linux/BSD |
| bench/tests/src/custom_protocol.rs | Port bench harness from tao to winit; add GTK4 path for Linux/BSD |
| bench/tests/src/cpu_intensive.rs | Port bench harness from tao to winit; add GTK4 path for Linux/BSD |
| bench/tests/Cargo.toml | Replace tao with winit; add gtk4 dep on Linux/BSD |
| bench/src/utils.rs | Make strace parsing tolerant of locale decimal separators |
| bench/src/run_benchmark.rs | Make benchmarks more robust (missing tools); rename size metrics to winit; adjust paths and time format parsing |
| .gitignore | Ignore bench workspace lockfiles |
| .github/workflows/clippy-fmt.yml | Install libwebkitgtk-6.0-dev + libgtk-4-dev on Ubuntu |
| .github/workflows/build.yml | Install libwebkitgtk-6.0-dev + libgtk-4-dev (+ at-spi2-core) on Ubuntu; update labels |
| .github/workflows/bench.yml | Update checkout/python actions; install GTK4/WebKitGTK6; set DMA-BUF disable env for headless runs |
| .changes/windows-devtools-close-unimplemented.md | Changelog: implement Windows devtools close/state |
| .changes/unified-reparent.md | Changelog: add unified reparent API |
| .changes/streaming-mime-improvements.md | Changelog: streaming example improvements |
| .changes/permission-handler.md | Changelog: permission API wording updates for webkit6/macOS |
| .changes/macos-set-background-color-no-feature.md | Changelog: macOS background color fix without transparent feature |
| .changes/macos-permission-handler-geolocation-sensors.md | Changelog: macOS geolocation + sensors permission support |
| .changes/linux-webview-handle-api.md | Changelog: Linux WebViewHandle::from_webkit_webview |
| .changes/linux-web-process-terminated-handler.md | Changelog: Linux web-process-terminated builder hook |
| .changes/linux-wayland-native-embed.md | Changelog: native Wayland embedding feature |
| .changes/linux-wayland-fractional-scale.md | Changelog: Wayland scaling helper |
| .changes/linux-wayland-doc-update.md | Changelog: Wayland documentation updates |
| .changes/linux-wayland-bug-fixes.md | Changelog: Wayland embedding bug fixes |
| .changes/linux-typed-container-dispatch.md | Changelog: typed container downcasts |
| .changes/linux-theme-control.md | Changelog: theme control on Linux |
| .changes/linux-silent-noop-docs.md | Changelog: clarify no-op builder methods |
| .changes/linux-scroll-handler.md | Changelog: scroll handler on Linux |
| .changes/linux-scale-factor-unified.md | Changelog: unified scale factor helper |
| .changes/linux-reparent-gtk.md | Changelog: rename Unix reparent trait method |
| .changes/linux-remove-size-allocate.md | Changelog: remove internal GTK layout calls |
| .changes/linux-primary-clipboard.md | Changelog: X11 primary selection APIs |
| .changes/linux-opaque-webview-handle.md | Changelog: introduce opaque WebViewHandle |
| .changes/linux-newwindow-plain-window.md | Changelog: fix Linux NewWindowResponse Allow on plain Window |
| .changes/linux-motion-handler.md | Changelog: pointer motion handlers on Linux |
| .changes/linux-monitors-changed-handler.md | Changelog: monitor change handler |
| .changes/linux-media-stream-builder.md | Changelog: media stream/encrypted media builder flags |
| .changes/linux-keyboard-handler.md | Changelog: keyboard handler |
| .changes/linux-ime-preedit-gtk4.md | Changelog: remove IME workaround on gtk4/webkit6 |
| .changes/linux-hardware-acceleration-wry-type.md | Changelog: wry-owned hardware accel policy |
| .changes/linux-hardware-acceleration-policy.md | Changelog: hardware acceleration policy builder |
| .changes/linux-focus-handler.md | Changelog: focus handler |
| .changes/linux-drag-source.md | Changelog: drag source handler |
| .changes/linux-dnd-enter-data-coverage.md | Changelog: Wayland drag enter paths fix |
| .changes/linux-data-directory.md | Changelog: per-webview data directory |
| .changes/linux-data-directory-accessor.md | Changelog: data directory accessor |
| .changes/linux-cursor-from-name.md | Changelog: cursor override API |
| .changes/linux-cookie-blocking-iteration.md | Changelog: cookie methods future/block_on refactor |
| .changes/linux-cookie-accept-policy.md | Changelog: cookie accept policy API |
| .changes/linux-clipboard-write.md | Changelog: clipboard write API |
| .changes/linux-clipboard-read.md | Changelog: clipboard read API |
| .changes/linux-body-default.md | Changelog: enable linux-body by default |
| .changes/linux-accessible-role-passthrough.md | Changelog: accessibility role passthrough tweaks |
| .changes/gtk4-webkit6-linux.md | Changelog: headline GTK4/WebKitGTK6 migration entry |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| pub(crate) fn reparent_window(&self, window: &impl HasWindowHandle) -> crate::Result<()> { | ||
| let ns_view = match window.window_handle()?.as_raw() { | ||
| RawWindowHandle::AppKit(w) => w.ns_view.as_ptr(), | ||
| #[cfg(target_os = "ios")] | ||
| RawWindowHandle::UiKit(w) => w.ui_view.as_ptr(), | ||
| _ => return Err(crate::Error::UnsupportedWindowHandle), | ||
| }; | ||
|
|
||
| unsafe { | ||
| let ns_view: &objc2_app_kit::NSView = &*(ns_view as *const objc2_app_kit::NSView); | ||
| if let Some(ns_window) = ns_view.window() { | ||
| self.reparent(Retained::as_ptr(&ns_window) as *mut NSWindow) | ||
| } else { | ||
| // view not yet attached to a window — add directly as subview | ||
| ns_view.addSubview(&self.webview); | ||
| Ok(()) | ||
| } | ||
| } | ||
| } |
| // strace >= 6.x uses the system locale for decimal/thousands separators | ||
| // (e.g. "0,40" instead of "0.40" on many European locales). Normalise to | ||
| // dot-decimal so Rust's float parser can handle both formats. | ||
| let normalise_float = |s: &str| s.replace(',', "."); | ||
| let parse_f64 = |s: &str| str::parse::<f64>(&normalise_float(s)).unwrap(); |
| gtk::main_iteration_do(false); | ||
| } | ||
| } | ||
| while gtk4::glib::MainContext::default().iteration(false) {} |
| enum UserEvent { | ||
| TogglShadows, | ||
| } |
|
Confirming the verification I'm tagged in above. In a clean Debian trixie container (system WebKitGTK 6.0, GTK 4.18, Rust 1.96), cargo check passes on default features. End to end, a real Tauri app on this branch plus tao#1258 and muda#369 runs with working windows, rendering, keyboard input, and native menus. Happy to re-run both after the rebase on dev, and again as the branch evolves. |
|
@johncarmack1984 When you have the time, can you review the MIGRATION.md and add comments and and thoughts. |
|
Glad to. Calibration first: I'm an outside contributor here, same as you. Nothing below carries maintainer weight, and the review that moves this PR is the wry team's. What I can offer is that I've built against this exact rev, so I read the doc against the code and against what I actually hit. Overall it's a good guide. The section order matches the order a real migration hits things, and the "why" notes are the part most migration docs skip. The reparent section explaining the inherent-method shadowing is exactly the kind of thing that saves someone a silent wrong call. Same for the known-issues entries naming what isn't a wry bug. Three concrete items:
Minor: section 3 says when to call Everything else I checked holds: the dep and feature tables, the |
|
Thanks for the review, @johncarmack1984 Fixed:
Also found and fixed an unrelated IPC panic while in there: the script-message callback in |
# Conflicts: # Cargo.toml
|
Re-ran both after the merge with dev, at 0411857. Same trixie setup (GTK 4.18.6, WebKitGTK 2.52.3, Rust 1.97): cargo check passes on default features. The same Tauri app on this branch plus tao#1258 and muda#369 still runs end to end: windows, rendering, keyboard input, native menus. Consumer note: my tauri fork needed four lines for the reparent_gtk and handle renames, and MIGRATION.md already documents both. The doc holds up in practice. gtk_simple also renders on both X11 and headless Wayland at this rev. |
# Conflicts: # README.md # src/webkitgtk/mod.rs
|
Hi! Just a small follow-up since it's been a little while. I know it's the middle of summer, and this PR touches almost 100 files, so I completely understand that it takes time to review. I've kept this PR up to date by merging the latest upstream changes twice, so it should still be based on the current Since opening this PR, I've also started porting my own application (Marco) to use this GTK4/WebKit6 branch of Wry on Linux instead of using The Marco port is still a work in progress, but the Wry implementation is already working well in practice and has been tested in a real application. Whenever someone has time to review, I'd really appreciate any feedback — whether it's about the overall direction or specific implementation details. If there are changes you'd like to see before this can move forward, I'm happy to make them. |
Brings in wry 0.56.0 and the breaking removal of the `protocol`, `transparent`, and `fullscreen` feature flags. Conflict resolutions: - Cargo.toml: adopt upstream feature removals; keep this branch's `linux-body` (no webkit2gtk/v2_40 gate) and its inclusion in `default`. `tao` dev-dependency stays dropped since examples use winit/gtk4. - examples: apply upstream's `protocol` de-gating to this branch's winit/gtk4 rewrites, including the gtk_* examples upstream doesn't have. - src/lib.rs, README.md: keep gtk4/webkit6 docs; add upstream's `mac-proxy` feature entry and document the branch's `wayland` feature. - src/wkwebview/mod.rs: un-gate the `drawsBackground` call in `set_background_color`, matching upstream now that `transparent` is gone. - .changes/permission-handler.md: deleted, consumed by upstream's 0.56.0 release.
Brings in 4 upstream commits: - fix(android): override getDefaultVideoPoster to suppress placeholder (tauri-apps#1804) - fix(windows): ignore `MoveFocus` error on creation (tauri-apps#1799) - docs(android): why `WEBVIEW_ATTRIBUTES` exists (tauri-apps#1801) - fix(bench): rlib location on new nightly (tauri-apps#1800) Conflict in bench/src/run_benchmark.rs: upstream reworked `rlib_size` to take a bare library name and return `Result`, while this branch had switched the second measured rlib from tao to winit (this branch uses winit instead of tao for examples/dev-deps). Resolved by keeping upstream's new signature and calling it with "winit".
Pre-existing rustfmt violations in code added by this branch. CI runs `cargo fmt --all -- --check` on stable, so these would block the PR. Mechanical reformat only, no behavior change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts: # Cargo.lock # src/webkitgtk/mod.rs
This PR is a community contribution for #1474 — migrating the Linux backend from gtk3/webkit2gtk 4.1 to gtk4 0.11 / webkit6 0.6.
I've been developing this on my fork for a while and posted status updates on the issue thread along the way (June 23 and June 30 comments on #1474). @johncarmack1984 reviewed the branch and validated it end-to-end inside a real Tauri app; his feedback has been incorporated. I'm submitting it here in the hope it's useful as a base for the migration — I'm happy to rework any part of it, split it into smaller PRs, or adjust the approach based on your review.
What this covers
From the checklist in #1474:
gtk→gtk40.11 and handle all resulting errorswebkit2gtk→webkit60.6 and handle all resulting errorswrytogtk4-rsandwebkit6#1474 thread for early feedback before opening this PRMIGRATION.mdandLINUX.mdcargo checkandcargo clippypass cleanly on default features. All CI workflows are updated to installlibwebkitgtk-6.0-dev+libgtk-4-dev.Breaking changes (feedback especially welcome here)
These are the changes I couldn't make backwards-compatible. Full details with before/after code are in
MIGRATION.md; if any of them conflict with tauri's plans, I'm glad to revisit.WebViewHandle(cross-platform) —NewWindowOpener::webviewandNewWindowResponse::Create { webview }no longer expose raw platform types (webkit2gtk::WebView/ICoreWebView2/Retained<WKWebView>). Platform access goes through extension traits:WebViewHandleExtUnix::as_webkit_webview(),WebViewHandleExtWindows::as_core_webview2(),WebViewHandleExtDarwin::as_wk_webview(). AWebViewHandle::from_webkit_webviewconstructor lets embedders wrap externally-built views (thanks @johncarmack1984 for the constructor commit).with_related_viewtakesWebViewHandle(Linux) instead of a rawwebkit2gtk::WebView.wry::HardwareAccelerationPolicy— the policy enum is now a wry-owned type, so consumers no longer need a directwebkit6dependency to set it. Variants (Always/Never) are unchanged.reparent→reparent_gtk(Linux) — renamed because the new cross-platform inherent methodWebView::reparent(&impl HasWindowHandle)would silently shadow the trait method at existing call sites.build_gtkcontainer bound — now acceptsgtk4::Widget(GTK4 removed theContainerclass).new_gtkwas renamed tobuild_gtk.linux-bodyis now a default feature — WebKitGTK 6.x is above the v2.40 minimum it needed, so the silent empty-body behavior on Linux is gone. This changes whatdefault-features = trueconsumers compile.libwebkit2gtk-4.1-dev→libwebkitgtk-6.0-dev+libgtk-4-dev(per-distro table inMIGRATION.md).gtk::init()→gtk4::init(); the manualgtk::main_iteration_do(false)pattern is replaced by a newwry::pump_platform_events()helper for non-GTK windowing integration (winit et al.).X11 embedding note: my June 30 status update listed raw-handle X11 embedding as broken by design under GTK4. That turned out to be solvable —
build()/build_as_child()with an X11 handle now reparents the realized GTK surface's XID under the target window, andWebView::reparentcan move it between windows.build_gtkremains the recommended path for code that must run on both X11 and Wayland; manualset_boundscaveats are documented on the builder.New APIs and features
waylandcargo feature) —RawWindowHandle::Waylandsupport for realized GTK4 windows.v4_12soft dependency, with integer fallback below 4.12.WebViewBuilderExtUnix/WebViewExtUnixAPIs: scroll/focus/keyboard/motion handlers, clipboard (incl. X11 primary selection), cursor control, drag source, monitor-change and web-process-crash handlers, isolated per-webview data directories, cookie accept policy, theme control, hardware-acceleration policy, media-stream enable. Full table inMIGRATION.md§9, docs inLINUX.md. If this expands the API surface further than you'd like for the initial migration, I can split these into follow-up PRs.set_enable_preedit(false)workaround for the Fcitx popup-at-(0,0) bug is removed (fixed upstream in WebKitGTK 2.44) — inline CJK composition now works.Documentation added
MIGRATION.mdCargo.toml, GTK init/event loop, builder API,WebViewHandle, import paths, X11/Wayland embedding, behavioral differences, known issuesLINUX.md.changes/gtk4-webkit6-linux.md(minor bump), with individual entries per API addition and behavioral change — happy to consolidate or re-bump these to fit your release planA full set of GTK4-native
gtk_*examples was added as Wayland-capable counterparts to every winit example (gtk_simple,gtk_multiwebview,gtk_multiwindow,gtk_streaming,gtk_transparent,gtk_permission_handler,gtk_opengl, …) — run commands inLINUX.md.How it was tested
cargo checkclean; plus an end-to-end run of a real Tauri app on the full gtk4 stack (this branch + feat(linux): port to gtk4 tao#1258 + feat(gtk): port the backend to gtk4 muda#369): window, rendering, keyboard input, and menus all workingWEBKIT_DISABLE_DMABUF_RENDERER=1for headless xvfbRelated work
Open questions
wrytogtk4-rsandwebkit6#1474, but if the working group decides differently I'd like to know how that affects this PR.wrytogtk4-rsandwebkit6#1474) — I'll adjust the version bump and change entries to whatever fits the release plan.Thanks to @johncarmack1984 for the detailed reviews, integration testing, and the
WebViewHandleconstructor; @conradhale and @rmakestrash-jpg for the tao groundwork; and @FabianLars and @tweidinger for guidance on direction. I know this is a big diff — if it's easier to review in stages, tell me how you'd like it split and I'll do the legwork.