diff --git a/CHANGELOG.md b/CHANGELOG.md index 80388d5..141ebd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ GitHub are taken from the matching section here. renderer. - Clicking while a Roblox text box has focus no longer closes it. Only Roblox decides when a click ends typing. +- Going to another page in the web view, such as Friends from a profile, no + longer closes the web view. It crashed on every page change on Wayland + systems whose GL setup GTK could not use. ## [0.3.2] - 2026-09-29 diff --git a/src/webview/mocktail_webview_helper.cc b/src/webview/mocktail_webview_helper.cc index 76c3daf..3ff579c 100644 --- a/src/webview/mocktail_webview_helper.cc +++ b/src/webview/mocktail_webview_helper.cc @@ -1424,6 +1424,11 @@ void Activate(GtkApplication* application, gpointer user_data) { state->disable_hardware_acceleration = mocktail::webview::ShouldDisableWebViewHardwareAcceleration( wayland_display, std::getenv("WEBKIT_DISABLE_COMPOSITING_MODE")); + // GTK picks its renderer when a window is realized, which is after this. + if (mocktail::webview::ShouldForceSoftwareGtkRenderer( + state->disable_hardware_acceleration, std::getenv("GSK_RENDERER"))) { + setenv("GSK_RENDERER", "cairo", 0); + } std::cerr << "[webview] display=" << (wayland_display ? "wayland" : "other") << " compositing=" << (state->disable_hardware_acceleration ? "software" : "default") diff --git a/src/webview/webview_helper_policy.cc b/src/webview/webview_helper_policy.cc index d9e1730..828b252 100644 --- a/src/webview/webview_helper_policy.cc +++ b/src/webview/webview_helper_policy.cc @@ -133,6 +133,11 @@ bool ShouldDisableWebViewHardwareAcceleration( return wayland_display; } +bool ShouldForceSoftwareGtkRenderer(bool software_compositing, + const char* renderer_override) { + return software_compositing && renderer_override == nullptr; +} + const char* AndroidBridgeSource() { return kBridgeSource; } std::string BuildRobloxAndroidUserAgent() { diff --git a/src/webview/webview_helper_policy.h b/src/webview/webview_helper_policy.h index 4e3e783..e2333f2 100644 --- a/src/webview/webview_helper_policy.h +++ b/src/webview/webview_helper_policy.h @@ -38,6 +38,13 @@ bool ShouldDisableWebKitSandbox(std::string_view kernel_version, // Match WebKit's WEBKIT_DISABLE_COMPOSITING_MODE override semantics. bool ShouldDisableWebViewHardwareAcceleration( bool wayland_display, const char* compositing_override); +// GTK's GL renderer aborts in libepoxy when it snapshots a page switch on +// hosts where its GL context cannot become current. With software compositing +// the helper does not need GL for its UI, so use the Cairo renderer unless the +// user chose one through GSK_RENDERER. +bool ShouldForceSoftwareGtkRenderer(bool software_compositing, + const char* renderer_override); + const char* AndroidBridgeSource(); std::string BuildRobloxAndroidUserAgent(); bool IsBrowserLoginUrl(std::string_view url); diff --git a/tests/webview_helper_policy_test.cc b/tests/webview_helper_policy_test.cc index ee1f754..26dcfde 100644 --- a/tests/webview_helper_policy_test.cc +++ b/tests/webview_helper_policy_test.cc @@ -134,6 +134,19 @@ TEST(WebViewHelperPolicyTest, HonorsExplicitCompositingEnvironment) { } } +TEST(WebViewHelperPolicyTest, ForcesCairoRendererWithSoftwareCompositing) { + EXPECT_TRUE(ShouldForceSoftwareGtkRenderer(true, nullptr)); + EXPECT_FALSE(ShouldForceSoftwareGtkRenderer(false, nullptr)); +} + +TEST(WebViewHelperPolicyTest, HonorsExplicitGtkRendererEnvironment) { + for (bool software_compositing : {false, true}) { + for (const char* value : {"gl", "vulkan", "cairo", ""}) { + EXPECT_FALSE(ShouldForceSoftwareGtkRenderer(software_compositing, value)); + } + } +} + TEST(WebViewHelperPolicyTest, AllowsOnlyTlsTopLevelNavigation) { const UriPolicyResult roblox = EvaluateNavigationUri("https://www.roblox.com/login");