Skip to content

Commit ab76669

Browse files
[backport 1.25] Add automatic trackpad / mouse sensing (#4944)
Co-authored-by: filtered <[email protected]>
1 parent 08f834b commit ab76669

File tree

3 files changed

+71
-29
lines changed

3 files changed

+71
-29
lines changed

src/lib/litegraph/src/CanvasPointer.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ export class CanvasPointer {
4343
/** {@link maxClickDrift} squared. Used to calculate click drift without `sqrt`. */
4444
static #maxClickDrift2 = this.#maxClickDrift ** 2
4545

46+
/** Assume that "wheel" events with both deltaX and deltaY less than this value are trackpad gestures. */
47+
static trackpadThreshold = 60
48+
49+
/**
50+
* The minimum time between "wheel" events to allow switching between trackpad
51+
* and mouse modes.
52+
*
53+
* This prevents trackpad "flick" panning from registering as regular mouse wheel.
54+
* After a flick gesture is complete, the automatic wheel events are sent with
55+
* reduced frequency, but much higher deltaX and deltaY values.
56+
*/
57+
static trackpadMaxGap = 200
58+
4659
/** The element this PointerState should capture input against when dragging. */
4760
element: Element
4861
/** Pointer ID used by drag capture. */
@@ -77,6 +90,9 @@ export class CanvasPointer {
7790
/** The last pointerup event for the primary button */
7891
eUp?: CanvasPointerEvent
7992

93+
/** The last pointermove event that was treated as a trackpad gesture. */
94+
lastTrackpadEvent?: WheelEvent
95+
8096
/**
8197
* If set, as soon as the mouse moves outside the click drift threshold, this action is run once.
8298
* @param pointer [DEPRECATED] This parameter will be removed in a future release.
@@ -257,6 +273,35 @@ export class CanvasPointer {
257273
delete this.onDragStart
258274
}
259275

276+
/**
277+
* Checks if the given wheel event is part of a continued trackpad gesture.
278+
* @param e The wheel event to check
279+
* @returns `true` if the event is part of a continued trackpad gesture, otherwise `false`
280+
*/
281+
#isContinuationOfGesture(e: WheelEvent): boolean {
282+
const { lastTrackpadEvent } = this
283+
if (!lastTrackpadEvent) return false
284+
285+
return (
286+
e.timeStamp - lastTrackpadEvent.timeStamp < CanvasPointer.trackpadMaxGap
287+
)
288+
}
289+
290+
/**
291+
* Checks if the given wheel event is part of a trackpad gesture.
292+
* @param e The wheel event to check
293+
* @returns `true` if the event is part of a trackpad gesture, otherwise `false`
294+
*/
295+
isTrackpadGesture(e: WheelEvent): boolean {
296+
if (this.#isContinuationOfGesture(e)) {
297+
this.lastTrackpadEvent = e
298+
return true
299+
}
300+
301+
const threshold = CanvasPointer.trackpadThreshold
302+
return Math.abs(e.deltaX) < threshold && Math.abs(e.deltaY) < threshold
303+
}
304+
260305
/**
261306
* Resets the state of this {@link CanvasPointer} instance.
262307
*

src/lib/litegraph/src/LGraphCanvas.ts

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,46 +3455,41 @@ export class LGraphCanvas
34553455
processMouseWheel(e: WheelEvent): void {
34563456
if (!this.graph || !this.allow_dragcanvas) return
34573457

3458-
// TODO: Mouse wheel zoom rewrite
3459-
// @ts-expect-error wheelDeltaY is non-standard property on WheelEvent
3460-
const delta = e.wheelDeltaY ?? e.detail * -60
3461-
34623458
this.adjustMouseEvent(e)
34633459

34643460
const pos: Point = [e.clientX, e.clientY]
34653461
if (this.viewport && !isPointInRect(pos, this.viewport)) return
34663462

34673463
let { scale } = this.ds
34683464

3469-
if (
3470-
LiteGraph.canvasNavigationMode === 'legacy' ||
3471-
(LiteGraph.canvasNavigationMode === 'standard' && e.ctrlKey)
3472-
) {
3473-
if (delta > 0) {
3474-
scale *= this.zoom_speed
3475-
} else if (delta < 0) {
3476-
scale *= 1 / this.zoom_speed
3477-
}
3478-
this.ds.changeScale(scale, [e.clientX, e.clientY])
3479-
} else if (
3480-
LiteGraph.macTrackpadGestures &&
3481-
(!LiteGraph.macGesturesRequireMac || navigator.userAgent.includes('Mac'))
3482-
) {
3483-
if (e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey) {
3484-
if (e.deltaY > 0) {
3485-
scale *= 1 / this.zoom_speed
3486-
} else if (e.deltaY < 0) {
3465+
// Detect if this is a trackpad gesture or mouse wheel
3466+
const isTrackpad = this.pointer.isTrackpadGesture(e)
3467+
3468+
if (e.ctrlKey || LiteGraph.canvasNavigationMode === 'legacy') {
3469+
// Legacy mode or standard mode with ctrl - use wheel for zoom
3470+
if (isTrackpad) {
3471+
// Trackpad gesture - use smooth scaling
3472+
scale *= 1 + e.deltaY * (1 - this.zoom_speed) * 0.18
3473+
this.ds.changeScale(scale, [e.clientX, e.clientY], false)
3474+
} else {
3475+
// Mouse wheel - use stepped scaling
3476+
if (e.deltaY < 0) {
34873477
scale *= this.zoom_speed
3478+
} else if (e.deltaY > 0) {
3479+
scale *= 1 / this.zoom_speed
34883480
}
34893481
this.ds.changeScale(scale, [e.clientX, e.clientY])
3490-
} else if (e.ctrlKey) {
3491-
scale *= 1 + e.deltaY * (1 - this.zoom_speed) * 0.18
3492-
this.ds.changeScale(scale, [e.clientX, e.clientY], false)
3493-
} else if (e.shiftKey) {
3494-
this.ds.offset[0] -= e.deltaY * 1.18 * (1 / scale)
3482+
}
3483+
} else {
3484+
// Standard mode without ctrl - use wheel / gestures to pan
3485+
// Trackpads and mice work on significantly different scales
3486+
const factor = isTrackpad ? 0.18 : 0.008_333
3487+
3488+
if (!isTrackpad && e.shiftKey && e.deltaX === 0) {
3489+
this.ds.offset[0] -= e.deltaY * (1 + factor) * (1 / scale)
34953490
} else {
3496-
this.ds.offset[0] -= e.deltaX * 1.18 * (1 / scale)
3497-
this.ds.offset[1] -= e.deltaY * 1.18 * (1 / scale)
3491+
this.ds.offset[0] -= e.deltaX * (1 + factor) * (1 / scale)
3492+
this.ds.offset[1] -= e.deltaY * (1 + factor) * (1 / scale)
34983493
}
34993494
}
35003495

src/lib/litegraph/src/LiteGraphGlobal.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ export class LiteGraphGlobal {
284284
]
285285

286286
/**
287+
* @deprecated Removed; has no effect.
287288
* If `true`, mouse wheel events will be interpreted as trackpad gestures.
288289
* Tested on MacBook M4 Pro.
289290
* @default false
@@ -292,6 +293,7 @@ export class LiteGraphGlobal {
292293
macTrackpadGestures: boolean = false
293294

294295
/**
296+
* @deprecated Removed; has no effect.
295297
* If both this setting and {@link macTrackpadGestures} are `true`, trackpad gestures will
296298
* only be enabled when the browser user agent includes "Mac".
297299
* @default true

0 commit comments

Comments
 (0)