diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index 49f325c0c..91c91d704 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -96,7 +96,6 @@ import NodeSearchboxPopover from '@/components/searchbox/NodeSearchBoxPopover.vu import SideToolbar from '@/components/sidebar/SideToolbar.vue' import SecondRowWorkflowTabs from '@/components/topbar/SecondRowWorkflowTabs.vue' import { useChainCallback } from '@/composables/functional/useChainCallback' -import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions' import { useViewportCulling } from '@/composables/graph/useViewportCulling' import { useVueNodeLifecycle } from '@/composables/graph/useVueNodeLifecycle' import { useNodeBadge } from '@/composables/node/useNodeBadge' @@ -118,6 +117,7 @@ import { useWorkflowAutoSave } from '@/platform/workflow/persistence/composables import { useWorkflowPersistence } from '@/platform/workflow/persistence/composables/useWorkflowPersistence' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { SelectedNodeIdsKey } from '@/renderer/core/canvas/injectionKeys' +import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions' import TransformPane from '@/renderer/core/layout/transform/TransformPane.vue' import MiniMap from '@/renderer/extensions/minimap/MiniMap.vue' import VueGraphNode from '@/renderer/extensions/vueNodes/components/LGraphNode.vue' diff --git a/src/components/graph/GraphCanvasMenu.vue b/src/components/graph/GraphCanvasMenu.vue index d4ec414d6..c4050d30c 100644 --- a/src/components/graph/GraphCanvasMenu.vue +++ b/src/components/graph/GraphCanvasMenu.vue @@ -124,11 +124,11 @@ import ButtonGroup from 'primevue/buttongroup' import { computed, onBeforeUnmount, onMounted } from 'vue' import { useI18n } from 'vue-i18n' -import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions' import { useZoomControls } from '@/composables/useZoomControls' import { LiteGraph } from '@/lib/litegraph/src/litegraph' import { useSettingStore } from '@/platform/settings/settingStore' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' +import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions' import { useMinimap } from '@/renderer/extensions/minimap/composables/useMinimap' import { useCommandStore } from '@/stores/commandStore' import { useWorkspaceStore } from '@/stores/workspaceStore' diff --git a/src/components/graph/SelectionToolbox.spec.ts b/src/components/graph/SelectionToolbox.spec.ts index 7b78190e5..85acaf6cf 100644 --- a/src/components/graph/SelectionToolbox.spec.ts +++ b/src/components/graph/SelectionToolbox.spec.ts @@ -5,12 +5,12 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { createI18n } from 'vue-i18n' import SelectionToolbox from '@/components/graph/SelectionToolbox.vue' -import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' +import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions' import { useExtensionService } from '@/services/extensionService' // Mock the composables and services -vi.mock('@/composables/graph/useCanvasInteractions', () => ({ +vi.mock('@/renderer/core/canvas/useCanvasInteractions', () => ({ useCanvasInteractions: vi.fn(() => ({ handleWheel: vi.fn() })) diff --git a/src/components/graph/SelectionToolbox.vue b/src/components/graph/SelectionToolbox.vue index d87083d3d..067b04346 100644 --- a/src/components/graph/SelectionToolbox.vue +++ b/src/components/graph/SelectionToolbox.vue @@ -60,9 +60,9 @@ import MaskEditorButton from '@/components/graph/selectionToolbox/MaskEditorButt import RefreshSelectionButton from '@/components/graph/selectionToolbox/RefreshSelectionButton.vue' import PublishSubgraphButton from '@/components/graph/selectionToolbox/SaveToSubgraphLibrary.vue' import { useSelectionToolboxPosition } from '@/composables/canvas/useSelectionToolboxPosition' -import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions' import { useSelectionState } from '@/composables/graph/useSelectionState' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' +import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions' import { useMinimap } from '@/renderer/extensions/minimap/composables/useMinimap' import { useExtensionService } from '@/services/extensionService' import { type ComfyCommandImpl, useCommandStore } from '@/stores/commandStore' diff --git a/src/composables/node/useNodeImage.ts b/src/composables/node/useNodeImage.ts index 83600aec2..ad0a04178 100644 --- a/src/composables/node/useNodeImage.ts +++ b/src/composables/node/useNodeImage.ts @@ -1,5 +1,5 @@ -import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions' import type { LGraphNode } from '@/lib/litegraph/src/litegraph' +import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions' import { useNodeOutputStore } from '@/stores/imagePreviewStore' import { fitDimensionsToNodeWidth } from '@/utils/imageUtil' diff --git a/src/composables/graph/useCanvasInteractions.ts b/src/renderer/core/canvas/useCanvasInteractions.ts similarity index 87% rename from src/composables/graph/useCanvasInteractions.ts rename to src/renderer/core/canvas/useCanvasInteractions.ts index be807b771..cddc50d08 100644 --- a/src/composables/graph/useCanvasInteractions.ts +++ b/src/renderer/core/canvas/useCanvasInteractions.ts @@ -11,12 +11,21 @@ import { app } from '@/scripts/app' */ export function useCanvasInteractions() { const settingStore = useSettingStore() - const { getCanvas } = useCanvasStore() + const canvasStore = useCanvasStore() + const { getCanvas } = canvasStore const isStandardNavMode = computed( () => settingStore.get('Comfy.Canvas.NavigationMode') === 'standard' ) + /** + * Whether Vue node components should handle pointer events. + * Returns false when canvas is in read-only/panning mode (e.g., space key held for panning). + */ + const shouldHandleNodePointerEvents = computed( + () => !(canvasStore.canvas?.read_only ?? false) + ) + /** * Handles wheel events from UI components that should be forwarded to canvas * when appropriate (e.g., Ctrl+wheel for zoom in standard mode) @@ -97,6 +106,7 @@ export function useCanvasInteractions() { return { handleWheel, handlePointer, - forwardEventToCanvas + forwardEventToCanvas, + shouldHandleNodePointerEvents } } diff --git a/src/renderer/extensions/vueNodes/components/LGraphNode.vue b/src/renderer/extensions/vueNodes/components/LGraphNode.vue index 808c21ca1..5d67d0de7 100644 --- a/src/renderer/extensions/vueNodes/components/LGraphNode.vue +++ b/src/renderer/extensions/vueNodes/components/LGraphNode.vue @@ -10,7 +10,9 @@ 'bg-white dark-theme:bg-charcoal-800', 'lg-node absolute rounded-2xl', 'border border-solid border-sand-100 dark-theme:border-charcoal-600', - 'hover:ring-7 ring-gray-500/50 dark-theme:ring-gray-500/20', + // hover (only when node should handle events) + shouldHandleNodePointerEvents && + 'hover:ring-7 ring-gray-500/50 dark-theme:ring-gray-500/20', 'outline-transparent -outline-offset-2 outline-2', borderClass, outlineClass, @@ -21,7 +23,9 @@ 'will-change-transform': isDragging }, lodCssClass, - 'pointer-events-auto' + shouldHandleNodePointerEvents + ? 'pointer-events-auto' + : 'pointer-events-none' ) " :style="[ @@ -34,6 +38,7 @@ @pointerdown="handlePointerDown" @pointermove="handlePointerMove" @pointerup="handlePointerUp" + @wheel="handleWheel" >