Cycles: svn merge -r41225:41232 ^/trunk/blender
[blender.git] / intern / ghost / intern / GHOST_SystemCocoa.mm
index 3ab69ac3f6422b5a34bc93615e6a11b668748f49..ffc858d2fc52717eb00b32cf9097be8f4469b9e9 100644 (file)
@@ -1,5 +1,4 @@
-/**
- * $Id$
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -21,9 +20,8 @@
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s):     Maarten Gribnau 05/2001
- *                                     Damien Plisson 09/2009
- *                                     Mike Erwin 06/2010
+ * Contributors: Maarten Gribnau 05/2001
+ *               Damien Plisson 09/2009
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -32,7 +30,6 @@
 
 /*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>
 #include "GHOST_EventButton.h"
 #include "GHOST_EventCursor.h"
 #include "GHOST_EventWheel.h"
-#include "GHOST_EventNDOF.h"
 #include "GHOST_EventTrackpad.h"
 #include "GHOST_EventDragnDrop.h"
 #include "GHOST_EventString.h"
-
 #include "GHOST_TimerManager.h"
 #include "GHOST_TimerTask.h"
 #include "GHOST_WindowManager.h"
 #include "GHOST_WindowCocoa.h"
+#ifdef WITH_INPUT_NDOF
 #include "GHOST_NDOFManagerCocoa.h"
+#endif
+
 #include "AssertMacros.h"
 
 #pragma mark KeyMap, mouse converters
@@ -235,8 +233,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
@@ -266,7 +264,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;
@@ -279,7 +277,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;
@@ -318,24 +316,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;
@@ -347,12 +345,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')) {
@@ -363,38 +361,42 @@ 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) {
@@ -472,9 +474,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;
 }
@@ -545,15 +547,12 @@ 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 ();
@@ -564,28 +563,27 @@ 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));
-
+       
        //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
-       m_hasMultiTouchTrackpad =
-               (strstr(rstring,"MacBookAir") ||
-               (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')));
-
+       if (strstr(rstring,"MacBookAir") ||
+               (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')))
+               m_hasMultiTouchTrackpad = true;
+       else m_hasMultiTouchTrackpad = false;
+       
        free( rstring );
        rstring = NULL;
-
+       
        m_ignoreWindowSizedMessages = false;
-
-       m_input_fidelity_hint = HI_FI; // just for testing...
 }
 
 GHOST_SystemCocoa::~GHOST_SystemCocoa()
@@ -595,63 +593,74 @@ GHOST_SystemCocoa::~GHOST_SystemCocoa()
 
 GHOST_TSuccess GHOST_SystemCocoa::init()
 {
-       GHOST_TSuccess success = GHOST_System::init();
-       if (success) {
+       
+    GHOST_TSuccess success = GHOST_System::init();
+    if (success) {
 
+#ifdef WITH_INPUT_NDOF
                m_ndofManager = new GHOST_NDOFManagerCocoa(*this);
+#endif
+
+               //ProcessSerialNumber psn;
+               
+               //Carbon stuff to move window & menu to foreground
+               /*if (!GetCurrentProcess(&psn)) {
+                       TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+                       SetFrontProcess(&psn);
+               }*/
                
                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];
@@ -662,12 +671,12 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
                        [appDelegate setSystemCocoa:this];
                        [NSApp setDelegate:appDelegate];
                }
-
+               
                [NSApp finishLaunching];
-
+               
                [pool drain];
-       }
-       return success;
+    }
+    return success;
 }
 
 
@@ -677,10 +686,11 @@ 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);
 }
 
@@ -703,11 +713,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;
 
@@ -716,7 +726,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,
@@ -728,75 +738,57 @@ 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)];
+       
+       GHOST_TInt32 bottom = (contentRect.size.height - 1) - height - top;
 
        //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;
+       bottom = bottom > contentRect.origin.y ? bottom : contentRect.origin.y;
 
-       window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples);
+       window = new GHOST_WindowCocoa (this, title, left, bottom, 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;
-}
-
-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);
+    return window;
 }
 
-
-       
 /**
  * @note : returns coordinates in Cocoa screen coordinates
  */
 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;
 }
 
 /**
@@ -804,63 +796,65 @@ GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt3
  */
 GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
 {
-       GHOST_TInt32 wx,wy;
        GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow();
        if (!window) return GHOST_kFailure;
 
+       //Cursor and mouse dissociation placed here not to interfere with continuous grab
+       // (in cont. grab setMouseCursorPosition is directly called)
+       CGAssociateMouseAndMouseCursorPosition(false);
        setMouseCursorPosition(x, y);
-
+       CGAssociateMouseAndMouseCursorPosition(true);
+       
        //Force mouse move event (not pushed by Cocoa)
-       window->screenToClient(x, y, wx, wy);
-       pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, wx,wy));
+       pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x, y));
        m_outsideLoopEventProcessed = true;
-
+       
        return GHOST_kSuccess;
 }
 
-GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf)
+GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
 {
-//     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;
 }
 
 
 GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const
 {
-       keys.set(GHOST_kModifierKeyCommand, (m_modifierMask & NSCommandKeyMask) ? true : false);
+       keys.set(GHOST_kModifierKeyOS, (m_modifierMask & NSCommandKeyMask) ? true : false);
        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;
 }
 
 
@@ -874,130 +868,115 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
 {
        bool anyProcessed = false;
        NSEvent *event;
-       NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
+       
+       //      SetMouseCoalescingEnabled(false, NULL);
        //TODO : implement timer ??
        
-       do {
-               event = [NSApp nextEventMatchingMask:NSAnyEventMask
-                                                                       untilDate:[NSDate distantPast]
-                                                                         inMode:NSDefaultRunLoopMode
-                                                                        dequeue:YES];
-               if (event==nil)
-                       break;
+       /*do {
+               GHOST_TimerManager* timerMgr = getTimerManager();
                
-               anyProcessed = true;
+                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;
+                }*/
                
-               switch ([event type]) {
-                       case NSKeyDown:
-                               if ([event isARepeat])
-                                       break;
-                               // 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.
-                               }
+               do {
+                       NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+                       event = [NSApp nextEventMatchingMask:NSAnyEventMask
+                                                                          untilDate:[NSDate distantPast]
+                                                                                 inMode:NSDefaultRunLoopMode
+                                                                                dequeue:YES];
+                       if (event==nil) {
+                               [pool drain];
                                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();
-
+                       }
+                       
+                       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];
+                                        }*/
+                                       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();
+       
        if (m_outsideLoopEventProcessed) {
                m_outsideLoopEventProcessed = false;
                return true;
        }
-
-       return anyProcessed;
+       
+       m_ignoreWindowSizedMessages = false;
+       
+    return anyProcessed;
 }
 
-
 //Note: called from NSApplication delegate
 GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
 {
@@ -1005,7 +984,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;
@@ -1013,7 +992,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) );
        }
@@ -1024,11 +1003,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
                pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
        }
        if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
-               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
+               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyOS) );
        }
-
+       
        m_modifierMask = modifiers;
-
+       
        m_outsideLoopEventProcessed = true;
        return GHOST_kSuccess;
 }
@@ -1044,36 +1023,41 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
        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)
+                               {
+                                       //Enforce only one resize message per event loop (coalescing all the live resize messages)                                      
+                                       window->updateDrawingContext();
+                                       pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+                                       //Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager
+                                       pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonUp, window, convertButton(0)));
+                                       m_ignoreWindowSizedMessages = true;
+                               }
+                               break;
+                       default:
+                               return GHOST_kFailure;
+                               break;
+               }
        
        m_outsideLoopEventProcessed = true;
        return GHOST_kSuccess;
@@ -1086,76 +1070,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;
@@ -1168,13 +1152,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);
+                                       
+                                       ibuf = IMB_allocImBuf (imgSize.width , imgSize.height, 32, IB_rect);
                                        if (!ibuf) {
                                                [droppedImg release];
                                                return GHOST_kFailure;
                                        }
-
+                                       
                                        /*Get the bitmap of the image*/
                                        enumerator = [[droppedImg representations] objectEnumerator];
                                        while ((representation = [enumerator nextObject])) {
@@ -1184,7 +1168,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*/
@@ -1199,11 +1183,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 contexts with non premutliplied alpha,
+                                               /* As Core Graphics does not support contextes 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 
@@ -1213,12 +1197,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];
@@ -1226,7 +1210,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
@@ -1236,12 +1220,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];
@@ -1250,37 +1234,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;
                                }
-
+                                       break;
+                                       
                                default:
                                        return GHOST_kFailure;
                                        break;
                        }
                        pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,eventData));
-                       break;
                }
+                       break;
                default:
                        return GHOST_kFailure;
        }
@@ -1292,11 +1276,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())
        {
@@ -1311,6 +1295,11 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
                        NSArray *windowsList = [NSApp orderedWindows];
                        if ([windowsList count]) {
                                [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
+                               //Handle the modifiers keyes changed state issue
+                               //as recovering from the quit dialog is like application
+                               //gaining focus back.
+                               //Main issue fixed is Cmd modifier not being cleared
+                               handleApplicationBecomeActiveEvent();
                        }
                }
 
@@ -1320,7 +1309,7 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
                m_outsideLoopEventProcessed = true;
                return GHOST_kExitNow;
        }
-
+       
        return GHOST_kExitCancel;
 }
 
@@ -1332,11 +1321,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;
@@ -1357,16 +1346,16 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
 
        if (confirmOpen == NSAlertAlternateReturn)
        {
-               filenameTextSize = [filepath lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding];
-
+               filenameTextSize = [filepath lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+               
                temp_buff = (char*) malloc(filenameTextSize+1); 
-
+               
                if (temp_buff == NULL) {
                        return GHOST_kFailure;
                }
-
-               strncpy(temp_buff, [filepath cStringUsingEncoding:NSISOLatin1StringEncoding], filenameTextSize);
-
+               
+               strncpy(temp_buff, [filepath cStringUsingEncoding:NSUTF8StringEncoding], filenameTextSize);
+               
                temp_buff[filenameTextSize] = '\0';
 
                pushEvent(new GHOST_EventString(getMilliSeconds(),GHOST_kEventOpenMainFile,window,(GHOST_TEventDataPtr) temp_buff));
@@ -1376,292 +1365,262 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
        else return NO;
 }
 
-GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr)
+GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventType)
 {
-       printf("tablet prox: ");
        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;
-       }
-
-       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 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];
-
-               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
-               // (later though, after tablet mouse is fixed and (not) coalescing is in place)
-               }
-       else {
-               printf("leaving\n");
-               *tool_id_ptr = TOOL_ID_NONE;
-
-               ct.Active = GHOST_kTabletModeNone;
-               ct.Pressure = 0;
-               ct.Xtilt = 0;
-               ct.Ytilt = 0;
-               }
-
-       return GHOST_kSuccess;
-}
-
-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]);
-
+       GHOST_IWindow* window;
+       
+       window = m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
        if (!window) {
                //printf("\nW failure for event 0x%x",[event type]);
                return GHOST_kFailure;
        }
-
-       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:
-                       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])));
+       
+       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;
                        break;
-               case NSLeftMouseUp:
-                       if (m_input_fidelity_hint == HI_FI)
-                               {
-                               printf("hi-fi off\n");
-                               [NSEvent setMouseCoalescingEnabled:YES];
+               
+               case NSTabletProximity:
+                       ct.Pressure = 0;
+                       ct.Xtilt = 0;
+                       ct.Ytilt = 0;
+                       if ([event isEnteringProximity])
+                       {
+                               //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;
                                }
-                       pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
+                       } else {
+                               // pointer is leaving - return to mouse
+                               ct.Active = GHOST_kTabletModeNone;
+                       }
                        break;
+               
                default:
-                       {
-                       NSPoint pos = [event locationInWindow];
-                       pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, pos.x, pos.y));
+                       GHOST_ASSERT(FALSE,"GHOST_SystemCocoa::handleTabletEvent : unknown event received");
+                       return GHOST_kFailure;
                        break;
-                       }
-               }
-
+       }
        return GHOST_kSuccess;
 }
 
 
 GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 {
-       printf("mouse ");
        NSEvent *event = (NSEvent *)eventPtr;
-       GHOST_Window* window =
-               (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
-
+    GHOST_WindowCocoa* window;
+       
+       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;
        }
-
-       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]) {
+       
+       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])));
-                       // cheap hack, should reset when grab ends.
-                       warp_dx = warp_dy = 0;
+                       //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 NSLeftMouseDragged:
                case NSRightMouseDragged:
-               case NSOtherMouseDragged:
+               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 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;
-
+                                       {
+                                               GHOST_TInt32 x_warp, y_warp, x_accum, y_accum, x, y;
+                                               
                                                window->getCursorGrabInitPos(x_warp, y_warp);
-
+                                               
                                                window->getCursorGrabAccum(x_accum, y_accum);
-                                               x_accum += event_dx;
-                                               y_accum += event_dy;
+                                               x_accum += [event deltaX];
+                                               y_accum += -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ...
                                                window->setCursorGrabAccum(x_accum, y_accum);
-
-                                               pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum));
+                                               
+                                               window->clientToScreenIntern(x_warp+x_accum, y_warp+y_accum, x, y);
+                                               pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y));
+                                       }
                                                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_TInt32 x_accum, y_accum, x_cur, y_cur, x, y;
                                                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_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_dx - m_cursorDelta_x;
-                                               y_accum += event_dy - m_cursorDelta_y;
+                                               x_accum += [event deltaX]-m_cursorDelta_x;
+                                               y_accum += -[event deltaY]-m_cursorDelta_y; //Strange Apple implementation (inverted coordinates for the deltaY) ...
                                                window->setCursorGrabAccum(x_accum, y_accum);
-
+                                               
+                                               
                                                //Warp mouse cursor if needed
-                                               x_mouse += event_dx - m_cursorDelta_x;
-                                               y_mouse += event_dy - m_cursorDelta_y;
+                                               x_mouse += [event deltaX]-m_cursorDelta_x;
+                                               y_mouse += -[event deltaY]-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);
+                                               window->clientToScreenIntern(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));
-
+                                               window->clientToScreenIntern(x_cur + x_accum, y_cur + y_accum, x, y);
+                                               pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y));
+                                       }
                                                break;
-                                               }
                                        default:
+                                       {
                                                //Normal cursor operation: send mouse position in window
-                                               pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
-                                               m_cursorDelta_x=0;
-                                               m_cursorDelta_y=0; //Mouse motion occured between two cursor warps, so we can reset the delta counter
-                                               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 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;
+                                               NSPoint mousePos = [event locationInWindow];
+                                               GHOST_TInt32 x, y;
 
-                               double deltaF = [event deltaY];
-                               if (deltaF == 0.0) break; //discard trackpad delta=0 events
+                                               window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
+                                               pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y));
 
-                               delta = deltaF > 0.0 ? 1 : -1;
-                               pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta));
+                                               m_cursorDelta_x=0;
+                                               m_cursorDelta_y=0; //Mouse motion occurred between two cursor warps, so we can reset the delta counter
+                                       }
+                                               break;
+                               }
+                               break;
+                       
+               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) deltaF = [event deltaX]; // make blender decide if it's horizontal scroll
+                                       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];
+                                       GHOST_TInt32 x, y;
+                                       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;
+
+                                       window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
+                                       dy = -dy;
+
+                                       pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy));
+                               }
                        }
                        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));
-                       break;
+                               NSPoint mousePos = [event locationInWindow];
+                               GHOST_TInt32 x, y;
+                               window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
+                               pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, x, 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));
-                       break;
+                               NSPoint mousePos = [event locationInWindow];
+                               GHOST_TInt32 x, y;
+                               window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
+                               pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, x, y,
+                                                                                                 -[event rotation] * 5.0, 0));
                        }
                case NSEventTypeBeginGesture:
                        m_isGestureInProgress = true;
@@ -1670,10 +1629,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;
 }
 
@@ -1695,7 +1654,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                return GHOST_kFailure;
        }
 
+       char utf8_buf[6]= {'\0'};
+       ascii = 0;
+       
        switch ([event type]) {
+
                case NSKeyDown:
                case NSKeyUp:
                        charsIgnoringModifiers = [event charactersIgnoringModifiers];
@@ -1707,34 +1670,36 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                                keyCode = convertKey([event keyCode],0,
                                                                         [event type] == NSKeyDown?kUCKeyActionDown:kUCKeyActionUp);
 
-
+                       /* handling both unicode or ascii */
                        characters = [event characters];
-                       if ([characters length]>0) { //Check for dead keys
-                               //Convert characters to iso latin 1 encoding
-                               convertedCharacters = [characters dataUsingEncoding:NSISOLatin1StringEncoding];
-                               if ([convertedCharacters length]>0)
-                                       ascii =((char*)[convertedCharacters bytes])[0];
-                               else
-                                       ascii = 0; //Character not available in iso latin 1 encoding
+                       if ([characters length]>0) {
+                               convertedCharacters = [characters dataUsingEncoding:NSUTF8StringEncoding];
+                               
+                               for (int x = 0; x < [convertedCharacters length]; x++) {
+                                       utf8_buf[x] = ((char*)[convertedCharacters bytes])[x];
+                               }
+
+                               /* ascii is a subset of unicode */
+                               if ([convertedCharacters length] == 1) {
+                                       ascii = utf8_buf[0];
+                               }
                        }
-                       else
-                               ascii= 0;
 
                        if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask))
                                break; //Cmd-Q is directly handled by Cocoa
 
                        if ([event type] == NSKeyDown) {
-                               pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyDown, window, keyCode, ascii) );
-                               //printf("\nKey down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii);
+                               pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyDown, window, keyCode, ascii, utf8_buf) );
+                               //printf("Key down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf);
                        } else {
-                               pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyUp, window, keyCode, ascii) );
-                               //printf("\nKey up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii);
+                               pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyUp, window, keyCode, 0, '\0') );
+                               //printf("Key up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf);
                        }
                        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) );
                        }
@@ -1745,66 +1710,67 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                                pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
                        }
                        if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
-                               pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
+                               pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyOS) );
                        }
-
+                       
                        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];
@@ -1819,83 +1785,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];
-}
-
-#pragma mark Base directories retrieval
-
-const GHOST_TUns8* GHOST_SystemCocoa::getSystemDir() const
-{
-       static GHOST_TUns8 tempPath[512] = "";
-       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-       NSFileManager *fileManager;
-       NSString *basePath;
-       NSArray *paths;
-
-       paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSLocalDomainMask, YES);
-
-       if ([paths count] > 0)
-               basePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Blender"];
-       else { //Fall back to standard unix path in case of issue
-               basePath = @"/usr/share/blender";
-       }
-
-       /* Ensure path exists, creates it if needed */
-       fileManager = [NSFileManager defaultManager];
-       if (![fileManager fileExistsAtPath:basePath isDirectory:NULL]) {
-               [fileManager createDirectoryAtPath:basePath attributes:nil];
-       }
-
-       strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
-
+       
        [pool drain];
-       return tempPath;
 }
 
-const GHOST_TUns8* GHOST_SystemCocoa::getUserDir() const
-{
-       static GHOST_TUns8 tempPath[512] = "";
-       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-       NSFileManager *fileManager;
-       NSString *basePath;
-       NSArray *paths;
-
-       paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
-
-       if ([paths count] > 0)
-               basePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Blender"];
-       else { //Fall back to HOME in case of issue
-               basePath = [NSHomeDirectory() stringByAppendingPathComponent:@".blender"];
-       }
-
-       /* Ensure path exists, creates it if needed */
-       fileManager = [NSFileManager defaultManager];
-       if (![fileManager fileExistsAtPath:basePath isDirectory:NULL]) {
-               [fileManager createDirectoryAtPath:basePath attributes:nil];
-       }
-
-       strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
-
-       [pool drain];
-       return tempPath;
-}