feat(ux): auto-open omnibox on new blank panes
Implements automatic omnibox opening when a new pane is created with about:blank, providing immediate search/navigation access. Changes: - Remove dead JavaScript injection code from clonePaneState that tried to open omnibox via URI changed handler (timing issues) - Add simple client-side detection in Omnibox.svelte onMount that checks for about:blank and auto-opens omnibox - KISS approach: UI component knows its own state and acts accordingly The new implementation is more reliable and eliminates timing issues with WebKit event handlers and JS injection.
- commit
- 37da1ff43be1adf5a42571b9c6254eb19a7864e2
- author
- bamen · · 2025-10-06 16:03 UTC
- committer
- bamen · · 2025-10-06 16:25 UTC
- parent
- bc5cb18
- signature
- unsigned
3 files · +9 -16
M CHANGELOG.md +1 -0
| @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. | |||
| 5 | 5 | ## [Unreleased] | |
| 6 | 6 | ||
| 7 | 7 | ### Added | |
| 8 | + | - **Auto-open omnibox on blank panes**: Omnibox automatically opens when a new pane is created with about:blank, providing immediate search/navigation access | |
| 8 | 9 | - **Configurable default zoom**: Added `default_zoom` config (defaults to 1.2/120%). Per-domain zoom still overrides this | |
| 9 | 10 | - **Pin/favorite sites**: Pin websites from history or quick access to prioritize them in "Jump back in" section. Uses localStorage persistence with star icons for pin/unpin actions | |
| 10 | 11 | - **Zellij-style stacked panes**: Added Ctrl+P → 's' to stack panes instead of splitting, with Alt+Up/Down navigation between stacked panes. Features collapsed page title bars showing for inactive panes and full WebView interaction for the active pane. Includes GTK4 CSS styling for proper visual feedback | |
| @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. | |||||
| 5 | ## [Unreleased] | 5 | ## [Unreleased] | ||
| 6 | 6 | ||||
| 7 | ### Added | 7 | ### Added | ||
| 8 | + | - **Auto-open omnibox on blank panes**: Omnibox automatically opens when a new pane is created with about:blank, providing immediate search/navigation access | |||
| 8 | - **Configurable default zoom**: Added `default_zoom` config (defaults to 1.2/120%). Per-domain zoom still overrides this | 9 | - **Configurable default zoom**: Added `default_zoom` config (defaults to 1.2/120%). Per-domain zoom still overrides this | ||
| 9 | - **Pin/favorite sites**: Pin websites from history or quick access to prioritize them in "Jump back in" section. Uses localStorage persistence with star icons for pin/unpin actions | 10 | - **Pin/favorite sites**: Pin websites from history or quick access to prioritize them in "Jump back in" section. Uses localStorage persistence with star icons for pin/unpin actions | ||
| 10 | - **Zellij-style stacked panes**: Added Ctrl+P → 's' to stack panes instead of splitting, with Alt+Up/Down navigation between stacked panes. Features collapsed page title bars showing for inactive panes and full WebView interaction for the active pane. Includes GTK4 CSS styling for proper visual feedback | 11 | - **Zellij-style stacked panes**: Added Ctrl+P → 's' to stack panes instead of splitting, with Alt+Up/Down navigation between stacked panes. Features collapsed page title bars showing for inactive panes and full WebView interaction for the active pane. Includes GTK4 CSS styling for proper visual feedback | ||
M gui/src/components/omnibox/Omnibox.svelte +7 -1
| @@ -329,7 +329,7 @@ | |||
| 329 | 329 | }; | |
| 330 | 330 | ||
| 331 | 331 | console.log('✅ Omnibox API exposed:', Object.keys(window.__dumber_omnibox)); | |
| 332 | - | ||
| 332 | + | ||
| 333 | 333 | // Check for pending suggestions that arrived before API was ready | |
| 334 | 334 | if ((window as any).__dumber_omnibox_pending_suggestions) { | |
| 335 | 335 | console.log('🔄 [OMNIBOX] Processing pending suggestions'); | |
| @@ -337,6 +337,12 @@ | |||
| 337 | 337 | omniboxBridge.setSuggestions(pending); | |
| 338 | 338 | delete (window as any).__dumber_omnibox_pending_suggestions; | |
| 339 | 339 | } | |
| 340 | + | ||
| 341 | + | // Auto-open omnibox on about:blank pages | |
| 342 | + | if (window.location.href === 'about:blank') { | |
| 343 | + | console.log('🚀 Auto-opening omnibox for about:blank'); | |
| 344 | + | omniboxStore.open('omnibox'); | |
| 345 | + | } | |
| 340 | 346 | } catch (error) { | |
| 341 | 347 | console.error('❌ Failed to set up omnibox global API:', error); | |
| 342 | 348 | } | |
| @@ -329,7 +329,7 @@ | |||||
| 329 | }; | 329 | }; | ||
| 330 | 330 | ||||
| 331 | console.log('✅ Omnibox API exposed:', Object.keys(window.__dumber_omnibox)); | 331 | console.log('✅ Omnibox API exposed:', Object.keys(window.__dumber_omnibox)); | ||
| 332 | - | 332 | + | ||
| 333 | // Check for pending suggestions that arrived before API was ready | 333 | // Check for pending suggestions that arrived before API was ready | ||
| 334 | if ((window as any).__dumber_omnibox_pending_suggestions) { | 334 | if ((window as any).__dumber_omnibox_pending_suggestions) { | ||
| 335 | console.log('🔄 [OMNIBOX] Processing pending suggestions'); | 335 | console.log('🔄 [OMNIBOX] Processing pending suggestions'); | ||
| @@ -337,6 +337,12 @@ | |||||
| 337 | omniboxBridge.setSuggestions(pending); | 337 | omniboxBridge.setSuggestions(pending); | ||
| 338 | delete (window as any).__dumber_omnibox_pending_suggestions; | 338 | delete (window as any).__dumber_omnibox_pending_suggestions; | ||
| 339 | } | 339 | } | ||
| 340 | + | ||||
| 341 | + | // Auto-open omnibox on about:blank pages | |||
| 342 | + | if (window.location.href === 'about:blank') { | |||
| 343 | + | console.log('🚀 Auto-opening omnibox for about:blank'); | |||
| 344 | + | omniboxStore.open('omnibox'); | |||
| 345 | + | } | |||
| 340 | } catch (error) { | 346 | } catch (error) { | ||
| 341 | console.error('❌ Failed to set up omnibox global API:', error); | 347 | console.error('❌ Failed to set up omnibox global API:', error); | ||
| 342 | } | 348 | } | ||
M internal/app/browser/workspace_pane_ops.go +1 -15
| @@ -124,21 +124,7 @@ func (wm *WorkspaceManager) clonePaneState(_ *paneNode, target *paneNode) { | |||
| 124 | 124 | log.Printf("[workspace] failed to prepare blank pane: %v", err) | |
| 125 | 125 | } | |
| 126 | 126 | ||
| 127 | - | // Wait for about:blank to load before opening omnibox | |
| 128 | - | target.pane.webView.RegisterURIChangedHandler(func(uri string) { | |
| 129 | - | if uri == blankURL { | |
| 130 | - | // Defer omnibox opening to allow page to fully initialize | |
| 131 | - | wm.scheduleIdleGuarded(func() bool { | |
| 132 | - | if target == nil || target.pane == nil || target.pane.webView == nil { | |
| 133 | - | return false | |
| 134 | - | } | |
| 135 | - | if injErr := target.pane.webView.InjectScript("window.__dumber_omnibox?.open('omnibox');"); injErr != nil { | |
| 136 | - | log.Printf("[workspace] failed to open omnibox: %v", injErr) | |
| 137 | - | } | |
| 138 | - | return false // Remove idle callback | |
| 139 | - | }, target) | |
| 140 | - | } | |
| 141 | - | }) | |
| 127 | + | // Omnibox will auto-open on about:blank via client-side detection | |
| 142 | 128 | } | |
| 143 | 129 | ||
| 144 | 130 | // safelyDetachControllersBeforeReparent removes GTK controllers that GTK will auto-clean up during reparenting. | |
| @@ -124,21 +124,7 @@ func (wm *WorkspaceManager) clonePaneState(_ *paneNode, target *paneNode) { | |||||
| 124 | log.Printf("[workspace] failed to prepare blank pane: %v", err) | 124 | log.Printf("[workspace] failed to prepare blank pane: %v", err) | ||
| 125 | } | 125 | } | ||
| 126 | 126 | ||||
| 127 | - | // Wait for about:blank to load before opening omnibox | 127 | + | // Omnibox will auto-open on about:blank via client-side detection |
| 128 | - | target.pane.webView.RegisterURIChangedHandler(func(uri string) { | |||
| 129 | - | if uri == blankURL { | |||
| 130 | - | // Defer omnibox opening to allow page to fully initialize | |||
| 131 | - | wm.scheduleIdleGuarded(func() bool { | |||
| 132 | - | if target == nil || target.pane == nil || target.pane.webView == nil { | |||
| 133 | - | return false | |||
| 134 | - | } | |||
| 135 | - | if injErr := target.pane.webView.InjectScript("window.__dumber_omnibox?.open('omnibox');"); injErr != nil { | |||
| 136 | - | log.Printf("[workspace] failed to open omnibox: %v", injErr) | |||
| 137 | - | } | |||
| 138 | - | return false // Remove idle callback | |||
| 139 | - | }, target) | |||
| 140 | - | } | |||
| 141 | - | }) | |||
| 142 | } | 128 | } | ||
| 143 | 129 | ||||
| 144 | // safelyDetachControllersBeforeReparent removes GTK controllers that GTK will auto-clean up during reparenting. | 130 | // safelyDetachControllersBeforeReparent removes GTK controllers that GTK will auto-clean up during reparenting. | ||