mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-05 21:46:49 -04:00
Separate redraws from view-line invalidation
A view can need repainting even when its cached wrapping is still valid. Track that state independently so content-only flushes do not overload tainted, whose only job is to request a viewLines rebuild.
This commit is contained in:
+4
-4
@@ -1598,10 +1598,10 @@ func (g *Gui) flush() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Redraws only tainted views and skips the layout pass.
|
||||
// Redraws only dirty views and skips the layout pass.
|
||||
// tcell's cell-level dirty tracking ensures only
|
||||
// actually-changed cells are emitted to the terminal.
|
||||
// Will also redraw any views that overlap tainted views
|
||||
// Will also redraw any views that overlap dirty views.
|
||||
func (g *Gui) flushContentOnly(views []*View) {
|
||||
// The screen must not be touched while suspended (see Suspend).
|
||||
if g.isSuspended() {
|
||||
@@ -1619,7 +1619,7 @@ func viewsToRedrawContentOnly(views []*View) []*View {
|
||||
redrawIndexes := set.New[int]()
|
||||
|
||||
for i, v := range views {
|
||||
if !v.IsTainted() && !redrawIndexes.Includes(i) {
|
||||
if !v.NeedsRedraw() && !redrawIndexes.Includes(i) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1649,7 +1649,7 @@ func (g *Gui) ForceLayoutAndRedraw() error {
|
||||
return g.flush()
|
||||
}
|
||||
|
||||
// Redraws only tainted views outside of the normal main
|
||||
// Redraws only dirty views outside of the normal main
|
||||
// loop, without a layout pass. Useful during longer operations that block the
|
||||
// main thread, e.g. to update a spinner in a status view.
|
||||
func (g *Gui) ForceFlushViewsContentOnly(views []*View) {
|
||||
|
||||
+23
-3
@@ -86,6 +86,11 @@ type View struct {
|
||||
// tained is true if the viewLines must be updated
|
||||
tainted bool
|
||||
|
||||
// needsRedraw is true if the view's current state has not been drawn to the
|
||||
// screen yet. A tainted view always needs a redraw, but draw-only state can
|
||||
// require one without invalidating viewLines.
|
||||
needsRedraw bool
|
||||
|
||||
// firstDirtyLine is the index of the lowest line in `lines` that has been
|
||||
// written to since viewLines was last refreshed, and whose cached wrapping
|
||||
// (lineType.wrappedCells) may therefore be stale. Lines below it are
|
||||
@@ -274,11 +279,18 @@ type pos struct {
|
||||
// a view whose size has changed, whose content is the same but has to be wrapped
|
||||
// afresh, call RewrapContent instead.
|
||||
func (v *View) clearViewLines() {
|
||||
v.tainted = true
|
||||
v.markViewLinesDirty()
|
||||
v.viewLines = nil
|
||||
v.clearHover()
|
||||
}
|
||||
|
||||
// markViewLinesDirty records that the cached viewLines no longer represent the
|
||||
// view's buffer or wrapping, so both rebuilding and redrawing are required.
|
||||
func (v *View) markViewLinesDirty() {
|
||||
v.tainted = true
|
||||
v.needsRedraw = true
|
||||
}
|
||||
|
||||
// RewrapContent wraps the view's content for the size the view has now, and puts
|
||||
// the positions into that content — the scroll offset, the cursor, a range's
|
||||
// anchor — back on the lines they were on. They are all view lines, which count
|
||||
@@ -793,6 +805,7 @@ func NewView(name string, x0, y0, x1, y1 int, mode OutputMode) *View {
|
||||
Frame: true,
|
||||
Editor: DefaultEditor,
|
||||
tainted: true,
|
||||
needsRedraw: true,
|
||||
outMode: mode,
|
||||
buf: &viewBuffer{ei: newEscapeInterpreter(mode)},
|
||||
searcher: &searcher{},
|
||||
@@ -1169,7 +1182,7 @@ func (v *View) write(p []byte) {
|
||||
return
|
||||
}
|
||||
|
||||
v.tainted = true
|
||||
v.markViewLinesDirty()
|
||||
// write only ever touches lines from v.buf.wy onwards, so any cached wrapping
|
||||
// below that stays valid.
|
||||
v.firstDirtyLine = min(v.firstDirtyLine, v.buf.wy)
|
||||
@@ -1604,7 +1617,7 @@ func (v *View) SwapInOffscreenRender() {
|
||||
}
|
||||
v.buf = v.offscreen
|
||||
v.offscreen = nil
|
||||
v.tainted = true
|
||||
v.markViewLinesDirty()
|
||||
v.clearHover()
|
||||
}
|
||||
|
||||
@@ -1768,6 +1781,12 @@ func (v *View) IsTainted() bool {
|
||||
return v.tainted
|
||||
}
|
||||
|
||||
func (v *View) NeedsRedraw() bool {
|
||||
v.writeMutex.Lock()
|
||||
defer v.writeMutex.Unlock()
|
||||
return v.needsRedraw
|
||||
}
|
||||
|
||||
// draw re-draws the view's contents.
|
||||
func (v *View) draw(isWindowFocused bool) {
|
||||
v.writeMutex.Lock()
|
||||
@@ -1776,6 +1795,7 @@ func (v *View) draw(isWindowFocused bool) {
|
||||
if !v.Visible {
|
||||
return
|
||||
}
|
||||
defer func() { v.needsRedraw = false }()
|
||||
|
||||
v.clearRunes()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user