fix: defer omnibox auto-open until GTK layout completes
- commit
- 43b84097c708766f3ec5197dec8b35730b1262e7
- author
- brice · · 2026-01-26 04:40 UTC
- parent
- 9cc8eee
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +35 -5
M internal/ui/app.go +2 -0
| @@ -1698,6 +1698,8 @@ func (a *App) createWorkspaceViewWithoutAttach(ctx context.Context, tab *entity. | |||
| 1698 | 1698 | wsView.SetOmniboxConfig(a.omniboxCfg) | |
| 1699 | 1699 | // Set find bar config for this workspace view | |
| 1700 | 1700 | wsView.SetFindBarConfig(a.findBarCfg) | |
| 1701 | + | // Set auto-open omnibox on new pane | |
| 1702 | + | wsView.SetAutoOpenOnNewPane(config.Get().Omnibox.AutoOpenOnNewPane) | |
| 1701 | 1703 | ||
| 1702 | 1704 | wsView.SetOnPaneFocused(func(paneID entity.PaneID) { | |
| 1703 | 1705 | if a.keyboardHandler != nil && a.keyboardHandler.Mode() == input.ModeResize { | |
| @@ -1698,6 +1698,8 @@ func (a *App) createWorkspaceViewWithoutAttach(ctx context.Context, tab *entity. | |||||
| 1698 | wsView.SetOmniboxConfig(a.omniboxCfg) | 1698 | wsView.SetOmniboxConfig(a.omniboxCfg) | ||
| 1699 | // Set find bar config for this workspace view | 1699 | // Set find bar config for this workspace view | ||
| 1700 | wsView.SetFindBarConfig(a.findBarCfg) | 1700 | wsView.SetFindBarConfig(a.findBarCfg) | ||
| 1701 | + | // Set auto-open omnibox on new pane | |||
| 1702 | + | wsView.SetAutoOpenOnNewPane(config.Get().Omnibox.AutoOpenOnNewPane) | |||
| 1701 | 1703 | ||||
| 1702 | wsView.SetOnPaneFocused(func(paneID entity.PaneID) { | 1704 | wsView.SetOnPaneFocused(func(paneID entity.PaneID) { | ||
| 1703 | if a.keyboardHandler != nil && a.keyboardHandler.Mode() == input.ModeResize { | 1705 | if a.keyboardHandler != nil && a.keyboardHandler.Mode() == input.ModeResize { | ||
M internal/ui/component/workspace_view.go +30 -0
| @@ -11,6 +11,7 @@ import ( | |||
| 11 | 11 | "github.com/bnema/dumber/internal/domain/entity" | |
| 12 | 12 | "github.com/bnema/dumber/internal/logging" | |
| 13 | 13 | "github.com/bnema/dumber/internal/ui/layout" | |
| 14 | + | "github.com/jwijenbergh/puregotk/v4/glib" | |
| 14 | 15 | "github.com/rs/zerolog" | |
| 15 | 16 | ) | |
| 16 | 17 | ||
| @@ -55,6 +56,9 @@ type WorkspaceView struct { | |||
| 55 | 56 | // Prevents hover focus from overriding keyboard-initiated focus changes | |
| 56 | 57 | hoverSuppressedUntil time.Time | |
| 57 | 58 | ||
| 59 | + | // Auto-open omnibox on new pane creation | |
| 60 | + | autoOpenOnNewPane bool | |
| 61 | + | ||
| 58 | 62 | mu sync.RWMutex | |
| 59 | 63 | } | |
| 60 | 64 | ||
| @@ -547,6 +551,32 @@ func (wv *WorkspaceView) SetFindBarConfig(cfg FindBarConfig) { | |||
| 547 | 551 | wv.findBarCfg = cfg | |
| 548 | 552 | } | |
| 549 | 553 | ||
| 554 | + | // SetAutoOpenOnNewPane configures whether to show omnibox when a new pane is created. | |
| 555 | + | func (wv *WorkspaceView) SetAutoOpenOnNewPane(enabled bool) { | |
| 556 | + | wv.mu.Lock() | |
| 557 | + | defer wv.mu.Unlock() | |
| 558 | + | wv.autoOpenOnNewPane = enabled | |
| 559 | + | } | |
| 560 | + | ||
| 561 | + | // NotifyNewPaneCreated handles new pane creation events. | |
| 562 | + | // If auto-open is enabled, shows the omnibox after GTK layout completes. | |
| 563 | + | func (wv *WorkspaceView) NotifyNewPaneCreated(ctx context.Context) { | |
| 564 | + | wv.mu.RLock() | |
| 565 | + | autoOpen := wv.autoOpenOnNewPane | |
| 566 | + | wv.mu.RUnlock() | |
| 567 | + | ||
| 568 | + | if !autoOpen { | |
| 569 | + | return | |
| 570 | + | } | |
| 571 | + | ||
| 572 | + | // Defer omnibox show until after GTK layout allocation completes | |
| 573 | + | cb := glib.SourceFunc(func(uintptr) bool { | |
| 574 | + | wv.ShowOmnibox(ctx, "") | |
| 575 | + | return false | |
| 576 | + | }) | |
| 577 | + | glib.IdleAdd(&cb, 0) | |
| 578 | + | } | |
| 579 | + | ||
| 550 | 580 | // ShowOmnibox creates and shows the omnibox in the active pane. | |
| 551 | 581 | func (wv *WorkspaceView) ShowOmnibox(ctx context.Context, query string) { | |
| 552 | 582 | wv.mu.Lock() | |
| @@ -11,6 +11,7 @@ import ( | |||||
| 11 | "github.com/bnema/dumber/internal/domain/entity" | 11 | "github.com/bnema/dumber/internal/domain/entity" | ||
| 12 | "github.com/bnema/dumber/internal/logging" | 12 | "github.com/bnema/dumber/internal/logging" | ||
| 13 | "github.com/bnema/dumber/internal/ui/layout" | 13 | "github.com/bnema/dumber/internal/ui/layout" | ||
| 14 | + | "github.com/jwijenbergh/puregotk/v4/glib" | |||
| 14 | "github.com/rs/zerolog" | 15 | "github.com/rs/zerolog" | ||
| 15 | ) | 16 | ) | ||
| 16 | 17 | ||||
| @@ -55,6 +56,9 @@ type WorkspaceView struct { | |||||
| 55 | // Prevents hover focus from overriding keyboard-initiated focus changes | 56 | // Prevents hover focus from overriding keyboard-initiated focus changes | ||
| 56 | hoverSuppressedUntil time.Time | 57 | hoverSuppressedUntil time.Time | ||
| 57 | 58 | ||||
| 59 | + | // Auto-open omnibox on new pane creation | |||
| 60 | + | autoOpenOnNewPane bool | |||
| 61 | + | ||||
| 58 | mu sync.RWMutex | 62 | mu sync.RWMutex | ||
| 59 | } | 63 | } | ||
| 60 | 64 | ||||
| @@ -547,6 +551,32 @@ func (wv *WorkspaceView) SetFindBarConfig(cfg FindBarConfig) { | |||||
| 547 | wv.findBarCfg = cfg | 551 | wv.findBarCfg = cfg | ||
| 548 | } | 552 | } | ||
| 549 | 553 | ||||
| 554 | + | // SetAutoOpenOnNewPane configures whether to show omnibox when a new pane is created. | |||
| 555 | + | func (wv *WorkspaceView) SetAutoOpenOnNewPane(enabled bool) { | |||
| 556 | + | wv.mu.Lock() | |||
| 557 | + | defer wv.mu.Unlock() | |||
| 558 | + | wv.autoOpenOnNewPane = enabled | |||
| 559 | + | } | |||
| 560 | + | ||||
| 561 | + | // NotifyNewPaneCreated handles new pane creation events. | |||
| 562 | + | // If auto-open is enabled, shows the omnibox after GTK layout completes. | |||
| 563 | + | func (wv *WorkspaceView) NotifyNewPaneCreated(ctx context.Context) { | |||
| 564 | + | wv.mu.RLock() | |||
| 565 | + | autoOpen := wv.autoOpenOnNewPane | |||
| 566 | + | wv.mu.RUnlock() | |||
| 567 | + | ||||
| 568 | + | if !autoOpen { | |||
| 569 | + | return | |||
| 570 | + | } | |||
| 571 | + | ||||
| 572 | + | // Defer omnibox show until after GTK layout allocation completes | |||
| 573 | + | cb := glib.SourceFunc(func(uintptr) bool { | |||
| 574 | + | wv.ShowOmnibox(ctx, "") | |||
| 575 | + | return false | |||
| 576 | + | }) | |||
| 577 | + | glib.IdleAdd(&cb, 0) | |||
| 578 | + | } | |||
| 579 | + | ||||
| 550 | // ShowOmnibox creates and shows the omnibox in the active pane. | 580 | // ShowOmnibox creates and shows the omnibox in the active pane. | ||
| 551 | func (wv *WorkspaceView) ShowOmnibox(ctx context.Context, query string) { | 581 | func (wv *WorkspaceView) ShowOmnibox(ctx context.Context, query string) { | ||
| 552 | wv.mu.Lock() | 582 | wv.mu.Lock() | ||
M internal/ui/coordinator/workspace.go +3 -5
| @@ -145,8 +145,8 @@ func (c *WorkspaceCoordinator) Split(ctx context.Context, direction usecase.Spli | |||
| 145 | 145 | c.applySplitToView(ctx, splitCtx.wsView, splitCtx.ws, output, direction, splitCtx.existingWidget, splitCtx.isStackSplit, oldActivePaneID) | |
| 146 | 146 | } | |
| 147 | 147 | ||
| 148 | - | if splitCtx.wsView != nil && config.Get().Omnibox.AutoOpenOnNewPane { | |
| 149 | - | splitCtx.wsView.ShowOmnibox(ctx, "") | |
| 148 | + | if splitCtx.wsView != nil { | |
| 149 | + | splitCtx.wsView.NotifyNewPaneCreated(ctx) | |
| 150 | 150 | } | |
| 151 | 151 | ||
| 152 | 152 | // Notify state change for session snapshots | |
| @@ -1377,9 +1377,7 @@ func (c *WorkspaceCoordinator) StackPane(ctx context.Context) error { | |||
| 1377 | 1377 | log.Warn().Err(err).Msg("failed to set active pane") | |
| 1378 | 1378 | } | |
| 1379 | 1379 | ||
| 1380 | - | if config.Get().Omnibox.AutoOpenOnNewPane { | |
| 1381 | - | stackCtx.wsView.ShowOmnibox(ctx, "") | |
| 1382 | - | } | |
| 1380 | + | stackCtx.wsView.NotifyNewPaneCreated(ctx) | |
| 1383 | 1381 | ||
| 1384 | 1382 | // Set up title bar click and close callbacks | |
| 1385 | 1383 | tr := stackCtx.wsView.TreeRenderer() | |
| @@ -145,8 +145,8 @@ func (c *WorkspaceCoordinator) Split(ctx context.Context, direction usecase.Spli | |||||
| 145 | c.applySplitToView(ctx, splitCtx.wsView, splitCtx.ws, output, direction, splitCtx.existingWidget, splitCtx.isStackSplit, oldActivePaneID) | 145 | c.applySplitToView(ctx, splitCtx.wsView, splitCtx.ws, output, direction, splitCtx.existingWidget, splitCtx.isStackSplit, oldActivePaneID) | ||
| 146 | } | 146 | } | ||
| 147 | 147 | ||||
| 148 | - | if splitCtx.wsView != nil && config.Get().Omnibox.AutoOpenOnNewPane { | 148 | + | if splitCtx.wsView != nil { |
| 149 | - | splitCtx.wsView.ShowOmnibox(ctx, "") | 149 | + | splitCtx.wsView.NotifyNewPaneCreated(ctx) |
| 150 | } | 150 | } | ||
| 151 | 151 | ||||
| 152 | // Notify state change for session snapshots | 152 | // Notify state change for session snapshots | ||
| @@ -1377,9 +1377,7 @@ func (c *WorkspaceCoordinator) StackPane(ctx context.Context) error { | |||||
| 1377 | log.Warn().Err(err).Msg("failed to set active pane") | 1377 | log.Warn().Err(err).Msg("failed to set active pane") | ||
| 1378 | } | 1378 | } | ||
| 1379 | 1379 | ||||
| 1380 | - | if config.Get().Omnibox.AutoOpenOnNewPane { | 1380 | + | stackCtx.wsView.NotifyNewPaneCreated(ctx) |
| 1381 | - | stackCtx.wsView.ShowOmnibox(ctx, "") | |||
| 1382 | - | } | |||
| 1383 | 1381 | ||||
| 1384 | // Set up title bar click and close callbacks | 1382 | // Set up title bar click and close callbacks | ||
| 1385 | tr := stackCtx.wsView.TreeRenderer() | 1383 | tr := stackCtx.wsView.TreeRenderer() | ||