0032609: Visualization, Wasm_Window - handle mouse movements outside canvas element
authorkgv <kgv@opencascade.com>
Wed, 6 Oct 2021 20:55:43 +0000 (23:55 +0300)
committersmoskvin <smoskvin@opencascade.com>
Fri, 8 Oct 2021 17:26:22 +0000 (20:26 +0300)
Wasm_Window::ProcessMouseEvent() - removed redundant check on EMSCRIPTEN_EVENT_MOUSEUP event.
ViewerTest and WebGL sample - mouse movements are now tracked on window element
to allow tracking updates when mouse with clicked button is moved outside canvas element.

samples/webgl/WasmOcctView.cpp
src/ViewerTest/ViewerTest_EventManager.cxx
src/Wasm/Wasm_Window.cxx

index 65efdd3..e47f395 100644 (file)
@@ -185,12 +185,16 @@ void WasmOcctView::initWindow()
   emscripten_set_resize_callback     (EMSCRIPTEN_EVENT_TARGET_WINDOW, this, toUseCapture, onResizeCallback);
 
   emscripten_set_mousedown_callback  (aTargetId, this, toUseCapture, onMouseCallback);
-  emscripten_set_mouseup_callback    (aTargetId, this, toUseCapture, onMouseCallback);
-  emscripten_set_mousemove_callback  (aTargetId, this, toUseCapture, onMouseCallback);
+  // bind these events to window to track mouse movements outside of canvas
+  //emscripten_set_mouseup_callback    (aTargetId, this, toUseCapture, onMouseCallback);
+  //emscripten_set_mousemove_callback  (aTargetId, this, toUseCapture, onMouseCallback);
+  //emscripten_set_mouseleave_callback (aTargetId, this, toUseCapture, onMouseCallback);
+  emscripten_set_mouseup_callback    (EMSCRIPTEN_EVENT_TARGET_WINDOW, this, toUseCapture, onMouseCallback);
+  emscripten_set_mousemove_callback  (EMSCRIPTEN_EVENT_TARGET_WINDOW, this, toUseCapture, onMouseCallback);
+
   emscripten_set_dblclick_callback   (aTargetId, this, toUseCapture, onMouseCallback);
   emscripten_set_click_callback      (aTargetId, this, toUseCapture, onMouseCallback);
   emscripten_set_mouseenter_callback (aTargetId, this, toUseCapture, onMouseCallback);
-  emscripten_set_mouseleave_callback (aTargetId, this, toUseCapture, onMouseCallback);
   emscripten_set_wheel_callback      (aTargetId, this, toUseCapture, onWheelCallback);
 
   emscripten_set_touchstart_callback (aTargetId, this, toUseCapture, onTouchCallback);
@@ -474,6 +478,21 @@ EM_BOOL WasmOcctView::onResizeEvent (int theEventType, const EmscriptenUiEvent*
   return EM_TRUE;
 }
 
+//! Update canvas bounding rectangle.
+EM_JS(void, jsUpdateBoundingClientRect, (), {
+  Module._myCanvasRect = Module.canvas.getBoundingClientRect();
+});
+
+//! Get canvas bounding top.
+EM_JS(int, jsGetBoundingClientTop, (), {
+  return Math.round(Module._myCanvasRect.top);
+});
+
+//! Get canvas bounding left.
+EM_JS(int, jsGetBoundingClientLeft, (), {
+  return Math.round(Module._myCanvasRect.left);
+});
+
 // ================================================================
 // Function : onMouseEvent
 // Purpose  :
@@ -486,6 +505,17 @@ EM_BOOL WasmOcctView::onMouseEvent (int theEventType, const EmscriptenMouseEvent
   }
 
   Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (myView->Window());
+  if (theEventType == EMSCRIPTEN_EVENT_MOUSEMOVE
+   || theEventType == EMSCRIPTEN_EVENT_MOUSEUP)
+  {
+    // these events are bound to EMSCRIPTEN_EVENT_TARGET_WINDOW, and coordinates should be converted
+    jsUpdateBoundingClientRect();
+    EmscriptenMouseEvent anEvent = *theEvent;
+    anEvent.targetX -= jsGetBoundingClientLeft();
+    anEvent.targetY -= jsGetBoundingClientTop();
+    return aWindow->ProcessMouseEvent (*this, theEventType, &anEvent) ? EM_TRUE : EM_FALSE;
+  }
+
   return aWindow->ProcessMouseEvent (*this, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
 }
 
index e22e729..7ae3a25 100644 (file)
@@ -624,6 +624,21 @@ static EM_BOOL onResizeCallback (int theEventType, const EmscriptenUiEvent* theE
   return EM_FALSE;
 }
 
+//! Update canvas bounding rectangle.
+EM_JS(void, occJSUpdateBoundingClientRect, (), {
+  Module._myCanvasRect = Module.canvas.getBoundingClientRect();
+});
+
+//! Get canvas bounding top.
+EM_JS(int, occJSGetBoundingClientTop, (), {
+  return Math.round(Module._myCanvasRect.top);
+});
+
+//! Get canvas bounding left.
+EM_JS(int, occJSGetBoundingClientLeft, (), {
+  return Math.round(Module._myCanvasRect.left);
+});
+
 //! Handle mouse input event.
 static EM_BOOL onWasmMouseCallback (int theEventType, const EmscriptenMouseEvent* theEvent, void* )
 {
@@ -632,6 +647,17 @@ static EM_BOOL onWasmMouseCallback (int theEventType, const EmscriptenMouseEvent
    && !ViewerTest::CurrentView().IsNull())
   {
     Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window());
+    if (theEventType == EMSCRIPTEN_EVENT_MOUSEMOVE
+     || theEventType == EMSCRIPTEN_EVENT_MOUSEUP)
+    {
+      // these events are bound to EMSCRIPTEN_EVENT_TARGET_WINDOW, and coordinates should be converted
+      occJSUpdateBoundingClientRect();
+      EmscriptenMouseEvent anEvent = *theEvent;
+      anEvent.targetX -= occJSGetBoundingClientLeft();
+      anEvent.targetY -= occJSGetBoundingClientTop();
+      return aWindow->ProcessMouseEvent (*aViewCtrl, theEventType, &anEvent) ? EM_TRUE : EM_FALSE;
+    }
+
     return aWindow->ProcessMouseEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
   }
   return EM_FALSE;
@@ -730,13 +756,17 @@ void ViewerTest_EventManager::SetupWindowCallbacks (const Handle(Aspect_Window)&
   // so that if web application changes canvas size by other means it should use another way to tell OCCT about resize
   emscripten_set_resize_callback     (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onResizeCallback);
 
+  // bind these events to window to track mouse movements outside of canvas
+  //emscripten_set_mouseup_callback    (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
+  //emscripten_set_mousemove_callback  (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
+  //emscripten_set_mouseleave_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
+  emscripten_set_mouseup_callback    (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onWasmMouseCallback);
+  emscripten_set_mousemove_callback  (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onWasmMouseCallback);
+
   emscripten_set_mousedown_callback  (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
-  emscripten_set_mouseup_callback    (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
-  emscripten_set_mousemove_callback  (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
   emscripten_set_dblclick_callback   (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
   emscripten_set_click_callback      (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
   emscripten_set_mouseenter_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
-  emscripten_set_mouseleave_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
   emscripten_set_wheel_callback      (aTargetId, anOpaque, toUseCapture, onWasmWheelCallback);
 
   emscripten_set_touchstart_callback (aTargetId, anOpaque, toUseCapture, onWasmTouchCallback);
index b2a81e3..19100a4 100644 (file)
@@ -290,10 +290,13 @@ bool Wasm_Window::ProcessMouseEvent (Aspect_WindowInputListener& theListener,
     case EMSCRIPTEN_EVENT_MOUSEDOWN:
     case EMSCRIPTEN_EVENT_MOUSEUP:
     {
-      if (aNewPos2i.x() < 0 || aNewPos2i.x() > mySize.x()
-       || aNewPos2i.y() < 0 || aNewPos2i.y() > mySize.y())
+      if (theEventType == EMSCRIPTEN_EVENT_MOUSEDOWN)
       {
-        return false;
+        if (aNewPos2i.x() < 0 || aNewPos2i.x() > mySize.x()
+         || aNewPos2i.y() < 0 || aNewPos2i.y() > mySize.y())
+        {
+          return false;
+        }
       }
       if (theListener.UpdateMouseButtons (aNewPos2i, aButtons, aFlags, isEmulated))
       {