diff --git a/Cargo.lock b/Cargo.lock index 95ee2de..65e1207 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,7 @@ dependencies = [ "base64", "clap", "dirs", + "gtk", "image", "serde_json", "tao", diff --git a/README.md b/README.md index b8f8570..8f9c024 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ cargo run -- --title "RustyWolf" cargo run -- --private cargo run -- --dry-run -# Linux backend controls (wayland has issues currently, x11 recommended) +# Linux backend controls cargo run -- --linux-backend x11 cargo run -- --linux-backend wayland cargo run -- --linux-disable-dmabuf @@ -89,10 +89,29 @@ source "$HOME/.cargo/env" ```bash doas emerge --sync doas emerge --ask net-libs/webkit-gtk:4.1 x11-libs/gtk+ virtual/pkgconfig dev-vcs/git x11-misc/appmenu-gtk-module +doas mkdir -p /etc/portage/package.use +echo ">=media-libs/gst-plugins-base-1.24.13-r1 gbm" | doas tee /etc/portage/package.use/rustywolf-media +doas emerge --ask 'media-libs/gst-plugins-base[gbm]' media-plugins/gst-plugins-soup media-plugins/gst-plugins-vpx media-plugins/gst-plugins-hls media-plugins/gst-plugins-dash media-plugins/gst-plugins-libav curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh source "$HOME/.cargo/env" ``` +For NVIDIA, make the DRM modeset setting part of the boot command line, not only +`/etc/modprobe.d`, then reboot: + +```bash +doas cp /etc/default/grub /etc/default/grub.bak +doas sed -i 's/^#GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="nvidia-drm.modeset=1 nvidia-drm.fbdev=1"/' /etc/default/grub +doas grub-mkconfig -o /boot/grub/grub.cfg +doas reboot +``` + +After reboot, verify the active command line: + +```bash +cat /proc/cmdline +``` + ## Linux media playback deps (important) If Linux logs `gstreamer element autoaudiosink not found` or YouTube/audio fails, install GStreamer audio/video plugins. @@ -120,19 +139,27 @@ If your distro is not Debian-based, install the equivalent GStreamer base/good/b RustyWolf supports both X11 and native Wayland on Linux. Some NVIDIA + WebKitGTK stacks can fail with dmabuf/gbm allocation errors, especially on Wayland. +On NVIDIA X11, RustyWolf disables WebKitGTK's broken dmabuf renderer automatically. +This avoids the blank webview/GBM allocation failure while keeping GStreamer media +codecs available for sites such as YouTube. Try these launch modes: ```bash -# safest fallback on many NVIDIA setups -cargo run -- --linux-backend x11 --linux-disable-dmabuf +# auto backend (also applies the NVIDIA/X11 WebKitGTK fallback when needed) +cargo run # native wayland cargo run -- --linux-backend wayland +# X11/XWayland +cargo run -- --linux-backend x11 -# auto backend, dmabuf disabled only +# last-resort compatibility fallback cargo run -- --linux-disable-dmabuf + +# force the upstream dmabuf renderer anyway +WEBKIT_FORCE_DMABUF_RENDERER=1 cargo run ``` If you still see `Failed to load module "appmenu-gtk-module"`, that is a desktop GTK setup issue (not a RustyWolf crash). diff --git a/src/README.md b/src/README.md deleted file mode 100644 index 3ae7382..0000000 --- a/src/README.md +++ /dev/null @@ -1,174 +0,0 @@ -# RustyWolf - -RustyWolf is a minimal, privacy-focused browser shell built with Rust + system webviews. - -(complete honesty, this whole thing is vibecoded, however I never paid for any ai service (I got a free student plan for a year) so if you wanna avoid AI slop, just skip this but I never contributed to the AI BOOM with my money, if you wanna contribute, feel free to do so) - -- macOS: native `WKWebView` -- Linux: `WebKitGTK` -- Windows: `WebView2` - -No Firefox install. No extension system. Fast startup, clean UI. - -image - -## What It Does - -- Really, I mean really lightweight! the reason I even made this is because I need a lightweight browser to run on my old macbook unibody 2010 4gb ddr3 - - So light in fact in my gentoo(openrc)+i3wm setup it took only 285mb ram with one tab open (dvorakmortonxd.dev) compared to firefox which took 866mb ram - - THATS 3.04 TIMES AS MUCH RAM, so yeah it is light - - tabs have a toggle for Keeping-in-ram (`K`), it basically just saves the url if its off and reloads it on reclick, if you toggle it on it keeps the whole page in ram. -- Privacy-first defaults: DuckDuckGo home + search fallback from the URL bar -- Multi-tab browsing with back, forward, reload, and keyboard shortcuts (`Ctrl/Cmd+T`, `W`, `L`) -- Built-in custom adblock with top-bar toggle (`ADS`) -- Popup permission gate: asks before a site opens a new tab -- Download support with live progress panel (`D`) and session download history -- Properties page with session browsing history + download history -- Default window size `1000x600` (still fully resizable) -- Optional `--private` mode when backend support is available - -## Run - -```bash -cargo run -- -``` - -```bash -cargo run -- --url https://example.com -cargo run -- --url example.com -cargo run -- --title "RustyWolf" -cargo run -- --private -cargo run -- --dry-run - -# Linux backend controls -cargo run -- --linux-backend x11 -cargo run -- --linux-backend wayland -cargo run -- --linux-disable-dmabuf -cargo run -- --linux-backend x11 --linux-disable-dmabuf -``` - -## Privacy Notes - -RustyWolf applies baseline hardening in page context: - -- `navigator.doNotTrack = "1"` -- disables legacy `openDatabase` -- disables `RTCPeerConnection` - -Adblocking is built-in and lightweight. It is not full uBlock Origin parity. - -# Linux Setup (prerequisites) - -Install WebKitGTK development/runtime packages before building. - -## Debian - -```bash -sudo apt update -sudo apt install -y libwebkit2gtk-4.1-dev libgtk-3-dev build-essential pkg-config git appmenu-gtk3-module appmenu-gtk2-module -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -source "$HOME/.cargo/env" -``` - -## Arch - -```bash -sudo pacman -Sy -sudo pacman -S --needed webkit2gtk-4.1 gtk3 base-devel pkgconf git appmenu-gtk-module -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -source "$HOME/.cargo/env" -``` - -## Gentoo - -(u can replace doas with sudo btw) -```bash -doas emerge --sync -doas emerge --ask net-libs/webkit-gtk:4.1 x11-libs/gtk+ virtual/pkgconfig dev-vcs/git x11-misc/appmenu-gtk-module -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -source "$HOME/.cargo/env" -``` - -## Linux media playback deps (important) - -If Linux logs `gstreamer element autoaudiosink not found` or YouTube/audio fails, install GStreamer audio/video plugins. - -Debian/Ubuntu/Pop!_OS example: - -```bash -sudo apt update -sudo apt install -y gstreamer1.0-tools -sudo apt install -y gstreamer1.0-plugins-base gstreamer1.0-plugins-good -sudo apt install -y gstreamer1.0-plugins-bad gstreamer1.0-libav -sudo apt install -y gstreamer1.0-pulseaudio gstreamer1.0-pipewire gstreamer1.0-alsa -``` - -Verify the sink exists: - -```bash -gst-inspect-1.0 autoaudiosink -``` - -If your distro is not Debian-based, install the equivalent GStreamer base/good/bad/libav + audio sink plugin packages. - -# Linux Troubleshooting (Wayland/X11) - -RustyWolf supports both X11 and native Wayland on Linux. Linux webviews are hosted through GTK in both modes, which avoids the X11-only child-window path. - -Some NVIDIA + WebKitGTK stacks can fail with dmabuf/gbm allocation errors, especially on Wayland. - -Try these launch modes if your desktop session or GPU stack needs a specific backend: - -```bash -# native wayland -cargo run -- --linux-backend wayland - -# X11/XWayland -cargo run -- --linux-backend x11 - -# NVIDIA/GBM fallback -cargo run -- --linux-backend x11 --linux-disable-dmabuf - -# auto backend, dmabuf disabled only -cargo run -- --linux-disable-dmabuf -``` - -If you still see `Failed to load module "appmenu-gtk-module"`, that is a desktop GTK setup issue (not a RustyWolf crash). - -Debian/Ubuntu/Pop!_OS fix: - -```bash -sudo apt update -sudo apt install -y appmenu-gtk3-module appmenu-gtk2-module -``` - -If you do not want global appmenu integration, remove `appmenu-gtk-module` from GTK settings files: - -```bash -~/.config/gtk-3.0/settings.ini -/etc/gtk-3.0/settings.ini -/etc/xdg/gtk-3.0/settings.ini -``` - -# MacOS - -## installing Homebrew (skip if already installed) - -```bash -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -``` - -# Windows Setup - -Install the Microsoft Edge WebView2 Runtime (Evergreen), then build normally with Rust MSVC toolchain. - -- WebView2 Runtime: https://developer.microsoft.com/microsoft-edge/webview2/ -- Rust toolchain target: `x86_64-pc-windows-msvc` - -## Dev Quick Checks - -```bash -cargo fmt -cargo check -cargo test -``` diff --git a/src/webview.rs b/src/webview.rs index 27ba488..f682850 100644 --- a/src/webview.rs +++ b/src/webview.rs @@ -119,7 +119,7 @@ struct DownloadEntry { updated_at: String, } -#[cfg_attr(not(target_os = "linux"), allow(dead_code))] +#[allow(dead_code)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum WebViewHostMode { Child, @@ -737,8 +737,10 @@ pub fn launch_webkit(args: &Cli) -> Result<()> { .unwrap_or_else(|| "RustyWolf".to_string()); if args.dry_run { + let effective_dmabuf = + std::env::var("WEBKIT_DISABLE_DMABUF_RENDERER").unwrap_or_else(|_| "0".to_string()); println!( - "engine=webkit url={start_url} private={} linux_backend={:?} linux_disable_dmabuf={}", + "engine=webkit url={start_url} private={} linux_backend={:?} linux_disable_dmabuf={} effective_webkit_disable_dmabuf={effective_dmabuf}", args.private, args.linux_backend, args.linux_disable_dmabuf ); return Ok(()); @@ -847,15 +849,65 @@ fn apply_linux_runtime_overrides(_args: &Cli) { }, } - if _args.linux_disable_dmabuf { + if should_disable_webkit_dmabuf(_args) { // WebKitGTK + NVIDIA can fail with dmabuf/gbm allocation on some systems. - unsafe { - std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); + if std::env::var_os("WEBKIT_DISABLE_DMABUF_RENDERER").is_none() { + unsafe { + std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); + } + + if !_args.linux_disable_dmabuf { + eprintln!( + "Detected NVIDIA X11 WebKitGTK; disabled broken dmabuf renderer. Media codecs remain enabled." + ); + } } } } } +#[cfg(target_os = "linux")] +fn should_disable_webkit_dmabuf(args: &Cli) -> bool { + if args.linux_disable_dmabuf { + return true; + } + + if std::env::var("WEBKIT_FORCE_DMABUF_RENDERER") + .ok() + .as_deref() + == Some("1") + { + return false; + } + + is_linux_x11_session() && is_linux_nvidia_graphics() +} + +#[cfg(target_os = "linux")] +fn is_linux_x11_session() -> bool { + std::env::var("XDG_SESSION_TYPE") + .map(|value| value.eq_ignore_ascii_case("x11")) + .unwrap_or(false) + || (std::env::var_os("DISPLAY").is_some() && std::env::var_os("WAYLAND_DISPLAY").is_none()) +} + +#[cfg(target_os = "linux")] +fn is_linux_nvidia_graphics() -> bool { + env_value_contains("__GLX_VENDOR_LIBRARY_NAME", "nvidia") + || env_value_contains("GBM_BACKEND", "nvidia") + || env_value_contains("__NV_PRIME_RENDER_OFFLOAD", "1") + || Path::new("/proc/driver/nvidia/version").exists() + || Path::new("/sys/module/nvidia/version").exists() + || Path::new("/dev/nvidiactl").exists() +} + +#[cfg(target_os = "linux")] +fn env_value_contains(name: &str, needle: &str) -> bool { + std::env::var(name) + .map(|value| value.to_ascii_lowercase().contains(needle)) + .unwrap_or(false) +} + #[cfg(target_os = "linux")] fn sanitize_gtk_modules_env() { fn is_appmenu_module(token: &str) -> bool {