@@ -8,6 +8,8 @@ import { app } from '@/scripts/app'
88import { type ComfyWidgetConstructorV2 } from '@/scripts/widgets'
99import { useSettingStore } from '@/stores/settingStore'
1010
11+ const TRACKPAD_DETECTION_THRESHOLD = 50
12+
1113function addMultilineWidget (
1214 node : LGraphNode ,
1315 name : string ,
@@ -54,38 +56,55 @@ function addMultilineWidget(
5456 }
5557 } )
5658
57- /** Timer reference. `null` when the timer completes. */
58- let ignoreEventsTimer : ReturnType < typeof setTimeout > | null = null
59- /** Total number of events ignored since the timer started. */
60- let ignoredEvents = 0
61-
62- // Pass wheel events to the canvas when appropriate
6359 inputEl . addEventListener ( 'wheel' , ( event : WheelEvent ) => {
64- if ( ! Object . is ( event . deltaX , - 0 ) ) return
65-
66- // If the textarea has focus, require more effort to activate pass-through
67- const multiplier = document . activeElement === inputEl ? 2 : 1
68- const maxScrollHeight = inputEl . scrollHeight - inputEl . clientHeight
69-
70- if (
71- ( event . deltaY < 0 && inputEl . scrollTop === 0 ) ||
72- ( event . deltaY > 0 && inputEl . scrollTop === maxScrollHeight )
73- ) {
74- // Attempting to scroll past the end of the textarea
75- if ( ! ignoreEventsTimer || ignoredEvents > 25 * multiplier ) {
76- app . canvas . processMouseWheel ( event )
77- } else {
78- ignoredEvents ++
79- }
80- } else if ( event . deltaY !== 0 ) {
81- // Start timer whenever a successful scroll occurs
82- ignoredEvents = 0
83- if ( ignoreEventsTimer ) clearTimeout ( ignoreEventsTimer )
84-
85- ignoreEventsTimer = setTimeout ( ( ) => {
86- ignoreEventsTimer = null
87- } , 800 * multiplier )
60+ const gesturesEnabled = useSettingStore ( ) . get (
61+ 'LiteGraph.Pointer.TrackpadGestures'
62+ )
63+ const deltaX = event . deltaX
64+ const deltaY = event . deltaY
65+
66+ const canScrollY = inputEl . scrollHeight > inputEl . clientHeight
67+ const isHorizontal = Math . abs ( deltaX ) > Math . abs ( deltaY )
68+
69+ // Prevent pinch zoom from zooming the page
70+ if ( event . ctrlKey ) {
71+ event . preventDefault ( )
72+ event . stopPropagation ( )
73+ app . canvas . processMouseWheel ( event )
74+ return
8875 }
76+
77+ // Detect if this is likely a trackpad gesture vs mouse wheel
78+ // Trackpads usually have deltaX or smaller deltaY values (< TRACKPAD_DETECTION_THRESHOLD)
79+ // Mouse wheels typically have larger discrete deltaY values (>= TRACKPAD_DETECTION_THRESHOLD)
80+ const isLikelyTrackpad =
81+ Math . abs ( deltaX ) > 0 || Math . abs ( deltaY ) < TRACKPAD_DETECTION_THRESHOLD
82+
83+ // Trackpad gestures: when enabled, trackpad panning goes to canvas
84+ if ( gesturesEnabled && isLikelyTrackpad ) {
85+ event . preventDefault ( )
86+ event . stopPropagation ( )
87+ app . canvas . processMouseWheel ( event )
88+ return
89+ }
90+
91+ // When gestures disabled: horizontal always goes to canvas (no horizontal scroll in textarea)
92+ if ( isHorizontal ) {
93+ event . preventDefault ( )
94+ event . stopPropagation ( )
95+ app . canvas . processMouseWheel ( event )
96+ return
97+ }
98+
99+ // Vertical scrolling when gestures disabled: let textarea scroll if scrollable
100+ if ( canScrollY ) {
101+ event . stopPropagation ( )
102+ return
103+ }
104+
105+ // If textarea can't scroll vertically, pass to canvas
106+ event . preventDefault ( )
107+ app . canvas . processMouseWheel ( event )
89108 } )
90109
91110 return widget
0 commit comments