Nearly every window has a corresponding display window device in the Window Server. The window device holds the window’s drawn image, and has two attributes determined by the Window Server and five attributes that the window controls. The Window Server assigns the window device a unique identifier (within an application). This is the window number, and it’s returned by the windowNumber method. Each window also has a graphics state that most NSView objects share for drawing (views can create their own as well). The gState method returns its identifier. The five attributes under direct window control are:
Backing store type, described in “Setting How To Store the Window’s Image”
Window device creation, described in “Setting When the Window’s Image is Created”
One shot, described in “Setting Whether the Window’s Image Persists When Off-Screen”
Depth limit, described in “Setting the Depth Limit for the Window’s Image”
Dynamic depth limit, described in “Setting Whether the Depth Limit Changes to the Screen’s Capacity”
A window device’s backing store type determines how the window’s image is stored. It’s set when the window is initialized and can be one of three types.
A buffered window device renders all drawing into a display buffer and then flushes it to the screen. Always drawing to the buffer produces very smooth display, but can require significant amounts of memory. Buffered windows are best for displaying material that must be redrawn often, such as text. You must also use buffered windows if you want your windows to support transparency.
A retained window device also uses a buffer, but draws directly to the screen where possible and to the buffer for any portions that are obscured.
A nonretained window device has no buffer at all, and must redraw portions as they’re exposed. Further, this redrawing is suspended when the window’s display mechanism is preempted. For example, if the user drags a window across a nonretained window, the nonretained window is “erased” and isn’t redrawn until the user releases the mouse.
Both retained and nonretained windows are also subject to a flashing effect as individual drawing operations are performed, but their results do get to the screen more quickly than those of buffered windows.
You can change the backing store type between buffered and retained after initialization using the setBackingType: method.
The defer argument to the initializer specifies whether the window creates its window device immediately or only when it’s moved on screen. Deferring creation of the window device can offer some performance gain for windows that aren’t displayed immediately because it reduces the amount of work that needs to be performed up front. Deferring creation of the window device is particularly useful when creation of the window itself can’t be deferred or when an window is needed for purposes other than displaying content. Submenus with key equivalents, for example, must exist for the key equivalents to work, but may never actually be displayed.
Memory can also be saved by destroying the window device when the window is removed from the screen. The setOneShot: method controls this behavior. One-shot window devices exist only when their windows are onscreen.
Like the display hardware, a window device’s buffer has a depth, or a limit to the memory allotted each pixel. Buffered and retained windows start out with the same depth as the main display or 16 bits, whichever is deeper. These settings stay in effect unless changed using the setDepthLimit: method, which takes as an argument a window depth limit created using the NSBestDepth function.
Keeping a window’s depth at its richest preserves the displayed image, but may incur unnecessary memory overhead when the window buffer depth is deeper than the screen depth. You can use the setDynamicDepthLimit: method to tell a window to match the depth of the screen it’s on. When it’s moved to a new screen, a window with a dynamic depth limit adjusts its buffer to the new depth before redrawing. Making a window’s depth limit dynamic overrides the limit set using setDepthLimit:, and removing the dynamic limit reverts the window to the default limit.
Last updated: 2006-10-03