14 KiB
Main Browser Window Comparison: Original (C) vs Rust Implementation
Date: 2026-08-17 Scope: The main browser window — how tabs are generated, how new windows are generated, and the surrounding UI chrome (toolbars, menus, tab strip, sidebar). Reference files:
- Original (C):
sovereign_browser/src/main.candsovereign_browser/src/tab_manager.c - Rust:
src/main.rsandsrc/tab_manager.rs
1. Overview
The original C implementation is a mature, feature-complete multi-window browser. Each tab carries its own toolbar (hamburger menu, refresh/stop, back/forward, URL entry with search completion, bookmark button), a bookmark bar, a load-progress bar, a rich tab label (favicon + title + close button), and a right-click tab context menu. It supports multiple top-level windows, each with its own notebook, a per-window sidebar, tab drag-reordering, and a full hamburger menu with identity, network, security, and internal-page items.
The Rust implementation is a minimal single-window skeleton. It has a
single shared toolbar with one URL entry and a Settings button, a plain
GtkNotebook with simple text labels, and no per-tab chrome, no context menus,
no new-window support, no sidebar, and no drag-reordering. This document details
the differences and what would be needed to bring the Rust project up to the
same level.
2. High-Level Structural Differences
| Aspect | Original (C) | Rust |
|---|---|---|
| Windows | Multi-window (main + auxiliary GtkWindows) |
Single window only |
| Per-tab toolbar | ✅ Each tab has its own toolbar | ❌ One shared toolbar for all tabs |
| Tab label | Favicon + title + close button (rich) | Plain text label only |
| Tab context menu (right-click) | ✅ New / Close / Close Others / Close to Right / Open in New Window / Duplicate / Reload / Download Website | ❌ None |
| Middle-click to close | ✅ (configurable) | ❌ |
| Tab drag-reordering | ✅ (configurable) | ❌ |
| New-tab button on tab strip | ✅ (tab-new-symbolic action widget) |
❌ |
| User avatar on tab strip | ✅ (Nostr profile picture) | ❌ |
| Hamburger menu | ✅ Full menu (identity, network, security, internal pages) | ❌ (only a Settings button) |
| Sidebar (agent chat) | ✅ Per-window GtkPaned sidebar |
❌ |
| Bookmark bar | ✅ Per-tab bookmark bar | ❌ |
| Load-progress bar | ✅ Per-tab thin progress bar | ❌ |
| URL search completion | ✅ History + bookmarks + search suggestions | ❌ (plain entry) |
| Back/Forward/Refresh buttons | ✅ Per-tab | ❌ |
target="_blank" / window.open() |
✅ New tab or new window via create signal |
❌ (not handled) |
| Keyboard shortcuts | ✅ Full set (Ctrl+T/N/W, zoom, inspector, sidebar, fullscreen, etc.) | ⚠️ Defined in data but not wired to any handler |
| Session restore | ✅ With CLI precedence logic | ⚠️ Basic (restores URLs) |
| App theme / CSS | ✅ Custom red-accent theme | ❌ |
| Window close semantics | ✅ Multi-window aware (app quits only when last window closes) | ⚠️ Simple (quits on main window close) |
3. Tab Generation
3.1 Original (C) — tab_create() (tab_manager.c)
Each tab is a full tab_info_t with its own page (vertical box) containing:
- Per-tab toolbar (horizontal box, name
main-toolbar):- Hamburger menu button (
build_hamburger_menu) - Refresh/Stop button — left-click reloads, right-click shows hard-reload options (bypass cache, clear cookies + reload); icon/tooltip sync with loading state
- Back button and Forward button
- URL entry with search completion (history + bookmarks + domain heuristic + async search-engine suggestions)
- Bookmark button (opens a directory picker to bookmark the page)
- Hamburger menu button (
- Bookmark bar — buttons for the "Bookmarks Bar" folder + subfolder popovers
- Load-progress bar — thin 3px bar shown during loads
- WebView — with developer extras, hardware acceleration, smooth scrolling,
JSON viewer injection,
window.nostrinjection, and a battery of signal handlers (load-changed, load-failed, favicon, title, context-menu, decide-policy, create, key-press, button-press) - Tab label (
build_tab_label) — favicon + ellipsized title + close button, with middle-click/right-click handling on the label and all children
3.2 Rust — tab_manager_new_tab() (src/tab_manager.rs)
Each tab is a TabInfo struct plus a GtkScrolledWindow containing a bare
WebView. The tab label is a plain gtk::Label ("New Tab" → page title). There
is no per-tab toolbar, no bookmark bar, no progress bar, no favicon, no close
button, no context menu, no drag-reordering.
3.3 Differences
| Feature | Original (C) | Rust |
|---|---|---|
| Per-tab toolbar | ✅ | ❌ |
| URL entry per tab | ✅ | ❌ (one shared) |
| Back/Forward/Refresh buttons | ✅ | ❌ |
| Search completion in URL bar | ✅ | ❌ |
| Bookmark button + bar | ✅ | ❌ |
| Load-progress bar | ✅ | ❌ |
| Favicon in tab label | ✅ | ❌ |
| Close button on tab | ✅ | ❌ |
| Tab context menu | ✅ | ❌ |
| Middle-click close | ✅ | ❌ |
| Drag-reorder | ✅ | ❌ |
| Max-tabs limit | ✅ (settings.max_tabs) |
❌ |
| Focus URL entry on new tab | ✅ | ❌ |
| Per-tab signal wiring | ✅ (load/favicon/title/context/create/decide-policy) | ⚠️ (title only) |
4. New Window Generation
4.1 Original (C) — tab_manager_new_window() (tab_manager.c)
Creates a real top-level GtkWindow with:
- Its own
GtkNotebook(full tab infrastructure viatab_create) - New-tab button + avatar as notebook action widgets
- A window-level
GtkPaned(left = sidebar container, right = notebook) - A full tab created with
webkit_web_view_new_with_related_view()(shares the parent's WebProcess, avoiding theWindowFeaturesassertion crash) - Focus-in / destroy handlers that track the active window and revert to the main window when an auxiliary window closes (without quitting the app)
- A
window_state_tregistered ing_aux_windows
New windows are created from:
- Ctrl+N /
SHORTCUT_NEW_WINDOW→tab_manager_new_window_blank() - Tab context menu "Open in New Window" →
tab_manager_open_in_new_window() target="_blank"/window.open()→on_create_webview()creates a new tab (or window) via the WebKitcreatesignal
4.2 Rust — no new-window support
The Rust implementation has no new-window function at all. There is no
tab_manager_new_window, no create-signal handler, and no Ctrl+N handling.
target="_blank" links and window.open() are not handled, so they either do
nothing or open in the same view depending on WebKit defaults.
4.3 Differences
| Feature | Original (C) | Rust |
|---|---|---|
| Multiple top-level windows | ✅ | ❌ |
Ctrl+N new window |
✅ | ❌ |
| "Open in New Window" (context menu) | ✅ | ❌ |
target="_blank" → new tab/window |
✅ | ❌ |
| Per-window notebook | ✅ | ❌ |
| Per-window sidebar | ✅ | ❌ |
| Active-window tracking (focus-in) | ✅ | ❌ |
| App stays alive when aux window closes | ✅ | ❌ |
| Related-view webview (crash avoidance) | ✅ | ❌ |
5. Window Chrome & Menus
5.1 Hamburger menu (Original only)
The C version's per-tab hamburger menu (build_hamburger_menu)
contains:
- Navigation: Open File…, Reload, Stop
- Recents submenu (history)
- Bookmarks submenu
- Identity: Switch Identity…, Lock Session, Logout
- Networking: Tor-routed transport, FIPS mesh (check items, synced across tabs)
- Security/status: Security strip (SOP/CORS/certs), Nostr signing status
- Tools: Toggle Inspector, Toggle Agent Sidebar
- Internal pages: Profile, Agent Setup…, FIPS Mesh…, Processes…, Settings…, About
The Rust version has only a single "Settings" toolbar button that opens
sovereign://settings in a new tab. There is no hamburger menu, no identity
menu, no network toggles, no internal-page menu.
5.2 Tab strip action widgets (Original only)
The C version adds to each notebook:
- A new-tab button (
tab-new-symbolic) at the end of the tab strip - A user avatar button at the start (Nostr profile picture, circular)
The Rust version has neither.
5.3 Sidebar (Original only)
The C version has a per-window GtkPaned sidebar (agent chat), hidden by
default, toggled via Ctrl+Shift+A / menu / ; shortcut. The Rust version has no
sidebar.
6. Keyboard Shortcuts
6.1 Original (C)
The C version wires a full on_key_press handler (main.c)
to both the window and every webview, dispatching through the configurable
shortcuts_lookup() table. Actions include: New Tab, New Window, Open File,
Close Tab, Focus URL, Next/Prev Tab (Ctrl+Tab and Ctrl+PageUp/Down), Reload,
Force Reload, Back, Forward, Find, Open Settings, Open Processes, New Identity,
Toggle Fullscreen, Toggle Inspector, Toggle Sidebar, Toggle Toolbars, Zoom
In/Out/Reset.
6.2 Rust
The Rust shortcuts.rs defines a default shortcut
table (Ctrl+T, Ctrl+W, Ctrl+L, Ctrl+Tab, Ctrl+R, Ctrl+Q, Ctrl+F, Ctrl+D, Ctrl+H,
Ctrl+B, Ctrl+J, zoom, etc.) and can load/save it, but nothing wires these to
actual handlers. There is no key-press-event handler in main.rs or
tab_manager.rs that dispatches them. The shortcuts are effectively dead data.
7. Session Restore & Window Close
7.1 Original (C)
- Session restore has explicit CLI precedence:
--no-session-restore/--urlskip restore;--session-restoreforces it; otherwise usessettings.restore_session. On restore failure, falls back to CLI URLs or the default new-tab URL. - Window close is multi-window aware:
on_window_delete_eventcloses the main window's tabs; if auxiliary windows still have tabs, it hides the main window and keeps the app alive; the app only quits when the last window closes.on_window_destroydoes session save (or privacy-mode clear), network service shutdown, agent server stop, signer free, andgtk_main_quit().
7.2 Rust
- Session restore is basic: if
settings.session_restoreis true, it restores URLs into new tabs. No CLI precedence logic. - Window close is simple:
delete_eventsaves the session and quits. No multi-window awareness (there's only one window).
8. Feature Matrix
| Feature | Original (C) | Rust |
|---|---|---|
| Multi-window | ✅ | ❌ |
| Per-tab toolbar | ✅ | ❌ |
| Back/Forward/Refresh buttons | ✅ | ❌ |
| URL search completion | ✅ | ❌ |
| Bookmark button + bar | ✅ | ❌ |
| Load-progress bar | ✅ | ❌ |
| Favicon in tab | ✅ | ❌ |
| Tab close button | ✅ | ❌ |
| Tab context menu | ✅ | ❌ |
| Middle-click close | ✅ | ❌ |
| Drag-reorder | ✅ | ❌ |
| New-tab button on strip | ✅ | ❌ |
| User avatar on strip | ✅ | ❌ |
| Hamburger menu | ✅ | ❌ |
| Identity menu (switch/lock/logout) | ✅ | ❌ |
| Network toggles (Tor/FIPS) | ✅ | ❌ |
| Sidebar (agent chat) | ✅ | ❌ |
| Inspector toggle | ✅ | ❌ |
| Zoom controls | ✅ | ❌ |
| Fullscreen toggle | ✅ | ❌ |
| Toolbar toggle | ✅ | ❌ |
target="_blank" handling |
✅ | ❌ |
| Keyboard shortcuts wired | ✅ | ❌ (data only) |
| App theme / CSS | ✅ | ❌ |
| Max-tabs limit | ✅ | ❌ |
| Multi-window close semantics | ✅ | ❌ |
| Session restore precedence | ✅ | ⚠️ basic |
9. Summary of Gaps
The Rust main window is a minimal single-window skeleton compared to the original. The most significant gaps, in priority order:
- No per-tab chrome — the original gives every tab its own toolbar (URL entry, back/forward/refresh, bookmark), bookmark bar, progress bar, and rich tab label. The Rust version has one shared toolbar and plain text tabs.
- No multi-window support — no new-window function, no
Ctrl+N, notarget="_blank"/window.open()handling, no per-window notebooks or sidebars. - No tab context menu — right-click and middle-click tab actions are entirely absent.
- No hamburger menu — identity switching, logout, network toggles, and internal-page navigation are missing.
- Keyboard shortcuts are not wired — the shortcut table exists but no handler dispatches it.
- No tab-strip action widgets — no new-tab button, no user avatar.
- No drag-reordering, favicons, or progress bars.
- No app theme/CSS — the original has a custom red-accent theme.
10. Recommended Path to Parity
To bring the Rust main window up to the original's level, the work breaks down into these steps:
- Per-tab toolbar — move the URL entry, back/forward/refresh buttons, and
bookmark button into each tab's page (a vertical box: toolbar → bookmark bar
→ progress bar → webview), mirroring
tab_create(). - Rich tab label — build a horizontal box per tab with favicon image,
ellipsized title label, and a close button; wire
notify::favicon,notify::title, and close-clicked signals. - Tab context menu — add a
button-press-eventhandler on the tab label (and children) for right-click (New, Close, Close Others, Close to Right, Open in New Window, Duplicate, Reload, Download Website) and middle-click close. - Multi-window support — add
tab_manager_new_window(), acreate-signal handler fortarget="_blank", per-window notebooks, and active-window tracking (focus-in/destroy). UseWebView::builder().related_view()to avoid the WindowFeatures crash. - Hamburger menu — build a
GtkMenuButtonper tab with the identity, network, security, and internal-page items, delegating identity actions tomain.rs. - Wire keyboard shortcuts — add a
key-press-eventhandler on the window and each webview that dispatches throughshortcuts_lookup(). - Tab-strip action widgets — add a new-tab button and user avatar via
notebook.set_action_widget(). - Drag-reordering — call
notebook.set_tab_reorderable()per tab, gated on atab_drag_reordersetting. - App theme — add a CSS provider with the red-accent theme, adapting to the
theme_darksetting. - Window close semantics — make
delete_eventmulti-window aware so the app quits only when the last window closes.