applied Linux SpaceNav patch from Rafael Ortis soc-2010-merwin
authorMike Erwin <significant.bit@gmail.com>
Fri, 21 Jan 2011 10:11:26 +0000 (10:11 +0000)
committerMike Erwin <significant.bit@gmail.com>
Fri, 21 Jan 2011 10:11:26 +0000 (10:11 +0000)
CMakeLists.txt
intern/ghost/intern/GHOST_NDOFManager.h
intern/ghost/intern/GHOST_NDOFManagerX11.h
intern/ghost/intern/GHOST_SystemX11.cpp
intern/ghost/intern/GHOST_SystemX11.h
intern/ghost/intern/GHOST_WindowX11.cpp

index 87265e959e53e73c7b6400e85f976b556ab48b85..4cc42ba994433bfff0d962959dcecbba18cf699a 100644 (file)
@@ -118,6 +118,9 @@ OPTION(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the rayt
 OPTION(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation tracking" OFF)
 OPTION(WITH_INSTALL       "Install accompanying scripts and language files needed to run blender" ON)
 OPTION(WITH_PYTHON_INSTALL       "Copy system python into the blender install folder" ON)
+IF(UNIX AND NOT APPLE)
+OPTION(WITH_SPACENAV       "Support for NDOF devices in Linux" ON)
+ENDIF(UNIX AND NOT APPLE)
 
 IF(APPLE)
        OPTION(WITH_COCOA         "Use Cocoa framework instead of deprecated Carbon" ON)
@@ -301,7 +304,9 @@ IF(UNIX AND NOT APPLE)
        IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
                # BSD's dont use libdl.so
                SET(LLIBS "${LLIBS} -ldl")
-
+               IF(WITH_SPACENAV)
+                       SET(LLIBS "${LLIBS} -lspnav")
+               ENDIF(WITH_SPACENAV)
                # binreloc is linux only
                SET(BINRELOC ${CMAKE_SOURCE_DIR}/extern/binreloc)
                SET(BINRELOC_INC ${BINRELOC}/include)
index 9d0bfa3b78977ff2182104643ac8ac92d3080d7c..f4adb4cab1d17b443d2327f7ecde4a94f2197a23 100644 (file)
@@ -45,7 +45,7 @@ public:
 
        // processes most recent raw data into an NDOFMotion event and sends it
        // returns whether an event was sent
-       bool sendMotionEvent();
+       virtual bool sendMotionEvent();
 
 protected:
        GHOST_System& m_system;
index 8f9c819a4817ebdf9ebcc5d1143a8fcb8a16e262..4c89bfe0ca697aaa7de8b915e94bc0e7fa78615b 100644 (file)
 #define _GHOST_NDOFMANAGERX11_H_
 
 #include "GHOST_NDOFManager.h"
-
+#include "GHOST_Types.h"
+#include "GHOST_WindowX11.h"
+#include "GHOST_EventNDOF.h"
+#include <X11/Xlib.h>
+#include <stdio.h>
 
 class GHOST_NDOFManagerX11 : public GHOST_NDOFManager
 {
+GHOST_WindowX11 * m_ghost_window_x11;
+
 public:
        GHOST_NDOFManagerX11(GHOST_System& sys)
                : GHOST_NDOFManager(sys)
                {}
 
+       void setGHOSTWindowX11(GHOST_WindowX11 * w){
+           if (m_ghost_window_x11 == NULL)
+               m_ghost_window_x11 = w;
+       }
+
+       GHOST_WindowX11 * getGHOSTWindowX11(){
+           return m_ghost_window_x11;
+       }       
+
        // whether multi-axis functionality is available (via the OS or driver)
        // does not imply that a device is plugged in or being used
        bool available()
                {
                // never available since I've not yet written it!
-               return false;
+               return true;
+               }
+
+       virtual bool sendMotionEvent()
+               {
+               if (m_atRest)
+                       return false;           
+
+               GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, getGHOSTWindowX11());
+               GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData();
+
+               const float scale = 1.f/350.f; // SpaceNavigator sends +/- 350 usually
+               // 350 according to their developer's guide; others recommend 500 as comfortable
+
+               // possible future enhancement
+               // scale *= m_sensitivity;
+
+               data->tx = -scale * m_translation[0];
+               data->ty = scale * m_translation[1];
+               data->tz = scale * m_translation[2];
+
+               data->rx = scale * m_rotation[0];
+               data->ry = scale * m_rotation[1];
+               data->rz = scale * m_rotation[2];
+
+               data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds
+
+               m_prevMotionTime = m_motionTime;
+
+               printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n",
+                       data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt);
+
+               if (!m_system.pushEvent(event))
+                   return false;
+
+               // 'at rest' test goes at the end so that the first 'rest' event gets sent
+               m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 &&
+                       m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0;
+
+               return true;
                }
 };
 
index dc519039af64d832035bc649c7b4857060621664..b389d25a7fea0b84b168a9768f0c93f91cf2a0f0 100644 (file)
@@ -267,6 +267,7 @@ createWindow(
                        m_windowManager->addWindow(window);
                        
                        pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+
                }
                else {
                        delete window;
@@ -631,10 +632,11 @@ GHOST_SystemX11::processEvent(XEvent *xe)
                                );
                        } else 
 #endif
-                       if (sNdofInfo.currValues) {
+                       if (m_ndofManager->available()) {
+
 //                             static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0};
-                               if (xcme.message_type == sNdofInfo.motionAtom)
-                               {
+                               if (xcme.message_type == sNdofInfo.motionAtom
+                                   || xcme.message_type == motion_event){
 //                                     data.changed = 1;
 //                                     data.delta = xcme.data.s[8] - data.time;
 //                                     data.time = xcme.data.s[8];
@@ -646,9 +648,9 @@ GHOST_SystemX11::processEvent(XEvent *xe)
 //                                     data.rz =-xcme.data.s[7];
                                                
                                        short t[3], r[3];
-                                       t[0] = xcme.data.s[2] >> 2;
-                                       t[1] = xcme.data.s[3] >> 2;
-                                       t[2] = xcme.data.s[4] >> 2;
+                                       t[0] = xcme.data.s[2];
+                                       t[1] = xcme.data.s[3];
+                                       t[2] = xcme.data.s[4];
                                        r[0] = xcme.data.s[5];
                                        r[1] = xcme.data.s[6];
                                        r[2] =-xcme.data.s[7];
@@ -663,7 +665,8 @@ GHOST_SystemX11::processEvent(XEvent *xe)
 //                                                                   GHOST_kEventNDOFMotion,
 //                                                                   window, data);
 
-                               } else if (xcme.message_type == sNdofInfo.btnPressAtom) {
+                               } else if (xcme.message_type == sNdofInfo.btnPressAtom
+                                          || xcme.message_type == button_press_event) {
 //                                     data.changed = 2;
 //                                     data.delta = xcme.data.s[8] - data.time;
 //                                     data.time = xcme.data.s[8];
@@ -803,7 +806,7 @@ GHOST_SystemX11::processEvent(XEvent *xe)
                        XFlush(m_display);
                        break;
                }
-               
+
                default: {
                        if(xe->type == window->GetXTablet().MotionEvent) 
                        {
@@ -1505,3 +1508,9 @@ const GHOST_TUns8* GHOST_SystemX11::getBinaryDir() const
        return NULL;
 }
 
+void GHOST_SystemX11::createNDOFAtoms(Display * display){
+    motion_event = XInternAtom(display, "MotionEvent", True);
+    button_press_event = XInternAtom(display, "ButtonPressEvent", True);
+    button_release_event = XInternAtom(display, "ButtonReleaseEvent", True);
+    command_event = XInternAtom(display, "CommandEvent", True);
+}
index e4b02d192e8390fb3846c30c5103fa29f884d8d4..4479dca5ecdd8d2e3e10cae09a2529b25f1b65a8 100644 (file)
@@ -214,6 +214,12 @@ public:
                         unsigned char **txt, unsigned long *len,
                         unsigned int *context) const;
 
+       /**
+        * Create the atoms used by ndof events
+        * @param display Current display
+        */
+       void createNDOFAtoms(Display * display);
+
        /**
         * Returns unsinged char from CUT_BUFFER0
         * @param selection             Get selection, X11 only feature
@@ -276,6 +282,14 @@ public:
        Atom m_incr;
        Atom m_utf8_string;
 
+       /**
+        * Atoms for NDOF
+        */
+       Atom motion_event;
+       Atom button_press_event;
+       Atom button_release_event;
+       Atom command_event;
+
 private :
 
        Display * m_display;
index 60e12ff78df9492f5361fa35a391110fbdb73bea..5ce5a66bfbab8dddef626d86eda04bee76f43f50 100644 (file)
 #include <X11/cursorfont.h>
 #include <X11/Xatom.h>
 
+// libspnav
+#include <spnav.h>
+#include "GHOST_NDOFManagerX11.h"
+
 #if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__) || defined (_AIX)
 #include <strings.h>
 #endif
@@ -269,6 +273,11 @@ GHOST_WindowX11(
                                CWBorderPixel|CWColormap|CWEventMask, 
                                &xattributes
                        );
+               if (spnav_x11_open(m_display, m_window)  == -1) {
+                   fprintf(stderr, "failed to connect to the space navigator daemon\n");
+               } else {
+                   m_system->createNDOFAtoms(m_display);
+               }
        } else {
 
                Window root_return;
@@ -297,12 +306,12 @@ GHOST_WindowX11(
                                m_visual->visual,
                                CWBorderPixel|CWColormap|CWEventMask, 
                                &xattributes
-                       );
 
+
+                       );
                XSelectInput(m_display , parentWindow, SubstructureNotifyMask);
-               
        }       
-       
+
        /*
         * One of the problem with WM-spec is that can't set a property
         * to a window that isn't mapped. That is why we can't "just
@@ -428,6 +437,8 @@ GHOST_WindowX11(
        XMapWindow(m_display, m_window);
        GHOST_PRINT("Mapped window\n");
 
+       
+       ((GHOST_NDOFManagerX11 *)m_system->getNDOFManager())->setGHOSTWindowX11(this);;
        XFlush(m_display);
 }
 
@@ -1258,6 +1269,9 @@ GHOST_WindowX11::
        if(m_xtablet.StylusDevice)
                XCloseDevice(m_display, m_xtablet.StylusDevice);
        
+       /*close ndof */
+       spnav_close();
+       
        if(m_xtablet.EraserDevice)
                XCloseDevice(m_display, m_xtablet.EraserDevice);