From 0124962d8a9cdfa4d46a5e44e4d002468d0c2b85 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sat, 7 Mar 2026 19:55:40 +0100 Subject: [PATCH 1/2] Handle hyperlinks earlier, and tabs later This shouldn't make a difference right now, but it makes it possible to disable switching tabs when a modal panel is open, but still handle clicks on hyperlinks in inactive views behind the panel, which is useful. --- gui.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/gui.go b/gui.go index 45e1617..934471a 100644 --- a/gui.go +++ b/gui.go @@ -1329,19 +1329,6 @@ func (g *Gui) onKey(ev *GocuiEvent) error { if err != nil { break } - if v.Frame && my == v.y0 { - if len(v.Tabs) > 0 { - tabIndex := v.GetClickedTabIndex(mx - v.x0) - - if tabIndex >= 0 { - for _, binding := range g.tabClickBindings { - if binding.viewName == v.Name() { - return binding.handler(tabIndex) - } - } - } - } - } // newCx and newCy are relative to the view port, i.e. to the visible area of the view newCx := mx - v.x0 - 1 @@ -1368,6 +1355,15 @@ func (g *Gui) onKey(ev *GocuiEvent) error { newCx = visibleLineWidth - v.ox } } + + if ev.Key == MouseLeft && (ev.Mod&ModMotion) == 0 && !v.Editable && g.openHyperlink != nil { + if newY >= 0 && newY <= len(v.viewLines)-1 && newX >= 0 && newX <= len(v.viewLines[newY].line)-1 { + if link := v.viewLines[newY].line[newX].hyperlink; link != "" { + return g.openHyperlink(link, v.name) + } + } + } + if !IsMouseScrollKey(ev.Key) { v.SetCursor(newCx, newCy) if v.Editable { @@ -1381,10 +1377,16 @@ func (g *Gui) onKey(ev *GocuiEvent) error { } } - if ev.Key == MouseLeft && (ev.Mod&ModMotion) == 0 && !v.Editable && g.openHyperlink != nil { - if newY >= 0 && newY <= len(v.viewLines)-1 && newX >= 0 && newX <= len(v.viewLines[newY].line)-1 { - if link := v.viewLines[newY].line[newX].hyperlink; link != "" { - return g.openHyperlink(link, v.name) + if v.Frame && my == v.y0 { + if len(v.Tabs) > 0 { + tabIndex := v.GetClickedTabIndex(mx - v.x0) + + if tabIndex >= 0 { + for _, binding := range g.tabClickBindings { + if binding.viewName == v.Name() { + return binding.handler(tabIndex) + } + } } } } From 00c06c48f8e0c18253c7301f3894794db94f3eb1 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 22 Feb 2026 19:48:47 +0100 Subject: [PATCH 2/2] Add an optional ShouldHandleMouseEvent hook This allows clients to reject clicks, which can be useful for disabling background views while a modal panel is open. Doing this client-side in a keybinding handler would not be enough, because it would still set the cursor position in the clicked view, and it would still handle clicks on tab headers. --- gui.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gui.go b/gui.go index 934471a..96c622b 100644 --- a/gui.go +++ b/gui.go @@ -196,6 +196,8 @@ type Gui struct { ErrorHandler func(error) error + ShouldHandleMouseEvent func(view *View, key Key) bool + screen tcell.Screen suspendedMutex sync.Mutex suspended bool @@ -1364,6 +1366,14 @@ func (g *Gui) onKey(ev *GocuiEvent) error { } } + if g.ShouldHandleMouseEvent != nil { + if !g.ShouldHandleMouseEvent(v, ev.Key) { + // Give clients a chance to reject clicks, for example clicks in inactive views + // when a modal panel is open. + break + } + } + if !IsMouseScrollKey(ev.Key) { v.SetCursor(newCx, newCy) if v.Editable {