diff options
author | Christoph Egger <Christoph.Egger@gmx.de> | 2009-06-14 21:52:32 +0200 |
---|---|---|
committer | Christoph Egger <Christoph.Egger@gmx.de> | 2009-06-14 21:52:32 +0200 |
commit | af202195872d59432cb74db74696bf1e57906663 (patch) | |
tree | 6606f4a90e91811e940f9fbc2e88a43154271939 /src/SFML/Window | |
parent | 9f9ee9c9f37ae026eb06e897a313aa26f68bf612 (diff) |
Imported Upstream version 1.5+repack1
Diffstat (limited to 'src/SFML/Window')
36 files changed, 2719 insertions, 1750 deletions
diff --git a/src/SFML/Window/Cocoa/AppController.h b/src/SFML/Window/Cocoa/AppController.h index 365afc9..f56db4e 100755 --- a/src/SFML/Window/Cocoa/AppController.h +++ b/src/SFML/Window/Cocoa/AppController.h @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // 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. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -26,12 +26,8 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#import <SFML/Window/Cocoa/WindowImplCocoa.hpp> #import <SFML/Window/VideoMode.hpp> -#import <SFML/System/Clock.hpp> #import <Cocoa/Cocoa.h> -#import <vector> -#import <iostream> #define SharedAppController [AppController sharedController] @@ -42,80 +38,50 @@ enum { CleanScreen }; - +@class WindowWrapper; @interface AppController : NSObject { - // Note: objc allocation doesn't call C++ constructor - std::vector <sf::priv::WindowImplCocoa *> *windows; - - NSAutoreleasePool *mainPool; - sf::Clock *cleaner; - sf::VideoMode desktopMode; - sf::VideoMode prevMode; + BOOL myOwningEventLoop; + WindowWrapper *myFullscreenWrapper; + NSAutoreleasePool *myMainPool; + sf::VideoMode myDesktopMode; + sf::VideoMode myPrevMode; } //////////////////////////////////////////////////////////// -/// Return the shared AppController object. Makes one if needed +/// Return the shared AppController instance. Make one if needed. //////////////////////////////////////////////////////////// + (AppController *)sharedController; //////////////////////////////////////////////////////////// -/// Reallocate main pool to release autoreleased objects -//////////////////////////////////////////////////////////// -- (void)resetPool; - -//////////////////////////////////////////////////////////// -/// Register our application and launch it if needed -//////////////////////////////////////////////////////////// -- (void)runApplication; - -//////////////////////////////////////////////////////////// -/// Terminate the current running application -//////////////////////////////////////////////////////////// -- (void)quitApplication:(id)sender; - -//////////////////////////////////////////////////////////// -/// Make menu bar +/// Make the menu bar //////////////////////////////////////////////////////////// - (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; //////////////////////////////////////////////////////////// -/// 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; - -//////////////////////////////////////////////////////////// -/// 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; +- (void)setFullscreenWindow:(WindowWrapper *)window mode:(sf::VideoMode *)fullscreenMode; //////////////////////////////////////////////////////////// /// Perform fade operation where 'operation' is one of { FillScreen, CleanScreen} /// 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 -/// of the fade operation. Pass the last used token or a new one if you are -/// using this method for the first time. This lets the method release some -/// resources when doing CleanScreen operation. +/// of the fade operation. //////////////////////////////////////////////////////////// -- (void)doFadeOperation:(int)operation time:(float)time sync:(bool)sync token:(CGDisplayFadeReservationToken *)prevToken; - -@end - +- (void)doFadeOperation:(int)operation time:(float)time sync:(bool)sync; //////////////////////////////////////////////////////////// -/// check that ptr is valid, otherwise print msg in -/// std::cerr and throw std::bad_alloc. -/// Must be used to check alloc results +/// Return the desktop video mode (made at the instance initialization) //////////////////////////////////////////////////////////// -template <typename T> -T *massert(T *ptr); +- (const sf::VideoMode&)desktopMode; + +@end diff --git a/src/SFML/Window/Cocoa/AppController.mm b/src/SFML/Window/Cocoa/AppController.mm index a6b7310..8d07eaf 100755 --- a/src/SFML/Window/Cocoa/AppController.mm +++ b/src/SFML/Window/Cocoa/AppController.mm @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // 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. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -27,14 +27,13 @@ // Headers //////////////////////////////////////////////////////////// #import <SFML/Window/Cocoa/AppController.h> -#import <SFML/Window/Cocoa/WindowController.h> -#import <SFML/Window/Cocoa/WindowImplCocoa.hpp> +#import <SFML/Window/Cocoa/GLKit.h> #import <SFML/System.hpp> #import <ApplicationServices/ApplicationServices.h> #import <iostream> -// AppController singleton +// AppController singleton object static AppController *shared = nil; @@ -45,6 +44,8 @@ static AppController *shared = nil; @end #endif +#define ENABLE_FADE_OPERATIONS 1 + @implementation NSApplication (SFML) - (void)setRunning:(BOOL)flag @@ -61,160 +62,120 @@ static AppController *shared = nil; @implementation AppController + +//////////////////////////////////////////////////////////// +/// Return an initialized AppController instance +/// Save the desktop mode +/// Make the main autorelease pool +/// Set the application observer +//////////////////////////////////////////////////////////// - (id)init { self = [super init]; if (self != nil) { - windows = new std::vector <sf::priv::WindowImplCocoa *>; - cleaner = new sf::Clock; + myOwningEventLoop = NO; + + // Save the desktop mode + myDesktopMode = sf::VideoMode::GetDesktopMode(); + myPrevMode = myDesktopMode; + + // Make the app autorelease pool + myMainPool = [[NSAutoreleasePool alloc] init]; + + // Don't go on if the user handles the app + if (![NSApp isRunning]) + { + // Force our application to appear in the Dock and make it able + // to get focus (even when it's a raw executable) + ProcessSerialNumber psn; + + if (!GetCurrentProcess(&psn)) { + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + SetFrontProcess(&psn); + } + + // Make the app + [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) { + [self makeMenuBar]; + } + } } return self; } +//////////////////////////////////////////////////////////// +/// Clean the controller +//////////////////////////////////////////////////////////// - (void)dealloc { - delete windows; - delete cleaner; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [myFullscreenWrapper release]; [super dealloc]; } //////////////////////////////////////////////////////////// -/// Return the shared AppController object. Makes one if needed +/// Return the shared AppController instance. Make one if needed. //////////////////////////////////////////////////////////// + (AppController *)sharedController { - if (nil == shared) { - shared = [massert([AppController alloc]) init]; - } + if (nil == shared) + shared = [[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; - - if (!GetCurrentProcess(&psn)) { - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - SetFrontProcess(&psn); - } - - if (NSApp == nil) { - massert([NSApplication sharedApplication]); - } - - if ([NSApp mainMenu] == nil) { - [self makeMenuBar]; - } - - [NSApp finishLaunching]; - [NSApp setRunning:YES]; - [NSApp setDelegate:self]; - - desktopMode = sf::VideoMode::GetDesktopMode(); -} - - -//////////////////////////////////////////////////////////// -/// Terminate the current running application -//////////////////////////////////////////////////////////// -- (void)quitApplication:(id)sender -{ - // Close all windows - // SFML user has to detect when all windows are closed - NSWindow *current = nil; - 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 -//////////////////////////////////////////////////////////// -- (SFWindow *)fullscreenWindow -{ - SFWindow *window = 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++) { - 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 { - if ([self isUsingFullscreen]) { - prevMode = sf::VideoMode::GetDesktopMode(); + if (myFullscreenWrapper) { + myPrevMode = sf::VideoMode::GetDesktopMode(); CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay, - desktopMode.BitsPerPixel, - desktopMode.Width, - desktopMode.Height, + myDesktopMode.BitsPerPixel, + myDesktopMode.Width, + myDesktopMode.Height, NULL); - CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken; - // 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 - std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); - 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]; - } - } + // Make the full screen window unvisible + [[myFullscreenWrapper window] setAlphaValue:0.0f]; // Switch to the wished display mode CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); // Fade to normal screen - [SharedAppController doFadeOperation:CleanScreen time:0.5f sync:false token:&token]; + [self doFadeOperation:CleanScreen time:0.5f sync:false]; } } @@ -224,41 +185,43 @@ static AppController *shared = nil; //////////////////////////////////////////////////////////// - (void)applicationWillUnhide:(NSNotification *)aNotification { - if ([self isUsingFullscreen]) { + if (myFullscreenWrapper) { CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay, - prevMode.BitsPerPixel, - prevMode.Width, - prevMode.Height, + myPrevMode.BitsPerPixel, + myPrevMode.Width, + myPrevMode.Height, NULL); - CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken; - // 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]; // Switch to the wished display mode CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); - // Make all the SFML windows visible - std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); - 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:1.0f]; - [static_cast <SFWindow *> (win->CocoaWindow()) center]; - } + // Show the fullscreen window if existing + if (myFullscreenWrapper) + { + [[myFullscreenWrapper window] setAlphaValue:1.0f]; + [[myFullscreenWrapper window] center]; } // 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 //////////////////////////////////////////////////////////// @@ -282,10 +245,10 @@ static AppController *shared = nil; // Create the main menu bar - [NSApp setMainMenu:[massert([NSMenu alloc]) init]]; + [NSApp setMainMenu:[[NSMenu alloc] init]]; // Create the application menu - appleMenu = [massert([NSMenu alloc]) initWithTitle:@""]; + appleMenu = [[NSMenu alloc] initWithTitle:@""]; // Put menu items // + 'About' menu item @@ -303,7 +266,7 @@ static AppController *shared = nil; keyEquivalent:@"h"]; // + 'Hide other' menu item - menuItem = static_cast <NSMenuItem *> ([appleMenu addItemWithTitle:@"Hide Others" + menuItem = reinterpret_cast <NSMenuItem *> ([appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]); [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; @@ -317,15 +280,15 @@ static AppController *shared = nil; // + 'Quit' menu item title = [@"Quit " stringByAppendingString:appName]; - quitMenuItem = [[massert([NSMenuItem alloc]) + quitMenuItem = [[[NSMenuItem alloc] initWithTitle:title - action:@selector(quitApplication:) + action:@selector(terminate:) keyEquivalent:@"q"] autorelease]; - [quitMenuItem setTarget:self]; + //[quitMenuItem setTarget:self]; [appleMenu addItem:quitMenuItem]; // Put the menu into the menubar - menuItem = [massert([NSMenuItem alloc]) + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; @@ -338,11 +301,11 @@ static AppController *shared = nil; [appleMenu release]; // 'File' menu - fileMenu = [massert([NSMenu alloc]) + fileMenu = [[NSMenu alloc] initWithTitle:@"File"]; // + 'Close' menu item - menuItem = [massert([NSMenuItem alloc]) + menuItem = [[NSMenuItem alloc] initWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"]; @@ -350,7 +313,7 @@ static AppController *shared = nil; [menuItem release]; // + 'File' menu item (head) - menuItem = [massert([NSMenuItem alloc]) + menuItem = [[NSMenuItem alloc] initWithTitle:@"File" action:nil keyEquivalent:@""]; @@ -359,11 +322,11 @@ static AppController *shared = nil; [menuItem release]; // 'Window' menu - windowMenu = [massert([NSMenu alloc]) + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; // + 'Minimize' menu item - menuItem = [massert([NSMenuItem alloc]) + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; @@ -371,7 +334,7 @@ static AppController *shared = nil; [menuItem release]; // + 'Window' menu item (head) - menuItem = [massert([NSMenuItem alloc]) + menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; [menuItem setSubmenu:windowMenu]; @@ -385,143 +348,143 @@ static AppController *shared = nil; //////////////////////////////////////////////////////////// -/// Delegate method in order to prevent usual -terminate: -//////////////////////////////////////////////////////////// -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -{ - [self quitApplication:nil]; - return NSTerminateCancel; -} - - -//////////////////////////////////////////////////////////// -/// 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 { - // Release the main autorelease pool every second - if (cleaner->GetElapsedTime() > 1.0f) { - cleaner->Reset(); - [self resetPool]; + // Check there is a run loop + if (![NSApp isRunning]) + { + // 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; - while (nil != (event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:nil - inMode:NSEventTrackingRunLoopMode - dequeue:YES])) { - NSWindow *keyWindow = [NSApp keyWindow]; - - if (keyWindow == nil) { - // Is there a fullscreen WindowImpl object ? + if (myOwningEventLoop) + { + // Minimal event loop + while (nil != (event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES])) + { [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]; - } } } } //////////////////////////////////////////////////////////// -/// 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 (windowImplObj != NULL) { - std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); - std::vector<sf::priv::WindowImplCocoa *>::size_type idx; + // If we have a fullscreen window and want to remove it + if (aWrapper == nil && myFullscreenWrapper) + { + // Get the CoreGraphics display mode according to the desktop mode + CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay, + myDesktopMode.BitsPerPixel, + myDesktopMode.Width, + myDesktopMode.Height, + NULL); - for (idx = 0; idx < sz; idx++) { - if (windows->at(idx) == windowImplObj) { - break; - } - } +#if ENABLE_FADE_OPERATIONS + // Fade to black screen + [self doFadeOperation:FillScreen time:0.2f sync:true]; +#endif + // Switch to the desktop display mode + CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); - // Register window only if not already registered - if (sz == idx) { - windows->push_back(windowImplObj); - } + // Close the window + [[myFullscreenWrapper window] close]; + + // Show the menu bar + [NSMenu setMenuBarVisible:YES]; + +#if ENABLE_FADE_OPERATIONS + // Fade to normal screen + [self doFadeOperation:CleanScreen time:0.5f sync:true]; +#endif + + // Release the saved window wrapper + myFullscreenWrapper = nil; } -} - - -//////////////////////////////////////////////////////////// -/// Remove the 'windowImplObj' object from the list of known windows -//////////////////////////////////////////////////////////// -- (void)unregisterWindow:(sf::priv::WindowImplCocoa *)windowImplObj -{ - if (windowImplObj != NULL) { - std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); - std::vector<sf::priv::WindowImplCocoa *>::size_type idx; + else if (aWrapper) + { + assert(fullscreenMode != NULL); - for (idx = 0; idx < sz; idx++) { - if (windows->at(idx) == windowImplObj) { - break; - } + // Get the CoreGraphics display mode according to the given sf mode + CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay, + fullscreenMode->BitsPerPixel, + fullscreenMode->Width, + fullscreenMode->Height, + NULL); + +#if ENABLE_FADE_OPERATIONS + // Fade to a black screen + [self doFadeOperation:FillScreen time:0.5f sync:true]; +#endif + + if (!myFullscreenWrapper) + { + // Hide the main menu bar + [NSMenu setMenuBarVisible:NO]; } - if (idx < sz) { - windows->erase(windows->begin() + idx); + if (myPrevMode != *fullscreenMode) + { + // Switch to the wished display mode + CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); } - } -} - - -//////////////////////////////////////////////////////////// -/// Return true is one of the registered window is a full screen one -//////////////////////////////////////////////////////////// -- (bool)isUsingFullscreen -{ - bool isUsing = false; - std::vector<sf::priv::WindowImplCocoa *>::size_type sz = windows->size(); - std::vector<sf::priv::WindowImplCocoa *>::size_type idx; - - for (idx = 0; idx < sz; idx++) { - sf::priv::WindowImplCocoa *win = windows->at(idx); - if (win && win->IsFullscreen()) { - isUsing = true; - break; + + if (myFullscreenWrapper) + { + [[myFullscreenWrapper window] close]; } + + // Open and center the window + [[aWrapper window] makeKeyAndOrderFront:nil]; + [[aWrapper window] center]; + +#if ENABLE_FADE_OPERATIONS + // Fade to normal screen + [self doFadeOperation:CleanScreen time:0.2f sync:false]; +#endif + + // Save the fullscreen wrapper + myFullscreenWrapper = aWrapper; + } + else + { + std::cerr << "Inconcistency error for arguments given to -[AppController setFullscreenWindow:mode:]" << std::endl; } - - return isUsing; } //////////////////////////////////////////////////////////// -/// 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. /// 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 /// 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 { - CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken; - if (prevToken) - token = *prevToken; + static CGDisplayFadeReservationToken prevToken = kCGDisplayFadeReservationInvalidToken; + CGDisplayFadeReservationToken token = prevToken; CGError result = 0, capture = 0; @@ -539,7 +502,7 @@ static AppController *shared = nil; CGDisplayFade(token, time, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, - 0.0, 0.0, 0.0, sync); + 0.0f, 0.0f, 0.0f, sync); // Now, release the non black-filling capture CGDisplayRelease(kCGDirectMainDisplay); @@ -549,8 +512,7 @@ static AppController *shared = nil; CGDisplayCaptureWithOptions(kCGDirectMainDisplay, kCGCaptureNoOptions); } - if (prevToken) - *prevToken = token; + prevToken = token; } } else if (operation == CleanScreen) { // Get access for the fade operation @@ -569,14 +531,13 @@ static AppController *shared = nil; CGDisplayFade(token, time, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, - 0.0, 0.0, 0.0, sync); + 0.0f, 0.0f, 0.0f, sync); // Release the fade operation token CGReleaseDisplayFadeReservation(token); // Invalidate the given token - if (prevToken) - *prevToken = kCGDisplayFadeReservationInvalidToken; + prevToken = kCGDisplayFadeReservationInvalidToken; } // Release the captured display @@ -585,15 +546,14 @@ static AppController *shared = nil; } } -@end - -template <typename T> -T *massert(T *ptr) +//////////////////////////////////////////////////////////// +/// Return the desktop video mode (made at the instance initialization) +//////////////////////////////////////////////////////////// +- (const sf::VideoMode&)desktopMode { - if (NULL == ptr) { - throw std::bad_alloc(); - } - - return ptr; + return myDesktopMode; } + +@end + diff --git a/src/SFML/Window/Cocoa/GLKit.h b/src/SFML/Window/Cocoa/GLKit.h new file mode 100755 index 0000000..ac12252 --- /dev/null +++ b/src/SFML/Window/Cocoa/GLKit.h @@ -0,0 +1,209 @@ +//////////////////////////////////////////////////////////// +// +// 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; + +//////////////////////////////////////////////////////////// +/// 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 + diff --git a/src/SFML/Window/Cocoa/GLKit.mm b/src/SFML/Window/Cocoa/GLKit.mm new file mode 100755 index 0000000..a570f44 --- /dev/null +++ b/src/SFML/Window/Cocoa/GLKit.mm @@ -0,0 +1,854 @@ +//////////////////////////////////////////////////////////// +// +// 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 <SFML/Window/Cocoa/GLKit.h> +#import <SFML/Window/Cocoa/AppController.h> +#import <SFML/Window/VideoMode.hpp> +#import <SFML/Window/WindowStyle.hpp> +#import <SFML/System/Sleep.hpp> +#import <OpenGL/gl.h> +#import <iostream> + + +//////////////////////////////////////////////////////////// +/// Window independant OpenGL context class +//////////////////////////////////////////////////////////// +@implementation GLContext + +static GLContext *sharedCtx = nil; + +//////////////////////////////////////////////////////////// +/// Return the shared OpenGL context instance (making one if needed) +//////////////////////////////////////////////////////////// ++ (id)sharedContext +{ + if (sharedCtx == nil) + { + // Make a new context with the default parameters + sf::WindowSettings params(0, 0, 0); + sharedCtx = [[GLContext alloc] initWithAttributes:params sharedContext:nil]; + } + + return sharedCtx; +} + +- (void)dealloc +{ + [mySharedContext release]; + [super dealloc]; +} + +//////////////////////////////////////////////////////////// +/// Make a new OpenGL context according to the @attribs settings +/// and the shared context @context +//////////////////////////////////////////////////////////// +- (id)initWithAttributes:(sf::WindowSettings&)attribs sharedContext:(GLContext *)context +{ + // Note about antialiasing and other context attributes : + // OpenGL context sharing does not allow the shared contexts to use different attributes. + // The point is that the default shared global OpenGL context uses default parameters. + // That means that all the other context *should* use the same paramaters. + // Fortunately some values parameters for some parameters are compatible, but some are not + // among which : the antialising level. + // + // I've no way to fix this for now. + + if (attribs.AntialiasingLevel) + std::cerr << "Warning: antialiasing settings are inhibited under Mac OS X for technical reasons" << std::endl; + + NSOpenGLPixelFormat *myPixelFormat = nil; + unsigned idx = 0; + + // Attributes list + NSOpenGLPixelFormatAttribute ctxtAttribs[15] = {(NSOpenGLPixelFormatAttribute) 0}; + + // Accelerated, double buffered + ctxtAttribs[idx++] = NSOpenGLPFAClosestPolicy; + ctxtAttribs[idx++] = NSOpenGLPFADoubleBuffer; + ctxtAttribs[idx++] = NSOpenGLPFAAccelerated; + + // windowed context (even fullscreen mode uses a window) + ctxtAttribs[idx++] = NSOpenGLPFAWindow; + + // Color size ; usually 32 bits per pixel + ctxtAttribs[idx++] = NSOpenGLPFAColorSize; + ctxtAttribs[idx++] = (NSOpenGLPixelFormatAttribute) sf::VideoMode::GetDesktopMode().BitsPerPixel; + + // Z-buffer size + ctxtAttribs[idx++] = NSOpenGLPFADepthSize; + ctxtAttribs[idx++] = (NSOpenGLPixelFormatAttribute) attribs.DepthBits; + + // Stencil bits (I don't really know what's that...) + ctxtAttribs[idx++] = NSOpenGLPFAStencilSize; + ctxtAttribs[idx++] = (NSOpenGLPixelFormatAttribute) attribs.StencilBits; + + myPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:ctxtAttribs]; + + if (myPixelFormat) { + self = [super initWithFormat:myPixelFormat + shareContext:context]; + + mySharedContext = [context retain]; + + // Get the effective properties from our OpenGL context + GLint tmpDepthSize = 0, tmpStencilBits = 0, tmpAntialiasingLevel = 0; + + if (self) { + [myPixelFormat getValues:&tmpDepthSize + forAttribute:NSOpenGLPFADepthSize + forVirtualScreen:[self currentVirtualScreen]]; + + [myPixelFormat getValues:&tmpStencilBits + forAttribute:NSOpenGLPFAStencilSize + forVirtualScreen:[self currentVirtualScreen]]; + + [myPixelFormat getValues:&tmpAntialiasingLevel + forAttribute:NSOpenGLPFASamples + forVirtualScreen:[self currentVirtualScreen]]; + } + + + attribs.DepthBits = (unsigned) tmpDepthSize; + attribs.StencilBits = (unsigned) tmpStencilBits; + attribs.AntialiasingLevel = (unsigned) tmpAntialiasingLevel; + + [myPixelFormat release]; + } + + return self; +} + +@end + + +//////////////////////////////////////////////////////////// +/// Customized Cocoa OpenGL view +//////////////////////////////////////////////////////////// +@implementation GLView + +//////////////////////////////////////////////////////////// +/// 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 +{ + assert(delegate != NULL); + + // make the view + self = [super initWithFrame:frame pixelFormat:nil]; + + if (self) + { + // enabled auto-resizing + [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + + // make the OpenGL context + myGLContext = [[GLContext alloc] initWithAttributes:settings sharedContext:sharedCtx]; + + // We need to update the OpenGL view when it's resized + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(viewFrameDidChange:) + name:NSViewFrameDidChangeNotification + object:self]; + + // Save the delegate + myDelegate = delegate; + } + + return self; +} + + +//////////////////////////////////////////////////////////// +/// Clean the instance +//////////////////////////////////////////////////////////// +- (void)dealloc +{ + // Remove the observer and release the OpenGL context + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [myGLContext release]; + + [super dealloc]; +} + + +//////////////////////////////////////////////////////////// +/// Finish view setting (after having added it to the window) +//////////////////////////////////////////////////////////// +- (void)finishInitialization +{ + assert([self superview] != nil); + assert(myGLContext != nil); + + // Attach the OpenGL context to our view + [self clearGLContext]; + [self setOpenGLContext:myGLContext]; + [myGLContext setView:self]; + + // Make our view the first responder + [[self window] makeFirstResponder:self]; +} + + +//////////////////////////////////////////////////////////// +/// Forward call to en/disable vertical synchronization +//////////////////////////////////////////////////////////// +- (void)enableVerticalSync:(bool)flag +{ + GLint enable = (flag) ? 1 : 0; + [[self openGLContext] setValues:&enable forParameter:NSOpenGLCPSwapInterval]; +} + + +//////////////////////////////////////////////////////////// +/// Forward call to set the OpenGL context as active according to @flag +//////////////////////////////////////////////////////////// +- (void)setActive:(bool)flag +{ + if (flag) { + if ([NSOpenGLContext currentContext] != [self openGLContext]) + [[self openGLContext] makeCurrentContext]; + } else { + if ([NSOpenGLContext currentContext] == [self openGLContext]) + [NSOpenGLContext clearCurrentContext]; + } +} + + +//////////////////////////////////////////////////////////// +/// Forward call to flush the OpenGL context +//////////////////////////////////////////////////////////// +- (void)flushBuffer +{ + [[self openGLContext] flushBuffer]; +} + + +//////////////////////////////////////////////////////////// +/// Send event to the linked window +//////////////////////////////////////////////////////////// +- (void)pushEvent:(sf::Event)sfEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleNotifiedEvent(sfEvent); +} + + +//////////////////////////////////////////////////////////// +/// Notification method receiver when OpenGL view size changes +//////////////////////////////////////////////////////////// +- (void)viewFrameDidChange:(NSNotification *)notification +{ + [self update]; + + sf::Event ev; + ev.Type = sf::Event::Resized; + ev.Size.Width = (unsigned) [self frame].size.width; + ev.Size.Height = (unsigned) [self frame].size.height; + + [self pushEvent:ev]; +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when a key is pressed +//////////////////////////////////////////////////////////// +- (void)keyDown:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + + NSText *field = [[self window] fieldEditor:YES forObject:nil]; + [field interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; + [field setString:@""]; + + myDelegate->HandleKeyDown(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when a key is released +//////////////////////////////////////////////////////////// +- (void)keyUp:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleKeyUp(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when a modifier flag has changed +//////////////////////////////////////////////////////////// +- (void)flagsChanged:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleModifierKey(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when the mouse wheel has been used +//////////////////////////////////////////////////////////// +- (void)scrollWheel:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleMouseWheel(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when left mouse click is pressed +//////////////////////////////////////////////////////////// +- (void)mouseDown:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleMouseDown(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when right mouse click is pressed +//////////////////////////////////////////////////////////// +- (void)rightMouseDown:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleMouseDown(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when left mouse click is released +//////////////////////////////////////////////////////////// +- (void)mouseUp:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleMouseUp(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when right mouse click is released +//////////////////////////////////////////////////////////// +- (void)rightMouseUp:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleMouseUp(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Receiver method called when mouse moves +//////////////////////////////////////////////////////////// +- (void)mouseMoved:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleMouseMove(theEvent); +} + +//////////////////////////////////////////////////////////// +/// Receiver method called when mouse is pressed (on left button) and moves +//////////////////////////////////////////////////////////// +- (void)mouseDragged:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleMouseMove(theEvent); +} + +//////////////////////////////////////////////////////////// +/// Receiver method called when mouse is pressed (on right button) and moves +//////////////////////////////////////////////////////////// +- (void)rightMouseDragged:(NSEvent *)theEvent +{ + assert(myDelegate != NULL); + myDelegate->HandleMouseMove(theEvent); +} + + +//////////////////////////////////////////////////////////// +/// Tells that the view can be focused +//////////////////////////////////////////////////////////// +- (BOOL)acceptsFirstResponder +{ + return YES; +} + + +//////////////////////////////////////////////////////////// +/// Tells that the view can become the key responder (ie. can catch key events) +//////////////////////////////////////////////////////////// +- (BOOL)canBecomeKeyView +{ + return YES; +} + +@end + + +//////////////////////////////////////////////////////////// +/// Cocoa window implementation to let fullscreen windows +/// catch key events +//////////////////////////////////////////////////////////// +@implementation GLWindow + +- (BOOL)canBecomeKeyWindow +{ + return YES; +} + +- (BOOL)canBecomeMainWindow +{ + return YES; +} + +@end + + +//////////////////////////////////////////////////////////// +/// WindowWrapper class : handles both imported and self-built windows +//////////////////////////////////////////////////////////// +@implementation WindowWrapper + +//////////////////////////////////////////////////////////// +/// 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&)params + videoMode:(sf::VideoMode&)mode + style:(unsigned long)style + title:(NSString *)title + delegate:(sf::priv::WindowImplCocoa *)delegate +{ + return [self initWithWindow:nil + settings:params + videoMode:mode + style:style + title:title + delegate: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 +{ + sf::VideoMode mode([[myWindow contentView] frame].size.width, [[myWindow contentView] frame].size.height); + return [self initWithWindow:window + settings:params + videoMode:mode + style:0 + title:nil + delegate: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 +{ + assert(delegate != NULL); + + self = [super init]; + + if (self) + { + if (window) { + myWindow = (GLWindow *)[window retain]; + } else { + assert(title != nil); + + NSRect frame = NSMakeRect (0.0f, 0.0f, (float) mode.Width, (float) mode.Height); + unsigned int mask = 0; + + if (style & sf::Style::Fullscreen) { + myIsFullscreen = true; + + // Check display mode and put new values in 'mode' if needed + boolean_t exact = true; + + CFDictionaryRef properties = CGDisplayBestModeForParameters(kCGDirectMainDisplay, mode.BitsPerPixel, + mode.Width, mode.Height, &exact); + + if (!properties) { + std::cerr << "Unable to get a display mode with the given parameters" << std::endl; + [self autorelease]; + return nil; + } + + if (exact == false) { + CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayWidth), + kCFNumberIntType, &mode.Width); + + CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayHeight), + kCFNumberIntType, &mode.Height); + + CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayBitsPerPixel), + kCFNumberIntType, &mode.BitsPerPixel); + + } + } + + // We grab options from WindowStyle and add them to our window mask + if (style & sf::Style::None || style & sf::Style::Fullscreen) { + mask |= NSBorderlessWindowMask; + + + + } else { + if (style & sf::Style::Titlebar) { + mask |= NSTitledWindowMask; + mask |= NSMiniaturizableWindowMask; + } + + if (style & sf::Style::Resize) { + mask |= NSTitledWindowMask; + mask |= NSMiniaturizableWindowMask; + mask |= NSResizableWindowMask; + } + + if (style & sf::Style::Close) { + mask |= NSTitledWindowMask; + mask |= NSClosableWindowMask; + mask |= NSMiniaturizableWindowMask; + } + } + + // Now we make the window with the values we got + // Note: defer flag set to NO to be able to use OpenGL in our window + myWindow = [[GLWindow alloc] initWithContentRect:frame + styleMask:mask + backing:NSBackingStoreBuffered + defer:NO]; + + if (myWindow) { + // We set title and window position + [myWindow setTitle:title]; + [myWindow center]; + } else { + std::cerr << "Unable to create the Cocoa window" << std::endl; + [self autorelease]; + return nil; + } + } + + // Make the OpenGL view + myView = [[GLView alloc] initWithFrame:[[myWindow contentView] frame] + mode:mode + settings:params + delegate:delegate]; + + if (myView) { + // Finish setting up the view and window + // Add the view to our window and tell it to the view + [[myWindow contentView] addSubview:myView]; + [myView finishInitialization]; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + // We want to know when our window got the focus + [nc addObserver:self + selector:@selector(windowDidBecomeMain:) + name:NSWindowDidBecomeMainNotification + object:myWindow]; + + // We want to know when our window lost the focus + [nc addObserver:self + selector:@selector(windowDidResignMain:) + name:NSWindowDidResignMainNotification + object:myWindow]; + + // We want to know when the user closes the window + [nc addObserver:self + selector:@selector(windowWillClose:) + name:NSWindowWillCloseNotification + object:myWindow]; + + // I want to re-center the window if it's a full screen one and moved by Spaces + [nc addObserver:self + selector:@selector(windowDidMove:) + name:NSWindowDidMoveNotification + object:myWindow]; + + // Needed not to make application crash when releasing the window in our destructor + // (I prefer to take control of everything :P) + [myWindow setReleasedWhenClosed:NO]; + [myWindow setAcceptsMouseMovedEvents:YES]; + + } else { + std::cerr << "Unable to create the OpenGL view" << std::endl; + [self autorelease]; + return nil; + } + + if (myIsFullscreen) { + myFullscreenMode = mode; + + // Using this because full screen window was not always + // in front of the other application windows when unhiding app + [myWindow setLevel:NSFloatingWindowLevel]; + } + } + + return self; +} + + +//////////////////////////////////////////////////////////// +/// Clean the window wrapper +//////////////////////////////////////////////////////////// +- (void)dealloc +{ + + // Remove the notification observer + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + // Close the window + [self show:false]; + + // Release the window and view + [myView release]; + [myWindow release]; + + [super dealloc]; +} + + +//////////////////////////////////////////////////////////// +/// Return a reference to the internal Cocoa window +//////////////////////////////////////////////////////////// +- (NSWindow *)window +{ + return myWindow; +} + + +//////////////////////////////////////////////////////////// +/// Return a reference to the internal Cocoa OpenGL view +//////////////////////////////////////////////////////////// +- (GLView *)glView +{ + return myView; +} + + +//////////////////////////////////////////////////////////// +/// Forward call to set the window position on screen +//////////////////////////////////////////////////////////// +- (void)setPosition:(NSPoint)pos +{ + assert(myWindow != nil); + + if (!myIsFullscreen) { + // Flip Y and set window position + pos.y = [[myWindow screen] frame].size.height - pos.y; + [myWindow setFrameTopLeftPoint:pos]; + } +} + + +//////////////////////////////////////////////////////////// +/// Forward call to set the window size +//////////////////////////////////////////////////////////// +- (void)setSize:(NSSize)size +{ + assert(myWindow != nil); + + if (!myIsFullscreen) { + [myWindow setFrame:NSMakeRect([myWindow frame].origin.x, + [myWindow frame].origin.y, + size.width, size.height) + display:YES]; + } +} + + +//////////////////////////////////////////////////////////// +/// Return the mouse location relative to the internal window +//////////////////////////////////////////////////////////// +- (NSPoint)mouseLocation +{ + assert(myWindow != nil); + + NSPoint relativeLocation = [myWindow convertScreenToBase:[NSEvent mouseLocation]]; + relativeLocation.y = [[self glView] frame].size.height - relativeLocation.y; + return relativeLocation; +} + + +//////////////////////////////////////////////////////////// +/// Return whether the mouse is on our window +//////////////////////////////////////////////////////////// +- (BOOL)mouseInside +{ + assert(myWindow != nil); + assert(myView != nil); + + BOOL flag = NO; + + if ([myWindow isVisible]) { + NSPoint relativeToWindow = [myWindow mouseLocationOutsideOfEventStream]; + NSPoint relativeToView = [myView convertPoint:relativeToWindow fromView:nil]; + + if (NSPointInRect (relativeToView, [myView bounds])) + { + flag = YES; + } + } + + return flag; +} + + +//////////////////////////////////////////////////////////// +/// Close or open the window +//////////////////////////////////////////////////////////// +- (void)show:(bool)flag +{ + assert(myWindow != nil); + + if (flag && ![myWindow isVisible]) { + // Wanna open the closed window + + if (myIsFullscreen) { + [SharedAppController setFullscreenWindow:self mode:&myFullscreenMode]; + } else { + // Show the window + [myWindow makeKeyAndOrderFront:nil]; + } + } else if (!flag && [myWindow isVisible]) { + // Wanna close the opened window + + if (myIsFullscreen) { + [SharedAppController setFullscreenWindow:nil mode:NULL]; + } else { + // Close the window + [myWindow close]; + } + } +} + + +//////////////////////////////////////////////////////////// +/// Forward call to en/disable the OpenGL view vertical synchronization +//////////////////////////////////////////////////////////// +- (void)enableVerticalSync:(bool)flag +{ + assert(myView != nil); + [myView enableVerticalSync:flag]; +} + + +//////////////////////////////////////////////////////////// +/// Forward 'setActive' call the the OpenGL view +//////////////////////////////////////////////////////////// +- (void)setActive:(bool)flag +{ + assert(myView != nil); + [myView setActive:flag]; +} + + +//////////////////////////////////////////////////////////// +/// Forward call to flush the OpenGL view +//////////////////////////////////////////////////////////// +- (void)flushBuffer +{ + assert(myView != nil); + [myView flushBuffer]; +} + + +//////////////////////////////////////////////////////////// +/// Notification method receiver when the window gains focus +//////////////////////////////////////////////////////////// +- (void)windowDidBecomeMain:(NSNotification *)notification +{ + sf::Event ev; + ev.Type = sf::Event::GainedFocus; + + [myView pushEvent:ev]; +} + + +//////////////////////////////////////////////////////////// +/// Notification method receiver when the window loses focus +//////////////////////////////////////////////////////////// +- (void)windowDidResignMain:(NSNotification *)notification +{ + sf::Event ev; + ev.Type = sf::Event::LostFocus; + + [myView pushEvent:ev]; +} + + +//////////////////////////////////////////////////////////// +/// Notification method receiver when the window closes +//////////////////////////////////////////////////////////// +- (void)windowWillClose:(NSNotification *)notification +{ + sf::Event ev; + ev.Type = sf::Event::Closed; + + [myView pushEvent:ev]; +} + + +//////////////////////////////////////////////////////////// +/// Notification method receiver when the window finish moving +//////////////////////////////////////////////////////////// +- (void)windowDidMove:(NSNotification *)notification +{ + NSWindow *sender = [notification object]; + + if (!([sender styleMask] & NSTitledWindowMask)) + [sender center]; +} + +@end + diff --git a/src/SFML/Window/Cocoa/Joystick.cpp b/src/SFML/Window/Cocoa/Joystick.cpp index 6b456a1..4ade09c 100755 --- a/src/SFML/Window/Cocoa/Joystick.cpp +++ b/src/SFML/Window/Cocoa/Joystick.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 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. diff --git a/src/SFML/Window/Cocoa/Joystick.hpp b/src/SFML/Window/Cocoa/Joystick.hpp index 7a78c93..4259075 100755 --- a/src/SFML/Window/Cocoa/Joystick.hpp +++ b/src/SFML/Window/Cocoa/Joystick.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 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. diff --git a/src/SFML/Window/Cocoa/VideoModeSupport.cpp b/src/SFML/Window/Cocoa/VideoModeSupport.cpp index 75f5d8e..9b5ebd0 100755 --- a/src/SFML/Window/Cocoa/VideoModeSupport.cpp +++ b/src/SFML/Window/Cocoa/VideoModeSupport.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 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. diff --git a/src/SFML/Window/Cocoa/VideoModeSupport.hpp b/src/SFML/Window/Cocoa/VideoModeSupport.hpp index 2b64685..4892fe5 100755 --- a/src/SFML/Window/Cocoa/VideoModeSupport.hpp +++ b/src/SFML/Window/Cocoa/VideoModeSupport.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 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. diff --git a/src/SFML/Window/Cocoa/WindowController.mm b/src/SFML/Window/Cocoa/WindowController.mm deleted file mode 100755 index 286a3ed..0000000 --- a/src/SFML/Window/Cocoa/WindowController.mm +++ /dev/null @@ -1,157 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 Lucas Soltic (elmerod@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 <SFML/Window/Cocoa/WindowController.h> -#import <SFML/Window/Cocoa/WindowImplCocoa.hpp> -#import <SFML/Window/Cocoa/AppController.h> -#import <OpenGL/gl.h> -#import <iostream> - -@implementation WindowController - -//////////////////////////////////////////////////////////// -/// Forbide use of WindowController without any linked WindowImplCocoa object -//////////////////////////////////////////////////////////// -- (id)init -{ - return [self initWithWindow:NULL]; -} - -//////////////////////////////////////////////////////////// -/// Initialize a new WindowController object and link it -/// to the 'window' object. -//////////////////////////////////////////////////////////// -- (WindowController *)initWithWindow:(sf::priv::WindowImplCocoa *)window -{ - if (window == NULL) { - std::cerr << "-[WindowController initWithWindow:NULL] -- initialization without any linked window is forbidden ; nil returned" << std::endl; - [self release]; - return nil; - } - - self = [super init]; - - if (self != nil) { - parentWindow = window; - } - - return self; -} - -//////////////////////////////////////////////////////////// -/// Return a new autoreleased WindowController object linked -/// to the 'window' WindowImplCocoa object. -//////////////////////////////////////////////////////////// -+ (WindowController *)controllerWithWindow:(sf::priv::WindowImplCocoa *)window -{ - WindowController *ctrl = - massert([WindowController alloc]); - return [[ctrl initWithWindow:window] autorelease]; -} - -//////////////////////////////////////////////////////////// -/// Send event to the linked window -//////////////////////////////////////////////////////////// -- (void)pushEvent:(sf::Event)sfEvent -{ - if (parentWindow != NULL) { - parentWindow->HandleNotifiedEvent(sfEvent); - } -} - -//////////////////////////////////////////////////////////// -/// Notification method receiver when OpenGL view size changes -//////////////////////////////////////////////////////////// -- (void)viewFrameDidChange:(NSNotification *)notification -{ - NSOpenGLView *glView = [notification object]; - [[glView openGLContext] update]; - - sf::Event ev; - ev.Type = sf::Event::Resized; - ev.Size.Width = (unsigned) [glView frame].size.width; - ev.Size.Height = (unsigned) [glView frame].size.height; - - [self pushEvent:ev]; -} - -//////////////////////////////////////////////////////////// -/// Notification method receiver when the window gains focus -//////////////////////////////////////////////////////////// -- (void)windowDidBecomeMain:(NSNotification *)notification -{ - sf::Event ev; - ev.Type = sf::Event::GainedFocus; - - [self pushEvent:ev]; -} - -//////////////////////////////////////////////////////////// -/// Notification method receiver when the window loses focus -//////////////////////////////////////////////////////////// -- (void)windowDidResignMain:(NSNotification *)notification -{ - sf::Event ev; - ev.Type = sf::Event::LostFocus; - - [self pushEvent:ev]; -} - -//////////////////////////////////////////////////////////// -/// Notification method receiver when the window closes -//////////////////////////////////////////////////////////// -- (void)windowWillClose:(NSNotification *)notification -{ - sf::Event ev; - ev.Type = sf::Event::Closed; - - [self pushEvent:ev]; -} - -- (void)windowDidMove:(NSNotification *)notification -{ - NSWindow *sender = [notification object]; - - if (!([sender styleMask] & NSTitledWindowMask)) - [sender center]; -} - -@end - - -@implementation SFWindow -- (BOOL)canBecomeKeyWindow -{ - return YES; -} - -- (BOOL)canBecomeMainWindow -{ - return YES; -} -@end diff --git a/src/SFML/Window/Cocoa/WindowImplCocoa.hpp b/src/SFML/Window/Cocoa/WindowImplCocoa.hpp index 1b2e96b..bc93d54 100755 --- a/src/SFML/Window/Cocoa/WindowImplCocoa.hpp +++ b/src/SFML/Window/Cocoa/WindowImplCocoa.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // 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. // 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 <string> +#ifdef __OBJC__ +#import <Cocoa/Cocoa.h> +@class WindowWrapper; +#endif + namespace sf { namespace priv { -typedef struct objc_members objc_members; - //////////////////////////////////////////////////////////// /// WindowImplCocoa is the Cocoa implementation of WindowImpl //////////////////////////////////////////////////////////// @@ -89,24 +92,22 @@ public : static bool IsContextActive(); //////////////////////////////////////////////////////////// - /// Handle Cocoa NSEvent - //////////////////////////////////////////////////////////// - void HandleEvent(void *eventRef); - - //////////////////////////////////////////////////////////// /// Handle an event sent by the default NSNotificationCenter //////////////////////////////////////////////////////////// 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 : //////////////////////////////////////////////////////////// @@ -183,37 +184,18 @@ 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 //////////////////////////////////////////////////////////// - // An opaque structure that contains all obj-C objects - objc_members *members; - - bool useKeyRepeat; - bool mouseIn; - float wheelStatus; +#ifdef __OBJC__ + WindowWrapper *myWrapper; +#else + void *myWrapper; +#endif - bool fullscreen; - VideoMode fullscreenMode; - VideoMode desktopMode; + bool myUseKeyRepeat; + bool myMouseIn; + float myWheelStatus; }; } // namespace priv diff --git a/src/SFML/Window/Cocoa/WindowImplCocoa.mm b/src/SFML/Window/Cocoa/WindowImplCocoa.mm index 7950ab2..3b66bbc 100755 --- a/src/SFML/Window/Cocoa/WindowImplCocoa.mm +++ b/src/SFML/Window/Cocoa/WindowImplCocoa.mm @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // 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. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -27,38 +27,16 @@ // Headers //////////////////////////////////////////////////////////// #import <SFML/Window/Cocoa/WindowImplCocoa.hpp> -#import <SFML/Window/Cocoa/WindowController.h> #import <SFML/Window/Cocoa/AppController.h> +#import <SFML/Window/Cocoa/GLKit.h> #import <SFML/Window/WindowStyle.hpp> #import <SFML/System.hpp> #import <OpenGL/OpenGL.h> #import <OpenGL/gl.h> -#import <Cocoa/Cocoa.h> +#import <CoreFoundation/CoreFoundation.h> #import <iostream> -#pragma mark Notes - -// ENABLE_ANTIALIASING macro : -// -// I use this to prevent the use of antialiasing -// as OpenGL context sharing does not allow only one of the -// shared OpenGL context to be shared. That means -// antialiasing could not be used without re-compiling -// the whole sfml-window library. -// -// I've no way to fix this for now. - -// ENABLE_WINDOWIMPORT macro : -// -// I use this to disable the import of Cocoa windows -// as it does not work fine for now and is not -// a high priority. - - - - - namespace sf { namespace priv @@ -72,75 +50,34 @@ make;\ __done = 1;\ } } -// Has the event been used or not ? If not, it must be sent to NSApp -enum { - UsedEvent, - UnusedEvent -}; - - -//////////////////////////////////////////////////////////// -/// Structure containing all the members I can't directly put in the class definition -/// because I would have to hide them in a #ifdef __OBJC__ block and the object -/// allocator would allocate space for it as it would be called from a C++ code -/// that wouldn't see these members -//////////////////////////////////////////////////////////// -struct objc_members { - WindowController *controller; - SFWindow *window; - NSOpenGLContext *context; - NSOpenGLView *view; -}; - -//////////////////////////////////////////////////////////// -/// Pointer to the shared OpenGL context -//////////////////////////////////////////////////////////// -static NSOpenGLContext *sharedContext = nil; - //////////////////////////////////////////////////////////// /// Private function declarations //////////////////////////////////////////////////////////// -static SFWindow * MakeWindow(WindowSettings& params, unsigned long style, VideoMode& mode, NSString *title); -static NSOpenGLContext *MakeOpenGLContext(WindowSettings& params); -static NSOpenGLView * MakeOpenGLView(SFWindow *window, NSOpenGLContext *context, WindowSettings& params); -static void ConfigureWindow(SFWindow *window, NSOpenGLView *view, WindowController *controller); static Key::Code KeyForVirtualCode(unsigned short vCode); static Key::Code KeyForUnicode(unsigned short uniCode); static bool IsTextEvent(NSEvent *event); -static bool MouseInside(SFWindow *window, NSView *view); -static NSPoint MouseLocation(SFWindow *window); //////////////////////////////////////////////////////////// /// Default constructor /// (creates a dummy window to provide a valid OpenGL context) //////////////////////////////////////////////////////////// + static WindowImplCocoa *globalWin = NULL; WindowImplCocoa::WindowImplCocoa() : -members(NULL), -useKeyRepeat(false), -mouseIn(false), -wheelStatus(0.0f), -fullscreen(false), -fullscreenMode(0, 0, 0), -desktopMode(0, 0, 0) +myWrapper(nil), +myUseKeyRepeat(false), +myMouseIn(false), +myWheelStatus(0.0f) { - Initialize(); - - // We just want to have a valid support for an OpenGL context - - // So we create the OpenGL context - WindowSettings params(0, 0, 0); - members->context = MakeOpenGLContext(params); + [AppController sharedController]; - if (members->context != nil) { - // Increase the reference counter for the shared OpenGL context - sharedContext = [members->context retain]; - + // Create the shared OpenGL context + if ([GLContext sharedContext]) { // Then we make it the current active OpenGL context SetActive(); } else { - std::cerr << "*** SFML: Unable to make the main shared OpenGL context" << std::endl; + std::cerr << "Unable to make the main shared OpenGL context" << std::endl; } } @@ -149,53 +86,39 @@ desktopMode(0, 0, 0) /// Create the window implementation from an existing control //////////////////////////////////////////////////////////// WindowImplCocoa::WindowImplCocoa(WindowHandle Handle, WindowSettings& params) : -members(NULL), -useKeyRepeat(false), -mouseIn(false), -wheelStatus(0.0f), -fullscreen(false), -fullscreenMode(0, 0, 0), -desktopMode(0, 0, 0) +myWrapper(NULL), +myUseKeyRepeat(false), +myMouseIn(false), +myWheelStatus(0.0f) { - Initialize(); - -#if ENABLE_WINDOWIMPORT - // Register ourselves for event handling - [[AppController sharedController] registerWindow:this]; - - // Make a WindowController to handle notifications - members->controller = [[WindowController controllerWithWindow:this] retain]; - - // Use existing window - members->window = [static_cast <SFWindow *> (Handle) retain]; - - if (members->window != nil) { - // We make the OpenGL context, associate it to the OpenGL view - // and add the view to our window - members->context = MakeOpenGLContext(params); - - if (members->context != nil) { - members->view = MakeOpenGLView(members->window, members->context, params); - - if (members->view != nil) { + if (Handle) + { + if (![(NSWindow *)Handle isKindOfClass:[NSWindow class]]) + std::cerr << "Cannot import this Window Handle because it is not a <NSWindow *> object" + << "(or one of its subclasses). You gave a <" + << [[(NSWindow *)Handle className] UTF8String] + << "> object." << std::endl; + else + { + + // We create the window according to the given handle + myWrapper = [[WindowWrapper alloc] initWithWindow:(NSWindow *)Handle + settings:params + delegate:this]; + + if (myWrapper) + { // initial mouse state - mouseIn = MouseInside(members->window, members->view); + myMouseIn = [myWrapper mouseInside]; - // Initialize myWidth and myHeight members from base class with the window size - myWidth = (unsigned) [members->window frame].size.width; - myHeight = (unsigned) [members->window frame].size.height; + // We set the myWidth and myHeight members to the correct values + myWidth = (int) [[myWrapper glView] frame].size.width; + myHeight = (int) [[myWrapper glView] frame].size.height; } else { - //error(__FILE__, __LINE__, "failed to make the OpenGL view for the public window"); + std::cerr << "Failed to make the public window" << std::endl; } - } else { - //error(__FILE__, __LINE__, "failed to make the OpenGL context for the public window"); } - } else { - //error(__FILE__, __LINE__, "invalid imported window"); } -#else - std::cerr << "*** SFML: making a sf::Window from a Cocoa one is not available in this version of the SFML" << std::endl; -#endif } @@ -203,65 +126,32 @@ desktopMode(0, 0, 0) /// Create the window implementation //////////////////////////////////////////////////////////// WindowImplCocoa::WindowImplCocoa(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& params) : -members(NULL), -useKeyRepeat(false), -mouseIn(false), -wheelStatus(0.0f), -fullscreen(WindowStyle & Style::Fullscreen), -fullscreenMode(0, 0, 0), -desktopMode(0, 0, 0) +myWrapper(NULL), +myUseKeyRepeat(false), +myMouseIn(false), +myWheelStatus(0.0f) { - Initialize(); - - // Make a WindowController to handle notifications - members->controller = [[WindowController controllerWithWindow:this] retain]; - // Create a new window with given size, title and style // First we define some objects used for our window - NSString *title = massert([NSString stringWithUTF8String:Title.c_str()]); + NSString *title = [NSString stringWithUTF8String:(Title.c_str()) ? (Title.c_str()) : ""]; // We create the window - members->window = MakeWindow(params, WindowStyle, Mode, title); - + myWrapper = [[WindowWrapper alloc] initWithSettings:params + videoMode:Mode + style:WindowStyle + title:title + delegate:this]; - if (members->window != nil) { - members->context = MakeOpenGLContext(params); + if (myWrapper) + { + // initial mouse state + myMouseIn = [myWrapper mouseInside]; - if (members->context != nil) { - // We make the OpenGL context, associate it to the OpenGL view - // and add the view to our window - members->view = MakeOpenGLView(members->window, members->context, params); - - if (members->view != nil) { - // Set observers and some window settings - ConfigureWindow(members->window, members->view, members->controller); - - // initial mouse state - mouseIn = MouseInside(members->window, members->view); - - // We set the myWidth and myHeight members to the correct values - myWidth = Mode.Width; - myHeight = Mode.Height; - - if (WindowStyle & Style::Fullscreen) { - fullscreenMode = Mode; - - // Using this because full screen window was not always - // in front of the other application windows when unhiding app - [members->window setLevel:NSFloatingWindowLevel]; - } - } else { - std::cerr << "*** SFML: failed to make the OpenGL view for the public window" << std::endl; - [members->context release], members->context = nil; - [sharedContext release]; - [members->window release], members->window = nil; - } - } else { - std::cerr << "*** SFML: failed to make the OpenGL context for the public window" << std::endl; - [members->window release], members->window = nil; - } + // We set the myWidth and myHeight members to the correct values + myWidth = Mode.Width; + myHeight = Mode.Height; } else { - std::cerr << "*** SFML: failed to make the public window" << std::endl; + std::cerr << "Failed to make the public window" << std::endl; } } @@ -271,26 +161,8 @@ desktopMode(0, 0, 0) //////////////////////////////////////////////////////////// WindowImplCocoa::~WindowImplCocoa() { - // Destroy the OpenGL context, the window and every resource allocated by this class - Show(false); - - if (members) { - if (members->window) - [[NSNotificationCenter defaultCenter] removeObserver:members->window]; - if (members->view) - [[NSNotificationCenter defaultCenter] removeObserver:members->view]; - [members->controller release]; - } - - [sharedContext release]; - if (members) { - [members->context release]; - [members->view release]; - [members->window release]; - } - - [[AppController sharedController] unregisterWindow:this]; - free (members); + // Release the window wrapper + [myWrapper release]; } @@ -304,63 +176,6 @@ bool WindowImplCocoa::IsContextActive() //////////////////////////////////////////////////////////// -/// Handle a Cocoa NSEvent -//////////////////////////////////////////////////////////// -void WindowImplCocoa::HandleEvent(void *eventRef) -{ - if (eventRef == nil) { - std::cerr << "*** SFML: cannot handle a NULL event. Returning." << std::endl; - return; - } - - NSEvent *event = static_cast <NSEvent *> (eventRef); - int eventStatus = UnusedEvent; - - switch ([event type]) { - case NSKeyDown: - eventStatus = HandleKeyDown(eventRef); - break; - - case NSKeyUp: - eventStatus = HandleKeyUp(eventRef); - break; - - case NSFlagsChanged: - eventStatus = HandleModifierKey(eventRef); - break; - - case NSScrollWheel: - eventStatus = HandleMouseWheel(eventRef); - break; - - case NSLeftMouseDown: - case NSRightMouseDown: - eventStatus = HandleMouseDown(eventRef); - break; - - case NSLeftMouseUp: - case NSRightMouseUp: - eventStatus = HandleMouseUp(eventRef); - break; - - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - eventStatus = HandleMouseMove(eventRef); - break; - - default: - break; - } - - if (eventStatus == UnusedEvent) { - [NSApp sendEvent:event]; - } -} - - -//////////////////////////////////////////////////////////// /// Handle event sent by the default NSNotificationCenter //////////////////////////////////////////////////////////// void WindowImplCocoa::HandleNotifiedEvent(Event& event) @@ -385,143 +200,133 @@ void WindowImplCocoa::HandleNotifiedEvent(Event& event) //////////////////////////////////////////////////////////// /// Handle a key down event (NSEvent) //////////////////////////////////////////////////////////// -int WindowImplCocoa::HandleKeyDown(void *eventRef) +void WindowImplCocoa::HandleKeyDown(void *eventRef) { - NSEvent *event = static_cast <NSEvent *> (eventRef); + NSEvent *event = reinterpret_cast <NSEvent *> (eventRef); Event sfEvent; unichar chr = 0, rawchr = 0; + unsigned long length = [[event characters] length]; unsigned mods = [event modifierFlags]; - if ([[event characters] length]) { + if (length) { chr = [[event characters] characterAtIndex:0]; // Note : I got a crash (out of bounds exception) while typing so now I test... if ([[event charactersIgnoringModifiers] length]) rawchr = [[event charactersIgnoringModifiers] characterAtIndex:0]; - } - - if (mods & NSCommandKeyMask) { - // Application commands - [NSApp sendEvent:event]; - } - - // User events - - if (!useKeyRepeat && [event isARepeat]) { - return UsedEvent; - } - -#if 1 - // Is it also a text event ? - if (IsTextEvent(event)) { - sfEvent.Type = Event::TextEntered; - sfEvent.Text.Unicode = chr; - - SendEvent(sfEvent); - } -#else - // Is it also a text event ? - if (IsTextEvent(event)) { - static NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:1]; - sfEvent.Type = Event::TextEntered; - sfEvent.Text.Unicode = chr; + // Don't handle repeated events if we chose not to send them + if (!myUseKeyRepeat && [event isARepeat]) + return; + + // Is it also a text event ? + if (IsTextEvent(event)) { + // buffer for the UTF-32 characters + Uint32 utf32Characters[2] = {0}; + + // convert the characters + // note: using CFString in order to keep compatibility with Mac OS X 10.4 + // (NSUTF32StringEncoding only defined since Mac OS X 10.5) + if (!CFStringGetCString ((CFStringRef)[event characters], + (char *)utf32Characters, + sizeof(utf32Characters), + kCFStringEncodingUTF32)) + { + const char *utf8Char = NULL; + if ([[event characters] lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) + utf8Char = [[event characters] UTF8String]; + + std::cerr << "Error while converting character to UTF32 : " + << ((utf8Char) ? utf8Char : "(undefined)") << std::endl; + } + else + { + sfEvent.Type = Event::TextEntered; + sfEvent.Text.Unicode = utf32Characters[0]; + + SendEvent(sfEvent); + } + } - NSText *field = [members->window fieldEditor:YES forObject:nil]; - [arr addObject:event]; - [field interpretKeyEvents:arr]; + // Anyway it's also a KeyPressed event + sfEvent.Type = Event::KeyPressed; - if ([[field string] length]) { - unichar unichr = [[field string] characterAtIndex:0]; - sfEvent.Text.Unicode = unichr; - SendEvent(sfEvent); - - unichar str[2] = {unichr, 0}; - NSLog(@"Char::%@", [NSString stringWithCharacters:str length:2]); - - [field setString:@""]; - [arr removeAllObjects]; + // Get the keys + if (Key::Code(0) == (sfEvent.Key.Code = KeyForUnicode(rawchr))) { + sfEvent.Key.Code = KeyForVirtualCode([event keyCode]); } + // Get the modifiers + sfEvent.Key.Alt = mods & NSAlternateKeyMask; + sfEvent.Key.Control = mods & NSControlKeyMask; + sfEvent.Key.Shift = mods & NSShiftKeyMask; + // Send the event + SendEvent(sfEvent); } -#endif - - // Anyway it's also a KeyPressed event - sfEvent.Type = Event::KeyPressed; - - // Get the keys - if (Key::Code(0) == (sfEvent.Key.Code = KeyForUnicode(chr))) { - sfEvent.Key.Code = KeyForVirtualCode([event keyCode]); - } - - // Get the modifiers - sfEvent.Key.Alt = mods & NSAlternateKeyMask; - sfEvent.Key.Control = mods & NSControlKeyMask; - sfEvent.Key.Shift = mods & NSShiftKeyMask; - - // Send the event - SendEvent(sfEvent); - - return UsedEvent; } //////////////////////////////////////////////////////////// /// Handle a key up event (NSEvent) //////////////////////////////////////////////////////////// -int WindowImplCocoa::HandleKeyUp(void *eventRef) +void WindowImplCocoa::HandleKeyUp(void *eventRef) { - NSEvent *event = static_cast <NSEvent *> (eventRef); + NSEvent *event = reinterpret_cast <NSEvent *> (eventRef); Event sfEvent; unsigned mods = [event modifierFlags]; - unichar chr = 0; + unichar chr = 0, rawchr = 0; if ([[event characters] length]) { chr = [[event characters] characterAtIndex:0]; + + if ([[event charactersIgnoringModifiers] length]) + rawchr = [[event charactersIgnoringModifiers] characterAtIndex:0]; + + sfEvent.Type = Event::KeyReleased; + + // Get the code + if (Key::Code(0) == (sfEvent.Key.Code = KeyForUnicode(rawchr))) { + sfEvent.Key.Code = KeyForVirtualCode([event keyCode]); + } + + // Get the modifiers + sfEvent.Key.Alt = mods & NSAlternateKeyMask; + sfEvent.Key.Control = mods & NSControlKeyMask; + sfEvent.Key.Shift = mods & NSShiftKeyMask; + + // Send the event + SendEvent(sfEvent); } - - if (mods & NSCommandKeyMask) { - [NSApp sendEvent:event]; - } - - sfEvent.Type = Event::KeyReleased; - - // Get the code - if (Key::Code(0) == (sfEvent.Key.Code = KeyForUnicode(chr))) { - sfEvent.Key.Code = KeyForVirtualCode([event keyCode]); - } - - // Get the modifiers - sfEvent.Key.Alt = mods & NSAlternateKeyMask; - sfEvent.Key.Control = mods & NSControlKeyMask; - sfEvent.Key.Shift = mods & NSShiftKeyMask; - - SendEvent(sfEvent); - - return UsedEvent; } //////////////////////////////////////////////////////////// /// Handle a key modifier event [Command, Option, Control, Shift] //////////////////////////////////////////////////////////// -int WindowImplCocoa::HandleModifierKey(void *eventRef) +void WindowImplCocoa::HandleModifierKey(void *eventRef) { - NSEvent *event = static_cast <NSEvent *> (eventRef); + NSEvent *event = reinterpret_cast <NSEvent *> (eventRef); Event sfEvent; unsigned mods = [event modifierFlags]; sfEvent.Type = Event::KeyPressed; + + // Get the code sfEvent.Key.Code = KeyForVirtualCode([event keyCode]); + // Get the modifiers sfEvent.Key.Alt = mods & NSAlternateKeyMask; sfEvent.Key.Control = mods & NSControlKeyMask; sfEvent.Key.Shift = mods & NSShiftKeyMask; + // Guess whether it's a pressed or released event + // Note: this does not work fine is both left and right modifiers are pressed + // I did not find any way to fix this. + // TODO: fix handling of modifier flags for use of left and right key at the same time if (!(mods & NSAlternateKeyMask) && (sfEvent.Key.Code == Key::LAlt || sfEvent.Key.Code == Key::RAlt)) { sfEvent.Type = Event::KeyReleased; @@ -542,18 +347,17 @@ int WindowImplCocoa::HandleModifierKey(void *eventRef) sfEvent.Type = Event::KeyReleased; } + // Send the event SendEvent(sfEvent); - - return UnusedEvent; } //////////////////////////////////////////////////////////// /// Handle a mouse down event (NSEvent) //////////////////////////////////////////////////////////// -int WindowImplCocoa::HandleMouseDown(void *eventRef) +void WindowImplCocoa::HandleMouseDown(void *eventRef) { - NSEvent *event = static_cast <NSEvent *> (eventRef); + NSEvent *event = reinterpret_cast <NSEvent *> (eventRef); Event sfEvent; NSPoint loc = {0, 0}; unsigned mods = [event modifierFlags]; @@ -562,18 +366,20 @@ int WindowImplCocoa::HandleMouseDown(void *eventRef) case NSLeftMouseDown: sfEvent.Type = Event::MouseButtonPressed; + // Guess whether it's a mouse left or mouse right event if (mods & NSControlKeyMask) { sfEvent.MouseButton.Button = Mouse::Right; } else { sfEvent.MouseButton.Button = Mouse::Left; } - // Get mouse position - loc = MouseLocation(members->window); + // Get mouse position relative to the window + loc = [myWrapper mouseLocation]; sfEvent.MouseButton.X = (int) loc.x; sfEvent.MouseButton.Y = (int) loc.y; + // Send the event SendEvent(sfEvent); break; @@ -581,30 +387,28 @@ int WindowImplCocoa::HandleMouseDown(void *eventRef) sfEvent.Type = Event::MouseButtonPressed; sfEvent.MouseButton.Button = Mouse::Right; - // Get mouse position - loc = MouseLocation(members->window); + // Get mouse position relative to the window + loc = [myWrapper mouseLocation]; sfEvent.MouseButton.X = (int) loc.x; sfEvent.MouseButton.Y = (int) loc.y; + // Send the event SendEvent(sfEvent); break; default: break; } - - return UnusedEvent; - } //////////////////////////////////////////////////////////// /// Handle a mouse up event (NSEvent) //////////////////////////////////////////////////////////// -int WindowImplCocoa::HandleMouseUp(void *eventRef) +void WindowImplCocoa::HandleMouseUp(void *eventRef) { - NSEvent *event = static_cast <NSEvent *> (eventRef); + NSEvent *event = reinterpret_cast <NSEvent *> (eventRef); Event sfEvent; NSPoint loc = {0, 0}; unsigned mods = [event modifierFlags]; @@ -613,18 +417,20 @@ int WindowImplCocoa::HandleMouseUp(void *eventRef) case NSLeftMouseUp: sfEvent.Type = Event::MouseButtonReleased; + // Guess whether it's a mouse left or mouse right event if (mods & NSControlKeyMask) { sfEvent.MouseButton.Button = Mouse::Right; } else { sfEvent.MouseButton.Button = Mouse::Left; } - // Get mouse position - loc = MouseLocation(members->window); + // Get mouse position relative to the window + loc = [myWrapper mouseLocation]; sfEvent.MouseButton.X = (int) loc.x; sfEvent.MouseButton.Y = (int) loc.y; + // Send the event SendEvent(sfEvent); break; @@ -632,32 +438,31 @@ int WindowImplCocoa::HandleMouseUp(void *eventRef) sfEvent.Type = Event::MouseButtonReleased; sfEvent.MouseButton.Button = Mouse::Right; - // Get mouse position - loc = MouseLocation(members->window); + // Get mouse position relative to the window + loc = [myWrapper mouseLocation]; sfEvent.MouseButton.X = (int) loc.x; sfEvent.MouseButton.Y = (int) loc.y; + // Send the event SendEvent(sfEvent); break; default: break; } - - return UnusedEvent; } //////////////////////////////////////////////////////////// /// Handle a mouse move event (NSEvent) //////////////////////////////////////////////////////////// -int WindowImplCocoa::HandleMouseMove(void *eventRef) +void WindowImplCocoa::HandleMouseMove(void *eventRef) { Event sfEvent; NSPoint loc = {0, 0}; - loc = MouseLocation(members->window); + loc = [myWrapper mouseLocation]; sfEvent.Type = Event::MouseMoved; sfEvent.MouseMove.X = (int) loc.x; @@ -665,65 +470,55 @@ int WindowImplCocoa::HandleMouseMove(void *eventRef) SendEvent(sfEvent); - // MouseEntered and MouseLeft events - if (MouseInside(members->window, members->view) && !mouseIn) { + if ([myWrapper mouseInside] && !myMouseIn) { + // If mouse IS inside but WAS not inside last time sfEvent.Type = Event::MouseEntered; - mouseIn = true; + myMouseIn = true; + SendEvent(sfEvent); - } else if (!MouseInside(members->window, members->view) && mouseIn) { + } else if (![myWrapper mouseInside] && myMouseIn) { + // Is mouse WAS not inside but IS now inside sfEvent.Type = Event::MouseLeft; - mouseIn = false; + myMouseIn = false; + SendEvent(sfEvent); } - - return UnusedEvent; } //////////////////////////////////////////////////////////// /// Handle a mouse wheel event (NSEvent) //////////////////////////////////////////////////////////// -int WindowImplCocoa::HandleMouseWheel(void *eventRef) +void WindowImplCocoa::HandleMouseWheel(void *eventRef) { - NSEvent *event = static_cast <NSEvent *> (eventRef); + NSEvent *event = reinterpret_cast <NSEvent *> (eventRef); - wheelStatus += [event deltaY]; + // SFML uses integer values for delta but Cocoa uses float and it is mostly fewer than 1.0 + // Therefore I chose to add the float value to a 'wheel status' and + // send a sf event only when it's greater than 1.0 + myWheelStatus += [event deltaY]; - if (fabs(wheelStatus) > 1.0f) { + if (fabs(myWheelStatus) > 1.0f) { + // Make the event and send it Event sfEvent; sfEvent.Type = Event::MouseWheelMoved; - sfEvent.MouseWheel.Delta = (int) wheelStatus; + sfEvent.MouseWheel.Delta = (int) myWheelStatus; SendEvent(sfEvent); - wheelStatus -= (int) wheelStatus; + // Remove as much integer units as the one that have been put in the event + // (was a mistake to set this to 0) + myWheelStatus -= (int) myWheelStatus; } - - return UnusedEvent; } - - -//////////////////////////////////////////////////////////// -/// Return a pointer to the SFWindow object -//////////////////////////////////////////////////////////// -void *WindowImplCocoa::CocoaWindow(void) -{ - return static_cast <void *> (members->window); -} - -//////////////////////////////////////////////////////////// -/// Return whether the window is in full screen mode -//////////////////////////////////////////////////////////// -bool WindowImplCocoa::IsFullscreen(void) -{ - return fullscreen; -} - + + //////////////////////////////////////////////////////////// /// /see sfWindowImpl::Display //////////////////////////////////////////////////////////// void WindowImplCocoa::Display() { - [members->context flushBuffer]; + // Forward flush call to the window + [myWrapper flushBuffer]; } @@ -732,10 +527,8 @@ void WindowImplCocoa::Display() //////////////////////////////////////////////////////////// void WindowImplCocoa::ProcessEvents() { - if (![NSApp isRunning]) - return; - - [[AppController sharedController] processEvents]; + // Forward event handling call to the application controller + [SharedAppController processEvents]; } @@ -744,13 +537,8 @@ void WindowImplCocoa::ProcessEvents() //////////////////////////////////////////////////////////// void WindowImplCocoa::SetActive(bool Active) const { - if (Active) { - if ([NSOpenGLContext currentContext] != members->context) - [members->context makeCurrentContext]; - } else { - if ([NSOpenGLContext currentContext] == members->context) - [NSOpenGLContext clearCurrentContext]; - } + // Forward the call to the window + [myWrapper setActive:Active]; } @@ -759,8 +547,8 @@ void WindowImplCocoa::SetActive(bool Active) const //////////////////////////////////////////////////////////// void WindowImplCocoa::UseVerticalSync(bool Enabled) { - GLint enable = (Enabled) ? 1 : 0; - [members->context setValues:&enable forParameter:NSOpenGLCPSwapInterval]; + // Forward the call to the window + [myWrapper enableVerticalSync:Enabled]; } @@ -784,24 +572,21 @@ void WindowImplCocoa::SetCursorPosition(unsigned int Left, unsigned int Top) { NSPoint pos = NSMakePoint ((float) Left, (float) Top); - if (members->window) { + if (myWrapper) { // Flip for SFML window coordinate system - pos.y = [members->window frame].size.height - pos.y; + pos.y = [[myWrapper window] frame].size.height - pos.y; // Adjust for view reference instead of window - pos.y -= [members->window frame].size.height - [members->view frame].size.height; + pos.y -= [[myWrapper window] frame].size.height - [[myWrapper glView] frame].size.height; // Convert to screen coordinates - NSPoint absolute = [members->window convertBaseToScreen:pos]; + NSPoint absolute = [[myWrapper window] convertBaseToScreen:pos]; // Flip screen coodinates absolute.y = [[NSScreen mainScreen] frame].size.height - absolute.y; // Move cursor CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, CGPointMake(absolute.x, absolute.y)); - } else { - std::cerr << "*** SFML: uninitialized 'members->window' member (objc_members) in " - << this << " (sf::priv::WindowImplCocoa)" << std::endl; } } @@ -811,16 +596,7 @@ void WindowImplCocoa::SetCursorPosition(unsigned int Left, unsigned int Top) //////////////////////////////////////////////////////////// void WindowImplCocoa::SetPosition(int Left, int Top) { - if (members->window) { - if (!fullscreen) { - // Change the window position - Top = (int) [[members->window screen] frame].size.height - Top; - [members->window setFrameTopLeftPoint:NSMakePoint(Left, Top)]; - } - } else { - std::cerr << "*** SFML: uninitialized 'members->window' member (objc_members) in " - << this << " (sf::priv::WindowImplCocoa)"; - } + [myWrapper setPosition:NSMakePoint(Left, Top)]; } @@ -830,17 +606,7 @@ void WindowImplCocoa::SetPosition(int Left, int Top) //////////////////////////////////////////////////////////// void WindowImplCocoa::SetSize(unsigned int Width, unsigned int Height) { - if (members->window) { - if (!fullscreen) { - [members->window setFrame:NSMakeRect([members->window frame].origin.x, - [members->window frame].origin.y, - (float) Width, (float) Height) - display:YES]; - } - } else { - std::cerr << "*** SFML: uninitialized 'members->window' member (objc_members) in " - << this << " (sf::priv::WindowImplCocoa)" << std::endl; - } + [myWrapper setSize:NSMakeSize(Width, Height)]; } @@ -849,83 +615,7 @@ void WindowImplCocoa::SetSize(unsigned int Width, unsigned int Height) //////////////////////////////////////////////////////////// void WindowImplCocoa::Show(bool State) { - if (State && ![members->window isVisible]) { - // Wanna open the closed window - - // Register ourselves for event handling - [[AppController sharedController] registerWindow:this]; - - if (fullscreen) { - desktopMode = VideoMode::GetDesktopMode(); - - CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay, - fullscreenMode.BitsPerPixel, - fullscreenMode.Width, - fullscreenMode.Height, - NULL); - - CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken; - - // Fade to a black screen - [SharedAppController doFadeOperation:FillScreen time:0.5f sync:true token:&token]; - [NSMenu setMenuBarVisible:NO]; - - // Switch to the wished display mode - CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); - - // Open the window - [members->window makeKeyAndOrderFront:nil]; - [members->window center]; - - // Fade to normal screen - [SharedAppController doFadeOperation:CleanScreen time:0.2f sync:false token:&token]; - - } else { - // Show the window - // Note: using these two lines instead of -[NSWindow makeKeyAndOrderFront:] - // in order to prevent the standard window buttons from not displaying - // the "mouse over" icons - [members->window orderFront:nil]; - [members->window makeKeyWindow]; - - } - } else if (!State && [members->window isVisible]) { - // Wanna close the opened window - - if (fullscreen) { - CFDictionaryRef displayMode = CGDisplayBestModeForParameters (kCGDirectMainDisplay, - desktopMode.BitsPerPixel, - desktopMode.Width, - desktopMode.Height, - NULL); - - CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken; - - // Fade to black screen - [SharedAppController doFadeOperation:FillScreen time:0.2f sync:true token:&token]; - - // Switch to the wished display mode - CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); - - // Close the window - [members->window close]; - [NSMenu setMenuBarVisible:YES]; - - // Fade to normal screen - [SharedAppController doFadeOperation:CleanScreen time:0.5f sync:false token:&token]; - - // Do not sync but sleep so that the Dock and the Finder desktop go back to normal - // state before the end of the fade operation - sf::Sleep(0.5f); - } else { - // Close the window - [members->window close]; - - } - - // Unregister ourselves from the event handler - [[AppController sharedController] unregisterWindow:this]; - } + [myWrapper show:State]; } @@ -934,7 +624,7 @@ void WindowImplCocoa::Show(bool State) //////////////////////////////////////////////////////////// void WindowImplCocoa::EnableKeyRepeat(bool Enabled) { - useKeyRepeat = Enabled; + myUseKeyRepeat = Enabled; } @@ -948,270 +638,6 @@ void WindowImplCocoa::SetIcon(unsigned int Width, unsigned int Height, const Uin //////////////////////////////////////////////////////////// -/// Make some allocations and initializations -//////////////////////////////////////////////////////////// -void WindowImplCocoa::Initialize(void) -{ - // Allocate mem for the private objc members - members = new objc_members; - bzero(members, sizeof(*members)); - - // Needed to always have an autorelease pool as soon as application is launched - ONCE([SharedAppController resetPool]); - - // Register application if needed and launch it - ONCE([SharedAppController runApplication]); -} - - -//////////////////////////////////////////////////////////// -/// Make the window -//////////////////////////////////////////////////////////// -static SFWindow *MakeWindow(WindowSettings& params, unsigned long style, VideoMode& mode, NSString *title) -{ - SFWindow *window = nil; - - NSRect frame = NSMakeRect (0.0f, 0.0f, (float) mode.Width, (float) mode.Height); - unsigned int mask = 0; - - // We grab options from WindowStyle and add them to our window mask - if (style & Style::None || style & Style::Fullscreen) { - mask |= NSBorderlessWindowMask; - - if (style & style & Style::Fullscreen) { - // Check display mode and put new values in 'mode' if needed - boolean_t exact = true; - CFDictionaryRef properties = CGDisplayBestModeForParameters(kCGDirectMainDisplay, mode.BitsPerPixel, - mode.Width, mode.Height, &exact); - - if (!properties) { - std::cerr << "*** SFML: unable to get a display mode with the given parameters" << std::endl; - return nil; - } - - if (exact == false) { - CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayWidth), - kCFNumberIntType, &mode.Width); - - CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayHeight), - kCFNumberIntType, &mode.Height); - - CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayBitsPerPixel), - kCFNumberIntType, &mode.BitsPerPixel); - } - } - - } else { - if (style & Style::Titlebar) { - mask |= NSTitledWindowMask; - mask |= NSMiniaturizableWindowMask; - } - - if (style & Style::Resize) { - mask |= NSTitledWindowMask; - mask |= NSMiniaturizableWindowMask; - mask |= NSResizableWindowMask; - } - - if (style & Style::Close) { - mask |= NSTitledWindowMask; - mask |= NSClosableWindowMask; - mask |= NSMiniaturizableWindowMask; - } - } - - // Now we make the window with the values we got - // Note: defer flag set to NO to be able to use OpenGL in our window - window =[massert([SFWindow alloc]) initWithContentRect:frame - styleMask:mask - backing:NSBackingStoreBuffered - defer:NO]; - - if (window != nil) { - // We set title and window position - [window setTitle:title]; - [window center]; - } - - return window; -} - - -//////////////////////////////////////////////////////////// -/// Make the OpenGL pixel format from the given attributes -//////////////////////////////////////////////////////////// -static NSOpenGLContext *MakeOpenGLContext(WindowSettings& params) -{ - NSOpenGLPixelFormat *pixFormat = nil; - NSOpenGLContext *context = nil; - unsigned idx = 0; -#if ENABLE_ANTIALIASING - unsigned samplesIdx = 0; -#endif - - // Attributes list - NSOpenGLPixelFormatAttribute attribs[15] = {(NSOpenGLPixelFormatAttribute) 0}; - - // Accelerated, double buffered - attribs[idx++] = NSOpenGLPFAClosestPolicy; - attribs[idx++] = NSOpenGLPFADoubleBuffer; - attribs[idx++] = NSOpenGLPFAAccelerated; - - // windowed context - attribs[idx++] = NSOpenGLPFAWindow; - - // Color size ; usually 32 bits per pixel - attribs[idx++] = NSOpenGLPFAColorSize; - attribs[idx++] = (NSOpenGLPixelFormatAttribute) VideoMode::GetDesktopMode().BitsPerPixel; - - // Z-buffer size - attribs[idx++] = NSOpenGLPFADepthSize; - attribs[idx++] = (NSOpenGLPixelFormatAttribute) params.DepthBits; - - // Stencil bits (I don't really know what's that...) - attribs[idx++] = NSOpenGLPFAStencilSize; - attribs[idx++] = (NSOpenGLPixelFormatAttribute) params.StencilBits; - -#if ENABLE_ANTIALIASING - // Antialiasing settings - if (params.AntialiasingLevel) { - samplesIdx = idx; - - attribs[idx++] = NSOpenGLPFASamples; - attribs[idx++] = (NSOpenGLPixelFormatAttribute) params.AntialiasingLevel; - - attribs[idx++] = NSOpenGLPFASampleBuffers; - attribs[idx++] = (NSOpenGLPixelFormatAttribute) GL_TRUE; - } -#endif - - pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; - -#if ENABLE_ANTIALIASING - // If pixel format creation fails and antialiasing level is - // greater than 2, we set it to 2. - if (pixFormat == nil && params.AntialiasingLevel > 2) { - std::cerr << "Failed to find a pixel format supporting " << params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl; - params.AntialiasingLevel = attribs[samplesIdx + 1] = (NSOpenGLPixelFormatAttribute) 2; - - pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; - } - - // If pixel format creation fails and antialiasing is enabled, - // we disable it. - if (pixFormat == nil && params.AntialiasingLevel > 0) { - std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl; - attribs[samplesIdx] = (NSOpenGLPixelFormatAttribute) nil; - - pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; - } -#endif - - if (pixFormat) { - context = [[NSOpenGLContext alloc] initWithFormat:pixFormat - shareContext:[sharedContext retain]]; - - // Get the effective properties from our OpenGL context - GLint tmpDepthSize = 0, tmpStencilBits = 0, tmpAntialiasingLevel = 0; - - if (context) { - [pixFormat getValues:&tmpDepthSize - forAttribute:NSOpenGLPFADepthSize - forVirtualScreen:[context currentVirtualScreen]]; - - [pixFormat getValues:&tmpStencilBits - forAttribute:NSOpenGLPFAStencilSize - forVirtualScreen:[context currentVirtualScreen]]; - - [pixFormat getValues:&tmpAntialiasingLevel - forAttribute:NSOpenGLPFASamples - forVirtualScreen:[context currentVirtualScreen]]; - } - - - params.DepthBits = (unsigned) tmpDepthSize; - params.StencilBits = (unsigned) tmpStencilBits; - params.AntialiasingLevel = (unsigned) tmpAntialiasingLevel; - - [pixFormat release]; - } - - return context; -} - - -static NSOpenGLView * MakeOpenGLView(SFWindow *window, NSOpenGLContext *context, WindowSettings& params) -{ - assert(window != nil); - assert(context != nil); - - NSOpenGLView *view = nil; - - - // We make the NSOpenGLView - view = [[NSOpenGLView alloc] initWithFrame:[[window contentView] bounds] - pixelFormat:nil]; - - if (view) { - // We add the NSOpenGLView to the window - [[window contentView] addSubview:view]; - - [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [view clearGLContext]; - [view setOpenGLContext:context]; - [context setView:view]; - } - - return view; -} - - -static void ConfigureWindow(SFWindow *window, NSOpenGLView *view, WindowController *controller) -{ - assert(window != nil); - assert(view != nil); - assert(controller != nil); - - // We need to update the OpenGL view when it changes - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:controller - selector:@selector(viewFrameDidChange:) - name:NSViewFrameDidChangeNotification - object:view]; - - // We want to know when our window got the focus - [nc addObserver:controller - selector:@selector(windowDidBecomeMain:) - name:NSWindowDidBecomeMainNotification - object:window]; - - // We want to know when our window lost the focus - [nc addObserver:controller - selector:@selector(windowDidResignMain:) - name:NSWindowDidResignMainNotification - object:window]; - - // We want to know when the user closes the window - [nc addObserver:controller - selector:@selector(windowWillClose:) - name:NSWindowWillCloseNotification - object:window]; - - // I want to re-center the window if it's a full screen one and moved by Spaces - [nc addObserver:controller - selector:@selector(windowDidMove:) - name:NSWindowDidMoveNotification - object:window]; - - - // Needed not to make application crash when releasing the window in our destructor - // (I prefer to take control of everything :P) - [window setReleasedWhenClosed:NO]; - [window setAcceptsMouseMovedEvents:YES]; -} - - -//////////////////////////////////////////////////////////// /// Return the SFML key corresponding to a key code //////////////////////////////////////////////////////////// static Key::Code KeyForVirtualCode(unsigned short vCode) @@ -1268,7 +694,7 @@ static Key::Code KeyForVirtualCode(unsigned short vCode) {0x36, Key::RSystem}, //< Right Command {0x3C, Key::RShift}, //< Right Shift - {0x39, Key::Code(0)} //< Caps Lock + {0x39, Key::Code(0)} //< Caps Lock (not handled by SFML for now) }; Key::Code result = Key::Code(0); @@ -1289,6 +715,7 @@ static Key::Code KeyForVirtualCode(unsigned short vCode) //////////////////////////////////////////////////////////// static Key::Code KeyForUnicode(unsigned short uniCode) { + // TODO: find a better way to get the language independant key static struct { unsigned short character; Key::Code sfKey; @@ -1388,43 +815,6 @@ static bool IsTextEvent(NSEvent *event) return res; } - -//////////////////////////////////////////////////////////// -/// Return whether the mouse is on our OpenGL view -//////////////////////////////////////////////////////////// -static bool MouseInside(SFWindow *window, NSView *view) -{ - bool res = false; - - if (window && view && [window isVisible]) { - NSPoint relativeToWindow = [window mouseLocationOutsideOfEventStream]; - NSPoint relativeToView = [view convertPoint:relativeToWindow fromView:nil]; - - if (NSPointInRect (relativeToView, [view bounds])) - res = true; - } - - return res; -} - - -//////////////////////////////////////////////////////////// -/// Return the mouse location in the SFML coordinates according to 'window' -//////////////////////////////////////////////////////////// -static NSPoint MouseLocation(SFWindow *window) -{ - NSPoint location = [NSEvent mouseLocation]; - NSPoint relativeLocation = {0, 0}; - - if (window) { - [window convertScreenToBase:location]; - relativeLocation.y = [[window contentView] frame].size.height - relativeLocation.y; - } else { - std::cerr << "*** SFML: tried to get mouse location from no window" << std::endl; - } - - return relativeLocation; -} } // namespace priv diff --git a/src/SFML/Window/Context.cpp b/src/SFML/Window/Context.cpp index 5f4cd74..107bc6e 100755 --- a/src/SFML/Window/Context.cpp +++ b/src/SFML/Window/Context.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
diff --git a/src/SFML/Window/Input.cpp b/src/SFML/Window/Input.cpp index d5fac6e..7b10270 100755 --- a/src/SFML/Window/Input.cpp +++ b/src/SFML/Window/Input.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
diff --git a/src/SFML/Window/Joystick.hpp b/src/SFML/Window/Joystick.hpp index 6bb1f2a..4a17f4e 100755 --- a/src/SFML/Window/Joystick.hpp +++ b/src/SFML/Window/Joystick.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 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. @@ -56,7 +56,7 @@ struct JoystickState #include <SFML/Window/Win32/Joystick.hpp> -#elif defined(SFML_SYSTEM_LINUX) +#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) #include <SFML/Window/Linux/Joystick.hpp> diff --git a/src/SFML/Window/Linux/Joystick.cpp b/src/SFML/Window/Linux/Joystick.cpp index ba85ccd..509bc53 100755 --- a/src/SFML/Window/Linux/Joystick.cpp +++ b/src/SFML/Window/Linux/Joystick.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
@@ -26,15 +26,22 @@ // Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Joystick.hpp>
-#include <linux/joystick.h>
-#include <fcntl.h>
#include <sstream>
+#if defined(SFML_SYSTEM_LINUX)
+ #include <linux/joystick.h>
+ #include <fcntl.h>
+#elif defined(SFML_SYSTEM_FREEBSD)
+ // #include <sys/joystick.h> ?
+#endif
+
namespace sf
{
namespace priv
{
+#if defined(SFML_SYSTEM_LINUX)
+
////////////////////////////////////////////////////////////
/// Initialize the instance and bind it to a physical joystick
////////////////////////////////////////////////////////////
@@ -120,6 +127,45 @@ unsigned int Joystick::GetButtonsCount() const }
+#elif defined(SFML_SYSTEM_FREEBSD)
+
+
+////////////////////////////////////////////////////////////
+/// Initialize the instance and bind it to a physical joystick
+////////////////////////////////////////////////////////////
+void Joystick::Initialize(unsigned int Index)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+/// Update the current joystick and return its new state
+////////////////////////////////////////////////////////////
+JoystickState Joystick::UpdateState()
+{
+ return JoystickState();
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the number of axes supported by the joystick
+////////////////////////////////////////////////////////////
+unsigned int Joystick::GetAxesCount() const
+{
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the number of buttons supported by the joystick
+////////////////////////////////////////////////////////////
+unsigned int Joystick::GetButtonsCount() const
+{
+ return 0;
+}
+
+#endif // defined(SFML_SYSTEM_FREEBSD)
+
} // namespace priv
} // namespace sf
diff --git a/src/SFML/Window/Linux/Joystick.hpp b/src/SFML/Window/Linux/Joystick.hpp index 1c1e4a2..a035f61 100755 --- a/src/SFML/Window/Linux/Joystick.hpp +++ b/src/SFML/Window/Linux/Joystick.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
diff --git a/src/SFML/Window/Linux/VideoModeSupport.cpp b/src/SFML/Window/Linux/VideoModeSupport.cpp index d328702..add99b2 100755 --- a/src/SFML/Window/Linux/VideoModeSupport.cpp +++ b/src/SFML/Window/Linux/VideoModeSupport.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
@@ -45,7 +45,7 @@ void VideoModeSupport::GetSupportedVideoModes(std::vector<VideoMode>& Modes) // First, clear array to fill
Modes.clear();
- // Get the display and screen from sfWindowImplUnix
+ // Get the display and screen from WindowImplUnix
WindowImplX11::OpenDisplay(false);
Display* Disp = WindowImplX11::ourDisplay;
int Screen = WindowImplX11::ourScreen;
@@ -63,15 +63,24 @@ void VideoModeSupport::GetSupportedVideoModes(std::vector<VideoMode>& Modes) XRRScreenSize* Sizes = XRRConfigSizes(Config, &NbSizes);
if (Sizes && (NbSizes > 0))
{
- // Add them to the video modes array
- for (int i = 0; i < NbSizes; ++i)
+ // Get the list of supported depths
+ int NbDepths = 0;
+ int* Depths = XListDepths(Disp, Screen, &NbDepths);
+ if (Depths && (NbDepths > 0))
{
- // Convert to sfVideoMode
- VideoMode Mode(Sizes[i].width, Sizes[i].height, 32);
-
- // Add it only if it is not already in the array
- if (std::find(Modes.begin(), Modes.end(), Mode) == Modes.end())
- Modes.push_back(Mode);
+ // Combine depths and sizes to fill the array of supported modes
+ for (int i = 0; i < NbDepths; ++i)
+ {
+ for (int j = 0; j < NbSizes; ++j)
+ {
+ // Convert to VideoMode
+ VideoMode Mode(Sizes[j].width, Sizes[j].height, Depths[i]);
+
+ // Add it only if it is not already in the array
+ if (std::find(Modes.begin(), Modes.end(), Mode) == Modes.end())
+ Modes.push_back(Mode);
+ }
+ }
}
}
@@ -99,7 +108,7 @@ VideoMode VideoModeSupport::GetDesktopVideoMode() {
VideoMode DesktopMode;
- // Get the display and screen from sfWindowImplUnix
+ // Get the display and screen from WindowImplUnix
WindowImplX11::OpenDisplay(false);
Display* Disp = WindowImplX11::ourDisplay;
int Screen = WindowImplX11::ourScreen;
@@ -120,7 +129,7 @@ VideoMode VideoModeSupport::GetDesktopVideoMode() int NbSizes;
XRRScreenSize* Sizes = XRRConfigSizes(Config, &NbSizes);
if (Sizes && (NbSizes > 0))
- DesktopMode = VideoMode(Sizes[CurrentMode].width, Sizes[CurrentMode].height, 32);
+ DesktopMode = VideoMode(Sizes[CurrentMode].width, Sizes[CurrentMode].height, DefaultDepth(Disp, Screen));
// Free the configuration instance
XRRFreeScreenConfigInfo(Config);
diff --git a/src/SFML/Window/Linux/VideoModeSupport.hpp b/src/SFML/Window/Linux/VideoModeSupport.hpp index 87291fc..9160ff5 100755 --- a/src/SFML/Window/Linux/VideoModeSupport.hpp +++ b/src/SFML/Window/Linux/VideoModeSupport.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
diff --git a/src/SFML/Window/Linux/WindowImplX11.cpp b/src/SFML/Window/Linux/WindowImplX11.cpp index 0659089..fa0bd8e 100755 --- a/src/SFML/Window/Linux/WindowImplX11.cpp +++ b/src/SFML/Window/Linux/WindowImplX11.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
@@ -37,6 +37,19 @@ #include <vector>
+namespace
+{
+ ////////////////////////////////////////////////////////////
+ /// Filter the events received by windows
+ /// (only allow those matching a specific window)
+ ////////////////////////////////////////////////////////////
+ Bool CheckEvent(::Display*, XEvent* Event, XPointer UserData)
+ {
+ // Just check if the event matches the window
+ return Event->xany.window == reinterpret_cast< ::Window >(UserData);
+ }
+}
+
namespace sf
{
namespace priv
@@ -340,7 +353,16 @@ WindowImplX11::~WindowImplX11() ////////////////////////////////////////////////////////////
/// Check if there's an active context on the current thread
+////////////////////
+////////////////////////////////////////////////////////////
+/// Filter the received events
+/// (only allow those matching a specific window)
////////////////////////////////////////////////////////////
+Bool CheckEvent(::Display*, XEvent* Event, XPointer UserData)
+{
+ // Just check if the event matches our window
+ return Event->xany.window == reinterpret_cast< ::Window >(UserData);
+}////////////////////////////////////////
bool WindowImplX11::IsContextActive()
{
return glXGetCurrentContext() != NULL;
@@ -362,30 +384,53 @@ void WindowImplX11::Display() ////////////////////////////////////////////////////////////
void WindowImplX11::ProcessEvents()
{
+ // This function implements a workaround to properly discard
+ // repeated key events when necessary. The problem is that the
+ // system's key events policy doesn't match SFML's one: X server will generate
+ // both repeated KeyPress and KeyRelease events when maintaining a key down, while
+ // SFML only wants repeated KeyPress events. Thus, we have to:
+ // - Discard duplicated KeyRelease events when EnableKeyRepeat is true
+ // - Discard both duplicated KeyPress and KeyRelease events when EnableKeyRepeat is false
+
+
// Process any event in the queue matching our window
XEvent Event;
- while (XCheckIfEvent(ourDisplay, &Event, &WindowImplX11::CheckEvent, reinterpret_cast<XPointer>(myWindow)))
+ while (XCheckIfEvent(ourDisplay, &Event, &CheckEvent, reinterpret_cast<XPointer>(myWindow)))
{
- // Filter repeated key events
- if (Event.type == KeyRelease)
+ // Detect repeated key events
+ if ((Event.type == KeyPress) || (Event.type == KeyRelease))
{
- if (XPending(ourDisplay))
+ if (Event.xkey.keycode < 256)
{
- XEvent NextEvent;
- XPeekEvent(ourDisplay, &NextEvent);
- if ((NextEvent.type == KeyPress) &&
- (NextEvent.xkey.keycode == Event.xkey.keycode) &&
- (NextEvent.xkey.time == Event.xkey.time))
+ // To detect if it is a repeated key event, we check the current state of the key.
+ // - If the state is "down", KeyReleased events must obviously be discarded.
+ // - KeyPress events are a little bit harder to handle: they depend on the EnableKeyRepeat state,
+ // and we need to properly forward the first one.
+ char Keys[32];
+ XQueryKeymap(ourDisplay, Keys);
+ if (Keys[Event.xkey.keycode >> 3] & (1 << (Event.xkey.keycode % 8)))
{
- if (!myKeyRepeat)
- XNextEvent(ourDisplay, &NextEvent);
- continue;
+ // KeyRelease event + key down = repeated event --> discard
+ if (Event.type == KeyRelease)
+ {
+ myLastKeyReleaseEvent = Event;
+ continue;
+ }
+
+ // KeyPress event + key repeat disabled + matching KeyRelease event = repeated event --> discard
+ if ((Event.type == KeyPress) && !myKeyRepeat &&
+ (myLastKeyReleaseEvent.xkey.keycode == Event.xkey.keycode) &&
+ (myLastKeyReleaseEvent.xkey.time == Event.xkey.time))
+ {
+ continue;
+ }
}
}
}
+ // Process the event
ProcessEvent(Event);
- }
+ }
}
@@ -649,7 +694,6 @@ bool WindowImplX11::CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisu {
BestScore = Score;
BestVisual = &Visuals[i];
- break;
}
}
@@ -710,6 +754,9 @@ bool WindowImplX11::CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisu ////////////////////////////////////////////////////////////
void WindowImplX11::Initialize()
{
+ // Make sure the "last key release" is initialized with invalid values
+ myLastKeyReleaseEvent.type = -1;
+
// Get the atom defining the close event
myAtomClose = XInternAtom(ourDisplay, "WM_DELETE_WINDOW", false);
XSetWMProtocols(ourDisplay, myWindow, &myAtomClose, 1);
@@ -804,17 +851,6 @@ void WindowImplX11::CleanUp() ////////////////////////////////////////////////////////////
-/// Filter the received events
-/// (only allow those matching a specific window)
-////////////////////////////////////////////////////////////
-Bool WindowImplX11::CheckEvent(::Display*, XEvent* Event, XPointer UserData)
-{
- // Just check if the event matches our window
- return Event->xany.window == reinterpret_cast< ::Window >(UserData);
-}
-
-
-////////////////////////////////////////////////////////////
/// Process an incoming event from the window
////////////////////////////////////////////////////////////
void WindowImplX11::ProcessEvent(XEvent WinEvent)
diff --git a/src/SFML/Window/Linux/WindowImplX11.hpp b/src/SFML/Window/Linux/WindowImplX11.hpp index b4506fc..9fd4e0e 100755 --- a/src/SFML/Window/Linux/WindowImplX11.hpp +++ b/src/SFML/Window/Linux/WindowImplX11.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
@@ -201,18 +201,6 @@ private : void CleanUp();
////////////////////////////////////////////////////////////
- /// Filter the received events
- /// (only allow those matching a specific window)
- ///
- /// \param Event : Event to filter
- /// \param UserData : Data passed to the function (here : the window to compare)
- ///
- /// \return True if the event belongs to the specified window
- ///
- ////////////////////////////////////////////////////////////
- static Bool CheckEvent(::Display*, XEvent* Event, XPointer UserData);
-
- ////////////////////////////////////////////////////////////
/// Process an incoming event from the window
///
/// \param WinEvent : Event which has been received
@@ -259,14 +247,15 @@ private : ////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- ::Window myWindow; ///< X11 structure defining our window
- bool myIsExternal; ///< Tell whether the window has been created externally or by SFML
- GLXContext myGLContext; ///< OpenGL context attached to the window
- Atom myAtomClose; ///< Atom used to identify the close event
- int myOldVideoMode; ///< Video mode in use before we switch to fullscreen
- Cursor myHiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
- XIC myInputContext; ///< Input context used to get unicode input in our window
- bool myKeyRepeat; ///< Is the KeyRepeat feature enabled ?
+ ::Window myWindow; ///< X11 structure defining our window
+ bool myIsExternal; ///< Tell whether the window has been created externally or by SFML
+ GLXContext myGLContext; ///< OpenGL context attached to the window
+ Atom myAtomClose; ///< Atom used to identify the close event
+ int myOldVideoMode; ///< Video mode in use before we switch to fullscreen
+ Cursor myHiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
+ XIC myInputContext; ///< Input context used to get unicode input in our window
+ bool myKeyRepeat; ///< Is the KeyRepeat feature enabled ?
+ XEvent myLastKeyReleaseEvent; ///< Last key release event we received (needed for discarding repeated key events)
};
} // namespace priv
diff --git a/src/SFML/Window/Cocoa/WindowController.h b/src/SFML/Window/Template for new ports/Joystick.cpp index 4c40825..442e329 100755 --- a/src/SFML/Window/Cocoa/WindowController.h +++ b/src/SFML/Window/Template for new ports/Joystick.cpp @@ -1,73 +1,74 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 Lucas Soltic (elmerod@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> -#import <SFML/Window/Event.hpp> - - -//////////////////////////////////////////////////////////// -/// WindowController is a Cocoa notification receiver -//////////////////////////////////////////////////////////// -@interface WindowController : NSObject { - sf::priv::WindowImplCocoa *parentWindow; -} - -//////////////////////////////////////////////////////////// -/// Return a new autoreleased WindowController object linked -/// to the 'window' WindowImplCocoa object. -//////////////////////////////////////////////////////////// -+ (WindowController *)controllerWithWindow:(sf::priv::WindowImplCocoa *)window; -- (WindowController *)initWithWindow:(sf::priv::WindowImplCocoa *)window; - -//////////////////////////////////////////////////////////// -/// Notification method receiver when OpenGL view size changes -//////////////////////////////////////////////////////////// -- (void)viewFrameDidChange:(NSNotification *)notification; - -//////////////////////////////////////////////////////////// -/// Notification method receiver when the window gains focus -//////////////////////////////////////////////////////////// -- (void)windowDidBecomeMain:(NSNotification *)notification; - -//////////////////////////////////////////////////////////// -/// Notification method receiver when the window loses focus -//////////////////////////////////////////////////////////// -- (void)windowDidResignMain:(NSNotification *)notification; - -//////////////////////////////////////////////////////////// -/// Notification method receiver when the window closes -//////////////////////////////////////////////////////////// -- (void)windowWillClose:(NSNotification *)notification; - -@end - -// NSWindow subclass used to allow full screen windows to receive events -@interface SFWindow : NSWindow -@end - +////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2009 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
+////////////////////////////////////////////////////////////
+#include <SFML/xxx/Joystick.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Initialize the instance and bind it to a physical joystick
+////////////////////////////////////////////////////////////
+void Joystick::Initialize(unsigned int Index)
+{
+ // Reset the joystick state
+
+ // Initialize the Index-th available joystick
+}
+
+
+////////////////////////////////////////////////////////////
+/// Update the current joystick and return its new state
+////////////////////////////////////////////////////////////
+JoystickState Joystick::UpdateState()
+{
+ // Fill a JoystickState instance with the current joystick state
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the number of axes supported by the joystick
+////////////////////////////////////////////////////////////
+unsigned int Joystick::GetAxesCount() const
+{
+ // Return number of supported axes
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the number of buttons supported by the joystick
+////////////////////////////////////////////////////////////
+unsigned int Joystick::GetButtonsCount() const
+{
+ // Return number of supported buttons
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Template for new ports/Joystick.hpp b/src/SFML/Window/Template for new ports/Joystick.hpp new file mode 100755 index 0000000..bb5243a --- /dev/null +++ b/src/SFML/Window/Template for new ports/Joystick.hpp @@ -0,0 +1,82 @@ +////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2009 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.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_JOYSTICKXXX_HPP
+#define SFML_JOYSTICKXXX_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Linux implementation of Joystick
+////////////////////////////////////////////////////////////
+class Joystick
+{
+public :
+
+ ////////////////////////////////////////////////////////////
+ /// Initialize the instance and bind it to a physical joystick
+ ///
+ /// \param Index : Index of the physical joystick to bind to
+ ///
+ ////////////////////////////////////////////////////////////
+ void Initialize(unsigned int Index);
+
+ ////////////////////////////////////////////////////////////
+ /// Update the current joystick and return its new state
+ ///
+ /// \return Current state of the joystick
+ ///
+ ////////////////////////////////////////////////////////////
+ JoystickState UpdateState();
+
+ ////////////////////////////////////////////////////////////
+ /// Get the number of axes supported by the joystick
+ ///
+ /// \return Number of axis
+ ///
+ ////////////////////////////////////////////////////////////
+ unsigned int GetAxesCount() const;
+
+ ////////////////////////////////////////////////////////////
+ /// Get the number of buttons supported by the joystick
+ ///
+ /// \return Number of buttons
+ ///
+ ////////////////////////////////////////////////////////////
+ unsigned int GetButtonsCount() const;
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_JOYSTICKXXX_HPP
diff --git a/src/SFML/Window/Template for new ports/VideoModeSupport.cpp b/src/SFML/Window/Template for new ports/VideoModeSupport.cpp new file mode 100755 index 0000000..0057992 --- /dev/null +++ b/src/SFML/Window/Template for new ports/VideoModeSupport.cpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2009 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
+////////////////////////////////////////////////////////////
+#include <SFML/Window/XXX/VideoModeSupport.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Get supported video modes
+////////////////////////////////////////////////////////////
+void VideoModeSupport::GetSupportedVideoModes(std::vector<VideoMode>& Modes)
+{
+ // Get all the supported fullscreen modes and put them in Modes array
+
+ // Just care about width, height and bpp (ignore frequency and other attributes)
+
+ // You must remove duplicates
+
+ // Order doesn't matter (the array will be sorted later)
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get current desktop video mode
+////////////////////////////////////////////////////////////
+VideoMode VideoModeSupport::GetDesktopVideoMode()
+{
+ // Return the current desktop video mode
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Template for new ports/VideoModeSupport.hpp b/src/SFML/Window/Template for new ports/VideoModeSupport.hpp new file mode 100755 index 0000000..9d46f78 --- /dev/null +++ b/src/SFML/Window/Template for new ports/VideoModeSupport.hpp @@ -0,0 +1,69 @@ +////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2009 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.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_VIDEOMODESUPPORTXXX_HPP
+#define SFML_VIDEOMODESUPPORTXXX_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/VideoMode.hpp>
+#include <vector>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// XXX implementation of VideoModeSupport
+/// Give access to video mode related OS-specific functions
+////////////////////////////////////////////////////////////
+class VideoModeSupport
+{
+public :
+
+ ////////////////////////////////////////////////////////////
+ /// Get supported video modes
+ ///
+ /// \param Modes : Array to fill with available video modes
+ ///
+ ////////////////////////////////////////////////////////////
+ static void GetSupportedVideoModes(std::vector<VideoMode>& Modes);
+
+ ////////////////////////////////////////////////////////////
+ /// Get current desktop video mode
+ ///
+ /// \return Current desktop video mode
+ ///
+ ////////////////////////////////////////////////////////////
+ static VideoMode GetDesktopVideoMode();
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_VIDEOMODESUPPORTXXX_HPP
diff --git a/src/SFML/Window/Template for new ports/WindowImplXXX.cpp b/src/SFML/Window/Template for new ports/WindowImplXXX.cpp new file mode 100755 index 0000000..46f5d2d --- /dev/null +++ b/src/SFML/Window/Template for new ports/WindowImplXXX.cpp @@ -0,0 +1,231 @@ +////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2009 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
+////////////////////////////////////////////////////////////
+#include <SFML/Window/XXX/WindowImplXXX.hpp>
+#include <SFML/Window/WindowStyle.hpp>
+#include <GL/gl.h>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Default constructor
+/// (creates a dummy window to provide a valid OpenGL context)
+////////////////////////////////////////////////////////////
+WindowImplXXX::WindowImplXXX()
+{
+ // Create a dummy window (with the fewest attributes -- it's just to have a valid support for an OpenGL context)
+
+ // Initialize myWidth and myHeight members from base class with the window size
+
+ // Create an OpenGL context in this window and DO NOT make it active
+}
+
+
+////////////////////////////////////////////////////////////
+/// Create the window implementation from an existing control
+////////////////////////////////////////////////////////////
+WindowImplXXX::WindowImplXXX(WindowHandle Handle, WindowSettings& Params)
+{
+ // Make sure we'll be able to catch all the events of the given window
+
+ // Initialize myWidth and myHeight members from base class with the window size
+
+ // Create an OpenGL context in this window and make it active
+}
+
+
+////////////////////////////////////////////////////////////
+/// Create the window implementation
+////////////////////////////////////////////////////////////
+WindowImplXXX::WindowImplXXX(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params) :
+{
+ // Create a new window with given size, title and style
+
+ // Initialize myWidth and myHeight members from base class with the window size
+
+ // Create an OpenGL context in this window and make it active
+}
+
+
+////////////////////////////////////////////////////////////
+/// Destructor
+////////////////////////////////////////////////////////////
+WindowImplXXX::~WindowImplXXX()
+{
+ // Destroy the OpenGL context, the window and every resource allocated by this class
+}
+
+
+////////////////////////////////////////////////////////////
+/// Check if there's an active context on the current thread
+////////////////////////////////////////////////////////////
+bool WindowImplXXX::IsContextActive()
+{
+ // Should return whether xxxGetCurrentContext() is NULL or not;
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::Display
+////////////////////////////////////////////////////////////
+void WindowImplXXX::Display()
+{
+ // Swap OpenGL buffers (should be a call to xxxSwapBuffers)
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::ProcessEvents
+////////////////////////////////////////////////////////////
+void WindowImplXXX::ProcessEvents()
+{
+ // Process every event for this window
+
+ // Generate a sf::Event and call SendEvent(Evt) for each event
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetActive
+////////////////////////////////////////////////////////////
+void WindowImplXXX::SetActive(bool Active) const
+{
+ // Bind / unbind OpenGL context (should be a call to xxxMakeCurrent)
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::UseVerticalSync
+////////////////////////////////////////////////////////////
+void WindowImplXXX::UseVerticalSync(bool Enabled)
+{
+ // Activate / deactivate vertical synchronization
+ // usually using an OpenGL extension (should be a call to xxxSwapInterval)
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::ShowMouseCursor
+////////////////////////////////////////////////////////////
+void WindowImplXXX::ShowMouseCursor(bool Show)
+{
+ // Show or hide the system cursor in this window
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetCursorPosition
+////////////////////////////////////////////////////////////
+void WindowImplXXX::SetCursorPosition(unsigned int Left, unsigned int Top)
+{
+ // Change the cursor position (Left and Top are relative to this window)
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetPosition
+////////////////////////////////////////////////////////////
+void WindowImplXXX::SetPosition(int Left, int Top)
+{
+ // Change the window position
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetSize
+////////////////////////////////////////////////////////////
+void WindowImplWin32::SetSize(unsigned int Width, unsigned int Height)
+{
+ // Change the window size
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::Show
+////////////////////////////////////////////////////////////
+void WindowImplXXX::Show(bool State)
+{
+ // Show or hide the window
+}
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::EnableKeyRepeat
+////////////////////////////////////////////////////////////
+void WindowImplXXX::EnableKeyRepeat(bool Enabled)
+{
+ // Enable or disable automatic key-repeat for keydown events
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetIcon
+////////////////////////////////////////////////////////////
+void WindowImplXXX::SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels)
+{
+ // Change all the necessary icons of the window (titlebar, task bar, ...) with the
+ // provided array of 32 bits RGBA pixels
+}
+
+
+/*===========================================================
+ STRATEGY FOR OPENGL CONTEXT CREATION
+
+- If the requested level of anti-aliasing is not supported and is greater than 2, try with 2
+ --> if level 2 fails, disable anti-aliasing
+ --> it's important not to generate an error if anti-aliasing is not supported
+
+- Use a matching pixel mode, or the best of all available pixel modes if no perfect match ;
+ You should use the function EvaluateConfig to get a score for a given configuration
+
+- Don't forget to fill Params (see constructors) back with the actual parameters we got from the chosen pixel format
+
+- IMPORTANT : all OpenGL contexts must be shared (usually a call to xxxShareLists)
+
+===========================================================*/
+
+
+/*===========================================================
+ STRATEGY FOR EVENT HANDLING
+
+- Process any event matching with the ones in sf::Event::EventType
+ --> Create a sf::Event, fill the members corresponding to the event type
+ --> No need to handle joystick events, they are handled by WindowImpl::ProcessJoystickEvents
+ --> Event::TextEntered must provide UTF-16 characters
+ (see http://www.unicode.org/Public/PROGRAMS/CVTUTF/ for unicode conversions)
+ --> Don't forget to process any destroy-like event (ie. when the window is destroyed externally)
+
+- Use SendEvent function from base class to propagate the created events
+
+===========================================================*/
+
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Template for new ports/WindowImplXXX.hpp b/src/SFML/Window/Template for new ports/WindowImplXXX.hpp new file mode 100755 index 0000000..e5dee89 --- /dev/null +++ b/src/SFML/Window/Template for new ports/WindowImplXXX.hpp @@ -0,0 +1,167 @@ +////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2009 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.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_WINDOWIMPLXXX_HPP
+#define SFML_WINDOWIMPLXXX_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Event.hpp>
+#include <SFML/Window/WindowImpl.hpp>
+#include <string>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// WindowImplXXX is the XXX implementation of WindowImpl
+////////////////////////////////////////////////////////////
+class WindowImplXXX : public WindowImpl
+{
+public :
+
+ ////////////////////////////////////////////////////////////
+ /// Default constructor
+ /// (creates a dummy window to provide a valid OpenGL context)
+ ///
+ ////////////////////////////////////////////////////////////
+ WindowImplXXX();
+
+ ////////////////////////////////////////////////////////////
+ /// Construct the window implementation from an existing control
+ ///
+ /// \param Handle : Platform-specific handle of the control
+ /// \param Params : Creation parameters
+ ///
+ ////////////////////////////////////////////////////////////
+ WindowImplXXX(WindowHandle Handle, WindowSettings& Params);
+
+ ////////////////////////////////////////////////////////////
+ /// Create the window implementation
+ ///
+ /// \param Mode : Video mode to use
+ /// \param Title : Title of the window
+ /// \param WindowStyle : Window style
+ /// \param Params : Creation parameters
+ ///
+ ////////////////////////////////////////////////////////////
+ WindowImplXXX(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params);
+
+ ////////////////////////////////////////////////////////////
+ /// Destructor
+ ///
+ ////////////////////////////////////////////////////////////
+ ~WindowImplXXX();
+
+ ////////////////////////////////////////////////////////////
+ /// Check if there's an active context on the current thread
+ ///
+ /// \return True if there's a context bound to the current thread
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool IsContextActive();
+
+private :
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::Display
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void Display();
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::ProcessEvents
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void ProcessEvents();
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetActive
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetActive(bool Active = true) const;
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::IsActive
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual bool IsActive() const;
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::UseVerticalSync
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void UseVerticalSync(bool Enabled);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::ShowMouseCursor
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void ShowMouseCursor(bool Show);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetCursorPosition
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetCursorPosition(unsigned int Left, unsigned int Top);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetPosition
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetPosition(int Left, int Top);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetSize
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetSize(unsigned int Width, unsigned int Height);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::Show
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void Show(bool State);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::EnableKeyRepeat
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void EnableKeyRepeat(bool Enabled);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetIcon
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+#endif // SFML_WINDOWIMPLXXX_HPP
diff --git a/src/SFML/Window/VideoMode.cpp b/src/SFML/Window/VideoMode.cpp index 8efff0f..3ed77bc 100755 --- a/src/SFML/Window/VideoMode.cpp +++ b/src/SFML/Window/VideoMode.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
diff --git a/src/SFML/Window/VideoModeSupport.hpp b/src/SFML/Window/VideoModeSupport.hpp index 63ee1e9..caa94aa 100755 --- a/src/SFML/Window/VideoModeSupport.hpp +++ b/src/SFML/Window/VideoModeSupport.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 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. @@ -35,7 +35,7 @@ #include <SFML/Window/Win32/VideoModeSupport.hpp> -#elif defined(SFML_SYSTEM_LINUX) +#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) #include <SFML/Window/Linux/VideoModeSupport.hpp> diff --git a/src/SFML/Window/Win32/Joystick.cpp b/src/SFML/Window/Win32/Joystick.cpp index 9cf195f..10bb0d6 100755 --- a/src/SFML/Window/Win32/Joystick.cpp +++ b/src/SFML/Window/Win32/Joystick.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
@@ -49,6 +49,8 @@ void Joystick::Initialize(unsigned int Index) // Get the Index-th connected joystick
MMRESULT Error;
JOYINFOEX JoyInfo;
+ JoyInfo.dwSize = sizeof(JoyInfo);
+ JoyInfo.dwFlags = JOY_RETURNALL;
for (unsigned int NbFound = 0; (Error = joyGetPosEx(myIndex, &JoyInfo)) != JOYERR_PARMS; myIndex++)
{
// Check if the current joystick is connected
diff --git a/src/SFML/Window/Win32/Joystick.hpp b/src/SFML/Window/Win32/Joystick.hpp index 95019cb..8303a7e 100755 --- a/src/SFML/Window/Win32/Joystick.hpp +++ b/src/SFML/Window/Win32/Joystick.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
diff --git a/src/SFML/Window/Win32/VideoModeSupport.cpp b/src/SFML/Window/Win32/VideoModeSupport.cpp index cd5f650..8b98e74 100755 --- a/src/SFML/Window/Win32/VideoModeSupport.cpp +++ b/src/SFML/Window/Win32/VideoModeSupport.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index e07eeab..9148774 100755 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
@@ -355,6 +355,13 @@ void WindowImplWin32::SetPosition(int Left, int Top) ////////////////////////////////////////////////////////////
void WindowImplWin32::SetSize(unsigned int Width, unsigned int Height)
{
+ // SetWindowPos wants the total size of the window (including title bar and borders),
+ // so we have to compute it
+ RECT Rect = {0, 0, Width, Height};
+ AdjustWindowRect(&Rect, GetWindowLong(myHandle, GWL_STYLE), false);
+ Width = Rect.right - Rect.left;
+ Height = Rect.bottom - Rect.top;
+
SetWindowPos(myHandle, NULL, 0, 0, Width, Height, SWP_NOMOVE | SWP_NOZORDER);
}
@@ -753,11 +760,22 @@ void WindowImplWin32::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam) {
Event Evt;
Evt.Type = Event::KeyPressed;
- Evt.Key.Code = (WParam == VK_SHIFT) ? GetShiftState(true) : VirtualKeyCodeToSF(WParam, LParam);
Evt.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
Evt.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
Evt.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
- SendEvent(Evt);
+
+ if (WParam != VK_SHIFT)
+ {
+ Evt.Key.Code = VirtualKeyCodeToSF(WParam, LParam);
+ SendEvent(Evt);
+ }
+ else
+ {
+ // Special case for shift, its state can't be retrieved directly
+ Evt.Key.Code = GetShiftState(true);
+ if (Evt.Key.Code != 0)
+ SendEvent(Evt);
+ }
}
break;
}
@@ -768,11 +786,23 @@ void WindowImplWin32::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam) {
Event Evt;
Evt.Type = Event::KeyReleased;
- Evt.Key.Code = (WParam == VK_SHIFT) ? GetShiftState(false) : VirtualKeyCodeToSF(WParam, LParam);
Evt.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
Evt.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
Evt.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
- SendEvent(Evt);
+
+ if (WParam != VK_SHIFT)
+ {
+ Evt.Key.Code = VirtualKeyCodeToSF(WParam, LParam);
+ SendEvent(Evt);
+ }
+ else
+ {
+ // Special case for shift, its state can't be retrieved directly
+ Evt.Key.Code = GetShiftState(false);
+ if (Evt.Key.Code != 0)
+ SendEvent(Evt);
+ }
+
break;
}
diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index 7b6a425..75c1c59 100755 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp index 7539bde..cfaae84 100755 --- a/src/SFML/Window/Window.cpp +++ b/src/SFML/Window/Window.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
@@ -32,19 +32,27 @@ #include <iostream>
+////////////////////////////////////////////////////////////
+// Private data
+////////////////////////////////////////////////////////////
+namespace
+{
+ const sf::Window* FullscreenWindow = NULL;
+}
+
+
namespace sf
{
////////////////////////////////////////////////////////////
/// Default constructor
-///
////////////////////////////////////////////////////////////
Window::Window() :
myWindow (NULL),
myLastFrameTime (0.f),
myIsExternal (false),
myFramerateLimit(0),
-mySetCursorPosX (-1),
-mySetCursorPosY (-1)
+mySetCursorPosX (0xFFFF),
+mySetCursorPosY (0xFFFF)
{
}
@@ -73,8 +81,8 @@ myWindow (NULL), myLastFrameTime (0.f),
myIsExternal (true),
myFramerateLimit(0),
-mySetCursorPosX (-1),
-mySetCursorPosY (-1)
+mySetCursorPosX (0xFFFF),
+mySetCursorPosY (0xFFFF)
{
Create(Handle, Params);
}
@@ -95,20 +103,36 @@ Window::~Window() ////////////////////////////////////////////////////////////
void Window::Create(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, const WindowSettings& Params)
{
- // Check validity of video mode
- if ((WindowStyle & Style::Fullscreen) && !Mode.IsValid())
+ // Destroy the previous window implementation
+ Close();
+
+ // Fullscreen style requires some tests
+ if (WindowStyle & Style::Fullscreen)
{
- std::cerr << "The requested video mode is not available, switching to a valid mode" << std::endl;
- Mode = VideoMode::GetMode(0);
+ // Make sure there's not already a fullscreen window (only one is allowed)
+ if (FullscreenWindow)
+ {
+ std::cerr << "Creating two fullscreen windows is not allowed, switching to windowed mode" << std::endl;
+ WindowStyle &= ~Style::Fullscreen;
+ }
+ else
+ {
+ // Make sure the chosen video mode is compatible
+ if (!Mode.IsValid())
+ {
+ std::cerr << "The requested video mode is not available, switching to a valid mode" << std::endl;
+ Mode = VideoMode::GetMode(0);
+ }
+
+ // Update the fullscreen window
+ FullscreenWindow = this;
+ }
}
// Check validity of style
if ((WindowStyle & Style::Close) || (WindowStyle & Style::Resize))
WindowStyle |= Style::Titlebar;
- // Destroy the previous window implementation
- delete myWindow;
-
// Activate the global context
Context::GetGlobal().SetActive(true);
@@ -123,7 +147,7 @@ void Window::Create(VideoMode Mode, const std::string& Title, unsigned long Wind void Window::Create(WindowHandle Handle, const WindowSettings& Params)
{
// Destroy the previous window implementation
- delete myWindow;
+ Close();
// Activate the global context
Context::GetGlobal().SetActive(true);
@@ -143,6 +167,10 @@ void Window::Close() // Delete the window implementation
delete myWindow;
myWindow = NULL;
+
+ // Update the fullscreen window
+ if (this == FullscreenWindow)
+ FullscreenWindow = NULL;
}
@@ -413,11 +441,12 @@ void Window::OnEvent(const Event& EventReceived) ////////////////////////////////////////////////////////////
void Window::Initialize(priv::WindowImpl* Window)
{
- // Assign new window and listen to its events
+ // Assign and initialize the new window
myWindow = Window;
- myWindow->AddListener(this);
+ myWindow->Initialize();
- // Attach input to the window
+ // Listen to events from the new window
+ myWindow->AddListener(this);
myWindow->AddListener(&myInput);
// Setup default behaviours (to get a consistent behaviour across different implementations)
diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp index fde2d44..bc60543 100755 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -1,252 +1,260 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2008 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 -//////////////////////////////////////////////////////////// -#include <SFML/Window/WindowImpl.hpp> -#include <SFML/Window/Event.hpp> -#include <SFML/Window/WindowListener.hpp> -#include <algorithm> -#include <cmath> - -#if defined(SFML_SYSTEM_WINDOWS) - - #include <SFML/Window/Win32/WindowImplWin32.hpp> - typedef sf::priv::WindowImplWin32 WindowImplType; - -#elif defined(SFML_SYSTEM_LINUX) - - #include <SFML/Window/Linux/WindowImplX11.hpp> - typedef sf::priv::WindowImplX11 WindowImplType; - -#elif defined(SFML_SYSTEM_MACOS) - - #include <SFML/Window/Cocoa/WindowImplCocoa.hpp> - typedef sf::priv::WindowImplCocoa WindowImplType; - -#endif - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// Create a new window depending on the current OS -//////////////////////////////////////////////////////////// -WindowImpl* WindowImpl::New() -{ - return new WindowImplType(); -} - - -//////////////////////////////////////////////////////////// -/// Create a new window depending on the current OS -//////////////////////////////////////////////////////////// -WindowImpl* WindowImpl::New(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params) -{ - return new WindowImplType(Mode, Title, WindowStyle, Params); -} - - -//////////////////////////////////////////////////////////// -/// Create a new window depending on the current OS -//////////////////////////////////////////////////////////// -WindowImpl* WindowImpl::New(WindowHandle Handle, WindowSettings& Params) -{ - return new WindowImplType(Handle, Params); -} - - -//////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -WindowImpl::WindowImpl() : -myWidth (0), -myHeight (0), -myJoyThreshold(0.1f) -{ - // Initialize the joysticks - for (unsigned int i = 0; i < JoysticksCount; ++i) - { - myJoysticks[i].Initialize(i); - myJoyStates[i] = myJoysticks[i].UpdateState(); - } -} - - -//////////////////////////////////////////////////////////// -/// Destructor -//////////////////////////////////////////////////////////// -WindowImpl::~WindowImpl() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -/// Add a listener to the window -//////////////////////////////////////////////////////////// -void WindowImpl::AddListener(WindowListener* Listener) -{ - if (Listener) - myListeners.insert(Listener); -} - - -//////////////////////////////////////////////////////////// -/// Remove a listener from the window -//////////////////////////////////////////////////////////// -void WindowImpl::RemoveListener(WindowListener* Listener) -{ - myListeners.erase(Listener); -} - - -//////////////////////////////////////////////////////////// -/// Get the client width of the window -//////////////////////////////////////////////////////////// -unsigned int WindowImpl::GetWidth() const -{ - return myWidth; -} - - -//////////////////////////////////////////////////////////// -/// Get the client height of the window -//////////////////////////////////////////////////////////// -unsigned int WindowImpl::GetHeight() const -{ - return myHeight; -} - - -//////////////////////////////////////////////////////////// -/// Change the joystick threshold, ie. the value below which -/// no move event will be generated -//////////////////////////////////////////////////////////// -void WindowImpl::SetJoystickThreshold(float Threshold) -{ - myJoyThreshold = Threshold; -} - - -//////////////////////////////////////////////////////////// -/// Process incoming events from operating system -//////////////////////////////////////////////////////////// -void WindowImpl::DoEvents() -{ - // Read the joysticks state and generate the appropriate events - ProcessJoystickEvents(); - - // Let the derived class process other events - ProcessEvents(); -} - - -//////////////////////////////////////////////////////////// -/// Check if there's an active context on the current thread -//////////////////////////////////////////////////////////// -bool WindowImpl::IsContextActive() -{ - return WindowImplType::IsContextActive(); -} - - -//////////////////////////////////////////////////////////// -/// Send an event to listeners -//////////////////////////////////////////////////////////// -void WindowImpl::SendEvent(const Event& EventToSend) -{ - for (std::set<WindowListener*>::iterator i = myListeners.begin(); i != myListeners.end(); ++i) - { - (*i)->OnEvent(EventToSend); - } -} - - -//////////////////////////////////////////////////////////// -/// Evaluate a pixel format configuration. -/// This functions can be used by implementations that have -/// several valid formats and want to get the best one -//////////////////////////////////////////////////////////// -int WindowImpl::EvaluateConfig(const VideoMode& Mode, const WindowSettings& Settings, int ColorBits, int DepthBits, int StencilBits, int Antialiasing) -{ - return abs(static_cast<int>(Mode.BitsPerPixel - ColorBits)) + - abs(static_cast<int>(Settings.DepthBits - DepthBits)) + - abs(static_cast<int>(Settings.StencilBits - StencilBits)) + - abs(static_cast<int>(Settings.AntialiasingLevel - Antialiasing)); -} - - -//////////////////////////////////////////////////////////// -/// Read the joysticks state and generate the appropriate events -//////////////////////////////////////////////////////////// -void WindowImpl::ProcessJoystickEvents() -{ - for (unsigned int i = 0; i < JoysticksCount; ++i) - { - // Copy the previous state of the joystick and get the new one - JoystickState PreviousState = myJoyStates[i]; - myJoyStates[i] = myJoysticks[i].UpdateState(); - - // Axis - for (unsigned int j = 0; j < myJoysticks[i].GetAxesCount(); ++j) - { - float PrevPos = PreviousState.Axis[j]; - float CurrPos = myJoyStates[i].Axis[j]; - if (fabs(CurrPos - PrevPos) >= myJoyThreshold) - { - Event Event; - Event.Type = Event::JoyMoved; - Event.JoyMove.JoystickId = i; - Event.JoyMove.Axis = static_cast<Joy::Axis>(j); - Event.JoyMove.Position = CurrPos; - SendEvent(Event); - } - } - - // Buttons - for (unsigned int j = 0; j < myJoysticks[i].GetButtonsCount(); ++j) - { - bool PrevPressed = PreviousState.Buttons[j]; - bool CurrPressed = myJoyStates[i].Buttons[j]; - - if ((!PrevPressed && CurrPressed) || (PrevPressed && !CurrPressed)) - { - Event Event; - Event.Type = CurrPressed ? Event::JoyButtonPressed : Event::JoyButtonReleased; - Event.JoyButton.JoystickId = i; - Event.JoyButton.Button = j; - SendEvent(Event); - } - } - } -} - - -} // namespace priv - -} // namespace sf +////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2009 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
+////////////////////////////////////////////////////////////
+#include <SFML/Window/WindowImpl.hpp>
+#include <SFML/Window/Event.hpp>
+#include <SFML/Window/WindowListener.hpp>
+#include <algorithm>
+#include <cmath>
+
+#if defined(SFML_SYSTEM_WINDOWS)
+
+ #include <SFML/Window/Win32/WindowImplWin32.hpp>
+ typedef sf::priv::WindowImplWin32 WindowImplType;
+
+#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
+
+ #include <SFML/Window/Linux/WindowImplX11.hpp>
+ typedef sf::priv::WindowImplX11 WindowImplType;
+
+#elif defined(SFML_SYSTEM_MACOS)
+
+ #include <SFML/Window/Cocoa/WindowImplCocoa.hpp>
+ typedef sf::priv::WindowImplCocoa WindowImplType;
+
+#endif
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Create a new window depending on the current OS
+////////////////////////////////////////////////////////////
+WindowImpl* WindowImpl::New()
+{
+ return new WindowImplType();
+}
+
+
+////////////////////////////////////////////////////////////
+/// Create a new window depending on the current OS
+////////////////////////////////////////////////////////////
+WindowImpl* WindowImpl::New(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params)
+{
+ return new WindowImplType(Mode, Title, WindowStyle, Params);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Create a new window depending on the current OS
+////////////////////////////////////////////////////////////
+WindowImpl* WindowImpl::New(WindowHandle Handle, WindowSettings& Params)
+{
+ return new WindowImplType(Handle, Params);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Default constructor
+////////////////////////////////////////////////////////////
+WindowImpl::WindowImpl() :
+myWidth (0),
+myHeight (0),
+myJoyThreshold(0.1f)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+/// Destructor
+////////////////////////////////////////////////////////////
+WindowImpl::~WindowImpl()
+{
+ // Nothing to do
+}
+
+
+////////////////////////////////////////////////////////////
+/// Add a listener to the window
+////////////////////////////////////////////////////////////
+void WindowImpl::AddListener(WindowListener* Listener)
+{
+ if (Listener)
+ myListeners.insert(Listener);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Remove a listener from the window
+////////////////////////////////////////////////////////////
+void WindowImpl::RemoveListener(WindowListener* Listener)
+{
+ myListeners.erase(Listener);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Initialize window's states that can't be done at construction
+////////////////////////////////////////////////////////////
+void WindowImpl::Initialize()
+{
+ // Initialize the joysticks
+ for (unsigned int i = 0; i < JoysticksCount; ++i)
+ {
+ myJoysticks[i].Initialize(i);
+ myJoyStates[i] = myJoysticks[i].UpdateState();
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the client width of the window
+////////////////////////////////////////////////////////////
+unsigned int WindowImpl::GetWidth() const
+{
+ return myWidth;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the client height of the window
+////////////////////////////////////////////////////////////
+unsigned int WindowImpl::GetHeight() const
+{
+ return myHeight;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Change the joystick threshold, ie. the value below which
+/// no move event will be generated
+////////////////////////////////////////////////////////////
+void WindowImpl::SetJoystickThreshold(float Threshold)
+{
+ myJoyThreshold = Threshold;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Process incoming events from operating system
+////////////////////////////////////////////////////////////
+void WindowImpl::DoEvents()
+{
+ // Read the joysticks state and generate the appropriate events
+ ProcessJoystickEvents();
+
+ // Let the derived class process other events
+ ProcessEvents();
+}
+
+
+////////////////////////////////////////////////////////////
+/// Check if there's an active context on the current thread
+////////////////////////////////////////////////////////////
+bool WindowImpl::IsContextActive()
+{
+ return WindowImplType::IsContextActive();
+}
+
+
+////////////////////////////////////////////////////////////
+/// Send an event to listeners
+////////////////////////////////////////////////////////////
+void WindowImpl::SendEvent(const Event& EventToSend)
+{
+ for (std::set<WindowListener*>::iterator i = myListeners.begin(); i != myListeners.end(); ++i)
+ {
+ (*i)->OnEvent(EventToSend);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Evaluate a pixel format configuration.
+/// This functions can be used by implementations that have
+/// several valid formats and want to get the best one
+////////////////////////////////////////////////////////////
+int WindowImpl::EvaluateConfig(const VideoMode& Mode, const WindowSettings& Settings, int ColorBits, int DepthBits, int StencilBits, int Antialiasing)
+{
+ return abs(static_cast<int>(Mode.BitsPerPixel - ColorBits)) +
+ abs(static_cast<int>(Settings.DepthBits - DepthBits)) +
+ abs(static_cast<int>(Settings.StencilBits - StencilBits)) +
+ abs(static_cast<int>(Settings.AntialiasingLevel - Antialiasing));
+}
+
+
+////////////////////////////////////////////////////////////
+/// Read the joysticks state and generate the appropriate events
+////////////////////////////////////////////////////////////
+void WindowImpl::ProcessJoystickEvents()
+{
+ for (unsigned int i = 0; i < JoysticksCount; ++i)
+ {
+ // Copy the previous state of the joystick and get the new one
+ JoystickState PreviousState = myJoyStates[i];
+ myJoyStates[i] = myJoysticks[i].UpdateState();
+
+ // Axis
+ for (unsigned int j = 0; j < myJoysticks[i].GetAxesCount(); ++j)
+ {
+ float PrevPos = PreviousState.Axis[j];
+ float CurrPos = myJoyStates[i].Axis[j];
+ if (fabs(CurrPos - PrevPos) >= myJoyThreshold)
+ {
+ Event Event;
+ Event.Type = Event::JoyMoved;
+ Event.JoyMove.JoystickId = i;
+ Event.JoyMove.Axis = static_cast<Joy::Axis>(j);
+ Event.JoyMove.Position = CurrPos;
+ SendEvent(Event);
+ }
+ }
+
+ // Buttons
+ for (unsigned int j = 0; j < myJoysticks[i].GetButtonsCount(); ++j)
+ {
+ bool PrevPressed = PreviousState.Buttons[j];
+ bool CurrPressed = myJoyStates[i].Buttons[j];
+
+ if ((!PrevPressed && CurrPressed) || (PrevPressed && !CurrPressed))
+ {
+ Event Event;
+ Event.Type = CurrPressed ? Event::JoyButtonPressed : Event::JoyButtonReleased;
+ Event.JoyButton.JoystickId = i;
+ Event.JoyButton.Button = j;
+ SendEvent(Event);
+ }
+ }
+ }
+}
+
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index e231ff3..15d29ec 100755 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2009 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.
@@ -109,6 +109,12 @@ public : void RemoveListener(WindowListener* Listener);
////////////////////////////////////////////////////////////
+ /// Initialize window's states that can't be done at construction
+ ///
+ ////////////////////////////////////////////////////////////
+ void Initialize();
+
+ ////////////////////////////////////////////////////////////
/// Get the client width of the window
///
/// \return Width of the window in pixels
|