From e5093892fd92c0721dad1e7f0c8d135f1f09e0b6 Mon Sep 17 00:00:00 2001 From: Dmitry Maluka Date: Sat, 5 Nov 2022 11:41:04 +0100 Subject: [PATCH] Reset mouse release state after restarting the screen When we temporarily disable the screen (e.g. during TermMessage or RunInteractiveShell), if the mouse is pressed when the screen is still active and then released when the screen is already stopped, we aren't able to catch this mouse release event, so we erroneously think that the mouse is still pressed after the screen is restarted. This results in wrong behavior due to a mouse press event treated as a mouse move event, e.g. upon the left button click we see an unexpected text selection. So need to reset the mouse release state to "released" after restarting the screen, assuming it is always released when the screen is restarted. --- internal/action/bufpane.go | 10 +++++++--- internal/action/tab.go | 15 +++++++++++++++ internal/screen/screen.go | 8 ++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/internal/action/bufpane.go b/internal/action/bufpane.go index f40efa7e..9cb3808b 100644 --- a/internal/action/bufpane.go +++ b/internal/action/bufpane.go @@ -325,6 +325,12 @@ func (h *BufPane) PluginCBRune(cb string, r rune) bool { return b } +func (h *BufPane) resetMouse() { + for me := range h.mousePressed { + delete(h.mousePressed, me) + } +} + // OpenBuffer opens the given buffer in this pane. func (h *BufPane) OpenBuffer(b *buffer.Buffer) { h.Buf.Close() @@ -335,9 +341,7 @@ func (h *BufPane) OpenBuffer(b *buffer.Buffer) { h.initialRelocate() // Set mouseReleased to true because we assume the mouse is not being // pressed when the editor is opened - for me := range h.mousePressed { - delete(h.mousePressed, me) - } + h.resetMouse() // Set isOverwriteMode to false, because we assume we are in the default // mode when editor is opened h.isOverwriteMode = false diff --git a/internal/action/tab.go b/internal/action/tab.go index 07a866ce..0967df3a 100644 --- a/internal/action/tab.go +++ b/internal/action/tab.go @@ -161,6 +161,21 @@ func InitTabs(bufs []*buffer.Buffer) { } } } + + screen.RestartCallback = func() { + // The mouse could be released after the screen was stopped, so that + // we couldn't catch the mouse release event and would erroneously think + // that it is still pressed. So need to reset the mouse release state + // after the screen is restarted. + for _, t := range Tabs.List { + t.release = true + for _, p := range t.Panes { + if bp, ok := p.(*BufPane); ok { + bp.resetMouse() + } + } + } + } } func MainTab() *Tab { diff --git a/internal/screen/screen.go b/internal/screen/screen.go index 339e69aa..16c011e6 100644 --- a/internal/screen/screen.go +++ b/internal/screen/screen.go @@ -22,6 +22,10 @@ var Screen tcell.Screen // Events is the channel of tcell events var Events chan (tcell.Event) +// RestartCallback is called when the screen is restarted after it was +// temporarily shut down +var RestartCallback func() + // The lock is necessary since the screen is polled on a separate thread var lock sync.Mutex @@ -134,6 +138,10 @@ func TempStart(screenWasNil bool) { if !screenWasNil { Init() Unlock() + + if RestartCallback != nil { + RestartCallback() + } } }