detached c89d890

fix(omnibox): center in-pane omnibox and show 5 of 10 scrollable results

commit
c89d89021f9a83e572d66fffcfd322575b8c84fe
author
brice · · 2026-10-10 00:58 UTC
parent
e7ebbf7
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
4 files · +67 -20
M internal/ui/component/modal_sizing.go +5 -4
@@ -43,19 +43,20 @@ var DefaultRowHeights = RowHeightDefaults{
4343 }
4444
4545 // OmniboxSizeDefaults provides default sizing for omnibox modal.
46+// The in-pane omnibox is vertically centered, so it has no top margin.
4647 var OmniboxSizeDefaults = ModalSizeConfig{
4748 WidthPct: 0.8,
4849 MaxWidth: 800,
49- TopMarginPct: 0.2,
5050 FallbackWidth: 800,
5151 FallbackHeight: 600,
5252 }
5353
54-// OmniboxListDefaults provides display limits for omnibox modal.
54+// OmniboxListDefaults provides display limits for omnibox modal:
55+// MaxResults rows are listed and navigable, MaxVisibleRows fit before scrolling.
5556 var OmniboxListDefaults = ListDisplayDefaults{
56- MaxVisibleRows: 10,
57+ MaxVisibleRows: 5,
5758 MaxResults: 10,
58- SmallMaxVisibleRows: 5,
59+ SmallMaxVisibleRows: 3,
5960 }
6061
6162 // SessionManagerSizeDefaults provides default sizing for session manager modal.
@@ -43,19 +43,20 @@ var DefaultRowHeights = RowHeightDefaults{
43 }43 }
44 44
45 // OmniboxSizeDefaults provides default sizing for omnibox modal.45 // OmniboxSizeDefaults provides default sizing for omnibox modal.
46+// The in-pane omnibox is vertically centered, so it has no top margin.
46 var OmniboxSizeDefaults = ModalSizeConfig{47 var OmniboxSizeDefaults = ModalSizeConfig{
47 WidthPct: 0.8,48 WidthPct: 0.8,
48 MaxWidth: 800,49 MaxWidth: 800,
49- TopMarginPct: 0.2,
50 FallbackWidth: 800,50 FallbackWidth: 800,
51 FallbackHeight: 600,51 FallbackHeight: 600,
52 }52 }
53 53
54-// OmniboxListDefaults provides display limits for omnibox modal.54+// OmniboxListDefaults provides display limits for omnibox modal:
55+// MaxResults rows are listed and navigable, MaxVisibleRows fit before scrolling.
55 var OmniboxListDefaults = ListDisplayDefaults{56 var OmniboxListDefaults = ListDisplayDefaults{
56- MaxVisibleRows: 10,57+ MaxVisibleRows: 5,
57 MaxResults: 10,58 MaxResults: 10,
58- SmallMaxVisibleRows: 5,59+ SmallMaxVisibleRows: 3,
59 }60 }
60 61
61 // SessionManagerSizeDefaults provides default sizing for session manager modal.62 // SessionManagerSizeDefaults provides default sizing for session manager modal.
M internal/ui/component/modal_sizing_test.go +15 -3
@@ -5,6 +5,7 @@ import (
55 "testing"
66
77 layoutmocks "github.com/bnema/dumber/internal/ui/layout/mocks"
8+ "github.com/bnema/puregotk/v4/gtk"
89 "github.com/stretchr/testify/assert"
910 )
1011
@@ -168,10 +169,21 @@ func TestDefaultRowHeights_Values(t *testing.T) {
168169 func TestOmniboxSizeDefaults_Values(t *testing.T) {
169170 assert.InDelta(t, 0.8, OmniboxSizeDefaults.WidthPct, 0.0001)
170171 assert.Equal(t, 800, OmniboxSizeDefaults.MaxWidth)
171- assert.InDelta(t, 0.2, OmniboxSizeDefaults.TopMarginPct, 0.0001)
172+ assert.Zero(t, OmniboxSizeDefaults.TopMarginPct)
172173 assert.Equal(t, 600, OmniboxSizeDefaults.FallbackHeight)
173174 }
174175
176+func TestOmniboxValign(t *testing.T) {
177+ assert.Equal(t, gtk.AlignCenterValue, omniboxValign(OmniboxSizeDefaults))
178+ assert.Equal(t, gtk.AlignStartValue, omniboxValign(ModalSizeConfig{UseFixedTopMargin: true}))
179+}
180+
181+func TestOmniboxListDefaults_ShowFiveScrollTen(t *testing.T) {
182+ assert.Equal(t, 5, OmniboxListDefaults.MaxVisibleRows)
183+ assert.Equal(t, 10, OmniboxListDefaults.MaxResults)
184+ assert.Less(t, OmniboxListDefaults.SmallMaxVisibleRows, OmniboxListDefaults.MaxVisibleRows)
185+}
186+
175187 func TestSessionManagerSizeDefaults_Values(t *testing.T) {
176188 assert.Greater(t, SessionManagerSizeDefaults.WidthPct, 0.0)
177189 assert.LessOrEqual(t, SessionManagerSizeDefaults.WidthPct, 1.0)
@@ -325,7 +337,7 @@ func TestCalculateModalDimensionsWithScale_LargeParent(t *testing.T) {
325337 parent := mockParent(t, 3000, 1200)
326338 w, m := CalculateModalDimensionsWithScale(parent, cfg, tt.scale)
327339 assert.Equal(t, tt.want, w, "scale %v", tt.scale)
328- assert.Equal(t, 240, m, "top margin unchanged")
340+ assert.Zero(t, m, "omnibox is centered, not top-margined")
329341 }
330342 }
331343
@@ -351,7 +363,7 @@ func TestCalculateModalDimensionsWithScale_NormalizesBadScale(t *testing.T) {
351363 parent := mockParent(t, 3000, 1080)
352364 w, m := CalculateModalDimensionsWithScale(parent, cfg, scale)
353365 assert.Equal(t, 800, w, "scale %v", scale)
354- assert.Equal(t, 216, m, "scale %v", scale)
366+ assert.Zero(t, m, "scale %v", scale)
355367 }
356368 }
357369
@@ -5,6 +5,7 @@ import (
5 "testing"5 "testing"
6 6
7 layoutmocks "github.com/bnema/dumber/internal/ui/layout/mocks"7 layoutmocks "github.com/bnema/dumber/internal/ui/layout/mocks"
8+ "github.com/bnema/puregotk/v4/gtk"
8 "github.com/stretchr/testify/assert"9 "github.com/stretchr/testify/assert"
9 )10 )
10 11
@@ -168,10 +169,21 @@ func TestDefaultRowHeights_Values(t *testing.T) {
168 func TestOmniboxSizeDefaults_Values(t *testing.T) {169 func TestOmniboxSizeDefaults_Values(t *testing.T) {
169 assert.InDelta(t, 0.8, OmniboxSizeDefaults.WidthPct, 0.0001)170 assert.InDelta(t, 0.8, OmniboxSizeDefaults.WidthPct, 0.0001)
170 assert.Equal(t, 800, OmniboxSizeDefaults.MaxWidth)171 assert.Equal(t, 800, OmniboxSizeDefaults.MaxWidth)
171- assert.InDelta(t, 0.2, OmniboxSizeDefaults.TopMarginPct, 0.0001)172+ assert.Zero(t, OmniboxSizeDefaults.TopMarginPct)
172 assert.Equal(t, 600, OmniboxSizeDefaults.FallbackHeight)173 assert.Equal(t, 600, OmniboxSizeDefaults.FallbackHeight)
173 }174 }
174 175
176+func TestOmniboxValign(t *testing.T) {
177+ assert.Equal(t, gtk.AlignCenterValue, omniboxValign(OmniboxSizeDefaults))
178+ assert.Equal(t, gtk.AlignStartValue, omniboxValign(ModalSizeConfig{UseFixedTopMargin: true}))
179+}
180+
181+func TestOmniboxListDefaults_ShowFiveScrollTen(t *testing.T) {
182+ assert.Equal(t, 5, OmniboxListDefaults.MaxVisibleRows)
183+ assert.Equal(t, 10, OmniboxListDefaults.MaxResults)
184+ assert.Less(t, OmniboxListDefaults.SmallMaxVisibleRows, OmniboxListDefaults.MaxVisibleRows)
185+}
186+
175 func TestSessionManagerSizeDefaults_Values(t *testing.T) {187 func TestSessionManagerSizeDefaults_Values(t *testing.T) {
176 assert.Greater(t, SessionManagerSizeDefaults.WidthPct, 0.0)188 assert.Greater(t, SessionManagerSizeDefaults.WidthPct, 0.0)
177 assert.LessOrEqual(t, SessionManagerSizeDefaults.WidthPct, 1.0)189 assert.LessOrEqual(t, SessionManagerSizeDefaults.WidthPct, 1.0)
@@ -325,7 +337,7 @@ func TestCalculateModalDimensionsWithScale_LargeParent(t *testing.T) {
325 parent := mockParent(t, 3000, 1200)337 parent := mockParent(t, 3000, 1200)
326 w, m := CalculateModalDimensionsWithScale(parent, cfg, tt.scale)338 w, m := CalculateModalDimensionsWithScale(parent, cfg, tt.scale)
327 assert.Equal(t, tt.want, w, "scale %v", tt.scale)339 assert.Equal(t, tt.want, w, "scale %v", tt.scale)
328- assert.Equal(t, 240, m, "top margin unchanged")340+ assert.Zero(t, m, "omnibox is centered, not top-margined")
329 }341 }
330 }342 }
331 343
@@ -351,7 +363,7 @@ func TestCalculateModalDimensionsWithScale_NormalizesBadScale(t *testing.T) {
351 parent := mockParent(t, 3000, 1080)363 parent := mockParent(t, 3000, 1080)
352 w, m := CalculateModalDimensionsWithScale(parent, cfg, scale)364 w, m := CalculateModalDimensionsWithScale(parent, cfg, scale)
353 assert.Equal(t, 800, w, "scale %v", scale)365 assert.Equal(t, 800, w, "scale %v", scale)
354- assert.Equal(t, 216, m, "scale %v", scale)366+ assert.Zero(t, m, "scale %v", scale)
355 }367 }
356 }368 }
357 369
M internal/ui/component/omnibox.go +46 -12
@@ -776,12 +776,21 @@ func (o *Omnibox) initOuterBox() error {
776776 return errNilWidget("outerBox")
777777 }
778778 o.outerBox.AddCssClass("omnibox-outer")
779- o.outerBox.SetHalign(gtk.AlignCenterValue) // Center horizontally
780- o.outerBox.SetValign(gtk.AlignStartValue) // Align to top
781- o.outerBox.SetVisible(false) // Hidden by default
779+ o.outerBox.SetHalign(gtk.AlignCenterValue)
780+ o.outerBox.SetValign(omniboxValign(o.sizeCfg))
781+ o.outerBox.SetVisible(false) // Hidden by default
782782 return nil
783783 }
784784
785+// omniboxValign centers the in-pane omnibox vertically; a fixed top margin
786+// (standalone window sized by its content) keeps it top-aligned.
787+func omniboxValign(cfg ModalSizeConfig) gtk.Align {
788+ if cfg.UseFixedTopMargin {
789+ return gtk.AlignStartValue
790+ }
791+ return gtk.AlignCenterValue
792+}
793+
785794 func (o *Omnibox) initMainBox() error {
786795 o.mainBox = gtk.NewBox(gtk.OrientationVerticalValue, 0)
787796 if o.mainBox == nil {
@@ -923,7 +932,7 @@ func (o *Omnibox) initList() error {
923932 return
924933 }
925934
926- targetURL := resolveTargetURLForSelection(mode, idx, o.effectiveMaxRows(), suggestions, favorites)
935+ targetURL := resolveTargetURLForSelection(mode, idx, OmniboxListDefaults.MaxResults, suggestions, favorites)
927936
928937 if targetURL != "" {
929938 o.submitNavigation(targetURL)
@@ -1503,7 +1512,7 @@ func (o *Omnibox) restoreEntryToRealInput() {
15031512 // updateGhostFromSelectionWithInput updates ghost text based on selected row and input.
15041513 func (o *Omnibox) updateGhostFromSelectionWithInput(entryText string) {
15051514 log := logging.FromContext(o.ctx)
1506- maxVisible := o.effectiveMaxRows()
1515+ maxVisible := OmniboxListDefaults.MaxResults
15071516 o.mu.RLock()
15081517 idx := o.selectedIndex
15091518 mode := o.viewMode
@@ -1632,7 +1641,7 @@ func (o *Omnibox) performSearch() {
16321641 }
16331642
16341643 // Perform fuzzy history search in background
1635- o.searchHistory(query, o.effectiveMaxRows(), token)
1644+ o.searchHistory(query, OmniboxListDefaults.MaxResults, token)
16361645 }
16371646
16381647 // searchHistory runs a fuzzy history search in a background goroutine.
@@ -1706,7 +1715,7 @@ func (o *Omnibox) loadInitialHistory(token uint64) {
17061715
17071716 // Capture effective result limit and age window on the GTK main thread
17081717 // before spawning goroutine.
1709- initialLimit := o.effectiveMaxRows()
1718+ initialLimit := OmniboxListDefaults.MaxResults
17101719 initialBehavior := o.initialBehavior
17111720 maxHistoryDays := o.maxHistoryDays
17121721
@@ -1962,8 +1971,13 @@ func (o *Omnibox) updateFavorites(favorites []Favorite, query string) {
19621971
19631972 // rebuildList rebuilds the ListBox contents.
19641973 func (o *Omnibox) rebuildList() {
1965- // Clear existing rows
1974+ // Clear existing rows and show new results from the top
19661975 o.listBox.RemoveAll()
1976+ if o.scrolledWin != nil {
1977+ if adj := o.scrolledWin.GetVadjustment(); adj != nil {
1978+ adj.SetValue(0)
1979+ }
1980+ }
19671981
19681982 o.mu.RLock()
19691983 mode := o.viewMode
@@ -2253,19 +2267,39 @@ func (o *Omnibox) selectIndex(index int) {
22532267 row := o.listBox.GetRowAtIndex(index)
22542268 if row != nil {
22552269 o.listBox.SelectRow(row)
2270+ o.scrollRowIntoView(row)
22562271 return
22572272 }
22582273
22592274 o.updateGhostFromSelection()
22602275 }
22612276
2277+// scrollRowIntoView scrolls the results list so the row is fully visible.
2278+// The entry keeps keyboard focus, so GTK does not scroll the list itself.
2279+func (o *Omnibox) scrollRowIntoView(row *gtk.ListBoxRow) {
2280+ if o.scrolledWin == nil || row == nil {
2281+ return
2282+ }
2283+ adj := o.scrolledWin.GetVadjustment()
2284+ if adj == nil {
2285+ return
2286+ }
2287+ src := &graphene.Point{}
2288+ out := &graphene.Point{}
2289+ if !row.ComputePoint(&o.listBox.Widget, src, out) {
2290+ return
2291+ }
2292+ top := float64(out.Y)
2293+ adj.ClampPage(top, top+float64(row.GetAllocatedHeight()))
2294+}
2295+
22622296 // selectNext moves selection down.
22632297 func (o *Omnibox) selectNext() {
22642298 o.mu.Lock()
22652299 current := o.selectedIndex
22662300 mode := o.viewMode
22672301 bangMode := o.bangMode
2268- maxVisible := o.effectiveMaxRows()
2302+ maxVisible := OmniboxListDefaults.MaxResults
22692303 var maxIndex int
22702304 if bangMode {
22712305 maxIndex = visibleResultCount(len(o.bangSuggestions), maxVisible) - 1
@@ -2294,7 +2328,7 @@ func (o *Omnibox) selectPrevious() {
22942328 current := o.selectedIndex
22952329 mode := o.viewMode
22962330 bangMode := o.bangMode
2297- maxVisible := o.effectiveMaxRows()
2331+ maxVisible := OmniboxListDefaults.MaxResults
22982332 var maxIndex int
22992333 if bangMode {
23002334 maxIndex = visibleResultCount(len(o.bangSuggestions), maxVisible) - 1
@@ -2327,7 +2361,7 @@ func (o *Omnibox) selectAndNavigate(index int) {
23272361 suggestions := o.suggestions
23282362 favorites := o.favorites
23292363 o.mu.RUnlock()
2330- maxVisible := o.effectiveMaxRows()
2364+ maxVisible := OmniboxListDefaults.MaxResults
23312365
23322366 if bangMode {
23332367 o.navigateToSelected()
@@ -2400,7 +2434,7 @@ func (o *Omnibox) navigateToSelected() {
24002434 var targetURL string
24012435 if idx >= 0 {
24022436 // If user has selected a result, navigate to that result.
2403- targetURL = resolveTargetURLForSelection(mode, idx, o.effectiveMaxRows(), suggestions, favorites)
2437+ targetURL = resolveTargetURLForSelection(mode, idx, OmniboxListDefaults.MaxResults, suggestions, favorites)
24042438 } else {
24052439 targetURL = o.buildURL(entryText)
24062440 }
@@ -776,12 +776,21 @@ func (o *Omnibox) initOuterBox() error {
776 return errNilWidget("outerBox")776 return errNilWidget("outerBox")
777 }777 }
778 o.outerBox.AddCssClass("omnibox-outer")778 o.outerBox.AddCssClass("omnibox-outer")
779- o.outerBox.SetHalign(gtk.AlignCenterValue) // Center horizontally779+ o.outerBox.SetHalign(gtk.AlignCenterValue)
780- o.outerBox.SetValign(gtk.AlignStartValue) // Align to top780+ o.outerBox.SetValign(omniboxValign(o.sizeCfg))
781- o.outerBox.SetVisible(false) // Hidden by default781+ o.outerBox.SetVisible(false) // Hidden by default
782 return nil782 return nil
783 }783 }
784 784
785+// omniboxValign centers the in-pane omnibox vertically; a fixed top margin
786+// (standalone window sized by its content) keeps it top-aligned.
787+func omniboxValign(cfg ModalSizeConfig) gtk.Align {
788+ if cfg.UseFixedTopMargin {
789+ return gtk.AlignStartValue
790+ }
791+ return gtk.AlignCenterValue
792+}
793+
785 func (o *Omnibox) initMainBox() error {794 func (o *Omnibox) initMainBox() error {
786 o.mainBox = gtk.NewBox(gtk.OrientationVerticalValue, 0)795 o.mainBox = gtk.NewBox(gtk.OrientationVerticalValue, 0)
787 if o.mainBox == nil {796 if o.mainBox == nil {
@@ -923,7 +932,7 @@ func (o *Omnibox) initList() error {
923 return932 return
924 }933 }
925 934
926- targetURL := resolveTargetURLForSelection(mode, idx, o.effectiveMaxRows(), suggestions, favorites)935+ targetURL := resolveTargetURLForSelection(mode, idx, OmniboxListDefaults.MaxResults, suggestions, favorites)
927 936
928 if targetURL != "" {937 if targetURL != "" {
929 o.submitNavigation(targetURL)938 o.submitNavigation(targetURL)
@@ -1503,7 +1512,7 @@ func (o *Omnibox) restoreEntryToRealInput() {
1503 // updateGhostFromSelectionWithInput updates ghost text based on selected row and input.1512 // updateGhostFromSelectionWithInput updates ghost text based on selected row and input.
1504 func (o *Omnibox) updateGhostFromSelectionWithInput(entryText string) {1513 func (o *Omnibox) updateGhostFromSelectionWithInput(entryText string) {
1505 log := logging.FromContext(o.ctx)1514 log := logging.FromContext(o.ctx)
1506- maxVisible := o.effectiveMaxRows()1515+ maxVisible := OmniboxListDefaults.MaxResults
1507 o.mu.RLock()1516 o.mu.RLock()
1508 idx := o.selectedIndex1517 idx := o.selectedIndex
1509 mode := o.viewMode1518 mode := o.viewMode
@@ -1632,7 +1641,7 @@ func (o *Omnibox) performSearch() {
1632 }1641 }
1633 1642
1634 // Perform fuzzy history search in background1643 // Perform fuzzy history search in background
1635- o.searchHistory(query, o.effectiveMaxRows(), token)1644+ o.searchHistory(query, OmniboxListDefaults.MaxResults, token)
1636 }1645 }
1637 1646
1638 // searchHistory runs a fuzzy history search in a background goroutine.1647 // searchHistory runs a fuzzy history search in a background goroutine.
@@ -1706,7 +1715,7 @@ func (o *Omnibox) loadInitialHistory(token uint64) {
1706 1715
1707 // Capture effective result limit and age window on the GTK main thread1716 // Capture effective result limit and age window on the GTK main thread
1708 // before spawning goroutine.1717 // before spawning goroutine.
1709- initialLimit := o.effectiveMaxRows()1718+ initialLimit := OmniboxListDefaults.MaxResults
1710 initialBehavior := o.initialBehavior1719 initialBehavior := o.initialBehavior
1711 maxHistoryDays := o.maxHistoryDays1720 maxHistoryDays := o.maxHistoryDays
1712 1721
@@ -1962,8 +1971,13 @@ func (o *Omnibox) updateFavorites(favorites []Favorite, query string) {
1962 1971
1963 // rebuildList rebuilds the ListBox contents.1972 // rebuildList rebuilds the ListBox contents.
1964 func (o *Omnibox) rebuildList() {1973 func (o *Omnibox) rebuildList() {
1965- // Clear existing rows1974+ // Clear existing rows and show new results from the top
1966 o.listBox.RemoveAll()1975 o.listBox.RemoveAll()
1976+ if o.scrolledWin != nil {
1977+ if adj := o.scrolledWin.GetVadjustment(); adj != nil {
1978+ adj.SetValue(0)
1979+ }
1980+ }
1967 1981
1968 o.mu.RLock()1982 o.mu.RLock()
1969 mode := o.viewMode1983 mode := o.viewMode
@@ -2253,19 +2267,39 @@ func (o *Omnibox) selectIndex(index int) {
2253 row := o.listBox.GetRowAtIndex(index)2267 row := o.listBox.GetRowAtIndex(index)
2254 if row != nil {2268 if row != nil {
2255 o.listBox.SelectRow(row)2269 o.listBox.SelectRow(row)
2270+ o.scrollRowIntoView(row)
2256 return2271 return
2257 }2272 }
2258 2273
2259 o.updateGhostFromSelection()2274 o.updateGhostFromSelection()
2260 }2275 }
2261 2276
2277+// scrollRowIntoView scrolls the results list so the row is fully visible.
2278+// The entry keeps keyboard focus, so GTK does not scroll the list itself.
2279+func (o *Omnibox) scrollRowIntoView(row *gtk.ListBoxRow) {
2280+ if o.scrolledWin == nil || row == nil {
2281+ return
2282+ }
2283+ adj := o.scrolledWin.GetVadjustment()
2284+ if adj == nil {
2285+ return
2286+ }
2287+ src := &graphene.Point{}
2288+ out := &graphene.Point{}
2289+ if !row.ComputePoint(&o.listBox.Widget, src, out) {
2290+ return
2291+ }
2292+ top := float64(out.Y)
2293+ adj.ClampPage(top, top+float64(row.GetAllocatedHeight()))
2294+}
2295+
2262 // selectNext moves selection down.2296 // selectNext moves selection down.
2263 func (o *Omnibox) selectNext() {2297 func (o *Omnibox) selectNext() {
2264 o.mu.Lock()2298 o.mu.Lock()
2265 current := o.selectedIndex2299 current := o.selectedIndex
2266 mode := o.viewMode2300 mode := o.viewMode
2267 bangMode := o.bangMode2301 bangMode := o.bangMode
2268- maxVisible := o.effectiveMaxRows()2302+ maxVisible := OmniboxListDefaults.MaxResults
2269 var maxIndex int2303 var maxIndex int
2270 if bangMode {2304 if bangMode {
2271 maxIndex = visibleResultCount(len(o.bangSuggestions), maxVisible) - 12305 maxIndex = visibleResultCount(len(o.bangSuggestions), maxVisible) - 1
@@ -2294,7 +2328,7 @@ func (o *Omnibox) selectPrevious() {
2294 current := o.selectedIndex2328 current := o.selectedIndex
2295 mode := o.viewMode2329 mode := o.viewMode
2296 bangMode := o.bangMode2330 bangMode := o.bangMode
2297- maxVisible := o.effectiveMaxRows()2331+ maxVisible := OmniboxListDefaults.MaxResults
2298 var maxIndex int2332 var maxIndex int
2299 if bangMode {2333 if bangMode {
2300 maxIndex = visibleResultCount(len(o.bangSuggestions), maxVisible) - 12334 maxIndex = visibleResultCount(len(o.bangSuggestions), maxVisible) - 1
@@ -2327,7 +2361,7 @@ func (o *Omnibox) selectAndNavigate(index int) {
2327 suggestions := o.suggestions2361 suggestions := o.suggestions
2328 favorites := o.favorites2362 favorites := o.favorites
2329 o.mu.RUnlock()2363 o.mu.RUnlock()
2330- maxVisible := o.effectiveMaxRows()2364+ maxVisible := OmniboxListDefaults.MaxResults
2331 2365
2332 if bangMode {2366 if bangMode {
2333 o.navigateToSelected()2367 o.navigateToSelected()
@@ -2400,7 +2434,7 @@ func (o *Omnibox) navigateToSelected() {
2400 var targetURL string2434 var targetURL string
2401 if idx >= 0 {2435 if idx >= 0 {
2402 // If user has selected a result, navigate to that result.2436 // If user has selected a result, navigate to that result.
2403- targetURL = resolveTargetURLForSelection(mode, idx, o.effectiveMaxRows(), suggestions, favorites)2437+ targetURL = resolveTargetURLForSelection(mode, idx, OmniboxListDefaults.MaxResults, suggestions, favorites)
2404 } else {2438 } else {
2405 targetURL = o.buildURL(entryText)2439 targetURL = o.buildURL(entryText)
2406 }2440 }
M internal/ui/component/omnibox_initial_behavior_test.go +1 -1
@@ -287,7 +287,7 @@ func TestOmniboxLoadInitialHistory_MostVisitedBoundsSQL(t *testing.T) {
287287 repo := repomocks.NewMockHistoryRepository(t)
288288 done := make(chan struct{})
289289 repo.EXPECT().
290- GetMostVisitedWithin(mock.Anything, OmniboxListDefaults.MaxVisibleRows, mock.Anything).
290+ GetMostVisitedWithin(mock.Anything, OmniboxListDefaults.MaxResults, mock.Anything).
291291 Run(func(context.Context, int, repository.HistoryScope) { close(done) }).
292292 Return([]*entity.HistoryEntry{{URL: "https://example.com"}}, nil)
293293
@@ -287,7 +287,7 @@ func TestOmniboxLoadInitialHistory_MostVisitedBoundsSQL(t *testing.T) {
287 repo := repomocks.NewMockHistoryRepository(t)287 repo := repomocks.NewMockHistoryRepository(t)
288 done := make(chan struct{})288 done := make(chan struct{})
289 repo.EXPECT().289 repo.EXPECT().
290- GetMostVisitedWithin(mock.Anything, OmniboxListDefaults.MaxVisibleRows, mock.Anything).290+ GetMostVisitedWithin(mock.Anything, OmniboxListDefaults.MaxResults, mock.Anything).
291 Run(func(context.Context, int, repository.HistoryScope) { close(done) }).291 Run(func(context.Context, int, repository.HistoryScope) { close(done) }).
292 Return([]*entity.HistoryEntry{{URL: "https://example.com"}}, nil)292 Return([]*entity.HistoryEntry{{URL: "https://example.com"}}, nil)
293 293

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close