diff --git a/pkg/gocui/gui.go b/pkg/gocui/gui.go index 700c2b54c..936e1a310 100644 --- a/pkg/gocui/gui.go +++ b/pkg/gocui/gui.go @@ -385,7 +385,7 @@ func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, er v.y1 = y1 if sizeChanged { - v.clearViewLines() + v.ClearViewLines() if v.Editable { cursorX, cursorY := v.TextArea.GetCursorXY() @@ -1461,7 +1461,7 @@ func (g *Gui) flush() error { // if GUI's size has changed, we need to redraw all views if maxX != g.maxX || maxY != g.maxY { for _, v := range g.views { - v.clearViewLines() + v.ClearViewLines() } } g.maxX, g.maxY = maxX, maxY @@ -1500,7 +1500,7 @@ func viewsToRedrawContentOnly(views []*View) []*View { redrawIndexes := set.New[int]() for i, v := range views { - if !v.tainted && !redrawIndexes.Includes(i) { + if !v.IsTainted() && !redrawIndexes.Includes(i) { continue } diff --git a/pkg/gocui/view.go b/pkg/gocui/view.go index ae8aea880..39f2d78a9 100644 --- a/pkg/gocui/view.go +++ b/pkg/gocui/view.go @@ -214,6 +214,16 @@ func (v *View) clearViewLines() { v.clearHover() } +// ClearViewLines is clearViewLines guarded by writeMutex. It's for callers on +// the UI thread (the layout pass) that touch a view whose content a task +// goroutine may be writing concurrently: viewLines/tainted/hover are all +// buffer state that writeMutex protects. +func (v *View) ClearViewLines() { + v.writeMutex.Lock() + defer v.writeMutex.Unlock() + v.clearViewLines() +} + type searcher struct { searchString string searchPositions []SearchPosition @@ -1287,6 +1297,8 @@ func (v *View) updateSearchPositions() { // IsTainted tells us if the view is tainted func (v *View) IsTainted() bool { + v.writeMutex.Lock() + defer v.writeMutex.Unlock() return v.tainted } @@ -1535,6 +1547,9 @@ func (v *View) BufferLines() []string { // Buffer returns a string with the contents of the view's internal // buffer. func (v *View) Buffer() string { + v.writeMutex.Lock() + defer v.writeMutex.Unlock() + return linesToString(v.lines) }