Fix OS X memory leak prints when starting blender:
[blender-staging.git] / intern / ghost / intern / GHOST_WindowCocoa.mm
index fd68b6200eefef220e1e276649f620a8781207bb..83f86840eb4b0b61f978ef69ac4e95478a9bc707 100644 (file)
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 #include <Carbon/Carbon.h>
 #endif
 
+#include <OpenGL/gl.h>
+/***** Multithreaded opengl code : uncomment for enabling
+#include <OpenGL/OpenGL.h>
+*/
+
 #include "GHOST_WindowCocoa.h"
 #include "GHOST_SystemCocoa.h"
 #include "GHOST_Debug.h"
 
 
-// Pixel Format Attributes for the windowed NSOpenGLContext
-static const NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
-{
-       NSOpenGLPFADoubleBuffer,
-       NSOpenGLPFAAccelerated,
-       NSOpenGLPFAAllowOfflineRenderers,   // NOTE: Needed to connect to secondary GPUs
-       NSOpenGLPFADepthSize, 32,
-       0
-};
-
 #pragma mark Cocoa window delegate object
-
+/* live resize ugly patch
+extern "C" {
+       struct bContext;
+       typedef struct bContext bContext;
+       bContext* ghostC;
+       extern int wm_window_timer(const bContext *C);
+       extern void wm_window_process_events(const bContext *C);
+       extern void wm_event_do_handlers(bContext *C);
+       extern void wm_event_do_notifiers(bContext *C);
+       extern void wm_draw_update(bContext *C);
+};*/
 @interface CocoaWindowDelegate : NSObject
+#ifdef MAC_OS_X_VERSION_10_6
+<NSWindowDelegate>
+#endif
 {
        GHOST_SystemCocoa *systemCocoa;
        GHOST_WindowCocoa *associatedWindow;
 }
 
-- (void)setSystemAndWindowCocoa:(const GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
+- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
 - (void)windowWillClose:(NSNotification *)notification;
 - (void)windowDidBecomeKey:(NSNotification *)notification;
 - (void)windowDidResignKey:(NSNotification *)notification;
-- (void)windowDidUpdate:(NSNotification *)notification;
+- (void)windowDidExpose:(NSNotification *)notification;
 - (void)windowDidResize:(NSNotification *)notification;
+- (void)windowDidMove:(NSNotification *)notification;
+- (void)windowWillMove:(NSNotification *)notification;
 @end
 
 @implementation CocoaWindowDelegate : NSObject
@@ -84,20 +95,42 @@ static const NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
 
 - (void)windowDidResignKey:(NSNotification *)notification
 {
-       //The window is no more key when its own view becomes fullscreen
-       //but ghost doesn't know the view/window difference, so hide this fact
-       if (associatedWindow->getState() != GHOST_kWindowStateFullScreen)
-               systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
 }
 
-- (void)windowDidUpdate:(NSNotification *)notification
+- (void)windowDidExpose:(NSNotification *)notification
 {
        systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow);
 }
 
+- (void)windowDidMove:(NSNotification *)notification
+{
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow);
+}
+
+- (void)windowWillMove:(NSNotification *)notification
+{
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow);
+}
+
 - (void)windowDidResize:(NSNotification *)notification
 {
-       systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
+#ifdef MAC_OS_X_VERSION_10_6
+       //if (![[notification object] inLiveResize]) {
+               //Send event only once, at end of resize operation (when user has released mouse button)
+#endif
+               systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
+#ifdef MAC_OS_X_VERSION_10_6
+       //}
+#endif
+       /* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run
+        if ([[notification object] inLiveResize]) {
+               systemCocoa->dispatchEvents();
+               wm_window_timer(ghostC);
+               wm_event_do_handlers(ghostC);
+               wm_event_do_notifiers(ghostC);
+               wm_draw_update(ghostC);
+       }*/
 }
 @end
 
@@ -105,18 +138,96 @@ static const NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
 //We need to subclass it to tell that even borderless (fullscreen), it can become key (receive user events)
 @interface CocoaWindow: NSWindow
 {
-
+       GHOST_SystemCocoa *systemCocoa;
+       GHOST_WindowCocoa *associatedWindow;
+       GHOST_TDragnDropTypes m_draggedObjectType;
 }
--(BOOL)canBecomeKeyWindow;
-
+- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
 @end
 @implementation CocoaWindow
+- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
+{
+       systemCocoa = sysCocoa;
+       associatedWindow = winCocoa;
+}
 
 -(BOOL)canBecomeKeyWindow
 {
        return YES;
 }
 
+//The drag'n'drop dragging destination methods
+- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
+{
+       NSPoint mouseLocation = [sender draggingLocation];
+       NSPasteboard *draggingPBoard = [sender draggingPasteboard];
+       
+       if ([[draggingPBoard types] containsObject:NSTIFFPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeBitmap;
+       else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeFilenames;
+       else if ([[draggingPBoard types] containsObject:NSStringPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeString;
+       else return NSDragOperationNone;
+       
+       associatedWindow->setAcceptDragOperation(TRUE); //Drag operation is accepted by default
+       systemCocoa->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil);
+       return NSDragOperationCopy;
+}
+
+- (BOOL)wantsPeriodicDraggingUpdates
+{
+       return NO; //No need to overflow blender event queue. Events shall be sent only on changes
+}
+
+- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
+{
+       NSPoint mouseLocation = [sender draggingLocation];
+       
+       systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil);
+       return associatedWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone;
+}
+
+- (void)draggingExited:(id < NSDraggingInfo >)sender
+{
+       systemCocoa->handleDraggingEvent(GHOST_kEventDraggingExited, m_draggedObjectType, associatedWindow, 0, 0, nil);
+       m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
+}
+
+- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
+{
+       if (associatedWindow->canAcceptDragOperation())
+               return YES;
+       else
+               return NO;
+}
+
+- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender
+{
+       NSPoint mouseLocation = [sender draggingLocation];
+       NSPasteboard *draggingPBoard = [sender draggingPasteboard];
+       NSImage *droppedImg;
+       id data;
+       
+       switch (m_draggedObjectType) {
+               case GHOST_kDragnDropTypeBitmap:
+                       if([NSImage canInitWithPasteboard:draggingPBoard]) {
+                               droppedImg = [[NSImage alloc]initWithPasteboard:draggingPBoard];
+                               data = droppedImg; //[draggingPBoard dataForType:NSTIFFPboardType];
+                       }
+                       else return NO;
+                       break;
+               case GHOST_kDragnDropTypeFilenames:
+                       data = [draggingPBoard propertyListForType:NSFilenamesPboardType];
+                       break;
+               case GHOST_kDragnDropTypeString:
+                       data = [draggingPBoard stringForType:NSStringPboardType];
+                       break;
+               default:
+                       return NO;
+                       break;
+       }
+       systemCocoa->handleDraggingEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, (void*)data);
+       return YES;
+}
+
 @end
 
 
@@ -125,7 +236,6 @@ static const NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
 //We need to subclass it in order to give Cocoa the feeling key events are trapped
 @interface CocoaOpenGLView : NSOpenGLView
 {
-       
 }
 @end
 @implementation CocoaOpenGLView
@@ -139,6 +249,32 @@ static const NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
 - (void)keyDown:(NSEvent *)theEvent
 {}
 
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+//Cmd+key are handled differently before 10.5
+- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
+{
+       NSString *chars = [theEvent charactersIgnoringModifiers];
+       
+       if ([chars length] <1) 
+               return NO;
+       
+       //Let cocoa handle menu shortcuts
+       switch ([chars characterAtIndex:0]) {
+               case 'q':
+               case 'w':
+               case 'h':
+               case 'm':
+               case '<':
+               case '>':
+               case '~':
+               case '`':
+                       return NO;
+               default:
+                       return YES;
+       }
+}
+#endif
+
 - (BOOL)isOpaque
 {
     return YES;
@@ -160,11 +296,15 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
        GHOST_TUns32 height,
        GHOST_TWindowState state,
        GHOST_TDrawingContextType type,
-       const bool stereoVisual
+       const bool stereoVisual, const GHOST_TUns16 numOfAASamples
 ) :
-       GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone),
+       GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples),
        m_customCursor(0)
 {
+       NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40];
+       NSOpenGLPixelFormat *pixelFormat = nil;
+       int i;
+               
        m_systemCocoa = systemCocoa;
        m_fullScreen = false;
        
@@ -173,6 +313,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
 
        //Creates the window
        NSRect rect;
+       NSSize  minSize;
        
        rect.origin.x = left;
        rect.origin.y = top;
@@ -187,13 +328,84 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
                return;
        }
        
-       [m_window setTitle:[NSString stringWithUTF8String:title]];
+       [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
        
-                       
-       //Creates the OpenGL View inside the window
-       NSOpenGLPixelFormat *pixelFormat =
-       [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
+       //Forbid to resize the window below the blender defined minimum one
+       minSize.width = 320;
+       minSize.height = 240;
+       [m_window setContentMinSize:minSize];
+       
+       setTitle(title);
+       
+       
+       // Pixel Format Attributes for the windowed NSOpenGLContext
+       i=0;
+       pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
+       
+       // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer
+       // needed for 'Draw Overlap' drawing method
+       pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; 
+       
+       pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
+       //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,;   // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
+
+       pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
+       pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
        
+       
+       if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
+       
+       if (numOfAASamples>0) {
+               // Multisample anti-aliasing
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample;
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers;
+               pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1;
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFASamples;
+               pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) numOfAASamples;
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFANoRecovery;
+       }
+       
+       pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
+       
+       pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
+       
+       
+       //Fall back to no multisampling if Antialiasing init failed
+       if (pixelFormat == nil) {
+               i=0;
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
+               
+               // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer
+               // needed for 'Draw Overlap' drawing method
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore;
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
+               //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,;   // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
+               pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
+               
+               if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
+               
+               pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
+               
+               pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
+               
+       }
+       
+       if (numOfAASamples>0) { //Set m_numOfAASamples to the actual value
+               GLint gli;
+               [pixelFormat getValues:&gli forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
+               if (m_numOfAASamples != (GHOST_TUns16)gli) {
+                       m_numOfAASamples = (GHOST_TUns16)gli;
+                       printf("GHOST_Window could be created with anti-aliasing of only %i samples\n",m_numOfAASamples);
+               }
+       }
+               
+       //Creates the OpenGL View inside the window
        m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect
                                                                                                 pixelFormat:pixelFormat];
        
@@ -220,6 +432,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
        
        [m_window setAcceptsMouseMovedEvents:YES];
        
+       [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
+                                                                                 NSStringPboardType, NSTIFFPboardType, nil]];
+                                                                                 
        if (state == GHOST_kWindowStateFullScreen)
                setState(GHOST_kWindowStateFullScreen);
                
@@ -253,16 +468,13 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
 
 bool GHOST_WindowCocoa::getValid() const
 {
-    bool valid;
-    if (!m_fullScreen) {
-        valid = (m_window != 0); //&& ::IsValidWindowPtr(m_windowRef);
-    }
-    else {
-        valid = true;
-    }
-    return valid;
+       return (m_window != 0);
 }
 
+void* GHOST_WindowCocoa::getOSWindow() const
+{
+       return (void*)m_window;
+}
 
 void GHOST_WindowCocoa::setTitle(const STR_String& title)
 {
@@ -271,7 +483,38 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title)
 
        NSString *windowTitle = [[NSString alloc] initWithUTF8String:title];
        
-       [m_window setTitle:windowTitle];
+       //Set associated file if applicable
+       if ([windowTitle hasPrefix:@"Blender"])
+       {
+               NSRange fileStrRange;
+               NSString *associatedFileName;
+               int len;
+               
+               fileStrRange.location = [windowTitle rangeOfString:@"["].location+1;
+               len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location;
+       
+               if (len >0)
+               {
+                       fileStrRange.length = len;
+                       associatedFileName = [windowTitle substringWithRange:fileStrRange];
+                       @try {
+                               [m_window setRepresentedFilename:associatedFileName];
+                       }
+                       @catch (NSException * e) {
+                               printf("\nInvalid file path given in window title");
+                       }
+                       [m_window setTitle:[associatedFileName lastPathComponent]];
+               }
+               else {
+                       [m_window setTitle:windowTitle];
+                       [m_window setRepresentedFilename:@""];
+               }
+
+       } else {
+               [m_window setTitle:windowTitle];
+               [m_window setRepresentedFilename:@""];
+       }
+
        
        [windowTitle release];
        [pool drain];
@@ -351,6 +594,7 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
 GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
 {
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid")
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        GHOST_Rect cBnds, wBnds;
        getClientBounds(cBnds);
        if (((GHOST_TUns32)cBnds.getWidth()) != width) {
@@ -359,6 +603,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
                size.height=cBnds.getHeight();
                [m_window setContentSize:size];
        }
+       [pool drain];
        return GHOST_kSuccess;
 }
 
@@ -366,6 +611,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
 GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
 {
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        GHOST_Rect cBnds, wBnds;
        getClientBounds(cBnds);
        if (((GHOST_TUns32)cBnds.getHeight()) != height) {
@@ -374,6 +620,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
                size.height=height;
                [m_window setContentSize:size];
        }
+       [pool drain];
        return GHOST_kSuccess;
 }
 
@@ -381,6 +628,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
 GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
 {
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        GHOST_Rect cBnds, wBnds;
        getClientBounds(cBnds);
        if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
@@ -390,6 +638,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32
                size.height=height;
                [m_window setContentSize:size];
        }
+       [pool drain];
        return GHOST_kSuccess;
 }
 
@@ -449,6 +698,13 @@ void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST
        outY = screenCoord.y;
 }
 
+
+NSScreen* GHOST_WindowCocoa::getScreen()
+{
+       return [m_window screen];
+}
+
+
 /**
  * @note Fullscreen switch is not actual fullscreen with display capture. As this capture removes all OS X window manager features.
  * Instead, the menu bar and the dock are hidden, and the window is made borderless and enlarged.
@@ -477,17 +733,18 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
 #ifdef MAC_OS_X_VERSION_10_6
                                //10.6 provides Cocoa functions to autoshow menu bar, and to change a window style
                                //Hide menu & dock if needed
-                               if ([[m_window screen] isEqual:[NSScreen mainScreen]])
+                               if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]])
                                {
                                        [NSApp setPresentationOptions:(NSApplicationPresentationHideDock | NSApplicationPresentationAutoHideMenuBar)];
                                }
                                //Make window borderless and enlarge it
                                [m_window setStyleMask:NSBorderlessWindowMask];
                                [m_window setFrame:[[m_window screen] frame] display:YES];
+                               [m_window makeFirstResponder:m_openGLView];
 #else
                                //With 10.5, we need to create a new window to change its style to borderless
                                //Hide menu & dock if needed
-                               if ([[m_window screen] isEqual:[NSScreen mainScreen]])
+                               if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]])
                                {
                                        //Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:NO];
                                        //One of the very few 64bit compatible Carbon function
@@ -501,7 +758,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
                                                                                  defer:YES];
                                //Copy current window parameters
                                [tmpWindow setTitle:[m_window title]];
-                               [tmpWindow setRepresentedURL:[m_window representedURL]];
+                               [tmpWindow setRepresentedFilename:[m_window representedFilename]];
                                [tmpWindow setReleasedWhenClosed:NO];
                                [tmpWindow setAcceptsMouseMovedEvents:YES];
                                [tmpWindow setDelegate:[m_window delegate]];
@@ -526,9 +783,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
                        break;
                case GHOST_kWindowStateNormal:
         default:
+                       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
                        if (m_fullScreen)
                        {
-                               NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
                                m_fullScreen = false;
 
                                //Exit fullscreen
@@ -541,6 +798,8 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
                                //Make window normal and resize it
                                [m_window setStyleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
                                [m_window setFrame:[[m_window screen] visibleFrame] display:YES];
+                               //TODO for 10.6 only : window title is forgotten after the style change
+                               [m_window makeFirstResponder:m_openGLView];
 #else
                                //With 10.5, we need to create a new window to change its style to borderless
                                //Show menu & dock if needed
@@ -557,7 +816,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
                                                                                                                defer:YES];
                                //Copy current window parameters
                                [tmpWindow setTitle:[m_window title]];
-                               [tmpWindow setRepresentedURL:[m_window representedURL]];
+                               [tmpWindow setRepresentedFilename:[m_window representedFilename]];
                                [tmpWindow setReleasedWhenClosed:NO];
                                [tmpWindow setAcceptsMouseMovedEvents:YES];
                                [tmpWindow setDelegate:[m_window delegate]];
@@ -576,15 +835,15 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
                        
                                //Tell WM of view new size
                                m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
-                               
-                               [pool drain];
                        }
             else if ([m_window isMiniaturized])
                                [m_window deminiaturize:nil];
                        else if ([m_window isZoomed])
                                [m_window zoom:nil];
+                       [pool drain];
             break;
     }
+
     return GHOST_kSuccess;
 }
 
@@ -602,13 +861,25 @@ GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges)
 
 GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
 {
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       
        GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid")
     if (order == GHOST_kWindowOrderTop) {
-               [m_window orderFront:nil];
+               [m_window makeKeyAndOrderFront:nil];
     }
     else {
+               NSArray *windowsList;
+               
                [m_window orderBack:nil];
+               
+               //Check for other blender opened windows and make the frontmost key
+               windowsList = [NSApp orderedWindows];
+               if ([windowsList count]) {
+                       [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
+               }
     }
+       
+       [pool drain];
     return GHOST_kSuccess;
 }
 
@@ -648,6 +919,9 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
                if (m_openGLContext != nil) {
                        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
                        [m_openGLContext makeCurrentContext];
+                       
+                       // Disable AA by default
+                       if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB);
                        [pool drain];
                        return GHOST_kSuccess;
                }
@@ -665,6 +939,10 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp
        NSOpenGLPixelFormat *pixelFormat;
        NSOpenGLContext *tmpOpenGLContext;
        
+       /***** Multithreaded opengl code : uncomment for enabling
+       CGLContextObj cglCtx;
+       */
+        
        switch (type) {
                case GHOST_kDrawingContextTypeOpenGL:
                        if (!getValid()) break;
@@ -677,17 +955,27 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp
                                break;
                        }
                        
+                       //Switch openGL to multhreaded mode
+                       /******* Multithreaded opengl code : uncomment for enabling
+                       cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
+                       if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
+                               printf("\nSwitched openGL to multithreaded mode");
+                        */
+                       
                        if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext;
 #ifdef WAIT_FOR_VSYNC
+                       {
+                               GLint swapInt = 1;
                                /* wait for vsync, to avoid tearing artifacts */
-                               [tmpOpenGLContext setValues:1 forParameter:NSOpenGLCPSwapInterval];
+                               [tmpOpenGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+                       }
 #endif
-                               [m_openGLView setOpenGLContext:tmpOpenGLContext];
-                               [tmpOpenGLContext setView:m_openGLView];
-                               
-                               m_openGLContext = tmpOpenGLContext;
+                       [m_openGLView setOpenGLContext:tmpOpenGLContext];
+                       [tmpOpenGLContext setView:m_openGLView];
+                       
+                       m_openGLContext = tmpOpenGLContext;
                        break;
-               
+       
                case GHOST_kDrawingContextTypeNone:
                        success = GHOST_kSuccess;
                        break;
@@ -733,14 +1021,72 @@ GHOST_TSuccess GHOST_WindowCocoa::invalidate()
        return GHOST_kSuccess;
 }
 
+#pragma mark Progress bar
+
+GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress)
+{
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       
+       if ((progress >=0.0) && (progress <=1.0)) {
+               NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)];
+               
+               [dockIcon lockFocus];
+        NSRect progressBox = {{4, 4}, {120, 16}};
+
+        [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0];
+        
+        // Track & Outline
+        [[NSColor blackColor] setFill];
+        NSRectFill(progressBox);
+        
+        [[NSColor whiteColor] set];
+        NSFrameRect(progressBox);
+        
+        // Progress fill
+        progressBox = NSInsetRect(progressBox, 1, 1);
+        [[NSColor knobColor] setFill];
+        progressBox.size.width = progressBox.size.width * progress;
+               NSRectFill(progressBox);
+               
+               [dockIcon unlockFocus];
+               
+               [NSApp setApplicationIconImage:dockIcon];
+               [dockIcon release];
+               
+               m_progressBarVisible = true;
+       }
+       
+       [pool drain];
+       return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::endProgressBar()
+{
+       if (!m_progressBarVisible) return GHOST_kFailure;
+       m_progressBarVisible = false;
+       
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       
+       NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)];
+       [dockIcon lockFocus];
+       [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0];
+       [dockIcon unlockFocus];
+       [NSApp setApplicationIconImage:dockIcon];
+       [dockIcon release];
+       
+       [pool drain];
+       return GHOST_kSuccess;
+}
+
+
+
 #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) {
@@ -796,6 +1142,7 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c
                        case GHOST_kStandardCursorTopRightCorner:
                        case GHOST_kStandardCursorBottomRightCorner:
                        case GHOST_kStandardCursorBottomLeftCorner:
+                       case GHOST_kStandardCursorCopy:
                        case GHOST_kStandardCursorDefault:
                        default:
                                tmpCursor = [NSCursor arrowCursor];
@@ -803,89 +1150,71 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c
                };
        }
        [tmpCursor set];
-       [pool drain];
 }
 
 
 
 GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
 {
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
+       
        if ([m_window isVisible]) {
                loadCursor(visible, getCursorShape());
        }
        
+       [pool drain];
        return GHOST_kSuccess;
 }
 
 
-//Override this method to provide set feature even if not in warp
-inline bool GHOST_WindowCocoa::setCursorWarpAccum(GHOST_TInt32 x, GHOST_TInt32 y)
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
 {
-       m_cursorWarpAccumPos[0]= x;
-       m_cursorWarpAccumPos[1]= y;
+       GHOST_TSuccess err = GHOST_kSuccess;
        
-       return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(bool grab, bool warp, bool restore)
-{
-       if (grab)
+       if (mode != GHOST_kGrabDisable)
        {
                //No need to perform grab without warp as it is always on in OS X
-               if(warp) {
+               if(mode != GHOST_kGrabNormal) {
                        GHOST_TInt32 x_old,y_old;
+                       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
-                       m_cursorWarp= true;
                        m_systemCocoa->getCursorPosition(x_old,y_old);
-                       screenToClient(x_old, y_old, m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
+                       screenToClient(x_old, y_old, m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
                        //Warp position is stored in client (window base) coordinates
-                       setWindowCursorVisibility(false);
-                       return CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
+                       setCursorGrabAccum(0, 0);
+                       
+                       if(mode == GHOST_kGrabHide) {
+                               setWindowCursorVisibility(false);
+                       }
+                       
+                       //Make window key if it wasn't to get the mouse move events
+                       [m_window makeKeyWindow];
+                       
+                       //Dissociate cursor position even for warp mode, to allow mouse acceleration to work even when warping the cursor
+                       err = CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
+                       
+                       [pool drain];
                }
        }
        else {
-               if(m_cursorWarp)
-               {/* are we exiting warp */
+               if(m_cursorGrab==GHOST_kGrabHide)
+               {
+                       //No need to set again cursor position, as it has not changed for Cocoa
                        setWindowCursorVisibility(true);
-                       /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
-                       if(restore) {
-                               GHOST_Rect bounds;
-                               GHOST_TInt32 x_new, y_new, x_cur, y_cur;
-                               
-                               getClientBounds(bounds);
-                               x_new= m_cursorWarpInitPos[0]+m_cursorWarpAccumPos[0];
-                               y_new= m_cursorWarpInitPos[1]+m_cursorWarpAccumPos[1];
-                               
-                               if(x_new < 0)           x_new = 0;
-                               if(y_new < 0)           y_new = 0;
-                               if(x_new > bounds.getWidth())   x_new = bounds.getWidth();
-                               if(y_new > bounds.getHeight())  y_new = bounds.getHeight();
-                               
-                               //get/set cursor position works in screen coordinates
-                               clientToScreen(x_new, y_new, x_cur, y_cur);
-                               m_systemCocoa->setCursorPosition(x_cur, y_cur);
-                               
-                               //As Cocoa will give as first deltaX,deltaY this change in cursor position, we need to compensate for it
-                               //Issue appearing in case of two transform operations conducted w/o mouse motion in between
-                               x_new=m_cursorWarpAccumPos[0];
-                               y_new=m_cursorWarpAccumPos[1];
-                               setCursorWarpAccum(-x_new, -y_new);
-                       }
-                       else {
-                               m_systemCocoa->setCursorPosition(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
-                               setCursorWarpAccum(0, 0);
-                       }
-                       
-                       m_cursorWarp= false;
-                       return CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
                }
+               
+               err = CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
+               /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
+               setCursorGrabAccum(0, 0);
+               m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
        }
-       return GHOST_kSuccess;
+       return err;
 }
        
 GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
 {
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
        if (m_customCursor) {
                [m_customCursor release];
                m_customCursor = nil;
@@ -895,11 +1224,11 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor sha
                loadCursor(getCursorVisibility(), shape);
        }
        
+       [pool drain];
        return GHOST_kSuccess;
 }
 
-#if 0
-/** Reverse the bits in a GHOST_TUns8 */
+/** Reverse the bits in a GHOST_TUns8
 static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
 {
        ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA);
@@ -907,7 +1236,7 @@ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
        ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0);
        return ch;
 }
-#endif
+*/
 
 
 /** Reverse the bits in a GHOST_TUns16 */
@@ -923,43 +1252,68 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
 GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
                                        int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color)
 {
-       int y;
+       int y,nbUns16;
        NSPoint hotSpotPoint;
+       NSBitmapImageRep *cursorImageRep;
        NSImage *cursorImage;
+       NSSize imSize;
+       GHOST_TUns16 *cursorBitmap;
+       
+       
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        
        if (m_customCursor) {
                [m_customCursor release];
                m_customCursor = nil;
        }
-       /*TODO: implement this (but unused inproject at present)
-       cursorImage = [[NSImage alloc] initWithData:bitmap];
        
-       for (y=0; y<16; y++) {
+
+       cursorImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
+                                                                                                                        pixelsWide:sizex
+                                                                                                                        pixelsHigh:sizey
+                                                                                                                 bitsPerSample:1 
+                                                                                                               samplesPerPixel:2
+                                                                                                                          hasAlpha:YES
+                                                                                                                          isPlanar:YES
+                                                                                                                colorSpaceName:NSDeviceWhiteColorSpace
+                                                                                                                       bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0))
+                                                                                                                  bitsPerPixel:1];
+       
+       
+       cursorBitmap = (GHOST_TUns16*)[cursorImageRep bitmapData];
+       nbUns16 = [cursorImageRep bytesPerPlane]/2;
+       
+       for (y=0; y<nbUns16; y++) {
 #if !defined(__LITTLE_ENDIAN__)
-               m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
-               m_customCursor->mask[y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
+               cursorBitmap[y] = ~uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
+               cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
 #else
-               m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
-               m_customCursor->mask[y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
+               cursorBitmap[y] = ~uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
+               cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
 #endif
-                       
+               
        }
        
        
+       imSize.width = sizex;
+       imSize.height= sizey;
+       cursorImage = [[NSImage alloc] initWithSize:imSize];
+       [cursorImage addRepresentation:cursorImageRep];
+       
        hotSpotPoint.x = hotX;
        hotSpotPoint.y = hotY;
        
+       //foreground and background color parameter is not handled for now (10.6)
        m_customCursor = [[NSCursor alloc] initWithImage:cursorImage
-                                                                foregroundColorHint:<#(NSColor *)fg#>
-                                                                backgroundColorHint:<#(NSColor *)bg#>
                                                                                         hotSpot:hotSpotPoint];
        
+       [cursorImageRep release];
        [cursorImage release];
        
        if ([m_window isVisible]) {
                loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
        }
-       */
+       [pool drain];
        return GHOST_kSuccess;
 }
 
@@ -968,36 +1322,3 @@ 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;
-}
-
-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