Skip to content

Window Guide

Aidan Cline edited this page Jan 8, 2023 · 5 revisions

This guide introduces the window related functions of GLFW.

Window objects

Creating a window with GLFWWindow.init also creates an underlying context, which is destroyed when the window is released or when GLFWSession.terminate() is called.

Window creation

A window and its OpenGL or OpenGL ES context are created with GLFWWindow.init. For example, this creates a 640 by 480 windowed mode window:

let window = try GLFWWindow(width: 640, height: 480, title: "My Title")

If window creation fails, a GLFWError will be thrown, so it is necessary to catch any errors.

Full screen windows

To create a full screen window, you need to specify which monitor the window should use. In most cases, the user's primary monitor is a good choice. For more information about retrieving monitors, see Retrieving monitors.

let window = try GLFWWindow(width: 640, height: 480, title: "My Title", monitor: .primary)

Full screen windows cover the entire display area of a monitor, have no border or decorations.

Windowed mode windows can be made full screen using the makeFullscreen() or makeFullscreen(monitor:) functions, and full screen ones can be made windowed with the exitFullscreen(withFrame:) function.

By default, the original video mode of the monitor will be restored and the window minimized if it loses input focus, to allow the user to switch back to the desktop. This behavior can be disabled with the autoMinimizeInFullscreen window hint, for example if you wish to simultaneously cover multiple monitors with full screen windows.

If a monitor is disconnected, all windows that are full screen on that monitor will be switched to windowed mode. See Monitor configuration changes for more information.

Window creation hints

There are a number of hints that can be set before the creation of a window and context. Some affect the window itself, others affect the framebuffer or context. These hints are set to their default values each time the library is initialized with GLFWSession.initialize(). To set one, use GLFWWindow.hints.<hint> = <newValue>. You can reset all at once to their defaults with GLFWWindow.hints.reset().

Note: Window hints need to be set before the creation of the window and context you wish to have the specified attributes. They function as additional arguments to GLFWWindow.init.

Window related hints

resizable specifies whether the windowed mode window will be resizable by the user. The window will still be resizable by changing the window's size member.

visible specifies whether the windowed mode window will be initially visible. This hint is ignored for full screen windows.

decorated specifies whether the windowed mode window will have window decorations such as a border, a close widget, etc. An undecorated window will not be resizable by the user but will still allow the user to generate close events on some platforms. This hint is ignored for full screen windows.

focused specifies whether the windowed mode window will be given input focus when created. This hint is ignored for full screen and initially hidden windows.

autoMinimizeInFullscreen specifies whether the full screen window will automatically minimize and restore the previous video mode on input focus loss. This hint is ignored for windowed mode windows.

floating specifies whether the windowed mode window will be floating above other regular windows, also called topmost or always-on-top. This is intended primarily for debugging purposes and cannot be used to implement proper full screen windows. This hint is ignored for full screen windows.

maximized specifies whether the windowed mode window will be maximized when created. This hint is ignored for full screen windows.

centerCursorOnShow specifies whether the cursor should be centered over newly created full screen windows. This hint is ignored for windowed mode windows.

transparentFramebuffer specifies whether the window framebuffer will be transparent. If enabled and supported by the system, the window framebuffer alpha channel will be used to combine the framebuffer with the background. This does not affect window decorations.

focusOnShow specifies whether the window will be given input focus when window.show() is called.

scaleToMonitor specifies whether the window content area should be resized based on the monitor content scale of any monitor it is placed on. This includes the initial placement when the window is created. This hint only has an effect on platforms where screen coordinates and pixels always map 1:1 such as Windows and X11. On platforms like macOS the resolution of the framebuffer is changed independently of the window size.

Framebuffer related hints

redBits, greenBits, blueBits, alphaBits, depthBits, and stencilBits specify the desired bit depths of the various components of the default framebuffer. A value of nil means the application has no preference.

stereoRendering specifies whether to use OpenGL stereoscopic rendering.

msaaSamples specifies the desired number of samples to use for multisampling. Zero disables multisampling. A value of nil means the application has no preference.

srgbCapable specifies whether the framebuffer should be sRGB capable. This is controlled by the GL_FRAMEBUFFER_SRGB enable in OpenGL if enabled.

doubleBuffer specifies whether the framebuffer should be double buffered. You nearly always want to use double buffering.

Monitor related hints

refreshRate specifies the desired refresh rate for full screen windows. A value of nil means the highest available refresh rate will be used. This hint is ignored for windowed mode windows.

Context related hints

clientAPI specifies which client API to create the context for. Possible values are openGL, openGLES and noAPI.

contextCreationAPI specifies which context creation API to use to create the context. Possible values are native, egl and osMesa. If no client API is requested, this hint is ignored.

contextVersion specifies the client API version that the created context must be compatible with, formatted as (major: Int, minor: Int). The exact behavior of this hint depends on the requested client API. While there is no way to ask the driver for a context of the highest supported version, GLFW will attempt to provide this when you ask for a version 1.0 context, which is the default for this hint.

OpenGL: This hint is not a hard constraint, but creation will fail if the OpenGL version of the created context is less than the one requested. It is therefore perfectly safe to use the default of version 1.0 for legacy code and you will still get backwards-compatible contexts of version 3.0 and above when available.

OpenGL ES: This hint is not a hard constraint, but creation will fail if the OpenGL ES version of the created context is less than the one requested. Additionally, OpenGL ES 1.x cannot be returned if 2.0 or later was requested, and vice versa. This is because OpenGL ES 3.x is backward compatible with 2.0, but OpenGL ES 2.0 is not backward compatible with 1.x.

macOS: The OS only supports forward-compatible core profile contexts for OpenGL versions 3.2 and later. Before creating an OpenGL context of version 3.2 or later you must set the openGLCompatibility hint and openGLProfile hints accordingly. OpenGL 3.0 and 3.1 contexts are not supported at all on macOS.

openGLDebugMode specifies whether the context should be created in debug mode, which may provide additional error and diagnostic reporting functionality.

openGLProfile specifies which OpenGL profile to create the context for. Possible values are one of core or compatibility, or any to not request a specific profile. If requesting an OpenGL version below 3.2, .any must be used. If OpenGL ES is requested, this hint is ignored.

robustness specifies the robustness strategy to be used by the context. This can be one of noResetNotification or loseContext, or any to not request a robustness strategy.

releaseBehavior specifies the release behavior to be used by the context. Possible values are one of any, flushPipeline or none. If the behavior is any, the default behavior of the context creation API will be used. If the behavior is flushPipeline, the pipeline will be flushed whenever the context is released from being the current one. If the behavior is none, the pipeline will not be flushed on release.

suppressErrors specifies whether errors should be generated by the context. If enabled, situations that would have generated errors instead cause undefined behavior.

macOS specific window hints

retinaFramebuffer specifies whether to use full resolution framebuffers on Retina displays.

frameName specifies the UTF-8 encoded name to use for autosaving the window frame, or if empty disables frame autosaving for the window.

autoGraphicsSwitching specifies whether to enable Automatic Graphics Switching, i.e. to allow the system to choose the integrated GPU for the OpenGL context and move it between GPUs if necessary or whether to force it to always run on the discrete GPU. This only affects systems with both integrated and discrete GPUs. Simpler programs and tools may want to enable this to save power, while games and other applications performing advanced rendering will want to leave it disabled.

X11 specific window hints

x11ClassName and x11InstanceName specify the desired ASCII encoded class and instance parts of the ICCCM WM_CLASS window property.

Window event processing

See Event processing.

Window properties and events

Window closing and close flag

When the user attempts to close the window, for example by clicking the close widget or using a key chord like Alt+F4, the close flag of the window is set. The window is however not actually destroyed and, unless you watch for this state change, nothing further happens.

The current state of the close flag is accessed or modified by the window.shouldClose member. A common pattern is to use the close flag as a main loop condition.

while !window.shouldClose {
    render(window)
    
    window.swapBuffers()
    GLFWSession.pollEvents()
}

If you wish to be notified when the user attempts to close a window, set a close callback.

window.shouldCloseHandler = { (window: GLFWWindow) -> Void in
    ...
}

The callback function is called directly after the close flag has been set. It can be used for example to filter close requests and clear the close flag again unless certain conditions are met.

window.shouldCloseHandler = { window in
    if !timeToClose {
        window.shouldClose = false
    }
}

Window size

The size of a window can be accessed or changed with window.size. For windowed mode windows, this sets the screen, in screen coordinates, of the content area of the window. The window system may impose limits on window size.

window.size.width = 640
window.size.height = 480

For full screen windows, the specified size becomes the new resolution of the window's desired video mode. The video mode most closely matching the new desired video mode is set immediately. The window is resized to fit the resolution of the set video mode.

If you wish to be notified when a window is resized, whether by the user, the system, or your own code, set a size callback.

window.sizeChangeHandler = { (window: GLFWWindow, width: Int, height: Int) -> Void in
    ...
}

Note:
Do not pass the window size to glViewport or other pixel-based OpenGL calls. The window size is in screen coordinates, not pixels. Use the framebuffer size, which is in pixels, for pixel-based calls.

The above functions work with the size of the content area, but decorated windows typically have title bars and window frames around this rectangle. You can retrieve the extents of these with window.margins.

The returned values are the distances, in screen coordinates, from the edges of the content area to the corresponding edges of the full window. As they are distances and not coordinates, they are always zero or positive.

Framebuffer size

While the size of a window is measured in screen coordinates, OpenGL works with pixels. The size you pass into glViewport, for example, should be in pixels. On some machines screen coordinates and pixels are the same, but on others they will not be. There is a second set of functions to retrieve the size, in pixels, of the framebuffer of a window.

If you wish to be notified when the framebuffer of a window is resized, whether by the user or the system, set a size callback.

window.framebufferSizeChangeHandler = { (window: GLFWWindow, width: Int, height: Int) -> Void in
    ...
}

The callback function receives the new size of the framebuffer when it is resized, which can for example be used to update the OpenGL viewport.

window.framebufferSizeChangeHandler = { (window, width, height) in
    glViewport(0, 0, width, height)
}

You can also get the framebuffer size directly from window.framebufferSize.

let size = window.framebufferSize
glViewport(0, 0, width, height)

The size of a framebuffer may change independently of the size of a window, for example if the window is dragged between a regular monitor and a high-DPI one.