This lesson explores the tools SDL2 offers for controlling window sizes and responding to changes. We’ll cover:
As we’ve seen, we can define the initial size when creating our window using the 4th and 5th arguments to SDL_CreateWindow()
:
SDL_CreateWindow(
"My Program", // Title
100, // Horizontal Position
200, // Vertical Position
600, // Width
300, // Height
0 // Configuration
);
In most desktop environments, users can resize windows by clicking and dragging their borders. We can allow our window to be resized by passing the SDL_WINDOW_RESIZABLE
window flag:
SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
);
We cover window flags in detail earlier in this chapter:
SDL_SetWindowResizable()
We can specify whether an existing window can be resized by players using the SDL_SetWindowResizable()
function. We pass the SDL_Window
pointer as the first argument. The second argument will be SDL_TRUE
if we want the window to be resizable, or SDL_FALSE
otherwise:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
// Not setting the resizable flag
0
)};
// Update the window to be resizable
SDL_SetWindowResizable(Window, SDL_TRUE);
// Disable resizing
SDL_SetWindowResizable(Window, SDL_FALSE);
If we need to check if an SDL_Window
is currently resizable by players, we can retrieve its window flags and use the &
operator to isolate the SDL_WINDOW_RESIZABLE
bit:
bool isResizable(SDL_Window* Window) {
Uint32 Flags{SDL_GetWindowFlags(Window)};
return Flags & SDL_WINDOW_RESIZABLE;
}
The window flags associated with a window are kept up to date as we use other functions, like SDL_SetWindowResizable()
, to update the configuration of our window:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
if (isResizable(Window)) {
std::cout << "Window is resizable\n";
}
SDL_SetWindowResizable(Window, SDL_FALSE);
if (!isResizable(Window)) {
std::cout << "Not any more!";
}
Window is resizable
Not any more!
If we want to let players resize our window, we will often want to set some constraints on how large or how small they can make it.
To set the minimum size, we use the SDL_SetWindowMinimumSize()
function, passing three arguments:
SDL_Window
we want to constrainSDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
SDL_SetWindowMinimumSize(Window, 200, 200);
We can retrieve the currently configured minimum size using SDL_GetWindowMinimumSize()
. We pass the SDL_Window
pointer and two integer pointers. The integers are updated with the current minimum width and height, respectively:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
SDL_SetWindowMinimumSize(Window, 200, 200);
int minW, minH;
SDL_GetWindowMinimumSize(Window, &minW, &minH);
std::cout << "Minimum Width: " << minW
<< "\nMinimum Height: " << minH;
Minimum Width: 200
Minimum Height: 200
Either of the integer pointers can be a nullptr
if we don’t care about the minimum size in that dimension:
int minW, minH;
// We only care about the minimum width
SDL_GetWindowMinimumSize(Window, &minW, nullptr);
// We only care about the minimum height
SDL_GetWindowMinimumSize(Window, nullptr, &minH);
For the maximum window size, we have the SDL_SetWindowMaximumSize()
and SDL_GetWindowMaximumSize()
functions. These work in the same way as their minimum-size counterparts:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
SDL_SetWindowMaximumSize(Window, 1200, 1200);
int maxW, maxH;
SDL_GetWindowMaximumSize(Window, &maxW, &maxH);
std::cout << "Maximum Width: " << maxW
<< "\nMaximum Height: " << maxH;
Maximum Width: 1200
Maximum Height: 1200
We can request the current window size at any time using the SDL_GetWindowSize()
function. We pass the window size and two pointers to integers. The integers will be updated with the width and height of the window respectively:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
int x, y;
SDL_GetWindowSize(Window, &x, &y);
std::cout << "Size: " << x << "x" << y;
Size: 600x300
If we only care about the size in a single dimension, we can pass a nullptr
as the other argument:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
int x;
SDL_GetWindowSize(Window, &x, nullptr);
std::cout << "Width: " << x;
int y;
SDL_GetWindowSize(Window, nullptr, &y);
std::cout << "\nHeight: " << x;
Width: 600
Height: 300
In addition to letting users resize our window, we can programmatically resize our window at any time. We do this using the SDL_SetWindowSize()
function, passing our SDL_Window
pointer, and two integers representing the desired width and height respectively:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
int x, y;
SDL_GetWindowSize(Window, &x, &y);
std::cout << "\nSize: " << x << "x" << y;
SDL_SetWindowSize(Window, 500, 700);
SDL_GetWindowSize(Window, &x, &y);
std::cout << "\nSize: " << x << "x" << y;
Size: 600x300
Size: 500x700
Desktop platforms typically support the idea of having a window maximized within a screen. Maximized windows are sized and positioned to fill almost the entire visible area of the screen, only leaving space for some platform-specific elements like the taskbar on Windows.
If our SDL_Window
is resizable, users will typically also be able to maximize by, for example, double-clicking the title bar in Windows or macOS:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
// If a window is resizable, it will also
// also be maximizable in supported platforms
SDL_WINDOW_RESIZABLE
)};
We can also create our window in the maximized state using the SDL_WINDOW_MAXIMIZED
flag. This does not require the window to be resizable but, in most circumstances, we’ll want a maximized window to also be resizable:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED
)};
SDL_MaximizeWindow()
We can maximize an existing window by passing its SDL_Window
pointer to SDL_MaximizeWindow()
:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
SDL_MaximizeWindow(Window);
SDL_RestoreWindow()
When a window is maximized, the platform remembers its previous position and size. We can restore a window to this state by passing its SDL_Window
pointer to SDL_RestoreWindow()
:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE
)};
SDL_MaximizeWindow(Window);
We can check if a window is currently maximized by retrieving its SDL_WindowFlags
and isolating the SDL_WINDOW_MAXIMIZED
bit:
SDL_Window* Window{SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED
)};
if (SDL_GetWindowFlags(Window) &
SDL_WINDOW_MAXIMIZED) {
std::cout << "Window is maximized";
}
Window is maximized
Maximizing a window typically means the window still leaves space for platform-specific UI elements that are typically always visible on screen, such as the taskbar on Windows, or the dock on macOS.
We can alternatively make a window full screen, where it will cover the entire visible area of the display. When our program is taking exclusive control of a monitor, there are some extra considerations we should be mindful of.
We cover full-screen windows and these considerations in a dedicated lesson in the next chapter.
When this happens, an SDL_WindowEvent
is created. As usual, we can detect window events within our event loop by checking if the type
of each SDL_Event
is SDL_WINDOWEVENT
.
If it is, the window
member of the SDL_Event
will contain an SDL_WindowEvent
, which we can further examine to determine what our reaction should be:
// main.cpp
#include <SDL.h>
#include "Window.h"
void HandleWindowEvent(SDL_WindowEvent& E) {
// Detected Window Event
}
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();
}
}
SDL_WINDOWEVENT_SIZE_CHANGED
When the SDL_WindowEvent
was created to report the size of our window changing, its event
member will be equal to SDL_WINDOWEVENT_SIZE_CHANGED
. The new horizontal and vertical dimensions of the window are available in the data1
and data2
variables respectively:
// main.cpp
#include <SDL.h>
#include <iostream>
#include "Window.h"
void HandleWindowEvent(SDL_WindowEvent& E) {
if (E.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
std::cout << "Window Resized to: "
<< E.data1 << "x" << E.data2 << '\n';
}
}
int main(int argc, char** argv) {/*...*/}
Window Size Changed to: 831x497
SDL_WINDOWEVENT_RESIZED
In the previous example, we tracked SDL_WINDOWEVENT_SIZE_CHANGED
events. These events are reported when the window size changes for any reason. This includes programmatic resizes using SDL_SetWindowSize()
, and resizing triggered by the platform itself.
When the resizing is triggered by the user, an additional SDL_WindowEvent
is generated, with its event
equal to SDL_WINDOWEVENT_RESIZED
. When we only need to react to user-triggered events, we can check explicitly for this event
rather than the more generic SDL_WINDOWEVENT_SIZE_CHANGED
:
// main.cpp
#include <SDL.h>
#include <iostream>
#include "Window.h"
void HandleWindowEvent(SDL_WindowEvent& E) {
if (E.event == SDL_WINDOWEVENT_RESIZED) {
std::cout << "Window Resized by Player to: "
<< E.data1 << "x" << E.data2 << '\n';
}
}
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
// This will create a
// SDL_WINDOWEVENT_SIZE_CHANGED event, but
// not a SDL_WINDOWEVENT_RESIZED event
SDL_SetWindowSize(
GameWindow.SDLWindow, 150, 150
);
SDL_Event E;
while (true) {/*...*/}
}
Window Resized by Player to: 1003x509
SDL_WINDOWEVENT_MAXIMIZED
and SDL_WINDOWEVENT_RESTORED
Window resize events will also be triggered if the act of maximizing or restoring a window causes the size to change. However, if we need to react to maximizing and restoring actions explicitly, additional events are also reported to help us achieve that.
The type
of these events will also be SDL_WINDOWEVENT
and, within the SDL_WindowEvent
, the event
field will be SDL_WINDOWEVENT_MAXIMIZED
or SDL_WINDOWEVENT_RESTORED
:
// main.cpp
#include <SDL.h>
#include <iostream>
#include "Window.h"
void HandleWindowEvent(SDL_WindowEvent& E) {
if (E.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
std::cout << "\nWindow Size Changed to: "
<< E.data1 << "x" << E.data2;
} else if (E.event == SDL_WINDOWEVENT_MAXIMIZED) {
std::cout << " (Maximized)";
} else if (E.event == SDL_WINDOWEVENT_RESTORED) {
std::cout << " (Restored)";
}
}
int main(int argc, char** argv) {/*...*/}
Window Size Changed to: 2560x1369 (Maximized)
Window Size Changed to: 600x300 (Restored)
This lesson explored the ways in which we manage our window sizes in SDL2 programs. Key takeaways include:
SDL_WINDOW_RESIZABLE
flag to create a resizable window, or to determine if an existing window is resizableSDL_SetWindowResizable()
function lets us configure whether an existing window is resizable.SDL_SetWindowMinimumSize()
and SDL_SetWindowMaximumSize()
to limit the extent to which a window is resizable.SDL_SetWindowSize()
SDL_GetWindowSize()
let’s us determine the current size of a windowSDL_MaximizeWindow()
and SDL_RestoreWindow()
SDL_WindowEvent
traffic.Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games