comparison Applications/Generic/GuiAdapter.cpp @ 1313:f30905f5d246 broker

Added support for OnGenericSdlEvent to GuiAdapter. This makes it possible to piggyback app-specific logic to special events (here, to support the Viewport refresh events)
author Benjamin Golinvaux <bgo@osimis.io>
date Mon, 16 Mar 2020 11:12:39 +0100
parents 4f8c9065ee52
children 8981bfca3457
comparison
equal deleted inserted replaced
1312:4f8c9065ee52 1313:f30905f5d246
518 dest.altKey = true; 518 dest.altKey = true;
519 else 519 else
520 dest.altKey = false; 520 dest.altKey = false;
521 } 521 }
522 522
523
524 #if ORTHANC_ENABLE_WASM != 1
525 // SDL ONLY 523 // SDL ONLY
526 void GuiAdapter::SetSdlResizeCallback( 524 void GuiAdapter::SetSdlResizeCallback(
527 std::string canvasId, void* userData, bool capture, OnSdlWindowResizeFunc func) 525 std::string canvasId, void* userData, bool capture, OnSdlWindowResizeFunc func)
528 { 526 {
529 resizeHandlers_.push_back(EventHandlerData<OnSdlWindowResizeFunc>(canvasId, func, userData)); 527 resizeHandlers_.push_back(EventHandlerData<OnSdlWindowResizeFunc>(canvasId, func, userData));
530 } 528 }
531 #endif
532 529
533 // SDL ONLY 530 // SDL ONLY
534 void GuiAdapter::SetMouseDownCallback( 531 void GuiAdapter::SetMouseDownCallback(
535 std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) 532 std::string canvasId, void* userData, bool capture, OnMouseEventFunc func)
536 { 533 {
575 // SDL ONLY 572 // SDL ONLY
576 void GuiAdapter::SetKeyUpCallback( 573 void GuiAdapter::SetKeyUpCallback(
577 std::string canvasId, void* userData, bool capture, OnKeyUpFunc func) 574 std::string canvasId, void* userData, bool capture, OnKeyUpFunc func)
578 { 575 {
579 keyUpHandlers_.push_back(EventHandlerData<OnKeyUpFunc>(canvasId, func, userData)); 576 keyUpHandlers_.push_back(EventHandlerData<OnKeyUpFunc>(canvasId, func, userData));
577 }
578
579 // SDL ONLY
580 void GuiAdapter::SetGenericSdlEventCallback(
581 std::string canvasId, void* userData, bool capture, OnSdlEventCallback func)
582 {
583 sdlEventHandlers_.push_back(EventHandlerData<OnSdlEventCallback>(canvasId, func, userData));
580 } 584 }
581 585
582 // SDL ONLY 586 // SDL ONLY
583 void GuiAdapter::OnAnimationFrame() 587 void GuiAdapter::OnAnimationFrame()
584 { 588 {
608 (*(resizeHandlers_[i].func))( 612 (*(resizeHandlers_[i].func))(
609 resizeHandlers_[i].canvasName, nullptr, width, height, resizeHandlers_[i].userData); 613 resizeHandlers_[i].canvasName, nullptr, width, height, resizeHandlers_[i].userData);
610 } 614 }
611 } 615 }
612 616
617
618
619 void GuiAdapter::OnSdlGenericEvent(const SDL_Event& sdlEvent)
620 {
621 // Events related to a window are only sent to the related canvas
622 // User events are sent to everyone (we can't filter them here)
623
624 /*
625 SDL_WindowEvent SDL_WINDOWEVENT
626 SDL_KeyboardEvent SDL_KEYDOWN
627 SDL_KEYUP
628 SDL_TextEditingEvent SDL_TEXTEDITING
629 SDL_TextInputEvent SDL_TEXTINPUT
630 SDL_MouseMotionEvent SDL_MOUSEMOTION
631 SDL_MouseButtonEvent SDL_MOUSEBUTTONDOWN
632 SDL_MOUSEBUTTONUP
633 SDL_MouseWheelEvent SDL_MOUSEWHEEL
634 SDL_UserEvent SDL_USEREVENT through ::SDL_LASTEVENT-1
635 */
636
637 // if this string is left empty, it means the message will be sent to
638 // all widgets.
639 // otherwise, it contains the originating message window title
640
641 std::string windowTitle;
642 uint32_t windowId = 0;
643
644 if (sdlEvent.type == SDL_WINDOWEVENT)
645 windowId = sdlEvent.window.windowID;
646 else if (sdlEvent.type == SDL_KEYDOWN || sdlEvent.type == SDL_KEYUP)
647 windowId = sdlEvent.key.windowID;
648 else if (sdlEvent.type == SDL_TEXTEDITING)
649 windowId = sdlEvent.edit.windowID;
650 else if (sdlEvent.type == SDL_TEXTINPUT)
651 windowId = sdlEvent.text.windowID;
652 else if (sdlEvent.type == SDL_MOUSEMOTION)
653 windowId = sdlEvent.motion.windowID;
654 else if (sdlEvent.type == SDL_MOUSEBUTTONDOWN || sdlEvent.type == SDL_MOUSEBUTTONUP)
655 windowId = sdlEvent.button.windowID;
656 else if (sdlEvent.type == SDL_MOUSEWHEEL)
657 windowId = sdlEvent.wheel.windowID;
658 else if (sdlEvent.type >= SDL_USEREVENT && sdlEvent.type <= (SDL_LASTEVENT-1))
659 windowId = sdlEvent.user.windowID;
660
661 if (windowId != 0)
662 {
663 SDL_Window* sdlWindow = SDL_GetWindowFromID(windowId);
664 ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowId << "\" is not a valid SDL window ID!");
665 const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow);
666 ORTHANC_ASSERT(windowTitleSz != NULL, "Window ID \"" << windowId << "\" has a NULL window title!");
667 windowTitle = windowTitleSz;
668 ORTHANC_ASSERT(windowTitle != "", "Window ID \"" << windowId << "\" has an empty window title!");
669 }
670
671 for (size_t i = 0; i < sdlEventHandlers_.size(); i++)
672 {
673 // normally, the handlers return a bool indicating whether they
674 // have handled the event or not, but we don't really care about this
675 std::string& canvasName = sdlEventHandlers_[i].canvasName;
676
677 bool sendEvent = true;
678
679 if (windowTitle != "" && (canvasName != windowTitle))
680 sendEvent = false;
681
682 if (sendEvent)
683 {
684 auto func = sdlEventHandlers_[i].func;
685 (*func)(canvasName, sdlEvent, sdlEventHandlers_[i].userData);
686 }
687 }
688 }
689
613 // SDL ONLY 690 // SDL ONLY
614 void GuiAdapter::OnMouseWheelEvent(uint32_t windowID, const GuiAdapterWheelEvent& event) 691 void GuiAdapter::OnMouseWheelEvent(uint32_t windowID, const GuiAdapterWheelEvent& event)
615 { 692 {
616
617 // the SDL window name IS the canvas name ("canvas" is used because this lib 693 // the SDL window name IS the canvas name ("canvas" is used because this lib
618 // is designed for Wasm 694 // is designed for Wasm
619 SDL_Window* sdlWindow = SDL_GetWindowFromID(windowID); 695 SDL_Window* sdlWindow = SDL_GetWindowFromID(windowID);
620 ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowID << "\" is not a valid SDL window ID!"); 696 ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowID << "\" is not a valid SDL window ID!");
621 697
729 break; 805 break;
730 default: 806 default:
731 ORTHANC_ASSERT(false, "Wrong event.type: " << event.type << " in GuiAdapter::OnMouseEvent(...)"); 807 ORTHANC_ASSERT(false, "Wrong event.type: " << event.type << " in GuiAdapter::OnMouseEvent(...)");
732 break; 808 break;
733 } 809 }
734
735 ////boost::shared_ptr<IGuiAdapterWidget> GetWidgetFromWindowId();
736 //boost::shared_ptr<IGuiAdapterWidget> foundWidget;
737 //VisitWidgets([foundWidget, windowID](auto widget)
738 // {
739 // if (widget->GetSdlWindowID() == windowID)
740 // foundWidget = widget;
741 // });
742 //ORTHANC_ASSERT(foundWidget, "WindowID " << windowID << " was not found in the registered widgets!");
743 //if(foundWidget)
744 // foundWidget->
745 } 810 }
746 } 811 }
747 812
748 813
749 // extern void Debug_SetContextToBeKilled(std::string title); 814 // extern void Debug_SetContextToBeKilled(std::string title);
774 type, severity, message); 839 type, severity, message);
775 } 840 }
776 } 841 }
777 # endif 842 # endif
778 843
844 #if 0
845 // TODO: remove this when generic sdl event handlers are implemented in
846 // the VolumeSlicerWidget
847 // SDL ONLY
848 bool GuiAdapter::IsSdlViewPortRefreshEvent(const SDL_Event& event) const
849 {
850 SDL_Window* sdlWindow = SDL_GetWindowFromID(event.window.windowID);
851
852 ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << event.window.windowID << "\" is not a valid SDL window ID!");
853
854 const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow);
855
856 // now we need to find the VolumeSlicerWidget from from the canvas name!
857 // (and retrieve the SdlViewport)
858 boost::shared_ptr<IGuiAdapterWidget> foundWidget;
859 VisitWidgets([&foundWidget, windowTitleSz](auto widget)
860 {
861 if (widget->GetCanvasIdentifier() == std::string(windowTitleSz))
862 foundWidget = widget;
863 });
864 ORTHANC_ASSERT(foundWidget, "The window named: \"" << windowTitleSz << "\" was not found in the registered widgets!");
865 return foundWidget->GetSdlViewport().IsRefreshEvent(event);
866 }
867 #endif
868
779 // SDL ONLY 869 // SDL ONLY
780 void GuiAdapter::Run(GuiAdapterRunFunc func, void* cookie) 870 void GuiAdapter::Run(GuiAdapterRunFunc func, void* cookie)
781 { 871 {
782 #if 1 872 #if 1
783 // TODO: MAKE THIS DYNAMIC !!! See SdlOpenGLViewport vs Cairo in ViewportWrapper 873 // TODO: MAKE THIS DYNAMIC !!! See SdlOpenGLViewport vs Cairo in ViewportWrapper
798 if(func != NULL) 888 if(func != NULL)
799 (*func)(cookie); 889 (*func)(cookie);
800 OnAnimationFrame(); // in SDL we must call it 890 OnAnimationFrame(); // in SDL we must call it
801 } 891 }
802 892
803 SDL_Event event; 893 while (!stop)
804
805 while (!stop && SDL_PollEvent(&event))
806 { 894 {
807 // TODO: lock all viewports here! (use a scoped object) 895 std::vector<SDL_Event> sdlEvents;
808 896 std::map<Uint32,SDL_Event> userEventsMap;
809 if (event.type == SDL_QUIT) 897
898 SDL_Event sdlEvent;
899
900 // FIRST: collect all pending events
901 while (SDL_PollEvent(&sdlEvent) != 0)
810 { 902 {
811 // TODO: call exit callbacks here 903 if ( (sdlEvent.type >= SDL_USEREVENT) &&
812 stop = true; 904 (sdlEvent.type <= SDL_USEREVENT) )
813 break; 905 {
906 // we don't want to have multiple events with the same event.type
907 userEventsMap[sdlEvent.type] = sdlEvent;
908 }
909 else
910 {
911 sdlEvents.push_back(sdlEvent);
912 }
814 } 913 }
815 else if ((event.type == SDL_MOUSEMOTION) || 914
816 (event.type == SDL_MOUSEBUTTONDOWN) || 915 // SECOND: collect all user events
817 (event.type == SDL_MOUSEBUTTONUP)) 916 for (auto& it : userEventsMap)
917 sdlEvents.push_back(it.second);
918
919 // now process the events
920 for(const SDL_Event& sdlEvent : sdlEvents)
818 { 921 {
819 int scancodeCount = 0; 922 // TODO: lock all viewports here! (use a scoped object)
820 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); 923
821 bool ctrlPressed(false); 924 if (sdlEvent.type == SDL_QUIT)
822 bool shiftPressed(false);
823 bool altPressed(false);
824
825 if (SDL_SCANCODE_LCTRL < scancodeCount && keyboardState[SDL_SCANCODE_LCTRL])
826 ctrlPressed = true;
827 if (SDL_SCANCODE_RCTRL < scancodeCount && keyboardState[SDL_SCANCODE_RCTRL])
828 ctrlPressed = true;
829 if (SDL_SCANCODE_LSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_LSHIFT])
830 shiftPressed = true;
831 if (SDL_SCANCODE_RSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_RSHIFT])
832 shiftPressed = true;
833 if (SDL_SCANCODE_LALT < scancodeCount && keyboardState[SDL_SCANCODE_LALT])
834 altPressed = true;
835
836 GuiAdapterMouseEvent dest;
837 ConvertFromPlatform(dest, ctrlPressed, shiftPressed, altPressed, event);
838 OnMouseEvent(event.window.windowID, dest);
839 #if 0
840 // for reference, how to create trackers
841 if (tracker)
842 { 925 {
843 PointerEvent e; 926 // TODO: call exit callbacks here
844 e.AddPosition(compositor.GetPixelCenterCoordinates(
845 event.button.x, event.button.y));
846 tracker->PointerMove(e);
847 }
848 #endif
849 }
850 else if (event.type == SDL_MOUSEWHEEL)
851 {
852
853 int scancodeCount = 0;
854 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount);
855 bool ctrlPressed(false);
856 bool shiftPressed(false);
857 bool altPressed(false);
858
859 if (SDL_SCANCODE_LCTRL < scancodeCount && keyboardState[SDL_SCANCODE_LCTRL])
860 ctrlPressed = true;
861 if (SDL_SCANCODE_RCTRL < scancodeCount && keyboardState[SDL_SCANCODE_RCTRL])
862 ctrlPressed = true;
863 if (SDL_SCANCODE_LSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_LSHIFT])
864 shiftPressed = true;
865 if (SDL_SCANCODE_RSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_RSHIFT])
866 shiftPressed = true;
867 if (SDL_SCANCODE_LALT < scancodeCount && keyboardState[SDL_SCANCODE_LALT])
868 altPressed = true;
869
870 GuiAdapterWheelEvent dest;
871 ConvertFromPlatform(dest, ctrlPressed, shiftPressed, altPressed, event);
872 OnMouseWheelEvent(event.window.windowID, dest);
873
874 //KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount);
875
876 //int x, y;
877 //SDL_GetMouseState(&x, &y);
878
879 //if (event.wheel.y > 0)
880 //{
881 // locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers);
882 //}
883 //else if (event.wheel.y < 0)
884 //{
885 // locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers);
886 //}
887 }
888 else if (event.type == SDL_WINDOWEVENT &&
889 (event.window.event == SDL_WINDOWEVENT_RESIZED ||
890 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED))
891 {
892 #if 0
893 tracker.reset();
894 #endif
895 OnResize(event.window.data1, event.window.data2);
896 }
897 else if (event.type == SDL_KEYDOWN && event.key.repeat == 0 /* Ignore key bounce */)
898 {
899 switch (event.key.keysym.sym)
900 {
901 case SDLK_f:
902 // window.GetWindow().ToggleMaximize(); //TODO: move to particular handler
903 break;
904
905 // This commented out code was used to debug the context
906 // loss/restoring code (2019-08-10)
907 // case SDLK_k:
908 // {
909 // SDL_Window* window = SDL_GetWindowFromID(event.window.windowID);
910 // std::string windowTitle(SDL_GetWindowTitle(window));
911 // Debug_SetContextToBeKilled(windowTitle);
912 // }
913 // break;
914 // case SDLK_l:
915 // {
916 // SDL_Window* window = SDL_GetWindowFromID(event.window.windowID);
917 // std::string windowTitle(SDL_GetWindowTitle(window));
918 // Debug_SetContextToBeRestored(windowTitle);
919 // }
920 // break;
921
922 case SDLK_q:
923 stop = true; 927 stop = true;
924 break; 928 break;
925
926 default:
927 GuiAdapterKeyboardEvent dest;
928 ConvertFromPlatform(dest, event);
929 OnKeyboardEvent(event.window.windowID, dest);
930 break;
931 } 929 }
930 else if ((sdlEvent.type == SDL_MOUSEMOTION) ||
931 (sdlEvent.type == SDL_MOUSEBUTTONDOWN) ||
932 (sdlEvent.type == SDL_MOUSEBUTTONUP))
933 {
934 int scancodeCount = 0;
935 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount);
936 bool ctrlPressed(false);
937 bool shiftPressed(false);
938 bool altPressed(false);
939
940 if (SDL_SCANCODE_LCTRL < scancodeCount && keyboardState[SDL_SCANCODE_LCTRL])
941 ctrlPressed = true;
942 if (SDL_SCANCODE_RCTRL < scancodeCount && keyboardState[SDL_SCANCODE_RCTRL])
943 ctrlPressed = true;
944 if (SDL_SCANCODE_LSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_LSHIFT])
945 shiftPressed = true;
946 if (SDL_SCANCODE_RSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_RSHIFT])
947 shiftPressed = true;
948 if (SDL_SCANCODE_LALT < scancodeCount && keyboardState[SDL_SCANCODE_LALT])
949 altPressed = true;
950
951 GuiAdapterMouseEvent dest;
952 ConvertFromPlatform(dest, ctrlPressed, shiftPressed, altPressed, sdlEvent);
953 OnMouseEvent(sdlEvent.window.windowID, dest);
954 #if 0
955 // for reference, how to create trackers
956 if (tracker)
957 {
958 PointerEvent e;
959 e.AddPosition(compositor.GetPixelCenterCoordinates(
960 sdlEvent.button.x, sdlEvent.button.y));
961 tracker->PointerMove(e);
962 }
963 #endif
964 }
965 else if (sdlEvent.type == SDL_MOUSEWHEEL)
966 {
967
968 int scancodeCount = 0;
969 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount);
970 bool ctrlPressed(false);
971 bool shiftPressed(false);
972 bool altPressed(false);
973
974 if (SDL_SCANCODE_LCTRL < scancodeCount && keyboardState[SDL_SCANCODE_LCTRL])
975 ctrlPressed = true;
976 if (SDL_SCANCODE_RCTRL < scancodeCount && keyboardState[SDL_SCANCODE_RCTRL])
977 ctrlPressed = true;
978 if (SDL_SCANCODE_LSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_LSHIFT])
979 shiftPressed = true;
980 if (SDL_SCANCODE_RSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_RSHIFT])
981 shiftPressed = true;
982 if (SDL_SCANCODE_LALT < scancodeCount && keyboardState[SDL_SCANCODE_LALT])
983 altPressed = true;
984
985 GuiAdapterWheelEvent dest;
986 ConvertFromPlatform(dest, ctrlPressed, shiftPressed, altPressed, sdlEvent);
987 OnMouseWheelEvent(sdlEvent.window.windowID, dest);
988
989 //KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount);
990
991 //int x, y;
992 //SDL_GetMouseState(&x, &y);
993
994 //if (sdlEvent.wheel.y > 0)
995 //{
996 // locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers);
997 //}
998 //else if (sdlEvent.wheel.y < 0)
999 //{
1000 // locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers);
1001 //}
1002 }
1003 else if (sdlEvent.type == SDL_WINDOWEVENT &&
1004 (sdlEvent.window.event == SDL_WINDOWEVENT_RESIZED ||
1005 sdlEvent.window.event == SDL_WINDOWEVENT_SIZE_CHANGED))
1006 {
1007 #if 0
1008 tracker.reset();
1009 #endif
1010 OnResize(sdlEvent.window.data1, sdlEvent.window.data2);
1011 }
1012 else if (sdlEvent.type == SDL_KEYDOWN && sdlEvent.key.repeat == 0 /* Ignore key bounce */)
1013 {
1014 switch (sdlEvent.key.keysym.sym)
1015 {
1016 case SDLK_f:
1017 // window.GetWindow().ToggleMaximize(); //TODO: move to particular handler
1018 break;
1019
1020 // This commented out code was used to debug the context
1021 // loss/restoring code (2019-08-10)
1022 // case SDLK_k:
1023 // {
1024 // SDL_Window* window = SDL_GetWindowFromID(sdlEvent.window.windowID);
1025 // std::string windowTitle(SDL_GetWindowTitle(window));
1026 // Debug_SetContextToBeKilled(windowTitle);
1027 // }
1028 // break;
1029 // case SDLK_l:
1030 // {
1031 // SDL_Window* window = SDL_GetWindowFromID(sdlEvent.window.windowID);
1032 // std::string windowTitle(SDL_GetWindowTitle(window));
1033 // Debug_SetContextToBeRestored(windowTitle);
1034 // }
1035 // break;
1036
1037 case SDLK_q:
1038 stop = true;
1039 break;
1040
1041 default:
1042 GuiAdapterKeyboardEvent dest;
1043 ConvertFromPlatform(dest, sdlEvent);
1044 OnKeyboardEvent(sdlEvent.window.windowID, dest);
1045 break;
1046 }
1047 }
1048
1049 OnSdlGenericEvent(sdlEvent);
932 } 1050 }
933 // HandleApplicationEvent(controller, compositor, event, tracker);
934 } 1051 }
935 1052
936 SDL_Delay(1); 1053 SDL_Delay(1);
937 } 1054 }
938 } 1055 }