From c00916f20ca87e7f854fb04295e5474565e56b2a Mon Sep 17 00:00:00 2001 From: imn Date: Tue, 15 Dec 2015 11:48:35 +0300 Subject: [PATCH] SpaceMouse migrate from Xlib to XCB --- src/SVTK/SVTK_RenderWindowInteractor.cxx | 77 ++++++- src/SVTK/SVTK_RenderWindowInteractor.h | 2 + src/SVTK/SVTK_SpaceMouse.cxx | 270 +++++++++++++++++++---- src/SVTK/SVTK_SpaceMouse.h | 66 +++++- 4 files changed, 357 insertions(+), 58 deletions(-) diff --git a/src/SVTK/SVTK_RenderWindowInteractor.cxx b/src/SVTK/SVTK_RenderWindowInteractor.cxx index ab1b2ed06..55e3b3cb9 100644 --- a/src/SVTK/SVTK_RenderWindowInteractor.cxx +++ b/src/SVTK/SVTK_RenderWindowInteractor.cxx @@ -35,7 +35,10 @@ // Put Qt includes before the X11 includes which #define the symbol None // (see SVTK_SpaceMouse.h) to avoid the compilation error. #ifndef WIN32 -# include +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +#include +#endif +#include #endif #include @@ -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(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 diff --git a/src/SVTK/SVTK_RenderWindowInteractor.h b/src/SVTK/SVTK_RenderWindowInteractor.h index 27a4daba9..5d3382803 100644 --- a/src/SVTK/SVTK_RenderWindowInteractor.h +++ b/src/SVTK/SVTK_RenderWindowInteractor.h @@ -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 myRenderWindow; vtkSmartPointer myDevice; diff --git a/src/SVTK/SVTK_SpaceMouse.cxx b/src/SVTK/SVTK_SpaceMouse.cxx index 5943ef6aa..a199829fd 100644 --- a/src/SVTK/SVTK_SpaceMouse.cxx +++ b/src/SVTK/SVTK_SpaceMouse.cxx @@ -28,65 +28,60 @@ #include #include +#include + #ifndef WIN32 #include -#include #include #include #include +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +#else +#include +#include +#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 diff --git a/src/SVTK/SVTK_SpaceMouse.h b/src/SVTK/SVTK_SpaceMouse.h index caa559432..733b826a1 100644 --- a/src/SVTK/SVTK_SpaceMouse.h +++ b/src/SVTK/SVTK_SpaceMouse.h @@ -27,21 +27,25 @@ #ifndef SVTK_SpaceMouse_h #define SVTK_SpaceMouse_h +#include + #ifndef WIN32 extern "C" { #include +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #include +#else +#include +#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 -- 2.39.2