1 // Created on: 1998-08-27
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <ViewerTest_EventManager.hxx>
19 #include <AIS_AnimationCamera.hxx>
20 #include <Aspect_DisplayConnection.hxx>
21 #include <AIS_InteractiveContext.hxx>
22 #include <AIS_Shape.hxx>
23 #include <Aspect_Grid.hxx>
25 #include <Message.hxx>
26 #include <ViewerTest_ContinuousRedrawer.hxx>
27 #include <ViewerTest_V3dView.hxx>
28 #include <ViewerTest.hxx>
32 #elif defined(HAVE_XLIB)
33 #include <Xw_Window.hxx>
35 #include <X11/Xutil.h>
36 #elif defined(__EMSCRIPTEN__)
37 #include <Wasm_Window.hxx>
38 #include <emscripten.h>
39 #include <emscripten/html5.h>
41 //=======================================================================
42 //function : onWasmRedrawView
44 //=======================================================================
45 void ViewerTest_EventManager::onWasmRedrawView (void* )
47 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
48 if (!aViewCtrl.IsNull())
50 aViewCtrl->myNbUpdateRequests = 0;
52 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
53 const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
54 if (!aView.IsNull() && !aCtx.IsNull())
56 aViewCtrl->ProcessExpose();
62 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
64 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_EventManager,Standard_Transient)
66 //=======================================================================
67 //function : GlobalViewAnimation
69 //=======================================================================
70 const Handle(AIS_AnimationCamera)& ViewerTest_EventManager::GlobalViewAnimation()
72 static Handle(AIS_AnimationCamera) THE_CAMERA_ANIM = new AIS_AnimationCamera ("ViewerTest_EventManager_ViewAnimation", Handle(V3d_View)());
73 THE_CAMERA_ANIM->SetOwnDuration (0.5);
74 return THE_CAMERA_ANIM;
77 //=======================================================================
78 //function : ViewerTest_EventManager
80 //=======================================================================
81 ViewerTest_EventManager::ViewerTest_EventManager (const Handle(V3d_View)& theView,
82 const Handle(AIS_InteractiveContext)& theCtx)
85 myToPickPnt (Standard_False),
86 myIsTmpContRedraw (Standard_False),
87 myNbUpdateRequests (0)
89 myViewAnimation = GlobalViewAnimation();
91 addActionHotKeys (Aspect_VKey_NavForward, (Standard_UInteger )Aspect_VKey_W,
92 (Standard_UInteger )Aspect_VKey_W | (Standard_UInteger )Aspect_VKeyFlags_SHIFT);
93 addActionHotKeys (Aspect_VKey_NavBackward , (Standard_UInteger )Aspect_VKey_S,
94 (Standard_UInteger )Aspect_VKey_S | (Standard_UInteger )Aspect_VKeyFlags_SHIFT);
95 addActionHotKeys (Aspect_VKey_NavSlideLeft, (Standard_UInteger )Aspect_VKey_A,
96 (Standard_UInteger )Aspect_VKey_A | (Standard_UInteger )Aspect_VKeyFlags_SHIFT);
97 addActionHotKeys (Aspect_VKey_NavSlideRight, (Standard_UInteger )Aspect_VKey_D,
98 (Standard_UInteger )Aspect_VKey_D | (Standard_UInteger )Aspect_VKeyFlags_SHIFT);
99 addActionHotKeys (Aspect_VKey_NavRollCCW, (Standard_UInteger )Aspect_VKey_Q,
100 (Standard_UInteger )Aspect_VKey_Q | (Standard_UInteger )Aspect_VKeyFlags_SHIFT);
101 addActionHotKeys (Aspect_VKey_NavRollCW, (Standard_UInteger )Aspect_VKey_E,
102 (Standard_UInteger )Aspect_VKey_E | (Standard_UInteger )Aspect_VKeyFlags_SHIFT);
104 addActionHotKeys (Aspect_VKey_NavSpeedIncrease, (Standard_UInteger )Aspect_VKey_Plus,
105 (Standard_UInteger )Aspect_VKey_Plus | (Standard_UInteger )Aspect_VKeyFlags_SHIFT,
106 (Standard_UInteger )Aspect_VKey_Equal,
107 (Standard_UInteger )Aspect_VKey_NumpadAdd,
108 (Standard_UInteger )Aspect_VKey_NumpadAdd | (Standard_UInteger )Aspect_VKeyFlags_SHIFT);
109 addActionHotKeys (Aspect_VKey_NavSpeedDecrease, (Standard_UInteger )Aspect_VKey_Minus,
110 (Standard_UInteger )Aspect_VKey_Minus | (Standard_UInteger )Aspect_VKeyFlags_SHIFT,
111 (Standard_UInteger )Aspect_VKey_NumpadSubtract,
112 (Standard_UInteger )Aspect_VKey_NumpadSubtract | (Standard_UInteger )Aspect_VKeyFlags_SHIFT);
114 addActionHotKeys (Aspect_VKey_NavLookUp, (Standard_UInteger )Aspect_VKey_Up);
115 addActionHotKeys (Aspect_VKey_NavLookDown, (Standard_UInteger )Aspect_VKey_Down);
116 addActionHotKeys (Aspect_VKey_NavLookLeft, (Standard_UInteger )Aspect_VKey_Left);
117 addActionHotKeys (Aspect_VKey_NavLookRight, (Standard_UInteger )Aspect_VKey_Right);
118 addActionHotKeys (Aspect_VKey_NavSlideLeft, (Standard_UInteger )Aspect_VKey_Left | (Standard_UInteger)Aspect_VKeyFlags_SHIFT);
119 addActionHotKeys (Aspect_VKey_NavSlideRight, (Standard_UInteger )Aspect_VKey_Right | (Standard_UInteger)Aspect_VKeyFlags_SHIFT);
120 addActionHotKeys (Aspect_VKey_NavSlideUp, (Standard_UInteger )Aspect_VKey_Up | (Standard_UInteger)Aspect_VKeyFlags_SHIFT);
121 addActionHotKeys (Aspect_VKey_NavSlideDown, (Standard_UInteger )Aspect_VKey_Down | (Standard_UInteger)Aspect_VKeyFlags_SHIFT);
123 // window could be actually not yet set to the View
124 //SetupWindowCallbacks (theView->Window());
127 //=======================================================================
128 //function : ~ViewerTest_EventManager
130 //=======================================================================
131 ViewerTest_EventManager::~ViewerTest_EventManager()
133 if (!myViewAnimation.IsNull()
134 && myViewAnimation->View() == myView)
136 myViewAnimation->Stop();
137 myViewAnimation->SetView (Handle(V3d_View)());
141 // =======================================================================
142 // function : UpdateMouseClick
144 // =======================================================================
145 bool ViewerTest_EventManager::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
146 Aspect_VKeyMouse theButton,
147 Aspect_VKeyFlags theModifiers,
148 bool theIsDoubleClick)
150 if (theIsDoubleClick && !myView.IsNull() && !myCtx.IsNull())
152 FitAllAuto (myCtx, myView);
155 return AIS_ViewController::UpdateMouseClick (thePoint, theButton, theModifiers, theIsDoubleClick);
158 //=======================================================================
159 //function : UpdateMouseButtons
161 //=======================================================================
162 bool ViewerTest_EventManager::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
165 && (myView->IsSubview()
166 || !myView->Subviews().IsEmpty()))
168 Handle(V3d_View) aParent = !myView->IsSubview() ? myView : myView->ParentView();
169 Handle(V3d_View) aPickedView = aParent->PickSubview (theDelta.Point);
170 if (!aPickedView.IsNull()
171 && aPickedView != myView)
173 // switch input focus to another subview
174 OnSubviewChanged (myCtx, myView, aPickedView);
179 return AIS_ViewController::UpdateMouseScroll (theDelta);
182 //=======================================================================
183 //function : UpdateMouseButtons
185 //=======================================================================
186 bool ViewerTest_EventManager::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
187 Aspect_VKeyMouse theButtons,
188 Aspect_VKeyFlags theModifiers,
192 && myMousePressed == Aspect_VKeyMouse_NONE
193 && theButtons != Aspect_VKeyMouse_NONE
194 && (myView->IsSubview()
195 || !myView->Subviews().IsEmpty()))
197 Handle(V3d_View) aParent = !myView->IsSubview() ? myView : myView->ParentView();
198 Handle(V3d_View) aPickedView = aParent->PickSubview (thePoint);
199 if (!aPickedView.IsNull()
200 && aPickedView != myView)
202 // switch input focus to another subview
203 OnSubviewChanged (myCtx, myView, aPickedView);
207 SetAllowRotation (!ViewerTest_V3dView::IsCurrentViewIn2DMode());
209 if (theButtons == Aspect_VKeyMouse_LeftButton)
211 if (myToPickPnt && (theModifiers & Aspect_VKeyFlags_CTRL) != 0)
213 Graphic3d_Vec3d anXYZ;
214 myView->Convert (thePoint.x(), thePoint.y(), anXYZ.x(), anXYZ.y(), anXYZ.z());
215 Draw::Set (myPickPntArgVec[0].ToCString(), anXYZ.x());
216 Draw::Set (myPickPntArgVec[1].ToCString(), anXYZ.y());
217 Draw::Set (myPickPntArgVec[2].ToCString(), anXYZ.z());
222 return AIS_ViewController::UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated);
225 //==============================================================================
226 //function : ProcessExpose
228 //==============================================================================
229 void ViewerTest_EventManager::ProcessExpose()
231 if (!myView.IsNull())
233 FlushViewEvents (myCtx, myView, true);
237 //==============================================================================
238 //function : handleViewRedraw
240 //==============================================================================
241 void ViewerTest_EventManager::handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx,
242 const Handle(V3d_View)& theView)
244 AIS_ViewController::handleViewRedraw (theCtx, theView);
246 // On non-Windows platforms Aspect_Window::InvalidateContent() from rendering thread does not work as expected
247 // as in Tcl event loop the new message might go to sleep with new event remaining in queue.
248 // As a workaround - use dedicated background thread to ping Tcl event loop.
249 if (myToAskNextFrame)
251 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
252 if (!myIsTmpContRedraw
253 && (!aRedrawer.IsStarted() || aRedrawer.IsPaused()))
255 myIsTmpContRedraw = true;
256 #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
257 aRedrawer.Start (theView, 60.0);
262 if (++myNbUpdateRequests == 1)
264 #if defined(__EMSCRIPTEN__)
265 emscripten_async_call (onWasmRedrawView, this, -1);
269 else if (myIsTmpContRedraw)
271 myIsTmpContRedraw = false;
272 #if !defined(_WIN32) && !defined(__APPLE__)
273 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
279 //==============================================================================
280 //function : ProcessConfigure
282 //==============================================================================
283 void ViewerTest_EventManager::ProcessConfigure (bool theIsResized)
291 // track window moves to reverse stereo pair
292 && myView->RenderingParams().StereoMode != Graphic3d_StereoMode_RowInterlaced
293 && myView->RenderingParams().StereoMode != Graphic3d_StereoMode_ColumnInterlaced
294 && myView->RenderingParams().StereoMode != Graphic3d_StereoMode_ChessBoard)
299 Handle(V3d_View) aParent = !myView->IsSubview()
301 : myView->ParentView();
302 aParent->Window()->DoResize();
303 aParent->MustBeResized();
304 aParent->Invalidate();
305 for (const Handle(V3d_View)& aChildIter : aParent->Subviews())
307 aChildIter->Window()->DoResize();
308 aChildIter->MustBeResized();
309 aChildIter->Invalidate();
312 FlushViewEvents (myCtx, myView, true);
315 //==============================================================================
316 //function : OnSubviewChanged
318 //==============================================================================
319 void ViewerTest_EventManager::OnSubviewChanged (const Handle(AIS_InteractiveContext)& ,
320 const Handle(V3d_View)& ,
321 const Handle(V3d_View)& theNewView)
323 ViewerTest::ActivateView (theNewView, false);
326 //==============================================================================
327 //function : ProcessInput
329 //==============================================================================
330 void ViewerTest_EventManager::ProcessInput()
337 #if defined(__EMSCRIPTEN__)
338 // Queue onWasmRedrawView() callback to redraw canvas after all user input is flushed by browser.
339 // Redrawing viewer on every single message would be a pointless waste of resources,
340 // as user will see only the last drawn frame due to WebGL implementation details.
341 // -1 in emscripten_async_call() redirects to requestAnimationFrame();
342 // requestPostAnimationFrame() is a better under development alternative.
343 if (++myNbUpdateRequests == 1)
345 emscripten_async_call (onWasmRedrawView, this, -1);
348 // handle synchronously
353 // =======================================================================
354 // function : navigationKeyModifierSwitch
356 // =======================================================================
357 bool ViewerTest_EventManager::navigationKeyModifierSwitch (unsigned int theModifOld,
358 unsigned int theModifNew,
361 bool hasActions = false;
362 for (unsigned int aKeyIter = 0; aKeyIter < Aspect_VKey_ModifiersLower; ++aKeyIter)
364 if (!myKeys.IsKeyDown (aKeyIter))
369 Aspect_VKey anActionOld = Aspect_VKey_UNKNOWN, anActionNew = Aspect_VKey_UNKNOWN;
370 myNavKeyMap.Find (aKeyIter | theModifOld, anActionOld);
371 myNavKeyMap.Find (aKeyIter | theModifNew, anActionNew);
372 if (anActionOld == anActionNew)
377 if (anActionOld != Aspect_VKey_UNKNOWN)
379 myKeys.KeyUp (anActionOld, theTimeStamp);
381 if (anActionNew != Aspect_VKey_UNKNOWN)
384 myKeys.KeyDown (anActionNew, theTimeStamp);
390 //=======================================================================
393 //=======================================================================
394 void ViewerTest_EventManager::KeyDown (Aspect_VKey theKey,
398 const unsigned int aModifOld = myKeys.Modifiers();
399 AIS_ViewController::KeyDown (theKey, theTime, thePressure);
401 const unsigned int aModifNew = myKeys.Modifiers();
402 if (aModifNew != aModifOld
403 && navigationKeyModifierSwitch (aModifOld, aModifNew, theTime))
405 // modifier key just pressed
408 Aspect_VKey anAction = Aspect_VKey_UNKNOWN;
409 if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction)
410 && anAction != Aspect_VKey_UNKNOWN)
412 AIS_ViewController::KeyDown (anAction, theTime, thePressure);
416 //=======================================================================
419 //=======================================================================
420 void ViewerTest_EventManager::KeyUp (Aspect_VKey theKey,
423 const unsigned int aModifOld = myKeys.Modifiers();
424 AIS_ViewController::KeyUp (theKey, theTime);
426 Aspect_VKey anAction = Aspect_VKey_UNKNOWN;
427 if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction)
428 && anAction != Aspect_VKey_UNKNOWN)
430 AIS_ViewController::KeyUp (anAction, theTime);
431 ProcessKeyPress (anAction);
434 const unsigned int aModifNew = myKeys.Modifiers();
435 if (aModifNew != aModifOld
436 && navigationKeyModifierSwitch (aModifOld, aModifNew, theTime))
438 // modifier key released
441 ProcessKeyPress (theKey | aModifNew);
444 //==============================================================================
445 //function : ProcessKeyPress
447 //==============================================================================
448 void ViewerTest_EventManager::ProcessKeyPress (Aspect_VKey theKey)
458 case Aspect_VKey_Backspace: // AXO
460 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
462 myView->SetProj(V3d_XposYnegZpos);
468 if (myCtx->NbSelected() > 0)
470 myCtx->FitSelected (myView);
478 case Aspect_VKey_H: // HLR
480 std::cout << "HLR\n";
481 myView->SetComputedMode (!myView->ComputedMode());
485 case Aspect_VKey_P: // Type of HLR
487 myCtx->DefaultDrawer()->SetTypeOfHLR (myCtx->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo
490 if (myCtx->NbSelected() == 0)
492 AIS_ListOfInteractive aListOfShapes;
493 myCtx->DisplayedObjects (aListOfShapes);
494 for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
496 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value()))
498 aShape->SetTypeOfHLR (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo
500 : Prs3d_TOH_PolyAlgo);
501 myCtx->Redisplay (aShape, Standard_False);
507 for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected())
509 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (myCtx->SelectedInteractive()))
511 aShape->SetTypeOfHLR (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo
513 : Prs3d_TOH_PolyAlgo);
514 myCtx->Redisplay (aShape, Standard_False);
518 myCtx->UpdateCurrentViewer();
521 case (Standard_UInteger)Aspect_VKey_S | (Standard_UInteger)Aspect_VKeyFlags_CTRL:
522 case (Standard_UInteger)Aspect_VKey_W | (Standard_UInteger)Aspect_VKeyFlags_CTRL:
524 Standard_Integer aDispMode = AIS_Shaded;
525 if (theKey == ((Standard_UInteger)Aspect_VKey_S | (Standard_UInteger)Aspect_VKeyFlags_CTRL))
527 aDispMode = AIS_Shaded;
528 std::cout << "setup Shaded display mode\n";
532 aDispMode = AIS_WireFrame;
533 std::cout << "setup WireFrame display mode\n";
536 if (myCtx->NbSelected() == 0)
538 myCtx->SetDisplayMode (aDispMode, true);
542 for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected())
544 myCtx->SetDisplayMode (myCtx->SelectedInteractive(), aDispMode, false);
546 myCtx->UpdateCurrentViewer();
550 case Aspect_VKey_U: // Unset display mode
552 std::cout << "reset display mode to defaults\n";
553 if (myCtx->NbSelected() == 0)
555 myCtx->SetDisplayMode (AIS_WireFrame, true);
559 for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected())
561 myCtx->UnsetDisplayMode (myCtx->SelectedInteractive(), false);
563 myCtx->UpdateCurrentViewer();
569 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
571 myView->SetProj (V3d_TypeOfOrientation_Zup_Top);
577 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
579 myView->SetProj (V3d_TypeOfOrientation_Zup_Bottom);
585 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
587 myView->SetProj (V3d_TypeOfOrientation_Zup_Left);
593 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
595 myView->SetProj (V3d_TypeOfOrientation_Zup_Right);
599 case Aspect_VKey_Comma:
601 myCtx->HilightNextDetected (myView);
604 case Aspect_VKey_Period:
606 myCtx->HilightPreviousDetected (myView);
609 case Aspect_VKey_Slash:
610 case Aspect_VKey_NumpadDivide:
612 Handle(Graphic3d_Camera) aCamera = myView->Camera();
613 if (aCamera->IsStereo())
615 aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
620 case Aspect_VKey_NumpadMultiply:
622 Handle(Graphic3d_Camera) aCamera = myView->Camera();
623 if (aCamera->IsStereo())
625 aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
630 case Aspect_VKey_Delete:
633 && myCtx->NbSelected() > 0)
635 Draw_Interprete ("verase");
639 case Aspect_VKey_Escape:
642 && ViewerTest_EventManager::ToCloseViewOnEscape())
644 Draw_Interprete (ViewerTest_EventManager::ToExitOnCloseView() ? "exit" : "vclose");
648 case Aspect_VKey_NavSpeedDecrease:
649 case Aspect_VKey_NavSpeedIncrease:
651 // handle slide speed
652 float aNewSpeed = theKey == Aspect_VKey_NavSpeedDecrease
653 ? myWalkSpeedRelative * 0.5f
654 : myWalkSpeedRelative * 2.0f;
655 if (aNewSpeed >= 0.00001f
656 && aNewSpeed <= 10.0f)
658 if (Abs (aNewSpeed - 0.1f) < 0.001f)
662 myWalkSpeedRelative = aNewSpeed;
668 if (theKey >= Aspect_VKey_0
669 && theKey <= Aspect_VKey_7)
671 const Standard_Integer aSelMode = theKey - Aspect_VKey_0;
672 bool toEnable = true;
675 AIS_ListOfInteractive aPrsList;
676 myCtx->DisplayedObjects (aPrsList);
677 for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
679 TColStd_ListOfInteger aModes;
680 myCtx->ActivatedModes (aPrsIter.Value(), aModes);
681 for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
683 if (aModeIter.Value() == aSelMode)
690 TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
691 Draw_Interprete (aCmd.ToCString());
695 #if defined(__EMSCRIPTEN__)
696 //! Handle browser window resize event.
697 static EM_BOOL onResizeCallback (int theEventType, const EmscriptenUiEvent* theEvent, void* )
699 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
700 if (!aViewCtrl.IsNull()
701 && !ViewerTest::CurrentView().IsNull())
703 Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window());
704 return aWindow->ProcessUiEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
709 //! Update canvas bounding rectangle.
710 EM_JS(void, occJSUpdateBoundingClientRect, (), {
711 Module._myCanvasRect = Module.canvas.getBoundingClientRect();
714 //! Get canvas bounding top.
715 EM_JS(int, occJSGetBoundingClientTop, (), {
716 return Math.round(Module._myCanvasRect.top);
719 //! Get canvas bounding left.
720 EM_JS(int, occJSGetBoundingClientLeft, (), {
721 return Math.round(Module._myCanvasRect.left);
724 //! Handle mouse input event.
725 static EM_BOOL onWasmMouseCallback (int theEventType, const EmscriptenMouseEvent* theEvent, void* )
727 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
728 if (!aViewCtrl.IsNull()
729 && !ViewerTest::CurrentView().IsNull())
731 Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window());
732 if (theEventType == EMSCRIPTEN_EVENT_MOUSEMOVE
733 || theEventType == EMSCRIPTEN_EVENT_MOUSEUP)
735 // these events are bound to EMSCRIPTEN_EVENT_TARGET_WINDOW, and coordinates should be converted
736 occJSUpdateBoundingClientRect();
737 EmscriptenMouseEvent anEvent = *theEvent;
738 anEvent.targetX -= occJSGetBoundingClientLeft();
739 anEvent.targetY -= occJSGetBoundingClientTop();
740 aWindow->ProcessMouseEvent (*aViewCtrl, theEventType, &anEvent);
744 return aWindow->ProcessMouseEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
749 //! Handle mouse wheel event.
750 static EM_BOOL onWasmWheelCallback (int theEventType, const EmscriptenWheelEvent* theEvent, void* )
752 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
753 if (!aViewCtrl.IsNull()
754 && !ViewerTest::CurrentView().IsNull())
756 Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window());
757 return aWindow->ProcessWheelEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
762 //! Handle touch input event.
763 static EM_BOOL onWasmTouchCallback (int theEventType, const EmscriptenTouchEvent* theEvent, void* )
765 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
766 if (!aViewCtrl.IsNull()
767 && !ViewerTest::CurrentView().IsNull())
769 Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window());
770 return aWindow->ProcessTouchEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
775 //! Handle keyboard input event.
776 static EM_BOOL onWasmKeyCallback (int theEventType, const EmscriptenKeyboardEvent* theEvent, void* )
778 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
779 if (!aViewCtrl.IsNull()
780 && !ViewerTest::CurrentView().IsNull())
782 Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window());
783 aWindow->ProcessKeyEvent (*aViewCtrl, theEventType, theEvent);
789 //! Handle focus change event.
790 static EM_BOOL onWasmFocusCallback (int theEventType, const EmscriptenFocusEvent* theEvent, void*)
792 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
793 if (!aViewCtrl.IsNull()
794 && !ViewerTest::CurrentView().IsNull())
796 Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window());
797 return aWindow->ProcessFocusEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
803 // ==============================================================================
804 // function : SetupWindowCallbacks
806 // ==============================================================================
807 void ViewerTest_EventManager::SetupWindowCallbacks (const Handle(Aspect_Window)& theWin)
811 #elif defined(HAVE_XLIB)
813 Window anXWin = (Window )theWin->NativeHandle();
814 Display* anXDisplay = (Display* )theWin->DisplayConnection()->GetDisplayAspect();
815 XSynchronize (anXDisplay, 1);
817 // X11 : For keyboard on SUN
819 memset (&aWmHints, 0, sizeof(aWmHints));
820 aWmHints.flags = InputHint;
822 XSetWMHints (anXDisplay, anXWin, &aWmHints);
824 XSelectInput (anXDisplay, anXWin,
825 ExposureMask | KeyPressMask | KeyReleaseMask
826 | ButtonPressMask | ButtonReleaseMask
827 | StructureNotifyMask
829 | Button1MotionMask | Button2MotionMask
830 | Button3MotionMask | FocusChangeMask);
831 Atom aDeleteWindowAtom = theWin->DisplayConnection()->GetAtom (Aspect_XA_DELETE_WINDOW);
832 XSetWMProtocols (anXDisplay, anXWin, &aDeleteWindowAtom, 1);
834 XSynchronize (anXDisplay, 0);
835 #elif defined(__EMSCRIPTEN__)
836 Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (theWin);
837 if (aWindow->CanvasId().IsEmpty()
838 || aWindow->CanvasId() == "#")
840 Message::SendFail ("Error: unable registering callbacks to Module.canvas");
844 const char* aTargetId = aWindow->CanvasId().ToCString();
845 const EM_BOOL toUseCapture = EM_TRUE;
846 void* anOpaque = NULL; //this; // unused
848 // make sure to clear previously set listeners (e.g. created by another ViewerTest_EventManager instance)
849 emscripten_html5_remove_all_event_listeners();
851 // resize event implemented only for a window by browsers,
852 // so that if web application changes canvas size by other means it should use another way to tell OCCT about resize
853 emscripten_set_resize_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onResizeCallback);
855 // bind these events to window to track mouse movements outside of canvas
856 //emscripten_set_mouseup_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
857 //emscripten_set_mousemove_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
858 //emscripten_set_mouseleave_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
859 emscripten_set_mouseup_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onWasmMouseCallback);
860 emscripten_set_mousemove_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onWasmMouseCallback);
862 emscripten_set_mousedown_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
863 emscripten_set_dblclick_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
864 emscripten_set_click_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
865 emscripten_set_mouseenter_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
866 emscripten_set_wheel_callback (aTargetId, anOpaque, toUseCapture, onWasmWheelCallback);
868 emscripten_set_touchstart_callback (aTargetId, anOpaque, toUseCapture, onWasmTouchCallback);
869 emscripten_set_touchend_callback (aTargetId, anOpaque, toUseCapture, onWasmTouchCallback);
870 emscripten_set_touchmove_callback (aTargetId, anOpaque, toUseCapture, onWasmTouchCallback);
871 emscripten_set_touchcancel_callback(aTargetId, anOpaque, toUseCapture, onWasmTouchCallback);
873 // keyboard input requires a focusable element or EMSCRIPTEN_EVENT_TARGET_WINDOW
874 emscripten_set_keydown_callback (aTargetId, anOpaque, toUseCapture, onWasmKeyCallback);
875 emscripten_set_keyup_callback (aTargetId, anOpaque, toUseCapture, onWasmKeyCallback);
876 //emscripten_set_focus_callback (aTargetId, anOpaque, toUseCapture, onWasmFocusCallback);
877 //emscripten_set_focusin_callback (aTargetId, anOpaque, toUseCapture, onWasmFocusCallback);
878 emscripten_set_focusout_callback (aTargetId, anOpaque, toUseCapture, onWasmFocusCallback);