changeset 1370:28eb7106ef44 broker

Changes to GuiAdapter to allow it to work correctly with both new and old Emscripten event selection rules that are defined by the DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR linker flag. Doc has been added to GuiAdapter.cpp, should you require more info on what has been done.
author Benjamin Golinvaux <bgo@osimis.io>
date Mon, 20 Apr 2020 13:08:43 +0200
parents aadc374bc006
children f15529add7b0
files Applications/Generic/GuiAdapter.cpp Applications/Generic/GuiAdapter.h Samples/Deprecated/WebAssembly/BasicMPR.cpp
diffstat 3 files changed, 112 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Generic/GuiAdapter.cpp	Sat Apr 18 14:45:38 2020 +0200
+++ b/Applications/Generic/GuiAdapter.cpp	Mon Apr 20 13:08:43 2020 +0200
@@ -147,7 +147,7 @@
   template<typename GenericFunc>
   struct FuncAdapterPayload
   {
-    std::string canvasId;
+    std::string canvasCssSelector;
     void* userData;
     GenericFunc callback;
   };
@@ -158,7 +158,6 @@
     EM_BOOL OnEventAdapterFunc(
       int eventType, const EmscriptenEvent* emEvent, void* userData)
   {
-
     // userData is OnMouseWheelFuncAdapterPayload
     FuncAdapterPayload<GenericFunc>* payload =
       reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData);
@@ -170,7 +169,7 @@
 
     GuiAdapterEvent guiEvent;
     ConvertFromPlatform(guiEvent, eventType, *emEvent);
-    bool ret = (*(payload->callback))(payload->canvasId, &guiEvent, payload->userData);
+    bool ret = (*(payload->callback))(payload->canvasCssSelector, &guiEvent, payload->userData);
     return static_cast<EM_BOOL>(ret);
   }
 
@@ -186,7 +185,7 @@
 
     GuiAdapterEvent guiEvent;
     ConvertFromPlatform(guiEvent, *wheelEvent);
-    bool ret = (*(payload->callback))(payload->canvasId, &guiEvent, payload->userData);
+    bool ret = (*(payload->callback))(payload->canvasCssSelector, &guiEvent, payload->userData);
     return static_cast<EM_BOOL>(ret);
   }
 
@@ -202,6 +201,76 @@
     return static_cast<EM_BOOL>(ret);
   }
 
+  /*
+  
+  Explanation
+  ===========
+
+  - in "older" Emscripten, where DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR doesn't exist or is set to 0,
+    the following strings need to be used to register events:
+    - for canvas, the canvas DOM id. In case of <canvas id="mycanvas1" width='640' ...></canvas>", the string needs 
+      to be "mycanvas"
+    - for the window (for key events), the string needs to be "#window"
+  - in newer Emscripten where DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR==1 (or maybe is not there anymore, in the
+    future as of 2020-04-20)
+    - for canvas, the canvas DOM id. In case of <canvas id="mycanvas1" width='640' ...></canvas>", the string needs
+      to be "#mycanvas"  (notice the "number sign", aka "hash", NOT AKA "sharp", as can be read on https://en.wikipedia.org/wiki/Number_sign)
+    - for the window (for key events), the string needs to be EMSCRIPTEN_EVENT_TARGET_WINDOW. I do not mean 
+      "EMSCRIPTEN_EVENT_TARGET_WINDOW", but the #define EMSCRIPTEN_EVENT_TARGET_WINDOW         ((const char*)2) that
+      can be found in emscripten/html5.h
+
+  The code below converts the input canvasId (as in the old emscripten) to the emscripten-compliant one, with the
+  following compile condition : #if DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR == 1
+
+  If the DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR build parameter disappears, you might want to refactor this code
+  or continue to pass the DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR compile macro (which is different from the CMake
+  variable)     
+
+  What we are doing below:
+  - in older Emscripten, the registration functions will receive "mycanvas" and "#window" and the callbacks will receive 
+    the same std::string in their payload ("mycanvas" and "#window")
+
+  - in newer Emscripten, the registration functions will receive "#mycanvas" and EMSCRIPTEN_EVENT_TARGET_WINDOW, but 
+    the callbacks will receive "#mycanvas" and "#window" (since it is not possible to store the EMSCRIPTEN_EVENT_TARGET_WINDOW
+    magic value in an std::string, while we still want the callback to be able to change its behavior according to the
+    target element.
+  
+  */
+
+  void convertElementTarget(const char*& outCanvasCssSelectorSz, std::string& outCanvasCssSelector, const std::string& canvasId)
+  {
+    // only "#window" can start with a #
+    if (canvasId[0] == '#')
+    {
+      ORTHANC_ASSERT(canvasId == "#window");
+    }
+#if DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR == 1
+    if (canvasId == "#window")
+    {
+      // we store this in the payload so that the callback can 
+      outCanvasCssSelector = "#window";
+      outCanvasCssSelectorSz = EMSCRIPTEN_EVENT_TARGET_WINDOW;
+    }
+    else
+    {
+      outCanvasCssSelector = "#" + canvasId;
+      outCanvasCssSelectorSz = outCanvasCssSelector.c_str();
+    }
+#else
+    if (canvasId == "#window")
+    {
+      // we store this in the payload so that the callback can 
+      outCanvasCssSelector = "#window";
+      outCanvasCssSelectorSz = outCanvasCssSelector.c_str();;
+    }
+    else
+    {
+      outCanvasCssSelector = canvasId;
+      outCanvasCssSelectorSz = outCanvasCssSelector.c_str();;
+    }
+#endif
+  }
+
   // resize: (const char* target, void* userData, EM_BOOL useCapture, em_ui_callback_func callback)
   template<
     typename GenericFunc,
@@ -212,24 +281,26 @@
       EmscriptenSetCallbackFunc emFunc,
       std::string canvasId, void* userData, bool capture, GenericFunc func)
   {
-    // TODO: write RemoveCallback with an int id that gets returned from
-    // here
-    FuncAdapterPayload<GenericFunc>* payload =
-      new FuncAdapterPayload<GenericFunc>();
-    std::unique_ptr<FuncAdapterPayload<GenericFunc> > payloadP(payload);
-    payload->canvasId = canvasId;
+    std::string canvasCssSelector;
+    const char* canvasCssSelectorSz = NULL;
+    convertElementTarget(canvasCssSelectorSz, canvasCssSelector, canvasId);
+
+    // TODO: write RemoveCallback with an int id that gets returned from here
+
+    // create userdata payload
+    std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(new FuncAdapterPayload<GenericFunc>());
+    payload->canvasCssSelector = canvasCssSelector;
     payload->callback = func;
     payload->userData = userData;
-    void* userDataRaw = reinterpret_cast<void*>(payload);
-    // LOG(INFO) << "SetCallback -- userDataRaw: " << userDataRaw <<
-    //   " payload: " << payload << " payload->userData: " << payload->userData;
+    void* userDataRaw = reinterpret_cast<void*>(payload.release());
+
+    // call the registration function
     (*emFunc)(
-      canvasId.c_str(),
+      canvasCssSelectorSz,
       userDataRaw,
       static_cast<EM_BOOL>(capture),
       &OnEventAdapterFunc<GenericFunc, GuiAdapterEvent, EmscriptenEvent>,
       EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD);
-    payloadP.release();
   }
 
   template<
@@ -241,15 +312,22 @@
       EmscriptenSetCallbackFunc emFunc,
       std::string canvasId, void* userData, bool capture, GenericFunc func)
   {
-    std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(
-      new FuncAdapterPayload<GenericFunc>()
-    );
-    payload->canvasId = canvasId;
+    std::string canvasCssSelector;
+    const char* canvasCssSelectorSz = NULL;
+    convertElementTarget(canvasCssSelectorSz, canvasCssSelector, canvasId);
+
+    // TODO: write RemoveCallback with an int id that gets returned from here
+
+    // create userdata payload
+    std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(new FuncAdapterPayload<GenericFunc>());
+    payload->canvasCssSelector = canvasCssSelector;
     payload->callback = func;
     payload->userData = userData;
     void* userDataRaw = reinterpret_cast<void*>(payload.release());
+
+    // call the registration function
     (*emFunc)(
-      canvasId.c_str(),
+      canvasCssSelectorSz,
       userDataRaw,
       static_cast<EM_BOOL>(capture),
       &OnEventAdapterFunc2<GenericFunc, GuiAdapterEvent, EmscriptenEvent>,
@@ -266,7 +344,7 @@
     std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(
       new FuncAdapterPayload<GenericFunc>()
     );
-    payload->canvasId = "UNDEFINED";
+    payload->canvasCssSelector = "UNDEFINED";
     payload->callback = func;
     payload->userData = userData;
     void* userDataRaw = reinterpret_cast<void*>(payload.release());
--- a/Applications/Generic/GuiAdapter.h	Sat Apr 18 14:45:38 2020 +0200
+++ b/Applications/Generic/GuiAdapter.h	Mon Apr 20 13:08:43 2020 +0200
@@ -254,14 +254,14 @@
     }
 
     /**
-      emscripten_set_resize_callback("#window", NULL, false, OnWindowResize);
+      emscripten_set_resize_callback("EMSCRIPTEN_EVENT_TARGET_WINDOW", NULL, false, OnWindowResize);
 
-      emscripten_set_wheel_callback("mycanvas1", widget1_.get(), false, OnXXXMouseWheel);
-      emscripten_set_wheel_callback("mycanvas2", widget2_.get(), false, OnXXXMouseWheel);
-      emscripten_set_wheel_callback("mycanvas3", widget3_.get(), false, OnXXXMouseWheel);
+      emscripten_set_wheel_callback("#mycanvas1", widget1_.get(), false, OnXXXMouseWheel);
+      emscripten_set_wheel_callback("#mycanvas2", widget2_.get(), false, OnXXXMouseWheel);
+      emscripten_set_wheel_callback("#mycanvas3", widget3_.get(), false, OnXXXMouseWheel);
 
-      emscripten_set_keydown_callback("#window", NULL, false, OnKeyDown);
-      emscripten_set_keyup_callback("#window", NULL, false, OnKeyUp);
+      emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnKeyDown); ---> NO!
+      emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnKeyUp);
 
       emscripten_request_animation_frame_loop(OnAnimationFrame, NULL);
     
@@ -285,6 +285,7 @@
     typedef bool (*OnSdlEventCallback)  (std::string canvasId, const SDL_Event& sdlEvent, void* userData);
 
     // if you pass "#window", then any Window resize will trigger the callback
+    // (this special string is converted to EMSCRIPTEN_EVENT_TARGET_WINDOW in DOM, when DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1)
     void SetSdlResizeCallback(std::string canvasId, 
                               void* userData, 
                               bool capture, 
--- a/Samples/Deprecated/WebAssembly/BasicMPR.cpp	Sat Apr 18 14:45:38 2020 +0200
+++ b/Samples/Deprecated/WebAssembly/BasicMPR.cpp	Mon Apr 20 13:08:43 2020 +0200
@@ -396,14 +396,14 @@
       }
       widget3_->UpdateSize();
 
-      emscripten_set_resize_callback("#window", NULL, false, OnWindowResize);
+      emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnWindowResize); // DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 !!
 
-      emscripten_set_wheel_callback("mycanvas1", widget1_.get(), false, OnMouseWheel);
-      emscripten_set_wheel_callback("mycanvas2", widget2_.get(), false, OnMouseWheel);
-      emscripten_set_wheel_callback("mycanvas3", widget3_.get(), false, OnMouseWheel);
+      emscripten_set_wheel_callback("#mycanvas1", widget1_.get(), false, OnMouseWheel);
+      emscripten_set_wheel_callback("#mycanvas2", widget2_.get(), false, OnMouseWheel);
+      emscripten_set_wheel_callback("#mycanvas3", widget3_.get(), false, OnMouseWheel);
 
-      emscripten_set_keydown_callback("#window", NULL, false, OnKeyDown);
-      emscripten_set_keyup_callback("#window", NULL, false, OnKeyUp);
+      emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnKeyDown);
+      emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnKeyUp);
     
       emscripten_request_animation_frame_loop(OnAnimationFrame, NULL);