fix: rewrite glass drag to use pointer capture for reliable cursor reset
This commit is contained in:
@@ -114,11 +114,15 @@ export class UiManager {
|
||||
this.glassDiv.style.pointerEvents = 'auto';
|
||||
this.glassDiv.classList.add('drag-mode');
|
||||
|
||||
// Add drag handlers
|
||||
const onMouseDown = (e: MouseEvent) => {
|
||||
// Add drag handlers using pointer events + pointer capture for reliable tracking
|
||||
const onPointerDown = (e: PointerEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Capture pointer to this element — ensures all move/up events
|
||||
// are delivered here even if the pointer leaves the glass element
|
||||
this.glassDiv!.setPointerCapture(e.pointerId);
|
||||
|
||||
// Calculate the fixed offset between mouse and glass top-left
|
||||
// This maintains the "grab point" relative to the glass
|
||||
const rect = this.glassDiv!.getBoundingClientRect();
|
||||
@@ -135,12 +139,12 @@ export class UiManager {
|
||||
this.glassDiv!.style.transform = 'none'; // Clear any centering transforms if they exist
|
||||
|
||||
// Set body cursor so it persists even when dragging outside the glass div
|
||||
document.body.style.cursor = 'all-scroll';
|
||||
this.glassDiv!.style.cursor = 'grabbing';
|
||||
document.body.style.cursor = 'grabbing';
|
||||
document.body.style.userSelect = 'none';
|
||||
|
||||
const onMouseMove = (moveEvent: MouseEvent) => {
|
||||
const onPointerMove = (moveEvent: PointerEvent) => {
|
||||
moveEvent.preventDefault();
|
||||
moveEvent.stopPropagation();
|
||||
|
||||
// 1:1 Movement: Glass moves exactly with mouse
|
||||
// New Pos = Mouse Pos + Initial Grab Offset
|
||||
@@ -153,14 +157,22 @@ export class UiManager {
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseUp = (upEvent: MouseEvent) => {
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
const finishDrag = () => {
|
||||
this.glassDiv!.removeEventListener('pointermove', onPointerMove);
|
||||
this.glassDiv!.removeEventListener('pointerup', onPointerUp);
|
||||
this.glassDiv!.removeEventListener('pointercancel', onPointerUp);
|
||||
this.glassDiv!.removeEventListener('lostpointercapture', onPointerUp);
|
||||
|
||||
// Reset body cursor and user-select
|
||||
document.body.style.cursor = '';
|
||||
document.body.style.userSelect = '';
|
||||
|
||||
// Also reset the ComfyUI canvas cursor directly
|
||||
const canvas = document.querySelector('canvas.graph-canvas-container, #graph-canvas') as HTMLElement;
|
||||
if (canvas) {
|
||||
canvas.style.cursor = '';
|
||||
}
|
||||
|
||||
// Disable drag mode after drop
|
||||
this.state.isDragModeEnabled = false;
|
||||
this.setDragMode(false);
|
||||
@@ -172,24 +184,30 @@ export class UiManager {
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
const onPointerUp = (upEvent: PointerEvent) => {
|
||||
finishDrag();
|
||||
};
|
||||
|
||||
this.glassDiv!.addEventListener('pointermove', onPointerMove);
|
||||
this.glassDiv!.addEventListener('pointerup', onPointerUp);
|
||||
this.glassDiv!.addEventListener('pointercancel', onPointerUp);
|
||||
this.glassDiv!.addEventListener('lostpointercapture', onPointerUp);
|
||||
};
|
||||
|
||||
this.glassDiv.addEventListener('mousedown', onMouseDown);
|
||||
(this.glassDiv as any)._dragHandler = onMouseDown;
|
||||
this.glassDiv.addEventListener('pointerdown', onPointerDown);
|
||||
(this.glassDiv as any)._dragHandler = onPointerDown;
|
||||
} else {
|
||||
this.glassDiv.style.cursor = '';
|
||||
this.glassDiv.style.pointerEvents = 'none';
|
||||
this.glassDiv.classList.remove('drag-mode');
|
||||
|
||||
// Safety: ensure body cursor/userSelect are reset in case mouseup was missed
|
||||
// Safety: ensure body cursor/userSelect are reset in case pointerup was missed
|
||||
document.body.style.cursor = '';
|
||||
document.body.style.userSelect = '';
|
||||
|
||||
// Remove drag handler
|
||||
if ((this.glassDiv as any)._dragHandler) {
|
||||
this.glassDiv.removeEventListener('mousedown', (this.glassDiv as any)._dragHandler);
|
||||
this.glassDiv.removeEventListener('pointerdown', (this.glassDiv as any)._dragHandler);
|
||||
delete (this.glassDiv as any)._dragHandler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,9 +87,10 @@ class UiManager {
|
||||
this.glassDiv.style.cursor = "all-scroll";
|
||||
this.glassDiv.style.pointerEvents = "auto";
|
||||
this.glassDiv.classList.add("drag-mode");
|
||||
const onMouseDown = (e) => {
|
||||
const onPointerDown = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.glassDiv.setPointerCapture(e.pointerId);
|
||||
const rect = this.glassDiv.getBoundingClientRect();
|
||||
const grabOffsetX = rect.left - e.clientX;
|
||||
const grabOffsetY = rect.top - e.clientY;
|
||||
@@ -98,11 +99,11 @@ class UiManager {
|
||||
this.glassDiv.style.right = "auto";
|
||||
this.glassDiv.style.bottom = "auto";
|
||||
this.glassDiv.style.transform = "none";
|
||||
document.body.style.cursor = "all-scroll";
|
||||
this.glassDiv.style.cursor = "grabbing";
|
||||
document.body.style.cursor = "grabbing";
|
||||
document.body.style.userSelect = "none";
|
||||
const onMouseMove = (moveEvent) => {
|
||||
const onPointerMove = (moveEvent) => {
|
||||
moveEvent.preventDefault();
|
||||
moveEvent.stopPropagation();
|
||||
const newLeft = moveEvent.clientX + grabOffsetX;
|
||||
const newTop = moveEvent.clientY + grabOffsetY;
|
||||
if (this.glassDiv) {
|
||||
@@ -110,11 +111,17 @@ class UiManager {
|
||||
this.glassDiv.style.top = `${newTop}px`;
|
||||
}
|
||||
};
|
||||
const onMouseUp = (upEvent) => {
|
||||
document.removeEventListener("mousemove", onMouseMove);
|
||||
document.removeEventListener("mouseup", onMouseUp);
|
||||
const finishDrag = () => {
|
||||
this.glassDiv.removeEventListener("pointermove", onPointerMove);
|
||||
this.glassDiv.removeEventListener("pointerup", onPointerUp);
|
||||
this.glassDiv.removeEventListener("pointercancel", onPointerUp);
|
||||
this.glassDiv.removeEventListener("lostpointercapture", onPointerUp);
|
||||
document.body.style.cursor = "";
|
||||
document.body.style.userSelect = "";
|
||||
const canvas = document.querySelector("canvas.graph-canvas-container, #graph-canvas");
|
||||
if (canvas) {
|
||||
canvas.style.cursor = "";
|
||||
}
|
||||
this.state.isDragModeEnabled = false;
|
||||
this.setDragMode(false);
|
||||
const infoPanel = window.infoPanelManager;
|
||||
@@ -122,11 +129,16 @@ class UiManager {
|
||||
infoPanel.uiManager.updateControlStates();
|
||||
}
|
||||
};
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
const onPointerUp = (upEvent) => {
|
||||
finishDrag();
|
||||
};
|
||||
this.glassDiv.addEventListener("pointermove", onPointerMove);
|
||||
this.glassDiv.addEventListener("pointerup", onPointerUp);
|
||||
this.glassDiv.addEventListener("pointercancel", onPointerUp);
|
||||
this.glassDiv.addEventListener("lostpointercapture", onPointerUp);
|
||||
};
|
||||
this.glassDiv.addEventListener("mousedown", onMouseDown);
|
||||
this.glassDiv._dragHandler = onMouseDown;
|
||||
this.glassDiv.addEventListener("pointerdown", onPointerDown);
|
||||
this.glassDiv._dragHandler = onPointerDown;
|
||||
} else {
|
||||
this.glassDiv.style.cursor = "";
|
||||
this.glassDiv.style.pointerEvents = "none";
|
||||
@@ -134,7 +146,7 @@ class UiManager {
|
||||
document.body.style.cursor = "";
|
||||
document.body.style.userSelect = "";
|
||||
if (this.glassDiv._dragHandler) {
|
||||
this.glassDiv.removeEventListener("mousedown", this.glassDiv._dragHandler);
|
||||
this.glassDiv.removeEventListener("pointerdown", this.glassDiv._dragHandler);
|
||||
delete this.glassDiv._dragHandler;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user