// Created on: 1998-08-27 // Created by: Robert COUBLANC // Copyright (c) 1998-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include #include #include #include #include #include #include #if defined(_WIN32) // #elif defined(HAVE_XLIB) #include #include #include #elif defined(__EMSCRIPTEN__) #include #include #include //! Callback flushing events and redrawing the WebGL canvas. static void onWasmRedrawView (void* ) { Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager(); const Handle(V3d_View)& aView = ViewerTest::CurrentView(); const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext(); if (!aViewCtrl.IsNull() && !aView.IsNull() && !aCtx.IsNull()) { aViewCtrl->ProcessExpose(); } } #endif Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand); IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_EventManager,Standard_Transient) //======================================================================= //function : GlobalViewAnimation //purpose : //======================================================================= const Handle(AIS_AnimationCamera)& ViewerTest_EventManager::GlobalViewAnimation() { static Handle(AIS_AnimationCamera) THE_CAMERA_ANIM = new AIS_AnimationCamera ("ViewerTest_EventManager_ViewAnimation", Handle(V3d_View)()); THE_CAMERA_ANIM->SetOwnDuration (0.5); return THE_CAMERA_ANIM; } //======================================================================= //function : ViewerTest_EventManager //purpose : //======================================================================= ViewerTest_EventManager::ViewerTest_EventManager (const Handle(V3d_View)& theView, const Handle(AIS_InteractiveContext)& theCtx) : myCtx (theCtx), myView (theView), myToPickPnt (Standard_False), myIsTmpContRedraw (Standard_False), myUpdateRequests (0) { myViewAnimation = GlobalViewAnimation(); addActionHotKeys (Aspect_VKey_NavForward, Aspect_VKey_W, Aspect_VKey_W | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavBackward , Aspect_VKey_S, Aspect_VKey_S | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavSlideLeft, Aspect_VKey_A, Aspect_VKey_A | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavSlideRight, Aspect_VKey_D, Aspect_VKey_D | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavRollCCW, Aspect_VKey_Q, Aspect_VKey_Q | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavRollCW, Aspect_VKey_E, Aspect_VKey_E | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavSpeedIncrease, Aspect_VKey_Plus, Aspect_VKey_Plus | Aspect_VKeyFlags_SHIFT, Aspect_VKey_Equal, Aspect_VKey_NumpadAdd, Aspect_VKey_NumpadAdd | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavSpeedDecrease, Aspect_VKey_Minus, Aspect_VKey_Minus | Aspect_VKeyFlags_SHIFT, Aspect_VKey_NumpadSubtract, Aspect_VKey_NumpadSubtract | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavLookUp, Aspect_VKey_Up); addActionHotKeys (Aspect_VKey_NavLookDown, Aspect_VKey_Down); addActionHotKeys (Aspect_VKey_NavLookLeft, Aspect_VKey_Left); addActionHotKeys (Aspect_VKey_NavLookRight, Aspect_VKey_Right); addActionHotKeys (Aspect_VKey_NavSlideLeft, Aspect_VKey_Left | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavSlideRight, Aspect_VKey_Right | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavSlideUp, Aspect_VKey_Up | Aspect_VKeyFlags_SHIFT); addActionHotKeys (Aspect_VKey_NavSlideDown, Aspect_VKey_Down | Aspect_VKeyFlags_SHIFT); // window could be actually not yet set to the View //SetupWindowCallbacks (theView->Window()); } //======================================================================= //function : ~ViewerTest_EventManager //purpose : //======================================================================= ViewerTest_EventManager::~ViewerTest_EventManager() { if (!myViewAnimation.IsNull() && myViewAnimation->View() == myView) { myViewAnimation->Stop(); myViewAnimation->SetView (Handle(V3d_View)()); } } // ======================================================================= // function : UpdateMouseClick // purpose : // ======================================================================= bool ViewerTest_EventManager::UpdateMouseClick (const Graphic3d_Vec2i& thePoint, Aspect_VKeyMouse theButton, Aspect_VKeyFlags theModifiers, bool theIsDoubleClick) { if (theIsDoubleClick && !myView.IsNull() && !myCtx.IsNull()) { FitAllAuto (myCtx, myView); return true; } return AIS_ViewController::UpdateMouseClick (thePoint, theButton, theModifiers, theIsDoubleClick); } //======================================================================= //function : UpdateMouseButtons //purpose : //======================================================================= bool ViewerTest_EventManager::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint, Aspect_VKeyMouse theButtons, Aspect_VKeyFlags theModifiers, bool theIsEmulated) { SetAllowRotation (!ViewerTest_V3dView::IsCurrentViewIn2DMode()); if (theButtons == Aspect_VKeyMouse_LeftButton) { if (myToPickPnt && (theModifiers & Aspect_VKeyFlags_CTRL) != 0) { Graphic3d_Vec3d anXYZ; myView->Convert (thePoint.x(), thePoint.y(), anXYZ.x(), anXYZ.y(), anXYZ.z()); Draw::Set (myPickPntArgVec[0].ToCString(), anXYZ.x()); Draw::Set (myPickPntArgVec[1].ToCString(), anXYZ.y()); Draw::Set (myPickPntArgVec[2].ToCString(), anXYZ.z()); myToPickPnt = false; } } return AIS_ViewController::UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated); } //============================================================================== //function : ProcessExpose //purpose : //============================================================================== void ViewerTest_EventManager::ProcessExpose() { if (!myView.IsNull()) { FlushViewEvents (myCtx, myView, true); } } //============================================================================== //function : handleViewRedraw //purpose : //============================================================================== void ViewerTest_EventManager::handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx, const Handle(V3d_View)& theView) { myUpdateRequests = 0; AIS_ViewController::handleViewRedraw (theCtx, theView); // On non-Windows platforms Aspect_Window::InvalidateContent() from rendering thread does not work as expected // as in Tcl event loop the new message might go to sleep with new event remaining in queue. // As a workaround - use dedicated background thread to ping Tcl event loop. if (myToAskNextFrame) { ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance(); if (!myIsTmpContRedraw && (!aRedrawer.IsStarted() || aRedrawer.IsPaused())) { myIsTmpContRedraw = true; #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) aRedrawer.Start (theView, 60.0); #endif } // ask more frames ++myUpdateRequests; #if defined(__EMSCRIPTEN__) emscripten_async_call (onWasmRedrawView, this, 0); #endif } else if (myIsTmpContRedraw) { myIsTmpContRedraw = false; #ifndef _WIN32 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance(); aRedrawer.Pause(); #endif } } //============================================================================== //function : ProcessConfigure //purpose : //============================================================================== void ViewerTest_EventManager::ProcessConfigure (bool theIsResized) { if (!myView.IsNull()) { if (!theIsResized // track window moves to reverse stereo pair && myView->RenderingParams().StereoMode != Graphic3d_StereoMode_RowInterlaced && myView->RenderingParams().StereoMode != Graphic3d_StereoMode_ColumnInterlaced && myView->RenderingParams().StereoMode != Graphic3d_StereoMode_ChessBoard) { return; } myView->Window()->DoResize(); myView->MustBeResized(); myView->Invalidate(); FlushViewEvents (myCtx, myView, true); } } //============================================================================== //function : ProcessInput //purpose : //============================================================================== void ViewerTest_EventManager::ProcessInput() { if (myView.IsNull()) { return; } #if defined(__EMSCRIPTEN__) // Queue onWasmRedrawView() callback to redraw canvas after all user input is flushed by browser. // Redrawing viewer on every single message would be a pointless waste of resources, // as user will see only the last drawn frame due to WebGL implementation details. if (++myUpdateRequests == 1) { #if defined(__EMSCRIPTEN__) emscripten_async_call (onWasmRedrawView, this, 0); #endif } #else // handle synchronously ProcessExpose(); #endif } // ======================================================================= // function : navigationKeyModifierSwitch // purpose : // ======================================================================= bool ViewerTest_EventManager::navigationKeyModifierSwitch (unsigned int theModifOld, unsigned int theModifNew, double theTimeStamp) { bool hasActions = false; for (unsigned int aKeyIter = 0; aKeyIter < Aspect_VKey_ModifiersLower; ++aKeyIter) { if (!myKeys.IsKeyDown (aKeyIter)) { continue; } Aspect_VKey anActionOld = Aspect_VKey_UNKNOWN, anActionNew = Aspect_VKey_UNKNOWN; myNavKeyMap.Find (aKeyIter | theModifOld, anActionOld); myNavKeyMap.Find (aKeyIter | theModifNew, anActionNew); if (anActionOld == anActionNew) { continue; } if (anActionOld != Aspect_VKey_UNKNOWN) { myKeys.KeyUp (anActionOld, theTimeStamp); } if (anActionNew != Aspect_VKey_UNKNOWN) { hasActions = true; myKeys.KeyDown (anActionNew, theTimeStamp); } } return hasActions; } //======================================================================= //function : KeyDown //purpose : //======================================================================= void ViewerTest_EventManager::KeyDown (Aspect_VKey theKey, double theTime, double thePressure) { const unsigned int aModifOld = myKeys.Modifiers(); AIS_ViewController::KeyDown (theKey, theTime, thePressure); const unsigned int aModifNew = myKeys.Modifiers(); if (aModifNew != aModifOld && navigationKeyModifierSwitch (aModifOld, aModifNew, theTime)) { // modifier key just pressed } Aspect_VKey anAction = Aspect_VKey_UNKNOWN; if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction) && anAction != Aspect_VKey_UNKNOWN) { AIS_ViewController::KeyDown (anAction, theTime, thePressure); } } //======================================================================= //function : KeyUp //purpose : //======================================================================= void ViewerTest_EventManager::KeyUp (Aspect_VKey theKey, double theTime) { const unsigned int aModifOld = myKeys.Modifiers(); AIS_ViewController::KeyUp (theKey, theTime); Aspect_VKey anAction = Aspect_VKey_UNKNOWN; if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction) && anAction != Aspect_VKey_UNKNOWN) { AIS_ViewController::KeyUp (anAction, theTime); ProcessKeyPress (anAction); } const unsigned int aModifNew = myKeys.Modifiers(); if (aModifNew != aModifOld && navigationKeyModifierSwitch (aModifOld, aModifNew, theTime)) { // modifier key released } ProcessKeyPress (theKey | aModifNew); } //============================================================================== //function : ProcessKeyPress //purpose : //============================================================================== void ViewerTest_EventManager::ProcessKeyPress (Aspect_VKey theKey) { if (myCtx.IsNull() || myView.IsNull()) { return; } switch (theKey) { case Aspect_VKey_Backspace: // AXO { if (!ViewerTest_V3dView::IsCurrentViewIn2DMode()) { myView->SetProj(V3d_XposYnegZpos); } break; } case Aspect_VKey_F: { if (myCtx->NbSelected() > 0) { myCtx->FitSelected (myView); } else { myView->FitAll(); } break; } case Aspect_VKey_H: // HLR { std::cout << "HLR\n"; myView->SetComputedMode (!myView->ComputedMode()); myView->Redraw(); break; } case Aspect_VKey_P: // Type of HLR { myCtx->DefaultDrawer()->SetTypeOfHLR (myCtx->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo ? Prs3d_TOH_PolyAlgo : Prs3d_TOH_Algo); if (myCtx->NbSelected() == 0) { AIS_ListOfInteractive aListOfShapes; myCtx->DisplayedObjects (aListOfShapes); for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next()) { if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value())) { aShape->SetTypeOfHLR (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo); myCtx->Redisplay (aShape, Standard_False); } } } else { for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected()) { if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (myCtx->SelectedInteractive())) { aShape->SetTypeOfHLR (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo); myCtx->Redisplay (aShape, Standard_False); } } } myCtx->UpdateCurrentViewer(); break; } case Aspect_VKey_S | Aspect_VKeyFlags_CTRL: case Aspect_VKey_W | Aspect_VKeyFlags_CTRL: { Standard_Integer aDispMode = AIS_Shaded; if (theKey == (Aspect_VKey_S | Aspect_VKeyFlags_CTRL)) { aDispMode = AIS_Shaded; std::cout << "setup Shaded display mode\n"; } else { aDispMode = AIS_WireFrame; std::cout << "setup WireFrame display mode\n"; } if (myCtx->NbSelected() == 0) { myCtx->SetDisplayMode (aDispMode, true); } else { for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected()) { myCtx->SetDisplayMode (myCtx->SelectedInteractive(), aDispMode, false); } myCtx->UpdateCurrentViewer(); } break; } case Aspect_VKey_U: // Unset display mode { std::cout << "reset display mode to defaults\n"; if (myCtx->NbSelected() == 0) { myCtx->SetDisplayMode (AIS_WireFrame, true); } else { for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected()) { myCtx->UnsetDisplayMode (myCtx->SelectedInteractive(), false); } myCtx->UpdateCurrentViewer(); } break; } case Aspect_VKey_T: { if (!ViewerTest_V3dView::IsCurrentViewIn2DMode()) { myView->SetProj (V3d_TypeOfOrientation_Zup_Top); } break; } case Aspect_VKey_B: { if (!ViewerTest_V3dView::IsCurrentViewIn2DMode()) { myView->SetProj (V3d_TypeOfOrientation_Zup_Bottom); } break; } case Aspect_VKey_L: { if (!ViewerTest_V3dView::IsCurrentViewIn2DMode()) { myView->SetProj (V3d_TypeOfOrientation_Zup_Left); } break; } case Aspect_VKey_R: { if (!ViewerTest_V3dView::IsCurrentViewIn2DMode()) { myView->SetProj (V3d_TypeOfOrientation_Zup_Right); } break; } case Aspect_VKey_Comma: { myCtx->HilightNextDetected (myView); break; } case Aspect_VKey_Period: { myCtx->HilightPreviousDetected (myView); break; } case Aspect_VKey_Slash: case Aspect_VKey_NumpadDivide: { Handle(Graphic3d_Camera) aCamera = myView->Camera(); if (aCamera->IsStereo()) { aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01); myView->Redraw(); } break; } case Aspect_VKey_NumpadMultiply: { Handle(Graphic3d_Camera) aCamera = myView->Camera(); if (aCamera->IsStereo()) { aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01); myView->Redraw(); } break; } case Aspect_VKey_Delete: { if (!myCtx.IsNull() && myCtx->NbSelected() > 0) { Draw_Interprete ("verase"); } break; } case Aspect_VKey_Escape: { if (!myCtx.IsNull() && ViewerTest_EventManager::ToCloseViewOnEscape()) { Draw_Interprete (ViewerTest_EventManager::ToExitOnCloseView() ? "exit" : "vclose"); } break; } case Aspect_VKey_NavSpeedDecrease: case Aspect_VKey_NavSpeedIncrease: { // handle slide speed float aNewSpeed = theKey == Aspect_VKey_NavSpeedDecrease ? myWalkSpeedRelative * 0.5f : myWalkSpeedRelative * 2.0f; if (aNewSpeed >= 0.00001f && aNewSpeed <= 10.0f) { if (Abs (aNewSpeed - 0.1f) < 0.001f) { aNewSpeed = 0.1f; } myWalkSpeedRelative = aNewSpeed; } break; } } if (theKey >= Aspect_VKey_0 && theKey <= Aspect_VKey_7) { const Standard_Integer aSelMode = theKey - Aspect_VKey_0; bool toEnable = true; if (!myCtx.IsNull()) { AIS_ListOfInteractive aPrsList; myCtx->DisplayedObjects (aPrsList); for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next()) { TColStd_ListOfInteger aModes; myCtx->ActivatedModes (aPrsIter.Value(), aModes); for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next()) { if (aModeIter.Value() == aSelMode) { toEnable = false; } } } } TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0"); Draw_Interprete (aCmd.ToCString()); } } #if defined(__EMSCRIPTEN__) //! Handle browser window resize event. static EM_BOOL onResizeCallback (int theEventType, const EmscriptenUiEvent* theEvent, void* ) { Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager(); if (!aViewCtrl.IsNull() && !ViewerTest::CurrentView().IsNull()) { Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window()); return aWindow->ProcessUiEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE; } return EM_FALSE; } //! Handle mouse input event. static EM_BOOL onWasmMouseCallback (int theEventType, const EmscriptenMouseEvent* theEvent, void* ) { Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager(); if (!aViewCtrl.IsNull() && !ViewerTest::CurrentView().IsNull()) { Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window()); return aWindow->ProcessMouseEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE; } return EM_FALSE; } //! Handle mouse wheel event. static EM_BOOL onWasmWheelCallback (int theEventType, const EmscriptenWheelEvent* theEvent, void* ) { Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager(); if (!aViewCtrl.IsNull() && !ViewerTest::CurrentView().IsNull()) { Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window()); return aWindow->ProcessWheelEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE; } return EM_FALSE; } //! Handle touch input event. static EM_BOOL onWasmTouchCallback (int theEventType, const EmscriptenTouchEvent* theEvent, void* ) { Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager(); if (!aViewCtrl.IsNull() && !ViewerTest::CurrentView().IsNull()) { Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window()); return aWindow->ProcessTouchEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE; } return EM_FALSE; } //! Handle keyboard input event. static EM_BOOL onWasmKeyCallback (int theEventType, const EmscriptenKeyboardEvent* theEvent, void* ) { Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager(); if (!aViewCtrl.IsNull() && !ViewerTest::CurrentView().IsNull()) { Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window()); aWindow->ProcessKeyEvent (*aViewCtrl, theEventType, theEvent); return EM_TRUE; } return EM_FALSE; } #endif // ============================================================================== // function : SetupWindowCallbacks // purpose : // ============================================================================== void ViewerTest_EventManager::SetupWindowCallbacks (const Handle(Aspect_Window)& theWin) { #ifdef _WIN32 (void )theWin; #elif defined(HAVE_XLIB) // X11 Window anXWin = (Window )theWin->NativeHandle(); Display* anXDisplay = (Display* )theWin->DisplayConnection()->GetDisplayAspect(); XSynchronize (anXDisplay, 1); // X11 : For keyboard on SUN XWMHints aWmHints; memset (&aWmHints, 0, sizeof(aWmHints)); aWmHints.flags = InputHint; aWmHints.input = 1; XSetWMHints (anXDisplay, anXWin, &aWmHints); XSelectInput (anXDisplay, anXWin, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | PointerMotionMask | Button1MotionMask | Button2MotionMask | Button3MotionMask | FocusChangeMask); Atom aDeleteWindowAtom = theWin->DisplayConnection()->GetAtom (Aspect_XA_DELETE_WINDOW); XSetWMProtocols (anXDisplay, anXWin, &aDeleteWindowAtom, 1); XSynchronize (anXDisplay, 0); #elif defined(__EMSCRIPTEN__) Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (theWin); if (aWindow->CanvasId().IsEmpty() || aWindow->CanvasId() == "#") { Message::SendFail ("Error: unable registering callbacks to Module.canvas"); return; } const char* aTargetId = aWindow->CanvasId().ToCString(); const EM_BOOL toUseCapture = EM_TRUE; void* anOpaque = NULL; //this; // unused // make sure to clear previously set listeners (e.g. created by another ViewerTest_EventManager instance) emscripten_html5_remove_all_event_listeners(); // resize event implemented only for a window by browsers, // so that if web application changes canvas size by other means it should use another way to tell OCCT about resize emscripten_set_resize_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onResizeCallback); emscripten_set_mousedown_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback); emscripten_set_mouseup_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback); emscripten_set_mousemove_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback); emscripten_set_dblclick_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback); emscripten_set_click_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback); emscripten_set_mouseenter_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback); emscripten_set_mouseleave_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback); emscripten_set_wheel_callback (aTargetId, anOpaque, toUseCapture, onWasmWheelCallback); emscripten_set_touchstart_callback (aTargetId, anOpaque, toUseCapture, onWasmTouchCallback); emscripten_set_touchend_callback (aTargetId, anOpaque, toUseCapture, onWasmTouchCallback); emscripten_set_touchmove_callback (aTargetId, anOpaque, toUseCapture, onWasmTouchCallback); emscripten_set_touchcancel_callback(aTargetId, anOpaque, toUseCapture, onWasmTouchCallback); // keyboard input requires a focusable element or EMSCRIPTEN_EVENT_TARGET_WINDOW emscripten_set_keydown_callback (aTargetId, anOpaque, toUseCapture, onWasmKeyCallback); emscripten_set_keyup_callback (aTargetId, anOpaque, toUseCapture, onWasmKeyCallback); #else (void )theWin; #endif }