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

323 lines
14 KiB
Markdown

# 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.c`](../sovereign_browser/src/main.c) and
[`sovereign_browser/src/tab_manager.c`](../sovereign_browser/src/tab_manager.c)
- Rust: [`src/main.rs`](../src/main.rs) and [`src/tab_manager.rs`](../src/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 `GtkWindow`s) | **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`](../sovereign_browser/src/tab_manager.c:2993))
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`](../src/tab_manager.rs:48))
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`](../sovereign_browser/src/tab_manager.c:1263))
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`](../sovereign_browser/src/tab_manager.c:2562))
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`](../sovereign_browser/src/main.c:501))
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`](../src/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.
---
## 10. Recommended Path to Parity
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.