[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23779] trunk/blender/intern/ghost/intern: Cocoa : Fullscreen mode improvement (Bugfix# 16682)

Damien Plisson damien.plisson at yahoo.fr
Mon Oct 12 11:53:28 CEST 2009


Revision: 23779
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23779
Author:   damien78
Date:     2009-10-12 11:53:28 +0200 (Mon, 12 Oct 2009)

Log Message:
-----------
Cocoa : Fullscreen mode improvement (Bugfix# 16682)

Instead of capturing the display and all user input (video game mode), the mechanism is now to hide dock & menu bar, and enlarge the window made borderless to cover the whole screen surface.

Thus all OS X window management features remains available (other windows,multi screens compatible, process switching, expose, spaces, ..)

Modified Paths:
--------------
    trunk/blender/intern/ghost/intern/GHOST_SystemCocoa.mm
    trunk/blender/intern/ghost/intern/GHOST_WindowCocoa.mm

Modified: trunk/blender/intern/ghost/intern/GHOST_SystemCocoa.mm
===================================================================
--- trunk/blender/intern/ghost/intern/GHOST_SystemCocoa.mm	2009-10-12 09:39:57 UTC (rev 23778)
+++ trunk/blender/intern/ghost/intern/GHOST_SystemCocoa.mm	2009-10-12 09:53:28 UTC (rev 23779)
@@ -733,13 +733,6 @@
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	GHOST_IWindow* window = 0;
 	
-	//First check if we are in fullscreen mode
-	//If so, exit it before creating a new window
-	window = m_windowManager->getActiveWindow();
-	if (window && (window->getState() == GHOST_kWindowStateFullScreen))
-		window->setState(GHOST_kWindowStateNormal);
-	window = NULL;
-	
 	//Get the available rect for including window contents
 	NSRect frame = [[NSScreen mainScreen] visibleFrame];
 	NSRect contentRect = [NSWindow contentRectForFrameRect:frame
@@ -1008,13 +1001,6 @@
 	//Check open windows if some changes are not saved
 	if (m_windowManager->getAnyModifiedState())
 	{
-		//First check if we are in fullscreen mode
-		//If so, exit it before creating a new window
-		GHOST_IWindow *window = m_windowManager->getActiveWindow();
-		if (window && (window->getState() == GHOST_kWindowStateFullScreen))
-			window->setState(GHOST_kWindowStateNormal);
-		window = NULL;		
-		
 		int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved. Do you really want to quit ?",
 										 @"Cancel", @"Quit anyway", nil);
 		if (shouldQuit == NSAlertAlternateReturn)

Modified: trunk/blender/intern/ghost/intern/GHOST_WindowCocoa.mm
===================================================================
--- trunk/blender/intern/ghost/intern/GHOST_WindowCocoa.mm	2009-10-12 09:39:57 UTC (rev 23778)
+++ trunk/blender/intern/ghost/intern/GHOST_WindowCocoa.mm	2009-10-12 09:53:28 UTC (rev 23779)
@@ -29,6 +29,11 @@
 
 #include <Cocoa/Cocoa.h>
 
+#ifndef MAC_OS_X_VERSION_10_6
+//Use of the SetSystemUIMode function (64bit compatible)
+#include <Carbon/Carbon.h>
+#endif
+
 #include "GHOST_WindowCocoa.h"
 #include "GHOST_SystemCocoa.h"
 #include "GHOST_Debug.h"
@@ -44,7 +49,7 @@
 	0
 };
 
-#pragma mark Cocoa delegate object
+#pragma mark Cocoa window delegate object
 
 @interface CocoaWindowDelegate : NSObject
 {
@@ -96,6 +101,26 @@
 }
 @end
 
+#pragma mark NSWindow subclass
+//We need to subclass it to tell that even borderless (fullscreen), it can become key (receive user events)
+ at interface CocoaWindow: NSWindow
+{
+
+}
+-(BOOL)canBecomeKeyWindow;
+
+ at end
+ at implementation CocoaWindow
+
+-(BOOL)canBecomeKeyWindow
+{
+	return YES;
+}
+
+ at end
+
+
+
 #pragma mark NSOpenGLView subclass
 //We need to subclass it in order to give Cocoa the feeling key events are trapped
 @interface CocoaOpenGLView : NSOpenGLView
@@ -152,7 +177,7 @@
 	rect.size.width = width;
 	rect.size.height = height;
 	
-	m_window = [[NSWindow alloc] initWithContentRect:rect
+	m_window = [[CocoaWindow alloc] initWithContentRect:rect
 										   styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
 											 backing:NSBackingStoreBuffered defer:NO];
 	if (m_window == nil) {
@@ -212,9 +237,16 @@
 	
 	if (m_window) {
 		[m_window close];
+		[[m_window delegate] release];
 		[m_window release];
 		m_window = nil;
 	}
+	
+	//Check for other blender opened windows and make the frontmost key
+	NSArray *windowsList = [NSApp orderedWindows];
+	if ([windowsList count]) {
+		[[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
+	}
 	[pool drain];
 }
 
@@ -295,8 +327,8 @@
 		NSRect screenSize = [[m_window screen] visibleFrame];
 
 		//Max window contents as screen size (excluding title bar...)
-		NSRect contentRect = [NSWindow contentRectForFrameRect:screenSize
-													 styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
+		NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize
+													 styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
 
 		rect = [m_window contentRectForFrameRect:[m_window frame]];
 		
@@ -418,7 +450,11 @@
 	outY = screenCoord.y;
 }
 
-
+/**
+ * @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.
+ * Thus, process switch, exposé, spaces, ... still work in fullscreen mode
+ */
 GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
 {
 	GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid")
@@ -439,9 +475,50 @@
 				//to give window delegate hint not to forward its deactivation to ghost wm that doesn't know view/window difference
 				m_fullScreen = true;
 
-				//Only 10.6 API will enable to manage several display in fullscreen mode, and topmenu autoshow
-				[m_openGLView enterFullScreenMode:[m_window screen] withOptions:nil];
+#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]])
+				{
+					[NSApp setPresentationOptions:(NSApplicationPresentationHideDock | NSApplicationPresentationAutoHideMenuBar)];
+				}
+				//Make window borderless and enlarge it
+				[m_window setStyleMask:NSBorderlessWindowMask];
+				[m_window setFrame:[[m_window screen] frame] display:YES];
+#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]])
+				{
+					//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
+					SetSystemUIMode(kUIModeAllHidden,kUIOptionAutoShowMenuBar);
+				}
+				//Create a fullscreen borderless window
+				CocoaWindow *tmpWindow = [[CocoaWindow alloc]
+										  initWithContentRect:[[m_window screen] frame]
+										  styleMask:NSBorderlessWindowMask
+										  backing:NSBackingStoreBuffered
+										  defer:YES];
+				//Copy current window parameters
+				[tmpWindow setTitle:[m_window title]];
+				[tmpWindow setRepresentedURL:[m_window representedURL]];
+				[tmpWindow setReleasedWhenClosed:NO];
+				[tmpWindow setAcceptsMouseMovedEvents:YES];
+				[tmpWindow setDelegate:[m_window delegate]];
 				
+				//Assign the openGL view to the new window
+				[tmpWindow setContentView:m_openGLView];
+				
+				//Show the new window
+				[tmpWindow makeKeyAndOrderFront:nil];
+				//Close and release old window
+				[m_window setDelegate:nil]; // To avoid the notification of "window closed" event
+				[m_window close];
+				[m_window release];
+				m_window = tmpWindow;
+#endif
+			
 				//Tell WM of view new size
 				m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
 				
@@ -456,11 +533,48 @@
 				m_fullScreen = false;
 
 				//Exit fullscreen
-				[m_openGLView exitFullScreenModeWithOptions:nil];
+#ifdef MAC_OS_X_VERSION_10_6
+				//Show again menu & dock if needed
+				if ([[m_window screen] isEqual:[NSScreen mainScreen]])
+				{
+					[NSApp setPresentationOptions:NSApplicationPresentationDefault];
+				}
+				//Make window normal and resize it
+				[m_window setStyleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
+				[m_window setFrame:[[m_window screen] visibleFrame] display:YES];
+#else
+				//With 10.5, we need to create a new window to change its style to borderless
+				//Show menu & dock if needed
+				if ([[m_window screen] isEqual:[NSScreen mainScreen]])
+				{
+					//Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:YES];
+					SetSystemUIMode(kUIModeNormal, 0); //One of the very few 64bit compatible Carbon function
+				}
+				//Create a fullscreen borderless window
+				CocoaWindow *tmpWindow = [[CocoaWindow alloc]
+										  initWithContentRect:[[m_window screen] frame]
+													styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
+													  backing:NSBackingStoreBuffered
+														defer:YES];
+				//Copy current window parameters
+				[tmpWindow setTitle:[m_window title]];
+				[tmpWindow setRepresentedURL:[m_window representedURL]];
+				[tmpWindow setReleasedWhenClosed:NO];
+				[tmpWindow setAcceptsMouseMovedEvents:YES];
+				[tmpWindow setDelegate:[m_window delegate]];
 				
-				[m_window makeKeyAndOrderFront:nil];
-				[m_window makeFirstResponder:m_openGLView];
+				//Assign the openGL view to the new window
+				[tmpWindow setContentView:m_openGLView];
 				
+				//Show the new window
+				[tmpWindow makeKeyAndOrderFront:nil];
+				//Close and release old window
+				[m_window setDelegate:nil]; // To avoid the notification of "window closed" event
+				[m_window close];
+				[m_window release];
+				m_window = tmpWindow;
+#endif
+			
 				//Tell WM of view new size
 				m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
 				
@@ -534,22 +648,7 @@
 	if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
 		if (m_openGLContext != nil) {
 			NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-			
 			[m_openGLContext makeCurrentContext];
-#ifdef GHOST_DRAW_CARBON_GUTTER
-			// Restrict drawing to non-gutter area
-			::aglEnable(m_aglCtx, AGL_BUFFER_RECT);
-			GHOST_Rect bnds;
-			getClientBounds(bnds);
-			GLint b[4] =
-			{
-				bnds.m_l,
-				bnds.m_t+s_sizeRectSize,
-				bnds.m_r-bnds.m_l,
-				bnds.m_b-bnds.m_t
-			};
-			GLboolean result = ::aglSetInteger(m_aglCtx, AGL_BUFFER_RECT, b);
-#endif //GHOST_DRAW_CARBON_GUTTER
 			[pool drain];
 			return GHOST_kSuccess;
 		}
@@ -725,7 +824,6 @@
 
 GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(bool grab, bool warp, bool restore)
 {
-	printf("\ncursor grab %i",grab);
 	if (grab)
 	{
 		//No need to perform grab without warp as it is always on in OS X





More information about the Bf-blender-cvs mailing list