Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9f62f20d5 |
@@ -684,6 +684,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
lastPointerUpEvent: React.PointerEvent<HTMLElement> | PointerEvent | null =
|
lastPointerUpEvent: React.PointerEvent<HTMLElement> | PointerEvent | null =
|
||||||
null;
|
null;
|
||||||
lastPointerMoveEvent: PointerEvent | null = null;
|
lastPointerMoveEvent: PointerEvent | null = null;
|
||||||
|
_diagPointerMoveLogged = false;
|
||||||
/** current frame pointer cords */
|
/** current frame pointer cords */
|
||||||
lastPointerMoveCoords: { x: number; y: number } | null = null;
|
lastPointerMoveCoords: { x: number; y: number } | null = null;
|
||||||
/** previous frame pointer coords */
|
/** previous frame pointer coords */
|
||||||
@@ -3006,6 +3007,77 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
this.excalidrawContainerValue.container =
|
this.excalidrawContainerValue.container =
|
||||||
this.excalidrawContainerRef.current;
|
this.excalidrawContainerRef.current;
|
||||||
|
|
||||||
|
// [DIAG] Capture-phase listener to detect if pointerdown is intercepted
|
||||||
|
// before reaching our React handler. Patches stopPropagation/
|
||||||
|
// stopImmediatePropagation so we can detect if another listener kills
|
||||||
|
// the event before it reaches the canvas.
|
||||||
|
document.addEventListener(
|
||||||
|
"pointerdown",
|
||||||
|
(e) => {
|
||||||
|
const target = e.target as HTMLElement | null;
|
||||||
|
if (
|
||||||
|
target?.closest(".excalidraw") &&
|
||||||
|
(target.tagName === "CANVAS" || target.closest("canvas"))
|
||||||
|
) {
|
||||||
|
console.info(
|
||||||
|
"[DIAG] document capture pointerdown on canvas, tool:",
|
||||||
|
this.state.activeTool?.type,
|
||||||
|
{
|
||||||
|
defaultPrevented: e.defaultPrevented,
|
||||||
|
cancelable: e.cancelable,
|
||||||
|
isTrusted: e.isTrusted,
|
||||||
|
target: target.tagName,
|
||||||
|
pointerType: e.pointerType,
|
||||||
|
button: e.button,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Patch to detect stopPropagation/stopImmediatePropagation
|
||||||
|
const origStop = e.stopPropagation.bind(e);
|
||||||
|
const origStopImm = e.stopImmediatePropagation.bind(e);
|
||||||
|
const origPD = e.preventDefault.bind(e);
|
||||||
|
e.stopPropagation = () => {
|
||||||
|
console.warn(
|
||||||
|
"[DIAG] capture: pointerdown stopPropagation called!",
|
||||||
|
new Error().stack,
|
||||||
|
);
|
||||||
|
origStop();
|
||||||
|
};
|
||||||
|
e.stopImmediatePropagation = () => {
|
||||||
|
console.warn(
|
||||||
|
"[DIAG] capture: pointerdown stopImmediatePropagation called!",
|
||||||
|
new Error().stack,
|
||||||
|
);
|
||||||
|
origStopImm();
|
||||||
|
};
|
||||||
|
e.preventDefault = () => {
|
||||||
|
console.warn(
|
||||||
|
"[DIAG] capture: pointerdown preventDefault called!",
|
||||||
|
new Error().stack,
|
||||||
|
);
|
||||||
|
origPD();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true, // capture phase
|
||||||
|
);
|
||||||
|
// [DIAG] Bubble-phase listener to confirm event wasn't stopped
|
||||||
|
document.addEventListener(
|
||||||
|
"pointerdown",
|
||||||
|
(e) => {
|
||||||
|
const target = e.target as HTMLElement | null;
|
||||||
|
if (
|
||||||
|
target?.closest(".excalidraw") &&
|
||||||
|
(target.tagName === "CANVAS" || target.closest("canvas"))
|
||||||
|
) {
|
||||||
|
console.info(
|
||||||
|
"[DIAG] document bubble pointerdown reached (not stopped)",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false, // bubble phase
|
||||||
|
);
|
||||||
|
|
||||||
if (isTestEnv() || isDevEnv()) {
|
if (isTestEnv() || isDevEnv()) {
|
||||||
const setState = this.setState.bind(this);
|
const setState = this.setState.bind(this);
|
||||||
Object.defineProperties(window.h, {
|
Object.defineProperties(window.h, {
|
||||||
@@ -3500,8 +3572,14 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onTouchStart = (event: TouchEvent) => {
|
private onTouchStart = (event: TouchEvent) => {
|
||||||
|
console.info("[DIAG] touchStart", {
|
||||||
|
touches: event.touches.length,
|
||||||
|
defaultPrevented: event.defaultPrevented,
|
||||||
|
isIOS,
|
||||||
|
});
|
||||||
// fix for Apple Pencil Scribble (do not prevent for other devices)
|
// fix for Apple Pencil Scribble (do not prevent for other devices)
|
||||||
if (isIOS) {
|
if (isIOS) {
|
||||||
|
console.info("[DIAG] touchStart: calling preventDefault (isIOS)");
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6416,6 +6494,20 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
private handleCanvasPointerMove = (
|
private handleCanvasPointerMove = (
|
||||||
event: React.PointerEvent<HTMLCanvasElement>,
|
event: React.PointerEvent<HTMLCanvasElement>,
|
||||||
) => {
|
) => {
|
||||||
|
if (!this._diagPointerMoveLogged) {
|
||||||
|
console.info("[DIAG] pointerMove (first)", {
|
||||||
|
pointerType: event.pointerType,
|
||||||
|
isPanning,
|
||||||
|
isHoldingSpace,
|
||||||
|
viewModeEnabled: this.state.viewModeEnabled,
|
||||||
|
activeTool: this.state.activeTool.type,
|
||||||
|
cursorButton: this.state.cursorButton,
|
||||||
|
});
|
||||||
|
this._diagPointerMoveLogged = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this._diagPointerMoveLogged = false;
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
this.savePointer(event.clientX, event.clientY, this.state.cursorButton);
|
this.savePointer(event.clientX, event.clientY, this.state.cursorButton);
|
||||||
this.lastPointerMoveEvent = event.nativeEvent;
|
this.lastPointerMoveEvent = event.nativeEvent;
|
||||||
const scenePointer = viewportCoordsToSceneCoords(event, this.state);
|
const scenePointer = viewportCoordsToSceneCoords(event, this.state);
|
||||||
@@ -7196,6 +7288,56 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
private handleCanvasPointerDown = (
|
private handleCanvasPointerDown = (
|
||||||
event: React.PointerEvent<HTMLElement>,
|
event: React.PointerEvent<HTMLElement>,
|
||||||
) => {
|
) => {
|
||||||
|
console.info("[DIAG] pointerDown", {
|
||||||
|
pointerType: event.pointerType,
|
||||||
|
button: event.button,
|
||||||
|
isPanning,
|
||||||
|
isHoldingSpace,
|
||||||
|
viewModeEnabled: this.state.viewModeEnabled,
|
||||||
|
penMode: this.state.penMode,
|
||||||
|
activeTool: this.state.activeTool.type,
|
||||||
|
editingTextElement: !!this.state.editingTextElement,
|
||||||
|
openDialog: this.state.openDialog?.name ?? null,
|
||||||
|
gesturePointers: gesture.pointers.size,
|
||||||
|
newElement: this.state.newElement?.type ?? null,
|
||||||
|
target: (event.target as HTMLElement)?.tagName,
|
||||||
|
defaultPrevented: event.nativeEvent.defaultPrevented,
|
||||||
|
cancelable: event.nativeEvent.cancelable,
|
||||||
|
isTrusted: event.nativeEvent.isTrusted,
|
||||||
|
hasSetPointerCapture: "setPointerCapture" in HTMLElement.prototype,
|
||||||
|
composedPath: event.nativeEvent
|
||||||
|
.composedPath()
|
||||||
|
.slice(0, 3)
|
||||||
|
.map((el) => (el as HTMLElement).tagName || el.constructor?.name),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Patch nativeEvent to detect if something calls preventDefault/stopPropagation
|
||||||
|
const nativeEvt = event.nativeEvent;
|
||||||
|
const origPreventDefault = nativeEvt.preventDefault.bind(nativeEvt);
|
||||||
|
const origStopProp = nativeEvt.stopPropagation.bind(nativeEvt);
|
||||||
|
const origStopImmediate =
|
||||||
|
nativeEvt.stopImmediatePropagation.bind(nativeEvt);
|
||||||
|
nativeEvt.preventDefault = () => {
|
||||||
|
console.warn(
|
||||||
|
"[DIAG] pointerDown preventDefault called!",
|
||||||
|
new Error().stack,
|
||||||
|
);
|
||||||
|
origPreventDefault();
|
||||||
|
};
|
||||||
|
nativeEvt.stopPropagation = () => {
|
||||||
|
console.warn(
|
||||||
|
"[DIAG] pointerDown stopPropagation called!",
|
||||||
|
new Error().stack,
|
||||||
|
);
|
||||||
|
origStopProp();
|
||||||
|
};
|
||||||
|
nativeEvt.stopImmediatePropagation = () => {
|
||||||
|
console.warn(
|
||||||
|
"[DIAG] pointerDown stopImmediatePropagation called!",
|
||||||
|
new Error().stack,
|
||||||
|
);
|
||||||
|
origStopImmediate();
|
||||||
|
};
|
||||||
// If Ctrl is not held, ensure isBindingEnabled reflects the user preference.
|
// If Ctrl is not held, ensure isBindingEnabled reflects the user preference.
|
||||||
if (!event.ctrlKey) {
|
if (!event.ctrlKey) {
|
||||||
const preferenceEnabled = this.state.bindingPreference === "enabled";
|
const preferenceEnabled = this.state.bindingPreference === "enabled";
|
||||||
@@ -7330,6 +7472,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPanning) {
|
if (isPanning) {
|
||||||
|
console.info("[DIAG] pointerDown EXIT: isPanning");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7339,6 +7482,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
// else it will send pointer state & laser pointer events in collab when
|
// else it will send pointer state & laser pointer events in collab when
|
||||||
// panning
|
// panning
|
||||||
if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {
|
if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {
|
||||||
|
console.info("[DIAG] pointerDown EXIT: panUsingWheelOrSpaceDrag");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7403,11 +7547,16 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
event.button !== POINTER_BUTTON.TOUCH &&
|
event.button !== POINTER_BUTTON.TOUCH &&
|
||||||
event.button !== POINTER_BUTTON.ERASER
|
event.button !== POINTER_BUTTON.ERASER
|
||||||
) {
|
) {
|
||||||
|
console.info("[DIAG] pointerDown EXIT: unhandled button", event.button);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't select while panning
|
// don't select while panning
|
||||||
if (gesture.pointers.size > 1) {
|
if (gesture.pointers.size > 1) {
|
||||||
|
console.info(
|
||||||
|
"[DIAG] pointerDown EXIT: multi-pointer gesture",
|
||||||
|
gesture.pointers.size,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7420,12 +7569,16 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (this.handleDraggingScrollBar(event, pointerDownState)) {
|
if (this.handleDraggingScrollBar(event, pointerDownState)) {
|
||||||
|
console.info("[DIAG] pointerDown EXIT: dragging scrollbar");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clearSelectionIfNotUsingSelection();
|
this.clearSelectionIfNotUsingSelection();
|
||||||
|
|
||||||
if (this.handleSelectionOnPointerDown(event, pointerDownState)) {
|
if (this.handleSelectionOnPointerDown(event, pointerDownState)) {
|
||||||
|
console.info(
|
||||||
|
"[DIAG] pointerDown EXIT: handled by selectionOnPointerDown",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7438,6 +7591,11 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
this.state.activeTool.type === "image";
|
this.state.activeTool.type === "image";
|
||||||
|
|
||||||
if (!allowOnPointerDown) {
|
if (!allowOnPointerDown) {
|
||||||
|
console.info("[DIAG] pointerDown EXIT: penMode blocking touch", {
|
||||||
|
penMode: this.state.penMode,
|
||||||
|
pointerType: event.pointerType,
|
||||||
|
activeTool: this.state.activeTool.type,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7625,6 +7783,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!this.state.viewModeEnabled || this.state.activeTool.type === "laser") {
|
if (!this.state.viewModeEnabled || this.state.activeTool.type === "laser") {
|
||||||
|
console.info("[DIAG] pointerDown: registering move/up listeners");
|
||||||
window.addEventListener(EVENT.POINTER_MOVE, onPointerMove);
|
window.addEventListener(EVENT.POINTER_MOVE, onPointerMove);
|
||||||
window.addEventListener(EVENT.POINTER_UP, onPointerUp);
|
window.addEventListener(EVENT.POINTER_UP, onPointerUp);
|
||||||
window.addEventListener(EVENT.KEYDOWN, onKeyDown);
|
window.addEventListener(EVENT.KEYDOWN, onKeyDown);
|
||||||
@@ -7633,12 +7792,20 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
pointerDownState.eventListeners.onUp = onPointerUp;
|
pointerDownState.eventListeners.onUp = onPointerUp;
|
||||||
pointerDownState.eventListeners.onKeyUp = onKeyUp;
|
pointerDownState.eventListeners.onKeyUp = onKeyUp;
|
||||||
pointerDownState.eventListeners.onKeyDown = onKeyDown;
|
pointerDownState.eventListeners.onKeyDown = onKeyDown;
|
||||||
|
} else {
|
||||||
|
console.info(
|
||||||
|
"[DIAG] pointerDown: NOT registering listeners (viewMode + non-laser)",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private handleCanvasPointerUp = (
|
private handleCanvasPointerUp = (
|
||||||
event: React.PointerEvent<HTMLCanvasElement>,
|
event: React.PointerEvent<HTMLCanvasElement>,
|
||||||
) => {
|
) => {
|
||||||
|
console.info("[DIAG] pointerUp", {
|
||||||
|
pointerType: event.pointerType,
|
||||||
|
button: event.button,
|
||||||
|
});
|
||||||
if (getFeatureFlag("COMPLEX_BINDINGS")) {
|
if (getFeatureFlag("COMPLEX_BINDINGS")) {
|
||||||
this.resetDelayedBindMode();
|
this.resetDelayedBindMode();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user