Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Drawing to the Screen

If you want to take over the entire screen for your drawing, you can do so from a Cocoa application. Entering full-screen drawing mode is a two-step process:

  1. Capture the desired screen (or screens) for drawing.

  2. Configure your drawing environment.

After capturing the screen, the way you configure your drawing environment depends on whether you are using Cocoa or OpenGL to draw. In OpenGL, you create an NSOpenGLContext object and invoke several of its methods to enter full-screen mode. In Cocoa, you have to create a window that fills the screen and configure that window.

In this section:

Capturing the Screen
Full-Screen Drawing in OpenGL
Full-Screen Drawing in Cocoa
Disabling Screen Updates


Capturing the Screen

Cocoa does not provide direct support for capturing and releasing screens. The NSScreen class provides read-only access to information about the available screens. To capture or manipulate a screen, you must use the functions found in Quartz Services.

To capture all of the available screens, you can simply call the CGCaptureAllDisplays function. To capture an individual display, you must get the ID of the desired display and call the CGDisplayCapture function to capture it. The following example shows how to use information provided by an NSScreen object to capture the main screen of a system.

- (BOOL) captureMainScreen
{
    // Get the ID of the main screen.
    NSScreen* mainScreen = [NSScreen mainScreen];
    NSDictionary* screenInfo = [mainScreen deviceDescription];
    NSNumber* screenID = [screenInfo objectForKey:@"NSScreenNumber"];
 
    // Capture the display.
    CGDisplayErr err = CGDisplayCapture([screenID longValue]);
    if (err != CGDisplayNoErr)
        return NO;
 
    return YES;
}

To release a display you previously captured, use the CGDisplayRelease function. If you captured all of the active displays, you can release them all by calling the CGReleaseAllDisplays function.

For more information about capturing and manipulating screens, see Quartz Display Services Reference.

Full-Screen Drawing in OpenGL

Applications that do full-screen drawing tend to be graphics intensive and thus use OpenGL to improve rendering speed. Creating a full-screen context using OpenGL is easy to do from Cocoa. After capturing the desired displays, create and configure an NSOpenGLContext object and then invoke its setFullScreen and makeCurrentContext methods. After invoking these methods, your application goes immediately to full-screen mode and you can start drawing content.

When requesting a full-screen context in OpenGL, the pixel format for your context should include the following attributes:

Listing 8-4 shows the basic steps for capturing all displays and setting up the OpenGL context for full-screen drawing. For information on how to create an NSOpenGLContext object, see “Creating an OpenGL Graphics Context.”

Listing 8-4  Creating an OpenGL full-screen context

NSOpenGLContext* CreateScreenContext()
{
    CGDisplayErr err;
 
    err = CGCaptureAllDisplays();
    if (err != CGDisplayNoErr)
        return nil;
 
    // Create the context object.
    NSOpenGLContext* glContext = CreateMyGLContext();
 
    // If the context is bad, release the displays.
    if (!glContext)
    {
        CGReleaseAllDisplays();
        return nil;
    }
 
    // Go to full screen mode.
    [glContext setFullScreen];
 
    // Make this context current so that it receives OpenGL calls.
    [glContext makeCurrentContext];
 
    return glContext;
}

Once you go into full-screen mode with your graphics context, your application has full control of the screen. To exit full-screen mode, invoke the clearDrawable method of your OpenGL context and call the CGReleaseAllDisplays function to release the screens back to the system.

For detailed sample code showing you how to enter full-screen mode using OpenGL and Cocoa, see the NSOpenGL Fullscreen sample in Sample Code > Graphics & Imaging > OpenGL.

Full-Screen Drawing in Cocoa

All Cocoa drawing occurs in a window, but for full screen drawing, the window you create is a little different. Instead of a bordered window with a title bar, you need to create a borderless window that spans the entire screen area.

Although you create a full-screen window using Cocoa classes, you still have to use Quartz Services to capture the display and configure the window properly. The capture process is described in “Capturing the Screen.” Once you capture the screen, the window server puts up a shield window that hides most other content. To make your full-screen window visible, you must adjust its level to sit above this shield. You can get the shield level using the CGShieldingWindowLevel function and pass the returned value to the setLevel: method of your window.

Listing 8-5 shows an action method defined in a subclass of NSDocument. The document object uses this method to capture the main display and create the window to fill that screen space. The window itself contains a single view (of type MyFullScreenView) for drawing content. (In your own code, you would replace this view with your own custom drawing view.) A reference to the window is stored in the myScreenWindow class instance variable, which is initialized to nil when the class is first instantiated.

Listing 8-5  Creating a Cocoa full-screen context

- (IBAction)goFullScreen:(id)sender
{
    // Get the screen information.
    NSScreen* mainScreen = [NSScreen mainScreen];
    NSDictionary* screenInfo = [mainScreen deviceDescription];
    NSNumber* screenID = [screenInfo objectForKey:@"NSScreenNumber"];
 
    // Capture the screen.
    CGDirectDisplayID displayID = (CGDirectDisplayID)[screenID longValue];
    CGDisplayErr err = CGDisplayCapture(displayID);
    if (err == CGDisplayNoErr)
    {
        // Create the full-screen window if it doesn’t already  exist.
        if (!myScreenWindow)
        {
            // Create the full-screen window.
            NSRect winRect = [mainScreen frame];
            myScreenWindow = [[NSWindow alloc] initWithContentRect:winRect
                    styleMask:NSBorderlessWindowMask
                    backing:NSBackingStoreBuffered
                    defer:NO
                    screen:[NSScreen mainScreen]];
 
            // Establish the window attributes.
            [myScreenWindow setReleasedWhenClosed:NO];
            [myScreenWindow setDisplaysWhenScreenProfileChanges:YES];
            [myScreenWindow setDelegate:self];
 
            // Create the custom view for the window.
            MyFullScreenView* theView = [[MyFullScreenView alloc]
                                             initWithFrame:winRect];
            [myScreenWindow setContentView:theView];
            [theView setNeedsDisplay:YES];
            [theView release];
        }
 
        // Make the screen window the current document window.
        // Be sure to retain the previous window if you want to  use it again.
        NSWindowController* winController = [[self windowControllers]
                                                 objectAtIndex:0];
        [winController setWindow:myScreenWindow];
 
        // The window has to be above the level of the shield window.
        int32_t     shieldLevel = CGShieldingWindowLevel();
        [myScreenWindow setLevel:shieldLevel];
 
        // Show the window.
        [myScreenWindow makeKeyAndOrderFront:self];
    }
}

To exit full screen mode using Cocoa, simply release the captured display, resize your window so that it does not occupy the entire screen, and set its level back to NSNormalWindowLevel. For more information about the shield window, see Quartz Display Services Reference.

Disabling Screen Updates

You can disable and reenable all screen flushes using the NSDisableScreenUpdates and NSEnableScreenUpdates functions. (In Mac OS X v10.4 and later, you can also use the disableScreenUpdatesUntilFlush method of NSWindow.) You can use this technique to synchronize flushes to both a parent and child window. As soon as you reenable screen updates, all windows are flushed simultaneously (or at least close to it).

To prevent the system from appearing frozen, the system may automatically reenable screen updates if your application leaves them disabled for a prolonged period of time. If you leave screen updates disabled for more than 1 second, the system automatically reenables them.



< Previous PageNext Page > Hide TOC


Last updated: 2007-10-31




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice