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