In this lesson, we’ll continue exploring window management with SDL2, focusing on visibility. We’ll cover:
We can create a window that is initially hidden using the SDL_WINDOW_HIDDEN
window flag:
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_HIDDEN
);
It may be unclear why we would ever want to hide a window. This is indeed unusual when our program is only managing a single window, however, many programs will be managing multiple windows.
It is often the case that programs manage more windows than we might initially realize. For example, it’s common to design UI elements like tooltips and menus as distinct windows. These are sometimes referred to as utility windows:
Showing and hiding windows is primarily useful when we design our programs this way. We cover this technique in detail, and why we should use it, in the next lesson.
The SDL_WINDOW_HIDDEN
flag is kept up to date through the lifecycle of our window. As such, we can check if a window is currently hidden by using SDL_GetWindowFlags()
and using the &
operator to isolate the SDL_WINDOW_HIDDEN
bit:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_HIDDEN
)};
Uint32 Flags{SDL_GetWindowFlags(Window)};
if (Flags & SDL_WINDOW_HIDDEN) {
std::cout << "Window is hidden\n";
}
Window is hidden
SDL_HideWindow()
We can hide an existing window by passing its SDL_Window
pointer to the SDL_HideWindow()
function:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
0 // Not hidden initially
)};
// Hide the window later
SDL_HideWindow(Window);
The opposite of the SDL_WINDOW_HIDDEN
flag is SDL_WINDOW_SHOWN
. Windows are shown by default, but we can include this flag in the SDL_CreateWindow()
invocation if we want to be explicit:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_SHOWN
)};
As usual, we can check the SDL_WINDOW_SHOWN
flag to determine if a window is currently visible:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
0 // Not explicit, but window will be shown
)};
Uint32 Flags{SDL_GetWindowFlags(Window)};
if (Flags & SDL_WINDOW_SHOWN) {
std::cout << "Window is shown by default\n";
}
Window is shown by default
SDL_ShowWindow()
We can show a window that is currently hidden by passing its SDL_Window
pointer to SDL_ShowWindow()
:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_HIDDEN
)};
Uint32 Flags{SDL_GetWindowFlags(Window)};
if (Flags & SDL_WINDOW_HIDDEN) {
std::cout << "Window is hidden\n";
}
SDL_ShowWindow(Window);
Flags = SDL_GetWindowFlags(Window);
if (Flags & SDL_WINDOW_SHOWN) {
std::cout << "Not any more!\n";
}
Window is hidden
Not any more!
When we hide a window, our player has no realistic way to make that window visible again. It is hidden until we use SDL_ShowWindow()
to make it visible again.
Of course, we can call SDL_ShowWindow()
in response to some user input, thereby giving them that capability. However, desktop platforms typically offer the option to minimize a window rather than hide it entirely.
A minimized window remains visible on the user’s task bar (in Windows) or Dock (in MacOS). They can then use those platform-specific mechanisms to restore the window and continue to interact with it.
We can create a window that is initially minimized using the SDL_WINDOW_MINIMIZED
flag:
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_MINIMIZED
)
Unlike visibility, whether a window is minimized is something that can easily be controlled by our players. Platforms typically allow users to minimize a window by clicking on a button on the window’s title bar.
We can check if a window is currently minimized by using the &
operator on its window flags:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_MINIMIZED
)};
Uint32 Flags{SDL_GetWindowFlags(Window)};
if (Flags & SDL_WINDOW_MINIMIZED) {
std::cout << "Window is minimized\n";
}
Window is minimized
Whilst a minimized window typically occupies no space on the user’s screen, SDL will report the size it was prior to the window being minimized. This will also be the size of the window once the user restores it:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_MINIMIZED
)};
int x, y;
SDL_GetWindowSize(Window, &x, &y);
std::cout << "Window size: " << x << 'x' << y;
Window size: 600x300
In most scenarios where our logic depends on the window size, we’d also want to check that the window is minimized in addition to its size.
SDL_MinimizeWindow()
We can programmatically minimize an existing window by passing its SDL_Window
pointer to SDL_MinimizeWindow()
:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
0 // Not initially minimized
)};
SDL_MinimizeWindow(Window);
Uint32 Flags{SDL_GetWindowFlags(Window)};
if (Flags & SDL_WINDOW_MINIMIZED) {
std::cout << "Window is now minimized\n";
}
Window is now minimized
SDL_RestoreWindow()
We can restore a minimized window to its previous size by passing its SDL_Window
pointer to SDL_RestoreWindow()
:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_MINIMIZED
)};
SDL_RestoreWindow(Window);
Uint32 Flags{SDL_GetWindowFlags(Window)};
if (!(Flags & SDL_WINDOW_MINIMIZED)) {
std::cout << "Window is no longer minimized";
}
Window is no longer minimized
When a window is minimized or restored, an SDL_WindowEvent
is dispatched through the SDL’s event queue. If we need to react to these events, we can check through them through our event loop.
When a window is minimized or restored, the event
field of the SDL_WindowEvent
will contain either SDL_WINDOWEVENT_MINIMIZED
or SDL_WINDOWEVENT_RESTORED
:
#include <SDL.h>
#include <iostream>
#include "Window.h"
void HandleWindowEvent(SDL_WindowEvent& E) {
if (E.event == SDL_WINDOWEVENT_MINIMIZED) {
std::cout << "Window minimized\n";
} else if (E.event == SDL_WINDOWEVENT_RESTORED) {
std::cout << "Window restored\n";
}
}
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
SDL_Event E;
while (true) {
while (SDL_PollEvent(&E)) {
if (E.type == SDL_WINDOWEVENT) {
HandleWindowEvent(E.window);
} else if (E.type == SDL_QUIT) {
SDL_Quit();
return 0;
}
}
GameWindow.Update();
GameWindow.Render();
}
}
Window minimized
Window restored
Many platforms allow us to create windows that always visually appear to be on top of other windows, even if those other windows have input focus.
This can be useful for tools like task managers, music players, or notifications that need to remain accessible.
We can configure a window to be always on top using the SDL_WINDOW_ALWAYS_ON_TOP
flag:
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_ALWAYS_ON_TOP
)};
SDL_SetWindowAlwaysOnTop()
We can update an existing window’s always-on-top configuration using the SDL_SetWindowAlwaysOnTop()
function. We pass the SDL_Window
pointer as our first argument. The second argument will be SDL_TRUE
to enable always-on-top, and SDL_FALSE
to disable it:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300, 0
)};
// Enable always-on-top
SDL_SetWindowAlwaysOnTop(Window, SDL_TRUE);
// Disable always-on-top
SDL_SetWindowAlwaysOnTop(Window, SDL_FALSE);
We can check if a window is currently configured to be always-on-top by examining the SDL_WINDOW_ALWAYS_ON_TOP
flag:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_ALWAYS_ON_TOP
)};
Uint32 Flags{SDL_GetWindowFlags(Window)};
if (Flags & SDL_WINDOW_ALWAYS_ON_TOP) {
std::cout << "Window is always on top\n";
}
SDL_SetWindowAlwaysOnTop(Window, SDL_FALSE);
Flags = SDL_GetWindowFlags(Window);
if (!(Flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
std::cout << "Not any more!\n";
}
Window is always on top
Not any more!
We’ve now seen two ways to draw the user’s attention to a window. We can raise the window and cause it to grab input focus using SDL_RaiseWindow()
, or set a window to be always on top.
However, these techniques should be used sparingly, as they can be disruptive when the user is trying to work with other programs.
Most platforms provide a friendlier mechanism for windows to request the user’s attention. This is called "flashing" the window, but the specific visual effect of "flashing" varies from platform to platform.
On Windows, for example, flashing a window means it will be highlighted in the user’s taskbar:
The SDL_FlashWindow()
function lets us access these attention-grabbing mechanisms:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300, 0
)};
SDL_FlashWindow(Window, SDL_FLASH_BRIEFLY);
Our first argument is the SDL_Window*
we want to attract attention, and the second argument is one of three possible values:
SDL_FLASH_BRIEFLY
- Briefly flash the window to attract attentionSDL_FLASH_UNTIL_FOCUSED
- Attract attention continuously until the user moves input focus to our window, or until we cancel the flashingSDL_FLASH_CANCEL
- Stop flashingThe SDL_FlashWindow()
function includes error reporting. If the invocation was successful, the function will return 0
, or a negative error code otherwise.
We can check this return value to check if the window flashing failed, and use SDL_GetError()
to understand why:
SDL_Window* Window{
SDL_CreateWindow(
"My Program",
100, 200, 600, 300, 0
)};
if (SDL_FlashWindow(
Window, SDL_FLASH_BRIEFLY) < 0) {
std::cout << "Error flashing window: "
<< SDL_GetError();
}
In this lesson, we explored how to manage the visibility and state of SDL2 windows. We learned how to hide, show, minimize, and restore windows, as well as how to check their current state using window flags.
Additionally, we covered techniques for making windows always stay on top and attracting user attention through flashing. Key takeaways:
SDL_WINDOW_HIDDEN
to create hidden windows and SDL_HideWindow()
to hide an existing window.SDL_ShowWindow()
.SDL_WINDOW_MINIMIZED
, SDL_MinimizeWindow()
, and SDL_RestoreWindow()
.SDL_WINDOW_ALWAYS_ON_TOP
and SDL_SetWindowAlwaysOnTop()
.SDL_FlashWindow()
.Learn how to control the visibility of SDL2 windows, including showing, hiding, minimizing, and more
Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games