merged 30707:31141 from trunk
authorMike Erwin <significant.bit@gmail.com>
Sat, 7 Aug 2010 12:51:51 +0000 (12:51 +0000)
committerMike Erwin <significant.bit@gmail.com>
Sat, 7 Aug 2010 12:51:51 +0000 (12:51 +0000)
56 files changed:
intern/ghost/GHOST_C-api.h
intern/ghost/GHOST_ISystem.h
intern/ghost/GHOST_Rect.h
intern/ghost/GHOST_Types.h
intern/ghost/intern/GHOST_C-api.cpp
intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp [deleted file]
intern/ghost/intern/GHOST_DisplayManagerCarbon.h [deleted file]
intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
intern/ghost/intern/GHOST_DropTargetWin32.cpp
intern/ghost/intern/GHOST_DropTargetWin32.h
intern/ghost/intern/GHOST_EventButton.h
intern/ghost/intern/GHOST_EventCursor.h
intern/ghost/intern/GHOST_EventManager.cpp
intern/ghost/intern/GHOST_EventManager.h
intern/ghost/intern/GHOST_EventNDOF.h
intern/ghost/intern/GHOST_NDOFManager.cpp
intern/ghost/intern/GHOST_NDOFManager.h
intern/ghost/intern/GHOST_NDOFManagerCocoa.h [new file with mode: 0644]
intern/ghost/intern/GHOST_NDOFManagerCocoa.mm [new file with mode: 0644]
intern/ghost/intern/GHOST_NDOFManagerWin32.h [new file with mode: 0644]
intern/ghost/intern/GHOST_NDOFManagerX11.h [new file with mode: 0644]
intern/ghost/intern/GHOST_System.cpp
intern/ghost/intern/GHOST_System.h
intern/ghost/intern/GHOST_SystemCarbon.cpp [deleted file]
intern/ghost/intern/GHOST_SystemCarbon.h [deleted file]
intern/ghost/intern/GHOST_SystemCocoa.h
intern/ghost/intern/GHOST_SystemCocoa.mm
intern/ghost/intern/GHOST_SystemWin32.cpp
intern/ghost/intern/GHOST_SystemWin32.h
intern/ghost/intern/GHOST_SystemX11.cpp
intern/ghost/intern/GHOST_SystemX11.h
intern/ghost/intern/GHOST_WindowCarbon.cpp [deleted file]
intern/ghost/intern/GHOST_WindowCarbon.h [deleted file]
intern/ghost/intern/GHOST_WindowCocoa.h
intern/ghost/intern/GHOST_WindowCocoa.mm
intern/ghost/intern/GHOST_WindowWin32.cpp
intern/ghost/intern/GHOST_WindowWin32.h
intern/ghost/intern/Utils.c [new file with mode: 0644]
intern/ghost/intern/Utils.h [new file with mode: 0644]
source/blender/blenlib/intern/math_rotation.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/space_view3d/view3d_ops.c
source/blender/makesdna/DNA_view3d_types.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/wm.h
source/blender/windowmanager/wm_event_types.h
tools/Blender.py [new file with mode: 0644]
tools/__init__.py [new file with mode: 0644]
tools/bcolors.py [new file with mode: 0644]
tools/btools.py [new file with mode: 0644]
tools/crossmingw.py [new file with mode: 0644]
tools/mstoolkit.py [new file with mode: 0644]

index 28fa72f970022b2d9a2ac9da4cac54cf10a3dfca..6110b31a95ab96ee973bb82cf8ec352f16ba6e54 100644 (file)
@@ -280,21 +280,7 @@ 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
index 47f142e4c8accf351274f40c4007eae5da655453..ab97450814564aa36991344d30fc00a49647df45 100644 (file)
@@ -295,21 +295,6 @@ public:
         * @return Indication of success.
         */
        virtual GHOST_TSuccess addEventConsumer(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;
 
 
        /***************************************************************************************
@@ -353,7 +338,15 @@ public:
         */
        virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0;
 
-       
+       /** Fidelity of mouse and pen input (this definition will probably live somewhere else)*/
+       typedef enum { LO_FI, NORMAL_FI, HI_FI } InputFidelity;
+
+       /**
+        * Requests input at a certain fidelity. Certain tools want very smooth input, others don't care.
+        * @param hint          Desired fidelity of mouse and pen events.
+        */
+       virtual void setInputFidelity(InputFidelity hint) = 0;
+
        /***************************************************************************************
         ** Access to clipboard.
         ***************************************************************************************/
index e3d056dd4675909f8b948d091cbbf024da67d7f8..c72b918d63ed8e149166ec0b50849b1e23c72a84 100644 (file)
@@ -228,7 +228,7 @@ inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y)
        if (y < m_t) m_t = y;
        if (y > m_b) m_b = y;
 }
-#include <stdio.h>
+
 inline void GHOST_Rect::wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, GHOST_TInt32 ofs)
 {
        GHOST_TInt32 w= getWidth();
index f7d0425aec84291f2f0b639ef229ea427d65d78f..952c1860dc15814afde4819daadc64a1c1dec67c 100644 (file)
 #ifndef _GHOST_TYPES_H_
 #define _GHOST_TYPES_H_
 
-typedef        char                            GHOST_TInt8;
-typedef        unsigned char           GHOST_TUns8;
-typedef short                          GHOST_TInt16;
-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
+typedef char           GHOST_TInt8;
+typedef unsigned char  GHOST_TUns8;
+typedef short          GHOST_TInt16;
+typedef unsigned short GHOST_TUns16;
+typedef int            GHOST_TInt32;
+typedef unsigned int   GHOST_TUns32;
 
 #if defined(WIN32) && !defined(FREE_WINDOWS)
-typedef __int64                                GHOST_TInt64;
-typedef unsigned __int64       GHOST_TUns64;
+  typedef __int64          GHOST_TInt64;
+  typedef unsigned __int64 GHOST_TUns64;
 #else
-typedef long long                      GHOST_TInt64;
-typedef unsigned long long     GHOST_TUns64;
+  typedef long long          GHOST_TInt64;
+  typedef unsigned long long GHOST_TUns64;
 #endif
 
-typedef void*                          GHOST_TUserDataPtr;
+typedef void* GHOST_TUserDataPtr;
 
 typedef enum
 {
@@ -154,7 +149,7 @@ typedef enum {
        GHOST_kEventTrackpad,           /// Trackpad event
 
        GHOST_kEventNDOFMotion,         /// N degree of freedom device motion event
-       GHOST_kEventNDOFButton,         /// N degree of freedom device button event
+       GHOST_kEventNDOFButton,
 
        GHOST_kEventKeyDown,
        GHOST_kEventKeyUp,
@@ -275,7 +270,6 @@ typedef enum {
        GHOST_kKeyRightBracket = ']',
        GHOST_kKeyBackslash    = 0x5C,
        GHOST_kKeyAccentGrave  = '`',
-
        
        GHOST_kKeyLeftShift = 0x100,
        GHOST_kKeyRightShift,
@@ -283,8 +277,8 @@ typedef enum {
        GHOST_kKeyRightControl,
        GHOST_kKeyLeftAlt,
        GHOST_kKeyRightAlt,
-    GHOST_kKeyCommand,                         // APPLE only!
-    GHOST_kKeyGrLess ,         // German PC only!
+       GHOST_kKeyCommand,  // APPLE only!
+       GHOST_kKeyGrLess,   // German PC only!
 
        GHOST_kKeyCapsLock,
        GHOST_kKeyNumLock,
@@ -364,11 +358,17 @@ typedef struct {
        GHOST_TInt32 x;
        /** The y-coordinate of the cursor position. */
        GHOST_TInt32 y;
+
+       GHOST_TabletData tablet;
+
 } GHOST_TEventCursorData;
 
 typedef struct {
        /** The mask of the mouse button. */
        GHOST_TButtonMask button;
+
+       GHOST_TabletData tablet;
+
 } GHOST_TEventButtonData;
 
 typedef struct {
@@ -383,7 +383,6 @@ typedef enum {
        GHOST_kTrackpadEventSwipe, /* Reserved, not used for now */
        GHOST_kTrackpadEventMagnify
 } GHOST_TTrackpadEventSubTypes;
-       
 
 typedef struct {
        /** The event subtype */
@@ -422,37 +421,23 @@ typedef struct {
        GHOST_TUns8 **strings;
 } GHOST_TStringArray;
 
+typedef struct {
+   /** N-degree of freedom device data v3 [GSoC 2010]*/
+   /* Each component normally ranges from -1 to +1, but can exceed that. */
+   float tx, ty, tz; /* translation: -x left, +y forward, -z up */
+   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 (or zero if this is the first)
+
+} GHOST_TEventNDOFMotionData;
 
-/* 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 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)();
-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. */
@@ -474,13 +459,13 @@ typedef struct {
 
 
 #ifdef _WIN32
-typedef long GHOST_TEmbedderWindowID;
+  typedef long GHOST_TEmbedderWindowID;
 #endif // _WIN32
 
 #ifndef _WIN32
-// I can't use "Window" from "<X11/Xlib.h>" because it conflits with Window defined in winlay.h
-typedef int GHOST_TEmbedderWindowID;
-#endif // _WIN32
+  // I can't use "Window" from "<X11/Xlib.h>" because it conflits with Window defined in winlay.h
+  typedef int GHOST_TEmbedderWindowID;
+#endif
 
 /**
  * A timer task callback routine.
@@ -488,12 +473,11 @@ typedef int GHOST_TEmbedderWindowID;
  * @param time The current time.
  */
 #ifdef __cplusplus
-class GHOST_ITimerTask;
-typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time);
+  class GHOST_ITimerTask;
+  typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time);
 #else
-struct GHOST_TimerTaskHandle__;
-typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time);
+  struct GHOST_TimerTaskHandle__;
+  typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time);
 #endif
 
 #endif // _GHOST_TYPES_H_
-
index 839d85c9617d13365809b704cc46d5837530c797..60c9a860a2e595c4bd3d1ce8b957675851ecb58f 100644 (file)
@@ -263,22 +263,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)
 {
@@ -701,7 +685,7 @@ GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle)
        return window->invalidate();
 }
 
-
+// [mce] this is going away soon
 extern const GHOST_TabletData* GHOST_GetTabletData(GHOST_WindowHandle windowhandle)
 {
        return ((GHOST_IWindow*)windowhandle)->GetTabletData();
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp
deleted file mode 100644 (file)
index 2c92ef0..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/**
- * $Id$
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/**
-
- * $Id$
- * Copyright (C) 2001 NaN Technologies B.V.
- * @author     Maarten Gribnau
- * @date       September 21, 2001
- */
-
-#include "GHOST_DisplayManagerCarbon.h"
-#include "GHOST_Debug.h"
-
-// We do not support multiple monitors at the moment
-
-
-GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(void)
-{
-       if (::CGGetActiveDisplayList(0, NULL, &m_numDisplays) != CGDisplayNoErr)
-       {
-               m_numDisplays = 0;
-               m_displayIDs = NULL;
-       }
-       if (m_numDisplays > 0)
-       {
-               m_displayIDs = new CGDirectDisplayID [m_numDisplays];
-               GHOST_ASSERT((m_displayIDs!=NULL), "GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(): memory allocation failed");
-               ::CGGetActiveDisplayList(m_numDisplays, m_displayIDs, &m_numDisplays);
-       }
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplays(GHOST_TUns8& numDisplays) const
-{
-       numDisplays = (GHOST_TUns8) m_numDisplays;
-       return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
-{
-       GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getNumDisplaySettings(): only main display is supported");
-       
-       CFArrayRef displayModes;
-       displayModes = ::CGDisplayAvailableModes(m_displayIDs[display]);
-       CFIndex numModes = ::CFArrayGetCount(displayModes);
-       numSettings = (GHOST_TInt32)numModes;
-       
-       return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCarbon::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
-{
-       GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getDisplaySetting(): only main display is supported");
-       
-       CFArrayRef displayModes;
-       CGDirectDisplayID d = m_displayIDs[display];
-       displayModes = ::CGDisplayAvailableModes(d);
-       //CFIndex numModes = ::CFArrayGetCount(displayModes);/*unused*/
-       //GHOST_TInt32 numSettings = (GHOST_TInt32)numModes; /*unused*/
-        CFDictionaryRef displayModeValues = (CFDictionaryRef)::CFArrayGetValueAtIndex(displayModes, index);
-                       
-       setting.xPixels         = getValue(displayModeValues, kCGDisplayWidth);
-       setting.yPixels         = getValue(displayModeValues, kCGDisplayHeight);
-       setting.bpp                     = getValue(displayModeValues, kCGDisplayBitsPerPixel);
-       setting.frequency       = getValue(displayModeValues, kCGDisplayRefreshRate);
-                       
-#ifdef GHOST_DEBUG
-       printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency);
-#endif // GHOST_DEBUG
-
-       return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
-{
-       GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(): only main display is supported");
-        
-       CFDictionaryRef displayModeValues = ::CGDisplayCurrentMode(m_displayIDs[display]);
-       
-       setting.xPixels         = getValue(displayModeValues, kCGDisplayWidth);
-       setting.yPixels         = getValue(displayModeValues, kCGDisplayHeight);
-       setting.bpp                     = getValue(displayModeValues, kCGDisplayBitsPerPixel);
-       setting.frequency       = getValue(displayModeValues, kCGDisplayRefreshRate);
-
-#ifdef GHOST_DEBUG
-       printf("current display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency);
-#endif // GHOST_DEBUG
-
-       return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
-{
-       GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): only main display is supported");
-
-#ifdef GHOST_DEBUG
-       printf("GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): requested settings:\n");
-       printf("  setting.xPixels=%d\n", setting.xPixels);
-       printf("  setting.yPixels=%d\n", setting.yPixels);
-       printf("  setting.bpp=%d\n", setting.bpp);
-       printf("  setting.frequency=%d\n", setting.frequency);
-#endif // GHOST_DEBUG
-
-       CFDictionaryRef displayModeValues = ::CGDisplayBestModeForParametersAndRefreshRate(
-               m_displayIDs[display],
-               (size_t)setting.bpp,
-               (size_t)setting.xPixels,
-               (size_t)setting.yPixels,
-               (CGRefreshRate)setting.frequency,
-               NULL);
-
-#ifdef GHOST_DEBUG
-       printf("GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): switching to:\n");
-       printf("  setting.xPixels=%d\n", getValue(displayModeValues, kCGDisplayWidth));
-       printf("  setting.yPixels=%d\n", getValue(displayModeValues, kCGDisplayHeight));
-       printf("  setting.bpp=%d\n", getValue(displayModeValues, kCGDisplayBitsPerPixel));
-       printf("  setting.frequency=%d\n", getValue(displayModeValues, kCGDisplayRefreshRate));
-#endif // GHOST_DEBUG
-
-       CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues);
-        
-       return err == CGDisplayNoErr ? GHOST_kSuccess : GHOST_kFailure;
-}
-
-
-long GHOST_DisplayManagerCarbon::getValue(CFDictionaryRef values, CFStringRef key) const
-{
-    CFNumberRef numberValue = (CFNumberRef) CFDictionaryGetValue(values, key);
-    
-    if (!numberValue)
-    {
-        return -1;
-    }
-    
-    long intValue;
-    
-    if (!CFNumberGetValue(numberValue, kCFNumberLongType, &intValue))
-    {
-        return -1;
-    }
-    
-    return intValue;
-}
-
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h
deleted file mode 100644 (file)
index 5571efb..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * $Id$
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-/**
- * @file       GHOST_DisplayManagerCarbon.h
- * Declaration of GHOST_DisplayManagerCarbon class.
- */
-
-#ifndef _GHOST_DISPLAY_MANAGER_CARBON_H_
-#define _GHOST_DISPLAY_MANAGER_CARBON_H_
-
-#ifndef __APPLE__
-#error Apple only!
-#endif // __APPLE__
-
-#include "GHOST_DisplayManager.h"
-
-#define __CARBONSOUND__
-#include <Carbon/Carbon.h>
-
-/**
- * Manages system displays  (Mac OSX/Carbon implementation).
- * @see GHOST_DisplayManager
- * @author     Maarten Gribnau
- * @date       September 21, 2001
- */
-class GHOST_DisplayManagerCarbon : public GHOST_DisplayManager
-{
-public:
-       /**
-        * Constructor.
-        */
-       GHOST_DisplayManagerCarbon(void);
-
-       /**
-        * Returns the number of display devices on this system.
-        * @param numDisplays The number of displays on this system.
-        * @return Indication of success.
-        */
-       virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
-
-       /**
-        * Returns the number of display settings for this display device.
-        * @param display The index of the display to query with 0 <= display < getNumDisplays().
-        * @param setting The number of settings of the display device with this index.
-        * @return Indication of success.
-        */
-       virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
-
-       /**
-        * Returns the current setting for this display device. 
-        * @param display The index of the display to query with 0 <= display < getNumDisplays().
-        * @param index   The setting index to be returned.
-        * @param setting The setting of the display device with this index.
-        * @return Indication of success.
-        */
-       virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
-
-       /**
-        * Returns the current setting for this display device. 
-        * @param display The index of the display to query with 0 <= display < getNumDisplays().
-        * @param setting The current setting of the display device with this index.
-        * @return Indication of success.
-        */
-       virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
-
-       /**
-        * Changes the current setting for this display device. 
-        * @param display The index of the display to query with 0 <= display < getNumDisplays().
-        * @param setting The current setting of the display device with this index.
-        * @return Indication of success.
-        */
-       virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
-
-protected:
-       /**
-        * Returns a value from a dictionary.
-        * @param       values  Dictionary to return value from.
-        * @param       key     Key to return value for.
-        * @return The value for this key.
-        */
-       long getValue(CFDictionaryRef values, CFStringRef key) const;
-       
-       /** Cached number of displays. */
-       CGDisplayCount m_numDisplays;
-       /** Cached display id's for each display. */
-       CGDirectDisplayID* m_displayIDs;
-};
-
-
-#endif // _GHOST_DISPLAY_MANAGER_CARBON_H_
-
index 29d15d3e4deea873a3b262d4099b68b8b7f465ec..916ddf812175630899778fa80695a6cb327b296a 100644 (file)
 #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>
+
 #define COMPILE_MULTIMON_STUBS
 #ifndef FREE_WINDOWS
 #include <multimon.h>
index 6470b40649250cbb4c1d5cce7d487d5467105cdb..432a4f93b4d8d0b0b979695ff73c4df97de645f5 100644 (file)
@@ -377,7 +377,9 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out)
        out = (char*)::malloc(size);
        if (!out)
        {
+#ifdef GHOST_DEBUG
                ::printf("\nmalloc failed!!!");
+#endif
                return 0;
        }
 
index 6fbf33ce9f8bcaa0bdaa53756283cfd8e457d29b..039c8e8a313613e873a01454d361e35e15d61d52 100644 (file)
 #ifndef _GHOST_DROP_TARGET_WIN32_H_
 #define _GHOST_DROP_TARGET_WIN32_H_
 
+#define _WIN32_WINNT 0x501 // require Windows XP or newer
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
+#include <shellapi.h>
+
 #include <string.h>
 #include <GHOST_Types.h>
 #include "GHOST_WindowWin32.h"
@@ -41,7 +45,7 @@ public:
         * Enables clients to get pointers to other interfaces on a given object 
         * through the QueryInterface method, and manage the existence of the object
         * through the AddRef and Release methods. All other COM interfaces are 
-        * inherited, directly or indirectly, from IUnknown. Therefore, the three 
+        * inherited, directly or indirectly, from IUnknown. Therefore, the three
         * methods in IUnknown are the first entries in the VTable for every interface. 
         */
        HRESULT __stdcall QueryInterface (REFIID riid, void ** ppvObj);
index d8631ea47e4b0513def923fa6fd0e83fea07776c..b33095a8efecc8a29e707aa56d864ec957dd0e6d 100644 (file)
@@ -55,6 +55,7 @@ public:
                : GHOST_Event(time, type, window)
        {
                m_buttonEventData.button = button;
+               m_buttonEventData.tablet.Active = GHOST_kTabletModeNone;
                m_data = &m_buttonEventData;
        }
 
@@ -64,4 +65,3 @@ protected:
 };
 
 #endif // _GHOST_EVENT_BUTTON_H_
-
index 5390e3b22538679f0864037e403b6f223d8dc336..e324cf6e9fa7e87ca8089206b5a084884e0911a6 100644 (file)
@@ -55,6 +55,7 @@ public:
        {
                m_cursorEventData.x = x;
                m_cursorEventData.y = y;
+               m_cursorEventData.tablet.Active = GHOST_kTabletModeNone;
                m_data = &m_cursorEventData;
        }
 
index 0eeb2245cd0fdbbcbae7b66f672a446f38840ede..b566c1e38c8d3589b41915f6a1bea0a362661644 100644 (file)
 #include <algorithm>
 #include "GHOST_Debug.h"
 
+// for testing lo-fi
+#include "GHOST_EventPrinter.h"
+#include <iostream>
+using namespace std;
 
 GHOST_EventManager::GHOST_EventManager()
 {
@@ -81,7 +85,7 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
 GHOST_IEvent* GHOST_EventManager::peekEvent()
 {
        GHOST_IEvent* event = 0;
-       if (m_events.size() > 0) {
+       if (!m_events.empty()) {
                event = m_events.back();
        }
        return event;
@@ -104,6 +108,24 @@ GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event)
 
 
 bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event)
+{
+       // [mce] this variant switches the "handled" flag to work as described in the header
+       //       it also stops after the first consumer has handled the event (no it doesn't)
+       bool handled = false;
+       if (event) {
+               TConsumerVector::iterator iter;
+               for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) {
+                       if ((*iter)->processEvent(event)) {
+                               handled = true;
+                               // break;
+                       }
+               }
+       }
+       return handled;
+}
+
+#if 0 // disable to test a variant
+bool GHOST_EventManager::dispatchEvent_original(GHOST_IEvent* event)
 {
        bool handled;
        if (event) {
@@ -120,7 +142,7 @@ bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event)
        }
        return handled;
 }
-
+#endif
 
 bool GHOST_EventManager::dispatchEvent()
 {
@@ -152,6 +174,51 @@ bool GHOST_EventManager::dispatchEvents()
 }
 
 
+bool GHOST_EventManager::dispatchEvents_lo_fi()
+{
+       if (m_events.empty())
+               return false;
+
+       bool allHandled = true;
+       GHOST_IEvent* cursorMove = NULL;
+       GHOST_IEvent* event = NULL;
+
+//     GHOST_EventPrinter printer;
+
+       // when Pen gets its own event type, track it alongside mouse moves
+       // they probably won't both be active, but you never know
+
+//     cout << "\n--- lo-fi dispatch ---";
+//     cout << "\ndiscard:";
+       while ((event = popEvent()) != NULL) {
+               if (event->getType() == GHOST_kEventCursorMove) {
+                       // just a simple (x,y) pair, nothing much to adjust
+                       // discard the older event and keep the latest
+                       if (cursorMove) {
+//                             printer.processEvent(cursorMove);
+                               delete cursorMove;
+                       }
+                       cursorMove = event;
+               }
+               else // not a cursor move event
+                       if (!dispatchEvent(event))
+                               allHandled = false;
+       }
+               
+       // finally dispatch the single cursor update
+       if (cursorMove) {
+//             cout << "\nsend:";
+//             printer.processEvent(cursorMove);
+               if (!dispatchEvent(cursorMove))
+                       allHandled = false;
+       }
+
+//     cout << endl;
+
+       return allHandled;
+}
+
+
 GHOST_TSuccess GHOST_EventManager::addConsumer(GHOST_IEventConsumer* consumer)
 {
        GHOST_TSuccess success;
@@ -255,7 +322,7 @@ GHOST_IEvent* GHOST_EventManager::popEvent()
 
 void GHOST_EventManager::disposeEvents()
 {
-       while (m_events.size() > 0) {
+       while (!m_events.empty()) {
                GHOST_ASSERT(m_events[0], "invalid event");
                delete m_events[0];
                m_events.pop_front();
index 40ba133e8fdf3ce009809388150f77d3c5ab9db8..5071adb1bd49406bc3ab0525057932a73bacf53f 100644 (file)
@@ -108,6 +108,14 @@ public:
         */
        virtual bool dispatchEvents();
 
+       /**
+        * Dispatches most events on the stack, consolidating cursor moves into a single move.
+        * The event stack will be empty afterwards.
+        * @return Indicates whether all events were handled by some consumer.
+        */
+       bool dispatchEvents_lo_fi();
+
+
        /**
         * Adds a consumer to the list of event consumers.
         * @param consumer The consumer added to the list.
index 916fd7bbc089bf3d573fbc81b0ff2be6ccc9092a..394aff0493fc4edc17deeb5abc0d7ee7609df284 100644 (file)
 
 #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)
+
+class GHOST_EventNDOFMotion : public GHOST_Event
        {
-               m_ndofEventData = data;
-               m_data = &m_ndofEventData;
-       }
+       protected:
+               GHOST_TEventNDOFMotionData m_axisData;
+       
+       public:
+               GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow* window)
+                       : GHOST_Event(time, GHOST_kEventNDOFMotion, window)
+                       {
+                       m_data = &m_axisData;
+                       }
+       };
 
-protected:
-       /** translation & rotation from the device. */
-       GHOST_TEventNDOFData m_ndofEventData;
-};
 
+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_
 
+#endif // _GHOST_EVENT_NDOF_H_
index 5e5f04d5bc92ee11c898b41bb7005394e12bb550..1c00e991520bcc22d3c268d5f727d0c173bb0f02 100644 (file)
  * 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, July 2010.
  *
  * ***** END GPL LICENSE BLOCK *****
  */
 
-#include <stdio.h> /* just for printf */
-
 #include "GHOST_NDOFManager.h"
+#include "GHOST_EventNDOF.h"
+#include "GHOST_WindowManager.h"
+#include <string.h> // for memory functions
+#include <stdio.h> // for debug tracing
+
+GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys)
+       : m_system(sys)
+       , m_buttons(0)
+       , m_motionTime(1000) // one full second (operators should filter out such large time deltas)
+       , m_prevMotionTime(0)
+       , m_atRest(true)
+       {
+       // 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));
+       }
+
+void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time)
+       {
+       memcpy(m_translation, t, sizeof(m_translation));
+       m_motionTime = time;
+       m_atRest = false;
+       }
+
+void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time)
+       {
+       memcpy(m_rotation, r, sizeof(m_rotation));
+       m_motionTime = time;
+       m_atRest = false;
+       }
+
+void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time)
+       {
+       GHOST_System* system = (GHOST_System*) GHOST_System::getSystem();
+       GHOST_IWindow* window = system->getWindowManager()->getActiveWindow();
+
+       unsigned short diff = m_buttons ^ buttons;
+
+       for (int i = 0; i < 16; ++i)
+               {
+               unsigned short mask = 1 << i;
+
+               if (diff & mask)
+                       {
+                       GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window);
+                       GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData();
+                       
+                       data->action = (buttons & mask) ? GHOST_kPress : GHOST_kRelease;
+//                     data->pressed = buttons & mask;
+                       data->button = i + 1;
 
+//                     printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released");
 
-// 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};
-
-#if !defined(_WIN32) && !defined(__APPLE__)
-#include "GHOST_SystemX11.h"
-#endif
-
-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(_WIN32) || defined(__APPLE__)
-                       m_DeviceHandle = ndofDeviceOpen((void *)&currentNdofValues);    
-               #else
-                       GHOST_SystemX11 *sys;
-                       sys = static_cast<GHOST_SystemX11*>(GHOST_ISystem::getSystem());
-                       void *ndofInfo = sys->prepareNdofInfo(&currentNdofValues);
-                       m_DeviceHandle = ndofDeviceOpen(ndofInfo);
-               #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;
-}
+                       m_system.pushEvent(event);
+                       }
+               }
+
+       m_buttons = buttons;
+       }
+
+bool GHOST_NDOFManager::sendMotionEvent()
+       {
+       if (m_atRest)
+               return false;
+
+       GHOST_System* system = (GHOST_System*) GHOST_System::getSystem();
+       GHOST_IWindow* window = system->getWindowManager()->getActiveWindow();
+
+       GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window);
+       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
+
+       printf("dt = %d ms\n", (int)(m_motionTime - m_prevMotionTime));
+
+       m_prevMotionTime = m_motionTime;
+
+//     printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f)\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz);
+
+       m_system.pushEvent(event);
+
+       // '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 4805707b37bd3b69314a64529042aedbd6410343..9d0bfa3b78977ff2182104643ac8ac92d3080d7c 100644 (file)
 #define _GHOST_NDOFMANAGER_H_
 
 #include "GHOST_System.h"
-#include "GHOST_IWindow.h"
-
 
 
 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;
+
+       // the latest raw data from the device
+       void updateTranslation(short t[3], GHOST_TUns64 time);
+       void updateRotation(short r[3], GHOST_TUns64 time);
+       // this one sends events immediately for changed buttons
+       void updateButtons(unsigned short b, GHOST_TUns64 time);
+
+       // processes most recent raw data into an NDOFMotion event and sends it
+       // returns whether an event was sent
+       bool sendMotionEvent();
 
 protected:
-    void* m_DeviceHandle;
+       GHOST_System& m_system;
+
+       short m_translation[3];
+       short m_rotation[3];
+       unsigned short m_buttons;
+
+       GHOST_TUns64 m_motionTime;
+       GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent
+       bool m_atRest;
+
+       void updateMotionTime(GHOST_TUns64 t);
+       void resetMotion();
 };
 
 
diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h
new file mode 100644 (file)
index 0000000..4f2a227
--- /dev/null
@@ -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): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef _GHOST_NDOFMANAGERCOCOA_H_
+#define _GHOST_NDOFMANAGERCOCOA_H_
+
+#include "GHOST_NDOFManager.h"
+
+// Event capture is handled within the NDOFManager 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 (file)
index 0000000..b29cbb6
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * ***** 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): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "GHOST_NDOFManagerCocoa.h"
+#include "GHOST_SystemCocoa.h"
+
+extern "C" {
+       #include <3DconnexionClient/ConnexionClientAPI.h>
+       #include <stdio.h>
+       }
+
+static void SpaceNavAdded(io_connect_t connection)
+       {
+       printf("SpaceNav added\n");
+       }
+
+static void SpaceNavRemoved(io_connect_t connection)
+       {
+       printf("SpaceNav removed\n");
+       }
+
+static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument)
+       {
+       GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem();
+       GHOST_NDOFManager* manager = system->getNDOFManager();
+       switch (messageType)
+               {
+               case kConnexionMsgDeviceState:
+                       {
+                       ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument;
+
+                       GHOST_TUns64 now = system->getMilliSeconds();
+
+                       switch (s->command)
+                               {
+                               case kConnexionCmdHandleAxis:
+//                                     manager->updateTranslation(s->axis, s->time);
+                                       manager->updateTranslation(s->axis, now);
+                                       manager->updateRotation(s->axis + 3, now);
+                                       system->notifyExternalEventProcessed();
+                                       break;
+
+                               case kConnexionCmdHandleButtons:
+                                       manager->updateButtons(s->buttons, now);
+                                       system->notifyExternalEventProcessed();
+                                       break;
+                               }
+                       break;
+                       }
+               case kConnexionMsgPrefsChanged:
+                       printf("prefs changed\n"); // this includes app switches
+                       break;
+               case kConnexionMsgDoAction:
+                       printf("do action\n"); // no idea what this means
+                       // 'calibrate device' in System Prefs sends this
+                       break;
+               default:
+                       printf("<!> mystery event\n");
+               }
+       }
+
+GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys)
+       : GHOST_NDOFManager(sys)
+       {
+       if (available())
+               {
+               OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved);
+               if (error)
+                       {
+                       printf("<!> error = %d\n", error);
+                       return;
+                       }
+
+               // Pascal string *and* a four-letter constant. How old-skool.
+               m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender",
+                       kConnexionClientModeTakeOver, kConnexionMaskAll);
+
+               printf("client id = %d\n", m_clientID);
+               }
+       else
+               {
+               printf("<!> SpaceNav driver not found\n");
+               // This isn't a hard error, just means the user doesn't have a SpaceNavigator.
+               }
+       }
+
+GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
+       {
+       UnregisterConnexionClient(m_clientID);
+       CleanupConnexionHandlers();
+       }
+
+bool GHOST_NDOFManagerCocoa::available()
+       {
+//     extern OSErr InstallConnexionHandlers() __attribute__((weak_import));
+// ^-- not needed since the entire framework is weak-linked
+       return InstallConnexionHandlers != NULL;
+       }
diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h
new file mode 100644 (file)
index 0000000..a09808d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * ***** 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): none yet.
+ *
+ * ***** 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& 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 available()
+               {
+               // always available since RawInput is built into Windows
+               return true;
+               }
+};
+
+
+#endif
diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h
new file mode 100644 (file)
index 0000000..8f9c819
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * ***** 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): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef _GHOST_NDOFMANAGERX11_H_
+#define _GHOST_NDOFMANAGERX11_H_
+
+#include "GHOST_NDOFManager.h"
+
+
+class GHOST_NDOFManagerX11 : public GHOST_NDOFManager
+{
+public:
+       GHOST_NDOFManagerX11(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 available()
+               {
+               // never available since I've not yet written it!
+               return false;
+               }
+};
+
+
+#endif
index c89534e01c554f7a1163d73b0f9e03a9009a95a3..4e0888a87a7d69b44d2279f7d0597cbe8e511513 100644 (file)
@@ -48,7 +48,7 @@
 
 
 GHOST_System::GHOST_System()
-: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0)
+: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0), m_input_fidelity_hint(NORMAL_FI)
 {
 }
 
@@ -196,9 +196,15 @@ bool GHOST_System::getFullScreen(void)
 
 bool GHOST_System::dispatchEvents()
 {
+       // NDOF Motion event is sent only once per dispatch, so do it now:
+       m_ndofManager->sendMotionEvent();
+
        bool handled;
        if (m_eventManager) {
-               handled = m_eventManager->dispatchEvents();
+               if (m_input_fidelity_hint == LO_FI)
+                       handled = m_eventManager->dispatchEvents_lo_fi();
+               else
+                       handled = m_eventManager->dispatchEvents();
        }
        else {
                handled = false;
@@ -234,17 +240,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
 {
@@ -271,18 +266,19 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown
        return success;
 }
 
+void GHOST_System::setInputFidelity(InputFidelity hint)
+{
+       m_input_fidelity_hint = hint;
+}
+
 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();
+//     m_ndofManager = new GHOST_NDOFManager();
+// Each platform now has their own NDOFManager subclass
 
-#if 0
-       if(m_ndofManager)
-               printf("ndof manager \n");
-#endif
-       
 #ifdef GHOST_DEBUG
        if (m_eventManager) {
                m_eventPrinter = new GHOST_EventPrinter();
index a18670738fed9b880d7073a2396e5b859f2eb806..0f140a66d721b58ce734c5a8df58985a0d72343c 100644 (file)
@@ -39,6 +39,7 @@
 #include "GHOST_Buttons.h"
 #include "GHOST_ModifierKeys.h"
 #include "GHOST_EventManager.h"
+
 #ifdef GHOST_DEBUG
 #include "GHOST_EventPrinter.h"
 #endif // GHOST_DEBUG
@@ -183,26 +184,6 @@ public:
        virtual GHOST_TSuccess addEventConsumer(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
         ***************************************************************************************/
@@ -281,6 +262,12 @@ public:
         * @return                      Indication of success.
         */
        virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const = 0;
+       
+       /**
+        * Requests input at a certain fidelity. Certain tools want very smooth input, others don't care.
+        * @param hint          Desired fidelity of mouse and pen events.
+        */
+       void setInputFidelity(InputFidelity hint);
 
        /**
         * Returns the selection buffer
@@ -359,6 +346,8 @@ protected:
 
        /** Settings of the display before the display went fullscreen. */
        GHOST_DisplaySetting m_preFullScreenSetting;
+       
+       InputFidelity m_input_fidelity_hint;
 };
 
 inline GHOST_TimerManager* GHOST_System::getTimerManager() const
diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp
deleted file mode 100644 (file)
index ecdc03b..0000000
+++ /dev/null
@@ -1,1252 +0,0 @@
-/**
- * $Id$
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/**
-
- * $Id$
- * Copyright (C) 2001 NaN Technologies B.V.
- * @author     Maarten Gribnau
- * @date       May 7, 2001
- */
-
-#include <Carbon/Carbon.h>
-#include <ApplicationServices/ApplicationServices.h>
-#include "GHOST_SystemCarbon.h"
-
-#include "GHOST_DisplayManagerCarbon.h"
-#include "GHOST_EventKey.h"
-#include "GHOST_EventButton.h"
-#include "GHOST_EventCursor.h"
-#include "GHOST_EventWheel.h"
-#include "GHOST_EventNDOF.h"
-
-#include "GHOST_TimerManager.h"
-#include "GHOST_TimerTask.h"
-#include "GHOST_WindowManager.h"
-#include "GHOST_WindowCarbon.h"
-#include "GHOST_NDOFManager.h"
-#include "AssertMacros.h"
-
-#define GHOST_KEY_SWITCH(mac, ghost) { case (mac): ghostKey = (ghost); break; }
-
-/* blender class and types events */
-enum {
-  kEventClassBlender              = 'blnd'
-};
-
-enum {
-       kEventBlenderNdofAxis                   = 1,
-       kEventBlenderNdofButtons                = 2
-};
-
-const EventTypeSpec    kEvents[] =
-{
-       { kEventClassAppleEvent, kEventAppleEvent },
-/*
-       { kEventClassApplication, kEventAppActivated },
-       { kEventClassApplication, kEventAppDeactivated },
-*/     
-       { kEventClassKeyboard, kEventRawKeyDown },
-       { kEventClassKeyboard, kEventRawKeyRepeat },
-       { kEventClassKeyboard, kEventRawKeyUp },
-       { kEventClassKeyboard, kEventRawKeyModifiersChanged },
-       
-       { kEventClassMouse, kEventMouseDown },
-       { kEventClassMouse, kEventMouseUp },
-       { kEventClassMouse, kEventMouseMoved },
-       { kEventClassMouse, kEventMouseDragged },
-       { kEventClassMouse, kEventMouseWheelMoved },
-       
-       { kEventClassWindow, kEventWindowClickZoomRgn } ,  /* for new zoom behaviour */ 
-       { kEventClassWindow, kEventWindowZoom },  /* for new zoom behaviour */ 
-       { kEventClassWindow, kEventWindowExpand } ,  /* for new zoom behaviour */ 
-       { kEventClassWindow, kEventWindowExpandAll },  /* for new zoom behaviour */ 
-
-       { kEventClassWindow, kEventWindowClose },
-       { kEventClassWindow, kEventWindowActivated },
-       { kEventClassWindow, kEventWindowDeactivated },
-       { kEventClassWindow, kEventWindowUpdate },
-       { kEventClassWindow, kEventWindowBoundsChanged },
-       
-       { kEventClassBlender, kEventBlenderNdofAxis },
-       { kEventClassBlender, kEventBlenderNdofButtons }
-       
-       
-       
-};
-
-
-
-static GHOST_TButtonMask convertButton(EventMouseButton button)
-{
-       switch (button) {
-       case kEventMouseButtonPrimary:
-               return GHOST_kButtonMaskLeft;
-       case kEventMouseButtonSecondary:
-               return GHOST_kButtonMaskRight;
-       case kEventMouseButtonTertiary:
-       default:
-               return GHOST_kButtonMaskMiddle;
-       }
-}
-
-static GHOST_TKey convertKey(int rawCode) 
-{      
-               /* This bit of magic converts the rawCode into a virtual
-                * Mac key based on the current keyboard mapping, but
-                * without regard to the modifiers (so we don't get 'a' 
-                * and 'A' for example.
-                */
-       static UInt32 dummy= 0;
-       Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache);
-       unsigned char vk = KeyTranslate(transData, rawCode, &dummy);    
-               /* Map numpad based on rawcodes first, otherwise they
-                * look like non-numpad events.
-                * Added too: mapping the number keys, for french keyboards etc (ton)
-                */
-       // printf("GHOST: vk: %d %c raw: %d\n", vk, vk, rawCode);
-                
-       switch (rawCode) {
-       case 18:        return GHOST_kKey1;
-       case 19:        return GHOST_kKey2;
-       case 20:        return GHOST_kKey3;
-       case 21:        return GHOST_kKey4;
-       case 23:        return GHOST_kKey5;
-       case 22:        return GHOST_kKey6;
-       case 26:        return GHOST_kKey7;
-       case 28:        return GHOST_kKey8;
-       case 25:        return GHOST_kKey9;
-       case 29:        return GHOST_kKey0;
-       
-       case 82:        return GHOST_kKeyNumpad0;
-       case 83:        return GHOST_kKeyNumpad1;
-       case 84:        return GHOST_kKeyNumpad2;
-       case 85:        return GHOST_kKeyNumpad3;
-       case 86:        return GHOST_kKeyNumpad4;
-       case 87:        return GHOST_kKeyNumpad5;
-       case 88:        return GHOST_kKeyNumpad6;
-       case 89:        return GHOST_kKeyNumpad7;
-       case 91:        return GHOST_kKeyNumpad8;
-       case 92:        return GHOST_kKeyNumpad9;
-       case 65:        return GHOST_kKeyNumpadPeriod;
-       case 76:        return GHOST_kKeyNumpadEnter;
-       case 69:        return GHOST_kKeyNumpadPlus;
-       case 78:        return GHOST_kKeyNumpadMinus;
-       case 67:        return GHOST_kKeyNumpadAsterisk;
-       case 75:        return GHOST_kKeyNumpadSlash;
-       }
-       
-       if ((vk >= 'a') && (vk <= 'z')) {
-               return (GHOST_TKey) (vk - 'a' + GHOST_kKeyA);
-       } else if ((vk >= '0') && (vk <= '9')) {
-               return (GHOST_TKey) (vk - '0' + GHOST_kKey0);
-       } else if (vk==16) {
-               switch (rawCode) {
-               case 122:       return GHOST_kKeyF1;
-               case 120:       return GHOST_kKeyF2;
-               case 99:        return GHOST_kKeyF3;
-               case 118:       return GHOST_kKeyF4;
-               case 96:        return GHOST_kKeyF5;
-               case 97:        return GHOST_kKeyF6;
-               case 98:        return GHOST_kKeyF7;
-               case 100:       return GHOST_kKeyF8;
-               case 101:       return GHOST_kKeyF9;
-               case 109:       return GHOST_kKeyF10;
-               case 103:       return GHOST_kKeyF11;
-               case 111:       return GHOST_kKeyF12;  // Never get, is used for ejecting the CD! 
-               }
-       } else {
-               switch (vk) {
-               case kUpArrowCharCode:          return GHOST_kKeyUpArrow;
-               case kDownArrowCharCode:        return GHOST_kKeyDownArrow;
-               case kLeftArrowCharCode:        return GHOST_kKeyLeftArrow;
-               case kRightArrowCharCode:       return GHOST_kKeyRightArrow;
-
-               case kReturnCharCode:           return GHOST_kKeyEnter;
-               case kBackspaceCharCode:        return GHOST_kKeyBackSpace;
-               case kDeleteCharCode:           return GHOST_kKeyDelete;
-               case kEscapeCharCode:           return GHOST_kKeyEsc;
-               case kTabCharCode:                      return GHOST_kKeyTab;
-               case kSpaceCharCode:            return GHOST_kKeySpace;
-
-               case kHomeCharCode:             return GHOST_kKeyHome;
-               case kEndCharCode:                      return GHOST_kKeyEnd;
-               case kPageUpCharCode:           return GHOST_kKeyUpPage;
-               case kPageDownCharCode:         return GHOST_kKeyDownPage;
-
-               case '-':       return GHOST_kKeyMinus;
-               case '=':       return GHOST_kKeyEqual;
-               case ',':       return GHOST_kKeyComma;
-               case '.':       return GHOST_kKeyPeriod;
-               case '/':       return GHOST_kKeySlash;
-               case ';':       return GHOST_kKeySemicolon;
-               case '\'':      return GHOST_kKeyQuote;
-               case '\\':      return GHOST_kKeyBackslash;
-               case '[':       return GHOST_kKeyLeftBracket;
-               case ']':       return GHOST_kKeyRightBracket;
-               case '`':       return GHOST_kKeyAccentGrave;
-               }
-       }
-       
-       // printf("GHOST: unknown key: %d %d\n", vk, rawCode);
-       
-       return GHOST_kKeyUnknown;
-}
-
-/* MacOSX returns a Roman charset with kEventParamKeyMacCharCodes
- * as defined here: http://developer.apple.com/documentation/mac/Text/Text-516.html
- * I am not sure how international this works...
- * For cross-platform convention, we'll use the Latin ascii set instead.
- * As defined at: http://www.ramsch.org/martin/uni/fmi-hp/iso8859-1.html
- * 
- */
-static unsigned char convertRomanToLatin(unsigned char ascii)
-{
-
-       if(ascii<128) return ascii;
-       
-       switch(ascii) {
-       case 128:       return 142;
-       case 129:       return 143;
-       case 130:       return 128;
-       case 131:       return 201;
-       case 132:       return 209;
-       case 133:       return 214;
-       case 134:       return 220;
-       case 135:       return 225;
-       case 136:       return 224;
-       case 137:       return 226;
-       case 138:       return 228;
-       case 139:       return 227;
-       case 140:       return 229;
-       case 141:       return 231;
-       case 142:       return 233;
-       case 143:       return 232;
-       case 144:       return 234;
-       case 145:       return 235;
-       case 146:       return 237;
-       case 147:       return 236;
-       case 148:       return 238;
-       case 149:       return 239;
-       case 150:       return 241;
-       case 151:       return 243;
-       case 152:       return 242;
-       case 153:       return 244;
-       case 154:       return 246;
-       case 155:       return 245;
-       case 156:       return 250;
-       case 157:       return 249;
-       case 158:       return 251;
-       case 159:       return 252;
-       case 160:       return 0;
-       case 161:       return 176;
-       case 162:       return 162;
-       case 163:       return 163;
-       case 164:       return 167;
-       case 165:       return 183;
-       case 166:       return 182;
-       case 167:       return 223;
-       case 168:       return 174;
-       case 169:       return 169;
-       case 170:       return 174;
-       case 171:       return 180;
-       case 172:       return 168;
-       case 173:       return 0;
-       case 174:       return 198;
-       case 175:       return 216;
-       case 176:       return 0;
-       case 177:       return 177;
-       case 178:       return 0;
-       case 179:       return 0;
-       case 180:       return 165;
-       case 181:       return 181;
-       case 182:       return 0;
-       case 183:       return 0;
-       case 184:       return 215;
-       case 185:       return 0;
-       case 186:       return 0;
-       case 187:       return 170;
-       case 188:       return 186;
-       case 189:       return 0;
-       case 190:       return 230;
-       case 191:       return 248;
-       case 192:       return 191;
-       case 193:       return 161;
-       case 194:       return 172;
-       case 195:       return 0;
-       case 196:       return 0;
-       case 197:       return 0;
-       case 198:       return 0;
-       case 199:       return 171;
-       case 200:       return 187;
-       case 201:       return 201;
-       case 202:       return 0;
-       case 203:       return 192;
-       case 204:       return 195;
-       case 205:       return 213;
-       case 206:       return 0;
-       case 207:       return 0;
-       case 208:       return 0;
-       case 209:       return 0;
-       case 210:       return 0;
-       
-       case 214:       return 247;
-
-       case 229:       return 194;
-       case 230:       return 202;
-       case 231:       return 193;
-       case 232:       return 203;
-       case 233:       return 200;
-       case 234:       return 205;
-       case 235:       return 206;
-       case 236:       return 207;
-       case 237:       return 204;
-       case 238:       return 211;
-       case 239:       return 212;
-       case 240:       return 0;
-       case 241:       return 210;
-       case 242:       return 218;
-       case 243:       return 219;
-       case 244:       return 217;
-       case 245:       return 0;
-       case 246:       return 0;
-       case 247:       return 0;
-       case 248:       return 0;
-       case 249:       return 0;
-       case 250:       return 0;
-
-       
-               default: return 0;
-       }
-
-}
-
-
-/***/
-
-GHOST_SystemCarbon::GHOST_SystemCarbon() :
-       m_modifierMask(0)
-{
-       m_displayManager = new GHOST_DisplayManagerCarbon ();
-       GHOST_ASSERT(m_displayManager, "GHOST_SystemCarbon::GHOST_SystemCarbon(): m_displayManager==0\n");
-       m_displayManager->initialize();
-
-       UnsignedWide micros;
-       ::Microseconds(&micros);
-       m_start_time = UnsignedWideToUInt64(micros)/1000;
-       m_ignoreWindowSizedMessages = false;
-}
-
-GHOST_SystemCarbon::~GHOST_SystemCarbon()
-{
-}
-
-
-GHOST_TUns64 GHOST_SystemCarbon::getMilliSeconds() const
-{
-       UnsignedWide micros;
-       ::Microseconds(&micros);
-       UInt64 millis;
-       millis = UnsignedWideToUInt64(micros);
-       return (millis / 1000) - m_start_time;
-}
-
-
-GHOST_TUns8 GHOST_SystemCarbon::getNumDisplays() const
-{
-       // We do not support multiple monitors at the moment
-       return 1;
-}
-
-
-void GHOST_SystemCarbon::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
-{
-       BitMap screenBits;
-    Rect bnds = GetQDGlobalsScreenBits(&screenBits)->bounds;
-       width = bnds.right - bnds.left;
-       height = bnds.bottom - bnds.top;
-}
-
-
-GHOST_IWindow* GHOST_SystemCarbon::createWindow(
-       const STR_String& title, 
-       GHOST_TInt32 left,
-       GHOST_TInt32 top,
-       GHOST_TUns32 width,
-       GHOST_TUns32 height,
-       GHOST_TWindowState state,
-       GHOST_TDrawingContextType type,
-       bool stereoVisual,
-       const GHOST_TUns16 numOfAASamples,
-       const GHOST_TEmbedderWindowID parentWindow
-)
-{
-    GHOST_IWindow* window = 0;
-
-       window = new GHOST_WindowCarbon (title, left, top, width, height, state, type);
-
-    if (window) {
-        if (window->getValid()) {
-            // Store the pointer to the window 
-            GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
-            m_windowManager->addWindow(window);
-            m_windowManager->setActiveWindow(window);
-            pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
-        }
-        else {
-                       GHOST_PRINT("GHOST_SystemCarbon::createWindow(): window invalid\n");
-            delete window;
-            window = 0;
-        }
-    }
-       else {
-               GHOST_PRINT("GHOST_SystemCarbon::createWindow(): could not create window\n");
-       }
-    return window;
-}
-
-GHOST_TSuccess GHOST_SystemCarbon::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)
-{      
-       GHOST_TSuccess success = GHOST_kFailure;
-
-       // need yo make this Carbon all on 10.5 for fullscreen to work correctly
-       CGCaptureAllDisplays();
-       
-       success = GHOST_System::beginFullScreen( setting, window, stereoVisual);
-       
-       if( success != GHOST_kSuccess ) {
-                       // fullscreen failed for other reasons, release
-                       CGReleaseAllDisplays(); 
-       }
-
-       return success;
-}
-
-GHOST_TSuccess GHOST_SystemCarbon::endFullScreen(void)
-{      
-       CGReleaseAllDisplays();
-       return GHOST_System::endFullScreen();
-}
-
-/* this is an old style low level event queue.
-  As we want to handle our own timers, this is ok.
-  the full screen hack should be removed */
-bool GHOST_SystemCarbon::processEvents(bool waitForEvent)
-{
-       bool anyProcessed = false;
-       EventRef event;
-       
-//     SetMouseCoalescingEnabled(false, NULL);
-
-       do {
-               GHOST_TimerManager* timerMgr = getTimerManager();
-               
-               if (waitForEvent) {
-                       GHOST_TUns64 next = timerMgr->nextFireTime();
-                       double timeOut;
-                       
-                       if (next == GHOST_kFireTimeNever) {
-                               timeOut = kEventDurationForever;
-                       } else {
-                               timeOut = (double)(next - getMilliSeconds())/1000.0;
-                               if (timeOut < 0.0)
-                                       timeOut = 0.0;
-                       }
-                       
-                       ::ReceiveNextEvent(0, NULL, timeOut, false, &event);
-               }
-               
-               if (timerMgr->fireTimers(getMilliSeconds())) {
-                       anyProcessed = true;
-               }
-
-               if (getFullScreen()) {
-                       // Check if the full-screen window is dirty
-                       GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
-                       if (((GHOST_WindowCarbon*)window)->getFullScreenDirty()) {
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
-                               anyProcessed = true;
-                       }
-               }
-
-               /* end loop when no more events available */
-               while (::ReceiveNextEvent(0, NULL, 0, true, &event)==noErr) {
-                       OSStatus status= ::SendEventToEventTarget(event, ::GetEventDispatcherTarget());
-                       if (status==noErr) {
-                               anyProcessed = true;
-                       } else {
-                               UInt32 i= ::GetEventClass(event);
-                               
-                                       /* Ignore 'cgs ' class, no documentation on what they
-                                        * are, but we get a lot of them
-                                        */
-                               if (i!='cgs ') {
-                                       if (i!='tblt') {  // tablet event. we use the one packaged in the mouse event
-                                               ; //printf("Missed - Class: '%.4s', Kind: %d\n", &i, ::GetEventKind(event));
-                                       }
-                               }
-                       }
-                       ::ReleaseEvent(event);
-               }
-       } while (waitForEvent && !anyProcessed);
-       
-    return anyProcessed;
-}
-       
-
-GHOST_TSuccess GHOST_SystemCarbon::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
-{
-    Point mouseLoc;
-    // Get the position of the mouse in the active port
-    ::GetGlobalMouse(&mouseLoc);
-    // Convert the coordinates to screen coordinates
-    x = (GHOST_TInt32)mouseLoc.h;
-    y = (GHOST_TInt32)mouseLoc.v;
-    return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_SystemCarbon::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
-{
-       float xf=(float)x, yf=(float)y;
-
-       CGAssociateMouseAndMouseCursorPosition(false);
-       CGSetLocalEventsSuppressionInterval(0);
-       CGWarpMouseCursorPosition(CGPointMake(xf, yf));
-       CGAssociateMouseAndMouseCursorPosition(true);
-
-//this doesn't work properly, see game engine mouse-look scripts
-//     CGWarpMouseCursorPosition(CGPointMake(xf, yf));
-       // this call below sends event, but empties other events (like shift)
-       // CGPostMouseEvent(CGPointMake(xf, yf), TRUE, 1, FALSE, 0);
-
-    return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_SystemCarbon::getModifierKeys(GHOST_ModifierKeys& keys) const
-{
-    UInt32 modifiers = ::GetCurrentKeyModifiers();
-
-    keys.set(GHOST_kModifierKeyCommand, (modifiers & cmdKey) ? true : false);
-    keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & optionKey) ? true : false);
-    keys.set(GHOST_kModifierKeyLeftShift, (modifiers & shiftKey) ? true : false);
-    keys.set(GHOST_kModifierKeyLeftControl, (modifiers & controlKey) ? true : false);
-       
-    return GHOST_kSuccess;
-}
-
-       /* XXX, incorrect for multibutton mice */
-GHOST_TSuccess GHOST_SystemCarbon::getButtons(GHOST_Buttons& buttons) const
-{
-    Boolean theOnlyButtonIsDown = ::Button();
-    buttons.clear();
-    buttons.set(GHOST_kButtonMaskLeft, theOnlyButtonIsDown);
-    return GHOST_kSuccess;
-}
-
-#define FIRSTFILEBUFLG 512
-static bool g_hasFirstFile = false;
-static char g_firstFileBuf[512];
-
-extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { 
-       if (g_hasFirstFile) {
-               strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
-               buf[FIRSTFILEBUFLG - 1] = '\0';
-               return 1;
-       } else {
-               return 0; 
-       }
-}
-
-OSErr GHOST_SystemCarbon::sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
-{
-       //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
-       
-       return noErr;
-}
-
-OSErr GHOST_SystemCarbon::sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
-{
-       //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
-       AEDescList docs;
-       SInt32 ndocs;
-       OSErr err;
-
-       err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docs);
-       if (err != noErr)  return err;
-
-       err = AECountItems(&docs, &ndocs);
-       if (err==noErr) {
-               int i;
-       
-               for (i=0; i<ndocs; i++) {
-                       FSSpec fss;
-                       AEKeyword kwd;
-                       DescType actType;
-                       Size actSize;
-               
-                       err = AEGetNthPtr(&docs, i+1, typeFSS, &kwd, &actType, &fss, sizeof(fss), &actSize);
-                       if (err!=noErr)
-                               break;
-               
-                       if (i==0) {
-                               FSRef fsref;
-                               
-                               if (FSpMakeFSRef(&fss, &fsref)!=noErr)
-                                       break;
-                               if (FSRefMakePath(&fsref, (UInt8*) g_firstFileBuf, sizeof(g_firstFileBuf))!=noErr)
-                                       break;
-
-                               g_hasFirstFile = true;
-                       }
-               }
-       }
-       
-       AEDisposeDesc(&docs);
-       
-       return err;
-}
-
-OSErr GHOST_SystemCarbon::sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
-{
-       //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
-       
-       return noErr;
-}
-
-OSErr GHOST_SystemCarbon::sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
-{
-       GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
-       
-       sys->pushEvent( new GHOST_Event(sys->getMilliSeconds(), GHOST_kEventQuit, NULL) );
-       
-       return noErr;
-}
-
-
-GHOST_TSuccess GHOST_SystemCarbon::init()
-{
-    GHOST_TSuccess success = GHOST_System::init();
-    if (success) {
-               /*
-         * Initialize the cursor to the standard arrow shape (so that we can change it later on).
-         * This initializes the cursor's visibility counter to 0.
-         */
-        ::InitCursor();
-
-               MenuRef windMenu;
-               ::CreateStandardWindowMenu(0, &windMenu);
-               ::InsertMenu(windMenu, 0);
-               ::DrawMenuBar();
-
-        ::InstallApplicationEventHandler(sEventHandlerProc, GetEventTypeCount(kEvents), kEvents, this, &m_handler);
-               
-               ::AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, sAEHandlerLaunch, (SInt32) this, false);
-               ::AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, sAEHandlerOpenDocs, (SInt32) this, false);
-               ::AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, sAEHandlerPrintDocs, (SInt32) this, false);
-               ::AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, sAEHandlerQuit, (SInt32) this, false);
-               
-    }
-    return success;
-}
-
-
-GHOST_TSuccess GHOST_SystemCarbon::exit()
-{
-    return GHOST_System::exit();
-}
-
-
-OSStatus GHOST_SystemCarbon::handleWindowEvent(EventRef event)
-{
-       WindowRef windowRef;
-       GHOST_WindowCarbon *window;
-       OSStatus err = eventNotHandledErr;
-       
-       // Check if the event was send to a GHOST window
-       ::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowRef);
-       window = (GHOST_WindowCarbon*) ::GetWRefCon(windowRef);
-       if (!validWindow(window)) {
-               return err;
-       }
-
-       //if (!getFullScreen()) {
-               err = noErr;
-               switch(::GetEventKind(event)) 
-               {
-                       case kEventWindowClose:
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
-                               break;
-                       case kEventWindowActivated:
-                               m_windowManager->setActiveWindow(window);
-                               window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
-                               break;
-                       case kEventWindowDeactivated:
-                               m_windowManager->setWindowInactive(window);
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
-                               break;
-                       case kEventWindowUpdate:
-                               //if (getFullScreen()) GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen update event\n");
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
-                               break;
-                       case kEventWindowBoundsChanged:
-                               if (!m_ignoreWindowSizedMessages)
-                               {
-                                       window->updateDrawingContext();
-                                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
-                               }
-                               break;
-                       default:
-                               err = eventNotHandledErr;
-                               break;
-               }
-//     }
-       //else {
-               //window = (GHOST_WindowCarbon*) m_windowManager->getFullScreenWindow();
-               //GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n");
-               //::RemoveEventFromQueue(::GetMainEventQueue(), event);
-       //}
-       
-       return err;
-}
-
-OSStatus GHOST_SystemCarbon::handleTabletEvent(EventRef event)
-{
-       GHOST_IWindow* window = m_windowManager->getActiveWindow();
-       TabletPointRec tabletPointRecord;
-       TabletProximityRec      tabletProximityRecord;
-       UInt32 anInt32;
-       GHOST_TabletData& ct=((GHOST_WindowCarbon*)window)->GetCarbonTabletData();
-       OSStatus err = eventNotHandledErr;
-       
-       ct.Pressure = 0;
-       ct.Xtilt = 0;
-       ct.Ytilt = 0;
-       
-       // is there an embedded tablet event inside this mouse event? 
-       if(noErr == GetEventParameter(event, kEventParamTabletEventType, typeUInt32, NULL, sizeof(UInt32), NULL, (void *)&anInt32))
-       {
-               // yes there is one!
-               // Embedded tablet events can either be a proximity or pointer event.
-               if(anInt32 == kEventTabletPoint)
-               {
-                       //GHOST_PRINT("Embedded pointer event!\n");
-                       
-                       // Extract the tablet Pointer Event. If there is no Tablet Pointer data
-                       // in this event, then this call will return an error. Just ignore the
-                       // error and go on. This can occur when a proximity event is embedded in
-                       // a mouse event and you did not check the mouse event to see which type
-                       // of tablet event was embedded.
-                       if(noErr == GetEventParameter(event, kEventParamTabletPointRec,
-                                                                                 typeTabletPointRec, NULL,
-                                                                                 sizeof(TabletPointRec),
-                                                                                 NULL, (void *)&tabletPointRecord))
-                       {
-                               ct.Pressure = tabletPointRecord.pressure / 65535.0f;
-                               ct.Xtilt = tabletPointRecord.tiltX / 32767.0f; /* can be positive or negative */
-                               ct.Ytilt = tabletPointRecord.tiltY / 32767.0f; /* can be positive or negative */
-                       }
-               } else {
-                       //GHOST_PRINT("Embedded proximity event\n");
-                       
-                       // Extract the Tablet Proximity record from the event.
-                       if(noErr == GetEventParameter(event, kEventParamTabletProximityRec,
-                                                                                 typeTabletProximityRec, NULL,
-                                                                                 sizeof(TabletProximityRec),
-                                                                                 NULL, (void *)&tabletProximityRecord))
-                       {
-                               if (tabletProximityRecord.enterProximity) {
-                                       //pointer is entering tablet area proximity
-                                       
-                                       switch(tabletProximityRecord.pointerType)
-                                       {
-                                               case 1: /* stylus */
-                                                       ct.Active = GHOST_kTabletModeStylus;
-                                                       break;
-                                               case 2: /* puck, not supported so far */
-                                                       ct.Active = GHOST_kTabletModeNone;
-                                                       break;
-                                               case 3: /* eraser */
-                                                       ct.Active = GHOST_kTabletModeEraser;
-                                                       break;
-                                               default:
-                                                       ct.Active = GHOST_kTabletModeNone;
-                                                       break;
-                                       }
-                               } else {
-                                       // pointer is leaving - return to mouse
-                                       ct.Active = GHOST_kTabletModeNone;
-                               }
-                       }
-               }
-       err = noErr;
-       }
-       return err;
-}
-
-OSStatus GHOST_SystemCarbon::handleMouseEvent(EventRef event)
-{
-    OSStatus err = eventNotHandledErr;
-       GHOST_IWindow* window = m_windowManager->getActiveWindow();
-       UInt32 kind = ::GetEventKind(event);
-                       
-       switch (kind)
-    {
-               case kEventMouseDown:
-               case kEventMouseUp:
-                       // Handle Mac application responsibilities
-                       if ((kind == kEventMouseDown) && handleMouseDown(event)) {
-                               err = noErr;
-                       }
-                       else {
-                               GHOST_TEventType type = (kind == kEventMouseDown) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp;
-                               EventMouseButton button;
-                               
-                               /* Window still gets mouse up after command-H */
-                               if (m_windowManager->getActiveWindow()) {
-                                       // handle any tablet events that may have come with the mouse event (optional)
-                                       handleTabletEvent(event);
-                                       
-                                       ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
-                                       pushEvent(new GHOST_EventButton(getMilliSeconds(), type, window, convertButton(button)));
-                                       err = noErr;
-                               }
-                       }
-            break;
-                       
-               case kEventMouseMoved:
-               case kEventMouseDragged: {
-                       Point mousePos;
-
-                       if (window) {
-                               //handle any tablet events that may have come with the mouse event (optional)
-                               handleTabletEvent(event);
-
-                               ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos);
-                               pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, mousePos.h, mousePos.v));
-                               err = noErr;
-                       }
-                       break;
-               }
-               case kEventMouseWheelMoved:
-                       {
-                               OSStatus status;
-                               //UInt32 modifiers;
-                               EventMouseWheelAxis axis;
-                               SInt32 delta;
-                               //status = ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
-                               //GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed");
-                               status = ::GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis);
-                               GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed");
-                               if (axis == kEventMouseWheelAxisY)
-                               {
-                                       status = ::GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(delta), NULL, &delta);
-                                       GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed");
-                                       /*
-                                        * Limit mouse wheel delta to plus and minus one.
-                                        */
-                                       delta = delta > 0 ? 1 : -1;
-                                       pushEvent(new GHOST_EventWheel(getMilliSeconds(), window, delta));
-                                       err = noErr;
-                               }
-                       }
-                       break;
-               }
-       
-       return err;
-}
-
-
-OSStatus GHOST_SystemCarbon::handleKeyEvent(EventRef event)
-{
-    OSStatus err = eventNotHandledErr;
-       GHOST_IWindow* window = m_windowManager->getActiveWindow();
-       UInt32 kind = ::GetEventKind(event);
-       UInt32 modifiers;
-       UInt32 rawCode;
-       GHOST_TKey key;
-       unsigned char ascii;
-
-       /* Can happen, very rarely - seems to only be when command-H makes
-        * the window go away and we still get an HKey up. 
-        */
-       if (!window) {
-               //::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode);
-               //key = convertKey(rawCode);
-               return err;
-       }
-       
-       err = noErr;
-       switch (kind) {
-               case kEventRawKeyDown: 
-               case kEventRawKeyRepeat: 
-               case kEventRawKeyUp: 
-                       ::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode);
-                       ::GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &ascii);
-       
-                       key = convertKey(rawCode);
-                       ascii= convertRomanToLatin(ascii);
-                       
-       //              if (key!=GHOST_kKeyUnknown) {
-                               GHOST_TEventType type;
-                               if (kind == kEventRawKeyDown) {
-                                       type = GHOST_kEventKeyDown;
-                               } else if (kind == kEventRawKeyRepeat) { 
-                                       type = GHOST_kEventKeyDown;  /* XXX, fixme */
-                               } else {
-                                       type = GHOST_kEventKeyUp;
-                               }
-                               pushEvent( new GHOST_EventKey( getMilliSeconds(), type, window, key, ascii) );
-//                     }
-                       break;
-       
-               case kEventRawKeyModifiersChanged: 
-                               /* ugh */
-                       ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
-                       if ((modifiers & shiftKey) != (m_modifierMask & shiftKey)) {
-                               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & shiftKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
-                       }
-                       if ((modifiers & controlKey) != (m_modifierMask & controlKey)) {
-                               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & controlKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
-                       }
-                       if ((modifiers & optionKey) != (m_modifierMask & optionKey)) {
-                               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & optionKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
-                       }
-                       if ((modifiers & cmdKey) != (m_modifierMask & cmdKey)) {
-                               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & cmdKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
-                       }
-                       
-                       m_modifierMask = modifiers;
-                       break;
-                       
-               default:
-                       err = eventNotHandledErr;
-                       break;
-       }
-       
-       return err;
-}
-
-
-bool GHOST_SystemCarbon::handleMouseDown(EventRef event)
-{
-       WindowPtr                       window;
-       short                           part;
-       BitMap                          screenBits;
-    bool                               handled = true;
-    GHOST_WindowCarbon* ghostWindow;
-    Point                              mousePos = {0 , 0};
-       
-       ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos);
-       
-       part = ::FindWindow(mousePos, &window);
-       ghostWindow = (GHOST_WindowCarbon*) ::GetWRefCon(window);
-       
-       switch (part) {
-               case inMenuBar:
-                       handleMenuCommand(::MenuSelect(mousePos));
-                       break;
-                       
-               case inDrag:
-                       /*
-                        * The DragWindow() routine creates a lot of kEventWindowBoundsChanged
-                        * events. By setting m_ignoreWindowSizedMessages these are suppressed.
-                        * @see GHOST_SystemCarbon::handleWindowEvent(EventRef event)
-                        */
-                       /* even worse: scale window also generates a load of events, and nothing 
-                          is handled (read: client's event proc called) until you release mouse (ton) */
-                       
-                       GHOST_ASSERT(validWindow(ghostWindow), "GHOST_SystemCarbon::handleMouseDown: invalid window");
-                       m_ignoreWindowSizedMessages = true;
-                       ::DragWindow(window, mousePos, &GetQDGlobalsScreenBits(&screenBits)->bounds);
-                       m_ignoreWindowSizedMessages = false;
-                       
-                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, ghostWindow) );
-
-                       break;
-               
-               case inContent:
-                       if (window != ::FrontWindow()) {
-                               ::SelectWindow(window);
-                               /*
-                                * We add a mouse down event on the newly actived window
-                                */             
-                               //GHOST_PRINT("GHOST_SystemCarbon::handleMouseDown(): adding mouse down event, " << ghostWindow << "\n");
-                               EventMouseButton button;
-                               ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
-                               pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonDown, ghostWindow, convertButton(button)));
-                       } else {
-                               handled = false;
-                       }
-                       break;
-                       
-               case inGoAway:
-                       GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
-                       if (::TrackGoAway(window, mousePos))
-                       {
-                               // todo: add option-close, because itÿs in the HIG
-                               // if (event.modifiers & optionKey) {
-                                       // Close the clean documents, others will be confirmed one by one.
-                               //}
-                               // else {
-                               pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, ghostWindow));
-                               //}
-                       }
-                       break;
-                       
-               case inGrow:
-                       GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
-                       ::ResizeWindow(window, mousePos, NULL, NULL);
-                       break;
-                       
-               case inZoomIn:
-               case inZoomOut:
-                       GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
-                       if (::TrackBox(window, mousePos, part)) {
-                               int macState;
-                               
-                               macState = ghostWindow->getMac_windowState();
-                               if ( macState== 0)
-                                       ::ZoomWindow(window, part, true);
-                               else 
-                                       if (macState == 2) { // always ok
-                                                       ::ZoomWindow(window, part, true);
-                                                       ghostWindow->setMac_windowState(1);
-                                       } else { // need to force size again
-                                       //      GHOST_TUns32 scr_x,scr_y; /*unused*/
-                                               Rect outAvailableRect;
-                                               
-                                               ghostWindow->setMac_windowState(2);
-                                               ::GetAvailableWindowPositioningBounds ( GetMainDevice(), &outAvailableRect);
-                                               
-                                               //this->getMainDisplayDimensions(scr_x,scr_y);
-                                               ::SizeWindow (window, outAvailableRect.right-outAvailableRect.left,outAvailableRect.bottom-outAvailableRect.top-1,false);
-                                               ::MoveWindow (window, outAvailableRect.left, outAvailableRect.top,true);
-                                       }
-                               
-                       }
-                       break;
-
-               default:
-                       handled = false;
-                       break;
-       }
-       
-       return handled;
-}
-
-
-bool GHOST_SystemCarbon::handleMenuCommand(GHOST_TInt32 menuResult)
-{
-       short           menuID;
-       short           menuItem;
-       UInt32          command;
-       bool            handled;
-       OSErr           err;
-       
-       menuID = HiWord(menuResult);
-       menuItem = LoWord(menuResult);
-
-       err = ::GetMenuItemCommandID(::GetMenuHandle(menuID), menuItem, &command);
-
-       handled = false;
-       
-       if (err || command == 0) {
-       }
-       else {
-               switch(command) {
-               }
-       }
-
-       ::HiliteMenu(0);
-    return handled;
-}
-
-
-OSStatus GHOST_SystemCarbon::sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData)
-{
-       GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) userData;
-    OSStatus err = eventNotHandledErr;
-       GHOST_IWindow* window;
-       GHOST_TEventNDOFData data;
-       UInt32 kind;
-       
-    switch (::GetEventClass(event))
-    {
-               case kEventClassAppleEvent:
-                       EventRecord eventrec;
-                       if (ConvertEventRefToEventRecord(event, &eventrec)) {
-                               err = AEProcessAppleEvent(&eventrec);
-                       }
-                       break;
-        case kEventClassMouse:
-            err = sys->handleMouseEvent(event);
-            break;
-               case kEventClassWindow:
-                       err = sys->handleWindowEvent(event);
-                       break;
-               case kEventClassKeyboard:
-                       err = sys->handleKeyEvent(event);
-                       break;
-               case kEventClassBlender :
-                       window = sys->m_windowManager->getActiveWindow();
-                       sys->m_ndofManager->GHOST_NDOFGetDatas(data);
-                       kind = ::GetEventKind(event);
-                       
-                       switch (kind)
-                       {
-                               case 1:
-                                       sys->m_eventManager->pushEvent(new GHOST_EventNDOF(sys->getMilliSeconds(), GHOST_kEventNDOFMotion, window, data));
-       //                              printf("motion\n");
-                                       break;
-                               case 2:
-                                       sys->m_eventManager->pushEvent(new GHOST_EventNDOF(sys->getMilliSeconds(), GHOST_kEventNDOFButton, window, data));
-//                                     printf("button\n");
-                                       break;
-                       }
-                       err = noErr;
-                       break;
-               default : 
-                       ;
-                       break;
-   }
-
-    return err;
-}
-
-GHOST_TUns8* GHOST_SystemCarbon::getClipboard(bool selection) const
-{
-       PasteboardRef inPasteboard;
-       PasteboardItemID itemID;
-       CFDataRef flavorData;
-       OSStatus err = noErr;
-       GHOST_TUns8 * temp_buff;
-       CFRange range;
-       OSStatus syncFlags;
-       
-       err = PasteboardCreate(kPasteboardClipboard, &inPasteboard);
-       if(err != noErr) { return NULL;}
-
-       syncFlags = PasteboardSynchronize( inPasteboard );
-               /* as we always get in a new string, we can safely ignore sync flags if not an error*/
-       if(syncFlags <0) { return NULL;}
-
-
-       err = PasteboardGetItemIdentifier( inPasteboard, 1, &itemID );
-       if(err != noErr) { return NULL;}
-
-       err = PasteboardCopyItemFlavorData( inPasteboard, itemID, CFSTR("public.utf8-plain-text"), &flavorData);
-       if(err != noErr) { return NULL;}
-
-       range = CFRangeMake(0, CFDataGetLength(flavorData));
-       
-       temp_buff = (GHOST_TUns8*) malloc(range.length+1); 
-
-       CFDataGetBytes(flavorData, range, (UInt8*)temp_buff);
-       
-       temp_buff[range.length] = '\0';
-       
-       if(temp_buff) {
-               return temp_buff;
-       } else {
-               return NULL;
-       }
-}
-
-void GHOST_SystemCarbon::putClipboard(GHOST_TInt8 *buffer, bool selection) const
-{
-       if(selection) {return;} // for copying the selection, used on X11
-
-       PasteboardRef inPasteboard;
-       CFDataRef textData = NULL;
-       OSStatus err = noErr; /*For error checking*/
-       OSStatus syncFlags;
-       
-       err = PasteboardCreate(kPasteboardClipboard, &inPasteboard);
-       if(err != noErr) { return;}
-       
-       syncFlags = PasteboardSynchronize( inPasteboard ); 
-       /* as we always put in a new string, we can safely ignore sync flags */
-       if(syncFlags <0) { return;}
-       
-       err = PasteboardClear( inPasteboard );
-       if(err != noErr) { return;}
-       
-       textData = CFDataCreate(kCFAllocatorDefault, (UInt8*)buffer, strlen(buffer));
-       
-       if (textData) {
-               err = PasteboardPutItemFlavor( inPasteboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), textData, 0);
-                       if(err != noErr) { 
-                               if(textData) { CFRelease(textData);}
-                               return;
-                       }
-       }
-       
-       if(textData) {
-               CFRelease(textData);
-       }
-}
-
-
-const GHOST_TUns8* GHOST_SystemCarbon::getSystemDir() const
-{
-       return (GHOST_TUns8*)"/Library/Application Support";
-}
-
-const GHOST_TUns8* GHOST_SystemCarbon::getUserDir() const
-{
-       static char usrPath[256] = "";
-       char* env = getenv("HOME");
-       
-       if (env) {
-               strncpy(usrPath, env, 245);
-               usrPath[245]=0;
-               strcat(usrPath, "/Library/Application Support");
-               return (GHOST_TUns8*) usrPath;
-       }
-       else
-               return NULL;
-}
-
-const GHOST_TUns8* GHOST_SystemCarbon::getBinaryDir() const
-{
-       CFURLRef bundleURL;
-       CFStringRef pathStr;
-       static char path[256];
-       CFBundleRef mainBundle = CFBundleGetMainBundle();
-       
-       bundleURL = CFBundleCopyBundleURL(mainBundle);
-       pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
-       CFStringGetCString(pathStr, path, 255, kCFStringEncodingASCII);
-       CFRelease(pathStr);
-       CFRelease(bundleURL);
-       return (GHOST_TUns8*)path;
-}
diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h
deleted file mode 100644 (file)
index 723652d..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/**
- * $Id$
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-/**
- * @file       GHOST_SystemCarbon.h
- * Declaration of GHOST_SystemCarbon class.
- */
-
-#ifndef _GHOST_SYSTEM_CARBON_H_
-#define _GHOST_SYSTEM_CARBON_H_
-
-#ifndef __APPLE__
-#error Apple OSX only!
-#endif // __APPLE__
-
-#define __CARBONSOUND__
-#include <Carbon/Carbon.h>
-
-#include "GHOST_System.h"
-
-class GHOST_EventCursor;
-class GHOST_EventKey;
-class GHOST_EventWindow;
-
-/**
- * OSX/Carbon Implementation of GHOST_System class.
- * @see GHOST_System.
- * @author     Maarten Gribnau
- * @date       May 21, 2001
- */
-class GHOST_SystemCarbon : public GHOST_System {
-public:
-    /**
-     * Constructor.
-     */
-    GHOST_SystemCarbon();
-    
-    /** 
-     * Destructor.
-     */
-    ~GHOST_SystemCarbon();
-    
-       /***************************************************************************************
-        ** Time(r) functionality
-        ***************************************************************************************/
-
-       /**
-        * Returns the system time.
-        * Returns the number of milliseconds since the start of the system process.
-        * Based on ANSI clock() routine.
-        * @return The number of milliseconds.
-        */
-       virtual GHOST_TUns64 getMilliSeconds() const;
-
-       /***************************************************************************************
-        ** Display/window management functionality
-        ***************************************************************************************/
-
-       /**
-        * Returns the number of displays on this system.
-        * @return The number of displays.
-        */
-       virtual GHOST_TUns8 getNumDisplays() const;
-
-       /**
-        * Returns the dimensions of the main display on this system.
-        * @return The dimension of the main display.
-        */
-       virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
-       
-       /**
-        * Create a new window.
-        * The new window is added to the list of windows managed. 
-        * Never explicitly delete the window, use disposeWindow() instead.
-        * @param       title   The name of the window (displayed in the title bar of the window if the OS supports it).
-        * @param       left    The coordinate of the left edge of the window.
-        * @param       top             The coordinate of the top edge of the window.
-        * @param       width   The width the window.
-        * @param       height  The height the window.
-        * @param       state   The state of the window when opened.
-        * @param       type    The type of drawing context installed in this window.
-        * @param       parentWindow    Parent (embedder) window
-        * @return      The new window (or 0 if creation failed).
-        */
-       virtual GHOST_IWindow* createWindow(
-               const STR_String& title,
-               GHOST_TInt32 left,
-               GHOST_TInt32 top,
-               GHOST_TUns32 width,
-               GHOST_TUns32 height,
-               GHOST_TWindowState state,
-               GHOST_TDrawingContextType type,
-               const bool stereoVisual,
-               const GHOST_TUns16 numOfAASamples = 0,
-               const GHOST_TEmbedderWindowID parentWindow = 0 
-       );
-       
-       virtual GHOST_TSuccess beginFullScreen(
-               const GHOST_DisplaySetting& setting, 
-               GHOST_IWindow** window,
-               const bool stereoVisual
-       );
-       
-       virtual GHOST_TSuccess endFullScreen( void );
-       
-       /***************************************************************************************
-        ** Event management functionality
-        ***************************************************************************************/
-
-       /**
-        * Gets events from the system and stores them in the queue.
-        * @param waitForEvent Flag to wait for an event (or return immediately).
-        * @return Indication of the presence of events.
-        */
-       virtual bool processEvents(bool waitForEvent);
-       
-       /***************************************************************************************
-        ** Cursor management functionality
-        ***************************************************************************************/
-
-       /**
-        * Returns the current location of the cursor (location in screen coordinates)
-        * @param x                     The x-coordinate of the cursor.
-        * @param y                     The y-coordinate of the cursor.
-        * @return                      Indication of success.
-        */
-       virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
-
-       /**
-        * Updates the location of the cursor (location in screen coordinates).
-        * @param x                     The x-coordinate of the cursor.
-        * @param y                     The y-coordinate of the cursor.
-        * @return                      Indication of success.
-        */
-       virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
-
-       /***************************************************************************************
-        ** Access to mouse button and keyboard states.
-        ***************************************************************************************/
-
-       /**
-        * Returns the state of all modifier keys.
-        * @param keys  The state of all modifier keys (true == pressed).
-        * @return              Indication of success.
-        */
-       virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
-
-       /**
-        * Returns the state of the mouse buttons (ouside the message queue).
-        * @param buttons       The state of the buttons.
-        * @return                      Indication of success.
-        */
-       virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
-
-       /**
-        * Returns Clipboard data
-        * @param selection             Indicate which buffer to return
-        * @return                              Returns the selected buffer
-        */
-       virtual GHOST_TUns8* getClipboard(bool selection) const;
-       
-       /**
-        * Puts buffer to system clipboard
-        * @param buffer        The buffer to be copied
-        * @param selection     Indicates which buffer to copy too, only used on X11
-        */
-       virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
-
-       
-       /**
-        * Determine the base dir in which shared resources are located. It will first try to use
-        * "unpack and run" path, then look for properly installed path, not including versioning.
-        * @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
-        */
-       virtual const GHOST_TUns8* getSystemDir() const;
-
-       /**
-        * Determine the base dir in which user configuration is stored, not including versioning.
-        * If needed, it will create the base directory.
-        * @return Unsigned char string pointing to user dir (eg ~/.blender/).
-        */
-       virtual const GHOST_TUns8* getUserDir() const;
-
-       /**
-         * Determine the directory of the current binary
-         * @return Unsigned char string pointing to the binary dir
-         */
-        virtual const GHOST_TUns8* getBinaryDir() const;
-
-protected:
-       /**
-        * Initializes the system.
-        * For now, it justs registers the window class (WNDCLASS).
-        * @return A success value.
-        */
-       virtual GHOST_TSuccess init();
-
-       /**
-        * Closes the system down.
-        * @return A success value.
-        */
-       virtual GHOST_TSuccess exit();
-
-       
-    /**
-     * Handles a tablet event.
-     * @param event    A Mac event.
-     * @return Indication whether the event was handled. 
-     */
-    OSStatus handleTabletEvent(EventRef event);
-    /**
-     * Handles a mouse event.
-     * @param event    A Mac event.
-     * @return Indication whether the event was handled. 
-     */
-    OSStatus handleMouseEvent(EventRef event);
-
-    /**
-     * Handles a key event.
-     * @param event    A Mac event.
-     * @return Indication whether the event was handled. 
-     */
-    OSStatus handleKeyEvent(EventRef event);
-
-   /**
-     * Handles a window event.
-     * @param event    A Mac event.
-     * @return Indication whether the event was handled. 
-     */
-    OSStatus handleWindowEvent(EventRef event);
-
-    /**
-     * Handles all basic Mac application stuff for a mouse down event.
-     * @param event    A Mac event.
-     * @return Indication whether the event was handled. 
-     */
-    bool handleMouseDown(EventRef event);
-
-    /**
-     * Handles a Mac menu command.
-     * @param menuResult A Mac menu/item identifier.
-     * @return Indication whether the event was handled. 
-     */
-    bool handleMenuCommand(GHOST_TInt32 menuResult);
-    
-    /* callback for blender generated events */
-//     static OSStatus blendEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData);
-
-
-    /**
-     * Callback for Carbon when it has events.
-     */
-       static OSStatus sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData);
-       
-       /** Apple Event Handlers */
-       static OSErr sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
-       static OSErr sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
-       static OSErr sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
-       static OSErr sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
-
-    /**
-     * Callback for Mac Timer tasks that expire.
-     * @param tmTask Pointer to the timer task that expired.
-     */
-    //static void s_timerCallback(TMTaskPtr tmTask);
-    
-    /** Event handler reference. */
-    EventHandlerRef m_handler;
-       
-       /** Start time at initialization. */
-       GHOST_TUns64 m_start_time;
-       
-    /** State of the modifiers. */
-    UInt32 m_modifierMask;
-
-    /** Ignores window size messages (when window is dragged). */
-    bool m_ignoreWindowSizedMessages;    
-};
-
-#endif // _GHOST_SYSTEM_CARBON_H_
-
index 3ae8ec02ddab4be9bb4e408bbe62aefbd4655831..c84c69707ad9f34e211fe7abcdb9cc5600244018 100644 (file)
 #define _GHOST_SYSTEM_COCOA_H_
 
 #ifndef __APPLE__
-#error Apple OSX only!
-#endif // __APPLE__
-
-//#define __CARBONSOUND__
-
+  #error Apple OSX only!
+#endif
 
 #include "GHOST_System.h"
 
@@ -240,14 +237,18 @@ public:
      * @return Indication whether the event was handled. 
      */
     GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window);
-       
+
        /**
      * Handles the Cocoa event telling the application has become active (again)
      * @return Indication whether the event was handled. 
      */
     GHOST_TSuccess handleApplicationBecomeActiveEvent();
-       
-       
+
+       /**
+     * External objects should call this when they send an event outside processEvents.
+     */
+       void notifyExternalEventProcessed();
+
 protected:
        /**
         * Initializes the system.
@@ -257,13 +258,33 @@ protected:
        virtual GHOST_TSuccess init();
 
     /**
-     * Handles a tablet event.
+     * Handles a tablet pen event.
      * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
-        * @param eventType The type of the event. It needs to be passed separately as it can be either directly in the event type, or as a subtype if combined with a mouse button event
      * @return Indication whether the event was handled. 
      */
-    GHOST_TSuccess handleTabletEvent(void *eventPtr, short eventType);
+    GHOST_TSuccess handleTabletEvent(void *eventPtr);
+
+    /**
+     * Helps handleTabletEvent function.
+     */
+       void fillTabletData(GHOST_TabletData& tablet, void* event_ptr);
     
+       /**
+     * Handles a tablet proximity event. Sets pen or mouse ID for later events.
+     * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
+     * @return Indication whether the event was handled. 
+     */
+    GHOST_TSuccess handleTabletProximity(void *eventPtr);
+
+       /** Tablet Mouse and Pen IDs, used to correlate events with the tool that caused them. */
+       int m_tablet_mouse_id;
+       int m_tablet_pen_id;
+
+       static const int TOOL_ID_NONE = -1;
+
+       /** Which end of the pen is active: tip or eraser? */
+       GHOST_TTabletMode m_tablet_pen_mode;
+
        /**
      * Handles a mouse event.
      * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
@@ -284,12 +305,13 @@ protected:
         * @param y                     The y-coordinate of the cursor.
         * @return                      Indication of success.
         */
-       GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+       GHOST_TSuccess setMouseCursorPosition(float x, float y);
 
        /** 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 */
+       double m_start_time_2;
+
+       /** 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 */
@@ -317,4 +339,3 @@ protected:
 };
 
 #endif // _GHOST_SYSTEM_COCOA_H_
-
index b7038a30e0086bdb83f327b8685063c043f6c10a..b0c7f10f3296458633db1e744276f6ebb37c50ed 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/**
  * $Id$
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -23,6 +23,7 @@
  *
  * Contributor(s):     Maarten Gribnau 05/2001
  *                                     Damien Plisson 09/2009
+ *                                     Mike Erwin 06/2010
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -31,6 +32,7 @@
 
 /*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/
 #include <Carbon/Carbon.h>
+//#include <HIToolbox/Events.h>
 
 #include <sys/time.h>
 #include <sys/types.h>
@@ -52,7 +54,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
@@ -233,8 +235,8 @@ static GHOST_TButtonMask convertButton(int button)
  * @return Ghost key code
  */
 static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) 
-{      
-       
+{
+
        //printf("\nrecvchar %c 0x%x",recvChar,recvChar);
        switch (rawCode) {
                /*Physical keycodes not used due to map changes in int'l keyboards
@@ -264,7 +266,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
                case kVK_ANSI_X:        return GHOST_kKeyX;
                case kVK_ANSI_Y:        return GHOST_kKeyY;
                case kVK_ANSI_Z:        return GHOST_kKeyZ;*/
-               
+
                /* Numbers keys mapped to handle some int'l keyboard (e.g. French)*/
                case kVK_ISO_Section: return    GHOST_kKeyUnknown;
                case kVK_ANSI_1:        return GHOST_kKey1;
@@ -277,7 +279,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
                case kVK_ANSI_8:        return GHOST_kKey8;
                case kVK_ANSI_9:        return GHOST_kKey9;
                case kVK_ANSI_0:        return GHOST_kKey0;
-       
+
                case kVK_ANSI_Keypad0:                  return GHOST_kKeyNumpad0;
                case kVK_ANSI_Keypad1:                  return GHOST_kKeyNumpad1;
                case kVK_ANSI_Keypad2:                  return GHOST_kKeyNumpad2;
@@ -316,24 +318,24 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
                case kVK_F18:                           return GHOST_kKeyF18;
                case kVK_F19:                           return GHOST_kKeyF19;
                case kVK_F20:                           return GHOST_kKeyF20;
-                       
+
                case kVK_UpArrow:                       return GHOST_kKeyUpArrow;
                case kVK_DownArrow:                     return GHOST_kKeyDownArrow;
                case kVK_LeftArrow:                     return GHOST_kKeyLeftArrow;
                case kVK_RightArrow:            return GHOST_kKeyRightArrow;
-                       
+
                case kVK_Return:                        return GHOST_kKeyEnter;
                case kVK_Delete:                        return GHOST_kKeyBackSpace;
                case kVK_ForwardDelete:         return GHOST_kKeyDelete;
                case kVK_Escape:                        return GHOST_kKeyEsc;
                case kVK_Tab:                           return GHOST_kKeyTab;
                case kVK_Space:                         return GHOST_kKeySpace;
-                       
+
                case kVK_Home:                          return GHOST_kKeyHome;
                case kVK_End:                           return GHOST_kKeyEnd;
                case kVK_PageUp:                        return GHOST_kKeyUpPage;
                case kVK_PageDown:                      return GHOST_kKeyDownPage;
-                       
+
                /*case kVK_ANSI_Minus:          return GHOST_kKeyMinus;
                case kVK_ANSI_Equal:            return GHOST_kKeyEqual;
                case kVK_ANSI_Comma:            return GHOST_kKeyComma;
@@ -345,12 +347,12 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
                case kVK_ANSI_LeftBracket:      return GHOST_kKeyLeftBracket;
                case kVK_ANSI_RightBracket:     return GHOST_kKeyRightBracket;
                case kVK_ANSI_Grave:            return GHOST_kKeyAccentGrave;*/
-                       
+
                case kVK_VolumeUp:
                case kVK_VolumeDown:
                case kVK_Mute:
                        return GHOST_kKeyUnknown;
-                       
+
                default:
                        /* alphanumerical or punctuation key that is remappable in int'l keyboards */
                        if ((recvChar >= 'A') && (recvChar <= 'Z')) {
@@ -361,42 +363,38 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
 #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
                                KeyboardLayoutRef keyLayout;
                                UCKeyboardLayout *uchrData;
-                               
+
                                KLGetCurrentKeyboardLayout(&keyLayout);
                                KLGetKeyboardLayoutProperty(keyLayout, kKLuchrData, (const void **)
                                                                                        &uchrData);
                                /*get actual character value of the "remappable" keys in int'l keyboards,
                                 if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
                                 then fallback on using the received charactersIgnoringModifiers */
-                               if (uchrData)
-                               {
+                               if (uchrData) {
                                        UInt32 deadKeyState=0;
                                        UniCharCount actualStrLength=0;
-                                       
+
                                        UCKeyTranslate(uchrData, rawCode, keyAction, 0,
-                                                                  LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
-                                       
-                               }                               
+                                                       LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
+                               }
 #else
                                /* Leopard and Snow Leopard 64bit compatible API*/
                                CFDataRef uchrHandle; /*the keyboard layout*/
                                TISInputSourceRef kbdTISHandle;
-                               
+
                                kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
                                uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
                                CFRelease(kbdTISHandle);
-                               
+
                                /*get actual character value of the "remappable" keys in int'l keyboards,
                                 if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
                                 then fallback on using the received charactersIgnoringModifiers */
-                               if (uchrHandle)
-                               {
+                               if (uchrHandle) {
                                        UInt32 deadKeyState=0;
                                        UniCharCount actualStrLength=0;
-                                       
+
                                        UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
                                                                   LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
-                                       
                                }
 #endif
                                switch (recvChar) {
@@ -474,9 +472,9 @@ int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op)
 {
        int result;
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-       
+
        result = fromcocoa_request_qtcodec_settings(C, op);
-       
+
        [pool drain];
        return result;
 }
@@ -547,12 +545,15 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
        struct timeval boottime;
        size_t len;
        char *rstring = NULL;
-       
+
        m_modifierMask =0;
        m_pressedMouseButtons =0;
        m_isGestureInProgress = false;
        m_cursorDelta_x=0;
        m_cursorDelta_y=0;
+       m_tablet_mouse_id = TOOL_ID_NONE;
+       m_tablet_pen_id = TOOL_ID_NONE;
+       m_tablet_pen_mode = GHOST_kTabletModeNone;
        m_outsideLoopEventProcessed = false;
        m_needDelayedApplicationBecomeActiveEventProcessing = false;
        m_displayManager = new GHOST_DisplayManagerCocoa ();
@@ -563,27 +564,30 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
        mib[0] = CTL_KERN;
        mib[1] = KERN_BOOTTIME;
        len = sizeof(struct timeval);
-       
+
        sysctl(mib, 2, &boottime, &len, NULL, 0);
        m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
-       
+
+       m_start_time_2 = CFAbsoluteTimeGetCurrent();
+
        //Detect multitouch trackpad
        mib[0] = CTL_HW;
        mib[1] = HW_MODEL;
        sysctl( mib, 2, NULL, &len, NULL, 0 );
        rstring = (char*)malloc( len );
        sysctl( mib, 2, rstring, &len, NULL, 0 );
-       
+
        //Hack on MacBook revision, as multitouch avail. function missing
-       if (strstr(rstring,"MacBookAir") ||
-               (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')))
-               m_hasMultiTouchTrackpad = true;
-       else m_hasMultiTouchTrackpad = false;
-       
+       m_hasMultiTouchTrackpad =
+               (strstr(rstring,"MacBookAir") ||
+               (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')));
+
        free( rstring );
        rstring = NULL;
-       
+
        m_ignoreWindowSizedMessages = false;
+
+       m_input_fidelity_hint = HI_FI; // just for testing...
 }
 
 GHOST_SystemCocoa::~GHOST_SystemCocoa()
@@ -593,69 +597,63 @@ GHOST_SystemCocoa::~GHOST_SystemCocoa()
 
 GHOST_TSuccess GHOST_SystemCocoa::init()
 {
-       
-    GHOST_TSuccess success = GHOST_System::init();
-    if (success) {
-               //ProcessSerialNumber psn;
-               
-               //Carbon stuff to move window & menu to foreground
-               /*if (!GetCurrentProcess(&psn)) {
-                       TransformProcessType(&psn, kProcessTransformToForegroundApplication);
-                       SetFrontProcess(&psn);
-               }*/
+       GHOST_TSuccess success = GHOST_System::init();
+       if (success) {
+
+               m_ndofManager = new GHOST_NDOFManagerCocoa(*this);
                
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
                if (NSApp == nil) {
                        [NSApplication sharedApplication];
-                       
+
                        if ([NSApp mainMenu] == nil) {
                                NSMenu *mainMenubar = [[NSMenu alloc] init];
                                NSMenuItem *menuItem;
                                NSMenu *windowMenu;
                                NSMenu *appMenu;
-                               
+
                                //Create the application menu
                                appMenu = [[NSMenu alloc] initWithTitle:@"Blender"];
-                               
+
                                [appMenu addItemWithTitle:@"About Blender" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
                                [appMenu addItem:[NSMenuItem separatorItem]];
-                               
+
                                menuItem = [appMenu addItemWithTitle:@"Hide Blender" action:@selector(hide:) keyEquivalent:@"h"];
                                [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
-                                
+
                                menuItem = [appMenu addItemWithTitle:@"Hide others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
                                [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)];
-                               
+
                                [appMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
-                               
+
                                menuItem = [appMenu addItemWithTitle:@"Quit Blender" action:@selector(terminate:) keyEquivalent:@"q"];
                                [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
-                               
+
                                menuItem = [[NSMenuItem alloc] init];
                                [menuItem setSubmenu:appMenu];
-                               
+
                                [mainMenubar addItem:menuItem];
                                [menuItem release];
                                [NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu]; //Needed for 10.5
                                [appMenu release];
-                               
+
                                //Create the window menu
                                windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
-                               
+
                                menuItem = [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
                                [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
-                               
+
                                [windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
-                               
+
                                menuItem = [windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
                                [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
-                               
+
                                menuItem = [[NSMenuItem alloc] init];
                                [menuItem setSubmenu:windowMenu];
-                               
+
                                [mainMenubar addItem:menuItem];
                                [menuItem release];
-                               
+
                                [NSApp setMainMenu:mainMenubar];
                                [NSApp setWindowsMenu:windowMenu];
                                [windowMenu release];
@@ -666,12 +664,12 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
                        [appDelegate setSystemCocoa:this];
                        [NSApp setDelegate:appDelegate];
                }
-               
+
                [NSApp finishLaunching];
-               
+
                [pool drain];
-    }
-    return success;
+       }
+       return success;
 }
 
 
@@ -679,14 +677,18 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
 
 GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const
 {
+/*
        //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime])
        struct timeval currentTime;
-       
+
        gettimeofday(&currentTime, NULL);
-       
+
        //Return timestamp of system uptime
-       
        return ((currentTime.tv_sec*1000)+(currentTime.tv_usec/1000)-m_start_time);
+*/
+
+       double now = CFAbsoluteTimeGetCurrent();
+       return 1000 * (now - m_start_time_2);
 }
 
 
@@ -708,11 +710,11 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        //Get visible frame, that is frame excluding dock and top menu bar
        NSRect frame = [[NSScreen mainScreen] visibleFrame];
-       
+
        //Returns max window contents (excluding title bar...)
        NSRect contentRect = [NSWindow contentRectForFrameRect:frame
                                                                                                 styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
-       
+
        width = contentRect.size.width;
        height = contentRect.size.height;
 
@@ -721,7 +723,7 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns
 
 
 GHOST_IWindow* GHOST_SystemCocoa::createWindow(
-       const STR_String& title, 
+       const STR_String& title,
        GHOST_TInt32 left,
        GHOST_TInt32 top,
        GHOST_TUns32 width,
@@ -733,59 +735,58 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
        const GHOST_TEmbedderWindowID parentWindow
 )
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        GHOST_IWindow* window = 0;
-       
+
        //Get the available rect for including window contents
        NSRect frame = [[NSScreen mainScreen] visibleFrame];
        NSRect contentRect = [NSWindow contentRectForFrameRect:frame
                                                                                                 styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
-       
+
        //Ensures window top left is inside this available rect
        left = left > contentRect.origin.x ? left : contentRect.origin.x;
        top = top > contentRect.origin.y ? top : contentRect.origin.y;
-       
+
        window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples);
 
-    if (window) {
-        if (window->getValid()) {
-            // Store the pointer to the window 
-            GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
-            m_windowManager->addWindow(window);
-            m_windowManager->setActiveWindow(window);
+       if (window) {
+               if (window->getValid()) {
+                       // Store the pointer to the window 
+                       GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
+                       m_windowManager->addWindow(window);
+                       m_windowManager->setActiveWindow(window);
                        //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
-            pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
+                       pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
                        pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
-
-        }
-        else {
-                       GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
-            delete window;
-            window = 0;
-        }
-    }
+               }
+               else {
+               GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
+               delete window;
+               window = 0;
+               }
+       }
        else {
                GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");
        }
        [pool drain];
-    return window;
+       return window;
 }
 
 GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)
-{      
+{
        GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
        *window = currentWindow;
-       
+
        if(!currentWindow) return GHOST_kFailure;
-       
+
        return currentWindow->setState(GHOST_kWindowStateFullScreen);
 }
 
 GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void)
-{      
+{
        GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
        if(!currentWindow) return GHOST_kFailure;
-       
+
        return currentWindow->setState(GHOST_kWindowStateNormal);
 }
 
@@ -796,12 +797,13 @@ GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void)
  */
 GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
 {
-    NSPoint mouseLoc = [NSEvent mouseLocation];
-       
-    // Returns the mouse location in screen coordinates
-    x = (GHOST_TInt32)mouseLoc.x;
-    y = (GHOST_TInt32)mouseLoc.y;
-    return GHOST_kSuccess;
+       NSPoint mouseLoc = [NSEvent mouseLocation];
+
+       // Returns the mouse location in screen coordinates
+       x = (GHOST_TInt32)mouseLoc.x;
+       y = (GHOST_TInt32)mouseLoc.y;
+
+       return GHOST_kSuccess;
 }
 
 /**
@@ -823,31 +825,31 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32
        window->screenToClient(x, y, wx, wy);
        pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, wx,wy));
        m_outsideLoopEventProcessed = true;
-       
+
        return GHOST_kSuccess;
 }
 
-GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf)
 {
-       float xf=(float)x, yf=(float)y;
+//     float xf=(float)x, yf=(float)y;
        GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow();
        if (!window) return GHOST_kFailure;
 
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSScreen *windowScreen = window->getScreen();
        NSRect screenRect = [windowScreen frame];
-       
+
        //Set position relative to current screen
        xf -= screenRect.origin.x;
        yf -= screenRect.origin.y;
-       
+
        //Quartz Display Services uses the old coordinates (top left origin)
        yf = screenRect.size.height -yf;
-
+       
        CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf));
 
        [pool drain];
-    return GHOST_kSuccess;
+       return GHOST_kSuccess;
 }
 
 
@@ -857,19 +859,19 @@ GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) cons
        keys.set(GHOST_kModifierKeyLeftAlt, (m_modifierMask & NSAlternateKeyMask) ? true : false);
        keys.set(GHOST_kModifierKeyLeftShift, (m_modifierMask & NSShiftKeyMask) ? true : false);
        keys.set(GHOST_kModifierKeyLeftControl, (m_modifierMask & NSControlKeyMask) ? true : false);
-       
-    return GHOST_kSuccess;
+
+       return GHOST_kSuccess;
 }
 
 GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const
 {
        buttons.clear();
-    buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft);
+       buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft);
        buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight);
        buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle);
        buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4);
        buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5);
-    return GHOST_kSuccess;
+       return GHOST_kSuccess;
 }
 
 
@@ -883,113 +885,130 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
 {
        bool anyProcessed = false;
        NSEvent *event;
-       
-       //      SetMouseCoalescingEnabled(false, NULL);
+       NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
        //TODO : implement timer ??
        
-       /*do {
-               GHOST_TimerManager* timerMgr = getTimerManager();
+       do {
+               event = [NSApp nextEventMatchingMask:NSAnyEventMask
+                                                                       untilDate:[NSDate distantPast]
+                                                                         inMode:NSDefaultRunLoopMode
+                                                                        dequeue:YES];
+               if (event==nil)
+                       break;
                
-                if (waitForEvent) {
-                GHOST_TUns64 next = timerMgr->nextFireTime();
-                double timeOut;
-                
-                if (next == GHOST_kFireTimeNever) {
-                timeOut = kEventDurationForever;
-                } else {
-                timeOut = (double)(next - getMilliSeconds())/1000.0;
-                if (timeOut < 0.0)
-                timeOut = 0.0;
-                }
-                
-                ::ReceiveNextEvent(0, NULL, timeOut, false, &event);
-                }
-                
-                if (timerMgr->fireTimers(getMilliSeconds())) {
-                anyProcessed = true;
-                }*/
+               anyProcessed = true;
                
-               do {
-                       NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-                       event = [NSApp nextEventMatchingMask:NSAnyEventMask
-                                                                          untilDate:[NSDate distantPast]
-                                                                                 inMode:NSDefaultRunLoopMode
-                                                                                dequeue:YES];
-                       if (event==nil) {
-                               [pool drain];
-                               break;
-                       }
-                       
-                       anyProcessed = true;
-                       
-                       switch ([event type]) {
-                               case NSKeyDown:
-                               case NSKeyUp:
-                               case NSFlagsChanged:
-                                       handleKeyEvent(event);
-                                       
-                                       /* Support system-wide keyboard shortcuts, like Expos√©, ...) =>included in always NSApp sendEvent */
-                                       /*              if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) {
-                                        [NSApp sendEvent:event];
-                                        }*/
+               switch ([event type]) {
+                       case NSKeyDown:
+                               if ([event isARepeat])
                                        break;
-                                       
-                               case NSLeftMouseDown:
-                               case NSLeftMouseUp:
-                               case NSRightMouseDown:
-                               case NSRightMouseUp:
-                               case NSMouseMoved:
-                               case NSLeftMouseDragged:
-                               case NSRightMouseDragged:
-                               case NSScrollWheel:
-                               case NSOtherMouseDown:
-                               case NSOtherMouseUp:
-                               case NSOtherMouseDragged:
-                               case NSEventTypeMagnify:
-                               case NSEventTypeRotate:
-                               case NSEventTypeBeginGesture:
-                               case NSEventTypeEndGesture:
-                                       handleMouseEvent(event);
-                                       break;
-                                       
-                               case NSTabletPoint:
-                               case NSTabletProximity:
-                                       handleTabletEvent(event,[event type]);
-                                       break;
-                                       
-                                       /* Trackpad features, fired only from OS X 10.5.2
-                                        case NSEventTypeGesture:
-                                        case NSEventTypeSwipe:
-                                        break; */
-                                       
-                                       /*Unused events
-                                        NSMouseEntered       = 8,
-                                        NSMouseExited        = 9,
-                                        NSAppKitDefined      = 13,
-                                        NSSystemDefined      = 14,
-                                        NSApplicationDefined = 15,
-                                        NSPeriodic           = 16,
-                                        NSCursorUpdate       = 17,*/
-                                       
-                               default:
-                                       break;
-                       }
-                       //Resend event to NSApp to ensure Mac wide events are handled
-                       [NSApp sendEvent:event];
-                       [pool drain];
-               } while (event!= nil);          
-       //} while (waitForEvent && !anyProcessed); Needed only for timer implementation
-       
-       if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent();
-       
+                               // else fall through
+                       case NSKeyUp:
+                       case NSFlagsChanged:
+                               handleKeyEvent(event);
+                               // resend to ensure Mac-wide events are handled
+                               [NSApp sendEvent:event];
+                               break;
+                               
+                       case NSLeftMouseDown:
+                       case NSLeftMouseUp:
+                       case NSLeftMouseDragged:
+                       case NSRightMouseDown:
+                       case NSRightMouseUp:
+                       case NSRightMouseDragged:
+                       case NSOtherMouseDown:
+                       case NSOtherMouseUp:
+                       case NSOtherMouseDragged:
+                       case NSMouseMoved:
+                               switch ([event subtype])
+                                       {
+                                       case NSMouseEventSubtype:
+                                               handleMouseEvent(event);
+                                               break;
+                                       case NSTabletPointEventSubtype:
+                                               if ([event deviceID] == m_tablet_mouse_id)
+                                                       handleMouseEvent(event);
+                                               else
+                                                       handleTabletEvent(event);
+                                               break;
+                                       case NSTabletProximityEventSubtype:
+                                               // I think only LMB down/up sends this.
+                                               // Always preceded by a real NSTabletProximity event, so it's redundant.
+                                               // handleTabletProximity(event);
+                                               break;
+
+                                       // Mac OS 10.6 introduces a Touch subtype
+                                       // that we ignore for now.
+                                       }
+                               break;
+
+                       case NSScrollWheel:
+                               handleMouseEvent(event);
+                               break;
+                               
+                       case NSTabletProximity:
+                               handleTabletProximity(event);
+                               break;
+
+                       case NSTabletPoint:
+                               if ([event deviceID] == m_tablet_pen_id)
+                                       handleTabletEvent(event);
+                               else {
+                                       // Treat tablet mouse like any other mouse.
+                                       // TODO: teach Windows and Linux the same trick
+
+                                       // It continues to send events even when still, to mimic the pen's
+                                       // ability to vary pressure without moving. Since the mouse is
+                                       // unable to vary its pressure, filter them out as noise!
+
+                                       bool didMove = [event deltaX] != 0 and [event deltaY] != 0;
+                                       if (didMove)
+                                               handleMouseEvent(event);
+                                       // LMB Down gets sent for the initial point (and LMB Up for the final), so this is safe.
+                               }
+                               break;
+                               
+                       case NSEventTypeMagnify:
+                       case NSEventTypeRotate:
+                       case NSEventTypeBeginGesture:
+                       case NSEventTypeEndGesture:
+                               handleMouseEvent(event);
+                               // break out into handleGestureEvent?
+                               break;
+
+                       /* Trackpad features, fired only from OS X 10.5.2
+                                case NSEventTypeGesture:
+                                case NSEventTypeSwipe:
+                                break; */
+
+                       default:
+                               break;
+                       /* Unused events:
+                               NSMouseEntered       = 8,
+                               NSMouseExited        = 9,
+                               NSAppKitDefined      = 13,
+                               NSSystemDefined      = 14,
+                               NSApplicationDefined = 15,
+                               NSPeriodic           = 16,
+                               NSCursorUpdate       = 17,*/
+               }
+       } while (event != nil);         
+
+       [pool drain];
+
+       if (m_needDelayedApplicationBecomeActiveEventProcessing)
+               handleApplicationBecomeActiveEvent();
+
        if (m_outsideLoopEventProcessed) {
                m_outsideLoopEventProcessed = false;
                return true;
        }
-       
-    return anyProcessed;
+
+       return anyProcessed;
 }
 
+
 //Note: called from NSApplication delegate
 GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
 {
@@ -997,7 +1016,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
        //(that is when update events are sent to another application)
        unsigned int modifiers;
        GHOST_IWindow* window = m_windowManager->getActiveWindow();
-       
+
        if (!window) {
                m_needDelayedApplicationBecomeActiveEventProcessing = true;
                return GHOST_kFailure;
@@ -1005,7 +1024,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
        else m_needDelayedApplicationBecomeActiveEventProcessing = false;
 
        modifiers = [[[NSApplication sharedApplication] currentEvent] modifierFlags];
-       
+
        if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
                pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
        }
@@ -1018,50 +1037,54 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
        if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
                pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
        }
-       
+
        m_modifierMask = modifiers;
-       
+
        m_outsideLoopEventProcessed = true;
        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)
 {
        if (!validWindow(window)) {
                return GHOST_kFailure;
        }
-               switch(eventType) 
-               {
-                       case GHOST_kEventWindowClose:
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
-                               break;
-                       case GHOST_kEventWindowActivate:
-                               m_windowManager->setActiveWindow(window);
-                               window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
-                               break;
-                       case GHOST_kEventWindowDeactivate:
-                               m_windowManager->setWindowInactive(window);
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
-                               break;
-                       case GHOST_kEventWindowUpdate:
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
-                               break;
-                       case GHOST_kEventWindowMove:
-                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) );
-                               break;
-                       case GHOST_kEventWindowSize:
-                               if (!m_ignoreWindowSizedMessages)
-                               {
-                                       window->updateDrawingContext();
-                                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
-                               }
-                               break;
-                       default:
-                               return GHOST_kFailure;
-                               break;
-               }
+
+       switch(eventType) {
+               case GHOST_kEventWindowClose:
+                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
+                       break;
+               case GHOST_kEventWindowActivate:
+                       m_windowManager->setActiveWindow(window);
+                       window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
+                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
+                       break;
+               case GHOST_kEventWindowDeactivate:
+                       m_windowManager->setWindowInactive(window);
+                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
+                       break;
+               case GHOST_kEventWindowUpdate:
+                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
+                       break;
+               case GHOST_kEventWindowMove:
+                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) );
+                       break;
+               case GHOST_kEventWindowSize:
+                       if (!m_ignoreWindowSizedMessages) {
+                               window->updateDrawingContext();
+                               pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+                       }
+                       break;
+               default:
+                       return GHOST_kFailure;
+                       break;
+       }
        
        m_outsideLoopEventProcessed = true;
        return GHOST_kSuccess;
@@ -1074,76 +1097,76 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
        if (!validWindow(window)) {
                return GHOST_kFailure;
        }
-       switch(eventType) 
-       {
+
+       switch(eventType) {
                case GHOST_kEventDraggingEntered:
                case GHOST_kEventDraggingUpdated:
                case GHOST_kEventDraggingExited:
                        pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,NULL));
                        break;
-                       
+
                case GHOST_kEventDraggingDropDone:
                {
                        GHOST_TUns8 * temp_buff;
                        GHOST_TStringArray *strArray;
                        NSArray *droppedArray;
-                       size_t pastedTextSize;  
+                       size_t pastedTextSize;
                        NSString *droppedStr;
                        GHOST_TEventDataPtr eventData;
                        int i;
 
                        if (!data) return GHOST_kFailure;
-                       
+
                        switch (draggedObjectType) {
                                case GHOST_kDragnDropTypeFilenames:
                                        droppedArray = (NSArray*)data;
-                                       
+
                                        strArray = (GHOST_TStringArray*)malloc(sizeof(GHOST_TStringArray));
                                        if (!strArray) return GHOST_kFailure;
-                                       
+
                                        strArray->count = [droppedArray count];
                                        if (strArray->count == 0) return GHOST_kFailure;
-                                       
+
                                        strArray->strings = (GHOST_TUns8**) malloc(strArray->count*sizeof(GHOST_TUns8*));
-                                       
+
                                        for (i=0;i<strArray->count;i++)
                                        {
                                                droppedStr = [droppedArray objectAtIndex:i];
-                                               
+
                                                pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-                                               temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); 
-                                       
+                                               temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1);
+
                                                if (!temp_buff) {
                                                        strArray->count = i;
                                                        break;
                                                }
-                                       
+
                                                strncpy((char*)temp_buff, [droppedStr cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize);
                                                temp_buff[pastedTextSize] = '\0';
-                                               
+
                                                strArray->strings[i] = temp_buff;
                                        }
 
-                                       eventData = (GHOST_TEventDataPtr) strArray;     
+                                       eventData = (GHOST_TEventDataPtr) strArray;
                                        break;
-                                       
+
                                case GHOST_kDragnDropTypeString:
                                        droppedStr = (NSString*)data;
                                        pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-                                       
+
                                        temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); 
-                                       
+
                                        if (temp_buff == NULL) {
                                                return GHOST_kFailure;
                                        }
-                                       
+
                                        strncpy((char*)temp_buff, [droppedStr cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize);
-                                       
+
                                        temp_buff[pastedTextSize] = '\0';
-                                       
+
                                        eventData = (GHOST_TEventDataPtr) temp_buff;
                                        break;
-                               
+
                                case GHOST_kDragnDropTypeBitmap:
                                {
                                        NSImage *droppedImg = (NSImage*)data;
@@ -1156,13 +1179,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
                                        NSBitmapImageRep *blBitmapFormatImageRGB,*blBitmapFormatImageRGBA,*bitmapImage=nil;
                                        NSEnumerator *enumerator;
                                        NSImageRep *representation;
-                                       
+
                                        ibuf = IMB_allocImBuf (imgSize.width , imgSize.height, 32, IB_rect, 0);
                                        if (!ibuf) {
                                                [droppedImg release];
                                                return GHOST_kFailure;
                                        }
-                                       
+
                                        /*Get the bitmap of the image*/
                                        enumerator = [[droppedImg representations] objectEnumerator];
                                        while ((representation = [enumerator nextObject])) {
@@ -1172,7 +1195,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
                                                }
                                        }
                                        if (bitmapImage == nil) return GHOST_kFailure;
-                                       
+
                                        if (([bitmapImage bitsPerPixel] == 32) && (([bitmapImage bitmapFormat] & 0x5) == 0)
                                                && ![bitmapImage isPlanar]) {
                                                /* Try a fast copy if the image is a meshed RGBA 32bit bitmap*/
@@ -1187,11 +1210,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
                                        else {
                                                /* Tell cocoa image resolution is same as current system one */
                                                [bitmapImage setSize:imgSize];
-                                               
+
                                                /* Convert the image in a RGBA 32bit format */
-                                               /* As Core Graphics does not support contextes with non premutliplied alpha,
+                                               /* As Core Graphics does not support contexts with non premutliplied alpha,
                                                 we need to get alpha key values in a separate batch */
-                                               
+
                                                /* First get RGB values w/o Alpha to avoid pre-multiplication, 32bit but last byte is unused */
                                                blBitmapFormatImageRGB = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                                                                                                                                                 pixelsWide:imgSize.width 
@@ -1201,12 +1224,12 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
                                                                                                                                                                           bitmapFormat:(NSBitmapFormat)0
                                                                                                                                                                                bytesPerRow:4*imgSize.width
                                                                                                                                                                           bitsPerPixel:32/*RGB format padded to 32bits*/];
-                                               
+
                                                [NSGraphicsContext saveGraphicsState];
                                                [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGB]];
                                                [bitmapImage draw];
                                                [NSGraphicsContext restoreGraphicsState];
-                                               
+
                                                rasterRGB = (GHOST_TUns8*)[blBitmapFormatImageRGB bitmapData];
                                                if (rasterRGB == NULL) {
                                                        [bitmapImage release];
@@ -1214,7 +1237,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
                                                        [droppedImg release];
                                                        return GHOST_kFailure;
                                                }
-                                               
+
                                                /* Then get Alpha values by getting the RGBA image (that is premultiplied btw) */
                                                blBitmapFormatImageRGBA = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                                                                                                                                                  pixelsWide:imgSize.width
@@ -1224,12 +1247,12 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
                                                                                                                                                                                bitmapFormat:(NSBitmapFormat)0
                                                                                                                                                                                 bytesPerRow:4*imgSize.width
                                                                                                                                                                                bitsPerPixel:32/* RGBA */];
-                                               
+
                                                [NSGraphicsContext saveGraphicsState];
                                                [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGBA]];
                                                [bitmapImage draw];
                                                [NSGraphicsContext restoreGraphicsState];
-                                               
+
                                                rasterRGBA = (GHOST_TUns8*)[blBitmapFormatImageRGBA bitmapData];
                                                if (rasterRGBA == NULL) {
                                                        [bitmapImage release];
@@ -1238,37 +1261,37 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
                                                        [droppedImg release];
                                                        return GHOST_kFailure;
                                                }
-                                               
+
                                                /*Copy the image to ibuf, flipping it vertically*/
                                                toIBuf = (GHOST_TUns8*)ibuf->rect;
                                                for (y = 0; y < imgSize.height; y++) {
                                                        for (x = 0; x < imgSize.width; x++) {
                                                                to_i = (imgSize.height-y-1)*imgSize.width + x;
                                                                from_i = y*imgSize.width + x;
-                                                               
+
                                                                toIBuf[4*to_i] = rasterRGB[4*from_i]; /* R */
                                                                toIBuf[4*to_i+1] = rasterRGB[4*from_i+1]; /* G */
                                                                toIBuf[4*to_i+2] = rasterRGB[4*from_i+2]; /* B */
                                                                toIBuf[4*to_i+3] = rasterRGBA[4*from_i+3]; /* A */
                                                        }
                                                }
-                                               
+
                                                [blBitmapFormatImageRGB release];
                                                [blBitmapFormatImageRGBA release];
                                                [droppedImg release];
                                        }
-                                       
+
                                        eventData = (GHOST_TEventDataPtr) ibuf;
-                               }
                                        break;
-                                       
+                               }
+
                                default:
                                        return GHOST_kFailure;
                                        break;
                        }
                        pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,eventData));
-               }
                        break;
+               }
                default:
                        return GHOST_kFailure;
        }
@@ -1280,11 +1303,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
 GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
 {
        GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow();
-       
+
        //Discard quit event if we are in cursor grab sequence
        if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal))
                return GHOST_kExitCancel;
-       
+
        //Check open windows if some changes are not saved
        if (m_windowManager->getAnyModifiedState())
        {
@@ -1313,7 +1336,7 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
                m_outsideLoopEventProcessed = true;
                return GHOST_kExitNow;
        }
-       
+
        return GHOST_kExitCancel;
 }
 
@@ -1325,11 +1348,11 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
        char * temp_buff;
        size_t filenameTextSize;        
        GHOST_Window* window= (GHOST_Window*)m_windowManager->getActiveWindow();
-       
+
        if (!window) {
                return NO;
        }       
-       
+
        //Discard event if we are in cursor grab sequence, it'll lead to "stuck cursor" situation if the alert panel is raised
        if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal))
                return GHOST_kExitCancel;
@@ -1351,15 +1374,15 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
        if (confirmOpen == NSAlertAlternateReturn)
        {
                filenameTextSize = [filepath lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding];
-               
+
                temp_buff = (char*) malloc(filenameTextSize+1); 
-               
+
                if (temp_buff == NULL) {
                        return GHOST_kFailure;
                }
-               
+
                strncpy(temp_buff, [filepath cStringUsingEncoding:NSISOLatin1StringEncoding], filenameTextSize);
-               
+
                temp_buff[filenameTextSize] = '\0';
 
                pushEvent(new GHOST_EventString(getMilliSeconds(),GHOST_kEventOpenMainFile,window,(GHOST_TEventDataPtr) temp_buff));
@@ -1369,246 +1392,323 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
        else return NO;
 }
 
-GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventType)
+GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr)
 {
+       printf("tablet prox: ");
        NSEvent *event = (NSEvent *)eventPtr;
-       GHOST_IWindow* window;
-       
-       window = m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
+       GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)
+               m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
+
        if (!window) {
-               //printf("\nW failure for event 0x%x",[event type]);
+               printf("\nW failure for event 0x%x",[event type]);
                return GHOST_kFailure;
        }
-       
-       GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData();
-       
-       switch (eventType) {
-               case NSTabletPoint:
-                       ct.Pressure = [event pressure];
-                       ct.Xtilt = [event tilt].x;
-                       ct.Ytilt = [event tilt].y;
+
+// don't involve the window!
+//     GHOST_TabletData& ct = window->GetCocoaTabletData();
+
+       GHOST_TTabletMode active_tool;
+       int* tool_id_ptr;
+
+       switch ([event pointingDeviceType])
+               {
+               case NSPenPointingDevice:
+                       printf("pen ");
+                       active_tool = GHOST_kTabletModeStylus;
+                       tool_id_ptr = &m_tablet_pen_id;
                        break;
-               
-               case NSTabletProximity:
-                       ct.Pressure = 0;
-                       ct.Xtilt = 0;
-                       ct.Ytilt = 0;
-                       if ([event isEnteringProximity])
+               case NSEraserPointingDevice:
+                       printf("eraser ");
+                       active_tool = GHOST_kTabletModeEraser;
+                       tool_id_ptr = &m_tablet_pen_id;
+                       break;
+               case NSCursorPointingDevice:
+                       printf("cursor ");
+                       active_tool = GHOST_kTabletModeNone;
+                       tool_id_ptr = &m_tablet_mouse_id;
+                       break;
+               default:
+                       printf("<!> unknown device %d\n", [event pointingDeviceType]);
+                       return GHOST_kFailure; // fail on unknown device
+               }
+
+       if ([event isEnteringProximity]) {
+               printf("entering\n");
+               *tool_id_ptr = [event deviceID];
+
+               m_tablet_pen_mode = active_tool;
+
+//             ct.Active = active_tool;
+//             ct.Pressure = (active_tool == GHOST_kTabletModeNone) ? /*mouse*/ 1 : /*pen*/ 0;
+//             ct.Xtilt = 0;
+//             ct.Ytilt = 0;
+
+               // this is a good place to remember the tool's capabilities
+               }
+       else {
+               printf("leaving\n");
+               *tool_id_ptr = TOOL_ID_NONE;
+
+               m_tablet_pen_mode = GHOST_kTabletModeNone;
+
+//             ct.Active = GHOST_kTabletModeNone;
+//             ct.Pressure = 0;
+//             ct.Xtilt = 0;
+//             ct.Ytilt = 0;
+               }
+
+       return GHOST_kSuccess;
+}
+
+void GHOST_SystemCocoa::fillTabletData(GHOST_TabletData& tablet, void* event_ptr)
+       {
+       NSEvent* event = (NSEvent*)event_ptr;
+       NSPoint tilt = [event tilt];
+
+       tablet.Active = m_tablet_pen_mode;
+       tablet.Pressure = [event pressure];
+       tablet.Xtilt = tilt.x;
+       tablet.Ytilt = tilt.y;
+
+       printf("> pressure = %.2f   tilt = %.2f %2f\n", tablet.Pressure, tablet.Xtilt, tablet.Ytilt);
+       }
+
+GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr)
+{
+       puts("tablet point");
+       NSEvent *event = (NSEvent*)eventPtr;
+       GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)
+               m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
+
+       if (!window) {
+               //printf("\nW failure for event 0x%x",[event type]);
+               return GHOST_kFailure;
+       }
+
+/*
+       // don't involve the window!
+       GHOST_TabletData& ct = window->GetCocoaTabletData();
+
+       ct.Pressure = [event pressure];
+       NSPoint tilt = [event tilt];
+       ct.Xtilt = tilt.x;
+       ct.Ytilt = tilt.y;
+*/
+
+       switch ([event type])
+               {
+               case NSLeftMouseDown:
                        {
-                               //pointer is entering tablet area proximity
-                               switch ([event pointingDeviceType]) {
-                                       case NSPenPointingDevice:
-                                               ct.Active = GHOST_kTabletModeStylus;
-                                               break;
-                                       case NSEraserPointingDevice:
-                                               ct.Active = GHOST_kTabletModeEraser;
-                                               break;
-                                       case NSCursorPointingDevice:
-                                       case NSUnknownPointingDevice:
-                                       default:
-                                               ct.Active = GHOST_kTabletModeNone;
-                                               break;
+                       if (m_input_fidelity_hint == HI_FI)
+                               {
+                               printf("hi-fi on\n");
+                               [NSEvent setMouseCoalescingEnabled:NO];
                                }
-                       } else {
-                               // pointer is leaving - return to mouse
-                               ct.Active = GHOST_kTabletModeNone;
+                       GHOST_EventButton* e = new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]));
+                       GHOST_TEventButtonData* data = (GHOST_TEventButtonData*) e->getData();
+                       fillTabletData(data->tablet, event);
+                       pushEvent(e);
+                       break;
                        }
+               case NSLeftMouseUp:
+                       {
+                       if (m_input_fidelity_hint == HI_FI)
+                               {
+                               printf("hi-fi off\n");
+                               [NSEvent setMouseCoalescingEnabled:YES];
+                               }
+                       // no tablet data needed for 'pen up'
+                       pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
                        break;
-               
+                       }
                default:
-                       GHOST_ASSERT(FALSE,"GHOST_SystemCocoa::handleTabletEvent : unknown event received");
-                       return GHOST_kFailure;
+                       {
+                       NSPoint pos = [event locationInWindow];
+                       GHOST_EventCursor* e = new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, pos.x, pos.y);
+                       GHOST_TEventCursorData* data = (GHOST_TEventCursorData*) e->getData();
+                       fillTabletData(data->tablet, event);
+                       pushEvent(e);
                        break;
-       }
+                       }
+               }
+
        return GHOST_kSuccess;
 }
 
 
 GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 {
+       printf("mouse ");
        NSEvent *event = (NSEvent *)eventPtr;
-    GHOST_Window* window;
-       
-       window = (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
+       GHOST_Window* window =
+               (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
+
        if (!window) {
-               //printf("\nW failure for event 0x%x",[event type]);
+               printf("\nW failure for event 0x%x",[event type]);
                return GHOST_kFailure;
        }
-       
-       switch ([event type])
-    {
+
+       static float warp_dx = 0, warp_dy = 0; // need to reset these. e.g. each grab operation should get its own.
+               // ^^ not currently useful, try m_cursorDelta_* instead.
+
+       switch ([event type]) {
                case NSLeftMouseDown:
                case NSRightMouseDown:
                case NSOtherMouseDown:
+                       printf("button down\n");
+                       if (m_input_fidelity_hint == HI_FI)
+                               {
+                               printf("hi-fi on\n");
+                               [NSEvent setMouseCoalescingEnabled:NO];
+                               }
                        pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber])));
-                       //Handle tablet events combined with mouse events
-                       switch ([event subtype]) {
-                               case NX_SUBTYPE_TABLET_POINT:
-                                       handleTabletEvent(eventPtr, NSTabletPoint);
-                                       break;
-                               case NX_SUBTYPE_TABLET_PROXIMITY:
-                                       handleTabletEvent(eventPtr, NSTabletProximity);
-                                       break;
-                               default:
-                                       //No tablet event included : do nothing
-                                       break;
-                       }
                        break;
-                                               
+
                case NSLeftMouseUp:
                case NSRightMouseUp:
                case NSOtherMouseUp:
+                       printf("button up\n");
+                       if (m_input_fidelity_hint == HI_FI)
+                               {
+                               printf("hi-fi off\n");
+                               [NSEvent setMouseCoalescingEnabled:YES];
+                               }
                        pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
-                       //Handle tablet events combined with mouse events
-                       switch ([event subtype]) {
-                               case NX_SUBTYPE_TABLET_POINT:
-                                       handleTabletEvent(eventPtr, NSTabletPoint);
-                                       break;
-                               case NX_SUBTYPE_TABLET_PROXIMITY:
-                                       handleTabletEvent(eventPtr, NSTabletProximity);
-                                       break;
-                               default:
-                                       //No tablet event included : do nothing
-                                       break;
-                       }
+                       // cheap hack, should reset when grab ends.
+                       warp_dx = warp_dy = 0;
                        break;
-                       
+
                case NSLeftMouseDragged:
                case NSRightMouseDragged:
-               case NSOtherMouseDragged:                               
-                       //Handle tablet events combined with mouse events
-                       switch ([event subtype]) {
-                               case NX_SUBTYPE_TABLET_POINT:
-                                       handleTabletEvent(eventPtr, NSTabletPoint);
-                                       break;
-                               case NX_SUBTYPE_TABLET_PROXIMITY:
-                                       handleTabletEvent(eventPtr, NSTabletProximity);
-                                       break;
-                               default:
-                                       //No tablet event included : do nothing
-                                       break;
-                       }
-                       
+               case NSOtherMouseDragged:
                case NSMouseMoved:
+                       {
+                       NSPoint mousePos = [event locationInWindow];
+                       float event_dx = [event deltaX];
+                       float event_dy = [event deltaY];
+
+                       bool coalesced = [NSEvent isMouseCoalescingEnabled];
+                       if (not coalesced)
+                               printf("[hi-fi] ");
+                       printf("move <%.2f,%.2f> to (%.2f,%.2f)\n", event_dx, event_dy, mousePos.x, mousePos.y);
+
+                       event_dy = -event_dy; //Strange Apple implementation (inverted coordinates for the deltaY) ...
+
                                switch (window->getCursorGrabMode()) {
                                        case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move
-                                       {
+                                               {
+                                               printf(" - grab hide\n");
                                                GHOST_TInt32 x_warp, y_warp, x_accum, y_accum;
-                                               
+
                                                window->getCursorGrabInitPos(x_warp, y_warp);
-                                               
+
                                                window->getCursorGrabAccum(x_accum, y_accum);
-                                               x_accum += [event deltaX];
-                                               y_accum += -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ...
+                                               x_accum += event_dx;
+                                               y_accum += event_dy;
                                                window->setCursorGrabAccum(x_accum, y_accum);
-                                               
+
                                                pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum));
-                                       }
                                                break;
+                                               }
                                        case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries
-                                       {
+                                               {
                                                NSPoint mousePos = [event locationInWindow];
                                                GHOST_TInt32 x_mouse= mousePos.x;
                                                GHOST_TInt32 y_mouse= mousePos.y;
                                                GHOST_TInt32 x_accum, y_accum, x_cur, y_cur;
                                                GHOST_Rect bounds, windowBounds, correctedBounds;
-                                               
+
                                                /* fallback to window bounds */
                                                if(window->getCursorGrabBounds(bounds)==GHOST_kFailure)
                                                        window->getClientBounds(bounds);
-                                               
+
                                                //Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates
                                                window->getClientBounds(windowBounds);
                                                window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t);
                                                window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b);
                                                correctedBounds.m_b = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_b;
                                                correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t;
-                                               
+
                                                //Update accumulation counts
                                                window->getCursorGrabAccum(x_accum, y_accum);
-                                               x_accum += [event deltaX]-m_cursorDelta_x;
-                                               y_accum += -[event deltaY]-m_cursorDelta_y; //Strange Apple implementation (inverted coordinates for the deltaY) ...
+                                               x_accum += event_dx - m_cursorDelta_x;
+                                               y_accum += event_dy - m_cursorDelta_y;
                                                window->setCursorGrabAccum(x_accum, y_accum);
-                                               
-                                               
+
                                                //Warp mouse cursor if needed
-                                               x_mouse += [event deltaX]-m_cursorDelta_x;
-                                               y_mouse += -[event deltaY]-m_cursorDelta_y;
+                                               x_mouse += event_dx - m_cursorDelta_x;
+                                               y_mouse += event_dy - m_cursorDelta_y;
                                                correctedBounds.wrapPoint(x_mouse, y_mouse, 2);
-                                               
+
                                                //Compensate for mouse moved event taking cursor position set into account
                                                m_cursorDelta_x = x_mouse-mousePos.x;
                                                m_cursorDelta_y = y_mouse-mousePos.y;
-                                               
+
                                                //Set new cursor position
                                                window->clientToScreen(x_mouse, y_mouse, x_cur, y_cur);
                                                setMouseCursorPosition(x_cur, y_cur); /* wrap */
-                                               
+
                                                //Post event
                                                window->getCursorGrabInitPos(x_cur, y_cur);
                                                pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_cur + x_accum, y_cur + y_accum));
-                                       }
+
                                                break;
+                                               }
                                        default:
-                                       {
                                                //Normal cursor operation: send mouse position in window
-                                               NSPoint mousePos = [event locationInWindow];
                                                pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
                                                m_cursorDelta_x=0;
                                                m_cursorDelta_y=0; //Mouse motion occurred between two cursor warps, so we can reset the delta counter
-                                       }
-                                               break;
-                               }
-                               break;
-                       
+                                               warp_dx = 0;
+                                               warp_dy = 0;
+                               } // END cursor grab mode
+                       break;
+                       } // END mouse moved
+
                case NSScrollWheel:
-                       {
-                               /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */
-                               if (!m_hasMultiTouchTrackpad || !m_isGestureInProgress) {
-                                       GHOST_TInt32 delta;
-                                       
-                                       double deltaF = [event deltaY];
-                                       if (deltaF == 0.0) break; //discard trackpad delta=0 events
-                                       
-                                       delta = deltaF > 0.0 ? 1 : -1;
-                                       pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta));
-                               }
-                               else {
-                                       NSPoint mousePos = [event locationInWindow];
-                                       double dx = [event deltaX];
-                                       double dy = -[event deltaY];
-                                       
-                                       const double deltaMax = 50.0;
-                                       
-                                       if ((dx == 0) && (dy == 0)) break;
-                                       
-                                       /* Quadratic acceleration */
-                                       dx = dx*(fabs(dx)+0.5);
-                                       if (dx<0.0) dx-=0.5; else dx+=0.5;
-                                       if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax;
-                                       
-                                       dy = dy*(fabs(dy)+0.5);
-                                       if (dy<0.0) dy-=0.5; else dy+=0.5;
-                                       if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax;
-
-                                       pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy));
-                               }
+                       /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */
+                       if (m_hasMultiTouchTrackpad and m_isGestureInProgress) {
+                               NSPoint mousePos = [event locationInWindow];
+                               double dx = [event deltaX];
+                               double dy = -[event deltaY];
+
+                               const double deltaMax = 50.0;
+
+                               if ((dx == 0) && (dy == 0)) break;
+
+                               /* Quadratic acceleration */
+                               dx = dx*(fabs(dx)+0.5);
+                               if (dx<0.0) dx-=0.5; else dx+=0.5;
+                               if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax;
+
+                               dy = dy*(fabs(dy)+0.5);
+                               if (dy<0.0) dy-=0.5; else dy+=0.5;
+                               if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax;
+
+                               pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy));
+                       }
+                       else {
+                               GHOST_TInt32 delta;
+
+                               double deltaF = [event deltaY];
+                               if (deltaF == 0.0) break; //discard trackpad delta=0 events
+
+                               delta = deltaF > 0.0 ? 1 : -1;
+                               pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta));
                        }
                        break;
-                       
+
                case NSEventTypeMagnify:
                        {
-                               NSPoint mousePos = [event locationInWindow];
-                               pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y,
-                                                                                                 [event magnification]*250.0 + 0.1, 0));
-                       }
+                       NSPoint mousePos = [event locationInWindow];
+                       pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, [event magnification]*250.0 + 0.1, 0));
                        break;
-
+                       }
                case NSEventTypeRotate:
                        {
-                               NSPoint mousePos = [event locationInWindow];
-                               pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y,
-                                                                                                 -[event rotation] * 5.0, 0));
+                       NSPoint mousePos = [event locationInWindow];
+                       pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, -[event rotation] * 5.0, 0));
+                       break;
                        }
                case NSEventTypeBeginGesture:
                        m_isGestureInProgress = true;
@@ -1617,10 +1717,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
                        m_isGestureInProgress = false;
                        break;
                default:
+                       printf("<!> unknown event type %d\n", [event type]);
                        return GHOST_kFailure;
-                       break;
-               }
-       
+       }
+
        return GHOST_kSuccess;
 }
 
@@ -1641,7 +1741,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                //printf("\nW failure for event 0x%x",[event type]);
                return GHOST_kFailure;
        }
-       
+
        switch ([event type]) {
                case NSKeyDown:
                case NSKeyUp:
@@ -1654,7 +1754,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                                keyCode = convertKey([event keyCode],0,
                                                                         [event type] == NSKeyDown?kUCKeyActionDown:kUCKeyActionUp);
 
-                               
+
                        characters = [event characters];
                        if ([characters length]>0) { //Check for dead keys
                                //Convert characters to iso latin 1 encoding
@@ -1666,7 +1766,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                        }
                        else
                                ascii= 0;
-                       
+
                        if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask))
                                break; //Cmd-Q is directly handled by Cocoa
 
@@ -1678,10 +1778,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                                //printf("\nKey up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii);
                        }
                        break;
-       
+
                case NSFlagsChanged: 
                        modifiers = [event modifierFlags];
-                       
+
                        if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
                                pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
                        }
@@ -1694,65 +1794,64 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                        if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
                                pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
                        }
-                       
+
                        m_modifierMask = modifiers;
                        break;
-                       
+
                default:
                        return GHOST_kFailure;
                        break;
        }
-       
+
        return GHOST_kSuccess;
 }
 
 
-
 #pragma mark Clipboard get/set
 
 GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
 {
        GHOST_TUns8 * temp_buff;
        size_t pastedTextSize;  
-       
+
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-       
+
        NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
-       
+
        if (pasteBoard == nil) {
                [pool drain];
                return NULL;
        }
-       
+
        NSArray *supportedTypes =
                [NSArray arrayWithObjects: NSStringPboardType, nil];
-       
+
        NSString *bestType = [[NSPasteboard generalPasteboard]
                                                  availableTypeFromArray:supportedTypes];
-       
+
        if (bestType == nil) {
                [pool drain];
                return NULL;
        }
-       
+
        NSString * textPasted = [pasteBoard stringForType:NSStringPboardType];
 
        if (textPasted == nil) {
                [pool drain];
                return NULL;
        }
-       
+
        pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding];
-       
+
        temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); 
 
        if (temp_buff == NULL) {
                [pool drain];
                return NULL;
        }
-       
+
        strncpy((char*)temp_buff, [textPasted cStringUsingEncoding:NSISOLatin1StringEncoding], pastedTextSize);
-       
+
        temp_buff[pastedTextSize] = '\0';
        
        [pool drain];
@@ -1767,26 +1866,26 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
 void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const
 {
        NSString *textToCopy;
-       
+
        if(selection) {return;} // for copying the selection, used on X11
 
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-               
+
        NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
-       
+
        if (pasteBoard == nil) {
                [pool drain];
                return;
        }
-       
+
        NSArray *supportedTypes = [NSArray arrayWithObject:NSStringPboardType];
-       
+
        [pasteBoard declareTypes:supportedTypes owner:nil];
-       
+
        textToCopy = [NSString stringWithCString:buffer encoding:NSISOLatin1StringEncoding];
-       
+
        [pasteBoard setString:textToCopy forType:NSStringPboardType];
-       
+
        [pool drain];
 }
 
@@ -1848,9 +1947,9 @@ const GHOST_TUns8* GHOST_SystemCocoa::getBinaryDir() const
                [pool drain];
                return NULL;
        }
-       
+
        strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
-       
+
        [pool drain];
        return tempPath;
 }
index da7a0399f41adaa9b39a61468d400c01df097530..cada3f6897537a5ce72500fe9a3f92c1aec110ce 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 /**
-
  * $Id$
  * Copyright (C) 2001 NaN Technologies B.V.
  * @author     Maarten Gribnau
 #include "GHOST_SystemWin32.h"
 #include "GHOST_EventDragnDrop.h"
 
-#define WIN32_LEAN_AND_MEAN
-#ifdef _WIN32_IE
-#undef _WIN32_IE
-#endif
-#define _WIN32_IE 0x0501
-#include <windows.h>
+#include <stdio.h> // for debug [mce]
+
 #include <shlobj.h>
 
+
 // win64 doesn't define GWL_USERDATA
 #ifdef WIN32
 #ifndef GWL_USERDATA
 #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
@@ -143,9 +108,23 @@ GHOST_SystemWin32::GHOST_SystemWin32()
        m_displayManager = new GHOST_DisplayManagerWin32 ();
        GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
        m_displayManager->initialize();
-       
+
        // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
        OleInitialize(0);
+
+       m_input_fidelity_hint = HI_FI; // just for testing...
+
+       // register for RawInput devices
+       RAWINPUTDEVICE devices[1];
+
+       // multi-axis mouse (SpaceNavigator)
+       devices[0].usUsagePage = 0x01;
+       devices[0].usUsage = 0x08;
+       devices[0].dwFlags = 0;
+       devices[0].hwndTarget = NULL;
+
+       if (RegisterRawInputDevices(devices, 1, sizeof(RAWINPUTDEVICE)))
+               puts("registered for multi-axis input");
 }
 
 GHOST_SystemWin32::~GHOST_SystemWin32()
@@ -350,6 +329,8 @@ GHOST_TSuccess GHOST_SystemWin32::init()
 {
        GHOST_TSuccess success = GHOST_System::init();
 
+       m_ndofManager = new GHOST_NDOFManagerWin32(*this);
+
        /* Disable scaling on high DPI displays on Vista */
        HMODULE user32 = ::LoadLibraryA("user32.dll");
        typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
@@ -397,6 +378,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
 
 GHOST_TSuccess GHOST_SystemWin32::exit()
 {
+       // [mce] since this duplicates its super, why bother?
        return GHOST_System::exit();
 }
 
@@ -523,13 +505,10 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
 }
 
 
-GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
+GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x_screen, int y_screen)
 {
-       GHOST_TInt32 x_screen, y_screen;
        GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
        GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
-       
-       system->getCursorPosition(x_screen, y_screen);
 
        if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
        {
@@ -556,7 +535,7 @@ GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type,
                        window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
                }else{
                        return new GHOST_EventCursor(system->getMilliSeconds(),
-                                                                                GHOST_kEventCursorMove,
+                                                                                type,
                                                                                 window,
                                                                                 x_screen + x_accum,
                                                                                 y_screen + y_accum
@@ -566,7 +545,7 @@ GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type,
        }
        else {
                return new GHOST_EventCursor(system->getMilliSeconds(),
-                                                                        GHOST_kEventCursorMove,
+                                                                        type,
                                                                         window,
                                                                         x_screen,
                                                                         y_screen
@@ -638,391 +617,167 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
        minmax->ptMinTrackSize.y=240;
 }
 
+bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window)
+{
+       bool eventSent = false;
+
+       if (raw.header.dwType == RIM_TYPEHID)
+               {
+//             RID_DEVICE_INFO info;
+//             DWORD infoSize = sizeof(RID_DEVICE_INFO);
+//             int n = GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize);
+               // ... and so on
+               // I'll finish this device checking code later. Since we ask for only multi-axis input
+               // in the constructor, that's all we should get here.
+
+/*
+Here's some handy info from http://www.linux-usb.org/usb.ids
+
+vendor ID
+046d  Logitech, Inc.
+
+       device IDs
+       c623  3Dconnexion Space Traveller 3D Mouse
+       c625  3Dconnexion Space Pilot 3D Mouse
+       c626  3Dconnexion Space Navigator 3D Mouse
+       c627  3Dconnexion Space Explorer 3D Mouse
+
+No other registered devices use the c62_ space, so a simple mask will work!
+*/
+
+               // The NDOF manager sends button changes immediately, and *pretends* to
+               // send motion. Mark as 'sent' so motion will always get dispatched.
+               eventSent = true;
+
+               // multiple events per RAWHID? MSDN hints at this.
+               printf("%d events\n", (int)raw.data.hid.dwCount);
+
+               BYTE const* data = &raw.data.hid.bRawData;
+               // MinGW's definition (below) doesn't agree with MSDN reference for bRawData:
+               // typedef struct tagRAWHID {
+               //      DWORD dwSizeHid;
+               //      DWORD dwCount;
+               //      BYTE bRawData; // <== isn't this s'posed to be a BYTE*?
+               // } RAWHID,*PRAWHID,*LPRAWHID;
+
+               BYTE packetType = data[0];
+               switch (packetType)
+                       {
+                       case 1: // translation
+                               {
+                               short t[3];
+                               memcpy(t, data + 1, sizeof(t));
+                               // too much noise -- disable for now
+                               // printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]);
+                               m_ndofManager->updateTranslation(t, getMilliSeconds());
+                               // wariness of alignment issues prevents me from saying it this way:
+                               // m_ndofManager->updateTranslation((short*)(data + 1), getMilliSeconds());
+                               // though it probably (94.7%) works fine
+                               break;
+                               }
+                       case 2: // rotation
+                               {
+                               short r[3];
+                               memcpy(r, data + 1, sizeof(r));
+                               // printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]);
+                               m_ndofManager->updateRotation(r, getMilliSeconds());
+                               break;
+                               }
+                       case 3: // buttons
+                               {
+                               unsigned short buttons;
+                               memcpy(&buttons, data + 1, sizeof(buttons));
+                               printf("buttons:");
+                               if (buttons)
+                                       {
+                                       // work our way through the bit mask
+                                       for (int i = 0; i < 16; ++i)
+                                               if (buttons & (1 << i))
+                                                       printf(" %d", i + 1);
+                                       printf("\n");
+                                       }
+                               else
+                                       printf(" none\n");
+                               m_ndofManager->updateButtons(buttons, getMilliSeconds());
+                               break;
+                               }
+                       }
+               }
+       return eventSent;
+}
+
+int GHOST_SystemWin32::getMoreMousePoints(int xLatest, int yLatest, int xPrev, int yPrev, GHOST_WindowWin32* window)
+       {
+       MOUSEMOVEPOINT point = {
+               xLatest & 0x0000FFFF, // confine to low word to make GetMouseMovePointsEx happy
+               yLatest & 0x0000FFFF,
+               0, // time stamp unknown
+               NULL // no extra info
+               };
+
+       MOUSEMOVEPOINT morePoints[64];
+
+       int n = GetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &point, morePoints, 64, GMMP_USE_DISPLAY_POINTS);
+       if (n == -1)
+               {
+               printf("<!> can't get more mouse points (error %d)\n", (int) GetLastError());
+               return 0;
+               }
+
+       // search for 'prev' point (we want only newer points)
+       // TODO: detect & ignore points that don't belong to our window
+       for (int i = 1; i < n; ++i)
+               if (morePoints[i].x == xPrev && morePoints[i].y == yPrev)
+                       {
+                       n = i; // don't include found point (or more ancient points)
+                       break;
+                       }
+
+       for (int i = n - 1; i > 0; --i)
+               {
+               signed short x = morePoints[i].x;
+               signed short y = morePoints[i].y;
+
+               // uncomment here and in WM_MOUSEMOVE handler to show effectiveness of hi-fi input
+               // printf("> (%d,%d)\n", x, y);
+
+               pushEvent(processCursorEvent(GHOST_kEventCursorMove, window, x, y));
+               }
+
+       return n;
+       }
 
 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-       GHOST_Event* event = 0;
        LRESULT lResult = 0;
        GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
        GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
+       // [mce] then why not register this function at the end of SystemWin32 constructor?
+
+       bool handled = false;
 
        if (hwnd) {
                GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
                if (window) {
-                       switch (msg) {
-                               ////////////////////////////////////////////////////////////////////////
-                               // Keyboard events, processed
-                               ////////////////////////////////////////////////////////////////////////
-                               case WM_KEYDOWN:
-                                       /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a 
-                                        * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
-                                        * key is not pressed. 
-                                        */
-                               case WM_SYSKEYDOWN:
-                                       /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when 
-                                        * the user presses the F10 key (which activates the menu bar) or holds down the 
-                                        * alt key and then presses another key. It also occurs when no window currently 
-                                        * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the 
-                                        * active window. The window that receives the message can distinguish between these 
-                                        * two contexts by checking the context code in the lKeyData parameter. 
-                                        */
-                                       switch (wParam) {
-                                               case VK_SHIFT:
-                                               case VK_CONTROL:
-                                               case VK_MENU:
-                                                       if (!system->m_separateLeftRightInitialized) {
-                                                               // Check whether this system supports separate left and right keys
-                                                               switch (wParam) {
-                                                                       case VK_SHIFT:
-                                                                               system->m_separateLeftRight = 
-                                                                                       (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
-                                                                                       (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
-                                                                                       true : false;
-                                                                               break;
-                                                                       case VK_CONTROL:
-                                                                               system->m_separateLeftRight = 
-                                                                                       (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
-                                                                                       (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
-                                                                                       true : false;
-                                                                               break;
-                                                                       case VK_MENU:
-                                                                               system->m_separateLeftRight = 
-                                                                                       (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
-                                                                                       (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
-                                                                                       true : false;
-                                                                               break;
-                                                               }
-                                                               system->m_separateLeftRightInitialized = true;
-                                                       }
-                                                       system->processModifierKeys(window);
-                                                       // Bypass call to DefWindowProc
-                                                       return 0;
-                                               default:
-                                                       event = processKeyEvent(window, true, wParam, lParam);
-                                                       if (!event) {
-                                                               GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
-                                                               GHOST_PRINT(msg)
-                                                               GHOST_PRINT(" key ignored\n")
-                                                       }
-                                                       break;
-                                               }
-                                       break;
-
-                               case WM_KEYUP:
-                               case WM_SYSKEYUP:
-                                       switch (wParam) {
-                                               case VK_SHIFT:
-                                               case VK_CONTROL:
-                                               case VK_MENU:
-                                                       system->processModifierKeys(window);
-                                                       // Bypass call to DefWindowProc
-                                                       return 0;
-                                               default:
-                                                       event = processKeyEvent(window, false, wParam, lParam);
-                                                       if (!event) {
-                                                               GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
-                                                               GHOST_PRINT(msg)
-                                                               GHOST_PRINT(" key ignored\n")
-                                                       }
-                                                       break;
-                                       }
-                                       break;
-
-                               ////////////////////////////////////////////////////////////////////////
-                               // Keyboard events, ignored
-                               ////////////////////////////////////////////////////////////////////////
-                               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. 
-                                        */
-                               case WM_DEADCHAR:
-                                       /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
-                                        * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR 
-                                        * specifies a character code generated by a dead key. A dead key is a key that 
-                                        * generates a character, such as the umlaut (double-dot), that is combined with 
-                                        * another character to form a composite character. For example, the umlaut-O 
-                                        * character (Ù) is generated by typing the dead key for the umlaut character, and 
-                                        * then typing the O key.
-                                        */
-                               case WM_SYSDEADCHAR:
-                                       /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when 
-                                        * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. 
-                                        * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, 
-                                        * a dead key that is pressed while holding down the alt key. 
-                                        */
-                                       break;
-                               ////////////////////////////////////////////////////////////////////////
-                               // Tablet events, processed
-                               ////////////////////////////////////////////////////////////////////////
-                               case WT_PACKET:
-                                       ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam);
-                                       break;
-                               case WT_CSRCHANGE:
-                               case WT_PROXIMITY:
-                                       ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent();
-                                       break;
-                               ////////////////////////////////////////////////////////////////////////
-                               // Mouse events, processed
-                               ////////////////////////////////////////////////////////////////////////
-                               case WM_LBUTTONDOWN:
-                                       window->registerMouseClickEvent(true);
-                                       event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
-                                       break;
-                               case WM_MBUTTONDOWN:
-                                       window->registerMouseClickEvent(true);
-                                       event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
-                                       break;
-                               case WM_RBUTTONDOWN:
-                                       window->registerMouseClickEvent(true);
-                                       event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
-                                       break;
-                               case WM_XBUTTONDOWN:
-                                       window->registerMouseClickEvent(true);
-                                       if ((short) HIWORD(wParam) == XBUTTON1){
-                                               event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4);
-                                       }else if((short) HIWORD(wParam) == XBUTTON2){
-                                               event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5);
-                                       }
-                                       break;
-                               case WM_LBUTTONUP:
-                                       window->registerMouseClickEvent(false);
-                                       event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
-                                       break;
-                               case WM_MBUTTONUP:
-                                       window->registerMouseClickEvent(false);
-                                       event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
-                                       break;
-                               case WM_RBUTTONUP:
-                                       window->registerMouseClickEvent(false);
-                                       event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
-                                       break;
-                               case WM_XBUTTONUP:
-                                       window->registerMouseClickEvent(false);
-                                       if ((short) HIWORD(wParam) == XBUTTON1){
-                                               event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4);
-                                       }else if((short) HIWORD(wParam) == XBUTTON2){
-                                               event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5);
-                                       }
-                                       break;
-                               case WM_MOUSEMOVE:
-                                       event = processCursorEvent(GHOST_kEventCursorMove, window);
-                                       break;
-                               case WM_MOUSEWHEEL:
-                                       /* The WM_MOUSEWHEEL message is sent to the focus window 
-                                        * when the mouse wheel is rotated. The DefWindowProc 
-                                        * function propagates the message to the window's parent.
-                                        * There should be no internal forwarding of the message, 
-                                        * since DefWindowProc propagates it up the parent chain 
-                                        * until it finds a window that processes it.
-                                        */
-                                       event = processWheelEvent(window, wParam, lParam);
-                                       break;
-                               case WM_SETCURSOR:
-                                       /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
-                                        * to move within a window and mouse input is not captured.
-                                        * This means we have to set the cursor shape every time the mouse moves!
-                                        * The DefWindowProc function uses this message to set the cursor to an 
-                                        * arrow if it is not in the client area.
-                                        */
-                                       if (LOWORD(lParam) == HTCLIENT) {
-                                               // Load the current cursor
-                                               window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
-                                               // Bypass call to DefWindowProc
-                                               return 0;
-                                       } 
-                                       else {
-                                               // Outside of client area show standard cursor
-                                               window->loadCursor(true, GHOST_kStandardCursorDefault);
-                                       }
-                                       break;
-
-                               ////////////////////////////////////////////////////////////////////////
-                               // Mouse events, ignored
-                               ////////////////////////////////////////////////////////////////////////
-                               case WM_NCMOUSEMOVE:
-                                       /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved 
-                                        * within the nonclient area of the window. This message is posted to the window 
-                                        * that contains the cursor. If a window has captured the mouse, this message is not posted.
-                                        */
-                               case WM_NCHITTEST:
-                                       /* The WM_NCHITTEST message is sent to a window when the cursor moves, or 
-                                        * when a mouse button is pressed or released. If the mouse is not captured, 
-                                        * the message is sent to the window beneath the cursor. Otherwise, the message 
-                                        * is sent to the window that has captured the mouse. 
-                                        */
-                                       break;
-
-                               ////////////////////////////////////////////////////////////////////////
-                               // Window events, processed
-                               ////////////////////////////////////////////////////////////////////////
-                               case WM_CLOSE:
-                                       /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */
-                                       event = processWindowEvent(GHOST_kEventWindowClose, window);
-                                       break;
-                               case WM_ACTIVATE:
-                                       /* The WM_ACTIVATE message is sent to both the window being activated and the window being 
-                                        * deactivated. If the windows use the same input queue, the message is sent synchronously, 
-                                        * first to the window procedure of the top-level window being deactivated, then to the window
-                                        * procedure of the top-level window being activated. If the windows use different input queues,
-                                        * the message is sent asynchronously, so the window is activated immediately. 
-                                        */
-                                       event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
-                                       /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
-                                       will not be dispatched to OUR active window if we minimize one of OUR windows. */
-                                       lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
-                                       break;
-                               case WM_PAINT:
-                                       /* An application sends the WM_PAINT message when the system or another application 
-                                        * makes a request to paint a portion of an application's window. The message is sent
-                                        * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage 
-                                        * function when the application obtains a WM_PAINT message by using the GetMessage or 
-                                        * PeekMessage function. 
-                                        */
-                                       event = processWindowEvent(GHOST_kEventWindowUpdate, window);
-                                       ::ValidateRect(hwnd, NULL);
-                                       break;
-                               case WM_GETMINMAXINFO:
-                                       /* The WM_GETMINMAXINFO message is sent to a window when the size or 
-                                        * position of the window is about to change. An application can use 
-                                        * this message to override the window's default maximized size and 
-                                        * position, or its default minimum or maximum tracking size. 
-                                        */
-                                       processMinMaxInfo((MINMAXINFO *) lParam);
-                                       /* Let DefWindowProc handle it. */
-                                       break;
-                               case WM_SIZE:
-                                       /* The WM_SIZE message is sent to a window after its size has changed.
-                                        * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
-                                        * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
-                                        * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
-                                        * message without calling DefWindowProc.
-                                        */
-                                       event = processWindowEvent(GHOST_kEventWindowSize, window);
-                                       break;
-                               case WM_CAPTURECHANGED:
-                                       window->lostMouseCapture();
-                                       break;
-                               case WM_MOVING:
-                                       /* The WM_MOVING message is sent to a window that the user is moving. By processing 
-                                        * this message, an application can monitor the size and position of the drag rectangle
-                                        * and, if needed, change its size or position.
-                                        */
-                               case WM_MOVE:
-                                       /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
-                                        * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
-                                        * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
-                                        * message without calling DefWindowProc. 
-                                        */
-                                       event = processWindowEvent(GHOST_kEventWindowMove, window);
-                                       break;
-                               ////////////////////////////////////////////////////////////////////////
-                               // Window events, ignored
-                               ////////////////////////////////////////////////////////////////////////
-                               case WM_WINDOWPOSCHANGED:
-                                       /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
-                                        * in the Z order has changed as a result of a call to the SetWindowPos function or 
-                                        * another window-management function.
-                                        * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
-                                        * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
-                                        * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
-                                        * message without calling DefWindowProc.
-                                        */
-                               case WM_ERASEBKGND:
-                                       /* An application sends the WM_ERASEBKGND message when the window background must be 
-                                        * erased (for example, when a window is resized). The message is sent to prepare an 
-                                        * invalidated portion of a window for painting. 
-                                        */
-                               case WM_NCPAINT:
-                                       /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */
-                               case WM_NCACTIVATE:
-                                       /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed 
-                                        * to indicate an active or inactive state. 
-                                        */
-                               case WM_DESTROY:
-                                       /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window 
-                                        * procedure of the window being destroyed after the window is removed from the screen. 
-                                        * This message is sent first to the window being destroyed and then to the child windows 
-                                        * (if any) as they are destroyed. During the processing of the message, it can be assumed 
-                                        * that all child windows still exist. 
-                                        */
-                               case WM_NCDESTROY:
-                                       /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The 
-                                        * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY
-                                        * message. WM_DESTROY is used to free the allocated memory object associated with the window. 
-                                        */
-                               case WM_KILLFOCUS:
-                                       /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */
-                               case WM_SHOWWINDOW:
-                                       /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
-                               case WM_WINDOWPOSCHANGING:
-                                       /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in 
-                                        * the Z order is about to change as a result of a call to the SetWindowPos function or 
-                                        * another window-management function. 
-                                        */
-                               case WM_SETFOCUS:
-                                       /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
-                               case WM_ENTERSIZEMOVE:
-                                       /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving 
-                                        * or sizing modal loop. The window enters the moving or sizing modal loop when the user 
-                                        * clicks the window's title bar or sizing border, or when the window passes the 
-                                        * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the 
-                                        * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when 
-                                        * DefWindowProc returns. 
-                                        */
-                                       break;
-                                       
-                               ////////////////////////////////////////////////////////////////////////
-                               // Other events
-                               ////////////////////////////////////////////////////////////////////////
-                               case WM_GETTEXT:
-                                       /* An application sends a WM_GETTEXT message to copy the text that 
-                                        * corresponds to a window into a buffer provided by the caller. 
-                                        */
-                               case WM_ACTIVATEAPP:
-                                       /* The WM_ACTIVATEAPP message is sent when a window belonging to a 
-                                        * different application than the active window is about to be activated.
-                                        * The message is sent to the application whose window is being activated
-                                        * and to the application whose window is being deactivated. 
-                                        */
-                               case WM_TIMER:
-                                       /* The WIN32 docs say:
-                                        * The WM_TIMER message is posted to the installing thread's message queue
-                                        * when a timer expires. You can process the message by providing a WM_TIMER
-                                        * case in the window procedure. Otherwise, the default window procedure will
-                                        * call the TimerProc callback function specified in the call to the SetTimer
-                                        * function used to install the timer. 
-                                        *
-                                        * 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;
-                       }
+                       handled = system->handleEvent(window, msg, wParam, lParam);
+
+                       // take care of misc. cases that need hwnd
+                       if (msg == WM_ACTIVATE)
+                               /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
+                               will not be dispatched to OUR active window if we minimize one of OUR windows. */
+                               lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
+                       else if (msg == WM_PAINT)
+                               /* An application sends the WM_PAINT message when the system or another application
+                               * makes a request to paint a portion of an application's window. The message is sent
+                               * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage
+                               * function when the application obtains a WM_PAINT message by using the GetMessage or
+                               * PeekMessage function. */
+                               ::ValidateRect(hwnd, NULL);
                }
                else {
                        // Event found for a window before the pointer to the class has been set.
                        GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
+
                        /* These are events we typically miss at this point:
                           WM_GETMINMAXINFO     0x24
                           WM_NCCREATE                  0x81
@@ -1037,16 +792,450 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
                GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
        }
 
-       if (event) {
-               system->pushEvent(event);
-       }
-       else {
+       if (!handled)
                lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
-       }
+
        return lResult;
 }
 
-GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const 
+bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam)
+       {
+       GHOST_Event* event = NULL;
+       bool eventSent = false;
+
+       static int mousePosX = 0, mousePosY = 0; // track mouse position between calls
+
+       switch (msg) {
+               ////////////////////////////////////////////////////////////////////////
+               // Keyboard events, processed
+               ////////////////////////////////////////////////////////////////////////
+               case WM_KEYDOWN:
+                       /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a
+                        * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
+                        * key is not pressed.
+                        */
+               case WM_SYSKEYDOWN:
+                       /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when 
+                        * the user presses the F10 key (which activates the menu bar) or holds down the 
+                        * alt key and then presses another key. It also occurs when no window currently 
+                        * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the 
+                        * active window. The window that receives the message can distinguish between these 
+                        * two contexts by checking the context code in the lKeyData parameter. 
+                        */
+                       switch (wParam) {
+                               case VK_SHIFT:
+                               case VK_CONTROL:
+                               case VK_MENU:
+                                       if (!m_separateLeftRightInitialized) {
+                                               // Check whether this system supports separate left and right keys
+                                               switch (wParam) {
+                                                       case VK_SHIFT:
+                                                               m_separateLeftRight =
+                                                                       (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
+                                                                       (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
+                                                                       true : false;
+                                                               break;
+                                                       case VK_CONTROL:
+                                                               m_separateLeftRight =
+                                                                       (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
+                                                                       (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
+                                                                       true : false;
+                                                               break;
+                                                       case VK_MENU:
+                                                               m_separateLeftRight =
+                                                                       (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
+                                                                       (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
+                                                                       true : false;
+                                                               break;
+                                               }
+                                               m_separateLeftRightInitialized = true;
+                                       }
+                                       processModifierKeys(window);
+                                       // Bypass call to DefWindowProc
+                                       return true;
+                               default:
+                                       event = processKeyEvent(window, true, wParam, lParam);
+                                       if (!event) {
+                                               GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
+                                               GHOST_PRINT(msg)
+                                               GHOST_PRINT(" key ignored\n")
+                                       }
+                                       break;
+                  &n