summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/terminal.go75
-rw-r--r--src/tui/light.go14
-rw-r--r--src/tui/tcell.go20
-rw-r--r--src/tui/tui.go36
4 files changed, 94 insertions, 51 deletions
diff --git a/src/terminal.go b/src/terminal.go
index 56b70e9b..5ff9f8de 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -4620,6 +4620,7 @@ func (t *Terminal) Loop() error {
pbarDragging := false
pborderDragging := -1
wasDown := false
+ pmx, pmy := -1, -1
needBarrier := true
// If an action is bound to 'start', we're going to process it before reading
@@ -5422,25 +5423,30 @@ func (t *Terminal) Loop() error {
case actMouse:
me := event.MouseEvent
mx, my := me.X, me.Y
- clicked := !wasDown && me.Down
+ click := !wasDown && me.Down
+ clicked := wasDown && !me.Down && (mx == pmx && my == pmy)
wasDown = me.Down
+ if click {
+ pmx, pmy = mx, my
+ }
if !me.Down {
barDragging = false
pbarDragging = false
pborderDragging = -1
previewDraggingPos = -1
+ pmx, pmy = -1, -1
}
// Scrolling
if me.S != 0 {
if t.window.Enclose(my, mx) && t.merger.Length() > 0 {
evt := tui.ScrollUp
- if me.Mod {
+ if me.Mod() {
evt = tui.SScrollUp
}
if me.S < 0 {
evt = tui.ScrollDown
- if me.Mod {
+ if me.Mod() {
evt = tui.SScrollDown
}
}
@@ -5456,7 +5462,7 @@ func (t *Terminal) Loop() error {
}
// Preview dragging
- if me.Down && (previewDraggingPos >= 0 || clicked && t.hasPreviewWindow() && t.pwindow.Enclose(my, mx)) {
+ if me.Down && (previewDraggingPos >= 0 || click && t.hasPreviewWindow() && t.pwindow.Enclose(my, mx)) {
if previewDraggingPos > 0 {
scrollPreviewBy(previewDraggingPos - my)
}
@@ -5466,7 +5472,7 @@ func (t *Terminal) Loop() error {
// Preview scrollbar dragging
headerLines := t.activePreviewOpts.headerLines
- pbarDragging = me.Down && (pbarDragging || clicked && t.hasPreviewWindow() && my >= t.pwindow.Top()+headerLines && my < t.pwindow.Top()+t.pwindow.Height() && mx == t.pwindow.Left()+t.pwindow.Width())
+ pbarDragging = me.Down && (pbarDragging || click && t.hasPreviewWindow() && my >= t.pwindow.Top()+headerLines && my < t.pwindow.Top()+t.pwindow.Height() && mx == t.pwindow.Left()+t.pwindow.Width())
if pbarDragging {
effectiveHeight := t.pwindow.Height() - headerLines
numLines := len(t.previewer.lines) - headerLines
@@ -5483,7 +5489,7 @@ func (t *Terminal) Loop() error {
}
// Preview border dragging (resizing)
- if pborderDragging < 0 && clicked && t.hasPreviewWindow() {
+ if pborderDragging < 0 && click && t.hasPreviewWindow() {
switch t.activePreviewOpts.position {
case posUp:
if t.pborder.Enclose(my, mx) && my == t.pborder.Top()+t.pborder.Height()-1 {
@@ -5564,9 +5570,7 @@ func (t *Terminal) Loop() error {
}
// Inside the header window
- // TODO: Should we trigger this on mouse up instead?
- // Should we still trigger it when the position has changed from the down event?
- if t.headerVisible && t.headerWindow != nil && t.headerWindow.Enclose(my, mx) {
+ if clicked && t.headerVisible && t.headerWindow != nil && t.headerWindow.Enclose(my, mx) {
mx -= t.headerWindow.Left() + t.headerIndent(t.headerBorderShape)
my -= t.headerWindow.Top()
if mx < 0 {
@@ -5580,7 +5584,7 @@ func (t *Terminal) Loop() error {
return doActions(actionsFor(tui.ClickHeader))
}
- if t.headerVisible && t.headerLinesWindow != nil && t.headerLinesWindow.Enclose(my, mx) {
+ if clicked && t.headerVisible && t.headerLinesWindow != nil && t.headerLinesWindow.Enclose(my, mx) {
mx -= t.headerLinesWindow.Left() + t.headerIndent(t.headerLinesShape)
my -= t.headerLinesWindow.Top()
if mx < 0 {
@@ -5616,7 +5620,7 @@ func (t *Terminal) Loop() error {
}
// Scrollbar dragging
- barDragging = me.Down && (barDragging || clicked && my >= min && mx == t.window.Width()-1)
+ barDragging = me.Down && (barDragging || click && my >= min && mx == t.window.Width()-1)
if barDragging {
barLength, barStart := t.getScrollbar()
if barLength > 0 {
@@ -5649,7 +5653,6 @@ func (t *Terminal) Loop() error {
return doActions(actionsFor(tui.DoubleClick))
}
}
- break
}
if me.Down {
@@ -5661,40 +5664,40 @@ func (t *Terminal) Loop() error {
t.vset(cy)
req(reqList)
evt := tui.RightClick
- if me.Mod {
+ if me.Mod() {
evt = tui.SRightClick
}
if me.Left {
evt = tui.LeftClick
- if me.Mod {
+ if me.Mod() {
evt = tui.SLeftClick
}
}
return doActions(actionsFor(evt))
- } else if t.headerVisible && t.headerWindow == nil {
- // Header
- // TODO: Should we trigger this on mouse up instead?
- numLines := t.visibleHeaderLinesInList()
- lineOffset := 0
- if t.inputWindow == nil && !t.headerFirst {
- // offset for info line
- if t.noSeparatorLine() {
- lineOffset = 1
- } else {
- lineOffset = 2
- }
+ }
+ }
+ if clicked && t.headerVisible && t.headerWindow == nil {
+ // Header
+ numLines := t.visibleHeaderLinesInList()
+ lineOffset := 0
+ if t.inputWindow == nil && !t.headerFirst {
+ // offset for info line
+ if t.noSeparatorLine() {
+ lineOffset = 1
+ } else {
+ lineOffset = 2
}
- my -= lineOffset
- mx -= t.pointerLen + t.markerLen
- if my >= 0 && my < numLines && mx >= 0 {
- if t.layout == layoutReverse {
- t.clickHeaderLine = my + 1
- } else {
- t.clickHeaderLine = numLines - my
- }
- t.clickHeaderColumn = mx + 1
- return doActions(actionsFor(tui.ClickHeader))
+ }
+ my -= lineOffset
+ mx -= t.pointerLen + t.markerLen
+ if my >= 0 && my < numLines && mx >= 0 {
+ if t.layout == layoutReverse {
+ t.clickHeaderLine = my + 1
+ } else {
+ t.clickHeaderLine = numLines - my
}
+ t.clickHeaderColumn = mx + 1
+ return doActions(actionsFor(tui.ClickHeader))
}
}
case actReload, actReloadSync:
diff --git a/src/tui/light.go b/src/tui/light.go
index 56e9ae0b..54c38c18 100644
--- a/src/tui/light.go
+++ b/src/tui/light.go
@@ -626,15 +626,13 @@ func (r *LightRenderer) mouseSequence(sz *int) Event {
// middle := t & 0b1
left := t&0b11 == 0
-
- // shift := t & 0b100
- // ctrl := t & 0b1000
- mod := t&0b1100 > 0
-
- drag := t&0b100000 > 0
+ ctrl := t&0b10000 > 0
+ alt := t&0b01000 > 0
+ shift := t&0b00100 > 0
+ drag := t&0b100000 > 0 // 32
if scroll != 0 {
- return Event{Mouse, 0, &MouseEvent{y, x, scroll, false, false, false, mod}}
+ return Event{Mouse, 0, &MouseEvent{y, x, scroll, false, false, false, ctrl, alt, shift}}
}
double := false
@@ -658,7 +656,7 @@ func (r *LightRenderer) mouseSequence(sz *int) Event {
}
}
}
- return Event{Mouse, 0, &MouseEvent{y, x, 0, left, down, double, mod}}
+ return Event{Mouse, 0, &MouseEvent{y, x, 0, left, down, double, ctrl, alt, shift}}
}
func (r *LightRenderer) smcup() {
diff --git a/src/tui/tcell.go b/src/tui/tcell.go
index 3c3e13fc..3738214a 100644
--- a/src/tui/tcell.go
+++ b/src/tui/tcell.go
@@ -266,7 +266,11 @@ func (r *FullscreenRenderer) GetChar() Event {
// so mouse click is three consecutive events, but the first and last are indistinguishable from movement events (with released buttons)
// dragging has same structure, it only repeats the middle (main) event appropriately
x, y := ev.Position()
- mod := ev.Modifiers() != 0
+
+ mod := ev.Modifiers()
+ ctrl := (mod & tcell.ModCtrl) > 0
+ alt := (mod & tcell.ModAlt) > 0
+ shift := (mod & tcell.ModShift) > 0
// since we dont have mouse down events (unlike LightRenderer), we need to track state in prevButton
prevButton, button := _prevMouseButton, ev.Buttons()
@@ -275,9 +279,9 @@ func (r *FullscreenRenderer) GetChar() Event {
switch {
case button&tcell.WheelDown != 0:
- return Event{Mouse, 0, &MouseEvent{y, x, -1, false, false, false, mod}}
+ return Event{Mouse, 0, &MouseEvent{y, x, -1, false, false, false, ctrl, alt, shift}}
case button&tcell.WheelUp != 0:
- return Event{Mouse, 0, &MouseEvent{y, x, +1, false, false, false, mod}}
+ return Event{Mouse, 0, &MouseEvent{y, x, +1, false, false, false, ctrl, alt, shift}}
case button&tcell.Button1 != 0:
double := false
if !drag {
@@ -300,9 +304,9 @@ func (r *FullscreenRenderer) GetChar() Event {
}
}
// fire single or double click event
- return Event{Mouse, 0, &MouseEvent{y, x, 0, true, !double, double, mod}}
+ return Event{Mouse, 0, &MouseEvent{y, x, 0, true, !double, double, ctrl, alt, shift}}
case button&tcell.Button2 != 0:
- return Event{Mouse, 0, &MouseEvent{y, x, 0, false, true, false, mod}}
+ return Event{Mouse, 0, &MouseEvent{y, x, 0, false, true, false, ctrl, alt, shift}}
default:
// double and single taps on Windows don't quite work due to
// the console acting on the events and not allowing us
@@ -311,7 +315,11 @@ func (r *FullscreenRenderer) GetChar() Event {
down := left || button&tcell.Button3 != 0
double := false
- return Event{Mouse, 0, &MouseEvent{y, x, 0, left, down, double, mod}}
+ // No need to report mouse movement events when no button is pressed
+ if drag {
+ return Event{Invalid, 0, nil}
+ }
+ return Event{Mouse, 0, &MouseEvent{y, x, 0, left, down, double, ctrl, alt, shift}}
}
// process keyboard:
diff --git a/src/tui/tui.go b/src/tui/tui.go
index eab5ad7e..fe8fc243 100644
--- a/src/tui/tui.go
+++ b/src/tui/tui.go
@@ -150,6 +150,10 @@ func (e Event) Comparable() Event {
}
func (e Event) KeyName() string {
+ if me := e.MouseEvent; me != nil {
+ return me.Name()
+ }
+
if e.Type >= Invalid {
return ""
}
@@ -367,7 +371,37 @@ type MouseEvent struct {
Left bool
Down bool
Double bool
- Mod bool
+ Ctrl bool
+ Alt bool
+ Shift bool
+}
+
+func (e MouseEvent) Mod() bool {
+ return e.Ctrl || e.Alt || e.Shift
+}
+
+func (e MouseEvent) Name() string {
+ name := ""
+ if e.Down {
+ return name
+ }
+
+ if e.Ctrl {
+ name += "ctrl-"
+ }
+ if e.Alt {
+ name += "alt-"
+ }
+ if e.Shift {
+ name += "shift-"
+ }
+ if e.Double {
+ name += "double-"
+ }
+ if !e.Left {
+ name += "right-"
+ }
+ return name + "click"
}
type BorderShape int