Salome HOME
updated copyright message
[modules/gui.git] / src / SVTK / SVTK_RenderWindowInteractor.cxx
index 4921f63f91ddc18db502c26b2970c206d585714b..3406d70136202bcad7bf040d7a5a3b9b7864e3dc 100644 (file)
@@ -1,39 +1,45 @@
-//  SALOME VTKViewer : build VTK viewer into Salome desktop
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
 //
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
 //
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SALOME VTKViewer : build VTK viewer into Salome desktop
 //  File   : 
 //  Author : 
-//  Module : SALOME
-//  $Header$
 
 #include "SVTK_RenderWindowInteractor.h"
-#include "SVTK_GenericRenderWindowInteractor.h"
 
 #include "SVTK_InteractorStyle.h"
 #include "SVTK_Renderer.h"
 #include "SVTK_Functor.h"
 #include "SALOME_Actor.h"
 
+// QT Includes
+// Put Qt includes before the X11 includes which #define the symbol None
+// (see SVTK_SpaceMouse.h) to avoid the compilation error.
+#if !defined(WIN32) && !defined(__APPLE__)
+#include <xcb/xcb.h>
+#include <QX11Info>
+#endif
+#include <QMouseEvent>
+
 #include "SVTK_SpaceMouse.h" 
 #include "SVTK_Event.h" 
 
 #include <vtkPicker.h>
 #include <vtkCamera.h>
 
-// QT Includes
-#include <qtimer.h>
-#include <qapplication.h>
-#include <qcolordialog.h>
-#include <qpaintdevice.h>
-
-using namespace std;
-
-static bool GENERATE_SUIT_EVENTS = false;
+static bool GENERATE_SUIT_EVENTS = true;
 static bool FOCUS_UNDER_MOUSE = false;
 
+// workaround about the bug in vtkImplicitPlaneWidget class
+// that eats mouse button release event
+// causing clipping plane preview in SMESH sticking up
+#define Fix_Of_vtkImplicitPlaneWidget_bug
 
 /*!
   Constructor
 */
 QVTK_RenderWindowInteractor
 ::QVTK_RenderWindowInteractor(QWidget* theParent, 
-                             const char* theName):
-  QWidget(theParent,theName,Qt::WNoAutoErase),
+                              const char* theName):
+  QWidget(theParent),
   myRenderWindow(vtkRenderWindow::New())
 {
+  setAttribute( Qt::WA_PaintOnScreen );
+  setAttribute( Qt::WA_NoSystemBackground );
+
+  setObjectName(theName);
+
   setMouseTracking(true);
 
   myRenderWindow->Delete();
   myRenderWindow->DoubleBufferOn();
 
-#ifndef WNT
-  myRenderWindow->SetDisplayId((void*)x11Display());
+#if !defined WIN32 && !defined __APPLE__
+  myRenderWindow->SetDisplayId((void*)QX11Info::display());
 #endif
   myRenderWindow->SetWindowId((void*)winId());
 }
@@ -88,13 +95,13 @@ void
 QVTK_RenderWindowInteractor
 ::Initialize(vtkGenericRenderWindowInteractor* theDevice)
 {
-  if(GetDevice())
-    myDevice->SetRenderWindow(NULL);
+  if ( GetDevice() )
+    myDevice->SetRenderWindow( NULL );
 
   myDevice = theDevice;
 
-  if(theDevice)
-    theDevice->SetRenderWindow(getRenderWindow());
+  if ( theDevice )
+    theDevice->SetRenderWindow( getRenderWindow() );
 }
 
 /*!
@@ -103,9 +110,11 @@ QVTK_RenderWindowInteractor
 QVTK_RenderWindowInteractor
 ::~QVTK_RenderWindowInteractor() 
 {
-  if(SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance())
-    if(aSpaceMouse->isSpaceMouseOn())
-      aSpaceMouse->close(x11Display());
+#if !defined WIN32 && !defined __APPLE__
+  SVTK_SpaceMouseXCB* aSpaceMouse = SVTK_SpaceMouseXCB::getInstance();
+  if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
+    aSpaceMouse->close( QX11Info::connection() );
+#endif
 }
 
 
@@ -139,6 +148,14 @@ QVTK_RenderWindowInteractor
   GetDevice()->InvokeEvent(theEvent,theCallData);
 }
 
+/*!
+  Get paint engine for the scene
+*/
+QPaintEngine* QVTK_RenderWindowInteractor::paintEngine() const
+{
+  return 0;
+}
+
 /*!
   Need for initial contents display on Win32
 */
@@ -159,7 +176,7 @@ QVTK_RenderWindowInteractor
 {
   // Final initialization just before the widget is displayed
   GetDevice()->SetSize(width(),height());
-  if(!GetDevice()->GetInitialized()){
+  if(!GetDevice()->GetInitialized() && GetDevice()->GetRenderWindow()){
     GetDevice()->Initialize();
     GetDevice()->ConfigureEvent();
   }
@@ -180,7 +197,7 @@ QVTK_RenderWindowInteractor
 */
 void
 QVTK_RenderWindowInteractor
-::paintEvent( QPaintEvent* theEvent ) 
+::paintEvent( QPaintEvent* /*theEvent*/ ) 
 {
   GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
 }
@@ -191,7 +208,7 @@ QVTK_RenderWindowInteractor
 */
 void
 QVTK_RenderWindowInteractor
-::resizeEvent( QResizeEvent* theEvent )
+::resizeEvent( QResizeEvent* /*theEvent*/ )
 {
   int* aSize = getRenderWindow()->GetSize();
   int aWidth = aSize[0];
@@ -205,13 +222,13 @@ QVTK_RenderWindowInteractor
       aRenderers->InitTraversal();
       double aCoeff = 1.0;
       if(vtkRenderer *aRenderer = aRenderers->GetNextItem()) {
-       vtkCamera *aCamera = aRenderer->GetActiveCamera();
-       double aScale = aCamera->GetParallelScale();
-       if((aWidth - width())*(aHeight - height()) > 0)
-         aCoeff = sqrt(double(aWidth)/double(width())*double(height())/double(aHeight));
-       else
-         aCoeff = double(aWidth)/double(width());
-       aCamera->SetParallelScale(aScale*aCoeff);
+        vtkCamera *aCamera = aRenderer->GetActiveCamera();
+        double aScale = aCamera->GetParallelScale();
+        if((aWidth - width())*(aHeight - height()) > 0)
+          aCoeff = sqrt(double(aWidth)/double(width())*double(height())/double(aHeight));
+        else
+          aCoeff = double(aWidth)/double(width());
+        aCamera->SetParallelScale(aScale*aCoeff);
       }
     }
   }
@@ -226,7 +243,7 @@ QVTK_RenderWindowInteractor
 */
 void
 QVTK_RenderWindowInteractor
-::contextMenuEvent( QContextMenuEvent* event )
+::contextMenuEvent( QContextMenuEvent* /*event*/ )
 {}
 
 /*!
@@ -237,9 +254,9 @@ QVTK_RenderWindowInteractor
 ::mouseMoveEvent( QMouseEvent* event ) 
 {
   GetDevice()->SetEventInformationFlipY(event->x(), 
-                                       event->y(),
-                                       event->state() & ControlButton,
-                                       event->state() & ShiftButton);
+                                        event->y(),
+                                        event->modifiers() & Qt::ControlModifier,
+                                        event->modifiers() & Qt::ShiftModifier);
   GetDevice()->MouseMoveEvent();
 }
 
@@ -252,14 +269,14 @@ QVTK_RenderWindowInteractor
 ::mousePressEvent( QMouseEvent* event ) 
 {
   GetDevice()->SetEventInformationFlipY(event->x(), 
-                                       event->y(),
-                                       event->state() & ControlButton,
-                                       event->state() & ShiftButton);
-  if( event->button() & LeftButton )
+                                        event->y(),
+                                        event->modifiers() & Qt::ControlModifier,
+                                        event->modifiers() & Qt::ShiftModifier);
+  if( event->button() & Qt::LeftButton )
     GetDevice()->LeftButtonPressEvent();
-  else if( event->button() & MidButton )
+  else if( event->button() & Qt::MidButton )
     GetDevice()->MiddleButtonPressEvent();
-  else if( event->button() & RightButton )
+  else if( event->button() & Qt::RightButton )
     GetDevice()->RightButtonPressEvent();
 }
 
@@ -272,16 +289,30 @@ QVTK_RenderWindowInteractor
 ::mouseReleaseEvent( QMouseEvent *event )
 {
   GetDevice()->SetEventInformationFlipY(event->x(), 
-                                       event->y(),
-                                       event->state() & ControlButton,
-                                       event->state() & ShiftButton);
+                                        event->y(),
+                                        event->modifiers() & Qt::ControlModifier,
+                                        event->modifiers() & Qt::ShiftModifier);
 
-  if( event->button() & LeftButton )
+  if( event->button() & Qt::LeftButton )
     GetDevice()->LeftButtonReleaseEvent();
-  else if( event->button() & MidButton )
+  else if( event->button() & Qt::MidButton )
     GetDevice()->MiddleButtonReleaseEvent();
-  else if( event->button() & RightButton )
+  else if( event->button() & Qt::RightButton ) {
+#if defined(Fix_Of_vtkImplicitPlaneWidget_bug)
+    GetDevice()->SetEventInformationFlipY( -99999, -99999,
+                                           event->modifiers() & Qt::ControlModifier,
+                                           event->modifiers() & Qt::ShiftModifier);
+    bool blocked = blockSignals( true );
+    GetDevice()->LeftButtonPressEvent();
+    GetDevice()->LeftButtonReleaseEvent();
+    blockSignals( blocked );
+    GetDevice()->SetEventInformationFlipY(event->x(),
+                                          event->y(),
+                                          event->modifiers() & Qt::ControlModifier,
+                                          event->modifiers() & Qt::ShiftModifier);
+#endif
     GetDevice()->RightButtonReleaseEvent();
+  }
 }
 
 
@@ -290,7 +321,7 @@ QVTK_RenderWindowInteractor
 */
 void
 QVTK_RenderWindowInteractor
-::mouseDoubleClickEvent( QMouseEvent* event )
+::mouseDoubleClickEvent( QMouseEvent* /*event*/ )
 {}
 
 
@@ -301,8 +332,16 @@ void
 QVTK_RenderWindowInteractor
 ::wheelEvent( QWheelEvent* event )
 {
-  setActiveWindow();
+  activateWindow();
   setFocus();
+  GetDevice()->SetEventInformationFlipY(event->x(), 
+                                        event->y(),
+                                        event->modifiers() & Qt::ControlModifier,
+                                        event->modifiers() & Qt::ShiftModifier);
+  if ( event->delta()>0)
+    GetDevice()->MouseWheelForwardEvent();
+  else
+    GetDevice()->MouseWheelBackwardEvent();
 }
 
 
@@ -313,9 +352,9 @@ void
 QVTK_RenderWindowInteractor
 ::keyPressEvent( QKeyEvent* event ) 
 {
-  GetDevice()->SetKeyEventInformation(event->state() & ControlButton,
-                                     event->state() & ShiftButton,
-                                     event->key());
+  GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
+                                      event->modifiers() & Qt::ShiftModifier,
+                                      event->key());
   GetDevice()->KeyPressEvent();
   GetDevice()->CharEvent();
 }
@@ -327,9 +366,9 @@ void
 QVTK_RenderWindowInteractor
 ::keyReleaseEvent( QKeyEvent * event ) 
 {
-  GetDevice()->SetKeyEventInformation(event->state() & ControlButton,
-                                     event->state() & ShiftButton,
-                                     event->key());
+  GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
+                                      event->modifiers() & Qt::ShiftModifier,
+                                      event->key());
   GetDevice()->KeyReleaseEvent();
 }
 
@@ -339,10 +378,10 @@ QVTK_RenderWindowInteractor
 */
 void  
 QVTK_RenderWindowInteractor
-::enterEvent( QEvent* event )
+::enterEvent( QEvent* /*event*/ )
 {
   if(FOCUS_UNDER_MOUSE){
-    setActiveWindow();
+    activateWindow();
     setFocus();
   }
   GetDevice()->EnterEvent();
@@ -368,14 +407,18 @@ QVTK_RenderWindowInteractor
 {
   QWidget::focusInEvent( event );
 
+#if !defined WIN32 && !defined __APPLE__
   // register set space mouse events receiver
-  if(SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance()){
-    if(!aSpaceMouse->isSpaceMouseOn()) {// initialize 3D space mouse driver 
-      aSpaceMouse->initialize(x11Display(),winId());
-    }else{
-      aSpaceMouse->setWindow(x11Display(),winId());
-    }
+  SVTK_SpaceMouseXCB* aSpaceMouse = SVTK_SpaceMouseXCB::getInstance();
+  if ( aSpaceMouse )
+  {
+    if ( !aSpaceMouse->isSpaceMouseOn() )
+      // initialize 3D space mouse driver
+      aSpaceMouse->initialize( QX11Info::connection(), winId() );
+    else
+      aSpaceMouse->setWindow( QX11Info::connection(), winId() );
   }
+#endif
 }
 
 /*!
@@ -388,41 +431,45 @@ QVTK_RenderWindowInteractor
 {
   QWidget::focusOutEvent( event );
 
-  // unregister set space mouse events receiver
-  if(SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance()){
-    if(aSpaceMouse->isSpaceMouseOn())
-      aSpaceMouse->setWindow(x11Display(),0);
-  }
+#if !defined WIN32 && !defined __APPLE__
+  SVTK_SpaceMouseXCB* aSpaceMouse = SVTK_SpaceMouseXCB::getInstance();
+  if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
+    aSpaceMouse->setWindow( QX11Info::connection(), 0 );
+#endif
 }
 
-
-/*!
-  To handle native X11 events (from such devices as SpaceMouse)
-*/
-bool 
-QVTK_RenderWindowInteractor
-::x11Event( XEvent *xEvent )
-{
-  // handle 3d space mouse events
-  if(SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance()){
-    if(aSpaceMouse->isSpaceMouseOn() && xEvent->type == ClientMessage){
-      SVTK_SpaceMouse::MoveEvent anEvent;
-      int type = aSpaceMouse->translateEvent( x11Display(), xEvent, &anEvent, 1.0, 1.0 );
-      switch( type ){
-      case SVTK_SpaceMouse::SpaceMouseMove : 
-       GetDevice()->InvokeEvent(SVTK::SpaceMouseMoveEvent, anEvent.data );
-       break;
-      case SVTK_SpaceMouse::SpaceButtonPress :
-       GetDevice()->InvokeEvent( SVTK::SpaceMouseButtonEvent, &anEvent.button );
-       break;
-      case SVTK_SpaceMouse::SpaceButtonRelease :
-       break;
+bool QVTK_RenderWindowInteractor
+::nativeEvent(const QByteArray& eventType, void* message, long* result)
+{
+#if defined(WIN32)
+  // TODO: WIN32-related implementation
+#elif !defined(__APPLE__)
+  if ( eventType == "xcb_generic_event_t" )
+  {
+    xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
+    if ( SVTK_SpaceMouseXCB* aSpaceMouse = SVTK_SpaceMouseXCB::getInstance() )
+    {
+      if ( aSpaceMouse->isSpaceMouseOn() && ev->response_type == XCB_CLIENT_MESSAGE )
+      {
+        SVTK_SpaceMouse::MoveEvent anEvent;
+        int type = aSpaceMouse->translateEvent( QX11Info::connection(), (xcb_client_message_event_t*)ev, &anEvent, 1.0, 1.0 );
+        switch ( type )
+        {
+        case SVTK_SpaceMouse::SpaceMouseMove:
+                GetDevice()->InvokeEvent( SVTK::SpaceMouseMoveEvent, anEvent.data );
+                break;
+        case SVTK_SpaceMouse::SpaceButtonPress:
+                GetDevice()->InvokeEvent( SVTK::SpaceMouseButtonEvent, &anEvent.button );
+                break;
+        case SVTK_SpaceMouse::SpaceButtonRelease:
+                break;
+        }
+        return true; // stop handling the event
       }
-      return true; // stop handling the event
     }
   }
-
 return QWidget::x11Event( xEvent );
+#endif
return QWidget::nativeEvent( eventType, message, result );
 }
 
 /*!
@@ -430,7 +477,7 @@ QVTK_RenderWindowInteractor
 */
 SVTK_RenderWindowInteractor
 ::SVTK_RenderWindowInteractor(QWidget* theParent, 
-                              const char* theName):
+                               const char* theName):
   QVTK_RenderWindowInteractor(theParent,theName),
   myEventCallbackCommand(vtkCallbackCommand::New())
 {
@@ -448,8 +495,8 @@ SVTK_RenderWindowInteractor
 void
 SVTK_RenderWindowInteractor
 ::Initialize(vtkGenericRenderWindowInteractor* theDevice,
-            SVTK_Renderer* theRenderer,
-            SVTK_Selector* theSelector)
+             SVTK_Renderer* theRenderer,
+             SVTK_Selector* theSelector)
 {
   QVTK_RenderWindowInteractor::Initialize(theDevice);
   SetRenderer(theRenderer);
@@ -470,10 +517,6 @@ SVTK_RenderWindowInteractor
     aStyle->SetInteractor(NULL);
     myInteractorStyles.pop();
   }
-
-  SetRenderer(NULL);
-
-  GetDevice()->SetRenderWindow(NULL);
 }
 
 /*!
@@ -590,8 +633,8 @@ SVTK_RenderWindowInteractor
 
   if(mySelector.GetPointer())
     mySelector->AddObserver(vtkCommand::EndPickEvent, 
-                           myEventCallbackCommand.GetPointer(), 
-                           myPriority);
+                            myEventCallbackCommand.GetPointer(), 
+                            myPriority);
 }
 
 /*!
@@ -600,9 +643,9 @@ SVTK_RenderWindowInteractor
 void 
 SVTK_RenderWindowInteractor
 ::ProcessEvents(vtkObject* vtkNotUsed(theObject), 
-               unsigned long theEvent,
-               void* theClientData, 
-               void* vtkNotUsed(theCallData))
+                unsigned long theEvent,
+                void* theClientData, 
+                void* vtkNotUsed(theCallData))
 {
   SVTK_RenderWindowInteractor* self = reinterpret_cast<SVTK_RenderWindowInteractor*>(theClientData);
 
@@ -680,8 +723,30 @@ void
 SVTK_RenderWindowInteractor
 ::mouseReleaseEvent( QMouseEvent *event )
 {
+  SVTK_InteractorStyle* style = 0;
+  bool aRightBtn = event->button() == Qt::RightButton;
+  bool isOperation = false;
+  bool isPolygonalSelection = false;
+  if( aRightBtn && GetInteractorStyle()) {
+    style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
+    if ( style )
+      isOperation = style->CurrentState() != VTK_INTERACTOR_STYLE_CAMERA_NONE;
+  }
+
   QVTK_RenderWindowInteractor::mouseReleaseEvent(event);
 
+  if ( style ) {
+    isPolygonalSelection = style->GetPolygonState() == Finished;
+    style->SetPolygonState( Disable );
+  }
+
+  if ( aRightBtn && !isOperation && !isPolygonalSelection &&
+       !( event->modifiers() & Qt::ControlModifier ) &&
+       !( event->modifiers() & Qt::ShiftModifier ) ) {
+    QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
+                              event->pos(), event->globalPos() );
+    emit contextMenuRequested( &aEvent );
+  }
   if(GENERATE_SUIT_EVENTS)
     emit MouseButtonReleased( event );
 }
@@ -694,6 +759,12 @@ void
 SVTK_RenderWindowInteractor
 ::mouseDoubleClickEvent( QMouseEvent* event )
 {
+  if( GetInteractorStyle() && event->button() == Qt::LeftButton ) {
+    SVTK_InteractorStyle* style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
+    if ( style )
+      style->OnMouseButtonDoubleClick();
+  }
+
   QVTK_RenderWindowInteractor::mouseDoubleClickEvent(event);
 
   if(GENERATE_SUIT_EVENTS)
@@ -745,13 +816,3 @@ SVTK_RenderWindowInteractor
     emit KeyReleased( event );
 }
 
-/*!
-  Custom context menu event handler
-*/
-void
-SVTK_RenderWindowInteractor
-::contextMenuEvent( QContextMenuEvent* event )
-{
-  if( !( event->state() & KeyButtonMask ) )
-    emit contextMenuRequested( event );
-}