Switching to Cocoa implementation way. Updated copyright year. Removed WindowController. Added Cocoa window import support.

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/trunk@1049 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
ceylo 2009-03-14 13:49:54 +00:00
parent a5120cd681
commit e42882d2ca
6 changed files with 1679 additions and 1176 deletions

View File

@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// //
// SFML - Simple and Fast Multimedia Library // SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2008 Lucas Soltic (elmerod@gmail.com) and Laurent Gomila (laurent.gom@gmail.com) // Copyright (C) 2007-2009 Lucas Soltic (ceylow@gmail.com) and Laurent Gomila (laurent.gom@gmail.com)
// //
// This software is provided 'as-is', without any express or implied warranty. // This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software. // In no event will the authors be held liable for any damages arising from the use of this software.
@ -26,12 +26,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#import <SFML/Window/Cocoa/WindowImplCocoa.hpp>
#import <SFML/Window/VideoMode.hpp> #import <SFML/Window/VideoMode.hpp>
#import <SFML/System/Clock.hpp>
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import <vector>
#import <iostream>
#define SharedAppController [AppController sharedController] #define SharedAppController [AppController sharedController]
@ -42,80 +38,50 @@ enum {
CleanScreen CleanScreen
}; };
@class WindowWrapper;
@interface AppController : NSObject { @interface AppController : NSObject {
// Note: objc allocation doesn't call C++ constructor BOOL myOwningEventLoop;
std::vector <sf::priv::WindowImplCocoa *> *windows; WindowWrapper *myFullscreenWrapper;
NSAutoreleasePool *myMainPool;
NSAutoreleasePool *mainPool; sf::VideoMode myDesktopMode;
sf::Clock *cleaner; sf::VideoMode myPrevMode;
sf::VideoMode desktopMode;
sf::VideoMode prevMode;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Return the shared AppController object. Makes one if needed /// Return the shared AppController instance. Make one if needed.
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
+ (AppController *)sharedController; + (AppController *)sharedController;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Reallocate main pool to release autoreleased objects /// Make the menu bar
////////////////////////////////////////////////////////////
- (void)resetPool;
////////////////////////////////////////////////////////////
/// Register our application and launch it if needed
////////////////////////////////////////////////////////////
- (void)runApplication;
////////////////////////////////////////////////////////////
/// Terminate the current running application
////////////////////////////////////////////////////////////
- (void)quitApplication:(id)sender;
////////////////////////////////////////////////////////////
/// Make menu bar
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)makeMenuBar; - (void)makeMenuBar;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the events and put them into an array for each window /// Process all the events and send them to the application
/// No event is processed if the AppController instance is
/// not the owner of the event loop (ie: user made his own loop)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)processEvents; - (void)processEvents;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Add the 'windowImplObj' object to the list of known windows /// Set @window as the current fullscreen window
/// Change the screen resolution if needed according to @window and @fullscreenMode
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)registerWindow:(sf::priv::WindowImplCocoa *)windowImplObj; - (void)setFullscreenWindow:(WindowWrapper *)window mode:(sf::VideoMode *)fullscreenMode;
////////////////////////////////////////////////////////////
/// Remove the 'windowImplObj' object from the list of known windows
////////////////////////////////////////////////////////////
- (void)unregisterWindow:(sf::priv::WindowImplCocoa *)windowImplObj;
////////////////////////////////////////////////////////////
/// Return true is one of the registered window is a full screen one
////////////////////////////////////////////////////////////
- (bool)isUsingFullscreen;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Perform fade operation where 'operation' is one of { FillScreen, CleanScreen} /// Perform fade operation where 'operation' is one of { FillScreen, CleanScreen}
/// and 'time' is the time during which you wish the operation to be performed. /// and 'time' is the time during which you wish the operation to be performed.
/// Set 'sync' to true if you do not want the method to end before the end /// Set 'sync' to true if you do not want the method to end before the end
/// of the fade operation. Pass the last used token or a new one if you are /// of the fade operation.
/// using this method for the first time. This lets the method release some
/// resources when doing CleanScreen operation.
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)doFadeOperation:(int)operation time:(float)time sync:(bool)sync token:(CGDisplayFadeReservationToken *)prevToken; - (void)doFadeOperation:(int)operation time:(float)time sync:(bool)sync;
////////////////////////////////////////////////////////////
/// Return the desktop video mode (made at the instance initialization)
////////////////////////////////////////////////////////////
- (const sf::VideoMode&)desktopMode;
@end @end
////////////////////////////////////////////////////////////
/// check that ptr is valid, otherwise print msg in
/// std::cerr and throw std::bad_alloc.
/// Must be used to check alloc results
////////////////////////////////////////////////////////////
template <typename T>
T *massert(T *ptr);

View File

@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// //
// SFML - Simple and Fast Multimedia Library // SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2008 Lucas Soltic (elmerod@gmail.com) and Laurent Gomila (laurent.gom@gmail.com) // Copyright (C) 2007-2009 Lucas Soltic (ceylow@gmail.com) and Laurent Gomila (laurent.gom@gmail.com)
// //
// This software is provided 'as-is', without any express or implied warranty. // This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software. // In no event will the authors be held liable for any damages arising from the use of this software.
@ -27,14 +27,13 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#import <SFML/Window/Cocoa/AppController.h> #import <SFML/Window/Cocoa/AppController.h>
#import <SFML/Window/Cocoa/WindowController.h> #import <SFML/Window/Cocoa/GLKit.h>
#import <SFML/Window/Cocoa/WindowImplCocoa.hpp>
#import <SFML/System.hpp> #import <SFML/System.hpp>
#import <ApplicationServices/ApplicationServices.h> #import <ApplicationServices/ApplicationServices.h>
#import <iostream> #import <iostream>
// AppController singleton // AppController singleton object
static AppController *shared = nil; static AppController *shared = nil;
@ -61,61 +60,32 @@ static AppController *shared = nil;
@implementation AppController @implementation AppController
////////////////////////////////////////////////////////////
/// Return an initialized AppController instance
/// Save the desktop mode
/// Make the main autorelease pool
/// Set the application observer
////////////////////////////////////////////////////////////
- (id)init - (id)init
{ {
self = [super init]; self = [super init];
if (self != nil) { if (self != nil) {
windows = new std::vector <sf::priv::WindowImplCocoa *>; myOwningEventLoop = NO;
cleaner = new sf::Clock;
}
return self; // Save the desktop mode
} myDesktopMode = sf::VideoMode::GetDesktopMode();
myPrevMode = myDesktopMode;
// Make the app autorelease pool
myMainPool = [[NSAutoreleasePool alloc] init];
- (void)dealloc // Don't go on if the user handles the app
if (![NSApp isRunning])
{ {
delete windows; // Force our application to appear in the Dock and make it able
delete cleaner; // to get focus (even when it's a raw executable)
[super dealloc];
}
////////////////////////////////////////////////////////////
/// Return the shared AppController object. Makes one if needed
////////////////////////////////////////////////////////////
+ (AppController *)sharedController
{
if (nil == shared) {
shared = [massert([AppController alloc]) init];
}
return shared;
}
////////////////////////////////////////////////////////////
/// Reallocate main pool to release autoreleased objects
////////////////////////////////////////////////////////////
- (void)resetPool
{
[mainPool release];
mainPool = [massert([NSAutoreleasePool alloc]) init];
}
////////////////////////////////////////////////////////////
/// Register our application and launch it if needed
////////////////////////////////////////////////////////////
- (void)runApplication
{
if ([NSApp isRunning])
return;
// We want our application to appear in the Dock and be able
// to get focus
ProcessSerialNumber psn; ProcessSerialNumber psn;
if (!GetCurrentProcess(&psn)) { if (!GetCurrentProcess(&psn)) {
@ -123,98 +93,87 @@ static AppController *shared = nil;
SetFrontProcess(&psn); SetFrontProcess(&psn);
} }
if (NSApp == nil) { // Make the app
massert([NSApplication sharedApplication]); [NSApplication sharedApplication];
}
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
// I want to go back to the desktop mode
// if we've a fullscreen window when hiding
[nc addObserver:self
selector:@selector(applicationWillHide:)
name:NSApplicationWillHideNotification
object:NSApp];
// And restore de fullscreen mode when unhiding
[nc addObserver:self
selector:@selector(applicationWillUnhide:)
name:NSApplicationWillUnhideNotification
object:NSApp];
// Go back to desktop mode before exit
[nc addObserver:self
selector:@selector(applicationWillTerminate:)
name:NSApplicationWillTerminateNotification
object:NSApp];
if ([NSApp mainMenu] == nil) { if ([NSApp mainMenu] == nil) {
[self makeMenuBar]; [self makeMenuBar];
} }
}
}
[NSApp finishLaunching]; return self;
[NSApp setRunning:YES];
[NSApp setDelegate:self];
desktopMode = sf::VideoMode::GetDesktopMode();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Terminate the current running application /// Clean the controller
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)quitApplication:(id)sender - (void)dealloc
{ {
// Close all windows [[NSNotificationCenter defaultCenter] removeObserver:self];
// SFML user has to detect when all windows are closed [myFullscreenWrapper release];
NSWindow *current = nil; [super dealloc];
sf::priv::WindowImplCocoa *priv = NULL;
while (windows->size()) {
priv = windows->at(0);
current = static_cast <NSWindow *> (priv->CocoaWindow());
[current close];
windows->erase(windows->begin());
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Returns the first full screen window found or nil /// Return the shared AppController instance. Make one if needed.
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (SFWindow *)fullscreenWindow + (AppController *)sharedController
{ {
SFWindow *window = nil; if (nil == shared)
std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); shared = [[AppController alloc] init];
std::vector<sf::priv::WindowImplCocoa *>::size_type idx;
for (idx = 0; idx < sz; idx++) { return shared;
sf::priv::WindowImplCocoa *win = windows->at(idx);
if (win && win->IsFullscreen()) {
window = static_cast <SFWindow *> (win->CocoaWindow());
break;
}
}
return window;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Hide all the fullscreen windows and switch to desktop display mode /// Hide all the fullscreen windows and switch back to the desktop display mode
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)applicationWillHide:(NSNotification *)aNotification - (void)applicationWillHide:(NSNotification *)aNotification
{ {
if ([self isUsingFullscreen]) { if (myFullscreenWrapper) {
prevMode = sf::VideoMode::GetDesktopMode(); myPrevMode = sf::VideoMode::GetDesktopMode();
CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay, CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay,
desktopMode.BitsPerPixel, myDesktopMode.BitsPerPixel,
desktopMode.Width, myDesktopMode.Width,
desktopMode.Height, myDesktopMode.Height,
NULL); NULL);
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
// Fade to black screen // Fade to black screen
[SharedAppController doFadeOperation:FillScreen time:0.2f sync:true token:&token]; [self doFadeOperation:FillScreen time:0.2f sync:true];
// Make all the full screen SFML windows unvisible // Make the full screen window unvisible
std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); [[myFullscreenWrapper window] setAlphaValue:0.0f];
std::vector<sf::priv::WindowImplCocoa *>::size_type idx;
for (idx = 0; idx < sz; idx++) {
sf::priv::WindowImplCocoa *win = windows->at(idx);
if (win->IsFullscreen()) {
[static_cast <SFWindow *> (win->CocoaWindow()) setAlphaValue:0.0f];
}
}
// Switch to the wished display mode // Switch to the wished display mode
CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode);
// Fade to normal screen // Fade to normal screen
[SharedAppController doFadeOperation:CleanScreen time:0.5f sync:false token:&token]; [self doFadeOperation:CleanScreen time:0.5f sync:false];
} }
} }
@ -224,41 +183,43 @@ static AppController *shared = nil;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)applicationWillUnhide:(NSNotification *)aNotification - (void)applicationWillUnhide:(NSNotification *)aNotification
{ {
if ([self isUsingFullscreen]) { if (myFullscreenWrapper) {
CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay, CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay,
prevMode.BitsPerPixel, myPrevMode.BitsPerPixel,
prevMode.Width, myPrevMode.Width,
prevMode.Height, myPrevMode.Height,
NULL); NULL);
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
// Fade to a black screen // Fade to a black screen
[SharedAppController doFadeOperation:FillScreen time:0.5f sync:true token:&token]; [self doFadeOperation:FillScreen time:0.5f sync:true];
[NSMenu setMenuBarVisible:NO]; [NSMenu setMenuBarVisible:NO];
// Switch to the wished display mode // Switch to the wished display mode
CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode);
// Make all the SFML windows visible // Show the fullscreen window if existing
std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); if (myFullscreenWrapper)
std::vector<sf::priv::WindowImplCocoa *>::size_type idx; {
[[myFullscreenWrapper window] setAlphaValue:1.0f];
for (idx = 0; idx < sz; idx++) { [[myFullscreenWrapper window] center];
sf::priv::WindowImplCocoa *win = windows->at(idx);
if (win->IsFullscreen()) {
[static_cast <SFWindow *> (win->CocoaWindow()) setAlphaValue:1.0f];
[static_cast <SFWindow *> (win->CocoaWindow()) center];
}
} }
// Fade to normal screen // Fade to normal screen
[SharedAppController doFadeOperation:CleanScreen time:0.5f sync:false token:&token]; [self doFadeOperation:CleanScreen time:0.5f sync:false];
} }
} }
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
if (myFullscreenWrapper)
[self setFullscreenWindow:nil mode:NULL];
// FIXME: should I really do this ? what about the user owned windows ?
// And is this really useful as the application is about to exit ?
[NSApp makeWindowsPerform:@selector(close) inOrder:NO];
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Make menu bar /// Make menu bar
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -282,10 +243,10 @@ static AppController *shared = nil;
// Create the main menu bar // Create the main menu bar
[NSApp setMainMenu:[massert([NSMenu alloc]) init]]; [NSApp setMainMenu:[[NSMenu alloc] init]];
// Create the application menu // Create the application menu
appleMenu = [massert([NSMenu alloc]) initWithTitle:@""]; appleMenu = [[NSMenu alloc] initWithTitle:@""];
// Put menu items // Put menu items
// + 'About' menu item // + 'About' menu item
@ -317,15 +278,15 @@ static AppController *shared = nil;
// + 'Quit' menu item // + 'Quit' menu item
title = [@"Quit " stringByAppendingString:appName]; title = [@"Quit " stringByAppendingString:appName];
quitMenuItem = [[massert([NSMenuItem alloc]) quitMenuItem = [[[NSMenuItem alloc]
initWithTitle:title initWithTitle:title
action:@selector(quitApplication:) action:@selector(terminate:)
keyEquivalent:@"q"] autorelease]; keyEquivalent:@"q"] autorelease];
[quitMenuItem setTarget:self]; //[quitMenuItem setTarget:self];
[appleMenu addItem:quitMenuItem]; [appleMenu addItem:quitMenuItem];
// Put the menu into the menubar // Put the menu into the menubar
menuItem = [massert([NSMenuItem alloc]) menuItem = [[NSMenuItem alloc]
initWithTitle:@"" initWithTitle:@""
action:nil action:nil
keyEquivalent:@""]; keyEquivalent:@""];
@ -338,11 +299,11 @@ static AppController *shared = nil;
[appleMenu release]; [appleMenu release];
// 'File' menu // 'File' menu
fileMenu = [massert([NSMenu alloc]) fileMenu = [[NSMenu alloc]
initWithTitle:@"File"]; initWithTitle:@"File"];
// + 'Close' menu item // + 'Close' menu item
menuItem = [massert([NSMenuItem alloc]) menuItem = [[NSMenuItem alloc]
initWithTitle:@"Close" initWithTitle:@"Close"
action:@selector(performClose:) action:@selector(performClose:)
keyEquivalent:@"w"]; keyEquivalent:@"w"];
@ -350,7 +311,7 @@ static AppController *shared = nil;
[menuItem release]; [menuItem release];
// + 'File' menu item (head) // + 'File' menu item (head)
menuItem = [massert([NSMenuItem alloc]) menuItem = [[NSMenuItem alloc]
initWithTitle:@"File" initWithTitle:@"File"
action:nil action:nil
keyEquivalent:@""]; keyEquivalent:@""];
@ -359,11 +320,11 @@ static AppController *shared = nil;
[menuItem release]; [menuItem release];
// 'Window' menu // 'Window' menu
windowMenu = [massert([NSMenu alloc]) windowMenu = [[NSMenu alloc]
initWithTitle:@"Window"]; initWithTitle:@"Window"];
// + 'Minimize' menu item // + 'Minimize' menu item
menuItem = [massert([NSMenuItem alloc]) menuItem = [[NSMenuItem alloc]
initWithTitle:@"Minimize" initWithTitle:@"Minimize"
action:@selector(performMiniaturize:) action:@selector(performMiniaturize:)
keyEquivalent:@"m"]; keyEquivalent:@"m"];
@ -371,7 +332,7 @@ static AppController *shared = nil;
[menuItem release]; [menuItem release];
// + 'Window' menu item (head) // + 'Window' menu item (head)
menuItem = [massert([NSMenuItem alloc]) menuItem = [[NSMenuItem alloc]
initWithTitle:@"Window" initWithTitle:@"Window"
action:nil keyEquivalent:@""]; action:nil keyEquivalent:@""];
[menuItem setSubmenu:windowMenu]; [menuItem setSubmenu:windowMenu];
@ -385,127 +346,109 @@ static AppController *shared = nil;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Delegate method in order to prevent usual -terminate: /// Process all the events and send them to the application
//////////////////////////////////////////////////////////// /// No event is processed if the AppController instance is
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender /// not the owner of the event loop (ie: user made his own loop)
{
[self quitApplication:nil];
return NSTerminateCancel;
}
////////////////////////////////////////////////////////////
/// Get the events and put them into an array for each window
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)processEvents - (void)processEvents
{ {
// Release the main autorelease pool every second // Check there is a run loop
if (cleaner->GetElapsedTime() > 1.0f) { if (![NSApp isRunning])
cleaner->Reset(); {
[self resetPool]; // Get the ownershipt of event handling if not and run
[NSApp finishLaunching];
[NSApp setRunning:YES];
myOwningEventLoop = YES;
} }
// Clean the autorelease pool
[myMainPool release];
myMainPool = [[NSAutoreleasePool alloc] init];
NSEvent *event = nil; NSEvent *event = nil;
if (myOwningEventLoop)
{
// Minimal event loop
while (nil != (event = [NSApp nextEventMatchingMask:NSAnyEventMask while (nil != (event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:nil untilDate:nil
inMode:NSEventTrackingRunLoopMode inMode:NSEventTrackingRunLoopMode
dequeue:YES])) { dequeue:YES]))
NSWindow *keyWindow = [NSApp keyWindow]; {
if (keyWindow == nil) {
// Is there a fullscreen WindowImpl object ?
[NSApp sendEvent:event];
} else {
std::vector<sf::priv::WindowImplCocoa *>::size_type cnt = windows->size();
std::vector<sf::priv::WindowImplCocoa *>::size_type idx;
// is the key window a SFML window ?
for (idx = 0;idx < cnt; idx++) {
sf::priv::WindowImplCocoa *ptr = windows->at(idx);;
if (ptr->CocoaWindow() == keyWindow) {
// yup, it is
ptr->HandleEvent(static_cast <void *> (event));
break;
}
}
// nop, it isn't
if (idx == cnt) {
[NSApp sendEvent:event]; [NSApp sendEvent:event];
} }
} }
} }
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Add the 'windowImplObj' object to the list of known windows /// Set @window as the current fullscreen window
/// Change the screen resolution if needed according to @window and @fullscreenMode
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void)registerWindow:(sf::priv::WindowImplCocoa *)windowImplObj - (void)setFullscreenWindow:(WindowWrapper *)aWrapper mode:(sf::VideoMode *)fullscreenMode
{ {
// If we have a fullscreen window and want to remove it
if (windowImplObj != NULL) { if (myFullscreenWrapper && aWrapper == nil)
std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size();
std::vector<sf::priv::WindowImplCocoa *>::size_type idx;
for (idx = 0; idx < sz; idx++) {
if (windows->at(idx) == windowImplObj) {
break;
}
}
// Register window only if not already registered
if (sz == idx) {
windows->push_back(windowImplObj);
}
}
}
////////////////////////////////////////////////////////////
/// Remove the 'windowImplObj' object from the list of known windows
////////////////////////////////////////////////////////////
- (void)unregisterWindow:(sf::priv::WindowImplCocoa *)windowImplObj
{ {
if (windowImplObj != NULL) { // Get the CoreGraphics display mode according to the desktop mode
std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay,
std::vector<sf::priv::WindowImplCocoa *>::size_type idx; myDesktopMode.BitsPerPixel,
myDesktopMode.Width,
myDesktopMode.Height,
NULL);
for (idx = 0; idx < sz; idx++) { // Fade to black screen
if (windows->at(idx) == windowImplObj) { [self doFadeOperation:FillScreen time:0.2f sync:true];
break;
}
}
if (idx < sz) { // Switch to the desktop display mode
windows->erase(windows->begin() + idx); CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode);
}
}
}
// Close the window
[[myFullscreenWrapper window] close];
//////////////////////////////////////////////////////////// // Show the menu bar
/// Return true is one of the registered window is a full screen one [NSMenu setMenuBarVisible:YES];
////////////////////////////////////////////////////////////
- (bool)isUsingFullscreen // Fade to normal screen
[self doFadeOperation:CleanScreen time:0.5f sync:true];
// Release the saved window wrapper
[myFullscreenWrapper release], myFullscreenWrapper = nil;
}
else if (myFullscreenWrapper == nil && aWrapper)
{ {
bool isUsing = false; assert(fullscreenMode != NULL);
std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size();
std::vector<sf::priv::WindowImplCocoa *>::size_type idx;
for (idx = 0; idx < sz; idx++) { // Get the CoreGraphics display mode according to the given sf mode
sf::priv::WindowImplCocoa *win = windows->at(idx); CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay,
if (win && win->IsFullscreen()) { fullscreenMode->BitsPerPixel,
isUsing = true; fullscreenMode->Width,
break; fullscreenMode->Height,
} NULL);
}
return isUsing; // Fade to a black screen
[self doFadeOperation:FillScreen time:0.5f sync:true];
// Hide to the main menu bar
[NSMenu setMenuBarVisible:NO];
// Switch to the wished display mode
CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode);
// Open and center the window
[[aWrapper window] makeKeyAndOrderFront:nil];
[[aWrapper window] center];
// Fade to normal screen
[self doFadeOperation:CleanScreen time:0.2f sync:false];
// Save the fullscreen wrapper
myFullscreenWrapper = [aWrapper retain];
}
else
{
std::cerr << "Inconcistency error for arguments given to -[AppController setFullscreenWindow:mode:]" << std::endl;
}
} }
@ -517,11 +460,10 @@ static AppController *shared = nil;
/// using this method for the first time. This lets the method release some /// using this method for the first time. This lets the method release some
/// resources when doing CleanScreen operation. /// resources when doing CleanScreen operation.
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
- (void) doFadeOperation:(int)operation time:(float)time sync:(bool)sync token:(CGDisplayFadeReservationToken *)prevToken - (void) doFadeOperation:(int)operation time:(float)time sync:(bool)sync
{ {
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken; static CGDisplayFadeReservationToken prevToken = kCGDisplayFadeReservationInvalidToken;
if (prevToken) CGDisplayFadeReservationToken token = prevToken;
token = *prevToken;
CGError result = 0, capture = 0; CGError result = 0, capture = 0;
@ -539,7 +481,7 @@ static AppController *shared = nil;
CGDisplayFade(token, time, CGDisplayFade(token, time,
kCGDisplayBlendNormal, kCGDisplayBlendNormal,
kCGDisplayBlendSolidColor, kCGDisplayBlendSolidColor,
0.0, 0.0, 0.0, sync); 0.0f, 0.0f, 0.0f, sync);
// Now, release the non black-filling capture // Now, release the non black-filling capture
CGDisplayRelease(kCGDirectMainDisplay); CGDisplayRelease(kCGDirectMainDisplay);
@ -549,8 +491,7 @@ static AppController *shared = nil;
CGDisplayCaptureWithOptions(kCGDirectMainDisplay, kCGCaptureNoOptions); CGDisplayCaptureWithOptions(kCGDirectMainDisplay, kCGCaptureNoOptions);
} }
if (prevToken) prevToken = token;
*prevToken = token;
} }
} else if (operation == CleanScreen) { } else if (operation == CleanScreen) {
// Get access for the fade operation // Get access for the fade operation
@ -569,14 +510,13 @@ static AppController *shared = nil;
CGDisplayFade(token, time, CGDisplayFade(token, time,
kCGDisplayBlendSolidColor, kCGDisplayBlendSolidColor,
kCGDisplayBlendNormal, kCGDisplayBlendNormal,
0.0, 0.0, 0.0, sync); 0.0f, 0.0f, 0.0f, sync);
// Release the fade operation token // Release the fade operation token
CGReleaseDisplayFadeReservation(token); CGReleaseDisplayFadeReservation(token);
// Invalidate the given token // Invalidate the given token
if (prevToken) prevToken = kCGDisplayFadeReservationInvalidToken;
*prevToken = kCGDisplayFadeReservationInvalidToken;
} }
// Release the captured display // Release the captured display
@ -585,15 +525,14 @@ static AppController *shared = nil;
} }
} }
////////////////////////////////////////////////////////////
/// Return the desktop video mode (made at the instance initialization)
////////////////////////////////////////////////////////////
- (const sf::VideoMode&)desktopMode
{
return myDesktopMode;
}
@end @end
template <typename T>
T *massert(T *ptr)
{
if (NULL == ptr) {
throw std::bad_alloc();
}
return ptr;
}

View File

@ -0,0 +1,216 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Lucas Soltic (ceylow@gmail.com) and Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#import <Cocoa/Cocoa.h>
#import <SFML/Window/Cocoa/WindowImplCocoa.hpp>
////////////////////////////////////////////////////////////
/// Window independant OpenGL context class
////////////////////////////////////////////////////////////
@interface GLContext : NSOpenGLContext
{
GLContext *mySharedContext;
}
////////////////////////////////////////////////////////////
/// Return the shared OpenGL context instance (making one if needed)
////////////////////////////////////////////////////////////
+ (id)sharedContext;
////////////////////////////////////////////////////////////
/// Make a new OpenGL context according to the @attribs settings
/// and the shared context @context
////////////////////////////////////////////////////////////
- (id)initWithAttributes:(sf::WindowSettings&)attribs
sharedContext:(GLContext *)context;
@end
////////////////////////////////////////////////////////////
/// Customized Cocoa OpenGL view
////////////////////////////////////////////////////////////
@interface GLView : NSOpenGLView
{
sf::priv::WindowImplCocoa *myDelegate;
GLContext *myGLContext;
}
////////////////////////////////////////////////////////////
/// Make a new view according the the rect @frame,
/// the video mode @mode, the window settings @settings
/// and the sf window delegate @delegate
/// @delegate must not be null
////////////////////////////////////////////////////////////
- (id)initWithFrame:(NSRect)frame
mode:(const sf::VideoMode&)mode
settings:(sf::WindowSettings&)settings
delegate:(sf::priv::WindowImplCocoa *)delegate;
////////////////////////////////////////////////////////////
/// Finish view setting (after having added it to the window)
////////////////////////////////////////////////////////////
- (void)finishInitialization;
////////////////////////////////////////////////////////////
/// Forward call to en/disable vertical synchronization
////////////////////////////////////////////////////////////
- (void)enableVerticalSync:(bool)flag;
////////////////////////////////////////////////////////////
/// Forward call to set the OpenGL context as active according to @flag
////////////////////////////////////////////////////////////
- (void)setActive:(bool)flag;
////////////////////////////////////////////////////////////
/// Forward call to flush the OpenGL context
////////////////////////////////////////////////////////////
- (void)flushBuffer;
@end
////////////////////////////////////////////////////////////
/// Cocoa window implementation to let fullscreen windows
/// catch key events
////////////////////////////////////////////////////////////
@interface GLWindow : NSWindow
////////////////////////////////////////////////////////////
/// Technical note: this class must neither contain new members
/// nor methods. It is used transparently as a NSWindow object
/// by WindowWrapper. Not following this rule could result
/// in a segmentation fault or data corruption.
////////////////////////////////////////////////////////////
@end
////////////////////////////////////////////////////////////
/// WindowWrapper class : handles both imported and self-built windows
////////////////////////////////////////////////////////////
@interface WindowWrapper : NSObject
{
GLWindow *myWindow;
GLView *myView;
sf::VideoMode myFullscreenMode;
bool myIsFullscreen;
}
////////////////////////////////////////////////////////////
/// Make a new window wrapper according to the window settings @attribs,
/// the video mode @mode, the window style @style, the window title @title
/// and the sf window implementation delegate @delegate
////////////////////////////////////////////////////////////
- (id)initWithSettings:(sf::WindowSettings&)attribs
videoMode:(sf::VideoMode&)mode
style:(unsigned long)style
title:(NSString *)title
delegate:(sf::priv::WindowImplCocoa *)delegate;
////////////////////////////////////////////////////////////
/// Make a new window wrapper by importing @window and according to
/// the window settings @params and the sf window implementation delegate
/// @delegate
/// @window and @delegate must not be null
////////////////////////////////////////////////////////////
- (id)initWithWindow:(NSWindow *)window
settings:(sf::WindowSettings&)params
delegate:(sf::priv::WindowImplCocoa *)delegate;
////////////////////////////////////////////////////////////
/// Make a new window wrapper by importing @window if it's not null and according to
/// the window settings @params and the sf window implementation delegate
/// @delegate; or by creating a new window if @window is null. In this case @title
/// must therefore not be null and @params must be valid.
/// @delegate must never be null
////////////////////////////////////////////////////////////
- (id)initWithWindow:(NSWindow *)window
settings:(sf::WindowSettings&)params
videoMode:(sf::VideoMode&)mode
style:(unsigned long)style
title:(NSString *)title
delegate:(sf::priv::WindowImplCocoa *)delegate;
////////////////////////////////////////////////////////////
/// Finish the window setup (without knowing whether it's a imported
/// window)
////////////////////////////////////////////////////////////
/* - (void)setupGLViewAndWindow; */
////////////////////////////////////////////////////////////
/// Return a reference to the internal Cocoa window
////////////////////////////////////////////////////////////
- (NSWindow *)window;
////////////////////////////////////////////////////////////
/// Return a reference to the internal Cocoa OpenGL view
////////////////////////////////////////////////////////////
- (GLView *)glView;
////////////////////////////////////////////////////////////
/// Forward call to set the window position on screen
////////////////////////////////////////////////////////////
- (void)setPosition:(NSPoint)pos;
////////////////////////////////////////////////////////////
/// Forward call to set the window size
////////////////////////////////////////////////////////////
- (void)setSize:(NSSize)size;
////////////////////////////////////////////////////////////
/// Return the mouse location relative to the internal window
////////////////////////////////////////////////////////////
- (NSPoint)mouseLocation;
////////////////////////////////////////////////////////////
/// Return whether the mouse is on our window
////////////////////////////////////////////////////////////
- (BOOL)mouseInside;
////////////////////////////////////////////////////////////
/// Close or open the window
////////////////////////////////////////////////////////////
- (void)show:(bool)flag;
////////////////////////////////////////////////////////////
/// Forward call to en/disable the OpenGL view vertical synchronization
////////////////////////////////////////////////////////////
- (void)enableVerticalSync:(bool)flag;
////////////////////////////////////////////////////////////
/// Forward 'setActive' call the the OpenGL view
////////////////////////////////////////////////////////////
- (void)setActive:(bool)flag;
////////////////////////////////////////////////////////////
/// Forward call to flush the OpenGL view
////////////////////////////////////////////////////////////
- (void)flushBuffer;
@end

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// //
// SFML - Simple and Fast Multimedia Library // SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2008 Lucas Soltic (elmerod@gmail.com) and Laurent Gomila (laurent.gom@gmail.com) // Copyright (C) 2007-2009 Lucas Soltic (ceylow@gmail.com) and Laurent Gomila (laurent.gom@gmail.com)
// //
// This software is provided 'as-is', without any express or implied warranty. // This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software. // In no event will the authors be held liable for any damages arising from the use of this software.
@ -32,13 +32,16 @@
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <string> #include <string>
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
@class WindowWrapper;
#endif
namespace sf namespace sf
{ {
namespace priv namespace priv
{ {
typedef struct objc_members objc_members;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// WindowImplCocoa is the Cocoa implementation of WindowImpl /// WindowImplCocoa is the Cocoa implementation of WindowImpl
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -88,25 +91,23 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static bool IsContextActive(); static bool IsContextActive();
////////////////////////////////////////////////////////////
/// Handle Cocoa NSEvent
////////////////////////////////////////////////////////////
void HandleEvent(void *eventRef);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Handle an event sent by the default NSNotificationCenter /// Handle an event sent by the default NSNotificationCenter
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void HandleNotifiedEvent(Event& eventRef); void HandleNotifiedEvent(Event& eventRef);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Return a pointer to the NSWindow (objc->windowHandle) object /// Event handling for every event type.
/// 'eventRef' is a NSEvent.
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void *CocoaWindow(void); void HandleKeyDown(void *eventRef);
void HandleKeyUp(void *eventRef);
void HandleModifierKey(void *eventRef);
void HandleMouseDown(void *eventRef);
void HandleMouseUp(void *eventRef);
void HandleMouseMove(void *eventRef);
void HandleMouseWheel(void *eventRef);
////////////////////////////////////////////////////////////
/// Return whether the window is in full screen mode
////////////////////////////////////////////////////////////
bool IsFullscreen(void);
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -182,38 +183,19 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/// Event handling for every event type.
/// 'eventRef' is a NSEvent.
////////////////////////////////////////////////////////////
int HandleKeyDown(void *eventRef);
int HandleKeyUp(void *eventRef);
int HandleModifierKey(void *eventRef);
int HandleMouseDown(void *eventRef);
int HandleMouseUp(void *eventRef);
int HandleMouseMove(void *eventRef);
int HandleMouseWheel(void *eventRef);
////////////////////////////////////////////////////////////
/// Make some allocations and initializations
////////////////////////////////////////////////////////////
void Initialize(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// An opaque structure that contains all obj-C objects #ifdef __OBJC__
objc_members *members; WindowWrapper *myWrapper;
#else
void *myWrapper;
#endif
bool useKeyRepeat; bool myUseKeyRepeat;
bool mouseIn; bool myMouseIn;
float wheelStatus; float myWheelStatus;
bool fullscreen;
VideoMode fullscreenMode;
VideoMode desktopMode;
}; };
} // namespace priv } // namespace priv

File diff suppressed because it is too large Load Diff