comparison Applications/Generic/GuiAdapter.cpp @ 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 d80a3e3cc800
children f15529add7b0
comparison
equal deleted inserted replaced
1369:aadc374bc006 1370:28eb7106ef44
145 } 145 }
146 146
147 template<typename GenericFunc> 147 template<typename GenericFunc>
148 struct FuncAdapterPayload 148 struct FuncAdapterPayload
149 { 149 {
150 std::string canvasId; 150 std::string canvasCssSelector;
151 void* userData; 151 void* userData;
152 GenericFunc callback; 152 GenericFunc callback;
153 }; 153 };
154 154
155 template<typename GenericFunc, 155 template<typename GenericFunc,
156 typename GuiAdapterEvent, 156 typename GuiAdapterEvent,
157 typename EmscriptenEvent> 157 typename EmscriptenEvent>
158 EM_BOOL OnEventAdapterFunc( 158 EM_BOOL OnEventAdapterFunc(
159 int eventType, const EmscriptenEvent* emEvent, void* userData) 159 int eventType, const EmscriptenEvent* emEvent, void* userData)
160 { 160 {
161
162 // userData is OnMouseWheelFuncAdapterPayload 161 // userData is OnMouseWheelFuncAdapterPayload
163 FuncAdapterPayload<GenericFunc>* payload = 162 FuncAdapterPayload<GenericFunc>* payload =
164 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); 163 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData);
165 // LOG(INFO) << "OnEventAdapterFunc"; 164 // LOG(INFO) << "OnEventAdapterFunc";
166 // LOG(INFO) << "------------------"; 165 // LOG(INFO) << "------------------";
168 // (int)wheelEvent << " userData: " << userData << 167 // (int)wheelEvent << " userData: " << userData <<
169 // " payload->userData: " << payload->userData; 168 // " payload->userData: " << payload->userData;
170 169
171 GuiAdapterEvent guiEvent; 170 GuiAdapterEvent guiEvent;
172 ConvertFromPlatform(guiEvent, eventType, *emEvent); 171 ConvertFromPlatform(guiEvent, eventType, *emEvent);
173 bool ret = (*(payload->callback))(payload->canvasId, &guiEvent, payload->userData); 172 bool ret = (*(payload->callback))(payload->canvasCssSelector, &guiEvent, payload->userData);
174 return static_cast<EM_BOOL>(ret); 173 return static_cast<EM_BOOL>(ret);
175 } 174 }
176 175
177 template<typename GenericFunc, 176 template<typename GenericFunc,
178 typename GuiAdapterEvent, 177 typename GuiAdapterEvent,
184 FuncAdapterPayload<GenericFunc>* payload = 183 FuncAdapterPayload<GenericFunc>* payload =
185 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); 184 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData);
186 185
187 GuiAdapterEvent guiEvent; 186 GuiAdapterEvent guiEvent;
188 ConvertFromPlatform(guiEvent, *wheelEvent); 187 ConvertFromPlatform(guiEvent, *wheelEvent);
189 bool ret = (*(payload->callback))(payload->canvasId, &guiEvent, payload->userData); 188 bool ret = (*(payload->callback))(payload->canvasCssSelector, &guiEvent, payload->userData);
190 return static_cast<EM_BOOL>(ret); 189 return static_cast<EM_BOOL>(ret);
191 } 190 }
192 191
193 template<typename GenericFunc> 192 template<typename GenericFunc>
194 EM_BOOL OnEventAdapterFunc3( 193 EM_BOOL OnEventAdapterFunc3(
198 FuncAdapterPayload<GenericFunc>* payload = 197 FuncAdapterPayload<GenericFunc>* payload =
199 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); 198 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData);
200 //std::unique_ptr< FuncAdapterPayload<GenericFunc> > deleter(payload); 199 //std::unique_ptr< FuncAdapterPayload<GenericFunc> > deleter(payload);
201 bool ret = (*(payload->callback))(time, payload->userData); 200 bool ret = (*(payload->callback))(time, payload->userData);
202 return static_cast<EM_BOOL>(ret); 201 return static_cast<EM_BOOL>(ret);
202 }
203
204 /*
205
206 Explanation
207 ===========
208
209 - in "older" Emscripten, where DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR doesn't exist or is set to 0,
210 the following strings need to be used to register events:
211 - for canvas, the canvas DOM id. In case of <canvas id="mycanvas1" width='640' ...></canvas>", the string needs
212 to be "mycanvas"
213 - for the window (for key events), the string needs to be "#window"
214 - in newer Emscripten where DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR==1 (or maybe is not there anymore, in the
215 future as of 2020-04-20)
216 - for canvas, the canvas DOM id. In case of <canvas id="mycanvas1" width='640' ...></canvas>", the string needs
217 to be "#mycanvas" (notice the "number sign", aka "hash", NOT AKA "sharp", as can be read on https://en.wikipedia.org/wiki/Number_sign)
218 - for the window (for key events), the string needs to be EMSCRIPTEN_EVENT_TARGET_WINDOW. I do not mean
219 "EMSCRIPTEN_EVENT_TARGET_WINDOW", but the #define EMSCRIPTEN_EVENT_TARGET_WINDOW ((const char*)2) that
220 can be found in emscripten/html5.h
221
222 The code below converts the input canvasId (as in the old emscripten) to the emscripten-compliant one, with the
223 following compile condition : #if DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR == 1
224
225 If the DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR build parameter disappears, you might want to refactor this code
226 or continue to pass the DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR compile macro (which is different from the CMake
227 variable)
228
229 What we are doing below:
230 - in older Emscripten, the registration functions will receive "mycanvas" and "#window" and the callbacks will receive
231 the same std::string in their payload ("mycanvas" and "#window")
232
233 - in newer Emscripten, the registration functions will receive "#mycanvas" and EMSCRIPTEN_EVENT_TARGET_WINDOW, but
234 the callbacks will receive "#mycanvas" and "#window" (since it is not possible to store the EMSCRIPTEN_EVENT_TARGET_WINDOW
235 magic value in an std::string, while we still want the callback to be able to change its behavior according to the
236 target element.
237
238 */
239
240 void convertElementTarget(const char*& outCanvasCssSelectorSz, std::string& outCanvasCssSelector, const std::string& canvasId)
241 {
242 // only "#window" can start with a #
243 if (canvasId[0] == '#')
244 {
245 ORTHANC_ASSERT(canvasId == "#window");
246 }
247 #if DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR == 1
248 if (canvasId == "#window")
249 {
250 // we store this in the payload so that the callback can
251 outCanvasCssSelector = "#window";
252 outCanvasCssSelectorSz = EMSCRIPTEN_EVENT_TARGET_WINDOW;
253 }
254 else
255 {
256 outCanvasCssSelector = "#" + canvasId;
257 outCanvasCssSelectorSz = outCanvasCssSelector.c_str();
258 }
259 #else
260 if (canvasId == "#window")
261 {
262 // we store this in the payload so that the callback can
263 outCanvasCssSelector = "#window";
264 outCanvasCssSelectorSz = outCanvasCssSelector.c_str();;
265 }
266 else
267 {
268 outCanvasCssSelector = canvasId;
269 outCanvasCssSelectorSz = outCanvasCssSelector.c_str();;
270 }
271 #endif
203 } 272 }
204 273
205 // resize: (const char* target, void* userData, EM_BOOL useCapture, em_ui_callback_func callback) 274 // resize: (const char* target, void* userData, EM_BOOL useCapture, em_ui_callback_func callback)
206 template< 275 template<
207 typename GenericFunc, 276 typename GenericFunc,
210 typename EmscriptenSetCallbackFunc> 279 typename EmscriptenSetCallbackFunc>
211 static void SetCallback( 280 static void SetCallback(
212 EmscriptenSetCallbackFunc emFunc, 281 EmscriptenSetCallbackFunc emFunc,
213 std::string canvasId, void* userData, bool capture, GenericFunc func) 282 std::string canvasId, void* userData, bool capture, GenericFunc func)
214 { 283 {
215 // TODO: write RemoveCallback with an int id that gets returned from 284 std::string canvasCssSelector;
216 // here 285 const char* canvasCssSelectorSz = NULL;
217 FuncAdapterPayload<GenericFunc>* payload = 286 convertElementTarget(canvasCssSelectorSz, canvasCssSelector, canvasId);
218 new FuncAdapterPayload<GenericFunc>(); 287
219 std::unique_ptr<FuncAdapterPayload<GenericFunc> > payloadP(payload); 288 // TODO: write RemoveCallback with an int id that gets returned from here
220 payload->canvasId = canvasId; 289
290 // create userdata payload
291 std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(new FuncAdapterPayload<GenericFunc>());
292 payload->canvasCssSelector = canvasCssSelector;
221 payload->callback = func; 293 payload->callback = func;
222 payload->userData = userData; 294 payload->userData = userData;
223 void* userDataRaw = reinterpret_cast<void*>(payload); 295 void* userDataRaw = reinterpret_cast<void*>(payload.release());
224 // LOG(INFO) << "SetCallback -- userDataRaw: " << userDataRaw << 296
225 // " payload: " << payload << " payload->userData: " << payload->userData; 297 // call the registration function
226 (*emFunc)( 298 (*emFunc)(
227 canvasId.c_str(), 299 canvasCssSelectorSz,
228 userDataRaw, 300 userDataRaw,
229 static_cast<EM_BOOL>(capture), 301 static_cast<EM_BOOL>(capture),
230 &OnEventAdapterFunc<GenericFunc, GuiAdapterEvent, EmscriptenEvent>, 302 &OnEventAdapterFunc<GenericFunc, GuiAdapterEvent, EmscriptenEvent>,
231 EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD); 303 EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD);
232 payloadP.release();
233 } 304 }
234 305
235 template< 306 template<
236 typename GenericFunc, 307 typename GenericFunc,
237 typename GuiAdapterEvent, 308 typename GuiAdapterEvent,
239 typename EmscriptenSetCallbackFunc> 310 typename EmscriptenSetCallbackFunc>
240 static void SetCallback2( 311 static void SetCallback2(
241 EmscriptenSetCallbackFunc emFunc, 312 EmscriptenSetCallbackFunc emFunc,
242 std::string canvasId, void* userData, bool capture, GenericFunc func) 313 std::string canvasId, void* userData, bool capture, GenericFunc func)
243 { 314 {
244 std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload( 315 std::string canvasCssSelector;
245 new FuncAdapterPayload<GenericFunc>() 316 const char* canvasCssSelectorSz = NULL;
246 ); 317 convertElementTarget(canvasCssSelectorSz, canvasCssSelector, canvasId);
247 payload->canvasId = canvasId; 318
319 // TODO: write RemoveCallback with an int id that gets returned from here
320
321 // create userdata payload
322 std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(new FuncAdapterPayload<GenericFunc>());
323 payload->canvasCssSelector = canvasCssSelector;
248 payload->callback = func; 324 payload->callback = func;
249 payload->userData = userData; 325 payload->userData = userData;
250 void* userDataRaw = reinterpret_cast<void*>(payload.release()); 326 void* userDataRaw = reinterpret_cast<void*>(payload.release());
327
328 // call the registration function
251 (*emFunc)( 329 (*emFunc)(
252 canvasId.c_str(), 330 canvasCssSelectorSz,
253 userDataRaw, 331 userDataRaw,
254 static_cast<EM_BOOL>(capture), 332 static_cast<EM_BOOL>(capture),
255 &OnEventAdapterFunc2<GenericFunc, GuiAdapterEvent, EmscriptenEvent>, 333 &OnEventAdapterFunc2<GenericFunc, GuiAdapterEvent, EmscriptenEvent>,
256 EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD); 334 EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD);
257 } 335 }
264 void* userData, GenericFunc func) 342 void* userData, GenericFunc func)
265 { 343 {
266 std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload( 344 std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(
267 new FuncAdapterPayload<GenericFunc>() 345 new FuncAdapterPayload<GenericFunc>()
268 ); 346 );
269 payload->canvasId = "UNDEFINED"; 347 payload->canvasCssSelector = "UNDEFINED";
270 payload->callback = func; 348 payload->callback = func;
271 payload->userData = userData; 349 payload->userData = userData;
272 void* userDataRaw = reinterpret_cast<void*>(payload.release()); 350 void* userDataRaw = reinterpret_cast<void*>(payload.release());
273 (*emFunc)( 351 (*emFunc)(
274 &OnEventAdapterFunc3<GenericFunc>, 352 &OnEventAdapterFunc3<GenericFunc>,