# HG changeset patch # User Benjamin Golinvaux # Date 1587380923 -7200 # Node ID 28eb7106ef4468edb7e362fae4d1fafee73dbc04 # Parent aadc374bc0061502c52c1865f96349c173ecac01 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. diff -r aadc374bc006 -r 28eb7106ef44 Applications/Generic/GuiAdapter.cpp --- 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 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* payload = reinterpret_cast*>(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(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(ret); } @@ -202,6 +201,76 @@ return static_cast(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 ", 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 ", 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* payload = - new FuncAdapterPayload(); - std::unique_ptr > 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 > payload(new FuncAdapterPayload()); + payload->canvasCssSelector = canvasCssSelector; payload->callback = func; payload->userData = userData; - void* userDataRaw = reinterpret_cast(payload); - // LOG(INFO) << "SetCallback -- userDataRaw: " << userDataRaw << - // " payload: " << payload << " payload->userData: " << payload->userData; + void* userDataRaw = reinterpret_cast(payload.release()); + + // call the registration function (*emFunc)( - canvasId.c_str(), + canvasCssSelectorSz, userDataRaw, static_cast(capture), &OnEventAdapterFunc, 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 > payload( - new FuncAdapterPayload() - ); - 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 > payload(new FuncAdapterPayload()); + payload->canvasCssSelector = canvasCssSelector; payload->callback = func; payload->userData = userData; void* userDataRaw = reinterpret_cast(payload.release()); + + // call the registration function (*emFunc)( - canvasId.c_str(), + canvasCssSelectorSz, userDataRaw, static_cast(capture), &OnEventAdapterFunc2, @@ -266,7 +344,7 @@ std::unique_ptr > payload( new FuncAdapterPayload() ); - payload->canvasId = "UNDEFINED"; + payload->canvasCssSelector = "UNDEFINED"; payload->callback = func; payload->userData = userData; void* userDataRaw = reinterpret_cast(payload.release()); diff -r aadc374bc006 -r 28eb7106ef44 Applications/Generic/GuiAdapter.h --- 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, diff -r aadc374bc006 -r 28eb7106ef44 Samples/Deprecated/WebAssembly/BasicMPR.cpp --- 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);