Nimbin[12]?Web & Tools / Browser / README.md

Browser git · main

Minimal browser in C (mini and big variant)

browser c · first commit 2026-08-25 · last commit 2026-10-05 (4 days ago) · synced 3 days ago · upstream: github.com/nimbin2/Browser

C 95.8% Markdown 3.9%
git clone https://git.christianimmanuel.de/web-tools/Browser.gitwget https://git.christianimmanuel.de/web-tools/Browser/archive/Browser.tar.gz
README.md 8.6 KB · 232 lines raw

browser-mini / browser-big

Two WebKitGTK 6.0 (GTK4) browsers sharing one core.

100% Vibecode but tested. Builds warning-free with -Wall -Wextra. Used for real video calls on WebKitGTK 2.54.0 with GStreamer 1.28.7.

Files

FileWhat it is
browser_core.c / .hWindow, keys, history, downloads, profiles, config
browser-mini.cFills in the hooks and calls browser_main()
browser-big.cCamera, GStreamer and WebRTC repairs, diagnostics
patches/Three upstream fixes for WebKitGTK and GStreamer (see Patches)
HANDOVER.mdBackground: each upstream bug and workaround, with evidence

Build

Debian or any Linux distro:

apt install build-essential pkg-config libgtk-4-dev libwebkitgtk-6.0-dev \
            libsoup-3.0-dev libgstreamer1.0-dev
make                # build both
make install        # into /usr/bin (PREFIX=... to change)
make uninstall
make clean
make version        # 4.39.0 (build …), md5 of the sources

Usage

browser-mini [URL] [options]
browser-big  [URL|PATH|diag] [options]

No address opens the start page. No scheme means https; a path opens as a file. -h lists every option and key.

Keys

KeyAction
Ctrl+O, Ctrl+LAddress (history below it)
Ctrl+HHistory
Ctrl+J / Ctrl+Shift+JBack / forward
Ctrl+FFind
Ctrl+SDownload directory for page, site or everything
Ctrl+KSearch keywords
Ctrl+DRecent downloads
Ctrl+P / Ctrl+YShow / copy the URL
Ctrl+G / Ctrl+Shift+GTop / bottom
Ctrl+R, F5Reload
Ctrl+plus/minus/0Zoom
F1Key list
F2Media mode (Ctrl+click sends videos to player, images to image_viewer)
F6Redraw without reloading
F12Developer tools

--mod alt|super|meta moves the modifier off Ctrl. browser-big adds Ctrl+Shift+M (diagnostics page), Ctrl+Shift+T (web process threads), Ctrl+Shift+V (video element state), Ctrl+Shift+C / X (warm / release the camera).

Features

Paths

browser-mini --paths prints them all.

PathWhat
~/.config/swov/configShared palette, read first
~/.config/browser-{mini,big}/configSettings
~/.local/share/wkview/<profile>/Cookies, history, search keywords, permissions
~/.local/share/wkview/download-dirs.tsvDownload rules (all profiles)
~/.cache/wkview/<profile>/Cache, safe to delete

--clear-data wipes the profile. --forget-permissions drops camera and microphone answers.

Config

key = value, # comments, colours as RRGGBB[AA]. The command line wins. Every key is also an option: --hl=ff8800. -c PATH reads one file only, -n reads none.

Patches

Video calls need three upstream fixes. They are real bugs in current releases, not configuration, and none is upstream yet.

FileApplies toWithout it
webkit-videorate-skip-to-first.patchWebKitGTK 2.52 / 2.54Own camera freezes or goes black, hundreds of frames per second, CPU pinned (WebKit PR 74373)
webkit-caps-normalize.patchWebKitGTK 2.54Camera modes listed as 640 x {480, 360} are ignored. Many laptop cameras get no 4:3 mode, so 16:9 with black bars
gst-glupload-null-meta.patchGStreamer 1.28 (gst-plugins-base)Web process crashes on a site's second camera request

Apply in the source tree, then rebuild and reinstall that package:

cd webkitgtk-2.54.0
patch -p1 < /path/to/patches/webkit-videorate-skip-to-first.patch
patch -p1 < /path/to/patches/webkit-caps-normalize.patch

cd gstreamer-1.28.x/subprojects/gst-plugins-base   # or the plain gst-plugins-base tarball
patch -p1 < /path/to/patches/gst-glupload-null-meta.patch

Add --dry-run first to check. Without the GStreamer patch, WEBKIT_GST_DISABLE_GL_SINK=1 avoids the crash at some CPU cost.

Check that they work:

Video calls

browser-big repairs these WebKit problems by default:

RepairWhy
libnice ICElibrice finds no public address, so nothing connects past the LAN. ice = rice undoes it
VP8 firstWebKit encodes the first codec of its own offer and ignores the answer. video_codecs = native undoes it
Real SSRC and payload typeWebKit writes no a=ssrc lines. mediasoup sites get the values WebKit really sends
RTCRtpSendParameters.codecsWebKit requires it; some libraries omit it
Camera without soundA remote stream with silent audio is shown video-only, since WebKit's player waits for audio
Permission stateAnswered from remembered permissions, so sites see device labels
Camera frame rateWebKit only takes modes with the exact requested frame rate. A soft limit is dropped. cam_size_fix = no undoes it

--no-fix-webrtc turns off the SSRC, parameters and silent-audio repairs. --no-cam-fix injects nothing.

Permissions. A request asks at the top of the window: Enter allows, Esc denies, remembered per site. media = ask|allow|deny in the config.

Per machine:

# ~/.config/browser-big/config
audio = alsa                     # no sound server
mic_match = ThinkPad             # mic whose label contains this text
feature = OffscreenCanvas=off    # Zoom
web_compat = yes                 # Zoom: screen.orientation

mic_match / cam_match pick a device by label. mic_match overrides the microphone a site asks for. arecord -l lists microphones.

When a call does not work

browser-big URL --rtc-trace 2>&1 | tee /tmp/bb.log
LineMeans
sdpEach description, codecs as payload-type name
ssrc-real, ssrc-ws, pt-fixedThe server got the real SSRC and payload type
rtc-statsEvery 3 s: out- sent, far- server report, in-* received
video-stateEach <video>: size, frames shown
video-audio-splitA silent-audio stream shown video-only
codec-mismatchWe encode something the far end did not agree to

Without a server: browser-big https://webrtc.github.io/samples/src/content/peerconnection/pc1/ --rtc-trace. If that works, WebKit's WebRTC is fine and the problem is site-specific.

Camera: browser-big --list-cameras shows every mode each camera offers. Check ls -l /dev/video* and membership in group video.

Crash: attach gdb before starting the camera:

gdb -p $(pgrep -nx WebKitWebProcess) -batch \
    -ex 'handle SIGUSR1 SIGUSR2 SIGPIPE SIG34 SIG35 nostop noprint pass' \
    -ex continue -ex 'thread apply all bt 30' > /tmp/bt.txt 2>&1

browser-big options

Option
--rtc-traceEvery WebRTC step, stats, video elements
--media-traceEvery getUserMedia call and result
--media-debugVerbose media, permission and capture logs
--list-camerasCamera modes, then exit
--gst-debug SPECGStreamer logging, e.g. webrtc*:5
--gst-rank SPECAppend to GST_PLUGIN_FEATURE_RANK
--cam-shareA repeated request gets the camera already open
--no-micCamera only
--audio-alsaALSA instead of PulseAudio
--no-hw-decode, --no-vaSoftware decoding / no VA-API

When a page renders badly

Try one at a time; the first that helps names the layer:

browser-mini URL --no-jit          # JavaScript JIT
browser-mini URL --no-dmabuf       # WebKit's dmabuf renderer
browser-mini URL --no-compositing
browser-mini URL --no-gpu
browser-mini URL --gsk cairo       # GTK renderer (default gl)

--feature NAME[=on|off] sets a WebKit runtime feature, --list-features lists them. --gl-info checks the graphics stack.