In this lesson, we'll explore SDL's window management features, learning how to implement both desktop and exclusive fullscreen modes. We’ll cover:
SDL_WINDOW_FULLSCREEN_DESKTOP
SDL_WINDOW_FULLSCREEN
SDL_SetWindowFullscreen()
lets you change modes at runtimeThe easiest way of creating a fullscreen experience is to simply render our game in a borderless window that has the same position and dimensions as the monitor’s display bounds.
SDL provides us with a quick way to set this up, which we’ll cover later in this lesson. However, we could achieve something similar by passing the display index to SDL_GetDisplayBounds()
, and then creating a borderless window with the same position and size:
// Get size and position of display with index 0
SDL_Rect Bounds;
SDL_GetDisplayBounds(0, &Bounds);
SDL_Window* Window{SDL_CreateWindow(
"Window",
Bounds.x, Bounds.y, // Position
Bounds.w, Bounds.h, // Size
SDL_WINDOW_BORDERLESS
)};
This technique is sometimes referred to as windowed fullscreen, desktop fullscreen, or borderless fullscreen. With this technique, our game is just another window, which makes multi-tasking easier. It provides a solid user experience when the player is switching between our game and other windows.
However, there are two problems:
SDL automatically handles both of these problems by rescaling each frame to match the display resolution and reformatting it to match the monitor's color requirements.
However, this additional rescaling and reformatting step means each frame takes slightly longer to complete. So, whilst windows fullscreen provides a smooth experience when multitasking, we pay for it by our game possibly running slightly slower.
Instead of having our frames rescaled and reformatted to meet the monitor’s requirements, we could instead update the monitor’s settings to match what our game is outputting.
This allows each frame to be displayed directly on the display. This technique is often called exclusive fullscreen or simply fullscreen, and it eliminates the performance overhead of windowed fullscreen.
However, changing the display mode of a typical monitor takes a few seconds, during which time the monitor is typically unusable. This makes switching to other windows more frustrating for users, as it takes a few seconds to update their display settings. We cover these display modes in detail in the next lesson.
Most games allow players to configure whether they’d prefer the game run in a window, windowed fullscreen or exclusive fullscreen:
When we know which mode they want to use, we can create or update our window to use that preference.
We can create an exclusive or fullscreen window by passing the appropriate flag to the SDL_CreateWindow()
function.
SDL_WINDOW_FULLSCREEN_DESKTOP
SDL uses the SDL_WINDOW_FULLSCREEN_DESKTOP
flag to configure desktop fullscreen windows:
SDL_Window* Window{SDL_CreateWindow(
"Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
1920, 1080,
SDL_WINDOW_FULLSCREEN_DESKTOP
)};
int x, y;
SDL_GetWindowSize(Window, &x, &y);
std::cout << "Size: " << x << 'x' << y;
Size: 2560x1440
The window size we specify for a fullscreen desktop window can still be relevant. For example, if we update our window to no longer be fullscreen, it will adopt the size we specified - 1920x1080 in this example. We cover how to change the fullscreen status of a window later in this lesson.
SDL_WINDOW_FULLSCREEN
Exclusive fullscreen windows are configured using the SDL_WINDOW_FULLSCREEN
flag:
SDL_Window* Window{SDL_CreateWindow(
"Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
1920, 1080,
SDL_WINDOW_FULLSCREEN
)};
int x, y;
SDL_GetWindowSize(Window, &x, &y);
std::cout << "Size: " << x << 'x' << y;
Size: 1920x1080
With an exclusive fullscreen window, the display the window is created on will be updated to adopt the resolution that matches our window size - 1920x1080 in this example.
If we disable fullscreen mode for this window, our display will revert to its original mode, and we will have a regular 1920x1080 window on that display. We cover display modes in detail in the next lesson.
We can update the fullscreen mode of an existing window using the SDL_SetWindowFullscreen()
function. We pass the SDL_Window
pointer as the first argument, and the desired window flag as the second argument. Our options are:
SDL_WINDOW_FULLSCREEN_DESKTOP
: Set the window to be desktop fullscreenSDL_WINDOW_FULLSCREEN
: Set the window to be exclusive fullscreen0
: Disable fullscreen mode for this windowHere’s an example:
SDL_Window* Window{SDL_CreateWindow(
"Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
1920, 1080,
0 // Not fullscreen
)};
// Set window to be desktop fullscreen
SDL_SetWindowFullscreen(Window,
SDL_WINDOW_FULLSCREEN_DESKTOP);
// Set window to be exclusive fullscreen
SDL_SetWindowFullscreen(Window,
SDL_WINDOW_FULLSCREEN);
// Disable fullscreen
SDL_SetWindowFullscreen(Window, 0);
The SDL_SetWindowFullscreen()
function returns 0
if it was successful, or a negative error code otherwise. We can call SDL_GetError()
to retrieve the error message:
if (SDL_SetWindowFullscreen(nullptr, 0) < 0) {
std::cout << "Error changing fullscreen "
"mode: " << SDL_GetError();
}
Error changing fullscreen mode: Invalid window
We can check a window's current fullscreen state using SDL_GetWindowFlags()
. This function returns a bit field containing all the window's current flags. To check for fullscreen modes, we examine specific bits using bitwise operations. The bitwise AND operator (&
) lets us check if specific flags are set:
SDL_Window* Window{SDL_CreateWindow(
"Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
1920, 1080,
SDL_WINDOW_FULLSCREEN_DESKTOP
)};
Uint32 Flags{SDL_GetWindowFlags(Window)};
if (Flags & SDL_WINDOW_FULLSCREEN_DESKTOP) {
std::cout << "Desktop fullscreen";
} else if (Flags & SDL_WINDOW_FULLSCREEN) {
std::cout << "Exclusive fullscreen";
} else {
std::cout << "Not fullscreen";
}
Desktop fullscreen
Note that the SDL_WINDOW_FULLSCREEN
is set if our window is running in either exclusive or desktop fullscreen. As such, the order of our if
statements in the previous example is important - specifically the decision to check SDL_WINDOW_FULLSCREEN_DESKTOP
before SDL_WINDOW_FULLSCREEN
. In other words:
SDL_WINDOW_FULLSCREEN
and SDL_WINDOW_FULLSCREEN_DESKTOP
are set.SDL_WINDOW_FULLSCREEN
is set but SDL_WINDOW_FULLSCREEN_DESKTOP
is not set.In this lesson, we've learned how to implement fullscreen functionality using SDL. We covered both desktop and exclusive fullscreen modes, understanding their benefits and tradeoffs. Key takeaways:
SDL_GetDisplayBounds()
to match monitor dimensionsSDL_WINDOW_FULLSCREEN_DESKTOP
- for easier multitaskingSDL_WINDOW_FULLSCREEN
- may provide better performanceSDL_SetWindowFullscreen()
enables runtime mode changesLearn how to create and manage fullscreen windows in SDL, including desktop and exclusive fullscreen modes.
Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games