Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Erwin <significant.bit@gmail.com>2011-08-02 08:28:05 +0400
committerMike Erwin <significant.bit@gmail.com>2011-08-02 08:28:05 +0400
commit56918978b725ef529ad332db7acdd0682ea17ea7 (patch)
tree669cc7fd644d26caab1d1010e41d0e79afc54c26 /intern/ghost
parentdb494472ac02ff73dbc0984940e7758321e5642d (diff)
parentdc2609da3d08ff2dde1747201ef4e0ebb17d5bd9 (diff)
3D mouse support from merwin-spacenav branch
Diffstat (limited to 'intern/ghost')
-rw-r--r--intern/ghost/CMakeLists.txt8
-rw-r--r--intern/ghost/GHOST_C-api.h15
-rw-r--r--intern/ghost/GHOST_ISystem.h16
-rw-r--r--intern/ghost/GHOST_Types.h57
-rw-r--r--intern/ghost/SConscript2
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp17
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.cpp5
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.cpp1
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.h1
-rw-r--r--intern/ghost/intern/GHOST_EventManager.cpp2
-rw-r--r--intern/ghost/intern/GHOST_EventNDOF.h56
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp563
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h143
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerCocoa.h48
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerCocoa.mm172
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerWin32.cpp37
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerWin32.h38
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerX11.cpp110
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerX11.h47
-rw-r--r--intern/ghost/intern/GHOST_System.cpp31
-rw-r--r--intern/ghost/intern/GHOST_System.h19
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h7
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm10
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.cpp7
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp397
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h133
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp69
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h5
-rw-r--r--intern/ghost/intern/GHOST_TaskbarWin32.h10
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h14
31 files changed, 1394 insertions, 648 deletions
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index ccd763ef42c..b69dff607e8 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -158,11 +158,13 @@ elseif(APPLE)
intern/GHOST_SystemCocoa.mm
intern/GHOST_SystemPathsCocoa.mm
intern/GHOST_WindowCocoa.mm
-
+ intern/GHOST_NDOFManagerCocoa.mm
+
intern/GHOST_DisplayManagerCocoa.h
intern/GHOST_SystemCocoa.h
intern/GHOST_SystemPathsCocoa.h
intern/GHOST_WindowCocoa.h
+ intern/GHOST_NDOFManagerCocoa.h
)
else()
list(APPEND SRC
@@ -197,11 +199,13 @@ elseif(UNIX)
intern/GHOST_SystemX11.cpp
intern/GHOST_SystemPathsX11.cpp
intern/GHOST_WindowX11.cpp
+ intern/GHOST_NDOFManagerX11.cpp
intern/GHOST_DisplayManagerX11.h
intern/GHOST_SystemX11.h
intern/GHOST_SystemPathsX11.h
intern/GHOST_WindowX11.h
+ intern/GHOST_NDOFManagerX11.h
)
if(NOT WITH_INSTALL_PORTABLE)
@@ -230,6 +234,7 @@ elseif(WIN32)
intern/GHOST_SystemPathsWin32.cpp
intern/GHOST_WindowWin32.cpp
intern/GHOST_DropTargetWin32.cpp
+ intern/GHOST_NDOFManagerWin32.cpp
intern/GHOST_DisplayManagerWin32.h
intern/GHOST_DropTargetWin32.h
@@ -237,6 +242,7 @@ elseif(WIN32)
intern/GHOST_SystemPathsWin32.h
intern/GHOST_WindowWin32.h
intern/GHOST_TaskbarWin32.h
+ intern/GHOST_NDOFManagerWin32.h
)
endif()
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 75837239c4a..a315dfa85e9 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -288,21 +288,6 @@ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, floa
* @param windowhandle The handle to the window
*/
extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle);
-
-
-/***************************************************************************************
- ** N-degree of freedom device management functionality
- ***************************************************************************************/
-
-/**
-* Open N-degree of freedom devices
- */
-extern int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle,
- GHOST_WindowHandle windowhandle,
- GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
- GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
- GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen
- );
/***************************************************************************************
** Cursor management functionality
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 69e10070be5..015ae780bea 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -298,22 +298,6 @@ public:
*/
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer) = 0;
- /***************************************************************************************
- ** N-degree of freedom device management functionality
- ***************************************************************************************/
-
- /**
- * Starts the N-degree of freedom device manager
- */
- virtual int openNDOF(GHOST_IWindow*,
- GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
- GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
- GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen
- // original patch only
- // GHOST_NDOFEventHandler_fp setNdofEventHandler
- ) = 0;
-
-
/***************************************************************************************
** Cursor management functionality
***************************************************************************************/
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 6a4da5c9d38..f24ab00acd3 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -47,11 +47,6 @@ typedef unsigned short GHOST_TUns16;
typedef int GHOST_TInt32;
typedef unsigned int GHOST_TUns32;
-#ifdef WIN32
-#define WM_BLND_NDOF_AXIS WM_USER + 1
-#define WM_BLND_NDOF_BTN WM_USER + 2
-#endif
-
#if defined(WIN32) && !defined(FREE_WINDOWS)
typedef __int64 GHOST_TInt64;
typedef unsigned __int64 GHOST_TUns64;
@@ -440,37 +435,33 @@ typedef struct {
GHOST_TUns8 **strings;
} GHOST_TStringArray;
+typedef enum {
+ GHOST_kNotStarted,
+ GHOST_kStarting,
+ GHOST_kInProgress,
+ GHOST_kFinishing,
+ GHOST_kFinished
+ } GHOST_TProgress;
-/* original patch used floats, but the driver return ints and uns. We will calibrate in view, no sense on doing conversions twice */
-/* as all USB device controls are likely to use ints, this is also more future proof */
-//typedef struct {
-// /** N-degree of freedom device data */
-// float tx, ty, tz; /** -x left, +y up, +z forward */
-// float rx, ry, rz;
-// float dt;
-//} GHOST_TEventNDOFData;
+typedef struct {
+ /** N-degree of freedom device data v3 [GSoC 2010] */
+ // Each component normally ranges from -1 to +1, but can exceed that.
+ // These use blender standard view coordinates, with positive rotations being CCW about the axis.
+ float tx, ty, tz; // translation
+ float rx, ry, rz; // rotation:
+ // axis = (rx,ry,rz).normalized
+ // amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg]
+ float dt; // time since previous NDOF Motion event
+ GHOST_TProgress progress; // Starting, InProgress or Finishing (for modal handlers)
+} GHOST_TEventNDOFMotionData;
+
+typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction;
+ // good for mouse or other buttons too, hmmm?
typedef struct {
- /** N-degree of freedom device data v2*/
- int changed;
- GHOST_TUns64 client;
- GHOST_TUns64 address;
- GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */
- GHOST_TInt16 rx, ry, rz;
- GHOST_TInt16 buttons;
- GHOST_TUns64 time;
- GHOST_TUns64 delta;
-} GHOST_TEventNDOFData;
-
-typedef int (*GHOST_NDOFLibraryInit_fp)(void);
-typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle);
-typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData);
-
-// original patch windows callback. In mac os X version the callback is internal to the plug-in and post an event to main thead.
-// not necessary faster, but better integration with other events.
-
-//typedef int (*GHOST_NDOFEventHandler_fp)(float* result7, void* deviceHandle, unsigned int message, unsigned int* wParam, unsigned long* lParam);
-//typedef void (*GHOST_NDOFCallBack_fp)(GHOST_TEventNDOFDataV2 *VolDatas);
+ GHOST_TButtonAction action;
+ short button;
+} GHOST_TEventNDOFButtonData;
typedef struct {
/** The key code. */
diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript
index c65ec58a97b..3dec748ce31 100644
--- a/intern/ghost/SConscript
+++ b/intern/ghost/SConscript
@@ -11,7 +11,7 @@ if window_system == 'darwin':
sources += env.Glob('intern/*.mm')
-pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget']
+pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget', 'GHOST_NDOFManager']
defs=['_USE_MATH_DEFINES']
incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC']
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 7ba8d7db411..6332d72a42f 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -275,23 +275,6 @@ GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle)
}
-int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle,
- GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
- GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
- GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
- //original patch only
- /* GHOST_NDOFEventHandler_fp setNdofEventHandler)*/
-{
- GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
-
- return system->openNDOF((GHOST_IWindow*) windowhandle,
- setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen);
-// original patch
-// setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen, setNdofEventHandler);
-}
-
-
-
GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
index 30d9aa31207..47f748927ab 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
@@ -35,8 +35,11 @@
#include "GHOST_DisplayManagerWin32.h"
#include "GHOST_Debug.h"
-// We do not support multiple monitors at the moment
+#define _WIN32_WINNT 0x501 // require Windows XP or newer
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+
+// We do not support multiple monitors at the moment
#define COMPILE_MULTIMON_STUBS
#ifndef FREE_WINDOWS
#include <multimon.h>
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
index 2e77da42b31..99990a46c2a 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
@@ -33,6 +33,7 @@
#include "GHOST_Debug.h"
#include "GHOST_DropTargetWin32.h"
+#include <ShellApi.h>
#ifdef GHOST_DEBUG
// utility
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h
index 0a553b6701e..980e9f9fe9b 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.h
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.h
@@ -33,7 +33,6 @@
#ifndef _GHOST_DROP_TARGET_WIN32_H_
#define _GHOST_DROP_TARGET_WIN32_H_
-#include <windows.h>
#include <string.h>
#include <GHOST_Types.h>
#include "GHOST_WindowWin32.h"
diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp
index 1483555c362..86b87973038 100644
--- a/intern/ghost/intern/GHOST_EventManager.cpp
+++ b/intern/ghost/intern/GHOST_EventManager.cpp
@@ -42,7 +42,7 @@
#include "GHOST_EventManager.h"
#include <algorithm>
#include "GHOST_Debug.h"
-
+#include <stdio.h> // [mce] temp debug
GHOST_EventManager::GHOST_EventManager()
{
diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h
index 70861b08fc6..394aff0493f 100644
--- a/intern/ghost/intern/GHOST_EventNDOF.h
+++ b/intern/ghost/intern/GHOST_EventNDOF.h
@@ -19,11 +19,6 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-
-/** \file ghost/intern/GHOST_EventNDOF.h
- * \ingroup GHOST
- */
-
#ifndef _GHOST_EVENT_NDOF_H_
@@ -31,32 +26,33 @@
#include "GHOST_Event.h"
-/**
- * N-degree of freedom device event.
- */
-class GHOST_EventNDOF : public GHOST_Event
-{
-public:
- /**
- * Constructor.
- * @param msec The time this event was generated.
- * @param type The type of this event.
- * @param x The x-coordinate of the location the cursor was at at the time of the event.
- * @param y The y-coordinate of the location the cursor was at at the time of the event.
- */
- GHOST_EventNDOF(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window,
- GHOST_TEventNDOFData data)
- : GHOST_Event(msec, type, window)
- {
- m_ndofEventData = data;
- m_data = &m_ndofEventData;
- }
-protected:
- /** translation & rotation from the device. */
- GHOST_TEventNDOFData m_ndofEventData;
-};
+class GHOST_EventNDOFMotion : public GHOST_Event
+ {
+ protected:
+ GHOST_TEventNDOFMotionData m_axisData;
+
+ public:
+ GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow* window)
+ : GHOST_Event(time, GHOST_kEventNDOFMotion, window)
+ {
+ m_data = &m_axisData;
+ }
+ };
+
+
+class GHOST_EventNDOFButton : public GHOST_Event
+ {
+ protected:
+ GHOST_TEventNDOFButtonData m_buttonData;
+
+ public:
+ GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_IWindow* window)
+ : GHOST_Event(time, GHOST_kEventNDOFButton, window)
+ {
+ m_data = &m_buttonData;
+ }
+ };
#endif // _GHOST_EVENT_NDOF_H_
-
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index dae6cb5b544..c9db8bc36de 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -15,122 +15,471 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor(s): none yet.
+ * Contributor(s):
+ * Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file ghost/intern/GHOST_NDOFManager.cpp
- * \ingroup GHOST
- */
+#include "GHOST_NDOFManager.h"
+#include "GHOST_EventNDOF.h"
+#include "GHOST_EventKey.h"
+#include "GHOST_WindowManager.h"
+#include <string.h> // for memory functions
+#include <stdio.h> // for error/info reporting
+#include <math.h>
+#ifdef DEBUG_NDOF_MOTION
+// printable version of each GHOST_TProgress value
+static const char* progress_string[] =
+ {"not started","starting","in progress","finishing","finished"};
+#endif
-#include <stdio.h> /* just for printf */
+#ifdef DEBUG_NDOF_BUTTONS
+static const char* ndof_button_names[] = {
+ // used internally, never sent
+ "NDOF_BUTTON_NONE",
+ // these two are available from any 3Dconnexion device
+ "NDOF_BUTTON_MENU",
+ "NDOF_BUTTON_FIT",
+ // standard views
+ "NDOF_BUTTON_TOP",
+ "NDOF_BUTTON_BOTTOM",
+ "NDOF_BUTTON_LEFT",
+ "NDOF_BUTTON_RIGHT",
+ "NDOF_BUTTON_FRONT",
+ "NDOF_BUTTON_BACK",
+ // more views
+ "NDOF_BUTTON_ISO1",
+ "NDOF_BUTTON_ISO2",
+ // 90 degree rotations
+ "NDOF_BUTTON_ROLL_CW",
+ "NDOF_BUTTON_ROLL_CCW",
+ "NDOF_BUTTON_SPIN_CW",
+ "NDOF_BUTTON_SPIN_CCW",
+ "NDOF_BUTTON_TILT_CW",
+ "NDOF_BUTTON_TILT_CCW",
+ // device control
+ "NDOF_BUTTON_ROTATE",
+ "NDOF_BUTTON_PANZOOM",
+ "NDOF_BUTTON_DOMINANT",
+ "NDOF_BUTTON_PLUS",
+ "NDOF_BUTTON_MINUS",
+ // general-purpose buttons
+ "NDOF_BUTTON_1",
+ "NDOF_BUTTON_2",
+ "NDOF_BUTTON_3",
+ "NDOF_BUTTON_4",
+ "NDOF_BUTTON_5",
+ "NDOF_BUTTON_6",
+ "NDOF_BUTTON_7",
+ "NDOF_BUTTON_8",
+ "NDOF_BUTTON_9",
+ "NDOF_BUTTON_10",
+ };
+#endif
-#include "GHOST_NDOFManager.h"
+static const NDOF_ButtonT SpaceNavigator_HID_map[] =
+ {
+ NDOF_BUTTON_MENU,
+ NDOF_BUTTON_FIT
+ };
+static const NDOF_ButtonT SpaceExplorer_HID_map[] =
+ {
+ NDOF_BUTTON_1,
+ NDOF_BUTTON_2,
+ NDOF_BUTTON_TOP,
+ NDOF_BUTTON_LEFT,
+ NDOF_BUTTON_RIGHT,
+ NDOF_BUTTON_FRONT,
+ NDOF_BUTTON_NONE, // esc key
+ NDOF_BUTTON_NONE, // alt key
+ NDOF_BUTTON_NONE, // shift key
+ NDOF_BUTTON_NONE, // ctrl key
+ NDOF_BUTTON_FIT,
+ NDOF_BUTTON_MENU,
+ NDOF_BUTTON_PLUS,
+ NDOF_BUTTON_MINUS,
+ NDOF_BUTTON_ROTATE
+ };
-// the variable is outside the class because it must be accessed from plugin
-static volatile GHOST_TEventNDOFData currentNdofValues = {0,0,0,0,0,0,0,0,0,0,0};
+static const NDOF_ButtonT SpacePilotPro_HID_map[] =
+ {
+ NDOF_BUTTON_MENU,
+ NDOF_BUTTON_FIT,
+ NDOF_BUTTON_TOP,
+ NDOF_BUTTON_LEFT,
+ NDOF_BUTTON_RIGHT,
+ NDOF_BUTTON_FRONT,
+ NDOF_BUTTON_BOTTOM,
+ NDOF_BUTTON_BACK,
+ NDOF_BUTTON_ROLL_CW,
+ NDOF_BUTTON_ROLL_CCW,
+ NDOF_BUTTON_ISO1,
+ NDOF_BUTTON_ISO2,
+ NDOF_BUTTON_1,
+ NDOF_BUTTON_2,
+ NDOF_BUTTON_3,
+ NDOF_BUTTON_4,
+ NDOF_BUTTON_5,
+ NDOF_BUTTON_6,
+ NDOF_BUTTON_7,
+ NDOF_BUTTON_8,
+ NDOF_BUTTON_9,
+ NDOF_BUTTON_10,
+ NDOF_BUTTON_NONE, // esc key
+ NDOF_BUTTON_NONE, // alt key
+ NDOF_BUTTON_NONE, // shift key
+ NDOF_BUTTON_NONE, // ctrl key
+ NDOF_BUTTON_ROTATE,
+ NDOF_BUTTON_PANZOOM,
+ NDOF_BUTTON_DOMINANT,
+ NDOF_BUTTON_PLUS,
+ NDOF_BUTTON_MINUS
+ };
-#if !defined(_WIN32) && !defined(__APPLE__)
-#include "GHOST_SystemX11.h"
-#endif
+static const NDOF_ButtonT SpacePilot_HID_map[] =
+// this is the older SpacePilot (sans Pro)
+// thanks to polosson for the info in this table
+ {
+ NDOF_BUTTON_1,
+ NDOF_BUTTON_2,
+ NDOF_BUTTON_3,
+ NDOF_BUTTON_4,
+ NDOF_BUTTON_5,
+ NDOF_BUTTON_6,
+ NDOF_BUTTON_TOP,
+ NDOF_BUTTON_LEFT,
+ NDOF_BUTTON_RIGHT,
+ NDOF_BUTTON_FRONT,
+ NDOF_BUTTON_NONE, // esc key
+ NDOF_BUTTON_NONE, // alt key
+ NDOF_BUTTON_NONE, // shift key
+ NDOF_BUTTON_NONE, // ctrl key
+ NDOF_BUTTON_FIT,
+ NDOF_BUTTON_MENU,
+ NDOF_BUTTON_PLUS,
+ NDOF_BUTTON_MINUS,
+ NDOF_BUTTON_DOMINANT,
+ NDOF_BUTTON_ROTATE,
+ NDOF_BUTTON_NONE // the CONFIG button -- what does it do?
+ };
-namespace
-{
- GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0;
- GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0;
- GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0;
-}
-
-GHOST_NDOFManager::GHOST_NDOFManager()
-{
- m_DeviceHandle = 0;
-
- // discover the API from the plugin
- ndofLibraryInit = 0;
- ndofLibraryShutdown = 0;
- ndofDeviceOpen = 0;
-}
-
-GHOST_NDOFManager::~GHOST_NDOFManager()
-{
- if (ndofLibraryShutdown)
- ndofLibraryShutdown(m_DeviceHandle);
-
- m_DeviceHandle = 0;
-}
-
-
-int
-GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window,
- GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
- GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
- GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
-{
- int Pid;
-
- ndofLibraryInit = setNdofLibraryInit;
- ndofLibraryShutdown = setNdofLibraryShutdown;
- ndofDeviceOpen = setNdofDeviceOpen;
-
- if (ndofLibraryInit && ndofDeviceOpen)
- {
- Pid= ndofLibraryInit();
-#if 0
- printf("%i client \n", Pid);
-#endif
- #if defined(WITH_HEADLESS)
- /* do nothing */
- #elif defined(_WIN32) || defined(__APPLE__)
- m_DeviceHandle = ndofDeviceOpen((void *)&currentNdofValues);
- #elif defined(WITH_GHOST_SDL)
- /* do nothing */
- #else
- GHOST_SystemX11 *sys;
- sys = static_cast<GHOST_SystemX11*>(GHOST_ISystem::getSystem());
- void *ndofInfo = sys->prepareNdofInfo(&currentNdofValues);
- m_DeviceHandle = ndofDeviceOpen(ndofInfo);
+GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys)
+ : m_system(sys)
+ , m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code
+ , m_buttonCount(0)
+ , m_buttonMask(0)
+ , m_buttons(0)
+ , m_motionTime(0)
+ , m_prevMotionTime(0)
+ , m_motionState(GHOST_kNotStarted)
+ , m_motionEventPending(false)
+ , m_deadZone(0.f)
+ {
+ // to avoid the rare situation where one triple is updated and
+ // the other is not, initialize them both here:
+ memset(m_translation, 0, sizeof(m_translation));
+ memset(m_rotation, 0, sizeof(m_rotation));
+
+ #ifdef WITH_BF_3DMOUSE
+ puts("WITH_BF_3DMOUSE is defined!");
+ #else
+ puts("WITH_BF_3DMOUSE is not defined.");
+ #endif
+ }
+
+bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id)
+ {
+ // default to NDOF_UnknownDevice so rogue button events will get discarded
+ // "mystery device" owners can help build a HID_map for their hardware
+
+ switch (vendor_id)
+ {
+ case 0x046D: // Logitech (3Dconnexion)
+ switch (product_id)
+ {
+ // -- current devices --
+ case 0xC626:
+ puts("ndof: using SpaceNavigator");
+ m_deviceType = NDOF_SpaceNavigator;
+ m_buttonCount = 2;
+ break;
+ case 0xC628:
+ puts("ndof: using SpaceNavigator for Notebooks");
+ m_deviceType = NDOF_SpaceNavigator; // for Notebooks
+ m_buttonCount = 2;
+ break;
+ case 0xC627:
+ puts("ndof: using SpaceExplorer");
+ m_deviceType = NDOF_SpaceExplorer;
+ m_buttonCount = 15;
+ break;
+ case 0xC629:
+ puts("ndof: using SpacePilotPro");
+ m_deviceType = NDOF_SpacePilotPro;
+ m_buttonCount = 31;
+ break;
+
+ // -- older devices --
+ case 0xC625:
+ puts("ndof: using SpacePilot");
+ m_deviceType = NDOF_SpacePilot;
+ m_buttonCount = 21;
+ break;
+
+ case 0xC623:
+ puts("ndof: SpaceTraveler not supported, please file a bug report");
+ m_buttonCount = 8;
+ break;
+
+ default:
+ printf("ndof: unknown Logitech product %04hx\n", product_id);
+ }
+ break;
+ default:
+ printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id);
+ }
+
+ if (m_deviceType == NDOF_UnknownDevice)
+ return false;
+ else
+ {
+ m_buttonMask = ~(-1 << m_buttonCount);
+
+ #ifdef DEBUG_NDOF_BUTTONS
+ printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask);
#endif
- return (Pid > 0) ? 0 : 1;
-
- } else
- return 1;
-}
-
-
-bool
-GHOST_NDOFManager::available() const
-{
- return m_DeviceHandle != 0;
-}
-
-bool
-GHOST_NDOFManager::event_present() const
-{
- if( currentNdofValues.changed >0) {
- printf("time %llu but%u x%i y%i z%i rx%i ry%i rz%i \n" ,
- currentNdofValues.time, currentNdofValues.buttons,
- currentNdofValues.tx,currentNdofValues.ty,currentNdofValues.tz,
- currentNdofValues.rx,currentNdofValues.ry,currentNdofValues.rz);
- return true;
- }else
- return false;
-
-}
-
-void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const
-{
- datas.tx = currentNdofValues.tx;
- datas.ty = currentNdofValues.ty;
- datas.tz = currentNdofValues.tz;
- datas.rx = currentNdofValues.rx;
- datas.ry = currentNdofValues.ry;
- datas.rz = currentNdofValues.rz;
- datas.buttons = currentNdofValues.buttons;
- datas.client = currentNdofValues.client;
- datas.address = currentNdofValues.address;
- datas.time = currentNdofValues.time;
- datas.delta = currentNdofValues.delta;
-}
+
+ return true;
+ }
+ }
+
+void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time)
+ {
+ memcpy(m_translation, t, sizeof(m_translation));
+ m_motionTime = time;
+ m_motionEventPending = true;
+ }
+
+void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time)
+ {
+ memcpy(m_rotation, r, sizeof(m_rotation));
+ m_motionTime = time;
+ m_motionEventPending = true;
+ }
+
+void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, GHOST_TUns64 time, GHOST_IWindow* window)
+ {
+ GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window);
+ GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData();
+
+ data->action = press ? GHOST_kPress : GHOST_kRelease;
+ data->button = button;
+
+ #ifdef DEBUG_NDOF_BUTTONS
+ printf("%s %s\n", ndof_button_names[button], press ? "pressed" : "released");
+ #endif
+
+ m_system.pushEvent(event);
+ }
+
+void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, bool press, GHOST_TUns64 time, GHOST_IWindow* window)
+ {
+ GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
+ GHOST_EventKey* event = new GHOST_EventKey(time, type, window, key);
+
+ #ifdef DEBUG_NDOF_BUTTONS
+ printf("keyboard %s\n", press ? "down" : "up");
+ #endif
+
+ m_system.pushEvent(event);
+ }
+
+void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time)
+ {
+ GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow();
+
+ #ifdef DEBUG_NDOF_BUTTONS
+ if (m_deviceType != NDOF_UnknownDevice)
+ printf("ndof: button %d -> ", button_number);
+ #endif
+
+ switch (m_deviceType)
+ {
+ case NDOF_SpaceNavigator:
+ sendButtonEvent(SpaceNavigator_HID_map[button_number], press, time, window);
+ break;
+ case NDOF_SpaceExplorer:
+ switch (button_number)
+ {
+ case 6: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break;
+ case 7: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break;
+ case 8: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break;
+ case 9: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break;
+ default: sendButtonEvent(SpaceExplorer_HID_map[button_number], press, time, window);
+ }
+ break;
+ case NDOF_SpacePilotPro:
+ switch (button_number)
+ {
+ case 22: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break;
+ case 23: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break;
+ case 24: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break;
+ case 25: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break;
+ default: sendButtonEvent(SpacePilotPro_HID_map[button_number], press, time, window);
+ }
+ break;
+ case NDOF_SpacePilot:
+ switch (button_number)
+ {
+ case 10: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break;
+ case 11: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break;
+ case 12: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break;
+ case 13: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break;
+ case 20: puts("ndof: ignoring CONFIG button"); break;
+ default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window);
+ }
+ break;
+ case NDOF_UnknownDevice:
+ printf("ndof: button %d on unknown device (ignoring)\n", button_number);
+ }
+
+ int mask = 1 << button_number;
+ if (press)
+ m_buttons |= mask; // set this button's bit
+ else
+ m_buttons &= ~mask; // clear this button's bit
+ }
+
+void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time)
+ {
+ button_bits &= m_buttonMask; // discard any "garbage" bits
+
+ int diff = m_buttons ^ button_bits;
+
+ for (int button_number = 0; button_number < m_buttonCount; ++button_number)
+ {
+ int mask = 1 << button_number;
+
+ if (diff & mask)
+ {
+ bool press = button_bits & mask;
+ updateButton(button_number, press, time);
+ }
+ }
+ }
+
+void GHOST_NDOFManager::setDeadZone(float dz)
+ {
+ if (dz < 0.f)
+ // negative values don't make sense, so clamp at zero
+ dz = 0.f;
+ else if (dz > 0.5f)
+ // warn the rogue user/programmer, but allow it
+ printf("ndof: dead zone of %.2f is rather high...\n", dz);
+
+ m_deadZone = dz;
+
+ printf("ndof: dead zone set to %.2f\n", dz);
+ }
+
+static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof)
+ {
+ #define HOME(foo) (ndof->foo == 0)
+ return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz);
+ }
+
+static bool nearHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold)
+ {
+ if (threshold == 0.f)
+ return atHomePosition(ndof);
+ else
+ {
+ #define HOME1(foo) (fabsf(ndof->foo) < threshold)
+ return HOME1(tx) && HOME1(ty) && HOME1(tz) && HOME1(rx) && HOME1(ry) && HOME1(rz);
+ }
+ }
+
+bool GHOST_NDOFManager::sendMotionEvent()
+ {
+ if (!m_motionEventPending)
+ return false;
+
+ m_motionEventPending = false; // any pending motion is handled right now
+
+ GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow();
+ if (window == NULL)
+ return false; // delivery will fail, so don't bother sending
+
+ GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window);
+ GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData();
+
+ // scale axis values here to normalize them to around +/- 1
+ // they are scaled again for overall sensitivity in the WM based on user prefs
+
+ const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually
+
+ 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
+
+ bool handMotion = !nearHomePosition(data, m_deadZone);
+
+ // determine what kind of motion event to send (Starting, InProgress, Finishing)
+ // and where that leaves this NDOF manager (NotStarted, InProgress, Finished)
+ switch (m_motionState)
+ {
+ case GHOST_kNotStarted:
+ case GHOST_kFinished:
+ if (handMotion)
+ {
+ data->progress = GHOST_kStarting;
+ m_motionState = GHOST_kInProgress;
+ // prev motion time will be ancient, so just make up something reasonable
+ data->dt = 0.0125f;
+ }
+ else
+ {
+ // send no event and keep current state
+ delete event;
+ return false;
+ }
+ break;
+ case GHOST_kInProgress:
+ if (handMotion)
+ {
+ data->progress = GHOST_kInProgress;
+ // keep InProgress state
+ }
+ else
+ {
+ data->progress = GHOST_kFinishing;
+ m_motionState = GHOST_kFinished;
+ }
+ break;
+ }
+
+ #ifdef DEBUG_NDOF_MOTION
+ printf("ndof motion sent -- %s\n", progress_string[data->progress]);
+
+ // show details about this motion event
+ printf(" 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);
+ #endif
+
+ m_system.pushEvent(event);
+
+ m_prevMotionTime = m_motionTime;
+
+ return true;
+ }
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index c9e09370e09..ce0c3e96171 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -15,43 +15,144 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor(s): none yet.
+ * Contributor(s):
+ * Mike Erwin
*
* ***** END GPL LICENSE BLOCK *****
*/
-
-/** \file ghost/intern/GHOST_NDOFManager.h
- * \ingroup GHOST
- */
-
#ifndef _GHOST_NDOFMANAGER_H_
#define _GHOST_NDOFMANAGER_H_
#include "GHOST_System.h"
-#include "GHOST_IWindow.h"
+// #define DEBUG_NDOF_MOTION
+#define DEBUG_NDOF_BUTTONS
+
+typedef enum {
+ NDOF_UnknownDevice, // <-- motion will work fine, buttons are ignored
+
+ // current devices
+ NDOF_SpaceNavigator,
+ NDOF_SpaceExplorer,
+ NDOF_SpacePilotPro,
+
+ // older devices
+ NDOF_SpacePilot
+
+ } NDOF_DeviceT;
+
+// NDOF device button event types
+typedef enum {
+ // used internally, never sent
+ NDOF_BUTTON_NONE,
+ // these two are available from any 3Dconnexion device
+ NDOF_BUTTON_MENU,
+ NDOF_BUTTON_FIT,
+ // standard views
+ NDOF_BUTTON_TOP,
+ NDOF_BUTTON_BOTTOM,
+ NDOF_BUTTON_LEFT,
+ NDOF_BUTTON_RIGHT,
+ NDOF_BUTTON_FRONT,
+ NDOF_BUTTON_BACK,
+ // more views
+ NDOF_BUTTON_ISO1,
+ NDOF_BUTTON_ISO2,
+ // 90 degree rotations
+ // these don't all correspond to physical buttons
+ NDOF_BUTTON_ROLL_CW,
+ NDOF_BUTTON_ROLL_CCW,
+ NDOF_BUTTON_SPIN_CW,
+ NDOF_BUTTON_SPIN_CCW,
+ NDOF_BUTTON_TILT_CW,
+ NDOF_BUTTON_TILT_CCW,
+ // device control
+ NDOF_BUTTON_ROTATE,
+ NDOF_BUTTON_PANZOOM,
+ NDOF_BUTTON_DOMINANT,
+ NDOF_BUTTON_PLUS,
+ NDOF_BUTTON_MINUS,
+ // general-purpose buttons
+ // users can assign functions via keymap editor
+ NDOF_BUTTON_1,
+ NDOF_BUTTON_2,
+ NDOF_BUTTON_3,
+ NDOF_BUTTON_4,
+ NDOF_BUTTON_5,
+ NDOF_BUTTON_6,
+ NDOF_BUTTON_7,
+ NDOF_BUTTON_8,
+ NDOF_BUTTON_9,
+ NDOF_BUTTON_10,
+
+ } NDOF_ButtonT;
class GHOST_NDOFManager
{
public:
- GHOST_NDOFManager();
- virtual ~GHOST_NDOFManager();
-
- int deviceOpen(GHOST_IWindow* window,
- GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
- GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
- GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
-
- void GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const;
-
- bool available() const;
- bool event_present() const;
+ GHOST_NDOFManager(GHOST_System&);
+
+ virtual ~GHOST_NDOFManager() {};
+
+ // whether multi-axis functionality is available (via the OS or driver)
+ // does not imply that a device is plugged in or being used
+ virtual bool available() = 0;
+
+ // each platform's device detection should call this
+ // use standard USB/HID identifiers
+ bool setDevice(unsigned short vendor_id, unsigned short product_id);
+
+ // filter out small/accidental/uncalibrated motions by
+ // setting up a "dead zone" around home position
+ // set to 0 to disable
+ // 0.1 is a safe and reasonable value
+ void setDeadZone(float);
+
+ // the latest raw axis data from the device
+ // NOTE: axis data should be in blender view coordinates
+ // +X is to the right
+ // +Y is up
+ // +Z is out of the screen
+ // for rotations, look from origin to each +axis
+ // rotations are + when CCW, - when CW
+ // each platform is responsible for getting axis data into this form
+ // these values should not be scaled (just shuffled or flipped)
+ void updateTranslation(short t[3], GHOST_TUns64 time);
+ void updateRotation(short r[3], GHOST_TUns64 time);
+
+ // the latest raw button data from the device
+ // use HID button encoding (not NDOF_ButtonT)
+ void updateButton(int button_number, bool press, GHOST_TUns64 time);
+ void updateButtons(int button_bits, GHOST_TUns64 time);
+ // NDOFButton events are sent immediately
+
+ // processes and sends most recent raw data as an NDOFMotion event
+ // returns whether an event was sent
+ bool sendMotionEvent();
protected:
- void* m_DeviceHandle;
-};
+ GHOST_System& m_system;
+private:
+ void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*);
+ void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*);
+
+ NDOF_DeviceT m_deviceType;
+ int m_buttonCount;
+ int m_buttonMask;
+
+ short m_translation[3];
+ short m_rotation[3];
+ int m_buttons; // bit field
+
+ GHOST_TUns64 m_motionTime; // in milliseconds
+ GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent
+
+ GHOST_TProgress m_motionState;
+ bool m_motionEventPending;
+ float m_deadZone; // discard motion with each component < this
+};
#endif
diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h
new file mode 100644
index 00000000000..d8711e915f6
--- /dev/null
+++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h
@@ -0,0 +1,48 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ * Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef _GHOST_NDOFMANAGERCOCOA_H_
+#define _GHOST_NDOFMANAGERCOCOA_H_
+
+#include "GHOST_NDOFManager.h"
+
+// Event capture is handled within the NDOF manager on Macintosh,
+// so there's no need for SystemCocoa to look for them.
+
+class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager
+{
+public:
+ GHOST_NDOFManagerCocoa(GHOST_System&);
+
+ ~GHOST_NDOFManagerCocoa();
+
+ // 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();
+
+private:
+ unsigned short m_clientID;
+};
+
+
+#endif
diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
new file mode 100644
index 00000000000..995f73955f2
--- /dev/null
+++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
@@ -0,0 +1,172 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ * Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "GHOST_NDOFManagerCocoa.h"
+#include "GHOST_SystemCocoa.h"
+
+extern "C" {
+ #include <3DconnexionClient/ConnexionClientAPI.h>
+ #include <stdio.h>
+ }
+
+// static functions need to talk to these objects:
+static GHOST_SystemCocoa* ghost_system = NULL;
+static GHOST_NDOFManager* ndof_manager = NULL;
+
+// 3Dconnexion drivers before 10.x are "old"
+// not all buttons will work
+static bool has_old_driver = true;
+
+static void NDOF_DeviceAdded(io_connect_t connection)
+ {
+ printf("ndof: device added\n"); // change these: printf --> informational reports
+
+#if 0 // device preferences will be useful some day
+ ConnexionDevicePrefs p;
+ ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p);
+#endif
+
+ // determine exactly which device is plugged in
+ SInt32 result = 0;
+ ConnexionControl(kConnexionCtlGetDeviceID, 0, &result);
+ unsigned short vendorID = result >> 16;
+ unsigned short productID = result & 0xffff;
+
+ ndof_manager->setDevice(vendorID, productID);
+ }
+
+static void NDOF_DeviceRemoved(io_connect_t connection)
+ {
+ printf("ndof: device removed\n");
+ }
+
+static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument)
+ {
+ switch (messageType)
+ {
+ case kConnexionMsgDeviceState:
+ {
+ ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument;
+
+ GHOST_TUns64 now = ghost_system->getMilliSeconds();
+
+ switch (s->command)
+ {
+ case kConnexionCmdHandleAxis:
+ {
+ // convert to blender view coordinates
+ short t[3] = {s->axis[0], -(s->axis[2]), s->axis[1]};
+ short r[3] = {-(s->axis[3]), s->axis[5], -(s->axis[4])};
+
+ ndof_manager->updateTranslation(t, now);
+ ndof_manager->updateRotation(r, now);
+
+ ghost_system->notifyExternalEventProcessed();
+ break;
+ }
+ case kConnexionCmdHandleButtons:
+ {
+ int button_bits = has_old_driver ? s->buttons8 : s->buttons;
+ ndof_manager->updateButtons(button_bits, now);
+ ghost_system->notifyExternalEventProcessed();
+ break;
+ }
+ case kConnexionCmdAppSpecific:
+ printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value);
+ break;
+
+ default:
+ printf("ndof: mystery device command %d\n", s->command);
+ }
+ break;
+ }
+ case kConnexionMsgPrefsChanged:
+ // printf("ndof: prefs changed\n"); // this includes app switches
+ // TODO: look through updated prefs for things blender cares about
+ break;
+ case kConnexionMsgCalibrateDevice:
+ printf("ndof: calibrate\n"); // but what should blender do?
+ break;
+ case kConnexionMsgDoMapping:
+ // printf("ndof: driver did something\n");
+ // sent when the driver itself consumes an NDOF event
+ // and performs whatever action is set in user prefs
+ // 3Dx header file says to ignore these
+ break;
+ default:
+ printf("ndof: mystery event %d\n", messageType);
+ }
+ }
+
+GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys)
+ : GHOST_NDOFManager(sys)
+ {
+ if (available())
+ {
+ // give static functions something to talk to:
+ ghost_system = dynamic_cast<GHOST_SystemCocoa*>(&sys);
+ ndof_manager = this;
+
+ OSErr error = InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved);
+ if (error)
+ {
+ printf("ndof: error %d while installing handlers\n", error);
+ return;
+ }
+
+ // Pascal string *and* a four-letter constant. How old-skool.
+ m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\007blender",
+ kConnexionClientModeTakeOver, kConnexionMaskAll);
+
+ // printf("ndof: client id = %d\n", m_clientID);
+
+ if (SetConnexionClientButtonMask != NULL)
+ {
+ has_old_driver = false;
+ SetConnexionClientButtonMask(m_clientID, kConnexionMaskAllButtons);
+ }
+ else
+ printf("ndof: old 3Dx driver installed, some buttons may not work\n");
+ }
+ else
+ {
+ printf("ndof: 3Dx driver not found\n");
+ // This isn't a hard error, just means the user doesn't have a 3D mouse.
+ }
+ }
+
+GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
+ {
+ UnregisterConnexionClient(m_clientID);
+ CleanupConnexionHandlers();
+ ghost_system = NULL;
+ ndof_manager = NULL;
+ }
+
+bool GHOST_NDOFManagerCocoa::available()
+ {
+ // extern OSErr InstallConnexionHandlers() __attribute__((weak_import));
+ // ^^ not needed since the entire framework is weak-linked
+ return InstallConnexionHandlers != NULL;
+ // this means that the driver is installed and dynamically linked to blender
+ }
diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
new file mode 100644
index 00000000000..d7285d568de
--- /dev/null
+++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
@@ -0,0 +1,37 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ * Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "GHOST_NDOFManagerWin32.h"
+
+
+GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System& sys)
+ : GHOST_NDOFManager(sys)
+ {}
+
+// whether multi-axis functionality is available (via the OS or driver)
+// does not imply that a device is plugged in or being used
+bool GHOST_NDOFManagerWin32::available()
+ {
+ // always available since RawInput is built into Windows
+ return true;
+ }
diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h
new file mode 100644
index 00000000000..3802a6de93d
--- /dev/null
+++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h
@@ -0,0 +1,38 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ * Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef _GHOST_NDOFMANAGERWIN32_H_
+#define _GHOST_NDOFMANAGERWIN32_H_
+
+#include "GHOST_NDOFManager.h"
+
+
+class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager
+{
+public:
+ GHOST_NDOFManagerWin32(GHOST_System&);
+ bool available();
+};
+
+
+#endif
diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
new file mode 100644
index 00000000000..233a9b367f1
--- /dev/null
+++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
@@ -0,0 +1,110 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ * Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "GHOST_NDOFManagerX11.h"
+#include "GHOST_SystemX11.h"
+#include <spnav.h>
+#include <stdio.h>
+
+
+GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
+ : GHOST_NDOFManager(sys)
+ , m_available(false)
+ {
+ setDeadZone(0.1f); // how to calibrate on Linux? throw away slight motion!
+
+ if (spnav_open() != -1)
+ {
+ // determine exactly which device (if any) is plugged in
+
+ #define MAX_LINE_LENGTH 100
+
+ // look for USB devices with Logitech's vendor ID
+ FILE* command_output = popen("lsusb -d 046d:","r");
+ if (command_output)
+ {
+ char line[MAX_LINE_LENGTH] = {0};
+ while (fgets(line, MAX_LINE_LENGTH, command_output))
+ {
+ unsigned short vendor_id = 0, product_id = 0;
+ if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2)
+ if (setDevice(vendor_id, product_id))
+ {
+ m_available = true;
+ break; // stop looking once the first 3D mouse is found
+ }
+ }
+ pclose(command_output);
+ }
+ }
+ else
+ {
+ printf("ndof: spacenavd not found\n");
+ // This isn't a hard error, just means the user doesn't have a 3D mouse.
+ }
+ }
+
+GHOST_NDOFManagerX11::~GHOST_NDOFManagerX11()
+ {
+ if (m_available)
+ spnav_close();
+ }
+
+bool GHOST_NDOFManagerX11::available()
+ {
+ return m_available;
+ }
+
+//bool GHOST_NDOFManagerX11::identifyDevice()
+// {
+//
+// }
+
+bool GHOST_NDOFManagerX11::processEvents()
+ {
+ GHOST_TUns64 now = m_system.getMilliSeconds();
+
+ bool anyProcessed = false;
+ spnav_event e;
+ while (spnav_poll_event(&e))
+ {
+ switch (e.type)
+ {
+ case SPNAV_EVENT_MOTION:
+ {
+ // convert to blender view coords
+ short t[3] = {e.motion.x, e.motion.y, -e.motion.z};
+ short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz};
+
+ updateTranslation(t, now);
+ updateRotation(r, now);
+ break;
+ }
+ case SPNAV_EVENT_BUTTON:
+ updateButton(e.button.bnum, e.button.press, now);
+ break;
+ }
+ anyProcessed = true;
+ }
+ return anyProcessed;
+ }
diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h
new file mode 100644
index 00000000000..5e1c9d91074
--- /dev/null
+++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h
@@ -0,0 +1,47 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ * Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef _GHOST_NDOFMANAGERX11_H_
+#define _GHOST_NDOFMANAGERX11_H_
+
+#include "GHOST_NDOFManager.h"
+
+// Event capture is handled within the NDOF manager on Linux,
+// so there's no need for SystemX11 to look for them.
+
+class GHOST_NDOFManagerX11 : public GHOST_NDOFManager
+ {
+public:
+ GHOST_NDOFManagerX11(GHOST_System&);
+ ~GHOST_NDOFManagerX11();
+ bool available();
+ bool processEvents();
+
+private:
+// bool identifyDevice();
+
+ bool m_available;
+ };
+
+#endif
+
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index cb3e97fc574..792adba7ce3 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -194,12 +194,15 @@ bool GHOST_System::getFullScreen(void)
bool GHOST_System::dispatchEvents()
{
- bool handled;
- if (m_eventManager) {
- handled = m_eventManager->dispatchEvents();
+ bool handled = false;
+
+ // NDOF Motion event is sent only once per dispatch, so do it now:
+ if (m_ndofManager) {
+ handled |= m_ndofManager->sendMotionEvent();
}
- else {
- handled = false;
+
+ if (m_eventManager) {
+ handled |= m_eventManager->dispatchEvents();
}
m_timerManager->fireTimers(getMilliSeconds());
@@ -243,18 +246,6 @@ GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event)
return success;
}
-int GHOST_System::openNDOF(GHOST_IWindow* w,
- GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
- GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
- GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
-{
- return m_ndofManager->deviceOpen(w,
- setNdofLibraryInit,
- setNdofLibraryShutdown,
- setNdofDeviceOpen);
-}
-
-
GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const
{
GHOST_ModifierKeys keys;
@@ -285,12 +276,6 @@ GHOST_TSuccess GHOST_System::init()
m_timerManager = new GHOST_TimerManager ();
m_windowManager = new GHOST_WindowManager ();
m_eventManager = new GHOST_EventManager ();
- m_ndofManager = new GHOST_NDOFManager();
-
-#if 0
- if(m_ndofManager)
- printf("ndof manager \n");
-#endif
#ifdef GHOST_DEBUG
if (m_eventManager) {
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index b5c64bfceb6..f62c0984c80 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -191,25 +191,6 @@ public:
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer);
/***************************************************************************************
- ** N-degree of freedom devcice management functionality
- ***************************************************************************************/
-
- /** Inherited from GHOST_ISystem
- * Opens the N-degree of freedom device manager
- * return 0 if device found, 1 otherwise
- */
- virtual int openNDOF(GHOST_IWindow* w,
- GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
- GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
- GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
-
-// original patch only
-// GHOST_NDOFEventHandler_fp setNdofEventHandler);
-
-
-
-
- /***************************************************************************************
** Cursor management functionality
***************************************************************************************/
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index ce777358389..d20aed63f42 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -221,6 +221,11 @@ public:
GHOST_TSuccess handleApplicationBecomeActiveEvent();
/**
+ * External objects should call this when they send an event outside processEvents.
+ */
+ void notifyExternalEventProcessed();
+
+ /**
* @see GHOST_ISystem
*/
int toggleConsole(int action) { return 0; }
@@ -267,7 +272,7 @@ protected:
/** Start time at initialization. */
GHOST_TUns64 m_start_time;
- /** Event has been processed directly by Cocoa and has sent a ghost event to be dispatched */
+ /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */
bool m_outsideLoopEventProcessed;
/** Raised window is not yet known by the window manager, so delay application become active event handling */
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 5c88523d406..8f2df4c396d 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -52,7 +52,7 @@
#include "GHOST_TimerTask.h"
#include "GHOST_WindowManager.h"
#include "GHOST_WindowCocoa.h"
-#include "GHOST_NDOFManager.h"
+#include "GHOST_NDOFManagerCocoa.h"
#include "AssertMacros.h"
#pragma mark KeyMap, mouse converters
@@ -596,6 +596,9 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
GHOST_TSuccess success = GHOST_System::init();
if (success) {
+
+ m_ndofManager = new GHOST_NDOFManagerCocoa(*this);
+
//ProcessSerialNumber psn;
//Carbon stuff to move window & menu to foreground
@@ -1007,6 +1010,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
return GHOST_kSuccess;
}
+void GHOST_SystemCocoa::notifyExternalEventProcessed()
+{
+ m_outsideLoopEventProcessed = true;
+}
+
//Note: called from NSWindow delegate
GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window)
{
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
index becccc2c29f..523d119c7e7 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
@@ -32,12 +32,9 @@
#include "GHOST_SystemPathsWin32.h"
-#define WIN32_LEAN_AND_MEAN
-#ifdef _WIN32_IE
-#undef _WIN32_IE
-#endif
+#ifndef _WIN32_IE
#define _WIN32_IE 0x0501
-#include <windows.h>
+#endif
#include <shlobj.h>
#if defined(__MINGW32__) || defined(__CYGWIN__)
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h
index 67cc2140e0e..3de7bbf934e 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.h
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h
@@ -38,6 +38,8 @@
#error WIN32 only!
#endif // WIN32
+#define _WIN32_WINNT 0x501 // require Windows XP or newer
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "GHOST_SystemPaths.h"
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 95b3456ce3b..1b43fa92bb2 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -39,21 +39,18 @@
* @date May 7, 2001
*/
+#ifdef BF_GHOST_DEBUG
#include <iostream>
-
-#ifdef FREE_WINDOWS
-# define WINVER 0x0501 /* GetConsoleWindow() for MinGW */
#endif
+#include <stdio.h> // [mce] temporary debug, remove soon!
+
#include "GHOST_SystemWin32.h"
#include "GHOST_EventDragnDrop.h"
-#define WIN32_LEAN_AND_MEAN
-#ifdef _WIN32_IE
-#undef _WIN32_IE
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */
#endif
-#define _WIN32_IE 0x0501
-#include <windows.h>
#include <shlobj.h>
#include <tlhelp32.h>
@@ -65,48 +62,17 @@
#endif
#endif
-/*
- * According to the docs the mouse wheel message is supported from windows 98
- * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the
- * wheel detent value are undefined.
- */
-#ifndef WM_MOUSEWHEEL
-#define WM_MOUSEWHEEL 0x020A
-#endif // WM_MOUSEWHEEL
-#ifndef WHEEL_DELTA
-#define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */
-#endif // WHEEL_DELTA
-
-/*
- * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2.
- * MSDN: Declared in Winuser.h, include Windows.h
- * This does not seem to work with MinGW so we define our own here.
- */
-#ifndef XBUTTON1
-#define XBUTTON1 0x0001
-#endif // XBUTTON1
-#ifndef XBUTTON2
-#define XBUTTON2 0x0002
-#endif // XBUTTON2
-#ifndef WM_XBUTTONUP
-#define WM_XBUTTONUP 524
-#endif // WM_XBUTTONUP
-#ifndef WM_XBUTTONDOWN
-#define WM_XBUTTONDOWN 523
-#endif // WM_XBUTTONDOWN
-
#include "GHOST_Debug.h"
#include "GHOST_DisplayManagerWin32.h"
#include "GHOST_EventButton.h"
#include "GHOST_EventCursor.h"
#include "GHOST_EventKey.h"
#include "GHOST_EventWheel.h"
-#include "GHOST_EventNDOF.h"
#include "GHOST_TimerTask.h"
#include "GHOST_TimerManager.h"
#include "GHOST_WindowManager.h"
#include "GHOST_WindowWin32.h"
-#include "GHOST_NDOFManager.h"
+#include "GHOST_NDOFManagerWin32.h"
// Key code values not found in winuser.h
#ifndef VK_MINUS
@@ -159,18 +125,25 @@
#define VK_MEDIA_PLAY_PAUSE 0xB3
#endif // VK_MEDIA_PLAY_PAUSE
-/*
- Initiates WM_INPUT messages from keyboard
- That way GHOST can retrieve true keys
-*/
-GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void)
+static void initRawInput()
{
- RAWINPUTDEVICE device = {0};
- device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/
- device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
+ RAWINPUTDEVICE devices[2];
+ memset(devices, 0, 2 * sizeof(RAWINPUTDEVICE));
- return RegisterRawInputDevices(&device, 1, sizeof(device));
-};
+ // multi-axis mouse (SpaceNavigator, etc.)
+ devices[0].usUsagePage = 0x01;
+ devices[0].usUsage = 0x08;
+
+ // Initiates WM_INPUT messages from keyboard
+ // That way GHOST can retrieve true keys
+ devices[1].usUsagePage = 0x01;
+ devices[1].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
+
+ if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE)))
+ puts("registered for RawInput (spacenav & keyboard)");
+ else
+ printf("could not register for RawInput: %d\n", (int)GetLastError());
+}
GHOST_SystemWin32::GHOST_SystemWin32()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0)
@@ -187,6 +160,8 @@ GHOST_SystemWin32::GHOST_SystemWin32()
this->handleKeyboardChange();
// Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
OleInitialize(0);
+
+ m_ndofManager = new GHOST_NDOFManagerWin32(*this);
}
GHOST_SystemWin32::~GHOST_SystemWin32()
@@ -245,6 +220,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
// Store the pointer to the window
// if (state != GHOST_kWindowStateFullScreen) {
m_windowManager->addWindow(window);
+ m_windowManager->setActiveWindow(window);
// }
}
else {
@@ -385,22 +361,15 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess success = GHOST_System::init();
/* Disable scaling on high DPI displays on Vista */
+ HMODULE
user32 = ::LoadLibraryA("user32.dll");
typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
(LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
if (SetProcessDPIAware)
SetProcessDPIAware();
- #ifdef NEED_RAW_PROC
- pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices");
- pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData");
- #else
- FreeLibrary(user32);
- #endif
-
- /* Initiates WM_INPUT messages from keyboard */
- initKeyboardRawInput();
-
+ FreeLibrary(user32);
+ initRawInput();
// Determine whether this system has a high frequency performance counter. */
m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
@@ -441,104 +410,84 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess GHOST_SystemWin32::exit()
{
- #ifdef NEED_RAW_PROC
- FreeLibrary(user32);
- #endif
-
return GHOST_System::exit();
}
-GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk)
+GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk)
{
- unsigned int size = 0;
- char * data;
GHOST_TKey key = GHOST_kKeyUnknown;
if(!keyDown)
return GHOST_kKeyUnknown;
- GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER));
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- if((data = (char*)malloc(size)) &&
- GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER)))
+ GHOST_ModifierKeys modifiers;
+ system->retrieveModifierKeys(modifiers);
+
+ *keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK);
+ key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
+
+ // extra handling of modifier keys: don't send repeats out from GHOST
+ if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
{
- RAWINPUT ri;
- memcpy(&ri,data,(size < sizeof(ri)) ? size : sizeof(ri));
-
- if (ri.header.dwType == RIM_TYPEKEYBOARD)
- {
- GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
-
- GHOST_ModifierKeys modifiers;
- system->retrieveModifierKeys(modifiers);
-
- *keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK);
- key = this->convertKey(window, ri.data.keyboard.VKey, ri.data.keyboard.MakeCode, (ri.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
-
- // extra handling of modifier keys: don't send repeats out from GHOST
- if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
- {
- bool changed = false;
- GHOST_TModifierKeyMask modifier;
- switch(key) {
- case GHOST_kKeyLeftShift:
- {
- changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown);
- modifier = GHOST_kModifierKeyLeftShift;
- }
- break;
- case GHOST_kKeyRightShift:
- {
- changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown);
- modifier = GHOST_kModifierKeyRightShift;
- }
- break;
- case GHOST_kKeyLeftControl:
- {
- changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown);
- modifier = GHOST_kModifierKeyLeftControl;
- }
- break;
- case GHOST_kKeyRightControl:
- {
- changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown);
- modifier = GHOST_kModifierKeyRightControl;
- }
- break;
- case GHOST_kKeyLeftAlt:
- {
- changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown);
- modifier = GHOST_kModifierKeyLeftAlt;
- }
- break;
- case GHOST_kKeyRightAlt:
- {
- changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown);
- modifier = GHOST_kModifierKeyRightAlt;
- }
- break;
- default: break;
+ bool changed = false;
+ GHOST_TModifierKeyMask modifier;
+ switch(key) {
+ case GHOST_kKeyLeftShift:
+ {
+ changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown);
+ modifier = GHOST_kModifierKeyLeftShift;
}
-
- if(changed)
+ break;
+ case GHOST_kKeyRightShift:
{
- modifiers.set(modifier, (bool)*keyDown);
- system->storeModifierKeys(modifiers);
+ changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown);
+ modifier = GHOST_kModifierKeyRightShift;
+ }
+ break;
+ case GHOST_kKeyLeftControl:
+ {
+ changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown);
+ modifier = GHOST_kModifierKeyLeftControl;
}
- else
+ break;
+ case GHOST_kKeyRightControl:
{
- key = GHOST_kKeyUnknown;
+ changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown);
+ modifier = GHOST_kModifierKeyRightControl;
}
- }
-
+ break;
+ case GHOST_kKeyLeftAlt:
+ {
+ changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown);
+ modifier = GHOST_kModifierKeyLeftAlt;
+ }
+ break;
+ case GHOST_kKeyRightAlt:
+ {
+ changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown);
+ modifier = GHOST_kModifierKeyRightAlt;
+ }
+ break;
+ default: break;
+ }
+
+ if(changed)
+ {
+ modifiers.set(modifier, (bool)*keyDown);
+ system->storeModifierKeys(modifiers);
+ }
+ else
+ {
+ key = GHOST_kKeyUnknown;
+ }
+ }
- if(vk) *vk = ri.data.keyboard.VKey;
- };
- };
- free(data);
+ if(vk) *vk = raw.data.keyboard.VKey;
return key;
}
@@ -742,12 +691,12 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP
}
-GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
+GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw)
{
int keyDown=0;
char vk;
GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem();
- GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk);
+ GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk);
GHOST_EventKey* event;
if (key != GHOST_kKeyUnknown) {
char ascii = '\0';
@@ -777,7 +726,15 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM
GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
{
- return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
+ GHOST_System* system = (GHOST_System*)getSystem();
+
+ if (type == GHOST_kEventWindowActivate)
+ {
+ puts("activating window");
+ system->getWindowManager()->setActiveWindow(window);
+ }
+
+ return new GHOST_Event(system->getMilliSeconds(), type, window);
}
GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
@@ -800,9 +757,101 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
minmax->ptMinTrackSize.y=240;
}
+bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw)
+{
+ bool eventSent = false;
+ GHOST_TUns64 now = getMilliSeconds();
+
+ static bool firstEvent = true;
+ if (firstEvent)
+ { // determine exactly which device is plugged in
+ RID_DEVICE_INFO info;
+ unsigned infoSize = sizeof(RID_DEVICE_INFO);
+ info.cbSize = infoSize;
+
+ GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize);
+ if (info.dwType == RIM_TYPEHID)
+ m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
+ else
+ puts("<!> not a HID device... mouse/kb perhaps?");
+
+ firstEvent = false;
+ }
+
+ // The NDOF manager sends button changes immediately, and *pretends* to
+ // send motion. Mark as 'sent' so motion will always get dispatched.
+ eventSent = true;
+
+#ifdef _MSC_VER
+ // using Microsoft compiler & header files
+ // they invented the RawInput API, so this version is (probably) correct
+ BYTE const* data = raw.data.hid.bRawData;
+ // struct RAWHID {
+ // DWORD dwSizeHid;
+ // DWORD dwCount;
+ // BYTE bRawData[1];
+ // };
+#else
+ // MinGW's definition (below) doesn't agree, so we need a slight
+ // workaround until it's fixed
+ BYTE const* data = &raw.data.hid.bRawData;
+ // struct RAWHID {
+ // DWORD dwSizeHid;
+ // DWORD dwCount;
+ // BYTE bRawData; // <== isn't this s'posed to be a BYTE*?
+ // };
+#endif
+
+ BYTE packetType = data[0];
+ switch (packetType)
+ {
+ case 1: // translation
+ {
+ short* axis = (short*)(data + 1);
+ short t[3] = {axis[0], -axis[2], axis[1]};
+ m_ndofManager->updateTranslation(t, now);
+
+ if (raw.data.hid.dwSizeHid == 13)
+ { // this report also includes rotation
+ short r[3] = {-axis[3], axis[5], -axis[4]};
+ m_ndofManager->updateRotation(r, now);
+
+ // I've never gotten one of these, has anyone else?
+ puts("ndof: combined T + R");
+ }
+ break;
+ }
+ case 2: // rotation
+ {
+ short* axis = (short*)(data + 1);
+ short r[3] = {-axis[0], axis[2], -axis[1]};
+ m_ndofManager->updateRotation(r, now);
+ break;
+ }
+ case 3: // buttons
+ {
+ #if 0
+ // I'm getting garbage bits -- examine whole report:
+ printf("ndof: HID report for buttons [");
+ for (int i = 0; i < raw.data.hid.dwSizeHid; ++i)
+ printf(" %02X", data[i]);
+ printf(" ]\n");
+ #endif
+
+ int button_bits;
+ memcpy(&button_bits, data + 1, sizeof(button_bits));
+ m_ndofManager->updateButtons(button_bits, now);
+ break;
+ }
+ }
+ return eventSent;
+}
+
LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
GHOST_Event* event = 0;
+ bool eventHandled = false;
+
LRESULT lResult = 0;
GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
@@ -819,18 +868,36 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
case WM_INPUT:
+ {
// check WM_INPUT from input sink when ghost window is not in the foreground
if (wParam == RIM_INPUTSINK) {
if (GetFocus() != hwnd) // WM_INPUT message not for this window
return 0;
- } //else wPAram == RIM_INPUT
- event = processKeyEvent(window, wParam, lParam);
- if (!event) {
- GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
- GHOST_PRINT(msg)
- GHOST_PRINT(" key ignored\n")
+ } //else wParam == RIM_INPUT
+
+ RAWINPUT raw;
+ RAWINPUT* raw_ptr = &raw;
+ UINT rawSize = sizeof(RAWINPUT);
+
+ GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER));
+
+ switch (raw.header.dwType)
+ {
+ case RIM_TYPEKEYBOARD:
+ event = processKeyEvent(window, raw);
+ if (!event) {
+ GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
+ GHOST_PRINT(msg)
+ GHOST_PRINT(" key ignored\n")
+ }
+ break;
+ case RIM_TYPEHID:
+ if (system->processNDOF(raw))
+ eventHandled = true;
+ break;
}
- break;
+ break;
+ }
////////////////////////////////////////////////////////////////////////
// Keyboard events, ignored
////////////////////////////////////////////////////////////////////////
@@ -840,9 +907,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
case WM_SYSKEYUP:
/* These functions were replaced by WM_INPUT*/
case WM_CHAR:
- /* The WM_CHAR message is posted to the window with the keyboard focus when
- * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
- * contains the character code of the key that was pressed.
+ /* The WM_CHAR message is posted to the window with the keyboard focus when
+ * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
+ * contains the character code of the key that was pressed.
*/
case WM_DEADCHAR:
/* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
@@ -1128,28 +1195,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* In GHOST, we let DefWindowProc call the timer callback.
*/
break;
- case WM_BLND_NDOF_AXIS:
- {
- GHOST_TEventNDOFData ndofdata;
- system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
- system->m_eventManager->
- pushEvent(new GHOST_EventNDOF(
- system->getMilliSeconds(),
- GHOST_kEventNDOFMotion,
- window, ndofdata));
- }
- break;
- case WM_BLND_NDOF_BTN:
- {
- GHOST_TEventNDOFData ndofdata;
- system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
- system->m_eventManager->
- pushEvent(new GHOST_EventNDOF(
- system->getMilliSeconds(),
- GHOST_kEventNDOFButton,
- window, ndofdata));
- }
- break;
}
}
else {
@@ -1171,10 +1216,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
if (event) {
system->pushEvent(event);
+ eventHandled = true;
}
- else {
+
+ if (!eventHandled)
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
- }
+
return lResult;
}
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 729ad56d875..c5dff27dace 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -38,7 +38,10 @@
#error WIN32 only!
#endif // WIN32
+#define _WIN32_WINNT 0x501 // require Windows XP or newer
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#include <ole2.h> // for drag-n-drop
#include "GHOST_System.h"
@@ -46,95 +49,6 @@
# define __int64 long long
#endif
-#ifndef WM_INPUT
-#define WM_INPUT 0x00FF
-#endif
-#ifndef RID_INPUT
-#define RID_INPUT 0x10000003
-#endif
-#ifndef RIM_INPUTSINK
-#define RIM_INPUTSINK 0x1
-#endif
-#ifndef RI_KEY_BREAK
-#define RI_KEY_BREAK 0x1
-#endif
-#ifndef RI_KEY_E0
-#define RI_KEY_E0 0x2
-#endif
-#ifndef RI_KEY_E1
-#define RI_KEY_E1 0x4
-#endif
-#ifndef RIM_TYPEMOUSE
-#define RIM_TYPEMOUSE 0x0
-#define RIM_TYPEKEYBOARD 0x1
-#define RIM_TYPEHID 0x2
-
-typedef struct tagRAWINPUTDEVICE {
- USHORT usUsagePage;
- USHORT usUsage;
- DWORD dwFlags;
- HWND hwndTarget;
-} RAWINPUTDEVICE;
-
-
-
-typedef struct tagRAWINPUTHEADER {
- DWORD dwType;
- DWORD dwSize;
- HANDLE hDevice;
- WPARAM wParam;
-} RAWINPUTHEADER;
-
-typedef struct tagRAWMOUSE {
- USHORT usFlags;
- union {
- ULONG ulButtons;
- struct {
- USHORT usButtonFlags;
- USHORT usButtonData;
- };
- };
- ULONG ulRawButtons;
- LONG lLastX;
- LONG lLastY;
- ULONG ulExtraInformation;
-} RAWMOUSE;
-
-typedef struct tagRAWKEYBOARD {
- USHORT MakeCode;
- USHORT Flags;
- USHORT Reserved;
- USHORT VKey;
- UINT Message;
- ULONG ExtraInformation;
-} RAWKEYBOARD;
-
-typedef struct tagRAWHID {
- DWORD dwSizeHid;
- DWORD dwCount;
- BYTE bRawData[1];
-} RAWHID;
-
-typedef struct tagRAWINPUT {
- RAWINPUTHEADER header;
- union {
- RAWMOUSE mouse;
- RAWKEYBOARD keyboard;
- RAWHID hid;
- } data;
-} RAWINPUT;
-
-DECLARE_HANDLE(HRAWINPUT);
-#endif
-
-#ifdef FREE_WINDOWS
-#define NEED_RAW_PROC
-typedef BOOL (WINAPI * LPFNDLLRRID)(RAWINPUTDEVICE*,UINT, UINT);
-
-typedef UINT (WINAPI * LPFNDLLGRID)(HRAWINPUT, UINT, LPVOID, PUINT, UINT);
-#define GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader) ((pGetRawInputData)?pGetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader):(UINT)-1)
-#endif
-
class GHOST_EventButton;
class GHOST_EventCursor;
class GHOST_EventKey;
@@ -314,14 +228,13 @@ protected:
/**
* Catches raw WIN32 key codes from WM_INPUT in the wndproc.
- * @param window-> The window for this handling
- * @param wParam The wParam from the wndproc
- * @param lParam The lParam from the wndproc
+ * @param window The window for this handling
+ * @param raw RawInput structure with detailed info about the key event
* @param keyDown Pointer flag that specify if a key is down
* @param vk Pointer to virtual key
* @return The GHOST key (GHOST_kKeyUnknown if no match).
*/
- virtual GHOST_TKey hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk);
+ virtual GHOST_TKey hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk);
/**
* Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys).
@@ -362,10 +275,9 @@ protected:
* In most cases this is a straightforward conversion of key codes.
* For the modifier keys however, we want to distinguish left and right keys.
* @param window The window receiving the event (the active window).
- * @param wParam The wParam from the wndproc
- * @param lParam The lParam from the wndproc
+ * @param raw RawInput structure with detailed info about the key event
*/
- static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam);
+ static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw);
/**
* Process special keys (VK_OEM_*), to see if current key layout
@@ -383,12 +295,22 @@ protected:
* @return The event created.
*/
static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window);
- /**
+
+ /**
* Handles minimum window size.
* @param minmax The MINMAXINFO structure.
*/
static void processMinMaxInfo(MINMAXINFO * minmax);
-
+
+ /**
+ * Handles Motion and Button events from a SpaceNavigator or related device.
+ * Instead of returning an event object, this function communicates directly
+ * with the GHOST_NDOFManager.
+ * @param raw RawInput structure with detailed info about the NDOF event
+ * @return Whether an event was generated and sent.
+ */
+ bool processNDOF(RAWINPUT const& raw);
+
/**
* Returns the local state of the modifier keys (from the message queue).
* @param keys The state of the keys.
@@ -413,11 +335,6 @@ protected:
static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
/**
- * Initiates WM_INPUT messages from keyboard
- */
- GHOST_TInt32 initKeyboardRawInput(void);
-
- /**
* Toggles console
* @action 0 - Hides
* 1 - Shows
@@ -445,15 +362,6 @@ protected:
/** Console status */
int m_consoleStatus;
-
- /** handle for user32.dll*/
- HMODULE user32;
- #ifdef NEED_RAW_PROC
- /* pointer to RegisterRawInputDevices function */
- LPFNDLLRRID pRegisterRawInputDevices;
- /* pointer to GetRawInputData function */
- LPFNDLLGRID pGetRawInputData;
- #endif
};
inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const
@@ -487,4 +395,3 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void)
}
}
#endif // _GHOST_SYSTEM_WIN32_H_
-
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index dd296fa979c..517c3a1ebac 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -42,8 +42,7 @@
#include "GHOST_EventKey.h"
#include "GHOST_EventButton.h"
#include "GHOST_EventWheel.h"
-#include "GHOST_EventNDOF.h"
-#include "GHOST_NDOFManager.h"
+#include "GHOST_NDOFManagerX11.h"
#include "GHOST_DisplayManagerX11.h"
#include "GHOST_Debug.h"
@@ -79,19 +78,6 @@
static GHOST_TKey
convertXKey(KeySym key);
-typedef struct NDOFPlatformInfo {
- Display *display;
- Window window;
- volatile GHOST_TEventNDOFData *currValues;
- Atom cmdAtom;
- Atom motionAtom;
- Atom btnPressAtom;
- Atom btnRelAtom;
-} NDOFPlatformInfo;
-
-static NDOFPlatformInfo sNdofInfo = {NULL, 0, NULL, 0, 0, 0, 0};
-
-
//these are for copy and select copy
static char *txt_cut_buffer= NULL;
static char *txt_select_buffer= NULL;
@@ -181,6 +167,7 @@ init(
GHOST_TSuccess success = GHOST_System::init();
if (success) {
+ m_ndofManager = new GHOST_NDOFManagerX11(*this);
m_displayManager = new GHOST_DisplayManagerX11(this);
if (m_displayManager) {
@@ -275,7 +262,7 @@ createWindow(
if (window->getValid()) {
// Store the pointer to the window
m_windowManager->addWindow(window);
-
+ m_windowManager->setActiveWindow(window);
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
}
else {
@@ -386,8 +373,6 @@ lastEventTime(Time default_time) {
return data.timestamp;
}
-
-
bool
GHOST_SystemX11::
processEvents(
@@ -428,6 +413,11 @@ processEvents(
if (generateWindowExposeEvents()) {
anyProcessed = true;
}
+
+ if (dynamic_cast<GHOST_NDOFManagerX11*>(m_ndofManager)->processEvents()) {
+ anyProcessed = true;
+ }
+
} while (waitForEvent && !anyProcessed);
return anyProcessed;
@@ -611,6 +601,9 @@ GHOST_SystemX11::processEvent(XEvent *xe)
case FocusOut:
{
XFocusChangeEvent &xfe = xe->xfocus;
+
+ // TODO: make sure this is the correct place for activate/deactivate
+ // printf("X: focus %s for window %d\n", xfe.type == FocusIn ? "in" : "out", (int) xfe.window);
// May have to look at the type of event and filter some
// out.
@@ -641,32 +634,8 @@ GHOST_SystemX11::processEvent(XEvent *xe)
);
} else
#endif
- if (sNdofInfo.currValues) {
- static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0};
- if (xcme.message_type == sNdofInfo.motionAtom)
- {
- data.changed = 1;
- data.delta = xcme.data.s[8] - data.time;
- data.time = xcme.data.s[8];
- data.tx = xcme.data.s[2] >> 2;
- data.ty = xcme.data.s[3] >> 2;
- data.tz = xcme.data.s[4] >> 2;
- data.rx = xcme.data.s[5];
- data.ry = xcme.data.s[6];
- data.rz =-xcme.data.s[7];
- g_event = new GHOST_EventNDOF(getMilliSeconds(),
- GHOST_kEventNDOFMotion,
- window, data);
- } else if (xcme.message_type == sNdofInfo.btnPressAtom) {
- data.changed = 2;
- data.delta = xcme.data.s[8] - data.time;
- data.time = xcme.data.s[8];
- data.buttons = xcme.data.s[2];
- g_event = new GHOST_EventNDOF(getMilliSeconds(),
- GHOST_kEventNDOFButton,
- window, data);
- }
- } else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
+
+ if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
XWindowAttributes attr;
Window fwin;
int revert_to;
@@ -723,6 +692,14 @@ GHOST_SystemX11::processEvent(XEvent *xe)
xce.y_root
);
}
+
+ // printf("X: %s window %d\n", xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window);
+
+ if (xce.type == EnterNotify)
+ m_windowManager->setActiveWindow(window);
+ else
+ m_windowManager->setWindowInactive(window);
+
break;
}
case MapNotify:
@@ -834,6 +811,8 @@ GHOST_SystemX11::processEvent(XEvent *xe)
}
}
+#if 0 // obsolete SpaceNav code
+
void *
GHOST_SystemX11::
prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues)
@@ -846,6 +825,8 @@ prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues)
return (void*)&sNdofInfo;
}
+#endif
+
GHOST_TSuccess
GHOST_SystemX11::
getModifierKeys(
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 746cd4ebdf4..845243f92e5 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -203,11 +203,6 @@ public:
return m_display;
}
- void *
- prepareNdofInfo(
- volatile GHOST_TEventNDOFData *current_values
- );
-
/* Helped function for get data from the clipboard. */
void getClipboard_xcout(XEvent evt, Atom sel, Atom target,
unsigned char **txt, unsigned long *len,
diff --git a/intern/ghost/intern/GHOST_TaskbarWin32.h b/intern/ghost/intern/GHOST_TaskbarWin32.h
index ef9ebdf5860..eddff8bb91b 100644
--- a/intern/ghost/intern/GHOST_TaskbarWin32.h
+++ b/intern/ghost/intern/GHOST_TaskbarWin32.h
@@ -3,20 +3,16 @@
*/
#ifndef GHOST_TASKBARWIN32_H_
#define GHOST_TASKBARWIN32_H_
+
#ifndef WIN32
#error WIN32 only!
#endif // WIN32
+#define _WIN32_WINNT 0x501 // require Windows XP or newer
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlobj.h>
-/* MinGW needs it */
-#ifdef FREE_WINDOWS
-#ifdef WINVER
-#undef WINVER
-#endif
-#define WINVER 0x0501
-#endif /* FREE_WINDOWS */
// ITaskbarList, ITaskbarList2 and ITaskbarList3 might be missing, present here in that case.
// Note, ITaskbarList3 is supported only since Windows 7, though. Check for that is done in
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 4055c3acf56..70914d9d2ef 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -39,19 +39,11 @@
#endif // WIN32
#include "GHOST_Window.h"
+#include "GHOST_TaskbarWin32.h"
-/* MinGW needs it */
-#ifdef FREE_WINDOWS
-#ifdef WINVER
-#undef WINVER
-#endif
-#define WINVER 0x0501
-#endif
-
-
-
+#define _WIN32_WINNT 0x501 // require Windows XP or newer
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#include "GHOST_TaskbarWin32.h"
#include <wintab.h>