From d8cc77c8b625c3f3fe7e6065015643d3fe5a1162 Mon Sep 17 00:00:00 2001
From: lindsay <lindsay.kay@xeolabs.com>
Date: Mon, 22 Apr 2024 19:51:22 +0200
Subject: [PATCH] [FIX] Ensure no interference between ContextMenus on
 measurements and Canvas #1461

---
 .../distance_createWithMouse_snapping.html    | 38 ++++++++++++++++---
 src/plugins/lib/html/Dot.js                   |  1 +
 src/plugins/lib/html/Label.js                 |  4 ++
 src/plugins/lib/html/Wire.js                  |  1 +
 4 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/examples/measurement/distance_createWithMouse_snapping.html b/examples/measurement/distance_createWithMouse_snapping.html
index 456d3b8fdb..71a8a6fe3d 100644
--- a/examples/measurement/distance_createWithMouse_snapping.html
+++ b/examples/measurement/distance_createWithMouse_snapping.html
@@ -134,7 +134,7 @@ <h3>Assets</h3>
     // Import the modules we need for this example
     //------------------------------------------------------------------------------------------------------------------
 
-    import {Viewer, XKTLoaderPlugin, ContextMenu, DistanceMeasurementsPlugin, DistanceMeasurementsMouseControl, PointerLens} from "../../dist/xeokit-sdk.min.es.js";
+    import {Viewer, XKTLoaderPlugin, ContextMenu, DistanceMeasurementsPlugin, DistanceMeasurementsMouseControl, PointerLens} from "../../dist/xeokit-sdk.es.js";
 
     //------------------------------------------------------------------------------------------------------------------
     // Create a Viewer and arrange the camera
@@ -282,10 +282,13 @@ <h3>Assets</h3>
         ]
     });
 
-    // viewer.cameraControl.on("rightClick", function (e) {
-    //     canvasContextMenu.show(e.pagePos[0], e.pagePos[1]);
-    //     e.event.preventDefault();
-    // });
+    viewer.scene.canvas.canvas.addEventListener('contextmenu', (event) => {
+       const canvasPos = getCanvasPosFromEvent(event);
+        console.log("canvas context menu")
+        canvasContextMenu.show(canvasPos[0], canvasPos[1]);
+        event.event.preventDefault();
+        event.event.stopPropagation();
+    });
 
     //------------------------------------------------------------------------------------------------------------------
     // Create an DistanceMeasurementsPlugin, activate its DistanceMeasuremntsControl
@@ -312,6 +315,31 @@ <h3>Assets</h3>
         e.event.preventDefault();
     });
 
+    const getCanvasPosFromEvent = function (event) {
+        const canvasPos = [];
+        if (!event) {
+            event = window.event;
+            canvasPos[0] = event.x;
+            canvasPos[1] = event.y;
+        } else {
+            let element = event.target;
+            let totalOffsetLeft = 0;
+            let totalOffsetTop = 0;
+            let totalScrollX = 0;
+            let totalScrollY = 0;
+            while (element.offsetParent) {
+                totalOffsetLeft += element.offsetLeft;
+                totalOffsetTop += element.offsetTop;
+                totalScrollX += element.scrollLeft;
+                totalScrollY += element.scrollTop;
+                element = element.offsetParent;
+            }
+            canvasPos[0] = event.pageX + totalScrollX - totalOffsetLeft;
+            canvasPos[1] = event.pageY + totalScrollY - totalOffsetTop;
+        }
+        return canvasPos;
+    };
+
     window.viewer = viewer;
 
 </script>
diff --git a/src/plugins/lib/html/Dot.js b/src/plugins/lib/html/Dot.js
index 5932ffd7e9..8ee93d941f 100644
--- a/src/plugins/lib/html/Dot.js
+++ b/src/plugins/lib/html/Dot.js
@@ -100,6 +100,7 @@ class Dot {
             dotClickable.addEventListener('contextmenu', (event) => {
                 cfg.onContextMenu(event, this);
                 event.preventDefault();
+                event.stopPropagation();
             });
         }
         
diff --git a/src/plugins/lib/html/Label.js b/src/plugins/lib/html/Label.js
index dc1c2aa0cb..d6a6479c69 100644
--- a/src/plugins/lib/html/Label.js
+++ b/src/plugins/lib/html/Label.js
@@ -66,12 +66,14 @@ class Label {
         if (cfg.onMouseDown) {
             label.addEventListener('mousedown', (event) => {
                 cfg.onMouseDown(event, this);
+                event.stopPropagation();
             });
         }
 
         if (cfg.onMouseUp) {
             label.addEventListener('mouseup', (event) => {
                 cfg.onMouseUp(event, this);
+                event.stopPropagation();
             });
         }
 
@@ -85,6 +87,8 @@ class Label {
             label.addEventListener('contextmenu', (event) => {
                 cfg.onContextMenu(event, this);
                 event.preventDefault();
+                event.stopPropagation();
+                console.log("Label context menu")
             });
         }
     }
diff --git a/src/plugins/lib/html/Wire.js b/src/plugins/lib/html/Wire.js
index 0c45546afd..4f4f991016 100644
--- a/src/plugins/lib/html/Wire.js
+++ b/src/plugins/lib/html/Wire.js
@@ -117,6 +117,7 @@ class Wire {
             wireClickable.addEventListener('contextmenu', (event) => {
                 cfg.onContextMenu(event, this);
                 event.preventDefault();
+                event.stopPropagation();
             });
         }