From 28a779d41aba0b89abc806f634362fb5f6238412 Mon Sep 17 00:00:00 2001 From: Terry Jia Date: Mon, 29 Sep 2025 22:51:37 -0400 Subject: [PATCH] Check if the wheel event is from an element that wants to capture wheel events (#5821) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Add generic wheel event capture mechanism for interactive widgets in vueNodes system to prevent event bubbling to canvas. ## Changes - What: Add event handling logic in LGraphNode.vue and GraphCanvas.vue that checks for data-capture-wheel attribute to determine whether wheel events should be forwarded to the canvas - How it works: Components that need to capture wheel events (like Three.js scenes) can add data-capture-wheel="true" attribute to prevent wheel events from bubbling up to the canvas zoom handler prerequirist for https://github.com/Comfy-Org/ComfyUI_frontend/pull/5765 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5821-Check-if-the-wheel-event-is-from-an-element-that-wants-to-capture-wheel-events-27b6d73d3650812493b5f13849147e6c) by [Unito](https://www.unito.io) --- .../core/canvas/useCanvasInteractions.ts | 18 ++++++++++++++++++ .../widgets/components/WidgetMarkdown.vue | 1 + .../widgets/components/WidgetSelectDefault.vue | 1 + .../widgets/components/WidgetTextarea.vue | 1 + 4 files changed, 21 insertions(+) diff --git a/src/renderer/core/canvas/useCanvasInteractions.ts b/src/renderer/core/canvas/useCanvasInteractions.ts index a32d5e864..46ce4ae46 100644 --- a/src/renderer/core/canvas/useCanvasInteractions.ts +++ b/src/renderer/core/canvas/useCanvasInteractions.ts @@ -30,6 +30,15 @@ export function useCanvasInteractions() { * when appropriate (e.g., Ctrl+wheel for zoom in standard mode) */ const handleWheel = (event: WheelEvent) => { + // Check if the wheel event is from an element that wants to capture wheel events + const target = event.target as HTMLElement + const captureElement = target?.closest('[data-capture-wheel="true"]') + + if (captureElement) { + // Element wants to capture wheel events, don't forward to canvas + return + } + // In standard mode, Ctrl+wheel should go to canvas for zoom if (isStandardNavMode.value && (event.ctrlKey || event.metaKey)) { forwardEventToCanvas(event) @@ -72,6 +81,15 @@ export function useCanvasInteractions() { const forwardEventToCanvas = ( event: WheelEvent | PointerEvent | MouseEvent ) => { + // Check if the wheel event is from an element that wants to capture wheel events + const target = event.target as HTMLElement + const captureElement = target?.closest('[data-capture-wheel="true"]') + + if (captureElement) { + // Element wants to capture wheel events, don't forward to canvas + return + } + const canvasEl = app.canvas?.canvas if (!canvasEl) return event.preventDefault() diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue index 7f3995f9e..3ffe47102 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue @@ -23,6 +23,7 @@ onBlur: handleBlur } }" + data-capture-wheel="true" @update:model-value="onChange" @click.stop @keydown.stop diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue index 4ac007669..4242c13ae 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue @@ -10,6 +10,7 @@ :pt="{ option: 'text-xs' }" + data-capture-wheel="true" @update:model-value="onChange" /> diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue index bd7ac7818..a2ec58de6 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue @@ -8,6 +8,7 @@ :placeholder="placeholder || widget.name || ''" size="small" rows="3" + data-capture-wheel="true" @update:model-value="onChange" />