Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,33 @@ import { setActivePinia } from 'pinia'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { nextTick, ref } from 'vue'

import { useNodePointerInteractions } from '@/renderer/extensions/vueNodes/composables/useNodePointerInteractions'
import { useNodeEventHandlers } from '@/renderer/extensions/vueNodes/composables/useNodeEventHandlers'
import { createTestingPinia } from '@pinia/testing'

import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
import type { NodeLayout } from '@/renderer/core/layout/types'
import { useNodeEventHandlers } from '@/renderer/extensions/vueNodes/composables/useNodeEventHandlers'
import { useNodePointerInteractions } from '@/renderer/extensions/vueNodes/composables/useNodePointerInteractions'
import { useNodeDrag } from '@/renderer/extensions/vueNodes/layout/useNodeDrag'

const forwardEventToCanvasMock = vi.fn()
const selectedItemsState: { items: Array<{ id?: string }> } = { items: [] }

const mockCanvas = vi.hoisted(() => {
const canvasElement = document.createElement('canvas')
return {
canvas: canvasElement,
processKey: vi.fn()
}
})

vi.mock('@/scripts/app', () => ({
app: {
get canvas() {
return mockCanvas
}
}
}))

// Mock the dependencies
vi.mock('@/renderer/core/canvas/useCanvasInteractions', () => ({
useCanvasInteractions: () => ({
Expand Down Expand Up @@ -324,4 +341,42 @@ describe('useNodePointerInteractions', () => {
true
)
})

describe('keydown forwarding for spacebar panning', () => {
it('forwards keydown events to canvas.processKey when target is not the canvas', () => {
// Initialize the composable to set up keydown forwarding
useNodePointerInteractions('test-node-123')

// Create a div to simulate a Vue node element
const vueNodeElement = document.createElement('div')
document.body.appendChild(vueNodeElement)

// Dispatch keydown event on the Vue node element (not the canvas)
const keydownEvent = new KeyboardEvent('keydown', {
key: ' ',
bubbles: true
})
vueNodeElement.dispatchEvent(keydownEvent)

// Should forward to canvas.processKey
expect(mockCanvas.processKey).toHaveBeenCalledWith(keydownEvent)

document.body.removeChild(vueNodeElement)
})

it('does not forward keydown events when target is the canvas itself', () => {
useNodePointerInteractions('test-node-123')
mockCanvas.processKey.mockClear()

// Dispatch keydown event directly on the canvas element
const keydownEvent = new KeyboardEvent('keydown', {
key: ' ',
bubbles: true
})
mockCanvas.canvas.dispatchEvent(keydownEvent)

// Should NOT forward (canvas handles it directly)
expect(mockCanvas.processKey).not.toHaveBeenCalled()
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,34 @@ import { useVueNodeLifecycle } from '@/composables/graph/useVueNodeLifecycle'
import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions'
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
import { useNodeEventHandlers } from '@/renderer/extensions/vueNodes/composables/useNodeEventHandlers'
import { isMultiSelectKey } from '@/renderer/extensions/vueNodes/utils/selectionUtils'
import { useNodeDrag } from '@/renderer/extensions/vueNodes/layout/useNodeDrag'
import { isMultiSelectKey } from '@/renderer/extensions/vueNodes/utils/selectionUtils'
import { app } from '@/scripts/app'

// Forward keydown events to litegraph's processKey when Vue nodes have focus
let keydownForwardingInitialized = false

function initKeydownForwarding() {
if (keydownForwardingInitialized) return
keydownForwardingInitialized = true

document.addEventListener(
'keydown',
(e) => {
const canvas = app.canvas
if (!canvas) return
if (e.target === canvas.canvas) return
canvas.processKey(e)
},
true
)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
Comment thread
DrJKL marked this conversation as resolved.
Outdated

export function useNodePointerInteractions(
nodeIdRef: MaybeRefOrGetter<string>
) {
initKeydownForwarding()

const { startDrag, endDrag, handleDrag } = useNodeDrag()
// Use canvas interactions for proper wheel event handling and pointer event capture control
const { forwardEventToCanvas, shouldHandleNodePointerEvents } =
Expand Down Expand Up @@ -65,6 +87,12 @@ export function useNodePointerInteractions(
function onPointermove(event: PointerEvent) {
if (forwardMiddlePointerIfNeeded(event)) return

// Don't handle pointer events when canvas is in panning mode - forward to canvas instead
if (!shouldHandleNodePointerEvents.value) {
forwardEventToCanvas(event)
return
}

// Don't activate drag while resizing
if (layoutStore.isResizingVueNodes.value) return

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ export function useSlotLinkInteraction({
raf.cancel()
dragContext.dispose()
clearCompatible()
if (app.canvas?.pointer) {
app.canvas.pointer.isDown = false
}
}

const updatePointerState = (event: PointerEvent) => {
Expand Down Expand Up @@ -409,6 +412,12 @@ export function useSlotLinkInteraction({

const handlePointerMove = (event: PointerEvent) => {
if (!pointerSession.matches(event)) return

const canvas = app.canvas
if (canvas?.read_only && canvas.dragging_canvas) {
canvas.processMouseMove(event)
}

event.stopPropagation()

dragContext.pendingPointerMove = {
Expand Down Expand Up @@ -703,6 +712,10 @@ export function useSlotLinkInteraction({
)

pointerSession.begin(event.pointerId)
if (canvas.pointer) {
canvas.pointer.isDown = true
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like something that we should not be storing statefully. Can we derive the button state from the MouseEvent buttons instead?

canvas.last_mouse = [event.clientX, event.clientY]

toCanvasPointerEvent(event)
updatePointerState(event)
Expand Down
Loading