diff --git a/web/static/main.js b/web/static/main.js index 715dd4b..68dd8a0 100644 --- a/web/static/main.js +++ b/web/static/main.js @@ -458,12 +458,13 @@ let rubberStart = /** @type {{x:number,y:number}|null} */ (null); function onCanvasPointerDown(e) { if (!state.active) return; - // Ignore clicks that started on a device/frame — their own handlers - // captured the pointer already. - if (e.target instanceof Element && e.target.closest("[data-device-id], [data-frame-id]")) return; const p = svgPoint(e); + // Armed tool wins: a click anywhere on the canvas — including on top + // of an existing frame or device — fires the tool. The +Dev tool needs + // this so m can drop a device inside a frame; without it the frame's + // own pointerdown handler would steal the click and start a drag. if (state.tool === "frame") { startFrameRubberBand(e, p); return; @@ -472,6 +473,11 @@ function onCanvasPointerDown(e) { placeDeviceAt(p); return; } + + // No tool armed: clicks that started on a device/frame go to their + // own handlers (drag / select). Leave them alone. + if (e.target instanceof Element && e.target.closest("[data-device-id], [data-frame-id]")) return; + // Plain canvas click = clear selection. if (state.selection) { state.selection = null; render(); } }