fix Vue nodes capturing wheel event when Ctrl+Shift+drag zooming (#5791)

## Summary

Fixed canvas read-only state during Ctrl+Shift drag-to-zoom to prevent
node interaction conflicts. This fix also benefits Litegraph nodes.

## Changes

- **What**: Canvas becomes read-only during [Ctrl+Shift drag
zoom](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent)
operations and restores original state when finished
- **What**: Added browser test coverage for zoom interaction behavior

## Review Focus

State restoration on zoom interruption and edge cases where drag zoom is
cancelled mid-operation.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5791-fix-Vue-nodes-capturing-wheel-event-when-Ctrl-Shift-drag-zooming-27a6d73d3650817d888ee59f8f7fcb01)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Christian Byrne
2025-09-27 10:25:12 -07:00
committed by GitHub
parent 45f5ec15c2
commit 0ac1074a25
3 changed files with 51 additions and 4 deletions

View File

@@ -0,0 +1,33 @@
import {
comfyExpect as expect,
comfyPageFixture as test
} from '../../../fixtures/ComfyPage'
test.describe('Vue Nodes Zoom', () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.VueNodes.Enabled', true)
await comfyPage.vueNodes.waitForNodes()
})
test('should not capture drag while zooming with ctrl+shift+drag', async ({
comfyPage
}) => {
const checkpointNode = comfyPage.vueNodes.getNodeByTitle('Load Checkpoint')
const nodeBoundingBox = await checkpointNode.boundingBox()
if (!nodeBoundingBox) throw new Error('Node bounding box not available')
const nodeMidpointX = nodeBoundingBox.x + nodeBoundingBox.width / 2
const nodeMidpointY = nodeBoundingBox.y + nodeBoundingBox.height / 2
// Start the Ctrl+Shift drag-to-zoom on the canvas and continue dragging over
// the node. The node should not capture the drag while drag-zooming.
await comfyPage.page.keyboard.down('Control')
await comfyPage.page.keyboard.down('Shift')
await comfyPage.dragAndDrop(
{ x: 200, y: 300 },
{ x: nodeMidpointX, y: nodeMidpointY }
)
await expect(comfyPage.canvas).toHaveScreenshot('zoomed-in-ctrl-shift.png')
})
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -688,8 +688,8 @@ export class LGraphCanvas
/** If true, enable drag zoom. Ctrl+Shift+Drag Up/Down: zoom canvas. */
dragZoomEnabled: boolean = false
/** The start position of the drag zoom. */
#dragZoomStart: { pos: Point; scale: number } | null = null
/** The start position of the drag zoom and original read-only state. */
#dragZoomStart: { pos: Point; scale: number; readOnly: boolean } | null = null
getMenuOptions?(): IContextMenuValue<string>[]
getExtraMenuOptions?(
@@ -2188,7 +2188,12 @@ export class LGraphCanvas
!e.altKey &&
e.buttons
) {
this.#dragZoomStart = { pos: [e.x, e.y], scale: this.ds.scale }
this.#dragZoomStart = {
pos: [e.x, e.y],
scale: this.ds.scale,
readOnly: this.read_only
}
this.read_only = true
return
}
@@ -3125,7 +3130,7 @@ export class LGraphCanvas
#processDragZoom(e: PointerEvent): void {
// stop canvas zoom action
if (!e.buttons) {
this.#dragZoomStart = null
this.#finishDragZoom()
return
}
@@ -3143,6 +3148,13 @@ export class LGraphCanvas
this.graph.change()
}
#finishDragZoom(): void {
const start = this.#dragZoomStart
if (!start) return
this.#dragZoomStart = null
this.read_only = start.readOnly
}
/**
* Called when a mouse move event has to be processed
*/
@@ -3524,6 +3536,8 @@ export class LGraphCanvas
const { graph, pointer } = this
if (!graph) return
this.#finishDragZoom()
LGraphCanvas.active_canvas = this
this.adjustMouseEvent(e)