mirror of
https://github.com/anomalyco/opentui.git
synced 2026-09-19 01:26:03 +08:00
mouse: track buttons independently (#1416)
Keep left-button selection state until its own release so right-click interactions do not interrupt dragging.
This commit is contained in:
@@ -380,19 +380,12 @@ describe("MouseParser SGR mode", () => {
|
||||
expect(move.type).toBe("move")
|
||||
})
|
||||
|
||||
test("multiple buttons pressed — any motion is drag", () => {
|
||||
test("releasing one of multiple pressed buttons keeps motion dragging", () => {
|
||||
parser.parseMouseEvent(encodeSGR(0, 5, 5, true)) // left down
|
||||
parser.parseMouseEvent(encodeSGR(2, 5, 5, true)) // right down
|
||||
const e = parser.parseMouseEvent(encodeSGR(32, 8, 5, false))!
|
||||
expect(e.type).toBe("drag")
|
||||
})
|
||||
|
||||
test("release clears ALL tracked buttons", () => {
|
||||
parser.parseMouseEvent(encodeSGR(0, 5, 5, true)) // left down
|
||||
parser.parseMouseEvent(encodeSGR(2, 5, 5, true)) // right down
|
||||
parser.parseMouseEvent(encodeSGR(0, 5, 5, false)) // release (clears all)
|
||||
const e = parser.parseMouseEvent(encodeSGR(32, 8, 5, false))!
|
||||
expect(e.type).toBe("move") // no buttons tracked → move, not drag
|
||||
parser.parseMouseEvent(encodeSGR(2, 5, 5, false)) // right up
|
||||
const event = parser.parseMouseEvent(encodeSGR(32, 8, 5, false))!
|
||||
expect(event.type).toBe("drag")
|
||||
})
|
||||
|
||||
test("reset() clears button tracking state", () => {
|
||||
|
||||
@@ -175,7 +175,7 @@ export class MouseParser {
|
||||
if (type === "down" && button !== 3) {
|
||||
this.mouseButtonsPressed.add(button)
|
||||
} else if (type === "up") {
|
||||
this.mouseButtonsPressed.clear()
|
||||
this.mouseButtonsPressed.delete(button)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3630,7 +3630,7 @@ export class CliRenderer extends EventEmitter implements RenderContext {
|
||||
return true
|
||||
}
|
||||
|
||||
if (mouseEvent.type === "up" && this.currentSelection?.isDragging) {
|
||||
if (mouseEvent.type === "up" && mouseEvent.button === MouseButton.LEFT && this.currentSelection?.isDragging) {
|
||||
if (maybeRenderable) {
|
||||
const event = new MouseEvent(maybeRenderable, {
|
||||
...mouseEvent,
|
||||
@@ -3716,7 +3716,12 @@ export class CliRenderer extends EventEmitter implements RenderContext {
|
||||
this.lastOverRenderable = undefined
|
||||
}
|
||||
|
||||
if (!event?.defaultPrevented && mouseEvent.type === "down" && this.currentSelection) {
|
||||
if (
|
||||
!event?.defaultPrevented &&
|
||||
mouseEvent.type === "down" &&
|
||||
mouseEvent.button === MouseButton.LEFT &&
|
||||
this.currentSelection
|
||||
) {
|
||||
this.clearSelection()
|
||||
}
|
||||
|
||||
|
||||
@@ -343,7 +343,7 @@ describe("renderer handleMouseData", () => {
|
||||
}
|
||||
})
|
||||
|
||||
test("selection drag marks events as dragging and ends on mouse up", async () => {
|
||||
test("selection drag ignores right-button release and ends on left mouse up", async () => {
|
||||
try {
|
||||
const target = new TestRenderable(renderer, {
|
||||
id: "selectable",
|
||||
@@ -372,7 +372,11 @@ describe("renderer handleMouseData", () => {
|
||||
const endY = target.y + 3
|
||||
|
||||
await mockMouse.pressDown(startX, startY)
|
||||
await mockMouse.click(startX, startY, MouseButtons.RIGHT)
|
||||
expect(renderer.getSelection()?.isDragging).toBe(true)
|
||||
|
||||
await mockMouse.moveTo(endX, endY)
|
||||
expect(renderer.getSelection()?.focus).toEqual({ x: endX, y: endY })
|
||||
await mockMouse.release(endX, endY)
|
||||
|
||||
expect(renderer.hasSelection).toBe(true)
|
||||
|
||||
Reference in New Issue
Block a user