0032306: Draw Harness, ViewerTest - move window message processing to TKService
authorkgv <kgv@opencascade.com>
Fri, 16 Apr 2021 10:01:17 +0000 (13:01 +0300)
committerkgv <kgv@opencascade.com>
Sat, 17 Apr 2021 12:14:16 +0000 (15:14 +0300)
Aspect_WindowInputListener - basic mouse/keyboard/expose input methods
have been moved out from AIS_ViewController to dedicated base interface.

Added WNT_Window::ProcessMessage()/Xw_Window::ProcessMessage() methods
redirecting Win32/X11 message to Aspect_WindowInputListener.

14 files changed:
src/AIS/AIS_ViewController.cxx
src/AIS/AIS_ViewController.hxx
src/Aspect/Aspect_WindowInputListener.cxx [new file with mode: 0644]
src/Aspect/Aspect_WindowInputListener.hxx [new file with mode: 0644]
src/Aspect/FILES
src/ViewerTest/ViewerTest_EventManager.cxx
src/ViewerTest/ViewerTest_EventManager.hxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
src/WNT/FILES
src/WNT/WNT_Window.cxx
src/WNT/WNT_Window.hxx
src/WNT/WNT_Window.lxx [deleted file]
src/Xw/Xw_Window.cxx
src/Xw/Xw_Window.hxx

index 0c03997..f93aeb9 100644 (file)
@@ -82,8 +82,6 @@ AIS_ViewController::AIS_ViewController()
   myMouseActiveGesture  (AIS_MouseGesture_NONE),
   myMouseActiveIdleRotation (false),
   myMouseClickCounter   (0),
-  myMousePressed        (Aspect_VKeyMouse_NONE),
-  myMouseModifiers      (Aspect_VKeyFlags_NONE),
   myMouseSingleButton   (-1),
   myMouseStopDragOnUnclick (false),
   //
@@ -99,16 +97,8 @@ AIS_ViewController::AIS_ViewController()
   myUpdateStartPointRot  (true),
   myUpdateStartPointZRot (true),
   //
-  my3dMouseNoRotate  (false, false, false),
-  my3dMouseToReverse (true,  false, false),
-  my3dMouseAccelTrans  (2.0f),
-  my3dMouseAccelRotate (4.0f),
-  my3dMouseIsQuadric   (true),
-  //
   myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
 {
-  memset(my3dMouseButtonState, 0, sizeof(my3dMouseButtonState));
-  myEventTimer.Start();
   myViewAnimation->SetOwnDuration (0.5);
 
   myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
@@ -1119,104 +1109,11 @@ bool AIS_ViewController::Update3dMouse (const WNT_HIDSpaceMouse& theEvent)
 {
   bool toUpdate = false;
   toUpdate = update3dMouseTranslation (theEvent) || toUpdate;
-  toUpdate = update3dMouseRotation (theEvent) || toUpdate;
+  toUpdate = (myToAllowRotation && update3dMouseRotation (theEvent)) || toUpdate;
   toUpdate = update3dMouseKeys (theEvent) || toUpdate;
   return toUpdate;
 }
 
-// =======================================================================
-// function : update3dMouseTranslation
-// purpose  :
-// =======================================================================
-bool AIS_ViewController::update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent)
-{
-  if (!theEvent.IsTranslation())
-  {
-    return false;
-  }
-
-  bool isIdle = true;
-  const double aTimeStamp = EventTime();
-  const Graphic3d_Vec3d aTrans = theEvent.Translation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelTrans;
-  myKeys.KeyFromAxis (Aspect_VKey_NavSlideLeft, Aspect_VKey_NavSlideRight, aTimeStamp, aTrans.x());
-  myKeys.KeyFromAxis (Aspect_VKey_NavForward,   Aspect_VKey_NavBackward,   aTimeStamp, aTrans.y());
-  myKeys.KeyFromAxis (Aspect_VKey_NavSlideUp,   Aspect_VKey_NavSlideDown,  aTimeStamp, aTrans.z());
-  return true;
-}
-
-// =======================================================================
-// function : update3dMouseRotation
-// purpose  :
-// =======================================================================
-bool AIS_ViewController::update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent)
-{
-  if (!theEvent.IsRotation()
-   || !myToAllowRotation)
-  {
-    return false;
-  }
-
-  bool isIdle = true, toUpdate = false;
-  const double aTimeStamp = EventTime();
-  const Graphic3d_Vec3d aRot3 = theEvent.Rotation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelRotate;
-  if (!my3dMouseNoRotate.x())
-  {
-    KeyFromAxis (Aspect_VKey_NavLookUp,   Aspect_VKey_NavLookDown,  aTimeStamp, !my3dMouseToReverse.x() ? aRot3.x() : -aRot3.x());
-    toUpdate = true;
-  }
-  if (!my3dMouseNoRotate.y())
-  {
-    KeyFromAxis (Aspect_VKey_NavRollCW,   Aspect_VKey_NavRollCCW,   aTimeStamp, !my3dMouseToReverse.y() ? aRot3.y() : -aRot3.y());
-    toUpdate = true;
-  }
-  if (!my3dMouseNoRotate.z())
-  {
-    KeyFromAxis (Aspect_VKey_NavLookLeft, Aspect_VKey_NavLookRight, aTimeStamp, !my3dMouseToReverse.z() ? aRot3.z() : -aRot3.z());
-    toUpdate = true;
-  }
-  return toUpdate;
-}
-
-// =======================================================================
-// function : update3dMouseKeys
-// purpose  :
-// =======================================================================
-bool AIS_ViewController::update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent)
-{
-  bool toUpdate = false;
-  const double aTimeStamp = EventTime();
-  if (theEvent.IsKeyState())
-  {
-    const uint32_t aKeyState = theEvent.KeyState();
-    for (unsigned short aKeyBit = 0; aKeyBit < 32; ++aKeyBit)
-    {
-      const bool isPressed  = (aKeyState & (1 << aKeyBit)) != 0;
-      const bool isReleased = my3dMouseButtonState[aKeyBit] && !isPressed;
-      //const bool isRepeated = my3dMouseButtonState[aKeyBit] &&  isPressed;
-      my3dMouseButtonState[aKeyBit] = isPressed;
-      if (!isReleased && !isPressed)
-      {
-        continue;
-      }
-
-      const Aspect_VKey aVKey = theEvent.HidToSpaceKey (aKeyBit);
-      if (aVKey != Aspect_VKey_UNKNOWN)
-      {
-        toUpdate = true;
-        if (isPressed)
-        {
-          KeyDown (aVKey, aTimeStamp);
-        }
-        else
-        {
-          KeyUp (aVKey, aTimeStamp);
-        }
-      }
-    }
-  }
-  return toUpdate;
-}
-
 // =======================================================================
 // function : SetNavigationMode
 // purpose  :
@@ -1240,7 +1137,7 @@ void AIS_ViewController::KeyDown (Aspect_VKey theKey,
                                   double theTime,
                                   double thePressure)
 {
-  myKeys.KeyDown (theKey, theTime, thePressure);
+  Aspect_WindowInputListener::KeyDown (theKey, theTime, thePressure);
 }
 
 // =======================================================================
@@ -1250,7 +1147,7 @@ void AIS_ViewController::KeyDown (Aspect_VKey theKey,
 void AIS_ViewController::KeyUp (Aspect_VKey theKey,
                                 double theTime)
 {
-  myKeys.KeyUp (theKey, theTime);
+  Aspect_WindowInputListener::KeyUp (theKey, theTime);
 }
 
 // =======================================================================
@@ -1262,7 +1159,7 @@ void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
                                       double theTime,
                                       double thePressure)
 {
-  myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
+  Aspect_WindowInputListener::KeyFromAxis (theNegative, thePositive, theTime, thePressure);
 }
 
 // =======================================================================
index 7cfcfbc..747e8bf 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <Aspect_VKeySet.hxx>
 #include <Aspect_TouchMap.hxx>
+#include <Aspect_WindowInputListener.hxx>
 #include <Aspect_XRHapticActionData.hxx>
 #include <Aspect_XRTrackedDeviceRole.hxx>
 #include <AIS_DragAction.hxx>
@@ -51,7 +52,7 @@ class WNT_HIDSpaceMouse;
 //! - Mapping mouse/multi-touch input to View camera manipulations (panning/rotating/zooming).
 //! - Input events are not applied immediately but queued for separate processing from two working threads
 //!   UI thread receiving user input and Rendering thread for OCCT 3D Viewer drawing.
-class AIS_ViewController
+class AIS_ViewController : public Aspect_WindowInputListener
 {
 public:
 
@@ -221,30 +222,30 @@ public: //! @name global parameters
 
 public: //! @name keyboard input
 
-  //! Return keyboard state.
-  const Aspect_VKeySet& Keys() const { return myKeys; }
-
-  //! Return keyboard state.
-  Aspect_VKeySet& ChangeKeys() { return myKeys; }
+  using Aspect_WindowInputListener::Keys;
+  using Aspect_WindowInputListener::ChangeKeys;
 
   //! Press key.
+  //! Default implementation updates internal cache.
   //! @param theKey key pressed
   //! @param theTime event timestamp
   Standard_EXPORT virtual void KeyDown (Aspect_VKey theKey,
                                         double theTime,
-                                        double thePressure = 1.0);
+                                        double thePressure = 1.0) Standard_OVERRIDE;
 
   //! Release key.
+  //! Default implementation updates internal cache.
   //! @param theKey key pressed
   //! @param theTime event timestamp
   Standard_EXPORT virtual void KeyUp (Aspect_VKey theKey,
-                                      double theTime);
+                                      double theTime) Standard_OVERRIDE;
 
   //! Simulate key up/down events from axis value.
+  //! Default implementation updates internal cache.
   Standard_EXPORT virtual void KeyFromAxis (Aspect_VKey theNegative,
                                             Aspect_VKey thePositive,
                                             double theTime,
-                                            double thePressure);
+                                            double thePressure) Standard_OVERRIDE;
 
   //! Fetch active navigation actions.
   Standard_EXPORT AIS_WalkDelta FetchNavigationKeys (Standard_Real theCrouchRatio,
@@ -313,7 +314,7 @@ public: //! @name mouse input
   //! This method is expected to be called from UI thread.
   //! @param theDelta mouse cursor position and delta
   //! @return TRUE if new event has been created or FALSE if existing one has been updated
-  Standard_EXPORT virtual bool UpdateMouseScroll (const Aspect_ScrollDelta& theDelta);
+  Standard_EXPORT virtual bool UpdateMouseScroll (const Aspect_ScrollDelta& theDelta) Standard_OVERRIDE;
 
   //! Handle mouse button press/release event.
   //! This method is expected to be called from UI thread.
@@ -326,7 +327,7 @@ public: //! @name mouse input
   Standard_EXPORT virtual bool UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
                                                    Aspect_VKeyMouse theButtons,
                                                    Aspect_VKeyFlags theModifiers,
-                                                   bool theIsEmulated);
+                                                   bool theIsEmulated) Standard_OVERRIDE;
 
   //! Handle mouse cursor movement event.
   //! This method is expected to be called from UI thread.
@@ -339,40 +340,7 @@ public: //! @name mouse input
   Standard_EXPORT virtual bool UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
                                                     Aspect_VKeyMouse theButtons,
                                                     Aspect_VKeyFlags theModifiers,
-                                                    bool theIsEmulated);
-
-  //! Handle mouse button press event.
-  //! This method is expected to be called from UI thread.
-  //! @param thePoint      mouse cursor position
-  //! @param theButton     pressed button
-  //! @param theModifiers  key modifiers
-  //! @param theIsEmulated if TRUE then mouse event comes NOT from real mouse
-  //!                      but emulated from non-precise input like touch on screen
-  //! @return TRUE if View should be redrawn
-  bool PressMouseButton (const Graphic3d_Vec2i& thePoint,
-                         Aspect_VKeyMouse theButton,
-                         Aspect_VKeyFlags theModifiers,
-                         bool theIsEmulated)
-  {
-    return UpdateMouseButtons (thePoint, myMousePressed | theButton, theModifiers, theIsEmulated);
-  }
-
-  //! Handle mouse button release event.
-  //! This method is expected to be called from UI thread.
-  //! @param thePoint      mouse cursor position
-  //! @param theButton     released button
-  //! @param theModifiers  key modifiers
-  //! @param theIsEmulated if TRUE then mouse event comes NOT from real mouse
-  //!                      but emulated from non-precise input like touch on screen
-  //! @return TRUE if View should be redrawn
-  bool ReleaseMouseButton (const Graphic3d_Vec2i& thePoint,
-                           Aspect_VKeyMouse theButton,
-                           Aspect_VKeyFlags theModifiers,
-                           bool theIsEmulated)
-  {
-    Aspect_VKeyMouse aButtons = myMousePressed & (~theButton);
-    return UpdateMouseButtons (thePoint, aButtons, theModifiers, theIsEmulated);
-  }
+                                                    bool theIsEmulated) Standard_OVERRIDE;
 
   //! Handle mouse button click event (emulated by UpdateMouseButtons() while releasing single button).
   //! Note that as this method is called by UpdateMouseButtons(), it should be executed from UI thread.
@@ -388,14 +356,12 @@ public: //! @name mouse input
                                                  Aspect_VKeyFlags theModifiers,
                                                  bool theIsDoubleClick);
 
-  //! Return currently pressed mouse buttons.
-  Aspect_VKeyMouse PressedMouseButtons() const { return myMousePressed; }
+  using Aspect_WindowInputListener::PressMouseButton;
+  using Aspect_WindowInputListener::ReleaseMouseButton;
 
-  //! Return active key modifiers passed with last mouse event.
-  Aspect_VKeyFlags LastMouseFlags() const { return myMouseModifiers; }
-
-  //! Return last mouse position.
-  const Graphic3d_Vec2i& LastMousePosition() const { return myMousePositionLast; }
+  using Aspect_WindowInputListener::PressedMouseButtons;
+  using Aspect_WindowInputListener::LastMouseFlags;
+  using Aspect_WindowInputListener::LastMousePosition;
 
 public: //! @name multi-touch input
 
@@ -436,52 +402,40 @@ public: //! @name multi-touch input
 
 public: //! @name 3d mouse input
 
-  //! Return acceleration ratio for translation event; 2.0 by default.
-  float Get3dMouseTranslationScale() const { return my3dMouseAccelTrans; }
-
-  //! Set acceleration ratio for translation event.
-  void Set3dMouseTranslationScale (float theScale) { my3dMouseAccelTrans = theScale; }
-
-  //! Return acceleration ratio for rotation event; 4.0 by default.
-  float Get3dMouseRotationScale() const { return my3dMouseAccelRotate; }
-
-  //! Set acceleration ratio for rotation event.
-  void Set3dMouseRotationScale (float theScale) { my3dMouseAccelRotate = theScale; }
-
-  //! Return quadric acceleration flag; TRUE by default.
-  bool To3dMousePreciseInput() const { return my3dMouseIsQuadric; }
-
-  //! Set quadric acceleration flag.
-  void Set3dMousePreciseInput (bool theIsQuadric) { my3dMouseIsQuadric = theIsQuadric; }
-
-  //! Return 3d mouse rotation axes (tilt/roll/spin) ignore flag; (FALSE, FALSE, FALSE) by default.
-  const NCollection_Vec3<bool>& Get3dMouseIsNoRotate() const { return my3dMouseNoRotate; }
-
-  //! Return 3d mouse rotation axes (tilt/roll/spin) ignore flag; (FALSE, FALSE, FALSE) by default.
-  NCollection_Vec3<bool>& Change3dMouseIsNoRotate() { return my3dMouseNoRotate; }
+  //! Process 3d mouse input event (redirects to translation, rotation and keys).
+  Standard_EXPORT virtual bool Update3dMouse (const WNT_HIDSpaceMouse& theEvent) Standard_OVERRIDE;
 
-  //! Return 3d mouse rotation axes (tilt/roll/spin) reverse flag; (TRUE, FALSE, FALSE) by default.
-  const NCollection_Vec3<bool>& Get3dMouseToReverse() const { return my3dMouseToReverse; }
+public: //! @name resize events
 
-  //! Return 3d mouse rotation axes (tilt/roll/spin) reverse flag; (TRUE, FALSE, FALSE) by default.
-  NCollection_Vec3<bool>& Change3dMouseToReverse() { return my3dMouseToReverse; }
+  //! Handle expose event (window content has been invalidation and should be redrawn).
+  //! Default implementation does nothing.
+  virtual void ProcessExpose() Standard_OVERRIDE {}
 
-  //! Process 3d mouse input event (redirects to translation, rotation and keys).
-  Standard_EXPORT virtual bool Update3dMouse (const WNT_HIDSpaceMouse& theEvent);
+  //! Handle window resize event.
+  //! Default implementation does nothing.
+  virtual void ProcessConfigure (bool theIsResized) Standard_OVERRIDE
+  {
+    (void )theIsResized;
+  }
 
-  //! Process 3d mouse input translation event.
-  Standard_EXPORT virtual bool update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent);
+  //! Handle window input event immediately.
+  //! Default implementation does nothing - input events are accumulated in internal buffer until explicit FlushViewEvents() call.
+  virtual void ProcessInput() Standard_OVERRIDE {}
 
-  //! Process 3d mouse input rotation event.
-  Standard_EXPORT virtual bool update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent);
+  //! Handle focus event.
+  //! Default implementation does nothing.
+  virtual void ProcessFocus (bool theIsActivated)
+  {
+    (void )theIsActivated;
+  }
 
-  //! Process 3d mouse input keys event.
-  Standard_EXPORT virtual bool update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent);
+  //! Handle window close event.
+  //! Default implementation does nothing.
+  virtual void ProcessClose() {}
 
 public:
 
-  //! Return event time (e.g. current time).
-  double EventTime() const { return myEventTimer.ElapsedTime(); }
+  using Aspect_WindowInputListener::EventTime;
 
   //! Reset input state (pressed keys, mouse buttons, etc.) e.g. on window focus loss.
   //! This method is expected to be called from UI thread.
@@ -712,7 +666,6 @@ protected:
   AIS_ViewInputBuffer myUI;                       //!< buffer for UI thread
   AIS_ViewInputBuffer myGL;                       //!< buffer for rendering thread
 
-  OSD_Timer           myEventTimer;               //!< timer for timestamping events
   Standard_Real       myLastEventsTime;           //!< last fetched events timer value for computing delta/progress
   Standard_Boolean    myToAskNextFrame;           //!< flag indicating that another frame should be drawn right after this one
 
@@ -764,10 +717,6 @@ protected: //! @name XR input variables
   Standard_Boolean    myToDisplayXRAuxDevices;    //!< flag to display auxiliary tracked XR devices
   Standard_Boolean    myToDisplayXRHands;         //!< flag to display XR hands
 
-protected: //! @name keyboard input variables
-
-  Aspect_VKeySet      myKeys;                     //!< keyboard state
-
 protected: //! @name mouse input variables
 
   Standard_Real       myMouseClickThreshold;      //!< mouse click threshold in pixels; 3 by default
@@ -779,13 +728,10 @@ protected: //! @name mouse input variables
   AIS_MouseSelectionSchemeMap
                       myMouseSelectionSchemes;    //!< map defining selection schemes bound to mouse + modifiers
   Standard_Boolean    myMouseActiveIdleRotation;  //!< flag indicating view idle rotation state
-  Graphic3d_Vec2i     myMousePositionLast;        //!< last mouse position
   Graphic3d_Vec2i     myMousePressPoint;          //!< mouse position where active gesture was been initiated
   Graphic3d_Vec2i     myMouseProgressPoint;       //!< gesture progress
   OSD_Timer           myMouseClickTimer;          //!< timer for handling double-click event
   Standard_Integer    myMouseClickCounter;        //!< counter for handling double-click event
-  Aspect_VKeyMouse    myMousePressed;             //!< active mouse buttons
-  Aspect_VKeyFlags    myMouseModifiers;           //!< active key modifiers passed with last mouse event
   Standard_Integer    myMouseSingleButton;        //!< index of mouse button pressed alone (>0)
   Standard_Boolean    myMouseStopDragOnUnclick;   //!< queue stop dragging even with at next mouse unclick
 
@@ -806,15 +752,6 @@ protected: //! @name multi-touch input variables
   Standard_Boolean    myUpdateStartPointRot;      //!< flag indicating that new gravity point should be picked for starting rotation   gesture
   Standard_Boolean    myUpdateStartPointZRot;     //!< flag indicating that new gravity point should be picked for starting Z-rotation gesture
 
-protected: //! @name 3d mouse input variables
-
-  bool                   my3dMouseButtonState[32];//!< cached button state
-  NCollection_Vec3<bool> my3dMouseNoRotate;       //!< ignore  3d mouse rotation axes
-  NCollection_Vec3<bool> my3dMouseToReverse;      //!< reverse 3d mouse rotation axes
-  float                  my3dMouseAccelTrans;     //!< acceleration ratio for translation event
-  float                  my3dMouseAccelRotate;    //!< acceleration ratio for rotation event
-  bool                   my3dMouseIsQuadric;      //!< quadric acceleration
-
 protected: //! @name rotation/panning transient state variables
 
   Handle(AIS_Point)   myAnchorPointPrs1;          //!< anchor point presentation (Graphic3d_ZLayerId_Top)
diff --git a/src/Aspect/Aspect_WindowInputListener.cxx b/src/Aspect/Aspect_WindowInputListener.cxx
new file mode 100644 (file)
index 0000000..ed6478b
--- /dev/null
@@ -0,0 +1,168 @@
+// Copyright (c) 2021 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 <Aspect_WindowInputListener.hxx>
+
+#include <WNT_HIDSpaceMouse.hxx>
+
+// =======================================================================
+// function : Aspect_WindowInputListener
+// purpose  :
+// =======================================================================
+Aspect_WindowInputListener::Aspect_WindowInputListener()
+: myMousePressed   (Aspect_VKeyMouse_NONE),
+  myMouseModifiers (Aspect_VKeyFlags_NONE),
+  //
+  my3dMouseNoRotate  (false, false, false),
+  my3dMouseToReverse (true,  false, false),
+  my3dMouseAccelTrans  (2.0f),
+  my3dMouseAccelRotate (4.0f),
+  my3dMouseIsQuadric   (true)
+{
+  memset(my3dMouseButtonState, 0, sizeof(my3dMouseButtonState));
+  myEventTimer.Start();
+}
+
+// =======================================================================
+// function : ~Aspect_WindowInputListener
+// purpose  :
+// =======================================================================
+Aspect_WindowInputListener::~Aspect_WindowInputListener()
+{
+  //
+}
+
+// =======================================================================
+// function : KeyDown
+// purpose  :
+// =======================================================================
+void Aspect_WindowInputListener::KeyDown (Aspect_VKey theKey,
+                                          double theTime,
+                                          double thePressure)
+{
+  myKeys.KeyDown (theKey, theTime, thePressure);
+}
+
+// =======================================================================
+// function : KeyUp
+// purpose  :
+// =======================================================================
+void Aspect_WindowInputListener::KeyUp (Aspect_VKey theKey,
+                                        double theTime)
+{
+  myKeys.KeyUp (theKey, theTime);
+}
+
+// =======================================================================
+// function : KeyFromAxis
+// purpose  :
+// =======================================================================
+void Aspect_WindowInputListener::KeyFromAxis (Aspect_VKey theNegative,
+                                              Aspect_VKey thePositive,
+                                              double theTime,
+                                              double thePressure)
+{
+  myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
+}
+
+// =======================================================================
+// function : update3dMouseTranslation
+// purpose  :
+// =======================================================================
+bool Aspect_WindowInputListener::update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent)
+{
+  if (!theEvent.IsTranslation())
+  {
+    return false;
+  }
+
+  bool isIdle = true;
+  const double aTimeStamp = EventTime();
+  const Graphic3d_Vec3d aTrans = theEvent.Translation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelTrans;
+  myKeys.KeyFromAxis (Aspect_VKey_NavSlideLeft, Aspect_VKey_NavSlideRight, aTimeStamp, aTrans.x());
+  myKeys.KeyFromAxis (Aspect_VKey_NavForward,   Aspect_VKey_NavBackward,   aTimeStamp, aTrans.y());
+  myKeys.KeyFromAxis (Aspect_VKey_NavSlideUp,   Aspect_VKey_NavSlideDown,  aTimeStamp, aTrans.z());
+  return true;
+}
+
+// =======================================================================
+// function : update3dMouseRotation
+// purpose  :
+// =======================================================================
+bool Aspect_WindowInputListener::update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent)
+{
+  if (!theEvent.IsRotation())
+  {
+    return false;
+  }
+
+  bool isIdle = true, toUpdate = false;
+  const double aTimeStamp = EventTime();
+  const Graphic3d_Vec3d aRot3 = theEvent.Rotation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelRotate;
+  if (!my3dMouseNoRotate.x())
+  {
+    KeyFromAxis (Aspect_VKey_NavLookUp,   Aspect_VKey_NavLookDown,  aTimeStamp, !my3dMouseToReverse.x() ? aRot3.x() : -aRot3.x());
+    toUpdate = true;
+  }
+  if (!my3dMouseNoRotate.y())
+  {
+    KeyFromAxis (Aspect_VKey_NavRollCW,   Aspect_VKey_NavRollCCW,   aTimeStamp, !my3dMouseToReverse.y() ? aRot3.y() : -aRot3.y());
+    toUpdate = true;
+  }
+  if (!my3dMouseNoRotate.z())
+  {
+    KeyFromAxis (Aspect_VKey_NavLookLeft, Aspect_VKey_NavLookRight, aTimeStamp, !my3dMouseToReverse.z() ? aRot3.z() : -aRot3.z());
+    toUpdate = true;
+  }
+  return toUpdate;
+}
+
+// =======================================================================
+// function : update3dMouseKeys
+// purpose  :
+// =======================================================================
+bool Aspect_WindowInputListener::update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent)
+{
+  bool toUpdate = false;
+  const double aTimeStamp = EventTime();
+  if (theEvent.IsKeyState())
+  {
+    const uint32_t aKeyState = theEvent.KeyState();
+    for (unsigned short aKeyBit = 0; aKeyBit < 32; ++aKeyBit)
+    {
+      const bool isPressed  = (aKeyState & (1 << aKeyBit)) != 0;
+      const bool isReleased = my3dMouseButtonState[aKeyBit] && !isPressed;
+      //const bool isRepeated = my3dMouseButtonState[aKeyBit] &&  isPressed;
+      my3dMouseButtonState[aKeyBit] = isPressed;
+      if (!isReleased && !isPressed)
+      {
+        continue;
+      }
+
+      const Aspect_VKey aVKey = theEvent.HidToSpaceKey (aKeyBit);
+      if (aVKey != Aspect_VKey_UNKNOWN)
+      {
+        toUpdate = true;
+        if (isPressed)
+        {
+          KeyDown (aVKey, aTimeStamp);
+        }
+        else
+        {
+          KeyUp (aVKey, aTimeStamp);
+        }
+      }
+    }
+  }
+  return toUpdate;
+}
diff --git a/src/Aspect/Aspect_WindowInputListener.hxx b/src/Aspect/Aspect_WindowInputListener.hxx
new file mode 100644 (file)
index 0000000..88e8825
--- /dev/null
@@ -0,0 +1,236 @@
+// Copyright (c) 2021 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.
+
+#ifndef _Aspect_WindowInputListener_HeaderFile
+#define _Aspect_WindowInputListener_HeaderFile
+
+#include <Aspect_VKeySet.hxx>
+#include <Graphic3d_Vec.hxx>
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+
+struct Aspect_ScrollDelta;
+class WNT_HIDSpaceMouse;
+
+//! Defines a listener for window input events.
+class Aspect_WindowInputListener
+{
+public:
+  ///DEFINE_STANDARD_ALLOC
+public:
+
+  //! Destructor.
+  Standard_EXPORT virtual ~Aspect_WindowInputListener();
+
+  //! Return event time (e.g. current time).
+  double EventTime() const { return myEventTimer.ElapsedTime(); }
+
+  //! Handle expose event (window content has been invalidation and should be redrawn).
+  virtual void ProcessExpose() = 0;
+
+  //! Handle window resize event.
+  virtual void ProcessConfigure (bool theIsResized) = 0;
+
+  //! Handle window input event immediately (flush input buffer or ignore).
+  virtual void ProcessInput() = 0;
+
+  //! Handle focus event.
+  virtual void ProcessFocus (bool theIsActivated) = 0;
+
+  //! Handle window close event.
+  virtual void ProcessClose() = 0;
+
+public: //! @name keyboard input
+
+  //! Return keyboard state.
+  const Aspect_VKeySet& Keys() const { return myKeys; }
+
+  //! Return keyboard state.
+  Aspect_VKeySet& ChangeKeys() { return myKeys; }
+
+  //! Press key.
+  //! Default implementation updates internal cache.
+  //! @param theKey key pressed
+  //! @param theTime event timestamp
+  Standard_EXPORT virtual void KeyDown (Aspect_VKey theKey,
+                                        double theTime,
+                                        double thePressure = 1.0) = 0;
+
+  //! Release key.
+  //! Default implementation updates internal cache.
+  //! @param theKey key pressed
+  //! @param theTime event timestamp
+  Standard_EXPORT virtual void KeyUp (Aspect_VKey theKey,
+                                      double theTime) = 0;
+
+  //! Simulate key up/down events from axis value.
+  //! Default implementation updates internal cache.
+  Standard_EXPORT virtual void KeyFromAxis (Aspect_VKey theNegative,
+                                            Aspect_VKey thePositive,
+                                            double theTime,
+                                            double thePressure) = 0;
+
+public: //! @name mouse input
+
+  //! Update mouse scroll event.
+  //! This method is expected to be called from UI thread.
+  //! @param theDelta mouse cursor position and delta
+  //! @return TRUE if new event has been created or FALSE if existing one has been updated
+  virtual bool UpdateMouseScroll (const Aspect_ScrollDelta& theDelta) = 0;
+
+  //! Handle mouse button press/release event.
+  //! This method is expected to be called from UI thread.
+  //! @param thePoint      mouse cursor position
+  //! @param theButtons    pressed buttons
+  //! @param theModifiers  key modifiers
+  //! @param theIsEmulated if TRUE then mouse event comes NOT from real mouse
+  //!                      but emulated from non-precise input like touch on screen
+  //! @return TRUE if window content should be redrawn
+  virtual bool UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
+                                   Aspect_VKeyMouse theButtons,
+                                   Aspect_VKeyFlags theModifiers,
+                                   bool theIsEmulated) = 0;
+
+  //! Handle mouse cursor movement event.
+  //! This method is expected to be called from UI thread.
+  //! Default implementation does nothing.
+  //! @param thePoint      mouse cursor position
+  //! @param theButtons    pressed buttons
+  //! @param theModifiers  key modifiers
+  //! @param theIsEmulated if TRUE then mouse event comes NOT from real mouse
+  //!                      but emulated from non-precise input like touch on screen
+  //! @return TRUE if window content should be redrawn
+  virtual bool UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
+                                    Aspect_VKeyMouse theButtons,
+                                    Aspect_VKeyFlags theModifiers,
+                                    bool theIsEmulated) = 0;
+
+  //! Handle mouse button press event.
+  //! This method is expected to be called from UI thread.
+  //! Default implementation redirects to UpdateMousePosition().
+  //! @param thePoint      mouse cursor position
+  //! @param theButton     pressed button
+  //! @param theModifiers  key modifiers
+  //! @param theIsEmulated if TRUE then mouse event comes NOT from real mouse
+  //!                      but emulated from non-precise input like touch on screen
+  //! @return TRUE if window content should be redrawn
+  bool PressMouseButton (const Graphic3d_Vec2i& thePoint,
+                         Aspect_VKeyMouse theButton,
+                         Aspect_VKeyFlags theModifiers,
+                         bool theIsEmulated)
+  {
+    return UpdateMouseButtons (thePoint, myMousePressed | theButton, theModifiers, theIsEmulated);
+  }
+
+  //! Handle mouse button release event.
+  //! This method is expected to be called from UI thread.
+  //! Default implementation redirects to UpdateMousePosition().
+  //! @param thePoint      mouse cursor position
+  //! @param theButton     released button
+  //! @param theModifiers  key modifiers
+  //! @param theIsEmulated if TRUE then mouse event comes NOT from real mouse
+  //!                      but emulated from non-precise input like touch on screen
+  //! @return TRUE if window content should be redrawn
+  bool ReleaseMouseButton (const Graphic3d_Vec2i& thePoint,
+                           Aspect_VKeyMouse theButton,
+                           Aspect_VKeyFlags theModifiers,
+                           bool theIsEmulated)
+  {
+    Aspect_VKeyMouse aButtons = myMousePressed & (~theButton);
+    return UpdateMouseButtons (thePoint, aButtons, theModifiers, theIsEmulated);
+  }
+
+  //! Return currently pressed mouse buttons.
+  Aspect_VKeyMouse PressedMouseButtons() const { return myMousePressed; }
+
+  //! Return active key modifiers passed with last mouse event.
+  Aspect_VKeyFlags LastMouseFlags() const { return myMouseModifiers; }
+
+  //! Return last mouse position.
+  const Graphic3d_Vec2i& LastMousePosition() const { return myMousePositionLast; }
+
+public: //! @name 3d mouse input
+
+  //! Return acceleration ratio for translation event; 2.0 by default.
+  float Get3dMouseTranslationScale() const { return my3dMouseAccelTrans; }
+
+  //! Set acceleration ratio for translation event.
+  void Set3dMouseTranslationScale (float theScale) { my3dMouseAccelTrans = theScale; }
+
+  //! Return acceleration ratio for rotation event; 4.0 by default.
+  float Get3dMouseRotationScale() const { return my3dMouseAccelRotate; }
+
+  //! Set acceleration ratio for rotation event.
+  void Set3dMouseRotationScale (float theScale) { my3dMouseAccelRotate = theScale; }
+
+  //! Return quadric acceleration flag; TRUE by default.
+  bool To3dMousePreciseInput() const { return my3dMouseIsQuadric; }
+
+  //! Set quadric acceleration flag.
+  void Set3dMousePreciseInput (bool theIsQuadric) { my3dMouseIsQuadric = theIsQuadric; }
+
+  //! Return 3d mouse rotation axes (tilt/roll/spin) ignore flag; (FALSE, FALSE, FALSE) by default.
+  const NCollection_Vec3<bool>& Get3dMouseIsNoRotate() const { return my3dMouseNoRotate; }
+
+  //! Return 3d mouse rotation axes (tilt/roll/spin) ignore flag; (FALSE, FALSE, FALSE) by default.
+  NCollection_Vec3<bool>& Change3dMouseIsNoRotate() { return my3dMouseNoRotate; }
+
+  //! Return 3d mouse rotation axes (tilt/roll/spin) reverse flag; (TRUE, FALSE, FALSE) by default.
+  const NCollection_Vec3<bool>& Get3dMouseToReverse() const { return my3dMouseToReverse; }
+
+  //! Return 3d mouse rotation axes (tilt/roll/spin) reverse flag; (TRUE, FALSE, FALSE) by default.
+  NCollection_Vec3<bool>& Change3dMouseToReverse() { return my3dMouseToReverse; }
+
+  //! Process 3d mouse input event (redirects to translation, rotation and keys).
+  virtual bool Update3dMouse (const WNT_HIDSpaceMouse& theEvent) = 0;
+
+  //! Process 3d mouse input translation event.
+  Standard_EXPORT virtual bool update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent);
+
+  //! Process 3d mouse input rotation event.
+  Standard_EXPORT virtual bool update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent);
+
+  //! Process 3d mouse input keys event.
+  Standard_EXPORT virtual bool update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent);
+
+protected:
+
+  //! Empty constructor.
+  Standard_EXPORT Aspect_WindowInputListener();
+
+protected:
+
+  OSD_Timer        myEventTimer;        //!< timer for timestamping events
+
+protected: //! @name keyboard input variables
+
+  Aspect_VKeySet   myKeys;              //!< keyboard state
+
+protected: //! @name mouse input variables
+
+  Graphic3d_Vec2i  myMousePositionLast; //!< last mouse position
+  Aspect_VKeyMouse myMousePressed;      //!< active mouse buttons
+  Aspect_VKeyFlags myMouseModifiers;    //!< active key modifiers passed with last mouse event
+
+protected: //! @name 3d mouse input variables
+
+  bool                   my3dMouseButtonState[32];//!< cached button state
+  NCollection_Vec3<bool> my3dMouseNoRotate;       //!< ignore  3d mouse rotation axes
+  NCollection_Vec3<bool> my3dMouseToReverse;      //!< reverse 3d mouse rotation axes
+  float                  my3dMouseAccelTrans;     //!< acceleration ratio for translation event
+  float                  my3dMouseAccelRotate;    //!< acceleration ratio for rotation event
+  bool                   my3dMouseIsQuadric;      //!< quadric acceleration
+
+};
+
+#endif // _Aspect_WindowInputListener_HeaderFile
index 8f18be0..112a2d4 100755 (executable)
@@ -66,6 +66,8 @@ Aspect_Window.cxx
 Aspect_Window.hxx
 Aspect_WindowDefinitionError.hxx
 Aspect_WindowError.hxx
+Aspect_WindowInputListener.cxx
+Aspect_WindowInputListener.hxx
 Aspect_XAtom.hxx
 Aspect_XRAction.hxx
 Aspect_XRActionSet.hxx
index a1e5837..2a2ed2f 100644 (file)
@@ -167,15 +167,36 @@ void ViewerTest_EventManager::handleViewRedraw (const Handle(AIS_InteractiveCont
 //function : ProcessConfigure
 //purpose  :
 //==============================================================================
-void ViewerTest_EventManager::ProcessConfigure()
+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->MustBeResized();
     FlushViewEvents (myCtx, myView, true);
   }
 }
 
+//==============================================================================
+//function : ProcessInput
+//purpose  :
+//==============================================================================
+void ViewerTest_EventManager::ProcessInput()
+{
+  if (!myView.IsNull())
+  {
+    FlushViewEvents (myCtx, myView, true);
+  }
+}
+
 // =======================================================================
 // function : navigationKeyModifierSwitch
 // purpose  :
index 2f1fc87..4b54598 100644 (file)
@@ -91,14 +91,17 @@ public:
                                       double theTime) Standard_OVERRIDE;
 
   //! Redraw the View on an Expose Event
-  Standard_EXPORT virtual void ProcessExpose();
+  Standard_EXPORT virtual void ProcessExpose() Standard_OVERRIDE;
 
   //! Handle redraw.
   Standard_EXPORT virtual void handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx,
                                                  const Handle(V3d_View)& theView) Standard_OVERRIDE;
 
   //! Resize View.
-  Standard_EXPORT virtual void ProcessConfigure();
+  Standard_EXPORT virtual void ProcessConfigure (bool theIsResized = true) Standard_OVERRIDE;
+
+  //! Handle window input event immediately (flush input buffer).
+  Standard_EXPORT virtual void ProcessInput() Standard_OVERRIDE;
 
   //! Handle KeyPress event.
   Standard_EXPORT void ProcessKeyPress (Aspect_VKey theKey);
index e67e667..ee7db32 100644 (file)
@@ -1390,19 +1390,9 @@ namespace
 //==============================================================================
 
 #ifdef _WIN32
-static LRESULT WINAPI ViewerWindowProc(
-                                       HWND hwnd,
-                                       UINT uMsg,
-                                       WPARAM wParam,
-                                       LPARAM lParam );
-static LRESULT WINAPI AdvViewerWindowProc(
-  HWND hwnd,
-  UINT uMsg,
-  WPARAM wParam,
-  LPARAM lParam );
+static LRESULT WINAPI AdvViewerWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 #endif
 
-
 //==============================================================================
 //function : WClass
 //purpose  :
@@ -3247,7 +3237,7 @@ static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
 {
   if (ViewerTest_myViews.IsEmpty())
   {
-    return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
+    return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
   }
 
   switch (theMsg)
@@ -3271,215 +3261,32 @@ static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
           ActivateView (FindViewIdByWindowHandle (theWinHandle));
         }
       }
-      break;
-    }
-    default:
-    {
-      return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
-    }
-  }
-  return 0;
-}
-
-static LRESULT WINAPI ViewerWindowProc (HWND theWinHandle,
-                                        UINT theMsg,
-                                        WPARAM wParam,
-                                        LPARAM lParam)
-{
-  const Handle(V3d_View)& aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
-  {
-    return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
-  }
-
-  switch (theMsg)
-  {
-    case WM_PAINT:
-    {
-      PAINTSTRUCT aPaint;
-      BeginPaint(theWinHandle, &aPaint);
-      EndPaint  (theWinHandle, &aPaint);
-      ViewerTest::CurrentEventManager()->ProcessExpose();
-      break;
-    }
-    case WM_SIZE:
-    {
-      ViewerTest::CurrentEventManager()->ProcessConfigure();
-      break;
-    }
-    case WM_MOVE:
-    case WM_MOVING:
-    case WM_SIZING:
-    {
-      switch (aView->RenderingParams().StereoMode)
-      {
-        case Graphic3d_StereoMode_RowInterlaced:
-        case Graphic3d_StereoMode_ColumnInterlaced:
-        case Graphic3d_StereoMode_ChessBoard:
-        {
-          // track window moves to reverse stereo pair
-          aView->MustBeResized();
-          aView->Update();
-          break;
-        }
-        default:
-          break;
-      }
-      break;
-    }
-    case WM_KEYUP:
-    case WM_KEYDOWN:
-    {
-      const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )wParam);
-      if (aVKey != Aspect_VKey_UNKNOWN)
-      {
-        const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
-        if (theMsg == WM_KEYDOWN)
-        {
-          ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
-        }
-        else
-        {
-          ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
-        }
-        ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
-      }
-      break;
+      return 0;
     }
-    case WM_LBUTTONUP:
-    case WM_MBUTTONUP:
-    case WM_RBUTTONUP:
     case WM_LBUTTONDOWN:
-    case WM_MBUTTONDOWN:
-    case WM_RBUTTONDOWN:
     {
-      const Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
-      const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
-      Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
-      switch (theMsg)
-      {
-        case WM_LBUTTONUP:
-        case WM_LBUTTONDOWN:
-          aButton = Aspect_VKeyMouse_LeftButton;
-          break;
-        case WM_MBUTTONUP:
-        case WM_MBUTTONDOWN:
-          aButton = Aspect_VKeyMouse_MiddleButton;
-          break;
-        case WM_RBUTTONUP:
-        case WM_RBUTTONDOWN:
-          aButton = Aspect_VKeyMouse_RightButton;
-          break;
-      }
-      if (theMsg == WM_LBUTTONDOWN
-       || theMsg == WM_MBUTTONDOWN
-       || theMsg == WM_RBUTTONDOWN)
-      {
-        if (aButton == Aspect_VKeyMouse_LeftButton)
-        {
-          TheIsAnimating = Standard_False;
-        }
-
-        SetFocus  (theWinHandle);
-        SetCapture(theWinHandle);
-        ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
-      }
-      else
-      {
-        ReleaseCapture();
-        ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
-      }
-      ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
-      break;
+      TheIsAnimating = Standard_False;
     }
-    case WM_MOUSEWHEEL:
-    {
-      const int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
-      const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
-      const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
-      Graphic3d_Vec2i aPos (int(short(LOWORD(lParam))), int(short(HIWORD(lParam))));
-      POINT aCursorPnt = { aPos.x(), aPos.y() };
-      if (ScreenToClient (theWinHandle, &aCursorPnt))
-      {
-        aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
-      }
-
-      ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
-      ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
-      break;
-    }
-    case WM_MOUSEMOVE:
+    Standard_FALLTHROUGH
+    default:
     {
-      Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
-      Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (wParam);
-      Aspect_VKeyFlags aFlags   = WNT_Window::MouseKeyFlagsFromEvent(wParam);
-
-      // don't make a slide-show from input events - fetch the actual mouse cursor position
-      CURSORINFO aCursor;
-      aCursor.cbSize = sizeof(aCursor);
-      if (::GetCursorInfo (&aCursor) != FALSE)
+      const Handle(V3d_View)& aView = ViewerTest::CurrentView();
+      if (!aView.IsNull()
+       && !VT_GetWindow().IsNull())
       {
-        POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
-        if (ScreenToClient (theWinHandle, &aCursorPnt))
+        MSG aMsg = {};
+        aMsg.hwnd = theWinHandle;
+        aMsg.message = theMsg;
+        aMsg.wParam = wParam;
+        aMsg.lParam = lParam;
+        if (VT_GetWindow()->ProcessMessage (*ViewerTest::CurrentEventManager(), aMsg))
         {
-          // as we override mouse position, we need overriding also mouse state
-          aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
-          aButtons = WNT_Window::MouseButtonsAsync();
-          aFlags   = WNT_Window::MouseKeyFlagsAsync();
+          return 0;
         }
       }
-
-      if (VT_GetWindow().IsNull()
-      || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
-      {
-        // mouse move events come also for inactive windows
-        break;
-      }
-
-      ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
-      ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
-      break;
-    }
-    case WM_INPUT:
-    {
-      UINT aSize = 0;
-      ::GetRawInputData ((HRAWINPUT )lParam, RID_INPUT, NULL, &aSize, sizeof(RAWINPUTHEADER));
-      NCollection_LocalArray<BYTE> aRawData (aSize);
-      if (aSize == 0 || ::GetRawInputData ((HRAWINPUT )lParam, RID_INPUT, aRawData, &aSize, sizeof(RAWINPUTHEADER)) != aSize)
-      {
-        break;
-      }
-
-      const RAWINPUT* aRawInput = (RAWINPUT* )(BYTE* )aRawData;
-      if (aRawInput->header.dwType != RIM_TYPEHID)
-      {
-        break;
-      }
-
-      RID_DEVICE_INFO aDevInfo;
-      aDevInfo.cbSize = sizeof(RID_DEVICE_INFO);
-      UINT aDevInfoSize = sizeof(RID_DEVICE_INFO);
-      if (::GetRawInputDeviceInfoW (aRawInput->header.hDevice, RIDI_DEVICEINFO, &aDevInfo, &aDevInfoSize) != sizeof(RID_DEVICE_INFO)
-        || (aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_LOGITECH
-         && aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_3DCONNEXION))
-      {
-        break;
-      }
-
-      WNT_HIDSpaceMouse aSpaceData (aDevInfo.hid.dwProductId, aRawInput->data.hid.bRawData, aRawInput->data.hid.dwSizeHid);
-      if (ViewerTest::CurrentEventManager()->Update3dMouse (aSpaceData)
-      && !VT_GetWindow().IsNull())
-      {
-        VT_GetWindow()->InvalidateContent();
-      }
-      break;
-    }
-    default:
-    {
-      return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
     }
   }
-  return 0L;
+  return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
 }
 
 //==============================================================================
@@ -3518,22 +3325,6 @@ int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
 
 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
 
-int min( int a, int b )
-{
-  if( a<b )
-    return a;
-  else
-    return b;
-}
-
-int max( int a, int b )
-{
-  if( a>b )
-    return a;
-  else
-    return b;
-}
-
 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
 {
   static XEvent aReport;
@@ -3573,170 +3364,22 @@ int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
       }
       break;
     }
-    case Expose:
-    {
-      Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
-      if (anXWindow == aReport.xexpose.window)
-      {
-        ViewerTest::CurrentEventManager()->ProcessExpose();
-      }
-
-      // remove all the ExposureMask and process them at once
-      for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
-      {
-        if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
-        {
-          break;
-        }
-      }
-
-      break;
-    }
-    case ConfigureNotify:
-    {
-      // remove all the StructureNotifyMask and process them at once
-      Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
-      for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
-      {
-        if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
-        {
-          break;
-        }
-      }
-
-      if (anXWindow == aReport.xconfigure.window)
-      {
-        ViewerTest::CurrentEventManager()->ProcessConfigure();
-      }
-      break;
-    }
-    case KeyPress:
-    case KeyRelease:
-    {
-      XKeyEvent*   aKeyEvent = (XKeyEvent* )&aReport;
-      const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
-      const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
-      if (aVKey != Aspect_VKey_UNKNOWN)
-      {
-        const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
-        if (aReport.type == KeyPress)
-        {
-          ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
-        }
-        else
-        {
-          ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
-        }
-        ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
-      }
-      break;
-    }
     case ButtonPress:
-    case ButtonRelease:
     {
-      const Graphic3d_Vec2i aPos (aReport.xbutton.x, aReport.xbutton.y);
-      Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
-      Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
       if (aReport.xbutton.button == Button1)
       {
-        aButton = Aspect_VKeyMouse_LeftButton;
+        TheIsAnimating = Standard_False;
       }
-      if (aReport.xbutton.button == Button2)
-      {
-        aButton = Aspect_VKeyMouse_MiddleButton;
-      }
-      if (aReport.xbutton.button == Button3)
-      {
-        aButton = Aspect_VKeyMouse_RightButton;
-      }
-
-      if (aReport.xbutton.state & ControlMask)
-      {
-        aFlags |= Aspect_VKeyFlags_CTRL;
-      }
-      if (aReport.xbutton.state & ShiftMask)
-      {
-        aFlags |= Aspect_VKeyFlags_SHIFT;
-      }
-      if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
-      {
-        aFlags |= Aspect_VKeyFlags_ALT;
-      }
-
-      if (aReport.xbutton.button == Button4
-       || aReport.xbutton.button == Button5)
-      {
-        if (aReport.type != ButtonPress)
-        {
-          break;
-        }
-
-        const double aDeltaF = (aReport.xbutton.button == Button4 ? 1.0 : -1.0);
-        ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
-      }
-      else if (aReport.type == ButtonPress)
-      {
-        if (aButton == Aspect_VKeyMouse_LeftButton)
-        {
-          TheIsAnimating = Standard_False;
-        }
-        ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
-      }
-      else
-      {
-        ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
-      }
-      ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
-      break;
     }
-    case MotionNotify:
+    Standard_FALLTHROUGH
+    default:
     {
-      Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
-      if (anXWindow != aReport.xmotion.window)
-      {
-        break;
-      }
-
-      // remove all the ButtonMotionMask and process them at once
-      for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
-      {
-        if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
-        {
-          break;
-        }
-      }
-
-      Graphic3d_Vec2i aPos (aReport.xmotion.x, aReport.xmotion.y);
-      Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
-      Aspect_VKeyFlags aFlags   = Aspect_VKeyFlags_NONE;
-      if ((aReport.xmotion.state & Button1Mask) != 0)
+      const Handle(V3d_View)& aView = ViewerTest::CurrentView();
+      if (!aView.IsNull()
+       && !VT_GetWindow().IsNull())
       {
-        aButtons |= Aspect_VKeyMouse_LeftButton;
+        VT_GetWindow()->ProcessMessage (*ViewerTest::CurrentEventManager(), aReport);
       }
-      else if ((aReport.xmotion.state & Button2Mask) != 0)
-      {
-        aButtons |= Aspect_VKeyMouse_MiddleButton;
-      }
-      else if ((aReport.xmotion.state & Button3Mask) != 0)
-      {
-        aButtons |= Aspect_VKeyMouse_RightButton;
-      }
-
-      if (aReport.xmotion.state & ControlMask)
-      {
-        aFlags |= Aspect_VKeyFlags_CTRL;
-      }
-      if (aReport.xmotion.state & ShiftMask)
-      {
-        aFlags |= Aspect_VKeyFlags_SHIFT;
-      }
-      if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
-      {
-        aFlags |= Aspect_VKeyFlags_ALT;
-      }
-
-      ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
-      ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
       break;
     }
   }
index 0d1163e..e323ce0 100755 (executable)
@@ -7,5 +7,4 @@ WNT_WClass.cxx
 WNT_WClass.hxx
 WNT_Window.cxx
 WNT_Window.hxx
-WNT_Window.lxx
 WNT_WindowPtr.hxx
index 6408620..8f9ed39 100644 (file)
 #if defined(_WIN32) && !defined(OCCT_UWP)
 
 #include <Aspect_Convert.hxx>
+#include <Aspect_ScrollDelta.hxx>
 #include <Aspect_WindowDefinitionError.hxx>
 #include <Aspect_WindowError.hxx>
+#include <Aspect_WindowInputListener.hxx>
 #include <Message.hxx>
-#include <Standard_Type.hxx>
+#include <NCollection_LocalArray.hxx>
 #include <TCollection_ExtendedString.hxx>
 #include <WNT_WClass.hxx>
+#include <WNT_HIDSpaceMouse.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(WNT_Window, Aspect_Window)
 
@@ -47,11 +50,13 @@ WNT_Window::WNT_Window (const Standard_CString           theTitle,
                         const Aspect_Handle              theMenu,
                         const Standard_Address           theClientStruct)
 : Aspect_Window(),
-  aXLeft (thePxLeft),
-  aYTop (thePxTop),
-  aXRight (thePxLeft + thePxWidth),
-  aYBottom (thePxTop + thePxHeight),
   myWClass (theClass),
+  myHWindow (NULL),
+  myHParentWindow (NULL),
+  myXLeft (thePxLeft),
+  myYTop  (thePxTop),
+  myXRight (thePxLeft + thePxWidth),
+  myYBottom (thePxTop + thePxHeight),
   myIsForeign (Standard_False)
 {
   if (thePxWidth <= 0 || thePxHeight <= 0)
@@ -71,22 +76,22 @@ WNT_Window::WNT_Window (const Standard_CString           theTitle,
 
   // include decorations in the window dimensions to reproduce same behavior of Xw_Window
   RECT aRect;
-  aRect.top    = aYTop;
-  aRect.bottom = aYBottom;
-  aRect.left   = aXLeft;
-  aRect.right  = aXRight;
+  aRect.top    = myYTop;
+  aRect.bottom = myYBottom;
+  aRect.left   = myXLeft;
+  aRect.right  = myXRight;
   AdjustWindowRect (&aRect, aStyle, theMenu != NULL ? TRUE : FALSE);
-  aXLeft   = aRect.left;
-  aYTop    = aRect.top;
-  aXRight  = aRect.right;
-  aYBottom = aRect.bottom;
+  myXLeft   = aRect.left;
+  myYTop    = aRect.top;
+  myXRight  = aRect.right;
+  myYBottom = aRect.bottom;
 
   const TCollection_ExtendedString aTitleW (theTitle);
   const TCollection_ExtendedString aClassNameW (myWClass->Name());
   myHWindow = CreateWindowW (aClassNameW.ToWideString(), aTitleW.ToWideString(),
                              aStyle,
-                             aXLeft, aYTop,
-                             (aXRight - aXLeft), (aYBottom - aYTop),
+                             myXLeft, myYTop,
+                             (myXRight - myXLeft), (myYBottom - myYTop),
                              (HWND )theParent,
                              (HMENU )theMenu,
                              (HINSTANCE )myWClass->Instance(),
@@ -106,21 +111,24 @@ WNT_Window::WNT_Window (const Standard_CString           theTitle,
 // =======================================================================
 WNT_Window::WNT_Window (const Aspect_Handle        theHandle,
                         const Quantity_NameOfColor theBackColor)
-: myIsForeign (Standard_True)
+: myHWindow (theHandle),
+  myHParentWindow (GetParent ((HWND )theHandle)),
+  myXLeft (0),
+  myYTop  (0),
+  myXRight (0),
+  myYBottom (0),
+  myIsForeign (Standard_True)
 {
-  myHWindow        = theHandle;
-  myHParentWindow  = GetParent ((HWND )theHandle);
-
   SetBackground (theBackColor);
 
-  WINDOWPLACEMENT aPlace;
-  aPlace.length = sizeof (WINDOWPLACEMENT);
+  WINDOWPLACEMENT aPlace = {};
+  aPlace.length = sizeof(WINDOWPLACEMENT);
   ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
 
-  aXLeft   = aPlace.rcNormalPosition.left;
-  aYTop    = aPlace.rcNormalPosition.top;
-  aXRight  = aPlace.rcNormalPosition.right;
-  aYBottom = aPlace.rcNormalPosition.bottom;
+  myXLeft   = aPlace.rcNormalPosition.left;
+  myYTop    = aPlace.rcNormalPosition.top;
+  myXRight  = aPlace.rcNormalPosition.right;
+  myYBottom = aPlace.rcNormalPosition.bottom;
 }
 
 // =======================================================================
@@ -159,8 +167,8 @@ Standard_Boolean WNT_Window::IsMapped() const
     return Standard_True;
   }
 
-  WINDOWPLACEMENT aPlace;
-  aPlace.length = sizeof (WINDOWPLACEMENT);
+  WINDOWPLACEMENT aPlace = {};
+  aPlace.length = sizeof(WINDOWPLACEMENT);
   ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
   return !(aPlace.showCmd == SW_HIDE
         || aPlace.showCmd == SW_MINIMIZE);
@@ -213,60 +221,37 @@ Aspect_TypeOfResize WNT_Window::DoResize()
     return Aspect_TOR_UNKNOWN;
   }
 
-  int                 mask = 0;
-  Aspect_TypeOfResize mode = Aspect_TOR_UNKNOWN;
-  WINDOWPLACEMENT     wp;
-
-  wp.length = sizeof ( WINDOWPLACEMENT );
-  GetWindowPlacement (  ( HWND )myHWindow, &wp  );
-
-  if (wp.showCmd != SW_SHOWMINIMIZED)
+  WINDOWPLACEMENT aPlace = {};
+  aPlace.length = sizeof(WINDOWPLACEMENT);
+  GetWindowPlacement ((HWND )myHWindow, &aPlace);
+  if (aPlace.showCmd == SW_SHOWMINIMIZED)
   {
-    if (Abs ((int )wp.rcNormalPosition.left   - aXLeft  ) > 2) mask |= 1;
-    if (Abs ((int )wp.rcNormalPosition.right  - aXRight ) > 2) mask |= 2;
-    if (Abs ((int )wp.rcNormalPosition.top    - aYTop   ) > 2) mask |= 4;
-    if (Abs ((int )wp.rcNormalPosition.bottom - aYBottom) > 2) mask |= 8;
+    return Aspect_TOR_UNKNOWN;
+  }
 
-    switch (mask)
-    {
-      case 0:
-        mode = Aspect_TOR_NO_BORDER;
-        break;
-      case 1:
-        mode = Aspect_TOR_LEFT_BORDER;
-        break;
-      case 2:
-        mode = Aspect_TOR_RIGHT_BORDER;
-        break;
-      case 4:
-        mode = Aspect_TOR_TOP_BORDER;
-        break;
-      case 5:
-        mode = Aspect_TOR_LEFT_AND_TOP_BORDER;
-        break;
-      case 6:
-        mode = Aspect_TOR_TOP_AND_RIGHT_BORDER;
-        break;
-      case 8:
-        mode = Aspect_TOR_BOTTOM_BORDER;
-        break;
-      case 9:
-        mode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER;
-        break;
-      case 10:
-        mode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER;
-        break;
-      default:
-        break;
-    }  // end switch
-
-    aXLeft   = wp.rcNormalPosition.left;
-    aXRight  = wp.rcNormalPosition.right;
-    aYTop    = wp.rcNormalPosition.top;
-    aYBottom = wp.rcNormalPosition.bottom;
-  }
-
-  return mode;
+  int aMask = 0;
+  if (Abs ((int )aPlace.rcNormalPosition.left   - myXLeft  ) > 2) { aMask |= 1; }
+  if (Abs ((int )aPlace.rcNormalPosition.right  - myXRight ) > 2) { aMask |= 2; }
+  if (Abs ((int )aPlace.rcNormalPosition.top    - myYTop   ) > 2) { aMask |= 4; }
+  if (Abs ((int )aPlace.rcNormalPosition.bottom - myYBottom) > 2) { aMask |= 8; }
+
+  myXLeft   = aPlace.rcNormalPosition.left;
+  myXRight  = aPlace.rcNormalPosition.right;
+  myYTop    = aPlace.rcNormalPosition.top;
+  myYBottom = aPlace.rcNormalPosition.bottom;
+  switch (aMask)
+  {
+    case 0:  return Aspect_TOR_NO_BORDER;
+    case 1:  return Aspect_TOR_LEFT_BORDER;
+    case 2:  return Aspect_TOR_RIGHT_BORDER;
+    case 4:  return Aspect_TOR_TOP_BORDER;
+    case 5:  return Aspect_TOR_LEFT_AND_TOP_BORDER;
+    case 6:  return Aspect_TOR_TOP_AND_RIGHT_BORDER;
+    case 8:  return Aspect_TOR_BOTTOM_BORDER;
+    case 9:  return Aspect_TOR_BOTTOM_AND_LEFT_BORDER;
+    case 10: return Aspect_TOR_RIGHT_AND_BOTTOM_BORDER;
+  }
+  return Aspect_TOR_UNKNOWN;
 }
 
 // =======================================================================
@@ -277,10 +262,10 @@ Standard_Real WNT_Window::Ratio() const
 {
   if (IsVirtual())
   {
-    return Standard_Real(aXRight - aXLeft)/ Standard_Real(aYBottom - aYTop);
+    return Standard_Real(myXRight - myXLeft)/ Standard_Real(myYBottom - myYTop);
   }
 
-  RECT aRect;
+  RECT aRect = {};
   GetClientRect ((HWND )myHWindow, &aRect);
   return Standard_Real(aRect.right - aRect.left) / Standard_Real(aRect.bottom - aRect.top);
 }
@@ -294,14 +279,14 @@ void WNT_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1,
 {
   if (IsVirtual())
   {
-    theX1  = aXLeft;
-    theX2  = aXRight;
-    theY1  = aYTop;
-    theY2  = aYBottom;
+    theX1  = myXLeft;
+    theX2  = myXRight;
+    theY1  = myYTop;
+    theY2  = myYBottom;
     return;
   }
 
-  RECT  aRect;
+  RECT aRect = {};
   ::GetClientRect ((HWND )myHWindow, &aRect);
 
   POINT aPntLeft, aPntRight;
@@ -332,12 +317,12 @@ void WNT_Window::Size (Standard_Integer& theWidth,
 {
   if (IsVirtual())
   {
-    theWidth  = aXRight - aXLeft;
-    theHeight = aYBottom - aYTop;
+    theWidth  = myXRight - myXLeft;
+    theHeight = myYBottom - myYTop;
     return;
   }
 
-  RECT aRect;
+  RECT aRect = {};
   ::GetClientRect ((HWND )myHWindow, &aRect);
   theWidth  = aRect.right;
   theHeight = aRect.bottom;
@@ -350,10 +335,10 @@ void WNT_Window::Size (Standard_Integer& theWidth,
 void WNT_Window::SetPos (const Standard_Integer theX,  const Standard_Integer theY,
                          const Standard_Integer theX1, const Standard_Integer theY1)
 {
-  aXLeft   = theX;
-  aYTop    = theY;
-  aXRight  = theX1;
-  aYBottom = theY1;
+  myXLeft   = theX;
+  myYTop    = theY;
+  myXRight  = theX1;
+  myYBottom = theY1;
 }
 
 // =======================================================================
@@ -699,4 +684,197 @@ int WNT_Window::RegisterRawInputDevices (unsigned int theRawDeviceMask)
   return 0;
 }
 
+// =======================================================================
+// function : ProcessMessage
+// purpose  :
+// =======================================================================
+bool WNT_Window::ProcessMessage (Aspect_WindowInputListener& theListener,
+                                 MSG& theMsg)
+{
+  switch (theMsg.message)
+  {
+    case WM_CLOSE:
+    {
+      if (theMsg.hwnd == (HWND )myHWindow)
+      {
+        theListener.ProcessClose();
+        return true;
+      }
+      return false;
+    }
+    case WM_ACTIVATE:
+    {
+      if (theMsg.hwnd == (HWND )myHWindow)
+      {
+        theListener.ProcessFocus (LOWORD(theMsg.wParam) == WA_CLICKACTIVE
+                               || LOWORD(theMsg.wParam) == WA_ACTIVE);
+        return true;
+      }
+      return false;
+    }
+    case WM_PAINT:
+    {
+      PAINTSTRUCT aPaint;
+      BeginPaint(theMsg.hwnd, &aPaint);
+      EndPaint  (theMsg.hwnd, &aPaint);
+      theListener.ProcessExpose();
+      return true;
+    }
+    case WM_SIZE:
+    case WM_MOVE:
+    case WM_MOVING:
+    case WM_SIZING:
+    {
+      theListener.ProcessConfigure (theMsg.message == WM_SIZE);
+      return true;
+    }
+    case WM_KEYUP:
+    case WM_KEYDOWN:
+    {
+      const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )theMsg.wParam);
+      if (aVKey != Aspect_VKey_UNKNOWN)
+      {
+        const double aTimeStamp = theListener.EventTime();
+        if (theMsg.message == WM_KEYDOWN)
+        {
+          theListener.KeyDown (aVKey, aTimeStamp);
+        }
+        else
+        {
+          theListener.KeyUp (aVKey, aTimeStamp);
+        }
+        theListener.ProcessInput();
+      }
+      return true;
+    }
+    case WM_LBUTTONUP:
+    case WM_MBUTTONUP:
+    case WM_RBUTTONUP:
+    case WM_LBUTTONDOWN:
+    case WM_MBUTTONDOWN:
+    case WM_RBUTTONDOWN:
+    {
+      const Graphic3d_Vec2i aPos (LOWORD(theMsg.lParam), HIWORD(theMsg.lParam));
+      const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theMsg.wParam);
+      Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
+      switch (theMsg.message)
+      {
+        case WM_LBUTTONUP:
+        case WM_LBUTTONDOWN:
+          aButton = Aspect_VKeyMouse_LeftButton;
+          break;
+        case WM_MBUTTONUP:
+        case WM_MBUTTONDOWN:
+          aButton = Aspect_VKeyMouse_MiddleButton;
+          break;
+        case WM_RBUTTONUP:
+        case WM_RBUTTONDOWN:
+          aButton = Aspect_VKeyMouse_RightButton;
+          break;
+      }
+      if (theMsg.message == WM_LBUTTONDOWN
+       || theMsg.message == WM_MBUTTONDOWN
+       || theMsg.message == WM_RBUTTONDOWN)
+      {
+        SetFocus  (theMsg.hwnd);
+        SetCapture(theMsg.hwnd);
+        theListener.PressMouseButton (aPos, aButton, aFlags, false);
+      }
+      else
+      {
+        ReleaseCapture();
+        theListener.ReleaseMouseButton (aPos, aButton, aFlags, false);
+      }
+      theListener.ProcessInput();
+      return true;
+    }
+    case WM_MOUSEWHEEL:
+    {
+      const int aDelta = GET_WHEEL_DELTA_WPARAM (theMsg.wParam);
+      const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
+      const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theMsg.wParam);
+      Graphic3d_Vec2i aPos (int(short(LOWORD(theMsg.lParam))), int(short(HIWORD(theMsg.lParam))));
+      POINT aCursorPnt = { aPos.x(), aPos.y() };
+      if (ScreenToClient (theMsg.hwnd, &aCursorPnt))
+      {
+        aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
+      }
+
+      if (theMsg.hwnd != (HWND )myHWindow)
+      {
+        return false;
+      }
+
+      theListener.UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
+      theListener.ProcessInput();
+      return true;
+    }
+    case WM_MOUSEMOVE:
+    {
+      Graphic3d_Vec2i aPos (LOWORD(theMsg.lParam), HIWORD(theMsg.lParam));
+      Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (theMsg.wParam);
+      Aspect_VKeyFlags aFlags   = WNT_Window::MouseKeyFlagsFromEvent(theMsg.wParam);
+
+      // don't make a slide-show from input events - fetch the actual mouse cursor position
+      CURSORINFO aCursor;
+      aCursor.cbSize = sizeof(aCursor);
+      if (::GetCursorInfo (&aCursor) != FALSE)
+      {
+        POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
+        if (ScreenToClient (theMsg.hwnd, &aCursorPnt))
+        {
+          // as we override mouse position, we need overriding also mouse state
+          aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
+          aButtons = WNT_Window::MouseButtonsAsync();
+          aFlags   = WNT_Window::MouseKeyFlagsAsync();
+        }
+      }
+
+      if (theMsg.hwnd != (HWND )myHWindow)
+      {
+        // mouse move events come also for inactive windows
+        return false;
+      }
+
+      theListener.UpdateMousePosition (aPos, aButtons, aFlags, false);
+      theListener.ProcessInput();
+      return true;
+    }
+    case WM_INPUT:
+    {
+      UINT aSize = 0;
+      ::GetRawInputData ((HRAWINPUT )theMsg.lParam, RID_INPUT, NULL, &aSize, sizeof(RAWINPUTHEADER));
+      NCollection_LocalArray<BYTE> aRawData (aSize);
+      if (aSize == 0 || ::GetRawInputData ((HRAWINPUT )theMsg.lParam, RID_INPUT, aRawData, &aSize, sizeof(RAWINPUTHEADER)) != aSize)
+      {
+        return true;
+      }
+
+      const RAWINPUT* aRawInput = (RAWINPUT* )(BYTE* )aRawData;
+      if (aRawInput->header.dwType != RIM_TYPEHID)
+      {
+        return true;
+      }
+
+      RID_DEVICE_INFO aDevInfo;
+      aDevInfo.cbSize = sizeof(RID_DEVICE_INFO);
+      UINT aDevInfoSize = sizeof(RID_DEVICE_INFO);
+      if (::GetRawInputDeviceInfoW (aRawInput->header.hDevice, RIDI_DEVICEINFO, &aDevInfo, &aDevInfoSize) != sizeof(RID_DEVICE_INFO)
+       || (aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_LOGITECH
+        && aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_3DCONNEXION))
+      {
+        return true;
+      }
+
+      WNT_HIDSpaceMouse aSpaceData (aDevInfo.hid.dwProductId, aRawInput->data.hid.bRawData, aRawInput->data.hid.dwSizeHid);
+      if (theListener.Update3dMouse (aSpaceData))
+      {
+        InvalidateContent (Handle(Aspect_DisplayConnection)());
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
 #endif // _WIN32
index c056a5e..530ece4 100644 (file)
 #include <Aspect_Drawable.hxx>
 #include <Aspect_VKey.hxx>
 #include <Aspect_Handle.hxx>
-#include <Standard_Type.hxx>
 #include <WNT_Dword.hxx>
 
+class Aspect_WindowInputListener;
 class WNT_WClass;
+typedef struct tagMSG MSG;
 
 DEFINE_STANDARD_HANDLE(WNT_Window, Aspect_Window)
 
 //! This class defines Windows NT window
 class WNT_Window : public Aspect_Window
 {
+  DEFINE_STANDARD_RTTIEXT(WNT_Window, Aspect_Window)
 public:
 
   //! Convert WInAPI virtual key (VK_ enumeration) into Aspect_VKey.
@@ -53,42 +55,45 @@ public:
 
 public:
 
-  //! Creates a Window defined by his position and size
-  //! in pixles from the Parent Window.
-  //! Trigger: Raises WindowDefinitionError if the Position out of the
-  //! Screen Space or the window creation failed.
-  Standard_EXPORT WNT_Window(const Standard_CString theTitle, const Handle(WNT_WClass)& theClass, const WNT_Dword& theStyle, const Standard_Integer thePxLeft, const Standard_Integer thePxTop, const Standard_Integer thePxWidth, const Standard_Integer thePxHeight, const Quantity_NameOfColor theBackColor = Quantity_NOC_MATRAGRAY, const Aspect_Handle theParent = 0, const Aspect_Handle theMenu = 0, const Standard_Address theClientStruct = 0);
-  
+  //! Creates a Window defined by his position and size in pixels from the Parent Window.
+  //! Trigger: Raises WindowDefinitionError if the Position out of the Screen Space or the window creation failed.
+  Standard_EXPORT WNT_Window (const Standard_CString theTitle,
+                              const Handle(WNT_WClass)& theClass,
+                              const WNT_Dword& theStyle,
+                              const Standard_Integer thePxLeft,  const Standard_Integer thePxTop,
+                              const Standard_Integer thePxWidth, const Standard_Integer thePxHeight,
+                              const Quantity_NameOfColor theBackColor = Quantity_NOC_MATRAGRAY,
+                              const Aspect_Handle theParent = 0,
+                              const Aspect_Handle theMenu = 0,
+                              const Standard_Address theClientStruct = 0);
+
   //! Creates a Window based on the existing window handle.
-  //! This handle equals ( aPart1 << 16 ) + aPart2.
-  Standard_EXPORT WNT_Window(const Aspect_Handle aHandle, const Quantity_NameOfColor aBackColor = Quantity_NOC_MATRAGRAY);
-  
-  //! Destroys the Window and all resourses attached to it.
-  Standard_EXPORT ~WNT_Window();
-  
-  //! Sets cursor <aCursor> for ENTIRE WINDOW CLASS to which
-  //! the Window belongs.
-  Standard_EXPORT void SetCursor (const Aspect_Handle aCursor) const;
-  
+  Standard_EXPORT WNT_Window (const Aspect_Handle theHandle,
+                              const Quantity_NameOfColor theBackColor = Quantity_NOC_MATRAGRAY);
+
+  //! Destroys the Window and all resources attached to it.
+  Standard_EXPORT virtual ~WNT_Window();
+
+  //! Sets cursor for ENTIRE WINDOW CLASS to which the Window belongs.
+  Standard_EXPORT void SetCursor (const Aspect_Handle theCursor) const;
+
   //! Opens the window <me>.
   Standard_EXPORT virtual void Map() const Standard_OVERRIDE;
   
-  //! Opens a window <me> according to <aMapMode>.
+  //! Opens a window according to the map mode.
   //! This method is specific to Windows NT.
-  //! <aMapMode> can be one of SW_xxx constants defined
-  //! in <windows.h>. See documentation.
-  Standard_EXPORT void Map (const Standard_Integer aMapMode) const;
-  
+  //! @param theMapMode [in] can be one of SW_xxx constants defined in <windows.h>
+  Standard_EXPORT void Map (const Standard_Integer theMapMode) const;
+
   //! Closes the window <me>.
   Standard_EXPORT virtual void Unmap() const Standard_OVERRIDE;
   
   //! Applies the resizing to the window <me>.
   Standard_EXPORT virtual Aspect_TypeOfResize DoResize() Standard_OVERRIDE;
   
-  //! Apply the mapping change to the window <me>
-  //! and returns TRUE if the window is mapped at screen.
-  virtual Standard_Boolean DoMapping() const Standard_OVERRIDE;
-  
+  //! Does nothing on Windows.
+  virtual Standard_Boolean DoMapping() const Standard_OVERRIDE { return Standard_True; }
+
   //! Changes variables due to window position.
   Standard_EXPORT void SetPos (const Standard_Integer X, const Standard_Integer Y, const Standard_Integer X1, const Standard_Integer Y1);
   
@@ -106,17 +111,11 @@ public:
   //! Returns The Window SIZE in PIXEL
   Standard_EXPORT virtual void Size (Standard_Integer& Width, Standard_Integer& Height) const Standard_OVERRIDE;
   
-  //! Returns the Windows NT handle of the created window <me>.
-  Aspect_Handle HWindow() const;
-  
-  //! Returns the Windows NT handle parent of the created window <me>.
-  Aspect_Handle HParentWindow() const;
-  
   //! Returns native Window handle (HWND)
-  virtual Aspect_Drawable NativeHandle() const Standard_OVERRIDE;
+  virtual Aspect_Drawable NativeHandle() const Standard_OVERRIDE { return (Aspect_Drawable )myHWindow; }
   
-  //! Returns parent of native Window handle (HWND on Windows, Window with Xlib, and so on)
-  virtual Aspect_Drawable NativeParentHandle() const Standard_OVERRIDE;
+  //! Returns parent of native Window handle (HWND on Windows).
+  virtual Aspect_Drawable NativeParentHandle() const Standard_OVERRIDE { return (Aspect_Drawable )myHParentWindow; }
 
   //! Returns nothing on Windows
   virtual Aspect_FBConfig NativeFBConfig() const Standard_OVERRIDE { return NULL; }
@@ -126,7 +125,15 @@ public:
 
   //! Invalidate entire window content by calling InvalidateRect() WinAPI function, resulting in WM_PAINT event put into window message loop.
   //! Method can be called from non-window thread, and system will also automatically aggregate multiple events into single one.
-  Standard_EXPORT virtual void InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp = NULL) Standard_OVERRIDE;
+  Standard_EXPORT virtual void InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp = Handle(Aspect_DisplayConnection)()) Standard_OVERRIDE;
+
+public:
+
+  //! Returns the Windows NT handle of the created window <me>.
+  Aspect_Handle HWindow() const { return myHWindow; }
+
+  //! Returns the Windows NT handle parent of the created window <me>.
+  Aspect_Handle HParentWindow() const { return myHParentWindow; }
 
   //! Raw input flags.
   enum RawInputMask
@@ -140,22 +147,25 @@ public:
   //! @return number of actually registered device types
   Standard_EXPORT int RegisterRawInputDevices (unsigned int theRawDeviceMask);
 
-  DEFINE_STANDARD_RTTIEXT(WNT_Window,Aspect_Window)
+  //! Process a single window message.
+  //! @param theListener [in][out] listener to redirect message
+  //! @param theMsg [in][out] message to process
+  //! @return TRUE if message has been processed
+  Standard_EXPORT virtual bool ProcessMessage (Aspect_WindowInputListener& theListener,
+                                               MSG& theMsg);
 
 protected:
 
-  Standard_Integer aXLeft;
-  Standard_Integer aYTop;
-  Standard_Integer aXRight;
-  Standard_Integer aYBottom;
   Handle(WNT_WClass) myWClass;
-  Aspect_Handle myHWindow;
-  Aspect_Handle myHParentWindow;
+  Aspect_Handle    myHWindow;
+  Aspect_Handle    myHParentWindow;
+  Standard_Integer myXLeft;
+  Standard_Integer myYTop;
+  Standard_Integer myXRight;
+  Standard_Integer myYBottom;
   Standard_Boolean myIsForeign;
 
 };
 
-#include <WNT_Window.lxx>
-
 #endif // _WIN32
 #endif // _WNT_Window_HeaderFile
diff --git a/src/WNT/WNT_Window.lxx b/src/WNT/WNT_Window.lxx
deleted file mode 100644 (file)
index ca2184d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 1996-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.
-
-inline Standard_Boolean WNT_Window::DoMapping() const
-{
-  // DO nothing on WNT
-  return Standard_True;
-}
-
-inline Aspect_Handle WNT_Window::HWindow() const
-{
-  return myHWindow;
-}
-
-inline Aspect_Handle WNT_Window::HParentWindow() const
-{
-  return myHParentWindow;
-}
-
-inline Aspect_Drawable WNT_Window::NativeHandle() const
-{
-  return (Aspect_Drawable )myHWindow;
-}
-
-inline Aspect_Drawable WNT_Window::NativeParentHandle() const
-{
-  return (Aspect_Drawable )myHParentWindow;
-}
index c3d9de7..47d93dc 100644 (file)
@@ -18,7 +18,9 @@
 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
 
 #include <Aspect_Convert.hxx>
+#include <Aspect_ScrollDelta.hxx>
 #include <Aspect_WindowDefinitionError.hxx>
+#include <Aspect_WindowInputListener.hxx>
 #include <Message.hxx>
 #include <Message_Messenger.hxx>
 
@@ -531,4 +533,168 @@ Aspect_VKey Xw_Window::VirtualKeyFromNative (unsigned long theKey)
   return Aspect_VKey_UNKNOWN;
 }
 
+// =======================================================================
+// function : ProcessMessage
+// purpose  :
+// =======================================================================
+bool Xw_Window::ProcessMessage (Aspect_WindowInputListener& theListener,
+                                XEvent& theMsg)
+{
+  Display* aDisplay = myDisplay->GetDisplay();
+
+  // Handle event for the chosen display connection
+  switch (theMsg.type)
+  {
+    case ClientMessage:
+    {
+      if ((Atom)theMsg.xclient.data.l[0] == myDisplay->GetAtom (Aspect_XA_DELETE_WINDOW)
+       && theMsg.xclient.window == myXWindow)
+      {
+        theListener.ProcessClose();
+        return true;
+      }
+      return false;
+    }
+    case FocusIn:
+    case FocusOut:
+    {
+      if (theMsg.xfocus.window == myXWindow)
+      {
+        theListener.ProcessFocus (theMsg.type == FocusIn);
+      }
+      return true;
+    }
+    case Expose:
+    {
+      if (theMsg.xexpose.window == myXWindow)
+      {
+        theListener.ProcessExpose();
+      }
+
+      // remove all the ExposureMask and process them at once
+      for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
+      {
+        if (!XCheckWindowEvent (aDisplay, myXWindow, ExposureMask, &theMsg))
+        {
+          break;
+        }
+      }
+
+      return true;
+    }
+    case ConfigureNotify:
+    {
+      // remove all the StructureNotifyMask and process them at once
+      for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
+      {
+        if (!XCheckWindowEvent (aDisplay, myXWindow, StructureNotifyMask, &theMsg))
+        {
+          break;
+        }
+      }
+
+      if (theMsg.xconfigure.window == myXWindow)
+      {
+        theListener.ProcessConfigure (true);
+      }
+      return true;
+    }
+    case KeyPress:
+    case KeyRelease:
+    {
+      XKeyEvent*   aKeyEvent = (XKeyEvent* )&theMsg;
+      const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
+      const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
+      if (aVKey != Aspect_VKey_UNKNOWN)
+      {
+        const double aTimeStamp = theListener.EventTime();
+        if (theMsg.type == KeyPress)
+        {
+          theListener.KeyDown (aVKey, aTimeStamp);
+        }
+        else
+        {
+          theListener.KeyUp (aVKey, aTimeStamp);
+        }
+        theListener.ProcessInput();
+      }
+      return true;
+    }
+    case ButtonPress:
+    case ButtonRelease:
+    {
+      const Graphic3d_Vec2i aPos (theMsg.xbutton.x, theMsg.xbutton.y);
+      Aspect_VKeyFlags aFlags  = Aspect_VKeyFlags_NONE;
+      Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
+      if (theMsg.xbutton.button == Button1) { aButton = Aspect_VKeyMouse_LeftButton; }
+      if (theMsg.xbutton.button == Button2) { aButton = Aspect_VKeyMouse_MiddleButton; }
+      if (theMsg.xbutton.button == Button3) { aButton = Aspect_VKeyMouse_RightButton; }
+
+      if ((theMsg.xbutton.state & ControlMask) != 0) { aFlags |= Aspect_VKeyFlags_CTRL; }
+      if ((theMsg.xbutton.state & ShiftMask)   != 0) { aFlags |= Aspect_VKeyFlags_SHIFT; }
+      if (theListener.Keys().IsKeyDown (Aspect_VKey_Alt))
+      {
+        aFlags |= Aspect_VKeyFlags_ALT;
+      }
+
+      if (theMsg.xbutton.button == Button4
+       || theMsg.xbutton.button == Button5)
+      {
+        if (theMsg.type != ButtonPress)
+        {
+          return true;
+        }
+
+        const double aDeltaF = (theMsg.xbutton.button == Button4 ? 1.0 : -1.0);
+        theListener.UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
+      }
+      else if (theMsg.type == ButtonPress)
+      {
+        theListener.PressMouseButton (aPos, aButton, aFlags, false);
+      }
+      else
+      {
+        theListener.ReleaseMouseButton (aPos, aButton, aFlags, false);
+      }
+      theListener.ProcessInput();
+      return true;
+    }
+    case MotionNotify:
+    {
+      if (theMsg.xmotion.window != myXWindow)
+      {
+        return false;
+      }
+
+      // remove all the ButtonMotionMask and process them at once
+      for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
+      {
+        if (!XCheckWindowEvent (aDisplay, myXWindow, ButtonMotionMask | PointerMotionMask, &theMsg))
+        {
+          break;
+        }
+      }
+
+      Graphic3d_Vec2i aPos (theMsg.xmotion.x, theMsg.xmotion.y);
+      Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
+      Aspect_VKeyFlags aFlags   = Aspect_VKeyFlags_NONE;
+      if ((theMsg.xmotion.state & Button1Mask) != 0) { aButtons |= Aspect_VKeyMouse_LeftButton; }
+      if ((theMsg.xmotion.state & Button2Mask) != 0) { aButtons |= Aspect_VKeyMouse_MiddleButton; }
+      if ((theMsg.xmotion.state & Button3Mask) != 0) { aButtons |= Aspect_VKeyMouse_RightButton; }
+
+      if ((theMsg.xmotion.state & ControlMask) != 0) { aFlags |= Aspect_VKeyFlags_CTRL; }
+      if ((theMsg.xmotion.state & ShiftMask)   != 0) { aFlags |= Aspect_VKeyFlags_SHIFT; }
+      if (theListener.Keys().IsKeyDown (Aspect_VKey_Alt))
+      {
+        aFlags |= Aspect_VKeyFlags_ALT;
+      }
+
+      theListener.UpdateMousePosition (aPos, aButtons, aFlags, false);
+      theListener.ProcessInput();
+      return true;
+    }
+  }
+  return false;
+}
+
 #endif //  Win32 or Mac OS X
index 0ba84dd..bda1c4d 100644 (file)
@@ -32,6 +32,7 @@
 
 class Aspect_WindowDefinitionError;
 class Aspect_WindowError;
+class Aspect_WindowInputListener;
 class Aspect_Background;
 class Quantity_Color;
 class Aspect_GradientBackground;
@@ -125,6 +126,13 @@ public:
   //! for this working thread to avoid race conditions, since Xlib display connection is not thread-safe by default.
   Standard_EXPORT virtual void InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp) Standard_OVERRIDE;
 
+  //! Process a single window message.
+  //! @param theListener [in][out] listener to redirect message
+  //! @param theMsg [in][out] message to process
+  //! @return TRUE if message has been processed
+  Standard_EXPORT virtual bool ProcessMessage (Aspect_WindowInputListener& theListener,
+                                               XEvent& theMsg);
+
 protected:
 
   Handle(Aspect_DisplayConnection) myDisplay; //!< X Display connection