From a3449771476955fd4a27eadd17ff4dce2655cc16 Mon Sep 17 00:00:00 2001 From: Damien Plisson Date: Mon, 5 Oct 2009 12:55:16 +0000 Subject: Cocoa port : - Window creation at preferred size Implement in Ghost the use of Cocoa functions to get the maximum visible rect (size and position) for the window contents (all screen excluding dock, top menu, and window title bar) Thus Apple specific code in window creation (wm_window.c & wm_apple.c) is no more needed => removed in case of Cocoa build - Alert on exiting despite unsaved changes Add to GHOST method to maintain an all platforms (not apple specific anymore) status on unsaved changes Update GHOST_SystemCocoa to use this for asking or not user to confirm exit without saving changes --- intern/ghost/GHOST_C-api.h | 10 ++ intern/ghost/GHOST_IWindow.h | 13 +++ intern/ghost/GHOST_Types.h | 6 ++ intern/ghost/intern/GHOST_C-api.cpp | 7 ++ intern/ghost/intern/GHOST_SystemCocoa.h | 24 ++--- intern/ghost/intern/GHOST_SystemCocoa.mm | 117 +++++++++++++++++------- intern/ghost/intern/GHOST_Window.cpp | 14 +++ intern/ghost/intern/GHOST_Window.h | 16 ++++ intern/ghost/intern/GHOST_WindowCocoa.h | 7 ++ intern/ghost/intern/GHOST_WindowCocoa.mm | 18 ++-- intern/ghost/intern/GHOST_WindowManager.cpp | 19 +++- intern/ghost/intern/GHOST_WindowManager.h | 10 +- source/blender/windowmanager/CMakeLists.txt | 4 + source/blender/windowmanager/intern/wm_window.c | 17 +++- 14 files changed, 219 insertions(+), 63 deletions(-) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index c0b7077fb53..9460fb504a9 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -598,6 +598,16 @@ extern GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle); extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, GHOST_TWindowState state); + +/** + * Sets the window "modified" status, indicating unsaved changes + * @param windowhandle The handle to the window + * @param isUnsavedChanges Unsaved changes or not + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, + GHOST_TUns8 isUnsavedChanges); + /** * Sets the order of the window (bottom, top). * @param windowhandle The handle to the window diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index d91995e35ec..ff1484909b0 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -161,6 +161,19 @@ public: */ virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0; + /** + * Sets the window "modified" status, indicating unsaved changes + * @param isUnsavedChanges Unsaved changes or not + * @return Indication of success. + */ + virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) = 0; + + /** + * Gets the window "modified" status, indicating unsaved changes + * @return True if there are unsaved changes + */ + virtual bool getModifiedState() = 0; + /** * Sets the order of the window (bottom, top). * @param order The order of the window. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 31819f341a0..14e3c4bb5f7 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -116,6 +116,12 @@ typedef enum { } GHOST_TWindowState; +/** Constants for the answer to the blender exit request */ +typedef enum { + GHOST_kExitCancel = 0, + GHOST_kExitNow +} GHOST_TExitRequestResponse; + typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 5c23b6c42a3..d14945d1bf8 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -629,6 +629,13 @@ GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, } +GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, GHOST_TUns8 isUnsavedChanges) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setModifiedState(isUnsavedChanges); +} + GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle, GHOST_TWindowOrder order) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index cd2cf12daa1..3e499f3d136 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -133,6 +133,12 @@ public: */ virtual bool processEvents(bool waitForEvent); + /** + * Handle User request to quit, from Menu bar Quit, and Cmd+Q + * Display alert panel if changes performed since last save + */ + GHOST_TUns8 handleQuitRequest(); + /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ @@ -193,39 +199,33 @@ protected: */ virtual GHOST_TSuccess init(); - /** - * Closes the system down. - * @return A success value. - */ - virtual GHOST_TSuccess exit(); - - /** * Handles a tablet event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) * @return Indication whether the event was handled. */ - int handleTabletEvent(void *eventPtr); - /** + GHOST_TSuccess handleTabletEvent(void *eventPtr); + + /** * Handles a mouse event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) * @return Indication whether the event was handled. */ - int handleMouseEvent(void *eventPtr); + GHOST_TSuccess handleMouseEvent(void *eventPtr); /** * Handles a key event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) * @return Indication whether the event was handled. */ - int handleKeyEvent(void *eventPtr); + 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. */ - int handleWindowEvent(void *eventPtr); + GHOST_TSuccess handleWindowEvent(void *eventPtr); /** * Handles all basic Mac application stuff for a mouse down event. diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index d0c382e1469..c66153ab670 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -414,6 +414,7 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { } -(void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; +- (void)applicationWillTerminate:(NSNotification *)aNotification; @end @implementation CocoaAppDelegate : NSObject @@ -424,15 +425,21 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { + //TODO: implement graceful termination through Cocoa mechanism to avoid session log off to be cancelled //Note that Cmd+Q is already handled by keyhandler - //FIXME: Need an event "QuitRequest" - int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes may not have been saved. Do you really want to quit ?", - @"No", @"Yes", nil); - - if (shouldQuit == NSAlertAlternateReturn) - systemCocoa->pushEvent( new GHOST_Event(systemCocoa->getMilliSeconds(), GHOST_kEventQuit, NULL) ); - - return NSTerminateCancel; + if (systemCocoa->handleQuitRequest() == GHOST_kExitNow) + return NSTerminateCancel;//NSTerminateNow; + else + return NSTerminateCancel; +} + +// To avoid cancelling a log off process, we must use Cocoa termination process +// And this function is the only chance to perform clean up +// So WM_exit needs to be called directly, as the event loop will never run before termination +- (void)applicationWillTerminate:(NSNotification *)aNotification +{ + /*G.afbreek = 0; //Let Cocoa perform the termination at the end + WM_exit(C);*/ } @end @@ -440,7 +447,6 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { #pragma mark initialization/finalization -/***/ GHOST_SystemCocoa::GHOST_SystemCocoa() { @@ -468,6 +474,8 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() GHOST_SystemCocoa::~GHOST_SystemCocoa() { + NSAutoreleasePool* pool = (NSAutoreleasePool *)m_autoReleasePool; + [pool drain]; } @@ -478,7 +486,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init() if (success) { //ProcessSerialNumber psn; - //FIXME: Carbon stuff to move window & menu to foreground + //Carbon stuff to move window & menu to foreground /*if (!GetCurrentProcess(&psn)) { TransformProcessType(&psn, kProcessTransformToForegroundApplication); SetFrontProcess(&psn); @@ -566,13 +574,6 @@ GHOST_TSuccess GHOST_SystemCocoa::init() } -GHOST_TSuccess GHOST_SystemCocoa::exit() -{ - NSAutoreleasePool* pool = (NSAutoreleasePool *)m_autoReleasePool; - [pool drain]; - return GHOST_System::exit(); -} - #pragma mark window management GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const @@ -602,11 +603,15 @@ GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { - //TODO: Provide visible frame or total frame, check for consistency with rest of code + //Get visible frame, that is frame excluding dock and top menu bar NSRect frame = [[NSScreen mainScreen] visibleFrame]; - width = frame.size.width; - height = frame.size.height; + //Returns max window contents (excluding title bar...) + NSRect contentRect = [NSWindow contentRectForFrameRect:frame + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; + + width = contentRect.size.width; + height = contentRect.size.height; } @@ -623,7 +628,16 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( ) { GHOST_IWindow* window = 0; - + + //Get the available rect for including window contents + NSRect frame = [[NSScreen mainScreen] visibleFrame]; + NSRect contentRect = [NSWindow contentRectForFrameRect:frame + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; + + //Ensures window top left is inside this available rect + left = left > contentRect.origin.x ? left : contentRect.origin.x; + top = top > contentRect.origin.y ? top : contentRect.origin.y; + window = new GHOST_WindowCocoa (title, left, top, width, height, state, type); if (window) { @@ -847,7 +861,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) } //TODO: To be called from NSWindow delegate -int GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) +GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) { /*WindowRef windowRef; GHOST_WindowCocoa *window; @@ -900,7 +914,29 @@ int GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) return GHOST_kSuccess; } -int GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) +GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest() +{ + //Check open windows if some changes are not saved + if (m_windowManager->getAnyModifiedState()) + { + int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved. Do you really want to quit ?", + @"Cancel", @"Quit anyway", nil); + if (shouldQuit == NSAlertAlternateReturn) + { + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) ); + return GHOST_kExitNow; + } + } + else { + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) ); + return GHOST_kExitNow; + } + + return GHOST_kExitCancel; +} + + +GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; GHOST_IWindow* window = m_windowManager->getActiveWindow(); @@ -964,7 +1000,7 @@ int GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) } -int GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) +GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; GHOST_IWindow* window = m_windowManager->getActiveWindow(); @@ -1018,11 +1054,12 @@ int GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } -int GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) +GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; GHOST_IWindow* window = m_windowManager->getActiveWindow(); NSUInteger modifiers; + NSString *characters; GHOST_TKey keyCode; unsigned char ascii; @@ -1036,9 +1073,16 @@ int GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) switch ([event type]) { case NSKeyDown: case NSKeyUp: - keyCode = convertKey([event keyCode], - [[event charactersIgnoringModifiers] characterAtIndex:0]); - ascii= convertRomanToLatin((char)[[event characters] characterAtIndex:0]); + characters = [event characters]; + if ([characters length]) { //Check for dead keys + keyCode = convertKey([event keyCode], + [[event charactersIgnoringModifiers] characterAtIndex:0]); + ascii= convertRomanToLatin((char)[characters characterAtIndex:0]); + } else { + keyCode = convertKey([event keyCode],0); + ascii= 0; + } + if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask)) break; //Cmd-Q is directly handled by Cocoa @@ -1223,9 +1267,12 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const GHOST_TUns8 * temp_buff; size_t pastedTextSize; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; if (pasteBoard = nil) { + [pool drain]; return NULL; } @@ -1235,7 +1282,10 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const NSString *bestType = [[NSPasteboard generalPasteboard] availableTypeFromArray:supportedTypes]; - if (bestType == nil) { return NULL; } + if (bestType == nil) { + [pool drain]; + return NULL; + } NSString * textPasted = [pasteBoard stringForType:@"public.utf8-plain-text"]; @@ -1249,6 +1299,8 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const temp_buff[pastedTextSize] = '\0'; + [pool drain]; + if(temp_buff) { return temp_buff; } else { @@ -1262,10 +1314,12 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const if(selection) {return;} // for copying the selection, used on X11 - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; if (pasteBoard = nil) { + [pool drain]; return; } @@ -1277,8 +1331,7 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const [pasteBoard setString:textToCopy forType:@"public.utf8-plain-text"]; - printf("\nCopy"); - + [pool drain]; } #pragma mark Carbon stuff to remove diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index 951c3bc381d..34e9f519a07 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -52,6 +52,8 @@ GHOST_Window::GHOST_Window( m_cursorShape(GHOST_kStandardCursorDefault), m_stereoVisual(stereoVisual) { + m_isUnsavedChanges = false; + m_fullScreen = state == GHOST_kWindowStateFullScreen; if (m_fullScreen) { m_fullScreenWidth = width; @@ -137,3 +139,15 @@ GHOST_TSuccess GHOST_Window::setCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUn } } + +GHOST_TSuccess GHOST_Window::setModifiedState(bool isUnsavedChanges) +{ + m_isUnsavedChanges = isUnsavedChanges; + + return GHOST_kSuccess; +} + +bool GHOST_Window::getModifiedState() +{ + return m_isUnsavedChanges; +} \ No newline at end of file diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 88178bae5b3..a2d1675f6ab 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -173,6 +173,19 @@ public: */ virtual GHOST_TSuccess setCursorGrab(bool grab); + /** + * Sets the window "modified" status, indicating unsaved changes + * @param isUnsavedChanges Unsaved changes or not + * @return Indication of success. + */ + virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); + + /** + * Gets the window "modified" status, indicating unsaved changes + * @return True if there are unsaved changes + */ + virtual bool getModifiedState(); + /** * Returns the type of drawing context used in this window. * @return The current type of drawing context. @@ -262,6 +275,9 @@ protected: /** The current shape of the cursor */ GHOST_TStandardCursor m_cursorShape; + /** Modified state : are there unsaved changes */ + bool m_isUnsavedChanges; + /** Stores wether this is a full screen window. */ bool m_fullScreen; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 146d0ff47de..f383e3a7a81 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -143,6 +143,13 @@ public: */ virtual GHOST_TWindowState getState() const; + /** + * Sets the window "modified" status, indicating unsaved changes + * @param isUnsavedChanges Unsaved changes or not + * @return Indication of success. + */ + virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); + /** * Converts a point in screen coordinates to client rectangle coordinates * @param inX The x-coordinate on the screen. diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 53d7fa9b245..092443814b0 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -378,12 +378,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) case GHOST_kWindowStateMinimized: ::HideWindow(m_windowRef); break; - case GHOST_kWindowStateModified: - SetWindowModified(m_windowRef, 1); - break; - case GHOST_kWindowStateUnModified: - SetWindowModified(m_windowRef, 0); - break; case GHOST_kWindowStateMaximized: case GHOST_kWindowStateNormal: default: @@ -393,6 +387,18 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) return GHOST_kSuccess; } +GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges) +{ + if (isUnsavedChanges) { + SetWindowModified(m_windowRef, 1); + } else { + SetWindowModified(m_windowRef, 0); + } + + return GHOST_Window::setModifiedState(isUnsavedChanges); +} + + GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp index af96653db13..15ee41e3dce 100644 --- a/intern/ghost/intern/GHOST_WindowManager.cpp +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -187,10 +187,21 @@ void GHOST_WindowManager::setWindowInactive(const GHOST_IWindow* window) } - std::vector & -GHOST_WindowManager:: -getWindows( -){ +std::vector &GHOST_WindowManager::getWindows() +{ return m_windows; } + +bool GHOST_WindowManager::getAnyModifiedState() +{ + bool isAnyModified = false; + std::vector::iterator iter; + + for (iter = m_windows.begin(); iter != m_windows.end(); iter++) { + if ((*iter)->getModifiedState()) + isAnyModified = true; + } + + return isAnyModified; +} \ No newline at end of file diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h index 46e80d2c603..3690ad41e2c 100644 --- a/intern/ghost/intern/GHOST_WindowManager.h +++ b/intern/ghost/intern/GHOST_WindowManager.h @@ -133,11 +133,13 @@ public: * this vector. Please do not destroy or add windows use the * interface above for this, */ + std::vector & getWindows(); - std::vector & - getWindows( - ); - + /** + * Return true if any windows has a modified status + * @return True if any window has unsaved changes + */ + bool getAnyModifiedState(); protected: /** The list of windows managed */ diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index cb2fc92a1b6..7deac8a4aa0 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -70,6 +70,10 @@ IF(WIN32) SET(INC ${INC} ${PTHREADS_INC}) ENDIF(WIN32) +IF(WITH_COCOA) + LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/wm_apple.c") +ENDIF(WITH_COCOA) + # TODO buildinfo IF(BF_BUILDINFO) ADD_DEFINITIONS(-DNAN_BUILDINFO) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index c853afe4507..466e5868723 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -71,7 +71,8 @@ static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0; /* ******** win open & close ************ */ -/* XXX this one should correctly check for apple top header... */ +/* XXX this one should correctly check for apple top header... + done for Cocoa : returns window contents (and not frame) max size*/ static void wm_get_screensize(int *width_r, int *height_r) { unsigned int uiwidth; @@ -90,7 +91,7 @@ static void wm_window_check_position(rcti *rect) wm_get_screensize(&width, &height); -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(GHOST_COCOA) height -= 70; #endif @@ -269,7 +270,12 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) else GHOST_SetTitle(win->ghostwin, "Blender"); -#ifdef __APPLE__ + /* Informs GHOST of unsaved changes, to set window modified visual indicator (MAC OS X) + and to give hint of unsaved changes for a user warning mechanism + in case of OS application terminate request (e.g. OS Shortcut Alt+F4, Cmd+Q, (...), or session end) */ + GHOST_SetWindowModifiedState(win->ghostwin, (GHOST_TUns8)!wm->file_saved); + +#if defined(__APPLE__) && !defined(GHOST_COCOA) if(wm->file_saved) GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateUnModified); else @@ -292,7 +298,7 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow // inital_state = GHOST_kWindowStateMaximized; inital_state = GHOST_kWindowStateNormal; -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(GHOST_COCOA) { extern int macPrefState; /* creator.c */ inital_state += macPrefState; @@ -339,7 +345,8 @@ void wm_window_add_ghostwindows(wmWindowManager *wm) if (!prefsizx) { wm_get_screensize(&prefsizx, &prefsizy); -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(GHOST_COCOA) +//Cocoa provides functions to get correct max window size { extern void wm_set_apple_prefsize(int, int); /* wm_apple.c */ -- cgit v1.2.3