Skip to content

Commit e1a8327

Browse files
authored
Avoid scrolling the selection into view on refresh (#5134)
It is possible to scroll the selection out of view using the mouse wheel; after doing this, it would sometimes scroll into view by itself again, for example when a background fetch occurred. In the files panel this would even happen every 10s with every regular files refresh. Fix this by adding a scrollIntoView parameter to HandleFocus, which is false by default, and is only set to true from controllers that change the selection. Fixes #5097.
2 parents 74b1255 + 478d51c commit e1a8327

File tree

17 files changed

+53
-37
lines changed

17 files changed

+53
-37
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ require (
1818
github.com/integrii/flaggy v1.4.0
1919
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c
2020
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd
21-
github.com/jesseduffield/gocui v0.3.1-0.20251214132308-02ab34c1c624
21+
github.com/jesseduffield/gocui v0.3.1-0.20251223143206-950739ccd44a
2222
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
2323
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
2424
github.com/karimkhaleel/jsonschema v0.0.0-20231001195015-d933f0d94ea3

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c h1:tC2Paiis
194194
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c/go.mod h1:F2fEBk0ddf6ixrBrJjY7phfQ3hL9rXG0uSjvwYe50bE=
195195
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd h1:ViKj6qth8FgcIWizn9KiACWwPemWSymx62OPN0tHT+Q=
196196
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd/go.mod h1:lRhCiBr6XjQrvcQVa+UYsy/99d3wMXn/a0nSQlhnhlA=
197-
github.com/jesseduffield/gocui v0.3.1-0.20251214132308-02ab34c1c624 h1:30mIX4f52zrO4fWfZQKHJG29t2apcSOtR/sbd3BNsVE=
198-
github.com/jesseduffield/gocui v0.3.1-0.20251214132308-02ab34c1c624/go.mod h1:sLIyZ2J42R6idGdtemZzsiR3xY5EF0KsvYEGh3dQv3s=
197+
github.com/jesseduffield/gocui v0.3.1-0.20251223143206-950739ccd44a h1:XRsyqrSljes4TlaPczQViIAA4xqdnB0fKEEpZdqWWTA=
198+
github.com/jesseduffield/gocui v0.3.1-0.20251223143206-950739ccd44a/go.mod h1:sLIyZ2J42R6idGdtemZzsiR3xY5EF0KsvYEGh3dQv3s=
199199
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
200200
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5/go.mod h1:qxN4mHOAyeIDLP7IK7defgPClM/z1Kze8VVQiaEjzsQ=
201201
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=

pkg/gui/context/list_context_trait.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ type ListContextTrait struct {
2525

2626
func (self *ListContextTrait) IsListContext() {}
2727

28-
func (self *ListContextTrait) FocusLine() {
29-
self.Context.FocusLine()
28+
func (self *ListContextTrait) FocusLine(scrollIntoView bool) {
29+
self.Context.FocusLine(scrollIntoView)
3030

3131
// Doing this at the end of the layout function because we need the view to be
3232
// resized before we focus the line, otherwise if we're in accordion mode
@@ -36,7 +36,7 @@ func (self *ListContextTrait) FocusLine() {
3636
oldOrigin, _ := self.GetViewTrait().ViewPortYBounds()
3737

3838
self.GetViewTrait().FocusPoint(
39-
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()))
39+
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()), scrollIntoView)
4040

4141
selectRangeIndex, isSelectingRange := self.list.GetRangeStartIdx()
4242
if isSelectingRange {
@@ -75,7 +75,7 @@ func formatListFooter(selectedLineIdx int, length int) string {
7575
}
7676

7777
func (self *ListContextTrait) HandleFocus(opts types.OnFocusOpts) {
78-
self.FocusLine()
78+
self.FocusLine(opts.ScrollSelectionIntoView)
7979

8080
self.GetViewTrait().SetHighlight(self.list.Len() > 0)
8181

pkg/gui/context/simple_context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (self *SimpleContext) HandleFocusLost(opts types.OnFocusLostOpts) {
5454
}
5555
}
5656

57-
func (self *SimpleContext) FocusLine() {
57+
func (self *SimpleContext) FocusLine(scrollIntoView bool) {
5858
}
5959

6060
func (self *SimpleContext) HandleRender() {

pkg/gui/context/view_trait.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ func NewViewTrait(view *gocui.View) *ViewTrait {
1717
return &ViewTrait{view: view}
1818
}
1919

20-
func (self *ViewTrait) FocusPoint(yIdx int) {
21-
self.view.FocusPoint(self.view.OriginX(), yIdx)
20+
func (self *ViewTrait) FocusPoint(yIdx int, scrollIntoView bool) {
21+
self.view.FocusPoint(self.view.OriginX(), yIdx, scrollIntoView)
2222
}
2323

2424
func (self *ViewTrait) SetRangeSelectStart(yIdx int) {

pkg/gui/controllers/branches_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ func (self *BranchesController) createNewBranchWithName(newBranchName string) er
531531
return err
532532
}
533533

534-
self.context().SetSelection(0)
534+
self.c.Helpers().Refs.SelectFirstBranchAndFirstCommit()
535535
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, KeepBranchSelectionIndex: true})
536536
return nil
537537
}

pkg/gui/controllers/helpers/cherry_pick_helper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func (self *CherryPickHelper) Paste() error {
101101
// below the selection.
102102
if commit := self.c.Contexts().LocalCommits.GetSelected(); commit != nil && !commit.IsTODO() {
103103
self.c.Contexts().LocalCommits.MoveSelection(len(cherryPickedCommits))
104-
self.c.Contexts().LocalCommits.FocusLine()
104+
self.c.Contexts().LocalCommits.FocusLine(true)
105105
}
106106

107107
// If we're in the cherry-picking state at this point, it must

pkg/gui/controllers/helpers/refs_helper.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ func NewRefsHelper(
3131
}
3232
}
3333

34+
func (self *RefsHelper) SelectFirstBranchAndFirstCommit() {
35+
self.c.Contexts().Branches.SetSelection(0)
36+
self.c.Contexts().ReflogCommits.SetSelection(0)
37+
self.c.Contexts().LocalCommits.SetSelection(0)
38+
self.c.Contexts().Branches.GetView().SetOriginY(0)
39+
self.c.Contexts().ReflogCommits.GetView().SetOriginY(0)
40+
self.c.Contexts().LocalCommits.GetView().SetOriginY(0)
41+
}
42+
3443
func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions) error {
3544
waitingStatus := options.WaitingStatus
3645
if waitingStatus == "" {
@@ -40,9 +49,8 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions
4049
cmdOptions := git_commands.CheckoutOptions{Force: false, EnvVars: options.EnvVars}
4150

4251
refresh := func() {
43-
self.c.Contexts().Branches.SetSelection(0)
44-
self.c.Contexts().ReflogCommits.SetSelection(0)
45-
self.c.Contexts().LocalCommits.SetSelection(0)
52+
self.SelectFirstBranchAndFirstCommit()
53+
4654
// loading a heap of commits is slow so we limit them whenever doing a reset
4755
self.c.Contexts().LocalCommits.SetLimitCommits(true)
4856

@@ -348,8 +356,7 @@ func (self *RefsHelper) NewBranch(from string, fromFormattedName string, suggest
348356
self.c.Context().Push(self.c.Contexts().Branches, types.OnFocusOpts{})
349357
}
350358

351-
self.c.Contexts().LocalCommits.SetSelection(0)
352-
self.c.Contexts().Branches.SetSelection(0)
359+
self.SelectFirstBranchAndFirstCommit()
353360

354361
self.c.Refresh(types.RefreshOptions{Mode: types.BLOCK_UI, KeepBranchSelectionIndex: true})
355362
}
@@ -504,8 +511,7 @@ func (self *RefsHelper) moveCommitsToNewBranchStackedOnCurrentBranch(newBranchNa
504511
}
505512
}
506513

507-
self.c.Contexts().LocalCommits.SetSelection(0)
508-
self.c.Contexts().Branches.SetSelection(0)
514+
self.SelectFirstBranchAndFirstCommit()
509515

510516
self.c.Refresh(types.RefreshOptions{Mode: types.BLOCK_UI, KeepBranchSelectionIndex: true})
511517
return nil
@@ -543,8 +549,7 @@ func (self *RefsHelper) moveCommitsToNewBranchOffOfMainBranch(newBranchName stri
543549
}
544550
}
545551

546-
self.c.Contexts().LocalCommits.SetSelection(0)
547-
self.c.Contexts().Branches.SetSelection(0)
552+
self.SelectFirstBranchAndFirstCommit()
548553

549554
self.c.Refresh(types.RefreshOptions{Mode: types.BLOCK_UI, KeepBranchSelectionIndex: true})
550555
return nil

pkg/gui/controllers/list_controller.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,12 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
116116
}
117117

118118
if cursorMoved || rangeBefore != rangeAfter {
119-
self.context.HandleFocus(types.OnFocusOpts{})
119+
self.context.HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})
120+
} else {
121+
// If the selection did not change (because, for example, we are at the top of the list and
122+
// press up), we still want to ensure that the selection is visible. This is useful after
123+
// scrolling the selection out of view with the mouse.
124+
self.context.FocusLine(true)
120125
}
121126

122127
return nil
@@ -173,6 +178,8 @@ func (self *ListController) handlePageChange(delta int) error {
173178
}
174179
}
175180

181+
// Since we are maintaining the scroll position ourselves above, there's no point in passing
182+
// ScrollSelectionIntoView=true here.
176183
self.context.HandleFocus(types.OnFocusOpts{})
177184

178185
return nil

pkg/gui/controllers/local_commits_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ func (self *LocalCommitsController) revert(commits []*models.Commit, start, end
869869
return err
870870
}
871871
self.context().MoveSelection(len(commits))
872-
self.context().HandleFocus(types.OnFocusOpts{})
872+
self.context().HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})
873873

874874
if mustStash {
875875
if err := self.c.Git().Stash.Pop(0); err != nil {

0 commit comments

Comments
 (0)