From c12752cf5315496282c81afcb868d6286a7ef1a5 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Thu, 1 Oct 2020 06:54:29 +1000 Subject: [PATCH] add mutex to views array --- go.mod | 2 +- go.sum | 2 + pkg/gui/context.go | 3 ++ vendor/github.com/jesseduffield/gocui/gui.go | 42 +++++++++++++++++--- vendor/modules.txt | 2 +- 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 4f2b48af480..c0088ab634b 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/golang/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.3.1 // indirect github.com/integrii/flaggy v1.4.0 - github.com/jesseduffield/gocui v0.3.1-0.20200927010622-b998f1723844 + github.com/jesseduffield/gocui v0.3.1-0.20200930205305-1b445b9bd5da github.com/jesseduffield/termbox-go v0.0.0-20200823212418-a2289ed6aafe // indirect github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect diff --git a/go.sum b/go.sum index e9a6e1f647f..0f1cbe1f09f 100644 --- a/go.sum +++ b/go.sum @@ -100,6 +100,8 @@ github.com/jesseduffield/gocui v0.3.1-0.20200824100831-1b6ec5d7d449 h1:G5Cm2QuFi github.com/jesseduffield/gocui v0.3.1-0.20200824100831-1b6ec5d7d449/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw= github.com/jesseduffield/gocui v0.3.1-0.20200927010622-b998f1723844 h1:D2/gUHscz5LmHojvNUmEVtvNBlX8OF6Ez82oW7GitfI= github.com/jesseduffield/gocui v0.3.1-0.20200927010622-b998f1723844/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw= +github.com/jesseduffield/gocui v0.3.1-0.20200930205305-1b445b9bd5da h1:I3GD+Set99tj57PgmjZJLoW6lkv0NTHadKNosJ1OKj4= +github.com/jesseduffield/gocui v0.3.1-0.20200930205305-1b445b9bd5da/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw= github.com/jesseduffield/termbox-go v0.0.0-20200823212418-a2289ed6aafe h1:qsVhCf2RFyyKIUe/+gJblbCpXMUki9rZrHuEctg6M/E= github.com/jesseduffield/termbox-go v0.0.0-20200823212418-a2289ed6aafe/go.mod h1:anMibpZtqNxjDbxrcDEAwSdaJ37vyUeM1f/M4uekib4= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= diff --git a/pkg/gui/context.go b/pkg/gui/context.go index c48626a4400..91d1d8738ec 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -617,6 +617,9 @@ func (gui *Gui) getFocusLayout() func(g *gocui.Gui) error { } func (gui *Gui) onViewFocusChange() error { + gui.g.Mutexes.ViewsMutex.Lock() + defer gui.g.Mutexes.ViewsMutex.Unlock() + currentView := gui.g.CurrentView() for _, view := range gui.g.Views() { view.Highlight = view.Name() != "main" && view == currentView diff --git a/vendor/github.com/jesseduffield/gocui/gui.go b/vendor/github.com/jesseduffield/gocui/gui.go index 3f89951b7c3..99cbf002b1a 100644 --- a/vendor/github.com/jesseduffield/gocui/gui.go +++ b/vendor/github.com/jesseduffield/gocui/gui.go @@ -48,6 +48,14 @@ type tabClickBinding struct { handler tabClickHandler } +type GuiMutexes struct { + // tickingMutex ensures we don't have two loops ticking. The point of 'ticking' + // is to refresh the gui rapidly so that loader characters can be animated. + tickingMutex sync.Mutex + + ViewsMutex sync.Mutex +} + // Gui represents the whole User Interface, including the views, layouts // and keybindings. type Gui struct { @@ -92,9 +100,7 @@ type Gui struct { // view edges SupportOverlaps bool - // tickingMutex ensures we don't have two loops ticking. The point of 'ticking' - // is to refresh the gui rapidly so that loader characters can be animated. - tickingMutex sync.Mutex + Mutexes GuiMutexes OnSearchEscape func() error // these keys must either be of type Key of rune @@ -192,11 +198,16 @@ func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, er return v, nil } + g.Mutexes.ViewsMutex.Lock() + v := newView(name, x0, y0, x1, y1, g.outputMode) v.BgColor, v.FgColor = g.BgColor, g.FgColor v.SelBgColor, v.SelFgColor = g.SelBgColor, g.SelFgColor v.Overlaps = overlaps g.views = append(g.views, v) + + g.Mutexes.ViewsMutex.Unlock() + return v, errors.Wrap(ErrUnknownView, 0) } @@ -213,6 +224,9 @@ func (g *Gui) SetViewBeneath(name string, aboveViewName string, height int) (*Vi // SetViewOnTop sets the given view on top of the existing ones. func (g *Gui) SetViewOnTop(name string) (*View, error) { + g.Mutexes.ViewsMutex.Lock() + defer g.Mutexes.ViewsMutex.Unlock() + for i, v := range g.views { if v.name == name { s := append(g.views[:i], g.views[i+1:]...) @@ -225,6 +239,9 @@ func (g *Gui) SetViewOnTop(name string) (*View, error) { // SetViewOnBottom sets the given view on bottom of the existing ones. func (g *Gui) SetViewOnBottom(name string) (*View, error) { + g.Mutexes.ViewsMutex.Lock() + defer g.Mutexes.ViewsMutex.Unlock() + for i, v := range g.views { if v.name == name { s := append(g.views[:i], g.views[i+1:]...) @@ -243,6 +260,9 @@ func (g *Gui) Views() []*View { // View returns a pointer to the view with the given name, or error // ErrUnknownView if a view with that name does not exist. func (g *Gui) View(name string) (*View, error) { + g.Mutexes.ViewsMutex.Lock() + defer g.Mutexes.ViewsMutex.Unlock() + for _, v := range g.views { if v.name == name { return v, nil @@ -254,6 +274,9 @@ func (g *Gui) View(name string) (*View, error) { // ViewByPosition returns a pointer to a view matching the given position, or // error ErrUnknownView if a view in that position does not exist. func (g *Gui) ViewByPosition(x, y int) (*View, error) { + g.Mutexes.ViewsMutex.Lock() + defer g.Mutexes.ViewsMutex.Unlock() + // traverse views in reverse order checking top views first for i := len(g.views); i > 0; i-- { v := g.views[i-1] @@ -271,6 +294,9 @@ func (g *Gui) ViewByPosition(x, y int) (*View, error) { // ViewPosition returns the coordinates of the view with the given name, or // error ErrUnknownView if a view with that name does not exist. func (g *Gui) ViewPosition(name string) (x0, y0, x1, y1 int, err error) { + g.Mutexes.ViewsMutex.Lock() + defer g.Mutexes.ViewsMutex.Unlock() + for _, v := range g.views { if v.name == name { return v.x0, v.y0, v.x1, v.y1, nil @@ -281,6 +307,9 @@ func (g *Gui) ViewPosition(name string) (x0, y0, x1, y1 int, err error) { // DeleteView deletes a view by name. func (g *Gui) DeleteView(name string) error { + g.Mutexes.ViewsMutex.Lock() + defer g.Mutexes.ViewsMutex.Unlock() + for i, v := range g.views { if v.name == name { g.views = append(g.views[:i], g.views[i+1:]...) @@ -292,6 +321,9 @@ func (g *Gui) DeleteView(name string) error { // SetCurrentView gives the focus to a given view. func (g *Gui) SetCurrentView(name string) (*View, error) { + g.Mutexes.ViewsMutex.Lock() + defer g.Mutexes.ViewsMutex.Unlock() + for _, v := range g.views { if v.name == name { g.currentView = v @@ -914,8 +946,8 @@ func (g *Gui) execKeybinding(v *View, kb *keybinding) (bool, error) { func (g *Gui) StartTicking() { go func() { - g.tickingMutex.Lock() - defer g.tickingMutex.Unlock() + g.Mutexes.tickingMutex.Lock() + defer g.Mutexes.tickingMutex.Unlock() ticker := time.NewTicker(time.Millisecond * 50) defer ticker.Stop() outer: diff --git a/vendor/modules.txt b/vendor/modules.txt index a1fd071be28..3379970e31c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -108,7 +108,7 @@ github.com/hashicorp/hcl/json/token github.com/integrii/flaggy # github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 github.com/jbenet/go-context/io -# github.com/jesseduffield/gocui v0.3.1-0.20200927010622-b998f1723844 +# github.com/jesseduffield/gocui v0.3.1-0.20200930205305-1b445b9bd5da ## explicit github.com/jesseduffield/gocui # github.com/jesseduffield/termbox-go v0.0.0-20200823212418-a2289ed6aafe