Synchronized with trunk

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1068 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
laurentgom 2009-03-28 19:24:12 +00:00
commit b194b9969a
81 changed files with 4492 additions and 2174 deletions

View file

@ -175,6 +175,17 @@ void Sound::SetPosition(const Vector3f& Position)
}
////////////////////////////////////////////////////////////
/// Make the sound's position relative to the listener's
/// position, or absolute.
/// The default value is false (absolute)
////////////////////////////////////////////////////////////
void Sound::SetRelativeToListener(bool Relative)
{
ALCheck(alSourcei(mySource, AL_SOURCE_RELATIVE, Relative));
}
////////////////////////////////////////////////////////////
/// Set the minimum distance - closer than this distance,
/// the listener will hear the sound at its maximum volume.
@ -263,6 +274,19 @@ Vector3f Sound::GetPosition() const
}
////////////////////////////////////////////////////////////
/// Tell if the sound's position is relative to the listener's
/// position, or if it's absolute
////////////////////////////////////////////////////////////
bool Sound::IsRelativeToListener() const
{
ALint Relative;
ALCheck(alGetSourcei(mySource, AL_SOURCE_RELATIVE, &Relative));
return Relative != 0;
}
////////////////////////////////////////////////////////////
/// Get the minimum distance
////////////////////////////////////////////////////////////

View file

@ -2037,7 +2037,6 @@ void dct_iv_slow(float *buffer, int n)
//acc += x[j] * cos(M_PI / n * (i + 0.5) * (j + 0.5));
buffer[i] = acc;
}
free(x);
}
void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)
@ -3504,8 +3503,8 @@ static int start_decoder(vorb *f)
#else
for (j=0; j < (int) c->lookup_values; ++j)
c->multiplicands[j] = mults[j] * c->delta_value + c->minimum_value;
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
#endif
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
}
skip:;
@ -3812,6 +3811,7 @@ static void vorbis_deinit(stb_vorbis *p)
setup_free(p, p->B[i]);
setup_free(p, p->C[i]);
setup_free(p, p->window[i]);
setup_free(p, p->bit_reverse[i]);
}
#ifndef STB_VORBIS_NO_STDIO
if (p->close_on_free) fclose(p->f);

View file

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 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.

View file

@ -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;
- (void)doFadeOperation:(int)operation time:(float)time sync:(bool)sync;
////////////////////////////////////////////////////////////
/// Return the desktop video mode (made at the instance initialization)
////////////////////////////////////////////////////////////
- (const sf::VideoMode&)desktopMode;
@end
////////////////////////////////////////////////////////////
/// check that ptr is valid, otherwise print msg in
/// std::cerr and throw std::bad_alloc.
/// Must be used to check alloc results
////////////////////////////////////////////////////////////
template <typename T>
T *massert(T *ptr);

View file

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// 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;
@ -61,160 +60,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 +183,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 +243,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 +264,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 +278,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 +299,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 +311,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 +320,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 +332,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,127 +346,109 @@ 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 (myFullscreenWrapper && aWrapper == nil)
{
// 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;
}
}
// Fade to black screen
[self doFadeOperation:FillScreen time:0.2f sync:true];
// 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];
// Fade to normal screen
[self doFadeOperation:CleanScreen time:0.5f sync:true];
// Release the saved window wrapper
[myFullscreenWrapper release], 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 (myFullscreenWrapper == nil && 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 (idx < sz) {
windows->erase(windows->begin() + idx);
}
// Fade to a black screen
[self doFadeOperation:FillScreen time:0.5f sync:true];
// Hide to the main menu bar
[NSMenu setMenuBarVisible:NO];
// Switch to the wished display mode
CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode);
// Open and center the window
[[aWrapper window] makeKeyAndOrderFront:nil];
[[aWrapper window] center];
// Fade to normal screen
[self doFadeOperation:CleanScreen time:0.2f sync:false];
// Save the fullscreen wrapper
myFullscreenWrapper = [aWrapper retain];
}
}
////////////////////////////////////////////////////////////
/// 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;
}
else
{
std::cerr << "Inconcistency error for arguments given to -[AppController setFullscreenWindow:mode:]" << std::endl;
}
return isUsing;
}
@ -517,11 +460,10 @@ static AppController *shared = nil;
/// 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 +481,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 +491,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 +510,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 +525,14 @@ static AppController *shared = nil;
}
}
////////////////////////////////////////////////////////////
/// Return the desktop video mode (made at the instance initialization)
////////////////////////////////////////////////////////////
- (const sf::VideoMode&)desktopMode
{
return myDesktopMode;
}
@end
template <typename T>
T *massert(T *ptr)
{
if (NULL == ptr) {
throw std::bad_alloc();
}
return ptr;
}

View file

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

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// 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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -1,73 +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 <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

View file

@ -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

View file

@ -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
////////////////////////////////////////////////////////////
@ -88,25 +91,23 @@ 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 :
////////////////////////////////////////////////////////////
@ -182,38 +183,19 @@ private :
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/// Event handling for every event type.
/// 'eventRef' is a NSEvent.
////////////////////////////////////////////////////////////
int HandleKeyDown(void *eventRef);
int HandleKeyUp(void *eventRef);
int HandleModifierKey(void *eventRef);
int HandleMouseDown(void *eventRef);
int HandleMouseUp(void *eventRef);
int HandleMouseMove(void *eventRef);
int HandleMouseWheel(void *eventRef);
////////////////////////////////////////////////////////////
/// Make some allocations and initializations
////////////////////////////////////////////////////////////
void Initialize(void);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
// An opaque structure that contains all obj-C objects
objc_members *members;
#ifdef __OBJC__
WindowWrapper *myWrapper;
#else
void *myWrapper;
#endif
bool useKeyRepeat;
bool mouseIn;
float wheelStatus;
bool fullscreen;
VideoMode fullscreenMode;
VideoMode desktopMode;
bool myUseKeyRepeat;
bool myMouseIn;
float myWheelStatus;
};
} // namespace priv

File diff suppressed because it is too large Load diff

View file

@ -61,15 +61,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);
}
}
}
}
@ -116,7 +125,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);

View file

@ -44,6 +44,16 @@ namespace
unsigned long EventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask |
EnterWindowMask | LeaveWindowMask;
////////////////////////////////////////////////////////////
/// 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);
}
}
@ -255,30 +265,53 @@ WindowImplX11::~WindowImplX11()
////////////////////////////////////////////////////////////
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(myDisplay, &Event, &WindowImplX11::CheckEvent, reinterpret_cast<XPointer>(myWindow)))
while (XCheckIfEvent(myDisplay, &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(myDisplay))
if (Event.xkey.keycode < 256)
{
XEvent NextEvent;
XPeekEvent(myDisplay, &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(myDisplay, Keys);
if (Keys[Event.xkey.keycode >> 3] & (1 << (Event.xkey.keycode % 8)))
{
if (!myKeyRepeat)
XNextEvent(myDisplay, &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);
}
}
}
@ -467,6 +500,9 @@ void WindowImplX11::SwitchToFullscreen(const VideoMode& Mode)
////////////////////////////////////////////////////////////
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(myDisplay, "WM_DELETE_WINDOW", false);
XSetWMProtocols(myDisplay, myWindow, &myAtomClose, 1);
@ -551,17 +587,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
////////////////////////////////////////////////////////////

View file

@ -155,18 +155,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
///
@ -188,16 +176,17 @@ private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
DisplayRef myDisplayRef; ///< Connection to the X server
::Window myWindow; ///< X11 structure defining our window
::Display* myDisplay; ///< Pointer to the display
int myScreen; ///< Screen identifier
bool myIsExternal; ///< Tell whether the window has been created externally or by SFML
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 ?
DisplayRef myDisplayRef; ///< Connection to the X server
::Window myWindow; ///< X11 structure defining our window
::Display* myDisplay; ///< Pointer to the display
int myScreen; ///< Screen identifier
bool myIsExternal; ///< Tell whether the window has been created externally or by SFML
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

View file

@ -32,11 +32,19 @@
#include <iostream>
////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////
namespace
{
const sf::Window* FullscreenWindow = NULL;
}
namespace sf
{
////////////////////////////////////////////////////////////
/// Default constructor
///
////////////////////////////////////////////////////////////
Window::Window() :
myWindow (NULL),
@ -97,11 +105,30 @@ Window::~Window()
////////////////////////////////////////////////////////////
void Window::Create(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, const ContextSettings& Settings)
{
// 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
@ -131,7 +158,7 @@ void Window::Create(VideoMode Mode, const std::string& Title, unsigned long Wind
void Window::Create(WindowHandle Handle, const ContextSettings& Settings)
{
// Recreate the window implementation
delete myWindow;
Close();
myWindow = priv::WindowImpl::New(Handle);
// Make sure another context is bound, so that:
@ -170,6 +197,10 @@ void Window::Close()
delete myWindow;
myWindow = NULL;
}
// Update the fullscreen window
if (this == FullscreenWindow)
FullscreenWindow = NULL;
}