Skip to content

Commit a67eda3

Browse files
committed
Rerender fewer views when their width changes
In d5b4f7b and 58a83b0 we introduced a combined mechanism for rerendering views when either their width changes (needed for the branches view which truncates long branch names), or the screen mode (needed for those views that display more information in half or full screen mode, e.g. the commits view). This was a bad idea, because it unnecessarily rerenders too many views when just their width changes, which causes a noticable lag. This is a problem, for example, when selecting a file in the files panel that has only unstaged changes, and then going to one that has both staged and unstaged changes; this splits the main view, causing the side panels to become a bit narrower, and rerendering all those views took almost 500ms on my machine. Another similar example is entering or leaving staging mode. Fix this by being more specific about which views need rerendering under what conditions; this improves the time it takes to rerender in the above scenarios from 450-500s down to about 20ms. This reintroduces the code that was removed in 58a83b0, but in a slightly different way.
1 parent 8e1464f commit a67eda3

File tree

8 files changed

+48
-11
lines changed

8 files changed

+48
-11
lines changed

pkg/gui/context/base_context.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type BaseContext struct {
2323
focusable bool
2424
transient bool
2525
hasControlledBounds bool
26-
needsRerenderOnWidthChange bool
26+
needsRerenderOnWidthChange types.NeedsRerenderOnWidthChangeLevel
2727
needsRerenderOnHeightChange bool
2828
highlightOnFocus bool
2929

@@ -46,7 +46,7 @@ type NewBaseContextOpts struct {
4646
Transient bool
4747
HasUncontrolledBounds bool // negating for the sake of making false the default
4848
HighlightOnFocus bool
49-
NeedsRerenderOnWidthChange bool
49+
NeedsRerenderOnWidthChange types.NeedsRerenderOnWidthChangeLevel
5050
NeedsRerenderOnHeightChange bool
5151

5252
OnGetOptionsMap func() map[string]string
@@ -201,7 +201,7 @@ func (self *BaseContext) HasControlledBounds() bool {
201201
return self.hasControlledBounds
202202
}
203203

204-
func (self *BaseContext) NeedsRerenderOnWidthChange() bool {
204+
func (self *BaseContext) NeedsRerenderOnWidthChange() types.NeedsRerenderOnWidthChangeLevel {
205205
return self.needsRerenderOnWidthChange
206206
}
207207

pkg/gui/context/branches_context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
4646
Key: LOCAL_BRANCHES_CONTEXT_KEY,
4747
Kind: types.SIDE_CONTEXT,
4848
Focusable: true,
49-
NeedsRerenderOnWidthChange: true,
49+
NeedsRerenderOnWidthChange: types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES,
5050
})),
5151
ListRenderer: ListRenderer{
5252
list: viewModel,

pkg/gui/context/local_commits_context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
7777
Key: LOCAL_COMMITS_CONTEXT_KEY,
7878
Kind: types.SIDE_CONTEXT,
7979
Focusable: true,
80-
NeedsRerenderOnWidthChange: true,
80+
NeedsRerenderOnWidthChange: types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES,
8181
NeedsRerenderOnHeightChange: true,
8282
})),
8383
ListRenderer: ListRenderer{

pkg/gui/context/reflog_commits_context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
4848
Key: REFLOG_COMMITS_CONTEXT_KEY,
4949
Kind: types.SIDE_CONTEXT,
5050
Focusable: true,
51-
NeedsRerenderOnWidthChange: true,
51+
NeedsRerenderOnWidthChange: types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES,
5252
})),
5353
ListRenderer: ListRenderer{
5454
list: viewModel,

pkg/gui/context/sub_commits_context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func NewSubCommitsContext(
121121
Kind: types.SIDE_CONTEXT,
122122
Focusable: true,
123123
Transient: true,
124-
NeedsRerenderOnWidthChange: true,
124+
NeedsRerenderOnWidthChange: types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES,
125125
NeedsRerenderOnHeightChange: true,
126126
})),
127127
ListRenderer: ListRenderer{

pkg/gui/controllers/screen_mode_actions.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package controllers
22

33
import (
4+
"github.com/jesseduffield/gocui"
45
"github.com/jesseduffield/lazygit/pkg/gui/types"
56
)
67

@@ -16,7 +17,7 @@ func (self *ScreenModeActions) Next() error {
1617
),
1718
)
1819

19-
return nil
20+
return self.rerenderViewsWithScreenModeDependentContent()
2021
}
2122

2223
func (self *ScreenModeActions) Prev() error {
@@ -27,9 +28,33 @@ func (self *ScreenModeActions) Prev() error {
2728
),
2829
)
2930

31+
return self.rerenderViewsWithScreenModeDependentContent()
32+
}
33+
34+
// these views need to be re-rendered when the screen mode changes. The commits view,
35+
// for example, will show authorship information in half and full screen mode.
36+
func (self *ScreenModeActions) rerenderViewsWithScreenModeDependentContent() error {
37+
for _, context := range self.c.Context().AllList() {
38+
if context.NeedsRerenderOnWidthChange() == types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES {
39+
if err := self.rerenderView(context.GetView()); err != nil {
40+
return err
41+
}
42+
}
43+
}
44+
3045
return nil
3146
}
3247

48+
func (self *ScreenModeActions) rerenderView(view *gocui.View) error {
49+
context, ok := self.c.Helpers().View.ContextForView(view.Name())
50+
if !ok {
51+
self.c.Log.Errorf("no context found for view %s", view.Name())
52+
return nil
53+
}
54+
55+
return context.HandleRender()
56+
}
57+
3358
func nextIntInCycle(sl []types.WindowMaximisation, current types.WindowMaximisation) types.WindowMaximisation {
3459
for i, val := range sl {
3560
if val == current {

pkg/gui/layout.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
7373
}
7474

7575
mustRerender := false
76-
if context.NeedsRerenderOnWidthChange() {
76+
if context.NeedsRerenderOnWidthChange() == types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES {
7777
// view.Width() returns the width -1 for some reason
7878
oldWidth := view.Width() + 1
7979
newWidth := dimensionsObj.X1 - dimensionsObj.X0 + 2*frameOffset

pkg/gui/types/context.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ type ParentContexter interface {
3939
GetParentContext() (Context, bool)
4040
}
4141

42+
type NeedsRerenderOnWidthChangeLevel int
43+
44+
const (
45+
// view doesn't render differently when its width changes
46+
NEEDS_RERENDER_ON_WIDTH_CHANGE_NONE NeedsRerenderOnWidthChangeLevel = iota
47+
// view renders differently when its width changes. An example is a view
48+
// that truncates long lines to the view width, e.g. the branches view
49+
NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES
50+
// view renders differently only when the screen mode changes
51+
NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES
52+
)
53+
4254
type IBaseContext interface {
4355
HasKeybindings
4456
ParentContexter
@@ -60,8 +72,8 @@ type IBaseContext interface {
6072
// determined independently.
6173
HasControlledBounds() bool
6274

63-
// true if the view needs to be rerendered when its width changes
64-
NeedsRerenderOnWidthChange() bool
75+
// to what extent the view needs to be rerendered when its width changes
76+
NeedsRerenderOnWidthChange() NeedsRerenderOnWidthChangeLevel
6577

6678
// true if the view needs to be rerendered when its height changes
6779
NeedsRerenderOnHeightChange() bool

0 commit comments

Comments
 (0)