Cocoa port : First pure Cocoa version !
authorDamien Plisson <damien.plisson@yahoo.fr>
Tue, 6 Oct 2009 16:56:22 +0000 (16:56 +0000)
committerDamien Plisson <damien.plisson@yahoo.fr>
Tue, 6 Oct 2009 16:56:22 +0000 (16:56 +0000)
(Mostly for very early testers)

Cocoa uses coordinates with y=0 at bottom : updated wm_window.c and wm_event_system.c for COCOA build to avoid double conversions in response to mouse move events and GHOST_getCursorPosition

Known limitations:
No fullscreen support
Font issue in preference panel
libSDL uses some Carbon functions

intern/ghost/intern/GHOST_SystemCocoa.h
intern/ghost/intern/GHOST_SystemCocoa.mm
intern/ghost/intern/GHOST_WindowCocoa.h
intern/ghost/intern/GHOST_WindowCocoa.mm
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_window.c

index 3e499f3d136dc7151acd2d8e9f2f73473d75f697..eab5a5b28aaa07aba8cb2d35ac2f34876b43e919 100644 (file)
@@ -46,6 +46,7 @@
 class GHOST_EventCursor;
 class GHOST_EventKey;
 class GHOST_EventWindow;
+class GHOST_WindowCocoa;
 
 
 class GHOST_SystemCocoa : public GHOST_System {
@@ -191,6 +192,13 @@ public:
         */
        virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
 
+       /**
+     * Handles a window event. Called by GHOST_WindowCocoa window delegate
+     * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
+     * @return Indication whether the event was handled. 
+     */
+    GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window);
+       
 protected:
        /**
         * Initializes the system.
@@ -220,13 +228,6 @@ protected:
      */
     GHOST_TSuccess handleKeyEvent(void *eventPtr);
 
-   /**
-     * Handles a window event.
-     * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
-     * @return Indication whether the event was handled. 
-     */
-    GHOST_TSuccess handleWindowEvent(void *eventPtr);
-
     /**
      * Handles all basic Mac application stuff for a mouse down event.
      * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
@@ -250,10 +251,7 @@ protected:
      * @param tmTask Pointer to the timer task that expired.
      */
     //static void s_timerCallback(TMTaskPtr tmTask);
-    
-       /** Cocoa autoReleasePool (void*) used for enablign standard C++ compilation */
-       void* m_autoReleasePool;
-       
+       
     /** Event handler reference. */
     //EventHandlerRef m_handler;
        
index 06ce2882bebad3177ddd2a4a78bf91b19af2f284..fe3cd80f265543c10901f31240dd545ce6061979 100644 (file)
@@ -89,7 +89,157 @@ const EventTypeSpec kEvents[] =
        
 };*/
 
-static GHOST_TButtonMask convertButton(EventMouseButton button)
+/* Keycodes from Carbon include file */
+/*  
+ *  Summary:
+ *    Virtual keycodes
+ *  
+ *  Discussion:
+ *    These constants are the virtual keycodes defined originally in
+ *    Inside Mac Volume V, pg. V-191. They identify physical keys on a
+ *    keyboard. Those constants with "ANSI" in the name are labeled
+ *    according to the key position on an ANSI-standard US keyboard.
+ *    For example, kVK_ANSI_A indicates the virtual keycode for the key
+ *    with the letter 'A' in the US keyboard layout. Other keyboard
+ *    layouts may have the 'A' key label on a different physical key;
+ *    in this case, pressing 'A' will generate a different virtual
+ *    keycode.
+ */
+enum {
+       kVK_ANSI_A                    = 0x00,
+       kVK_ANSI_S                    = 0x01,
+       kVK_ANSI_D                    = 0x02,
+       kVK_ANSI_F                    = 0x03,
+       kVK_ANSI_H                    = 0x04,
+       kVK_ANSI_G                    = 0x05,
+       kVK_ANSI_Z                    = 0x06,
+       kVK_ANSI_X                    = 0x07,
+       kVK_ANSI_C                    = 0x08,
+       kVK_ANSI_V                    = 0x09,
+       kVK_ANSI_B                    = 0x0B,
+       kVK_ANSI_Q                    = 0x0C,
+       kVK_ANSI_W                    = 0x0D,
+       kVK_ANSI_E                    = 0x0E,
+       kVK_ANSI_R                    = 0x0F,
+       kVK_ANSI_Y                    = 0x10,
+       kVK_ANSI_T                    = 0x11,
+       kVK_ANSI_1                    = 0x12,
+       kVK_ANSI_2                    = 0x13,
+       kVK_ANSI_3                    = 0x14,
+       kVK_ANSI_4                    = 0x15,
+       kVK_ANSI_6                    = 0x16,
+       kVK_ANSI_5                    = 0x17,
+       kVK_ANSI_Equal                = 0x18,
+       kVK_ANSI_9                    = 0x19,
+       kVK_ANSI_7                    = 0x1A,
+       kVK_ANSI_Minus                = 0x1B,
+       kVK_ANSI_8                    = 0x1C,
+       kVK_ANSI_0                    = 0x1D,
+       kVK_ANSI_RightBracket         = 0x1E,
+       kVK_ANSI_O                    = 0x1F,
+       kVK_ANSI_U                    = 0x20,
+       kVK_ANSI_LeftBracket          = 0x21,
+       kVK_ANSI_I                    = 0x22,
+       kVK_ANSI_P                    = 0x23,
+       kVK_ANSI_L                    = 0x25,
+       kVK_ANSI_J                    = 0x26,
+       kVK_ANSI_Quote                = 0x27,
+       kVK_ANSI_K                    = 0x28,
+       kVK_ANSI_Semicolon            = 0x29,
+       kVK_ANSI_Backslash            = 0x2A,
+       kVK_ANSI_Comma                = 0x2B,
+       kVK_ANSI_Slash                = 0x2C,
+       kVK_ANSI_N                    = 0x2D,
+       kVK_ANSI_M                    = 0x2E,
+       kVK_ANSI_Period               = 0x2F,
+       kVK_ANSI_Grave                = 0x32,
+       kVK_ANSI_KeypadDecimal        = 0x41,
+       kVK_ANSI_KeypadMultiply       = 0x43,
+       kVK_ANSI_KeypadPlus           = 0x45,
+       kVK_ANSI_KeypadClear          = 0x47,
+       kVK_ANSI_KeypadDivide         = 0x4B,
+       kVK_ANSI_KeypadEnter          = 0x4C,
+       kVK_ANSI_KeypadMinus          = 0x4E,
+       kVK_ANSI_KeypadEquals         = 0x51,
+       kVK_ANSI_Keypad0              = 0x52,
+       kVK_ANSI_Keypad1              = 0x53,
+       kVK_ANSI_Keypad2              = 0x54,
+       kVK_ANSI_Keypad3              = 0x55,
+       kVK_ANSI_Keypad4              = 0x56,
+       kVK_ANSI_Keypad5              = 0x57,
+       kVK_ANSI_Keypad6              = 0x58,
+       kVK_ANSI_Keypad7              = 0x59,
+       kVK_ANSI_Keypad8              = 0x5B,
+       kVK_ANSI_Keypad9              = 0x5C
+};
+
+/* keycodes for keys that are independent of keyboard layout*/
+enum {
+       kVK_Return                    = 0x24,
+       kVK_Tab                       = 0x30,
+       kVK_Space                     = 0x31,
+       kVK_Delete                    = 0x33,
+       kVK_Escape                    = 0x35,
+       kVK_Command                   = 0x37,
+       kVK_Shift                     = 0x38,
+       kVK_CapsLock                  = 0x39,
+       kVK_Option                    = 0x3A,
+       kVK_Control                   = 0x3B,
+       kVK_RightShift                = 0x3C,
+       kVK_RightOption               = 0x3D,
+       kVK_RightControl              = 0x3E,
+       kVK_Function                  = 0x3F,
+       kVK_F17                       = 0x40,
+       kVK_VolumeUp                  = 0x48,
+       kVK_VolumeDown                = 0x49,
+       kVK_Mute                      = 0x4A,
+       kVK_F18                       = 0x4F,
+       kVK_F19                       = 0x50,
+       kVK_F20                       = 0x5A,
+       kVK_F5                        = 0x60,
+       kVK_F6                        = 0x61,
+       kVK_F7                        = 0x62,
+       kVK_F3                        = 0x63,
+       kVK_F8                        = 0x64,
+       kVK_F9                        = 0x65,
+       kVK_F11                       = 0x67,
+       kVK_F13                       = 0x69,
+       kVK_F16                       = 0x6A,
+       kVK_F14                       = 0x6B,
+       kVK_F10                       = 0x6D,
+       kVK_F12                       = 0x6F,
+       kVK_F15                       = 0x71,
+       kVK_Help                      = 0x72,
+       kVK_Home                      = 0x73,
+       kVK_PageUp                    = 0x74,
+       kVK_ForwardDelete             = 0x75,
+       kVK_F4                        = 0x76,
+       kVK_End                       = 0x77,
+       kVK_F2                        = 0x78,
+       kVK_PageDown                  = 0x79,
+       kVK_F1                        = 0x7A,
+       kVK_LeftArrow                 = 0x7B,
+       kVK_RightArrow                = 0x7C,
+       kVK_DownArrow                 = 0x7D,
+       kVK_UpArrow                   = 0x7E
+};
+
+/* ISO keyboards only*/
+enum {
+       kVK_ISO_Section               = 0x0A
+};
+
+/* JIS keyboards only*/
+enum {
+       kVK_JIS_Yen                   = 0x5D,
+       kVK_JIS_Underscore            = 0x5E,
+       kVK_JIS_KeypadComma           = 0x5F,
+       kVK_JIS_Eisu                  = 0x66,
+       kVK_JIS_Kana                  = 0x68
+};
+
+
+static GHOST_TButtonMask convertButton(int button)
 {
        switch (button) {
                case 0:
@@ -474,8 +624,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
 
 GHOST_SystemCocoa::~GHOST_SystemCocoa()
 {
-       NSAutoreleasePool* pool = (NSAutoreleasePool *)m_autoReleasePool;
-       [pool drain];
 }
 
 
@@ -492,16 +640,18 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
                        SetFrontProcess(&psn);
                }*/
                
-               m_autoReleasePool = [[NSAutoreleasePool alloc] init];
+               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
-                               NSMenu *appMenu = [[NSMenu alloc] initWithTitle:@"Blender"];
+                               appMenu = [[NSMenu alloc] initWithTitle:@"Blender"];
                                
                                [appMenu addItemWithTitle:@"About Blender" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
                                [appMenu addItem:[NSMenuItem separatorItem]];
@@ -525,7 +675,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
                                [appMenu release];
                                
                                //Create the window menu
-                               NSMenu *windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+                               windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
                                
                                menuItem = [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
                                [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
@@ -549,7 +699,8 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
                        [appDelegate setSystemCocoa:this];
                        [NSApp setDelegate:appDelegate];
                }
-               
+                               
+               [pool drain];
                
                /*
          * Initialize the cursor to the standard arrow shape (so that we can change it later on).
@@ -597,12 +748,18 @@ GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const
 {
        //Note that OS X supports monitor hot plug
        // We do not support multiple monitors at the moment
-       return [[NSScreen screens] count];
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+       GHOST_TUns8 count = [[NSScreen screens] count];
+
+       [pool drain];
+       return count;
 }
 
 
 void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
 {
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        //Get visible frame, that is frame excluding dock and top menu bar
        NSRect frame = [[NSScreen mainScreen] visibleFrame];
        
@@ -612,6 +769,8 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns
        
        width = contentRect.size.width;
        height = contentRect.size.height;
+
+       [pool drain];
 }
 
 
@@ -627,7 +786,8 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
        const GHOST_TEmbedderWindowID parentWindow
 )
 {
-    GHOST_IWindow* window = 0;
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       GHOST_IWindow* window = 0;
        
        //Get the available rect for including window contents
        NSRect frame = [[NSScreen mainScreen] visibleFrame];
@@ -638,7 +798,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
        left = left > contentRect.origin.x ? left : contentRect.origin.x;
        top = top > contentRect.origin.y ? top : contentRect.origin.y;
        
-       window = new GHOST_WindowCocoa (title, left, top, width, height, state, type);
+       window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type);
 
     if (window) {
         if (window->getValid()) {
@@ -657,6 +817,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
        else {
                GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");
        }
+       [pool drain];
     return window;
 }
 
@@ -713,7 +874,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32
 
 GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const
 {
-    NSUInteger modifiers = [[NSApp currentEvent] modifierFlags];
+       NSUInteger modifiers = [[NSApp currentEvent] modifierFlags];
        //Direct query to modifierFlags can be used in 10.6
 
     keys.set(GHOST_kModifierKeyCommand, (modifiers & NSCommandKeyMask) ? true : false);
@@ -744,16 +905,9 @@ GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const
  */
 bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
 {
-       NSAutoreleasePool* pool = (NSAutoreleasePool*)m_autoReleasePool;
-       //bool anyProcessed = false;
+       bool anyProcessed = false;
        NSEvent *event;
        
-       //Reinit the AutoReleasePool
-       //This is not done the typical Cocoa way (init at beginning of loop, and drain at the end)
-       //to allow pool to work with other function calls outside this loop (but in same thread)
-       [pool drain];
-       m_autoReleasePool = [[NSAutoreleasePool alloc] init];
-       
        //      SetMouseCoalescingEnabled(false, NULL);
        //TODO : implement timer ??
        
@@ -790,14 +944,17 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
                 }*/
                
                do {
+                       NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
                        event = [NSApp nextEventMatchingMask:NSAnyEventMask
                                                                           untilDate:[NSDate distantPast]
                                                                                  inMode:NSDefaultRunLoopMode
                                                                                 dequeue:YES];
-                       if (event==nil)
+                       if (event==nil) {
+                               [pool drain];
                                break;
+                       }
                        
-                       //anyProcessed = true;
+                       anyProcessed = true;
                        
                        switch ([event type]) {
                                case NSKeyDown:
@@ -853,47 +1010,42 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
                        }
                        //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
        
        
-    return true; //anyProcessed;
+       
+    return anyProcessed;
 }
 
-//TODO: To be called from NSWindow delegate
-GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(void *eventPtr)
+//Note: called from NSWindow delegate
+GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window)
 {
-       /*WindowRef windowRef;
-       GHOST_WindowCocoa *window;
-       
-       // Check if the event was send to a GHOST window
-       ::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowRef);
-       window = (GHOST_WindowCarbon*) ::GetWRefCon(windowRef);
        if (!validWindow(window)) {
-               return err;
+               return GHOST_kFailure;
        }
 
        //if (!getFullScreen()) {
-               err = noErr;
-               switch([event ]) 
+               switch(eventType) 
                {
-                       case kEventWindowClose:
+                       case GHOST_kEventWindowClose:
                                pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
                                break;
-                       case kEventWindowActivated:
+                       case GHOST_kEventWindowActivate:
                                m_windowManager->setActiveWindow(window);
                                window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
                                pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
                                break;
-                       case kEventWindowDeactivated:
+                       case GHOST_kEventWindowDeactivate:
                                m_windowManager->setWindowInactive(window);
                                pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
                                break;
-                       case kEventWindowUpdate:
+                       case GHOST_kEventWindowUpdate:
                                //if (getFullScreen()) GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen update event\n");
                                pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
                                break;
-                       case kEventWindowBoundsChanged:
+                       case GHOST_kEventWindowSize:
                                if (!m_ignoreWindowSizedMessages)
                                {
                                        window->updateDrawingContext();
@@ -901,7 +1053,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(void *eventPtr)
                                }
                                break;
                        default:
-                               err = eventNotHandledErr;
+                               return GHOST_kFailure;
                                break;
                }
 //     }
@@ -910,7 +1062,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(void *eventPtr)
                //GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n");
                //::RemoveEventFromQueue(::GetMainEventQueue(), event);
        //}
-       */
        return GHOST_kSuccess;
 }
 
@@ -943,10 +1094,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr)
        GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData();
        NSUInteger tabletEvent;
        
-       ct.Pressure = 0;
-       ct.Xtilt = 0;
-       ct.Ytilt = 0;
-       
        //Handle tablet events combined with mouse events
        switch ([event subtype]) {
                case NX_SUBTYPE_TABLET_POINT:
@@ -969,6 +1116,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr)
                        break;
                
                case NSTabletProximity:
+                       ct.Pressure = 0;
+                       ct.Xtilt = 0;
+                       ct.Ytilt = 0;
                        if ([event isEnteringProximity])
                        {
                                //pointer is entering tablet area proximity
@@ -1005,23 +1155,24 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
        NSEvent *event = (NSEvent *)eventPtr;
     GHOST_IWindow* window = m_windowManager->getActiveWindow();
        
+       if (!window) {
+               printf("\nM invalid window");
+               return GHOST_kFailure;
+       }
+       
        switch ([event type])
     {
                case NSLeftMouseDown:
                case NSRightMouseDown:
                case NSOtherMouseDown:
-                       if (m_windowManager->getActiveWindow()) {
-                               pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonDown, window, convertButton([event buttonNumber])));
-                       }
+                       pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonDown, window, convertButton([event buttonNumber])));
                        handleTabletEvent(eventPtr);
                        break;
                                                
                case NSLeftMouseUp:
                case NSRightMouseUp:
                case NSOtherMouseUp:
-                       if (m_windowManager->getActiveWindow()) {
-                               pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
-                       }
+                       pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
                        handleTabletEvent(eventPtr);
                        break;
                        
@@ -1098,16 +1249,16 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
                case NSFlagsChanged: 
                        modifiers = [event modifierFlags];
                        if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
-                               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
+                               pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
                        }
                        if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) {
-                               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
+                               pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
                        }
                        if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) {
-                               pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
+                               pushEvent( new GHOST_EventKey([event timestamp], (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([event timestamp], (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
                        }
                        
                        m_modifierMask = modifiers;
index f383e3a7a811d33582d557397ad083d9bd378143..5ff205d964fe95b52ee6f49b1883bf75eb9a7f14 100644 (file)
@@ -40,8 +40,7 @@
 #include "GHOST_Window.h"
 #include "STR_String.h"
 
-#include <AGL/agl.h>
-
+class GHOST_SystemCocoa;
 
 /**
  * Window on Mac OSX/Cocoa.
@@ -60,6 +59,7 @@ public:
         * Constructor.
         * Creates a new window and opens it.
         * To check if the window was created properly, use the getValid() method.
+        * @param systemCocoa The associated system class to forward events to
         * @param title         The text shown in the title bar of the window.
         * @param left          The coordinate of the left edge of the window.
         * @param top           The coordinate of the top edge of the window.
@@ -70,6 +70,7 @@ public:
         * @param stereoVisual  Stereo visual for quad buffered stereo.
         */
        GHOST_WindowCocoa(
+               const GHOST_SystemCocoa *systemCocoa,
                const STR_String& title,
                GHOST_TInt32 left,
                GHOST_TInt32 top,
@@ -210,8 +211,8 @@ public:
     virtual bool getFullScreenDirty();
 
                /* accessor for fullscreen window */
-       virtual void setMac_windowState(short value);
-       virtual short getMac_windowState();
+       /*virtual void setMac_windowState(short value);
+       virtual short getMac_windowState();*/
 
 
        const GHOST_TabletData* GetTabletData()
@@ -260,48 +261,28 @@ protected:
                                        
        virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
     
-    /**
-     * Converts a string object to a Mac Pascal string.
-     * @param in       The string object to be converted.
-     * @param out      The converted string.
-     */
-    virtual void gen2mac(const STR_String& in, Str255 out) const;
-
-    /**
-     * Converts a Mac Pascal string to a string object.
-     * @param in       The string to be converted.
-     * @param out      The converted string object.
-     */
-    virtual void mac2gen(const Str255 in, STR_String& out) const;
+       /** The window containing the OpenGL view */
+    NSWindow *m_window;
        
-    WindowRef m_windowRef;
-    CGrafPtr m_grafPtr;
-    AGLContext m_aglCtx;
+       /** The openGL view */
+       NSOpenGLView *m_openGLView; 
+    
+       /** The opgnGL drawing context */
+       NSOpenGLContext *m_openGLContext;
+       
+       //CGrafPtr m_grafPtr;
+    //AGLContext m_aglCtx;
 
        /** The first created OpenGL context (for sharing display lists) */
-       static AGLContext s_firstaglCtx;
+       //static AGLContext s_firstaglCtx;
                
-       Cursor* m_customCursor;
+       NSCursor*       m_customCursor;
 
        GHOST_TabletData m_tablet;
     
     /** When running in full-screen this tells whether to refresh the window. */
     bool m_fullScreenDirty;
-       
-       /** specific MacOs X full screen window setting as we use partially system mechanism 
-           values :      0       not maximizable default
-                             1       normal state
-                                         2               maximized state
-       
-            this will be reworked when rebuilding GHOST carbon to use new OS X apis 
-               in order to be unified with GHOST fullscreen/maximised settings
-                
-                (lukep)
-    **/
-                
-       short mac_windowState;
-       
-
+                        
     /**
      * The width/height of the size rectangle in the lower right corner of a 
      * Mac/Carbon window. This is also the height of the gutter area.
index 092443814b0f08f7d211b7c224c563e8abbd1e5a..4d117d25df36dd0531dc38c14341b7b3fe23692e 100644 (file)
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): none yet.
+ * Contributor(s):     Maarten Gribnau 05/2001
+                                       Damien Plisson 10/2009
  *
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/**
- * Copyright (C) 2001 NaN Technologies B.V.
- * @author     Maarten Gribnau
- * @date       May 10, 2001
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <Carbon/Carbon.h>
+#include <Cocoa/Cocoa.h>
 
 #include "GHOST_WindowCocoa.h"
+#include "GHOST_SystemCocoa.h"
 #include "GHOST_Debug.h"
-
+/*
 AGLContext GHOST_WindowCocoa::s_firstaglCtx = NULL;
 #ifdef GHOST_DRAW_CARBON_GUTTER
 const GHOST_TInt32 GHOST_WindowCocoa::s_sizeRectSize = 16;
@@ -68,7 +60,7 @@ AGL_NONE,
 WindowRef ugly_hack=NULL;
 
 const EventTypeSpec    kWEvents[] = {
-       { kEventClassWindow, kEventWindowZoom },  /* for new zoom behaviour */ 
+       { kEventClassWindow, kEventWindowZoom },  // for new zoom behaviour  
 };
 
 static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) {
@@ -88,9 +80,86 @@ static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event,
 
        }
        return eventNotHandledErr;
+}*/
+
+#pragma mark Cocoa delegate object
+@interface CocoaWindowDelegate : NSObject
+{
+       GHOST_SystemCocoa *systemCocoa;
+       GHOST_WindowCocoa *associatedWindow;
+}
+
+- (void)setSystemAndWindowCocoa:(const GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
+- (void)windowWillClose:(NSNotification *)notification;
+- (void)windowDidBecomeKey:(NSNotification *)notification;
+- (void)windowDidResignKey:(NSNotification *)notification;
+- (void)windowDidUpdate:(NSNotification *)notification;
+- (void)windowDidResize:(NSNotification *)notification;
+@end
+
+@implementation CocoaWindowDelegate : NSObject
+- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
+{
+       systemCocoa = sysCocoa;
+       associatedWindow = winCocoa;
+}
+
+- (void)windowWillClose:(NSNotification *)notification
+{
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow);
+}
+
+- (void)windowDidBecomeKey:(NSNotification *)notification
+{
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow);
+}
+
+- (void)windowDidResignKey:(NSNotification *)notification
+{
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
+}
+
+- (void)windowDidUpdate:(NSNotification *)notification
+{
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow);
 }
 
+- (void)windowDidResize:(NSNotification *)notification
+{
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
+}
+@end
+
+#pragma mark NSOpenGLView subclass
+//We need to subclass it in order to give Cocoa the feeling key events are trapped
+@interface CocoaOpenGLView : NSOpenGLView
+{
+       
+}
+@end
+@implementation CocoaOpenGLView
+
+- (BOOL)acceptsFirstResponder
+{
+    return YES;
+}
+
+//The trick to prevent Cocoa from complaining (beeping)
+- (void)keyDown:(NSEvent *)theEvent
+{}
+
+- (BOOL)isOpaque
+{
+    return YES;
+}
+
+@end
+
+
+#pragma mark initialization / finalization
+
 GHOST_WindowCocoa::GHOST_WindowCocoa(
+       const GHOST_SystemCocoa *systemCocoa,
        const STR_String& title,
        GHOST_TInt32 left,
        GHOST_TInt32 top,
@@ -101,17 +170,13 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
        const bool stereoVisual
 ) :
        GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone),
-       m_windowRef(0),
-       m_grafPtr(0),
-       m_aglCtx(0),
        m_customCursor(0),
        m_fullScreenDirty(false)
 {
-    Str255 title255;
-       OSStatus err;
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        
        //fprintf(stderr," main screen top %i left %i height %i width %i\n", top, left, height, width);
-       
+       /*
        if (state >= GHOST_kWindowState8Normal ) {
                if(state == GHOST_kWindowState8Normal) state= GHOST_kWindowStateNormal;
                else if(state == GHOST_kWindowState8Maximized) state= GHOST_kWindowStateMaximized;
@@ -123,26 +188,77 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
                setMac_windowState(1);
        } else 
                setMac_windowState(0);
-
+*/
        if (state != GHOST_kWindowStateFullScreen) {
-        Rect bnds = { top, left, top+height, left+width };
-        // Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/
-        gen2mac(title, title255);
+               
+               //Creates the window
+               NSRect rect;
+               
+               rect.origin.x = left;
+               rect.origin.y = top;
+               rect.size.width = width;
+               rect.size.height = height;
+               
+               m_window = [[NSWindow alloc] initWithContentRect:rect
+                                                                                          styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
+                                                                                                backing:NSBackingStoreBuffered defer:NO];
+               if (m_window == nil) {
+                       [pool drain];
+                       return;
+               }
+               
+               [m_window setTitle:[NSString stringWithUTF8String:title]];
+               
+                               
+               //Creates the OpenGL View inside the window
+               NSOpenGLPixelFormatAttribute attributes[] =
+               {
+                       NSOpenGLPFADoubleBuffer,
+                       NSOpenGLPFAAccelerated,
+                       NSOpenGLPFAAllowOfflineRenderers,   // NOTE: Needed to connect to secondary GPUs
+                       NSOpenGLPFADepthSize, 32,
+                       0
+               };
+               
+               NSOpenGLPixelFormat *pixelFormat =
+        [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+               
+               m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect
+                                                                                                        pixelFormat:pixelFormat];
+               
+               [pixelFormat release];
+               
+               m_openGLContext = [m_openGLView openGLContext];
+               
+               [m_window setContentView:m_openGLView];
+               [m_window setInitialFirstResponder:m_openGLView];
+               
+               [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window
+               
+               [m_window makeKeyAndOrderFront:nil];
+               
+               setDrawingContextType(type);
+               updateDrawingContext();
+               activateDrawingContext();
+               
+               // Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/
+        /*gen2mac(title, title255);
         
+               
                err =  ::CreateNewWindow( kDocumentWindowClass,
                                                                 kWindowStandardDocumentAttributes+kWindowLiveResizeAttribute,
                                                                 &bnds,
                                                                 &m_windowRef);
                
                if ( err != noErr) {
-                       fprintf(stderr," error creating window %i \n",err);
+                       fprintf(stderr," error creating window %i \n",(int)err);
                } else {
                        
                        ::SetWRefCon(m_windowRef,(SInt32)this);
                        setTitle(title);
                        err = InstallWindowEventHandler (m_windowRef, myWEventHandlerProc, GetEventTypeCount(kWEvents), kWEvents,NULL,NULL); 
                        if ( err != noErr) {
-                               fprintf(stderr," error creating handler %i \n",err);
+                               fprintf(stderr," error creating handler %i \n",(int)err);
                        } else {
                                //      ::TransitionWindow (m_windowRef,kWindowZoomTransitionEffect,kWindowShowTransitionAction,NULL);
                                ::ShowWindow(m_windowRef);
@@ -162,7 +278,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
                        ProcessSerialNumber psn;
                        GetCurrentProcess(&psn);
                        SetFrontProcess(&psn);
-               }
+               }*/
     }
     else {
     /*
@@ -179,12 +295,20 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
             (SInt32)this);                                     // Store a pointer to the class in the refCon
     */
         //GHOST_PRINT("GHOST_WindowCocoa::GHOST_WindowCocoa(): creating full-screen OpenGL context\n");
-        setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);;installDrawingContext(GHOST_kDrawingContextTypeOpenGL);
+        setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);
+               installDrawingContext(GHOST_kDrawingContextTypeOpenGL);
         updateDrawingContext();
-        activateDrawingContext();        
-
-       m_tablet.Active = GHOST_kTabletModeNone;
+        activateDrawingContext();
     }
+       m_tablet.Active = GHOST_kTabletModeNone;
+       
+       CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init];
+       [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
+       [m_window setDelegate:windowDelegate];
+       
+       [m_window setAcceptsMouseMovedEvents:YES];
+       
+       [pool drain];
 }
 
 
@@ -192,21 +316,26 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
 {
        if (m_customCursor) delete m_customCursor;
 
-       if(ugly_hack==m_windowRef) ugly_hack= NULL;
+       /*if(ugly_hack==m_windowRef) ugly_hack= NULL;
        
-       // printf("GHOST_WindowCocoa::~GHOST_WindowCocoa(): removing drawing context\n");
-       if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone);
-    if (m_windowRef) {
-        ::DisposeWindow(m_windowRef);
-               m_windowRef = 0;
+       if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone);*/
+    
+       [m_openGLView release];
+       
+       if (m_window) {
+               [m_window close];
+               [m_window release];
+               m_window = nil;
        }
 }
 
+#pragma mark accessors
+
 bool GHOST_WindowCocoa::getValid() const
 {
     bool valid;
     if (!m_fullScreen) {
-        valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef);
+        valid = (m_window != 0); //&& ::IsValidWindowPtr(m_windowRef);
     }
     else {
         valid = true;
@@ -218,57 +347,73 @@ bool GHOST_WindowCocoa::getValid() const
 void GHOST_WindowCocoa::setTitle(const STR_String& title)
 {
     GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid")
-    Str255 title255;
-    gen2mac(title, title255);
-       ::SetWTitle(m_windowRef, title255);
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+       NSString *windowTitle = [[NSString alloc] initWithUTF8String:title];
+       
+       [m_window setTitle:windowTitle];
+       
+       [windowTitle release];
+       [pool drain];
 }
 
 
 void GHOST_WindowCocoa::getTitle(STR_String& title) const
 {
     GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid")
-    Str255 title255;
-    ::GetWTitle(m_windowRef, title255);
-    mac2gen(title255, title);
+
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+       NSString *windowTitle = [m_window title];
+
+       if (windowTitle != nil) {
+               title = [windowTitle UTF8String];               
+       }
+       
+       [pool drain];
 }
 
 
 void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const
 {
-       OSStatus success;
-       Rect rect;
+       NSRect rect;
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid")
-       success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect);
-       bounds.m_b = rect.bottom;
-       bounds.m_l = rect.left;
-       bounds.m_r = rect.right;
-       bounds.m_t = rect.top;
+
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       
+       NSRect screenSize = [[m_window screen] visibleFrame];
+
+       rect = [m_window frame];
+
+       bounds.m_b = screenSize.size.height - (rect.origin.y -screenSize.origin.y);
+       bounds.m_l = rect.origin.x -screenSize.origin.x;
+       bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width;
+       bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y);
+       
+       [pool drain];
 }
 
 
 void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
 {
-       Rect rect;
+       NSRect rect;
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid")
-       //::GetPortBounds(m_grafPtr, &rect);
-       ::GetWindowBounds(m_windowRef, kWindowContentRgn, &rect);
+       
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       NSRect screenSize = [[m_window screen] visibleFrame];
 
-       bounds.m_b = rect.bottom;
-       bounds.m_l = rect.left;
-       bounds.m_r = rect.right;
-       bounds.m_t = rect.top;
+       //Max window contents as screen size (excluding title bar...)
+       NSRect contentRect = [NSWindow contentRectForFrameRect:screenSize
+                                                                                                styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
 
-       // Subtract gutter height from bottom
-#ifdef GHOST_DRAW_CARBON_GUTTER
-       if ((bounds.m_b - bounds.m_t) > s_sizeRectSize)
-       {
-               bounds.m_b -= s_sizeRectSize;
-       }
-       else
-       {
-               bounds.m_t = bounds.m_b;
-       }
-#endif //GHOST_DRAW_CARBON_GUTTER
+       rect = [m_window contentRectForFrameRect:[m_window frame]];
+       
+       bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y);
+       bounds.m_l = rect.origin.x -contentRect.origin.x;
+       bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width;
+       bounds.m_t = contentRect.size.height - (rect.origin.y + rect.size.height -contentRect.origin.y);
+       
+       [pool drain];
 }
 
 
@@ -278,7 +423,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
        GHOST_Rect cBnds, wBnds;
        getClientBounds(cBnds);
        if (((GHOST_TUns32)cBnds.getWidth()) != width) {
-               ::SizeWindow(m_windowRef, width, cBnds.getHeight(), true);
+               NSSize size;
+               size.width=width;
+               size.height=cBnds.getHeight();
+               [m_window setContentSize:size];
        }
        return GHOST_kSuccess;
 }
@@ -289,15 +437,12 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")
        GHOST_Rect cBnds, wBnds;
        getClientBounds(cBnds);
-#ifdef GHOST_DRAW_CARBON_GUTTER
-       if (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize) {
-               ::SizeWindow(m_windowRef, cBnds.getWidth(), height+s_sizeRectSize, true);
-       }
-#else //GHOST_DRAW_CARBON_GUTTER
        if (((GHOST_TUns32)cBnds.getHeight()) != height) {
-               ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true);
+               NSSize size;
+               size.width=cBnds.getWidth();
+               size.height=height;
+               [m_window setContentSize:size];
        }
-#endif //GHOST_DRAW_CARBON_GUTTER
        return GHOST_kSuccess;
 }
 
@@ -307,17 +452,13 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")
        GHOST_Rect cBnds, wBnds;
        getClientBounds(cBnds);
-#ifdef GHOST_DRAW_CARBON_GUTTER
-       if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
-           (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize)) {
-               ::SizeWindow(m_windowRef, width, height+s_sizeRectSize, true);
-       }
-#else //GHOST_DRAW_CARBON_GUTTER
        if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
            (((GHOST_TUns32)cBnds.getHeight()) != height)) {
-               ::SizeWindow(m_windowRef, width, height, true);
+               NSSize size;
+               size.width=width;
+               size.height=height;
+               [m_window setContentSize:size];
        }
-#endif //GHOST_DRAW_CARBON_GUTTER
        return GHOST_kSuccess;
 }
 
@@ -325,16 +466,18 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32
 GHOST_TWindowState GHOST_WindowCocoa::getState() const
 {
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid")
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        GHOST_TWindowState state;
-       if (::IsWindowVisible(m_windowRef) == false) {
+       if ([m_window isMiniaturized]) {
                state = GHOST_kWindowStateMinimized;
        }
-       else if (::IsWindowInStandardState(m_windowRef, nil, nil)) {
+       else if ([m_window isZoomed]) {
                state = GHOST_kWindowStateMaximized;
        }
        else {
                state = GHOST_kWindowStateNormal;
        }
+       [pool drain];
        return state;
 }
 
@@ -342,32 +485,34 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const
 void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
 {
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid")
-       Point point;
-       point.h = inX;
-       point.v = inY;
-    GrafPtr oldPort;
-    ::GetPort(&oldPort);
-    ::SetPort(m_grafPtr);
-       ::GlobalToLocal(&point);
-    ::SetPort(oldPort);
-       outX = point.h;
-       outY = point.v;
+       
+       NSPoint screenCoord;
+       NSPoint baseCoord;
+       
+       screenCoord.x = inX;
+       screenCoord.y = inY;
+       
+       baseCoord = [m_window convertScreenToBase:screenCoord];
+       
+       outX = baseCoord.x;
+       outY = baseCoord.y;
 }
 
 
 void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
 {
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid")
-       Point point;
-       point.h = inX;
-       point.v = inY;
-    GrafPtr oldPort;
-    ::GetPort(&oldPort);
-    ::SetPort(m_grafPtr);
-       ::LocalToGlobal(&point);
-    ::SetPort(oldPort);
-       outX = point.h;
-       outY = point.v;
+       
+       NSPoint screenCoord;
+       NSPoint baseCoord;
+       
+       baseCoord.x = inX;
+       baseCoord.y = inY;
+       
+       screenCoord = [m_window convertBaseToScreen:baseCoord];
+       
+       outX = screenCoord.x;
+       outY = screenCoord.y;
 }
 
 
@@ -376,12 +521,17 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid")
     switch (state) {
        case GHOST_kWindowStateMinimized:
-            ::HideWindow(m_windowRef);
+            [m_window miniaturize:nil];
             break;
        case GHOST_kWindowStateMaximized:
+                       [m_window zoom:nil];
+                       break;
        case GHOST_kWindowStateNormal:
         default:
-            ::ShowWindow(m_windowRef);
+            if ([m_window isMiniaturized])
+                               [m_window deminiaturize:nil];
+                       else if ([m_window isZoomed])
+                               [m_window zoom:nil];
             break;
     }
     return GHOST_kSuccess;
@@ -389,11 +539,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
 
 GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges)
 {
-       if (isUnsavedChanges) {
-               SetWindowModified(m_windowRef, 1);
-       } else {
-               SetWindowModified(m_windowRef, 0);
-       }
+       [m_window setDocumentEdited:isUnsavedChanges];
        
        return GHOST_Window::setModifiedState(isUnsavedChanges);
 }
@@ -404,61 +550,45 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
 {
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid")
     if (order == GHOST_kWindowOrderTop) {
-        //::BringToFront(m_windowRef); is wrong, front window should be active for input too
-               ::SelectWindow(m_windowRef);
+               [m_window orderFront:nil];
     }
     else {
-               /* doesnt work if you do this with a mouseclick */
-        ::SendBehind(m_windowRef, nil);
+               [m_window orderBack:nil];
     }
     return GHOST_kSuccess;
 }
 
+#pragma mark Drawing context
+
 /*#define  WAIT_FOR_VSYNC 1*/
-#ifdef WAIT_FOR_VSYNC
-#include <OpenGL/OpenGL.h>
-#endif
 
 GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
 {
-#ifdef WAIT_FOR_VSYNC
-/* wait for vsync, to avoid tearing artifacts */
-long VBL = 1;
-CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL);
-#endif
-
-    GHOST_TSuccess succeeded = GHOST_kSuccess;
     if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
-        if (m_aglCtx) {
-            ::aglSwapBuffers(m_aglCtx);
-        }
-        else {
-            succeeded = GHOST_kFailure;
+        if (m_openGLContext != nil) {
+                       [m_openGLContext flushBuffer];
+            return GHOST_kSuccess;
         }
     }
-    return succeeded;
+    return GHOST_kFailure;
 }
 
 GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
 {
-       GHOST_TSuccess succeeded = GHOST_kSuccess;
        if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
-               if (m_aglCtx) {
-                       ::aglUpdateContext(m_aglCtx);
-               }
-               else {
-                       succeeded = GHOST_kFailure;
+               if (m_openGLContext != nil) {
+                       [m_openGLContext update];
+                       return GHOST_kSuccess;
                }
        }
-       return succeeded;
+       return GHOST_kFailure;
 }
 
 GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
 {
-       GHOST_TSuccess succeeded = GHOST_kSuccess;
        if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
-               if (m_aglCtx) {
-                       ::aglSetCurrentContext(m_aglCtx);
+               if (m_openGLContext != nil) {
+                       [m_openGLContext makeCurrentContext];
 #ifdef GHOST_DRAW_CARBON_GUTTER
                        // Restrict drawing to non-gutter area
                        ::aglEnable(m_aglCtx, AGL_BUFFER_RECT);
@@ -473,23 +603,44 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
                        };
                        GLboolean result = ::aglSetInteger(m_aglCtx, AGL_BUFFER_RECT, b);
 #endif //GHOST_DRAW_CARBON_GUTTER
-               }
-               else {
-                       succeeded = GHOST_kFailure;
+                       return GHOST_kSuccess;
                }
        }
-       return succeeded;
+       return GHOST_kFailure;
 }
 
 
 GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
 {
        GHOST_TSuccess success = GHOST_kFailure;
+       
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       
+       NSOpenGLPixelFormat *pixelFormat;
+       NSOpenGLContext *tmpOpenGLContext;
+       
        switch (type) {
                case GHOST_kDrawingContextTypeOpenGL:
-                       {
                        if (!getValid()) break;
-            
+                                       
+                       if(!m_fullScreen)
+                       {
+                               pixelFormat = [m_openGLView pixelFormat];
+                               tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
+                                                                                                                         shareContext:m_openGLContext];
+                               if (tmpOpenGLContext == nil)
+                                       break;
+#ifdef WAIT_FOR_VSYNC
+                               /* wait for vsync, to avoid tearing artifacts */
+                               [tmpOpenGLContext setValues:1 forParameter:NSOpenGLCPSwapInterval];
+#endif
+                               [m_openGLView setOpenGLContext:tmpOpenGLContext];
+                               [tmpOpenGLContext setView:m_openGLView];
+                               
+                               //[m_openGLContext release];
+                               m_openGLContext = tmpOpenGLContext;
+                       }
+                       /*      
             AGLPixelFormat pixelFormat;
             if (!m_fullScreen) {
                 pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow);
@@ -507,17 +658,16 @@ GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,s
                 //GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): created OpenGL context\n");
                 //::CGGetActiveDisplayList(0, NULL, &m_numDisplays)
                 success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
-                /*
+                
                 if (success == GHOST_kSuccess) {
                     GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL succeeded\n");
                 }
                 else {
                     GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL failed\n");
                 }
-                */
+                
             }
-            ::aglDestroyPixelFormat(pixelFormat);
-                       }
+            ::aglDestroyPixelFormat(pixelFormat);*/
                        break;
                
                case GHOST_kDrawingContextTypeNone:
@@ -527,41 +677,34 @@ GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,s
                default:
                        break;
        }
+       [pool drain];
        return success;
 }
 
 
 GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext()
 {
-       GHOST_TSuccess success = GHOST_kFailure;
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        switch (m_drawingContextType) {
                case GHOST_kDrawingContextTypeOpenGL:
-                       if (m_aglCtx) {
-                aglSetCurrentContext(NULL);
-                aglSetDrawable(m_aglCtx, NULL);
-                //aglDestroyContext(m_aglCtx);
-                               if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL;
-                               success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
-                               m_aglCtx = 0;
-                       }
-                       break;
+                       [m_openGLView clearGLContext];
+                       return GHOST_kSuccess;
                case GHOST_kDrawingContextTypeNone:
-                       success = GHOST_kSuccess;
+                       return GHOST_kSuccess;
                        break;
                default:
-                       break;
+                       return GHOST_kFailure;
        }
-       return success;
+       [pool drain];
 }
 
 
 GHOST_TSuccess GHOST_WindowCocoa::invalidate()
 {
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid")
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     if (!m_fullScreen) {
-        Rect rect;
-        ::GetPortBounds(m_grafPtr, &rect);
-        ::InvalWindowRect(m_windowRef, &rect);
+               [m_openGLView setNeedsDisplay:YES];
     }
     else {
         //EventRef event;
@@ -574,77 +717,81 @@ GHOST_TSuccess GHOST_WindowCocoa::invalidate()
         //GHOST_PRINT("GHOST_WindowCocoa::invalidate(): added event to queue " << status << " \n");
         m_fullScreenDirty = true;
     }
+       [pool drain];
        return GHOST_kSuccess;
 }
 
-
-void GHOST_WindowCocoa::gen2mac(const STR_String& in, Str255 out) const
-{
-       STR_String tempStr  = in;
-       int num = tempStr.Length();
-       if (num > 255) num = 255;
-       ::memcpy(out+1, tempStr.Ptr(), num);
-       out[0] = num;
-}
-
-
-void GHOST_WindowCocoa::mac2gen(const Str255 in, STR_String& out) const
-{
-       char tmp[256];
-       ::memcpy(tmp, in+1, in[0]);
-       tmp[in[0]] = '\0';
-       out = tmp;
-}
+#pragma mark Cursor handling
 
 void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
 {
        static bool systemCursorVisible = true;
        
+       NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
+
+       NSCursor *tmpCursor =nil;
+       
        if (visible != systemCursorVisible) {
                if (visible) {
-                       ::ShowCursor();
+                       [NSCursor unhide];
                        systemCursorVisible = true;
                }
                else {
-                       ::HideCursor();
+                       [NSCursor hide];
                        systemCursorVisible = false;
                }
        }
 
        if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
-               ::SetCursor( m_customCursor );
+               tmpCursor = m_customCursor;
        } else {
-               int carbon_cursor;
-       
-#define GCMAP(ghostCursor, carbonCursor)       case ghostCursor: carbon_cursor = carbonCursor; break
                switch (cursor) {
-               default:
-               GCMAP( GHOST_kStandardCursorDefault,                            kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorRightArrow,                         kThemeAliasArrowCursor);
-               GCMAP( GHOST_kStandardCursorLeftArrow,                          kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorInfo,                                       kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorDestroy,                            kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorHelp,                               kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorCycle,                                      kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorSpray,                                      kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorWait,                                       kThemeWatchCursor);
-               GCMAP( GHOST_kStandardCursorText,                                       kThemeIBeamCursor);
-               GCMAP( GHOST_kStandardCursorCrosshair,                          kThemeCrossCursor);
-               GCMAP( GHOST_kStandardCursorUpDown,                                     kThemeClosedHandCursor);
-               GCMAP( GHOST_kStandardCursorLeftRight,                          kThemeClosedHandCursor);
-               GCMAP( GHOST_kStandardCursorTopSide,                            kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorBottomSide,                         kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorLeftSide,                           kThemeResizeLeftCursor);
-               GCMAP( GHOST_kStandardCursorRightSide,                          kThemeResizeRightCursor);
-               GCMAP( GHOST_kStandardCursorTopLeftCorner,                      kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorTopRightCorner,                     kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorBottomRightCorner,          kThemeArrowCursor);
-               GCMAP( GHOST_kStandardCursorBottomLeftCorner,           kThemeArrowCursor);
+                       case GHOST_kStandardCursorDestroy:
+                               tmpCursor = [NSCursor disappearingItemCursor];
+                               break;
+                       case GHOST_kStandardCursorText:
+                               tmpCursor = [NSCursor IBeamCursor];
+                               break;
+                       case GHOST_kStandardCursorCrosshair:
+                               tmpCursor = [NSCursor crosshairCursor];
+                               break;
+                       case GHOST_kStandardCursorUpDown:
+                               tmpCursor = [NSCursor resizeUpDownCursor];
+                               break;
+                       case GHOST_kStandardCursorLeftRight:
+                               tmpCursor = [NSCursor resizeLeftRightCursor];
+                               break;
+                       case GHOST_kStandardCursorTopSide:
+                               tmpCursor = [NSCursor resizeUpCursor];
+                               break;
+                       case GHOST_kStandardCursorBottomSide:
+                               tmpCursor = [NSCursor resizeDownCursor];
+                               break;
+                       case GHOST_kStandardCursorLeftSide:
+                               tmpCursor = [NSCursor resizeLeftCursor];
+                               break;
+                       case GHOST_kStandardCursorRightSide:
+                               tmpCursor = [NSCursor resizeRightCursor];
+                               break;
+                       case GHOST_kStandardCursorRightArrow:
+                       case GHOST_kStandardCursorInfo:
+                       case GHOST_kStandardCursorLeftArrow:
+                       case GHOST_kStandardCursorHelp:
+                       case GHOST_kStandardCursorCycle:
+                       case GHOST_kStandardCursorSpray:
+                       case GHOST_kStandardCursorWait:
+                       case GHOST_kStandardCursorTopLeftCorner:
+                       case GHOST_kStandardCursorTopRightCorner:
+                       case GHOST_kStandardCursorBottomRightCorner:
+                       case GHOST_kStandardCursorBottomLeftCorner:
+                       case GHOST_kStandardCursorDefault:
+                       default:
+                               tmpCursor = [NSCursor arrowCursor];
+                               break;
                };
-#undef GCMAP
-
-               ::SetThemeCursor(carbon_cursor);
        }
+       [tmpCursor set];
+       [pool drain];
 }
 
 
@@ -656,7 +803,7 @@ bool GHOST_WindowCocoa::getFullScreenDirty()
 
 GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
 {
-       if (::FrontWindow() == m_windowRef) {
+       if ([m_window isVisible]) {
                loadCursor(visible, getCursorShape());
        }
        
@@ -666,11 +813,11 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
 GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
 {
        if (m_customCursor) {
-               delete m_customCursor;
-               m_customCursor = 0;
+               [m_customCursor release];
+               m_customCursor = nil;
        }
 
-       if (::FrontWindow() == m_windowRef) {
+       if ([m_window isVisible]) {
                loadCursor(getCursorVisibility(), shape);
        }
        
@@ -703,14 +850,15 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
                                        int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color)
 {
        int y;
+       NSPoint hotSpotPoint;
+       NSImage *cursorImage;
        
        if (m_customCursor) {
-               delete m_customCursor;
-               m_customCursor = 0;
+               [m_customCursor release];
+               m_customCursor = nil;
        }
-       
-       m_customCursor = new Cursor;
-       if (!m_customCursor) return GHOST_kFailure;
+       /*TODO: implement this (but unused inproject at present)
+       cursorImage = [[NSImage alloc] initWithData:bitmap];
        
        for (y=0; y<16; y++) {
 #if !defined(__LITTLE_ENDIAN__)
@@ -723,13 +871,21 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
                        
        }
        
-       m_customCursor->hotSpot.h = hotX;
-       m_customCursor->hotSpot.v = hotY;
        
-       if (::FrontWindow() == m_windowRef) {
+       hotSpotPoint.x = hotX;
+       hotSpotPoint.y = hotY;
+       
+       m_customCursor = [[NSCursor alloc] initWithImage:cursorImage
+                                                                foregroundColorHint:<#(NSColor *)fg#>
+                                                                backgroundColorHint:<#(NSColor *)bg#>
+                                                                                        hotSpot:hotSpotPoint];
+       
+       [cursorImage release];
+       
+       if ([m_window isVisible]) {
                loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
        }
-       
+       */
        return GHOST_kSuccess;
 }
 
@@ -739,7 +895,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 bitmap[
        return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1);
 }
 
+#pragma mark Old carbon stuff to remove
 
+#if 0
 void GHOST_WindowCocoa::setMac_windowState(short value)
 {
        mac_windowState = value;
@@ -749,3 +907,23 @@ short GHOST_WindowCocoa::getMac_windowState()
 {
        return mac_windowState;
 }
+
+void GHOST_WindowCocoa::gen2mac(const STR_String& in, Str255 out) const
+{
+       STR_String tempStr  = in;
+       int num = tempStr.Length();
+       if (num > 255) num = 255;
+       ::memcpy(out+1, tempStr.Ptr(), num);
+       out[0] = num;
+}
+
+
+void GHOST_WindowCocoa::mac2gen(const Str255 in, STR_String& out) const
+{
+       char tmp[256];
+       ::memcpy(tmp, in+1, in[0]);
+       tmp[in[0]] = '\0';
+       out = tmp;
+}
+
+#endif
\ No newline at end of file
index 80878cf6884aa3245676085d17a41548c553989b..c15106e21c9d87805548f256641c5e5eeff50d2d 100644 (file)
@@ -1569,14 +1569,18 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata)
                case GHOST_kEventCursorMove: {
                        if(win->active) {
                                GHOST_TEventCursorData *cd= customdata;
+#if defined(__APPLE__) && defined(GHOST_COCOA)
+                               //Cocoa already uses coordinates with y=0 at bottom, and returns inwindow coordinates on mouse moved event
+                               event.type= MOUSEMOVE;
+                               event.x= evt->x = cd->x;
+                               event.y = evt->y = cd->y;
+#else
                                int cx, cy;
-
                                GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
-                               
                                event.type= MOUSEMOVE;
                                event.x= evt->x= cx;
                                event.y= evt->y= (win->sizey-1) - cy;
-                               
+#endif
                                update_tablet_data(win, &event);
                                wm_event_add(win, &event);
                        }
index 466e5868723e8efee82c2db34c39358bfae7e043..e3cfb9ad60df51fbacf099e3a7254123c849bd86 100644 (file)
@@ -608,7 +608,13 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
                                
                                GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy);
                                win->eventstate->x= cx;
+
+#if defined(__APPLE__) && defined(GHOST_COCOA)
+                               //Cocoa already uses coordinates with y=0 at bottom
+                               win->eventstate->y= cy;
+#else
                                win->eventstate->y= (win->sizey-1) - cy;
+#endif
                                
                                wm_window_make_drawable(C, win);
                                break;