- Main Page
- Namespaces
- Classes
- Files

- File List

# GLKit.mm

    00001
    00002 //
    00003 // SFML - Simple and Fast Multimedia Library
    00004 // Copyright (C) 2007-2009 Lucas Soltic (ceylow@gmail.com) and Laurent Gomila (laurent.gom@gmail.com)
    00005 //
    00006 // This software is provided 'as-is', without any express or implied warranty.
    00007 // In no event will the authors be held liable for any damages arising from the use of this software.
    00008 //
    00009 // Permission is granted to anyone to use this software for any purpose,
    00010 // including commercial applications, and to alter it and redistribute it freely,
    00011 // subject to the following restrictions:
    00012 //
    00013 // 1. The origin of this software must not be misrepresented;
    00014 //    you must not claim that you wrote the original software.
    00015 //    If you use this software in a product, an acknowledgment
    00016 //    in the product documentation would be appreciated but is not required.
    00017 //
    00018 // 2. Altered source versions must be plainly marked as such,
    00019 //    and must not be misrepresented as being the original software.
    00020 //
    00021 // 3. This notice may not be removed or altered from any source distribution.
    00022 //
    00024
    00026 // Headers
    00028 #import <SFML/Window/Cocoa/GLKit.h>
    00029 #import <SFML/Window/Cocoa/AppController.h>
    00030 #import <SFML/Window/VideoMode.hpp>
    00031 #import <SFML/Window/WindowStyle.hpp>
    00032 #import <SFML/System/Sleep.hpp>
    00033 #import <OpenGL/gl.h>
    00034 #import <iostream>
    00035
    00036
    00040 @implementation GLContext
    00041
    00042 static GLContext *sharedCtx = nil;
    00043
    00047 + (id)sharedContext
    00048 {
    00049     if (sharedCtx == nil)
    00050     {
    00051         // Make a new context with the default parameters
    00052         sf::WindowSettings params(0, 0, 0);
    00053         sharedCtx = [[GLContext alloc] initWithAttributes:params sharedContext:nil];
    00054     }
    00055
    00056     return sharedCtx;
    00057 }
    00058
    00059 - (void)dealloc
    00060 {
    00061     [mySharedContext release];
    00062     [super dealloc];
    00063 }
    00064
    00069 - (id)initWithAttributes:(sf::WindowSettings&)attribs sharedContext:(GLContext *)context
    00070 {
    00071     // Note about antialiasing and other context attributes :
    00072     // OpenGL context sharing does not allow the shared contexts to use different attributes.
    00073     // The point is that the default shared global OpenGL context uses default parameters.
    00074     // That means that all the other context *should* use the same paramaters.
    00075     // Fortunately some values parameters for some parameters are compatible, but some are not
    00076     // among which : the antialising level.
    00077     //
    00078     // I've no way to fix this for now.
    00079
    00080     if (attribs.AntialiasingLevel)
    00081         std::cerr << "Warning: antialiasing settings are inhibited under Mac OS X for technical reasons" << std::endl;
    00082
    00083     NSOpenGLPixelFormat *myPixelFormat = nil;
    00084     unsigned idx = 0;
    00085
    00086     // Attributes list
    00087     NSOpenGLPixelFormatAttribute ctxtAttribs[15] = {(NSOpenGLPixelFormatAttribute) 0};
    00088
    00089     // Accelerated, double buffered
    00090     ctxtAttribs[idx++] = NSOpenGLPFAClosestPolicy;
    00091     ctxtAttribs[idx++] = NSOpenGLPFADoubleBuffer;
    00092     ctxtAttribs[idx++] = NSOpenGLPFAAccelerated;
    00093
    00094     // windowed context (even fullscreen mode uses a window)
    00095     ctxtAttribs[idx++] = NSOpenGLPFAWindow;
    00096
    00097     // Color size ; usually 32 bits per pixel
    00098     ctxtAttribs[idx++] = NSOpenGLPFAColorSize;
    00099     ctxtAttribs[idx++] = (NSOpenGLPixelFormatAttribute) sf::VideoMode::GetDesktopMode().BitsPerPixel;
    00100
    00101     // Z-buffer size
    00102     ctxtAttribs[idx++] = NSOpenGLPFADepthSize;
    00103     ctxtAttribs[idx++] = (NSOpenGLPixelFormatAttribute) attribs.DepthBits;
    00104
    00105     // Stencil bits (I don't really know what's that...)
    00106     ctxtAttribs[idx++] = NSOpenGLPFAStencilSize;
    00107     ctxtAttribs[idx++] = (NSOpenGLPixelFormatAttribute) attribs.StencilBits;
    00108
    00109     myPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:ctxtAttribs];
    00110
    00111     if (myPixelFormat) {
    00112         self = [super initWithFormat:myPixelFormat
    00113                                     shareContext:context];
    00114
    00115         mySharedContext = [context retain];
    00116
    00117         // Get the effective properties from our OpenGL context
    00118         GLint tmpDepthSize = 0, tmpStencilBits = 0, tmpAntialiasingLevel = 0;
    00119
    00120         if (self) {
    00121             [myPixelFormat getValues:&tmpDepthSize
    00122                     forAttribute:NSOpenGLPFADepthSize
    00123                 forVirtualScreen:[self currentVirtualScreen]];
    00124
    00125             [myPixelFormat getValues:&tmpStencilBits
    00126                     forAttribute:NSOpenGLPFAStencilSize
    00127                 forVirtualScreen:[self currentVirtualScreen]];
    00128
    00129             [myPixelFormat getValues:&tmpAntialiasingLevel
    00130                     forAttribute:NSOpenGLPFASamples
    00131                 forVirtualScreen:[self currentVirtualScreen]];
    00132         }
    00133
    00134
    00135         attribs.DepthBits = (unsigned) tmpDepthSize;
    00136         attribs.StencilBits = (unsigned) tmpStencilBits;
    00137         attribs.AntialiasingLevel = (unsigned) tmpAntialiasingLevel;
    00138
    00139         [myPixelFormat release];
    00140     }
    00141
    00142     return self;
    00143 }
    00144
    00145 @end
    00146
    00147
    00151 @implementation GLView
    00152
    00159 - (id)initWithFrame:(NSRect)frame
    00160                mode:(const sf::VideoMode&)mode
    00161            settings:(sf::WindowSettings&)settings
    00162            delegate:(sf::priv::WindowImplCocoa *)delegate
    00163 {
    00164     assert(delegate != NULL);
    00165
    00166     // make the view
    00167     self = [super initWithFrame:frame pixelFormat:nil];
    00168
    00169     if (self)
    00170     {
    00171         // enabled auto-resizing
    00172         [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
    00173
    00174         // make the OpenGL context
    00175         myGLContext = [[GLContext alloc] initWithAttributes:settings sharedContext:sharedCtx];
    00176
    00177         // We need to update the OpenGL view when it's resized
    00178         NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    00179         [nc addObserver:self
    00180                selector:@selector(viewFrameDidChange:)
    00181                    name:NSViewFrameDidChangeNotification
    00182                  object:self];
    00183
    00184         // Save the delegate
    00185         myDelegate = delegate;
    00186     }
    00187
    00188     return self;
    00189 }
    00190
    00191
    00195 - (void)dealloc
    00196 {
    00197     // Remove the observer and release the OpenGL context
    00198     [[NSNotificationCenter defaultCenter] removeObserver:self];
    00199     [myGLContext release];
    00200
    00201     [super dealloc];
    00202 }
    00203
    00204
    00208 - (void)finishInitialization
    00209 {
    00210     assert([self superview] != nil);
    00211     assert(myGLContext != nil);
    00212
    00213     // Attach the OpenGL context to our view
    00214     [self clearGLContext];
    00215     [self setOpenGLContext:myGLContext];
    00216     [myGLContext setView:self];
    00217
    00218     // Make our view the first responder
    00219     [[self window] makeFirstResponder:self];
    00220 }
    00221
    00222
    00226 - (void)enableVerticalSync:(bool)flag
    00227 {
    00228     GLint enable = (flag) ? 1 : 0;
    00229     [[self openGLContext] setValues:&enable forParameter:NSOpenGLCPSwapInterval];
    00230 }
    00231
    00232
    00236 - (void)setActive:(bool)flag
    00237 {
    00238     if (flag) {
    00239         if ([NSOpenGLContext currentContext] != [self openGLContext])
    00240             [[self openGLContext] makeCurrentContext];
    00241     } else {
    00242         if ([NSOpenGLContext currentContext] == [self openGLContext])
    00243             [NSOpenGLContext clearCurrentContext];
    00244     }
    00245 }
    00246
    00247
    00251 - (void)flushBuffer
    00252 {
    00253     [[self openGLContext] flushBuffer];
    00254 }
    00255
    00256
    00260 - (void)pushEvent:(sf::Event)sfEvent
    00261 {
    00262     assert(myDelegate != NULL);
    00263     myDelegate->HandleNotifiedEvent(sfEvent);
    00264 }
    00265
    00266
    00270 - (void)viewFrameDidChange:(NSNotification *)notification
    00271 {
    00272     [self update];
    00273
    00274     sf::Event ev;
    00275     ev.Type = sf::Event::Resized;
    00276     ev.Size.Width = (unsigned) [self frame].size.width;
    00277     ev.Size.Height = (unsigned) [self frame].size.height;
    00278
    00279     [self pushEvent:ev];
    00280 }
    00281
    00282
    00286 - (void)keyDown:(NSEvent *)theEvent
    00287 {
    00288     assert(myDelegate != NULL);
    00289
    00290     NSText *field = [[self window] fieldEditor:YES forObject:nil];
    00291     [field interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
    00292     [field setString:@""];
    00293
    00294     myDelegate->HandleKeyDown(theEvent);
    00295 }
    00296
    00297
    00301 - (void)keyUp:(NSEvent *)theEvent
    00302 {
    00303     assert(myDelegate != NULL);
    00304     myDelegate->HandleKeyUp(theEvent);
    00305 }
    00306
    00307
    00311 - (void)flagsChanged:(NSEvent *)theEvent
    00312 {
    00313     assert(myDelegate != NULL);
    00314     myDelegate->HandleModifierKey(theEvent);
    00315 }
    00316
    00317
    00321 - (void)scrollWheel:(NSEvent *)theEvent
    00322 {
    00323     assert(myDelegate != NULL);
    00324     myDelegate->HandleMouseWheel(theEvent);
    00325 }
    00326
    00327
    00331 - (void)mouseDown:(NSEvent *)theEvent
    00332 {
    00333     assert(myDelegate != NULL);
    00334     myDelegate->HandleMouseDown(theEvent);
    00335 }
    00336
    00337
    00341 - (void)rightMouseDown:(NSEvent *)theEvent
    00342 {
    00343     assert(myDelegate != NULL);
    00344     myDelegate->HandleMouseDown(theEvent);
    00345 }
    00346
    00347
    00351 - (void)mouseUp:(NSEvent *)theEvent
    00352 {
    00353     assert(myDelegate != NULL);
    00354     myDelegate->HandleMouseUp(theEvent);
    00355 }
    00356
    00357
    00361 - (void)rightMouseUp:(NSEvent *)theEvent
    00362 {
    00363     assert(myDelegate != NULL);
    00364     myDelegate->HandleMouseUp(theEvent);
    00365 }
    00366
    00367
    00371 - (void)mouseMoved:(NSEvent *)theEvent
    00372 {
    00373     assert(myDelegate != NULL);
    00374     myDelegate->HandleMouseMove(theEvent);
    00375 }
    00376
    00380 - (void)mouseDragged:(NSEvent *)theEvent
    00381 {
    00382     assert(myDelegate != NULL);
    00383     myDelegate->HandleMouseMove(theEvent);
    00384 }
    00385
    00389 - (void)rightMouseDragged:(NSEvent *)theEvent
    00390 {
    00391     assert(myDelegate != NULL);
    00392     myDelegate->HandleMouseMove(theEvent);
    00393 }
    00394
    00395
    00399 - (BOOL)acceptsFirstResponder
    00400 {
    00401     return YES;
    00402 }
    00403
    00404
    00408 - (BOOL)canBecomeKeyView
    00409 {
    00410     return YES;
    00411 }
    00412
    00413 @end
    00414
    00415
    00420 @implementation GLWindow
    00421
    00422 - (BOOL)canBecomeKeyWindow
    00423 {
    00424     return YES;
    00425 }
    00426
    00427 - (BOOL)canBecomeMainWindow
    00428 {
    00429     return YES;
    00430 }
    00431
    00432 @end
    00433
    00434
    00438 @implementation WindowWrapper
    00439
    00445 - (id)initWithSettings:(sf::WindowSettings&)params
    00446              videoMode:(sf::VideoMode&)mode
    00447                  style:(unsigned long)style
    00448                  title:(NSString *)title
    00449               delegate:(sf::priv::WindowImplCocoa *)delegate
    00450 {
    00451     return [self initWithWindow:nil
    00452                        settings:params
    00453                       videoMode:mode
    00454                           style:style
    00455                           title:title
    00456                        delegate:delegate];
    00457 }
    00458
    00459
    00466 - (id)initWithWindow:(NSWindow *)window
    00467             settings:(sf::WindowSettings&)params
    00468             delegate:(sf::priv::WindowImplCocoa *)delegate
    00469 {
    00470     sf::VideoMode mode([[myWindow contentView] frame].size.width, [[myWindow contentView] frame].size.height);
    00471     return [self initWithWindow:window
    00472                        settings:params
    00473                       videoMode:mode
    00474                           style:0
    00475                           title:nil
    00476                        delegate:delegate];
    00477 }
    00478
    00479
    00487 - (id)initWithWindow:(NSWindow *)window
    00488             settings:(sf::WindowSettings&)params
    00489            videoMode:(sf::VideoMode&)mode
    00490                style:(unsigned long)style
    00491                title:(NSString *)title
    00492             delegate:(sf::priv::WindowImplCocoa *)delegate
    00493 {
    00494     assert(delegate != NULL);
    00495
    00496     self = [super init];
    00497
    00498     if (self)
    00499     {
    00500         if (window) {
    00501             myWindow = (GLWindow *)[window retain];
    00502         } else {
    00503             assert(title != nil);
    00504
    00505             NSRect frame = NSMakeRect (0.0f, 0.0f, (float) mode.Width, (float) mode.Height);
    00506             unsigned int mask = 0;
    00507
    00508             if (style & sf::Style::Fullscreen) {
    00509                 myIsFullscreen = true;
    00510
    00511                 // Check display mode and put new values in 'mode' if needed
    00512                 boolean_t exact = true;
    00513
    00514                 CFDictionaryRef properties = CGDisplayBestModeForParameters(kCGDirectMainDisplay, mode.BitsPerPixel,
    00515                                                                             mode.Width, mode.Height, &exact);
    00516
    00517                 if (!properties) {
    00518                     std::cerr << "Unable to get a display mode with the given parameters" << std::endl;
    00519                     [self autorelease];
    00520                     return nil;
    00521                 }
    00522
    00523                 if (exact == false) {
    00524                     CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayWidth),
    00525                                      kCFNumberIntType, &mode.Width);
    00526
    00527                     CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayHeight),
    00528                                      kCFNumberIntType, &mode.Height);
    00529
    00530                     CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, kCGDisplayBitsPerPixel),
    00531                                      kCFNumberIntType, &mode.BitsPerPixel);
    00532
    00533                 }
    00534             }
    00535
    00536             // We grab options from WindowStyle and add them to our window mask
    00537             if (style & sf::Style::None || style & sf::Style::Fullscreen) {
    00538                 mask |= NSBorderlessWindowMask;
    00539
    00540
    00541
    00542             } else {
    00543                 if (style & sf::Style::Titlebar) {
    00544                     mask |= NSTitledWindowMask;
    00545                     mask |= NSMiniaturizableWindowMask;
    00546                 }
    00547
    00548                 if (style & sf::Style::Resize) {
    00549                     mask |= NSTitledWindowMask;
    00550                     mask |= NSMiniaturizableWindowMask;
    00551                     mask |= NSResizableWindowMask;
    00552                 }
    00553
    00554                 if (style & sf::Style::Close) {
    00555                     mask |= NSTitledWindowMask;
    00556                     mask |= NSClosableWindowMask;
    00557                     mask |= NSMiniaturizableWindowMask;
    00558                 }
    00559             }
    00560
    00561             // Now we make the window with the values we got
    00562             // Note: defer flag set to NO to be able to use OpenGL in our window
    00563             myWindow = [[GLWindow alloc] initWithContentRect:frame
    00564                                                    styleMask:mask
    00565                                                      backing:NSBackingStoreBuffered
    00566                                                        defer:NO];
    00567
    00568             if (myWindow) {
    00569                 // We set title and window position
    00570                 [myWindow setTitle:title];
    00571                 [myWindow center];
    00572             } else {
    00573                 std::cerr << "Unable to create the Cocoa window" << std::endl;
    00574                 [self autorelease];
    00575                 return nil;
    00576             }
    00577         }
    00578
    00579         // Make the OpenGL view
    00580         myView = [[GLView alloc] initWithFrame:[[myWindow contentView] frame]
    00581                                           mode:mode
    00582                                       settings:params
    00583                                       delegate:delegate];
    00584
    00585         if (myView) {
    00586             // Finish setting up the view and window
    00587             // Add the view to our window and tell it to the view
    00588             [[myWindow contentView] addSubview:myView];
    00589             [myView finishInitialization];
    00590
    00591             NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    00592
    00593             // We want to know when our window got the focus
    00594             [nc addObserver:self
    00595                    selector:@selector(windowDidBecomeMain:)
    00596                        name:NSWindowDidBecomeMainNotification
    00597                      object:myWindow];
    00598
    00599             // We want to know when our window lost the focus
    00600             [nc addObserver:self
    00601                    selector:@selector(windowDidResignMain:)
    00602                        name:NSWindowDidResignMainNotification
    00603                      object:myWindow];
    00604
    00605             // We want to know when the user closes the window
    00606             [nc addObserver:self
    00607                    selector:@selector(windowWillClose:)
    00608                        name:NSWindowWillCloseNotification
    00609                      object:myWindow];
    00610
    00611             // I want to re-center the window if it's a full screen one and moved by Spaces
    00612             [nc addObserver:self
    00613                    selector:@selector(windowDidMove:)
    00614                        name:NSWindowDidMoveNotification
    00615                      object:myWindow];
    00616
    00617             // Needed not to make application crash when releasing the window in our destructor
    00618             // (I prefer to take control of everything :P)
    00619             [myWindow setReleasedWhenClosed:NO];
    00620             [myWindow setAcceptsMouseMovedEvents:YES];
    00621
    00622         } else {
    00623             std::cerr << "Unable to create the OpenGL view" << std::endl;
    00624             [self autorelease];
    00625             return nil;
    00626         }
    00627
    00628         if (myIsFullscreen) {
    00629             myFullscreenMode = mode;
    00630
    00631             // Using this because full screen window was not always
    00632             // in front of the other application windows when unhiding app
    00633             [myWindow setLevel:NSFloatingWindowLevel];
    00634         }
    00635     }
    00636
    00637     return self;
    00638 }
    00639
    00640
    00644 - (void)dealloc
    00645 {
    00646
    00647     // Remove the notification observer
    00648     [[NSNotificationCenter defaultCenter] removeObserver:self];
    00649
    00650     // Close the window
    00651     [self show:false];
    00652
    00653     // Release the window and view
    00654     [myView release];
    00655     [myWindow release];
    00656
    00657     [super dealloc];
    00658 }
    00659
    00660
    00664 - (NSWindow *)window
    00665 {
    00666     return myWindow;
    00667 }
    00668
    00669
    00673 - (GLView *)glView
    00674 {
    00675     return myView;
    00676 }
    00677
    00678
    00682 - (void)setPosition:(NSPoint)pos
    00683 {
    00684     assert(myWindow != nil);
    00685
    00686     if (!myIsFullscreen) {
    00687         // Flip Y and set window position
    00688         pos.y = [[myWindow screen] frame].size.height - pos.y;
    00689         [myWindow setFrameTopLeftPoint:pos];
    00690     }
    00691 }
    00692
    00693
    00697 - (void)setSize:(NSSize)size
    00698 {
    00699     assert(myWindow != nil);
    00700
    00701     if (!myIsFullscreen) {
    00702         [myWindow setFrame:NSMakeRect([myWindow frame].origin.x,
    00703                                       [myWindow frame].origin.y,
    00704                                       size.width, size.height)
    00705                    display:YES];
    00706     }
    00707 }
    00708
    00709
    00713 - (NSPoint)mouseLocation
    00714 {
    00715     assert(myWindow != nil);
    00716
    00717     NSPoint relativeLocation = [myWindow convertScreenToBase:[NSEvent mouseLocation]];
    00718     relativeLocation.y = [[self glView] frame].size.height - relativeLocation.y;
    00719     return relativeLocation;
    00720 }
    00721
    00722
    00726 - (BOOL)mouseInside
    00727 {
    00728     assert(myWindow != nil);
    00729     assert(myView != nil);
    00730
    00731     BOOL flag = NO;
    00732
    00733     if ([myWindow isVisible]) {
    00734         NSPoint relativeToWindow = [myWindow mouseLocationOutsideOfEventStream];
    00735         NSPoint relativeToView = [myView convertPoint:relativeToWindow fromView:nil];
    00736
    00737         if (NSPointInRect (relativeToView, [myView bounds]))
    00738         {
    00739             flag = YES;
    00740         }
    00741     }
    00742
    00743     return flag;
    00744 }
    00745
    00746
    00750 - (void)show:(bool)flag
    00751 {
    00752     assert(myWindow != nil);
    00753
    00754     if (flag && ![myWindow isVisible]) {
    00755         // Wanna open the closed window
    00756
    00757         if (myIsFullscreen) {
    00758             [SharedAppController setFullscreenWindow:self mode:&myFullscreenMode];
    00759         } else {
    00760             // Show the window
    00761             [myWindow makeKeyAndOrderFront:nil];
    00762         }
    00763     } else if (!flag && [myWindow isVisible]) {
    00764         // Wanna close the opened window
    00765
    00766         if (myIsFullscreen) {
    00767             [SharedAppController setFullscreenWindow:nil mode:NULL];
    00768         } else {
    00769             // Close the window
    00770             [myWindow close];
    00771         }
    00772     }
    00773 }
    00774
    00775
    00779 - (void)enableVerticalSync:(bool)flag
    00780 {
    00781     assert(myView != nil);
    00782     [myView enableVerticalSync:flag];
    00783 }
    00784
    00785
    00789 - (void)setActive:(bool)flag
    00790 {
    00791     assert(myView != nil);
    00792     [myView setActive:flag];
    00793 }
    00794
    00795
    00799 - (void)flushBuffer
    00800 {
    00801     assert(myView != nil);
    00802     [myView flushBuffer];
    00803 }
    00804
    00805
    00809 - (void)windowDidBecomeMain:(NSNotification *)notification
    00810 {
    00811     sf::Event ev;
    00812     ev.Type = sf::Event::GainedFocus;
    00813
    00814     [myView pushEvent:ev];
    00815 }
    00816
    00817
    00821 - (void)windowDidResignMain:(NSNotification *)notification
    00822 {
    00823     sf::Event ev;
    00824     ev.Type = sf::Event::LostFocus;
    00825
    00826     [myView pushEvent:ev];
    00827 }
    00828
    00829
    00833 - (void)windowWillClose:(NSNotification *)notification
    00834 {
    00835     sf::Event ev;
    00836     ev.Type = sf::Event::Closed;
    00837
    00838     [myView pushEvent:ev];
    00839 }
    00840
    00841
    00845 - (void)windowDidMove:(NSNotification *)notification
    00846 {
    00847     NSWindow *sender = [notification object];
    00848
    00849     if (!([sender styleMask] & NSTitledWindowMask))
    00850         [sender center];
    00851 }
    00852
    00853 @end
    00854

:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::