Files
sovereign_browser_rust/plans/main-window-comparison.md

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:


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:

  1. 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)
  2. Bookmark bar — buttons for the "Bookmarks Bar" folder + subfolder popovers
  3. Load-progress bar — thin 3px bar shown during loads
  4. WebView — with developer extras, hardware acceleration, smooth scrolling, JSON viewer injection, window.nostr injection, and a battery of signal handlers (load-changed, load-failed, favicon, title, context-menu, decide-policy, create, key-press, button-press)
  5. 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 via tab_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 the WindowFeatures assertion 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_t registered in g_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 WebKit create signal

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 / --url skip restore; --session-restore forces it; otherwise uses settings.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_event closes 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_destroy does session save (or privacy-mode clear), network service shutdown, agent server stop, signer free, and gtk_main_quit().

7.2 Rust

  • Session restore is basic: if settings.session_restore is true, it restores URLs into new tabs. No CLI precedence logic.
  • Window close is simple: delete_event saves 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:

  1. 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.
  2. No multi-window support — no new-window function, no Ctrl+N, no target="_blank"/window.open() handling, no per-window notebooks or sidebars.
  3. No tab context menu — right-click and middle-click tab actions are entirely absent.
  4. No hamburger menu — identity switching, logout, network toggles, and internal-page navigation are missing.
  5. Keyboard shortcuts are not wired — the shortcut table exists but no handler dispatches it.
  6. No tab-strip action widgets — no new-tab button, no user avatar.
  7. No drag-reordering, favicons, or progress bars.
  8. No app theme/CSS — the original has a custom red-accent theme.

To bring the Rust main window up to the original's level, the work breaks down into these steps:

  1. 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().
  2. 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.
  3. Tab context menu — add a button-press-event handler 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.
  4. Multi-window support — add tab_manager_new_window(), a create-signal handler for target="_blank", per-window notebooks, and active-window tracking (focus-in/destroy). Use WebView::builder().related_view() to avoid the WindowFeatures crash.
  5. Hamburger menu — build a GtkMenuButton per tab with the identity, network, security, and internal-page items, delegating identity actions to main.rs.
  6. Wire keyboard shortcuts — add a key-press-event handler on the window and each webview that dispatches through shortcuts_lookup().
  7. Tab-strip action widgets — add a new-tab button and user avatar via notebook.set_action_widget().
  8. Drag-reordering — call notebook.set_tab_reorderable() per tab, gated on a tab_drag_reorder setting.
  9. App theme — add a CSS provider with the red-accent theme, adapting to the theme_dark setting.
  10. Window close semantics — make delete_event multi-window aware so the app quits only when the last window closes.