323 lines
14 KiB
Markdown
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.
|