//go:build linux && !386 package main import ( "os" "strings" ) // init runs before Wails' own init(), so the env vars are set in time. func init() { disableDMABUFRenderer() disableCompositingMode() disableWebKitSandboxIfNeeded() } func disableDMABUFRenderer() { if os.Getenv("WEBKIT_DISABLE_DMABUF_RENDERER") != "" { return } // WebKitGTK's DMA-BUF renderer fails on many setups (VMs, containers, // minimal WMs without proper GPU access) and leaves the window blank // white. Wails only disables it for NVIDIA+Wayland, but the issue is // broader. Always disable it — software rendering works fine for a // small UI like this. _ = os.Setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1") } // disableCompositingMode turns off WebKitGTK's accelerated (GL) compositing // path. Disabling the DMA-BUF renderer alone is not enough on some Intel // setups: WebKitGTK 2.52 still drives the GPU through the GL compositor, and // Mesa's anv/i965 hits unimplemented DRM-format-modifier code paths // ("FINISHME: support YUV colorspace with DRM format modifiers" / // "...multi-planar formats...") that crash with a SIGSEGV inside // g_application_run before the first frame paints. Forcing compositing off // makes WebKit render on the CPU, which is fine for a small UI like this and // sidesteps the broken modifier path. The user can re-enable it by setting // WEBKIT_DISABLE_COMPOSITING_MODE themselves (e.g. to "0"). func disableCompositingMode() { if os.Getenv("WEBKIT_DISABLE_COMPOSITING_MODE") != "" { return } _ = os.Setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1") } // disableWebKitSandboxIfNeeded works around WebKitGTK crashing at startup when // its bubblewrap (bwrap) sandbox can't create an unprivileged user namespace — // "bwrap: setting up uid map: Permission denied" followed by "Failed to fully // launch dbus-proxy" and a panic in webkit_web_view_load_uri. This happens in // containers/VMs and on Ubuntu 24.04+ where AppArmor restricts unprivileged // user namespaces (kernel.apparmor_restrict_unprivileged_userns=1). Software // can't grant the namespace from here, so when we detect that userns are // blocked we disable the WebKit sandbox to keep the UI usable. The user can // override either way by setting WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS. func disableWebKitSandboxIfNeeded() { if _, set := os.LookupEnv("WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS"); set { return } if unprivilegedUsernsAllowed() { return } _ = os.Setenv("WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS", "1") } // unprivilegedUsernsAllowed reports whether the kernel currently permits // unprivileged user namespaces, which WebKit's bwrap sandbox needs. It reads // the relevant procfs knobs; on a kernel that doesn't expose them (older or // hardened), it conservatively assumes namespaces are available so we don't // needlessly weaken the sandbox. func unprivilegedUsernsAllowed() bool { // Debian/Ubuntu legacy switch: 0 disables unprivileged user namespaces. if v, err := os.ReadFile("/proc/sys/kernel/unprivileged_userns_clone"); err == nil { if strings.TrimSpace(string(v)) == "0" { return false } } // Ubuntu 24.04+ AppArmor restriction: non-zero restricts/blocks them. if v, err := os.ReadFile("/proc/sys/kernel/apparmor_restrict_unprivileged_userns"); err == nil { if strings.TrimSpace(string(v)) != "0" { return false } } return true } // On Linux, the system tray provider may require the menu to be recreated // rather than updated in place. The rebuildExitNodeMenu method in tray.go // already handles this by removing and re-adding items; no additional // Linux-specific workaround is needed for Wails v3.