]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
SpaceMouse migrate from Xlib to XCB
authorimn <imn@opencascade.com>
Tue, 15 Dec 2015 08:48:35 +0000 (11:48 +0300)
committerimn <imn@opencascade.com>
Tue, 15 Dec 2015 08:48:35 +0000 (11:48 +0300)
src/SVTK/SVTK_RenderWindowInteractor.cxx
src/SVTK/SVTK_RenderWindowInteractor.h
src/SVTK/SVTK_SpaceMouse.cxx
src/SVTK/SVTK_SpaceMouse.h

index ab1b2ed06c2bca63158bea05a24e09172fb90ad4..55e3b3cb9c0f015812b3e07353191f2ef07a53a2 100644 (file)
 // Put Qt includes before the X11 includes which #define the symbol None
 // (see SVTK_SpaceMouse.h) to avoid the compilation error.
 #ifndef WIN32
-# include <QX11Info>
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+#include <xcb/xcb.h>
+#endif
+#include <QX11Info>
 #endif
 #include <QMouseEvent>
 
@@ -110,9 +113,15 @@ QVTK_RenderWindowInteractor
 ::~QVTK_RenderWindowInteractor() 
 {
 #ifndef WIN32
-  SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+  SVTK_SpaceMouseX* aSpaceMouse = SVTK_SpaceMouseX::getInstance();
   if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
     aSpaceMouse->close( QX11Info::display() );
+#else
+  SVTK_SpaceMouseXCB* aSpaceMouse = SVTK_SpaceMouseXCB::getInstance();
+  if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
+    aSpaceMouse->close( QX11Info::connection() );
+#endif
 #endif
 }
 
@@ -408,8 +417,8 @@ QVTK_RenderWindowInteractor
 
 #ifndef WIN32
   // register set space mouse events receiver
-  SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
-
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+  SVTK_SpaceMouseX* aSpaceMouse = SVTK_SpaceMouseX::getInstance();
   if ( aSpaceMouse )
   {
     if ( !aSpaceMouse->isSpaceMouseOn() )
@@ -418,6 +427,17 @@ QVTK_RenderWindowInteractor
     else
       aSpaceMouse->setWindow( QX11Info::display(), winId() );
   }
+#else
+  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
 #endif
 }
 
@@ -432,10 +452,16 @@ QVTK_RenderWindowInteractor
   QWidget::focusOutEvent( event );
 
 #ifndef WIN32
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
   // unregister set space mouse events receiver
-  SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
+  SVTK_SpaceMouseX* aSpaceMouse = SVTK_SpaceMouseX::getInstance();
   if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
     aSpaceMouse->setWindow( QX11Info::display(), 0 );
+#else
+  SVTK_SpaceMouseXCB* aSpaceMouse = SVTK_SpaceMouseXCB::getInstance();
+  if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
+    aSpaceMouse->setWindow( QX11Info::connection(), 0 );
+#endif
 #endif
 }
 
@@ -462,7 +488,7 @@ QVTK_RenderWindowInteractor
 ::x11Event( XEvent *xEvent )
 {
   // handle 3d space mouse events
-  if ( SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance() )
+  if ( SVTK_SpaceMouseX* aSpaceMouse = SVTK_SpaceMouseX::getInstance() )
   {
     if ( aSpaceMouse->isSpaceMouseOn() && xEvent->type == ClientMessage )
     {
@@ -487,6 +513,45 @@ QVTK_RenderWindowInteractor
 }
 
 #endif
+#else
+bool QVTK_RenderWindowInteractor
+::nativeEvent(const QByteArray& eventType, void* message, long* result)
+{
+  if ( eventType == "xcb_generic_event_t" )
+  {
+    xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+    if ( SVTK_SpaceMouseX* aSpaceMouse = SVTK_SpaceMouseX::getInstance() )
+#else
+    if ( SVTK_SpaceMouseXCB* aSpaceMouse = SVTK_SpaceMouseXCB::getInstance() )
+#endif
+    {
+      if ( aSpaceMouse->isSpaceMouseOn() && ev->response_type == XCB_CLIENT_MESSAGE )
+      {
+        SVTK_SpaceMouse::MoveEvent anEvent;
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+        int type = aSpaceMouse->translateEvent( QX11Info::display(), xEvent, &anEvent, 1.0, 1.0 );
+#else
+        int type = aSpaceMouse->translateEvent( QX11Info::connection(), (xcb_client_message_event_t*)ev, &anEvent, 1.0, 1.0 );
+#endif
+        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 QWidget::nativeEvent( eventType, message, result );
+}
 #endif
 /*!
   Constructor
index 27a4daba9e45e28bd3cc976e0f88864f4ffa650b..5d3382803fa9d5c1cb55cd8752a5b3774530a2e1 100644 (file)
@@ -129,6 +129,8 @@ class SVTK_EXPORT QVTK_RenderWindowInteractor: public QWidget
 #else
   virtual bool x11Event( XEvent *e );
 #endif
+#else
+  virtual bool nativeEvent( const QByteArray&, void*, long* );
 #endif
   vtkSmartPointer<vtkRenderWindow> myRenderWindow;
   vtkSmartPointer<vtkGenericRenderWindowInteractor> myDevice;
index 5943ef6aa53143d2e4835014eb14f54bb8e0f5fa..a199829fd83b03640d5a3bcf02e2135e88e01514 100644 (file)
 #include <math.h>
 #include <stdio.h>
 
+#include <QtGlobal>
+
 #ifndef WIN32
 #include <X11/X.h>
-#include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
 #include <X11/keysym.h>
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+#include <X11/Xlib.h>
+#else
+#include <xcb/xcb.h>
+#include <xcb/xcb_event.h>
+#endif
 #endif
 
 #include "SVTK_SpaceMouse.h"
 
-SVTK_SpaceMouse* SVTK_SpaceMouse::myInstance = 0;
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+SVTK_SpaceMouseX* SVTK_SpaceMouseX::myInstance = 0;
+#else
+SVTK_SpaceMouseXCB* SVTK_SpaceMouseXCB::myInstance = 0;
+#endif
 
 /*!
-  \return shared instance of object (creates if there is no one)
+  Constructor
 */
-SVTK_SpaceMouse* SVTK_SpaceMouse::getInstance()
+SVTK_SpaceMouse::SVTK_SpaceMouse()
 {
-  if ( !myInstance )
-    myInstance = new SVTK_SpaceMouse();
-  return myInstance;
+  spaceMouseOn = 0;
 }
-
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
 /*!
   Constructor
 */
-SVTK_SpaceMouse::SVTK_SpaceMouse()
+SVTK_SpaceMouseX::SVTK_SpaceMouseX()
+: SVTK_SpaceMouse()
 {
 #ifndef WIN32
   win = InputFocus;
 #endif
-  spaceMouseOn = 0;
 }
 
-#ifndef WIN32
-
 /*!
-  Initialization
+  \return shared instance of object (creates if there is no one)
 */
-int SVTK_SpaceMouse::initialize( Display *display, Window window )
+SVTK_SpaceMouseX* SVTK_SpaceMouseX::getInstance()
 {
- XMotionEvent        = XInternAtom( display, "MotionEvent",        1 );
- XButtonPressEvent   = XInternAtom( display, "ButtonPressEvent",   1 );
- XButtonReleaseEvent = XInternAtom( display, "ButtonReleaseEvent", 1 );
- XCommandEvent       = XInternAtom( display, "CommandEvent",       1 );
-
- spaceMouseOn = (XMotionEvent        != 0) && 
-                (XButtonPressEvent   != 0) && 
-                (XButtonReleaseEvent != 0) && 
-                (XCommandEvent       != 0);
- if ( !spaceMouseOn )
-  return 0;
-
- spaceMouseOn = setWindow( display, window );
- if ( !spaceMouseOn )
-  return 0;
- return spaceMouseOn; 
+  if ( !myInstance )
+    myInstance = new SVTK_SpaceMouseX();
+  return myInstance;
 }
 
+#ifndef WIN32
+
 static int errorCallback( Display *display, XErrorEvent *Error )
 {
   char msg[ 128 ];
@@ -97,10 +92,34 @@ static int errorCallback( Display *display, XErrorEvent *Error )
   return 0;
 }
 
+/*!
+  Initialization
+*/
+int SVTK_SpaceMouseX::initialize( Display *display, Window window )
+{
+  XMotionEvent        = XInternAtom( display, "MotionEvent",        1 );
+  XButtonPressEvent   = XInternAtom( display, "ButtonPressEvent",   1 );
+  XButtonReleaseEvent = XInternAtom( display, "ButtonReleaseEvent", 1 );
+  XCommandEvent       = XInternAtom( display, "CommandEvent",       1 );
+
+  spaceMouseOn = (XMotionEvent        != 0) &&
+                 (XButtonPressEvent   != 0) &&
+                 (XButtonReleaseEvent != 0) &&
+                 (XCommandEvent       != 0);
+  if ( !spaceMouseOn )
+    return 0;
+
+  spaceMouseOn = setWindow( display, window );
+  if ( !spaceMouseOn )
+    return 0;
+  return spaceMouseOn;
+}
+
 /*!
   Initialize by window
 */
-int SVTK_SpaceMouse::setWindow( Display *display, Window window )
+int SVTK_SpaceMouseX::setWindow( Display *display, Window window )
 {
   XTextProperty winName;
   XEvent xEvent;
@@ -109,10 +128,8 @@ int SVTK_SpaceMouse::setWindow( Display *display, Window window )
   unsigned long NItems, BytesReturn;
   unsigned char *PropReturn;
   Window root;
-  int result;
   int (*errorHandler)(Display *,XErrorEvent *);
 
-  result = 1;
   errorHandler = XSetErrorHandler( errorCallback );
  
   root = RootWindow( display, DefaultScreen(display) );
@@ -128,13 +145,13 @@ int SVTK_SpaceMouse::setWindow( Display *display, Window window )
     XFree( PropReturn );
   }
   else
-    return result = 0;
+    return 0;
 
   if ( XGetWMName( display, win, &winName ) == 0 )
-    return result = 0;
+    return 0;
 
   if ( strcmp( (char *) "Magellan Window", (char *) winName.value) != 0 )
-    return result = 0;
+    return 0;
 
   xEvent.type = ClientMessage;
   xEvent.xclient.format = 16;
@@ -148,18 +165,18 @@ int SVTK_SpaceMouse::setWindow( Display *display, Window window )
   xEvent.xclient.data.s[2] = 27695;
 
   if ( XSendEvent( display, win, 0, 0x0000, &xEvent ) == 0 )
-    return result = 0;
+    return 0;
 
   XFlush( display );
 
   XSetErrorHandler( errorHandler );
-  return result;
+  return 1;
 }
 
 /*!
   Close
 */
-int SVTK_SpaceMouse::close(Display *display)
+int SVTK_SpaceMouseX::close(Display *display)
 {
   initialize( display, (Window)InputFocus );
   spaceMouseOn = 0;
@@ -170,7 +187,7 @@ int SVTK_SpaceMouse::close(Display *display)
 /*!
   Custom event handler
 */
-int SVTK_SpaceMouse::translateEvent( Display* display, XEvent* xEvent, MoveEvent* spaceMouseEvent,
+int SVTK_SpaceMouseX::translateEvent( Display* display, XEvent* xEvent, MoveEvent* spaceMouseEvent,
                     double scale, double rScale )
 {
   if ( !spaceMouseOn )
@@ -207,5 +224,176 @@ int SVTK_SpaceMouse::translateEvent( Display* display, XEvent* xEvent, MoveEvent
   }
   return (!display);
 }
+#endif
+#else
+
+/*!
+  Constructor
+*/
+SVTK_SpaceMouseXCB::SVTK_SpaceMouseXCB()
+: SVTK_SpaceMouse()
+{
+#ifndef WIN32
+  win = InputFocus;
+#endif
+}
+
+/*!
+  \return shared instance of object (creates if there is no one)
+*/
+SVTK_SpaceMouseXCB* SVTK_SpaceMouseXCB::getInstance()
+{
+  if ( !myInstance )
+    myInstance = new SVTK_SpaceMouseXCB();
+  return myInstance;
+}
+/*!
+  Initialization
+*/
+#ifndef WIN32
+int SVTK_SpaceMouseXCB::initialize( xcb_connection_t *connection, xcb_window_t window )
+{
+  // make request
+  xcb_intern_atom_cookie_t cookie = xcb_intern_atom (connection, 0, strlen("XCB_MOTION_NOTIFY"), "XCB_MOTION_NOTIFY" );
+  // get response
+  xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply ( connection, cookie, NULL );
+  XCBMotionEvent = reply->atom;
+  cookie = xcb_intern_atom (connection, 0, strlen("XCB_BUTTON_PRESS"), "XCB_BUTTON_PRESS" );
+  reply = xcb_intern_atom_reply ( connection, cookie, NULL );
+  XCBButtonPressEvent = reply->atom;
+  cookie = xcb_intern_atom (connection, 0, strlen("XCB_BUTTON_RELEASE"), "XCB_BUTTON_RELEASE" );
+  reply = xcb_intern_atom_reply ( connection, cookie, NULL );
+  XCBButtonReleaseEvent = reply->atom;
+
+  free (reply);
+
+  spaceMouseOn = (XCBMotionEvent        != 0) &&
+                 (XCBButtonPressEvent   != 0) &&
+                 (XCBButtonReleaseEvent != 0);
+  if ( !spaceMouseOn )
+    return 0;
+
+  spaceMouseOn = setWindow( connection, window );
+  if ( !spaceMouseOn )
+    return 0;
+
+  return spaceMouseOn;
+}
+
+/*!
+  Initialize by window
+*/
+int SVTK_SpaceMouseXCB::setWindow( xcb_connection_t *connection, xcb_window_t window )
+{
+  xcb_client_message_event_t xcbEvent;
+  xcb_window_t root_window;
+  xcb_screen_t* screen;
+  xcb_generic_error_t* error;
+  xcb_void_cookie_t cookie;
+
+  screen = xcb_setup_roots_iterator ( xcb_get_setup ( connection ) ).data;
+
+  /* root window */
+  if ( screen )
+    root_window = screen->root;
+
+  xcb_get_property_cookie_t prop_cookie;
+  xcb_get_property_reply_t* prop_reply;
+  prop_cookie = xcb_get_property (connection, 0, root_window, XCB_ATOM_WM_NAME,
+                                  XCB_ATOM_STRING, 0, 0);
+
+  win = InputFocus;
+
+  if (( prop_reply = xcb_get_property_reply ( connection, prop_cookie, NULL ) ))
+  {
+    int len = xcb_get_property_value_length( prop_reply );
 
+    if ( len == 0 )
+    {
+      free(prop_reply);
+      return 0;
+    }
+
+    if ( strcmp( (char *) "Magellan Window", (char *) xcb_get_property_value( prop_reply ) ) != 0 )
+      return 0;
+
+    win = * ( xcb_window_t * ) xcb_get_property_value( prop_reply );
+  }
+
+  free(prop_reply);
+
+  xcbEvent.response_type = XCB_CLIENT_MESSAGE;
+  xcbEvent.format = 16;
+  xcbEvent.sequence = 0;
+  xcbEvent.window = win;
+
+  xcbEvent.data.data16[0] = (short) ((window>>16)&0x0000FFFF);
+  xcbEvent.data.data16[1] = (short)  (window&0x0000FFFF);
+  xcbEvent.data.data16[2] = 27695;
+
+  cookie = xcb_send_event( connection, 0, win, 0x0000, (const char *)&xcbEvent );
+
+  if (( error = xcb_request_check( connection, cookie )))
+  {
+    fprintf ( stderr, "SpaceMouse reported error = %s. Exit ... \n", xcb_event_get_label( error->response_type ) );
+    return 0;
+  }
+
+  xcb_flush(connection);
+
+  return 1;
+}
+
+/*!
+  Close
+*/
+int SVTK_SpaceMouseXCB::close(xcb_connection_t *connection)
+{
+  initialize( connection, (xcb_window_t)InputFocus );
+  spaceMouseOn = 0;
+
+  return 1;
+}
+
+/*!
+  Custom event handler
+*/
+int SVTK_SpaceMouseXCB::translateEvent( xcb_connection_t* connection, xcb_client_message_event_t* xcbEvent, MoveEvent* spaceMouseEvent,
+                    double scale, double rScale )
+{
+  if ( !spaceMouseOn )
+    return 0;
+
+  if ( xcbEvent->response_type == XCB_CLIENT_MESSAGE ) {
+    if ( xcbEvent->type == XCBMotionEvent ) {
+      spaceMouseEvent->type = SpaceMouseMove;
+      spaceMouseEvent->data[ x ] =
+        xcbEvent->data.data16[2] * scale;
+      spaceMouseEvent->data[ y ] =
+        xcbEvent->data.data16[3] * scale;
+      spaceMouseEvent->data[ z ] =
+        xcbEvent->data.data16[4] * scale;
+      spaceMouseEvent->data[ a ] =
+        xcbEvent->data.data16[5] * rScale;
+      spaceMouseEvent->data[ b ] =
+        xcbEvent->data.data16[6] * rScale;
+      spaceMouseEvent->data[ c ] =
+        xcbEvent->data.data16[7] * rScale;
+      spaceMouseEvent->period = xcbEvent->data.data16[8];
+      return 1;
+    }
+    else if ( xcbEvent->type == XCBButtonPressEvent ) {
+      spaceMouseEvent->type = SpaceButtonPress;
+      spaceMouseEvent->button = xcbEvent->data.data16[2];
+      return 2;
+    }
+    else if ( xcbEvent->type == XCBButtonReleaseEvent ) {
+      spaceMouseEvent->type = SpaceButtonRelease;
+      spaceMouseEvent->button = xcbEvent->data.data16[2];
+      return 3;
+    }
+  }
+  return (!connection);
+}
+#endif
 #endif
index caa559432204b6627bf33b65b133c353b4587bca..733b826a18077dc1c2f3b876d0b9f43a74f33189 100644 (file)
 #ifndef SVTK_SpaceMouse_h
 #define SVTK_SpaceMouse_h
 
+#include <QtGlobal>
+
 #ifndef WIN32
 extern "C"
 {
 #include <X11/X.h>
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
 #include <X11/Xlib.h>
+#else
+#include <xcb/xcb.h>
+#endif
 }
+
 #endif
 
 class SVTK_SpaceMouse 
 {
  public:
 
-  // access to SpaceMouse utility class
-  static SVTK_SpaceMouse* getInstance();
-
   enum MoveData { x, y, z, a, b, c };
   enum EventType { SpaceMouseMove = 1, SpaceButtonPress, SpaceButtonRelease };
 
@@ -54,26 +58,66 @@ class SVTK_SpaceMouse
 
   bool isSpaceMouseOn() const { return spaceMouseOn != 0; }
 
+  SVTK_SpaceMouse();
+
+ protected:
+
+  int spaceMouseOn;
+};
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+
+class SVTK_SpaceMouseX: public SVTK_SpaceMouse
+{
+
+public:
+  SVTK_SpaceMouseX();
+
+  // access to SpaceMouse utility class
+  static SVTK_SpaceMouseX* getInstance();
+
 #ifndef WIN32
   int initialize     ( Display*, Window );
   int setWindow      ( Display*, Window );
   int translateEvent ( Display*, XEvent*, MoveEvent*, double, double );
   int close          ( Display* );
-#endif
 
- private:
-  SVTK_SpaceMouse();
-  static SVTK_SpaceMouse* myInstance;
-
-#ifndef WIN32
+private:
   Atom XMotionEvent;
   Atom XButtonPressEvent;
   Atom XButtonReleaseEvent;
   Atom XCommandEvent;
-
   Window win;
 #endif
-  int spaceMouseOn;
+
+  static SVTK_SpaceMouseX* myInstance;
+
 };
+#else
+class SVTK_SpaceMouseXCB: public SVTK_SpaceMouse
+{
+
+public:
+  SVTK_SpaceMouseXCB();
 
+  // access to SpaceMouse utility class
+  static SVTK_SpaceMouseXCB* getInstance();
+
+#ifndef WIN32
+  int initialize     ( xcb_connection_t*, xcb_window_t );
+  int setWindow      ( xcb_connection_t*, xcb_window_t );
+  int translateEvent ( xcb_connection_t*, xcb_client_message_event_t*, MoveEvent*, double, double );
+  int close          ( xcb_connection_t* );
+
+private:
+  xcb_atom_t XCBMotionEvent;
+  xcb_atom_t XCBButtonPressEvent;
+  xcb_atom_t XCBButtonReleaseEvent;
+  xcb_window_t win;
+#endif
+
+  static SVTK_SpaceMouseXCB* myInstance;
+
+};
+#endif
 #endif