Mercurial > hg > orthanc-stone
comparison Applications/Generic/GuiAdapter.cpp @ 860:238693c3bc51 am-dev
merge default -> am-dev
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Mon, 24 Jun 2019 14:35:00 +0200 |
parents | e3c56d4f863f |
children | f0bf971a1e31 12b591d5d63c |
comparison
equal
deleted
inserted
replaced
856:a6e17a5a39e7 | 860:238693c3bc51 |
---|---|
1 /** | |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2019 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 #include "GuiAdapter.h" | |
22 | |
23 #if ORTHANC_ENABLE_OPENGL == 1 | |
24 # include "../../Framework/OpenGL/OpenGLIncludes.h" | |
25 #endif | |
26 | |
27 #if ORTHANC_ENABLE_SDL == 1 | |
28 # include <SDL_video.h> | |
29 # include <SDL_render.h> | |
30 # include <SDL.h> | |
31 #endif | |
32 | |
33 #if ORTHANC_ENABLE_THREADS == 1 | |
34 # include "../../Framework/Messages/LockingEmitter.h" | |
35 #endif | |
36 | |
37 namespace OrthancStone | |
38 { | |
39 void GuiAdapter::RegisterWidget(boost::shared_ptr<IGuiAdapterWidget> widget) | |
40 { | |
41 widgets_.push_back(widget); | |
42 } | |
43 | |
44 std::ostream& operator<<( | |
45 std::ostream& os, const GuiAdapterKeyboardEvent& event) | |
46 { | |
47 os << "ctrl: " << event.ctrlKey << ", " << | |
48 "shift: " << event.shiftKey << ", " << | |
49 "alt: " << event.altKey; | |
50 return os; | |
51 } | |
52 | |
53 #if ORTHANC_ENABLE_WASM == 1 | |
54 void GuiAdapter::Run() | |
55 { | |
56 } | |
57 | |
58 void ConvertFromPlatform( | |
59 GuiAdapterUiEvent& dest, | |
60 int eventType, | |
61 const EmscriptenUiEvent& src) | |
62 { | |
63 // no data for now | |
64 } | |
65 | |
66 void ConvertFromPlatform( | |
67 GuiAdapterMouseEvent& dest, | |
68 int eventType, | |
69 const EmscriptenMouseEvent& src) | |
70 { | |
71 memset(&dest, 0, sizeof(GuiAdapterMouseEvent)); | |
72 switch (eventType) | |
73 { | |
74 case EMSCRIPTEN_EVENT_CLICK: | |
75 LOG(ERROR) << "Emscripten EMSCRIPTEN_EVENT_CLICK is not supported"; | |
76 ORTHANC_ASSERT(false, "Not supported"); | |
77 break; | |
78 case EMSCRIPTEN_EVENT_MOUSEDOWN: | |
79 dest.type = GUIADAPTER_EVENT_MOUSEDOWN; | |
80 break; | |
81 case EMSCRIPTEN_EVENT_MOUSEMOVE: | |
82 dest.type = GUIADAPTER_EVENT_MOUSEMOVE; | |
83 break; | |
84 case EMSCRIPTEN_EVENT_MOUSEUP: | |
85 dest.type = GUIADAPTER_EVENT_MOUSEUP; | |
86 break; | |
87 case EMSCRIPTEN_EVENT_WHEEL: | |
88 dest.type = GUIADAPTER_EVENT_WHEEL; | |
89 break; | |
90 | |
91 default: | |
92 LOG(ERROR) << "Emscripten event: " << eventType << " is not supported"; | |
93 ORTHANC_ASSERT(false, "Not supported"); | |
94 } | |
95 //dest.timestamp = src.timestamp; | |
96 //dest.screenX = src.screenX; | |
97 //dest.screenY = src.screenY; | |
98 //dest.clientX = src.clientX; | |
99 //dest.clientY = src.clientY; | |
100 dest.ctrlKey = src.ctrlKey; | |
101 dest.shiftKey = src.shiftKey; | |
102 dest.altKey = src.altKey; | |
103 //dest.metaKey = src.metaKey; | |
104 dest.button = src.button; | |
105 //dest.buttons = src.buttons; | |
106 //dest.movementX = src.movementX; | |
107 //dest.movementY = src.movementY; | |
108 dest.targetX = src.targetX; | |
109 dest.targetY = src.targetY; | |
110 //dest.canvasX = src.canvasX; | |
111 //dest.canvasY = src.canvasY; | |
112 //dest.padding = src.padding; | |
113 } | |
114 | |
115 void ConvertFromPlatform( | |
116 GuiAdapterWheelEvent& dest, | |
117 int eventType, | |
118 const EmscriptenWheelEvent& src) | |
119 { | |
120 ConvertFromPlatform(dest.mouse, eventType, src.mouse); | |
121 dest.deltaX = src.deltaX; | |
122 dest.deltaY = src.deltaY; | |
123 switch (src.deltaMode) | |
124 { | |
125 case DOM_DELTA_PIXEL: | |
126 dest.deltaMode = GUIADAPTER_DELTA_PIXEL; | |
127 break; | |
128 case DOM_DELTA_LINE: | |
129 dest.deltaMode = GUIADAPTER_DELTA_LINE; | |
130 break; | |
131 case DOM_DELTA_PAGE: | |
132 dest.deltaMode = GUIADAPTER_DELTA_PAGE; | |
133 break; | |
134 default: | |
135 ORTHANC_ASSERT(false, "Unknown deltaMode: " << src.deltaMode << | |
136 " in wheel event..."); | |
137 } | |
138 dest.deltaMode = src.deltaMode; | |
139 } | |
140 | |
141 void ConvertFromPlatform( | |
142 GuiAdapterKeyboardEvent& dest, | |
143 const EmscriptenKeyboardEvent& src) | |
144 { | |
145 dest.ctrlKey = src.ctrlKey; | |
146 dest.shiftKey = src.shiftKey; | |
147 dest.altKey = src.altKey; | |
148 } | |
149 | |
150 template<typename GenericFunc> | |
151 struct FuncAdapterPayload | |
152 { | |
153 std::string canvasId; | |
154 void* userData; | |
155 GenericFunc callback; | |
156 }; | |
157 | |
158 template<typename GenericFunc, | |
159 typename GuiAdapterEvent, | |
160 typename EmscriptenEvent> | |
161 EM_BOOL OnEventAdapterFunc( | |
162 int eventType, const EmscriptenEvent* emEvent, void* userData) | |
163 { | |
164 | |
165 // userData is OnMouseWheelFuncAdapterPayload | |
166 FuncAdapterPayload<GenericFunc>* payload = | |
167 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); | |
168 // LOG(INFO) << "OnEventAdapterFunc"; | |
169 // LOG(INFO) << "------------------"; | |
170 // LOG(INFO) << "eventType: " << eventType << " wheelEvent: " << | |
171 // (int)wheelEvent << " userData: " << userData << | |
172 // " payload->userData: " << payload->userData; | |
173 | |
174 GuiAdapterEvent guiEvent; | |
175 ConvertFromPlatform(guiEvent, eventType, *emEvent); | |
176 bool ret = (*(payload->callback))(payload->canvasId, &guiEvent, payload->userData); | |
177 return static_cast<EM_BOOL>(ret); | |
178 } | |
179 | |
180 template<typename GenericFunc, | |
181 typename GuiAdapterEvent, | |
182 typename EmscriptenEvent> | |
183 EM_BOOL OnEventAdapterFunc2( | |
184 int /*eventType*/, const EmscriptenEvent* wheelEvent, void* userData) | |
185 { | |
186 // userData is OnMouseWheelFuncAdapterPayload | |
187 FuncAdapterPayload<GenericFunc>* payload = | |
188 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); | |
189 | |
190 GuiAdapterEvent guiEvent; | |
191 ConvertFromPlatform(guiEvent, *wheelEvent); | |
192 bool ret = (*(payload->callback))(payload->canvasId, &guiEvent, payload->userData); | |
193 return static_cast<EM_BOOL>(ret); | |
194 } | |
195 | |
196 template<typename GenericFunc> | |
197 EM_BOOL OnEventAdapterFunc3( | |
198 double time, void* userData) | |
199 { | |
200 // userData is OnMouseWheelFuncAdapterPayload | |
201 FuncAdapterPayload<GenericFunc>* payload = | |
202 reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); | |
203 //std::auto_ptr< FuncAdapterPayload<GenericFunc> > deleter(payload); | |
204 bool ret = (*(payload->callback))(time, payload->userData); | |
205 return static_cast<EM_BOOL>(ret); | |
206 } | |
207 | |
208 // resize: (const char* target, void* userData, EM_BOOL useCapture, em_ui_callback_func callback) | |
209 template< | |
210 typename GenericFunc, | |
211 typename GuiAdapterEvent, | |
212 typename EmscriptenEvent, | |
213 typename EmscriptenSetCallbackFunc> | |
214 static void SetCallback( | |
215 EmscriptenSetCallbackFunc emFunc, | |
216 std::string canvasId, void* userData, bool capture, GenericFunc func) | |
217 { | |
218 // TODO: write RemoveCallback with an int id that gets returned from | |
219 // here | |
220 FuncAdapterPayload<GenericFunc>* payload = | |
221 new FuncAdapterPayload<GenericFunc>(); | |
222 std::auto_ptr<FuncAdapterPayload<GenericFunc> > payloadP(payload); | |
223 payload->canvasId = canvasId; | |
224 payload->callback = func; | |
225 payload->userData = userData; | |
226 void* userDataRaw = reinterpret_cast<void*>(payload); | |
227 // LOG(INFO) << "SetCallback -- userDataRaw: " << userDataRaw << | |
228 // " payload: " << payload << " payload->userData: " << payload->userData; | |
229 (*emFunc)( | |
230 canvasId.c_str(), | |
231 userDataRaw, | |
232 static_cast<EM_BOOL>(capture), | |
233 &OnEventAdapterFunc<GenericFunc, GuiAdapterEvent, EmscriptenEvent>, | |
234 EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD); | |
235 payloadP.release(); | |
236 } | |
237 | |
238 template< | |
239 typename GenericFunc, | |
240 typename GuiAdapterEvent, | |
241 typename EmscriptenEvent, | |
242 typename EmscriptenSetCallbackFunc> | |
243 static void SetCallback2( | |
244 EmscriptenSetCallbackFunc emFunc, | |
245 std::string canvasId, void* userData, bool capture, GenericFunc func) | |
246 { | |
247 std::auto_ptr<FuncAdapterPayload<GenericFunc> > payload( | |
248 new FuncAdapterPayload<GenericFunc>() | |
249 ); | |
250 payload->canvasId = canvasId; | |
251 payload->callback = func; | |
252 payload->userData = userData; | |
253 void* userDataRaw = reinterpret_cast<void*>(payload.release()); | |
254 (*emFunc)( | |
255 canvasId.c_str(), | |
256 userDataRaw, | |
257 static_cast<EM_BOOL>(capture), | |
258 &OnEventAdapterFunc2<GenericFunc, GuiAdapterEvent, EmscriptenEvent>, | |
259 EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD); | |
260 } | |
261 | |
262 template< | |
263 typename GenericFunc, | |
264 typename EmscriptenSetCallbackFunc> | |
265 static void SetAnimationFrameCallback( | |
266 EmscriptenSetCallbackFunc emFunc, | |
267 void* userData, GenericFunc func) | |
268 { | |
269 // LOG(ERROR) << "SetAnimationFrameCallback !!!!!! (RequestAnimationFrame)"; | |
270 std::auto_ptr<FuncAdapterPayload<GenericFunc> > payload( | |
271 new FuncAdapterPayload<GenericFunc>() | |
272 ); | |
273 payload->canvasId = "UNDEFINED"; | |
274 payload->callback = func; | |
275 payload->userData = userData; | |
276 void* userDataRaw = reinterpret_cast<void*>(payload.release()); | |
277 (*emFunc)( | |
278 &OnEventAdapterFunc3<GenericFunc>, | |
279 userDataRaw); | |
280 } | |
281 | |
282 void GuiAdapter::SetWheelCallback( | |
283 std::string canvasId, void* userData, bool capture, OnMouseWheelFunc func) | |
284 { | |
285 SetCallback<OnMouseWheelFunc, GuiAdapterWheelEvent, EmscriptenWheelEvent>( | |
286 &emscripten_set_wheel_callback_on_thread, | |
287 canvasId, | |
288 userData, | |
289 capture, | |
290 func); | |
291 } | |
292 | |
293 void GuiAdapter::SetMouseDownCallback( | |
294 std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) | |
295 { | |
296 SetCallback<OnMouseEventFunc, GuiAdapterMouseEvent, EmscriptenMouseEvent>( | |
297 &emscripten_set_mousedown_callback_on_thread, | |
298 canvasId, | |
299 userData, | |
300 capture, | |
301 func); | |
302 } | |
303 | |
304 void GuiAdapter::SetMouseMoveCallback( | |
305 std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) | |
306 { | |
307 // LOG(INFO) << "SetMouseMoveCallback -- " << "supplied userData: " << | |
308 // userData; | |
309 | |
310 SetCallback<OnMouseEventFunc, GuiAdapterMouseEvent, EmscriptenMouseEvent>( | |
311 &emscripten_set_mousemove_callback_on_thread, | |
312 canvasId, | |
313 userData, | |
314 capture, | |
315 func); | |
316 } | |
317 | |
318 void GuiAdapter::SetMouseUpCallback( | |
319 std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) | |
320 { | |
321 SetCallback<OnMouseEventFunc, GuiAdapterMouseEvent, EmscriptenMouseEvent>( | |
322 &emscripten_set_mouseup_callback_on_thread, | |
323 canvasId, | |
324 userData, | |
325 capture, | |
326 func); | |
327 } | |
328 | |
329 void GuiAdapter::SetKeyDownCallback( | |
330 std::string canvasId, void* userData, bool capture, OnKeyDownFunc func) | |
331 { | |
332 SetCallback2<OnKeyDownFunc, GuiAdapterKeyboardEvent, EmscriptenKeyboardEvent>( | |
333 &emscripten_set_keydown_callback_on_thread, | |
334 canvasId, | |
335 userData, | |
336 capture, | |
337 func); | |
338 } | |
339 | |
340 void GuiAdapter::SetKeyUpCallback( | |
341 std::string canvasId, void* userData, bool capture, OnKeyUpFunc func) | |
342 { | |
343 SetCallback2<OnKeyUpFunc, GuiAdapterKeyboardEvent, EmscriptenKeyboardEvent>( | |
344 &emscripten_set_keyup_callback_on_thread, | |
345 canvasId, | |
346 userData, | |
347 capture, | |
348 func); | |
349 } | |
350 | |
351 void GuiAdapter::SetResizeCallback( | |
352 std::string canvasId, void* userData, bool capture, OnWindowResizeFunc func) | |
353 { | |
354 SetCallback<OnWindowResizeFunc, GuiAdapterUiEvent, EmscriptenUiEvent>( | |
355 &emscripten_set_resize_callback_on_thread, | |
356 canvasId, | |
357 userData, | |
358 capture, | |
359 func); | |
360 } | |
361 | |
362 void GuiAdapter::RequestAnimationFrame( | |
363 OnAnimationFrameFunc func, void* userData) | |
364 { | |
365 // LOG(ERROR) << "-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"; | |
366 // LOG(ERROR) << "RequestAnimationFrame"; | |
367 // LOG(ERROR) << "-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"; | |
368 SetAnimationFrameCallback<OnAnimationFrameFunc>( | |
369 &emscripten_request_animation_frame_loop, | |
370 userData, | |
371 func); | |
372 } | |
373 | |
374 #if 0 | |
375 void GuiAdapter::SetKeyDownCallback( | |
376 std::string canvasId, void* userData, bool capture, OnKeyDownFunc func) | |
377 { | |
378 emscripten_set_keydown_callback(canvasId.c_str(), userData, static_cast<EM_BOOL>(capture), func); | |
379 } | |
380 void GuiAdapter::SetKeyUpCallback( | |
381 std::string canvasId, void* userData, bool capture, OnKeyUpFunc func) | |
382 { | |
383 emscripten_set_keyup_callback(canvasId.c_str(), userData, static_cast<EM_BOOL>(capture), func); | |
384 } | |
385 | |
386 void GuiAdapter::SetResizeCallback(std::string canvasId, void* userData, bool capture, OnWindowResizeFunc func) | |
387 { | |
388 emscripten_set_resize_callback(canvasId.c_str(), userData, static_cast<EM_BOOL>(capture), func); | |
389 } | |
390 | |
391 void GuiAdapter::RequestAnimationFrame(OnAnimationFrameFunc func, void* userData) | |
392 { | |
393 emscripten_request_animation_frame_loop(func, userData); | |
394 } | |
395 #endif | |
396 | |
397 | |
398 #else | |
399 | |
400 // SDL ONLY | |
401 void ConvertFromPlatform( | |
402 GuiAdapterMouseEvent& dest, | |
403 bool ctrlPressed, bool shiftPressed, bool altPressed, | |
404 const SDL_Event& source) | |
405 { | |
406 memset(&dest, 0, sizeof(GuiAdapterMouseEvent)); | |
407 switch (source.type) | |
408 { | |
409 case SDL_MOUSEBUTTONDOWN: | |
410 dest.type = GUIADAPTER_EVENT_MOUSEDOWN; | |
411 break; | |
412 case SDL_MOUSEMOTION: | |
413 dest.type = GUIADAPTER_EVENT_MOUSEMOVE; | |
414 break; | |
415 case SDL_MOUSEBUTTONUP: | |
416 dest.type = GUIADAPTER_EVENT_MOUSEUP; | |
417 break; | |
418 case SDL_MOUSEWHEEL: | |
419 dest.type = GUIADAPTER_EVENT_WHEEL; | |
420 break; | |
421 default: | |
422 LOG(ERROR) << "SDL event: " << source.type << " is not supported"; | |
423 ORTHANC_ASSERT(false, "Not supported"); | |
424 } | |
425 //dest.timestamp = src.timestamp; | |
426 //dest.screenX = src.screenX; | |
427 //dest.screenY = src.screenY; | |
428 //dest.clientX = src.clientX; | |
429 //dest.clientY = src.clientY; | |
430 dest.ctrlKey = ctrlPressed; | |
431 dest.shiftKey = shiftPressed; | |
432 dest.altKey = altPressed; | |
433 //dest.metaKey = src.metaKey; | |
434 switch (source.button.button) | |
435 { | |
436 case SDL_BUTTON_MIDDLE: | |
437 dest.button = 1; | |
438 break; | |
439 | |
440 case SDL_BUTTON_RIGHT: | |
441 dest.button = 2; | |
442 break; | |
443 | |
444 case SDL_BUTTON_LEFT: | |
445 dest.button = 0; | |
446 break; | |
447 | |
448 default: | |
449 break; | |
450 } | |
451 //dest.buttons = src.buttons; | |
452 //dest.movementX = src.movementX; | |
453 //dest.movementY = src.movementY; | |
454 dest.targetX = source.button.x; | |
455 dest.targetY = source.button.y; | |
456 //dest.canvasX = src.canvasX; | |
457 //dest.canvasY = src.canvasY; | |
458 //dest.padding = src.padding; | |
459 } | |
460 | |
461 void ConvertFromPlatform( | |
462 GuiAdapterWheelEvent& dest, | |
463 bool ctrlPressed, bool shiftPressed, bool altPressed, | |
464 const SDL_Event& source) | |
465 { | |
466 ConvertFromPlatform(dest.mouse, ctrlPressed, shiftPressed, altPressed, source); | |
467 dest.deltaX = source.wheel.x; | |
468 dest.deltaY = source.wheel.y; | |
469 } | |
470 | |
471 | |
472 | |
473 // SDL ONLY | |
474 void GuiAdapter::SetResizeCallback( | |
475 std::string canvasId, void* userData, bool capture, OnWindowResizeFunc func) | |
476 { | |
477 resizeHandlers_.push_back(EventHandlerData<OnWindowResizeFunc>(canvasId, func, userData)); | |
478 } | |
479 | |
480 // SDL ONLY | |
481 void GuiAdapter::SetMouseDownCallback( | |
482 std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) | |
483 { | |
484 mouseDownHandlers_.push_back(EventHandlerData<OnMouseEventFunc>(canvasId, func, userData)); | |
485 } | |
486 | |
487 // SDL ONLY | |
488 void GuiAdapter::SetMouseMoveCallback( | |
489 std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) | |
490 { | |
491 mouseMoveHandlers_.push_back(EventHandlerData<OnMouseEventFunc>(canvasId, func, userData)); | |
492 } | |
493 | |
494 // SDL ONLY | |
495 void GuiAdapter::SetMouseUpCallback( | |
496 std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) | |
497 { | |
498 mouseUpHandlers_.push_back(EventHandlerData<OnMouseEventFunc>(canvasId, func, userData)); | |
499 } | |
500 | |
501 // SDL ONLY | |
502 void GuiAdapter::SetWheelCallback( | |
503 std::string canvasId, void* userData, bool capture, OnMouseWheelFunc func) | |
504 { | |
505 mouseWheelHandlers_.push_back(EventHandlerData<OnMouseWheelFunc>(canvasId, func, userData)); | |
506 } | |
507 | |
508 // SDL ONLY | |
509 void GuiAdapter::SetKeyDownCallback( | |
510 std::string canvasId, void* userData, bool capture, OnKeyDownFunc func) | |
511 { | |
512 } | |
513 | |
514 // SDL ONLY | |
515 void GuiAdapter::SetKeyUpCallback( | |
516 std::string canvasId, void* userData, bool capture, OnKeyUpFunc func) | |
517 { | |
518 } | |
519 | |
520 | |
521 // SDL ONLY | |
522 void GuiAdapter::OnAnimationFrame() | |
523 { | |
524 for (size_t i = 0; i < animationFrameHandlers_.size(); i++) | |
525 { | |
526 // TODO: fix time | |
527 (*(animationFrameHandlers_[i].first))(0, animationFrameHandlers_[i].second); | |
528 } | |
529 } | |
530 | |
531 // SDL ONLY | |
532 void GuiAdapter::OnResize() | |
533 { | |
534 for (size_t i = 0; i < resizeHandlers_.size(); i++) | |
535 { | |
536 (*(resizeHandlers_[i].func))( | |
537 resizeHandlers_[i].canvasName, 0, resizeHandlers_[i].userData); | |
538 } | |
539 } | |
540 | |
541 // SDL ONLY | |
542 void GuiAdapter::OnMouseWheelEvent(uint32_t windowID, const GuiAdapterWheelEvent& event) | |
543 { | |
544 | |
545 // the SDL window name IS the canvas name ("canvas" is used because this lib | |
546 // is designed for Wasm | |
547 SDL_Window* sdlWindow = SDL_GetWindowFromID(windowID); | |
548 ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowID << "\" is not a valid SDL window ID!"); | |
549 | |
550 const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow); | |
551 ORTHANC_ASSERT(windowTitleSz != NULL, "Window ID \"" << windowID << "\" has a NULL window title!"); | |
552 | |
553 std::string windowTitle(windowTitleSz); | |
554 ORTHANC_ASSERT(windowTitle != "", "Window ID \"" << windowID << "\" has an empty window title!"); | |
555 | |
556 switch (event.mouse.type) | |
557 { | |
558 case GUIADAPTER_EVENT_WHEEL: | |
559 for (size_t i = 0; i < mouseWheelHandlers_.size(); i++) | |
560 { | |
561 if(mouseWheelHandlers_[i].canvasName == windowTitle) | |
562 (*(mouseWheelHandlers_[i].func))(windowTitle, &event, mouseWheelHandlers_[i].userData); | |
563 } | |
564 break; | |
565 default: | |
566 ORTHANC_ASSERT(false, "Wrong event.type: " << event.mouse.type << " in GuiAdapter::OnMouseWheelEvent(...)"); | |
567 break; | |
568 } | |
569 } | |
570 | |
571 // SDL ONLY | |
572 void GuiAdapter::OnMouseEvent(uint32_t windowID, const GuiAdapterMouseEvent& event) | |
573 { | |
574 // the SDL window name IS the canvas name ("canvas" is used because this lib | |
575 // is designed for Wasm | |
576 SDL_Window* sdlWindow = SDL_GetWindowFromID(windowID); | |
577 ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowID << "\" is not a valid SDL window ID!"); | |
578 | |
579 const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow); | |
580 ORTHANC_ASSERT(windowTitleSz != NULL, "Window ID \"" << windowID << "\" has a NULL window title!"); | |
581 | |
582 std::string windowTitle(windowTitleSz); | |
583 ORTHANC_ASSERT(windowTitle != "", "Window ID \"" << windowID << "\" has an empty window title!"); | |
584 | |
585 switch (event.type) | |
586 { | |
587 case GUIADAPTER_EVENT_MOUSEDOWN: | |
588 for (size_t i = 0; i < mouseDownHandlers_.size(); i++) | |
589 { | |
590 if (mouseDownHandlers_[i].canvasName == windowTitle) | |
591 (*(mouseDownHandlers_[i].func))(windowTitle, &event, mouseDownHandlers_[i].userData); | |
592 } | |
593 break; | |
594 case GUIADAPTER_EVENT_MOUSEMOVE: | |
595 for (size_t i = 0; i < mouseMoveHandlers_.size(); i++) | |
596 { | |
597 if (mouseMoveHandlers_[i].canvasName == windowTitle) | |
598 (*(mouseMoveHandlers_[i].func))(windowTitle, &event, mouseMoveHandlers_[i].userData); | |
599 } | |
600 break; | |
601 case GUIADAPTER_EVENT_MOUSEUP: | |
602 for (size_t i = 0; i < mouseUpHandlers_.size(); i++) | |
603 { | |
604 if (mouseUpHandlers_[i].canvasName == windowTitle) | |
605 (*(mouseUpHandlers_[i].func))(windowTitle, &event, mouseUpHandlers_[i].userData); | |
606 } | |
607 break; | |
608 default: | |
609 ORTHANC_ASSERT(false, "Wrong event.type: " << event.type << " in GuiAdapter::OnMouseEvent(...)"); | |
610 break; | |
611 } | |
612 | |
613 ////boost::shared_ptr<IGuiAdapterWidget> GetWidgetFromWindowId(); | |
614 //boost::shared_ptr<IGuiAdapterWidget> foundWidget; | |
615 //VisitWidgets([foundWidget, windowID](auto widget) | |
616 // { | |
617 // if (widget->GetSdlWindowID() == windowID) | |
618 // foundWidget = widget; | |
619 // }); | |
620 //ORTHANC_ASSERT(foundWidget, "WindowID " << windowID << " was not found in the registered widgets!"); | |
621 //if(foundWidget) | |
622 // foundWidget-> | |
623 } | |
624 | |
625 // SDL ONLY | |
626 void GuiAdapter::RequestAnimationFrame(OnAnimationFrameFunc func, void* userData) | |
627 { | |
628 animationFrameHandlers_.push_back(std::make_pair(func, userData)); | |
629 } | |
630 | |
631 # if ORTHANC_ENABLE_OPENGL == 1 && !defined(__APPLE__) /* OpenGL debug is not available on OS X */ | |
632 | |
633 // SDL ONLY | |
634 static void GLAPIENTRY | |
635 OpenGLMessageCallback(GLenum source, | |
636 GLenum type, | |
637 GLuint id, | |
638 GLenum severity, | |
639 GLsizei length, | |
640 const GLchar* message, | |
641 const void* userParam) | |
642 { | |
643 if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) | |
644 { | |
645 fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", | |
646 (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), | |
647 type, severity, message); | |
648 } | |
649 } | |
650 # endif | |
651 | |
652 // SDL ONLY | |
653 void GuiAdapter::Run() | |
654 { | |
655 # if ORTHANC_ENABLE_OPENGL == 1 && !defined(__APPLE__) | |
656 glEnable(GL_DEBUG_OUTPUT); | |
657 glDebugMessageCallback(OpenGLMessageCallback, 0); | |
658 # endif | |
659 | |
660 // Uint32 SDL_GetWindowID(SDL_Window* window) | |
661 // SDL_Window* SDL_GetWindowFromID(Uint32 id) // may return NULL | |
662 | |
663 bool stop = false; | |
664 while (!stop) | |
665 { | |
666 { | |
667 LockingEmitter::WriterLock lock(lockingEmitter_); | |
668 OnAnimationFrame(); // in SDL we must call it | |
669 } | |
670 | |
671 SDL_Event event; | |
672 | |
673 while (!stop && SDL_PollEvent(&event)) | |
674 { | |
675 LockingEmitter::WriterLock lock(lockingEmitter_); | |
676 | |
677 if (event.type == SDL_QUIT) | |
678 { | |
679 // TODO: call exit callbacks here | |
680 stop = true; | |
681 break; | |
682 } | |
683 else if ( (event.type == SDL_MOUSEMOTION) || | |
684 (event.type == SDL_MOUSEBUTTONDOWN) || | |
685 (event.type == SDL_MOUSEBUTTONUP) ) | |
686 { | |
687 int scancodeCount = 0; | |
688 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); | |
689 bool ctrlPressed(false); | |
690 bool shiftPressed(false); | |
691 bool altPressed(false); | |
692 | |
693 if (SDL_SCANCODE_LCTRL < scancodeCount && keyboardState[SDL_SCANCODE_LCTRL]) | |
694 ctrlPressed = true; | |
695 if (SDL_SCANCODE_RCTRL < scancodeCount && keyboardState[SDL_SCANCODE_RCTRL]) | |
696 ctrlPressed = true; | |
697 if (SDL_SCANCODE_LSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_LSHIFT]) | |
698 shiftPressed = true; | |
699 if (SDL_SCANCODE_RSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_RSHIFT]) | |
700 shiftPressed = true; | |
701 if (SDL_SCANCODE_LALT < scancodeCount && keyboardState[SDL_SCANCODE_LALT]) | |
702 altPressed = true; | |
703 | |
704 GuiAdapterMouseEvent dest; | |
705 ConvertFromPlatform(dest, ctrlPressed, shiftPressed, altPressed, event); | |
706 OnMouseEvent(event.window.windowID, dest); | |
707 #if 0 | |
708 // for reference, how to create trackers | |
709 if (tracker) | |
710 { | |
711 PointerEvent e; | |
712 e.AddPosition(compositor.GetPixelCenterCoordinates( | |
713 event.button.x, event.button.y)); | |
714 tracker->PointerMove(e); | |
715 } | |
716 #endif | |
717 } | |
718 else if (event.type == SDL_MOUSEWHEEL) | |
719 { | |
720 | |
721 int scancodeCount = 0; | |
722 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); | |
723 bool ctrlPressed(false); | |
724 bool shiftPressed(false); | |
725 bool altPressed(false); | |
726 | |
727 if (SDL_SCANCODE_LCTRL < scancodeCount && keyboardState[SDL_SCANCODE_LCTRL]) | |
728 ctrlPressed = true; | |
729 if (SDL_SCANCODE_RCTRL < scancodeCount && keyboardState[SDL_SCANCODE_RCTRL]) | |
730 ctrlPressed = true; | |
731 if (SDL_SCANCODE_LSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_LSHIFT]) | |
732 shiftPressed = true; | |
733 if (SDL_SCANCODE_RSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_RSHIFT]) | |
734 shiftPressed = true; | |
735 if (SDL_SCANCODE_LALT < scancodeCount && keyboardState[SDL_SCANCODE_LALT]) | |
736 altPressed = true; | |
737 | |
738 GuiAdapterWheelEvent dest; | |
739 ConvertFromPlatform(dest, ctrlPressed, shiftPressed, altPressed, event); | |
740 OnMouseWheelEvent(event.window.windowID, dest); | |
741 | |
742 //KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount); | |
743 | |
744 //int x, y; | |
745 //SDL_GetMouseState(&x, &y); | |
746 | |
747 //if (event.wheel.y > 0) | |
748 //{ | |
749 // locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers); | |
750 //} | |
751 //else if (event.wheel.y < 0) | |
752 //{ | |
753 // locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers); | |
754 //} | |
755 } | |
756 else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) | |
757 { | |
758 #if 0 | |
759 tracker.reset(); | |
760 #endif | |
761 OnResize(); | |
762 } | |
763 else if (event.type == SDL_KEYDOWN && event.key.repeat == 0 /* Ignore key bounce */) | |
764 { | |
765 switch (event.key.keysym.sym) | |
766 { | |
767 case SDLK_f: | |
768 // window.GetWindow().ToggleMaximize(); //TODO: move to particular handler | |
769 break; | |
770 | |
771 case SDLK_s: | |
772 #if 0 | |
773 // TODO: re-enable at application-level!!!! | |
774 VisitWidgets( | |
775 [](auto value) | |
776 { | |
777 auto widget = boost::dynamic_pointer_cast<VolumeSlicerWidget() | |
778 value->FitContent(); | |
779 }); | |
780 #endif | |
781 break; | |
782 | |
783 case SDLK_q: | |
784 stop = true; | |
785 break; | |
786 | |
787 default: | |
788 break; | |
789 } | |
790 } | |
791 // HandleApplicationEvent(controller, compositor, event, tracker); | |
792 } | |
793 | |
794 SDL_Delay(1); | |
795 } | |
796 } | |
797 #endif | |
798 } | |
799 |