mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-24 10:13:41 -05:00
Preserve the first mouse movement of a drag
When the left button is pressed and the pointer then moves, the event that made the MAYBE_DRAGGING -> DRAGGING transition fell through the switch without being assigned a key or modifier, so the first cell of every drag arrived at handlers as a MouseRelease event without the motion modifier and was effectively lost. Give it the same MouseLeft/ModMotion identity as all subsequent drag events. Held-button motion events that stay within the pressed cell carry no information at all; swallow them instead of letting them through as further release-shaped events (which used to clobber the double-click state when the pointer jittered within a cell between two clicks).
This commit is contained in:
@@ -366,7 +366,9 @@ func gocuiEventFromTcellEvent(tev tcell.Event) GocuiEvent {
|
||||
|
||||
// process button events (not wheel events)
|
||||
button &= tcell.ButtonMask(0xff)
|
||||
newButtonPress := false
|
||||
if button != tcell.ButtonNone && lastMouseKey == tcell.ButtonNone {
|
||||
newButtonPress = true
|
||||
lastMouseKey = button
|
||||
lastMouseMod = tev.Modifiers()
|
||||
switch button {
|
||||
@@ -410,9 +412,23 @@ func gocuiEventFromTcellEvent(tev tcell.Event) GocuiEvent {
|
||||
}
|
||||
// if we haven't released the left mouse button and we've moved the cursor then we're dragging
|
||||
case MAYBE_DRAGGING:
|
||||
if x != lastX || y != lastY {
|
||||
dragState = DRAGGING
|
||||
if x == lastX && y == lastY {
|
||||
// Deliver the button press itself, but swallow held-button
|
||||
// motion events within the same cell: they carry no new
|
||||
// information, and if they fell through they would be
|
||||
// delivered with the default MouseRelease key.
|
||||
if !newButtonPress {
|
||||
return GocuiEvent{Type: eventNone}
|
||||
}
|
||||
break
|
||||
}
|
||||
// The first movement is already part of the drag; give it the
|
||||
// same key and modifier as the DRAGGING events below so it
|
||||
// reaches drag bindings instead of being delivered with the
|
||||
// default MouseRelease key.
|
||||
dragState = DRAGGING
|
||||
mouseMod = ModMotion
|
||||
mouseKey = MouseLeft
|
||||
case DRAGGING:
|
||||
mouseMod = ModMotion
|
||||
mouseKey = MouseLeft
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package gocui
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gdamore/tcell/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFirstMouseMovementAfterPressIsDragEvent(t *testing.T) {
|
||||
t.Cleanup(resetMouseState)
|
||||
resetMouseState()
|
||||
|
||||
pressEvent := gocuiEventFromTcellEvent(tcell.NewEventMouse(1, 2, tcell.ButtonPrimary, tcell.ModNone))
|
||||
unchangedHeldEvent := gocuiEventFromTcellEvent(tcell.NewEventMouse(1, 2, tcell.ButtonPrimary, tcell.ModNone))
|
||||
dragEvent := gocuiEventFromTcellEvent(tcell.NewEventMouse(1, 3, tcell.ButtonPrimary, tcell.ModNone))
|
||||
|
||||
assert.Equal(t, eventMouse, pressEvent.Type)
|
||||
assert.Equal(t, MouseLeft, pressEvent.Key.KeyName())
|
||||
assert.Equal(t, ModNone, pressEvent.Key.Mod())
|
||||
assert.Equal(t, eventNone, unchangedHeldEvent.Type)
|
||||
assert.Equal(t, eventMouse, dragEvent.Type)
|
||||
assert.Equal(t, MouseLeft, dragEvent.Key.KeyName())
|
||||
assert.Equal(t, ModMotion, dragEvent.Key.Mod())
|
||||
}
|
||||
|
||||
func resetMouseState() {
|
||||
lastMouseKey = tcell.ButtonNone
|
||||
lastMouseMod = tcell.ModNone
|
||||
dragState = NOT_DRAGGING
|
||||
lastX = 0
|
||||
lastY = 0
|
||||
}
|
||||
Reference in New Issue
Block a user