Previously, we’ve seen how we can retrieve aspects of our window’s configuration by checking its window flags. However, we don’t need to continuously monitor our SDL_Window
to understand its state.
For most use cases, monitoring the event loop makes more sense. SDL dispatches a wide variety of events reporting actions performed on our window. In this lesson, we’ll explore this in a bit more detail.
SDL_WindowEvent
SDL_Event
objects that correspond to window events will have a type
of SDL_WINDOWEVENT
. If an SDL_Event
has the SDL_WINDOWEVENT
type, a more specific SDL_WindowEvent
is available within the window
variable:
// main.cpp
#include <SDL.h>
#include <iostream>
#include "Window.h"
void HandleWindowEvent(SDL_WindowEvent& E) {
std::cout << "Detected Window Event\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();
}
}
Detected Window Event
Detected Window Event
Detected Window Event
Window events are used to report a wide range of actions, covering events like the window being resized, moved, and minimized. The nature of the event is available within the event
variable of an SDL_WindowEvent
. This variable has a type of SDL_WindowEventID
, with possible values being listed in the official documentation.
We’ll cover many of these events and how to make use of them throughout the remainder of this chapter. In this example, we implement a basic reaction to just a few of them:
#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_MOVED) {
std::cout << "Window Moved\n";
} else if (E.event == SDL_WINDOWEVENT_ENTER) {
std::cout << "Cursor Entered the Window\n";
}
}
int main(int argc, char** argv) {/*...*/}
Cursor Entered the Window
Window Moved
Window Minimized
In this example, we’ll react to the user’s cursor entering and leaving our window. We’ll use the SDL_SetWindowTitle()
function to change the title based on these events:
#include <SDL.h>
#include <iostream>
void HandleWindowEvent(SDL_WindowEvent& E, SDL_Window* Window) {
if (E.event == SDL_WINDOWEVENT_ENTER) {
SDL_SetWindowTitle(Window, "Mouse Inside the Window");
} else if (E.event == SDL_WINDOWEVENT_LEAVE) {
SDL_SetWindowTitle(Window, "Mouse Outside the Window");
}
}
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, GameWindow.SDLWindow);
} else if (E.type == SDL_QUIT) {
SDL_Quit();
return 0;
}
}
GameWindow.Update();
GameWindow.Render();
}
}
In the previous example, our HandleWindowEvent()
logic requires a pointer to the SDL_Window
it needs to change the title of. We did this by passing it to the handler as a second argument, but it’s also possible to retrieve the SDL_Window
from the SDL_WindowEvent
.
Internally, SDL assigns a unique identifier to each window it creates, in the form of a simple integer. The ID of the window associated with the event is available on the windowID
member of the SDL_WindowEvent
:
#include <SDL.h>
#include <iostream>
#include "Window.h"
void HandleKeydownEvent(SDL_KeyboardEvent& E) {
if (E.keysym.sym == SDLK_SPACE) {
std::cout << "\nWindowID: " << E.windowID;
}
}
int main(int argc, char** argv) {/*...*/}
WindowID: 1
Above, we’re responding to an SDL_WindowEvent
, but this windowID
variable exists on every event type that relates to a specific window. This includes types like SDL_KeyboardEvent
, where the windowID
will be the window with input focus, and SDL_MouseMotionEvent
and SDL_MouseButtonEvent
, where the ID will be the window the mouse is hovering over.
SDL_GetWindowFromID()
By passing this window ID to SDL_GetWindowFromID()
, we get the corresponding SDL_Window
pointer:
SDL_Window* Win{SDL_GetWindowFromID(E.windowID)};
Below, we update our previous program to combine these techniques to position the SDL_Window
directly, rather than passing a reference to our Window
object to our event handler and using our Move()
method:
#include <SDL.h>
#include <iostream>
#include "Window.h"
void HandleKeydownEvent(SDL_KeyboardEvent& E) {
if (E.keysym.sym == SDLK_SPACE) {
SDL_SetWindowPosition(
SDL_GetWindowFromID(E.windowID),
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED);
}
}
int main(int argc, char** argv) {/*...*/}
The SDL_GetWindowFromID()
approach is unnecessary in this case - it’s easier to use the initial technique where we simply provided a reference to our GameWindow
to the event handler.
However, using SDL_GetWindowFromID()
becomes valuable in multi-window applications, where we need to know which specific window should respond to user input. We cover multi-window applications and window IDs in more detail later in this chapter.
SDL_GetWindowID()
We can perform this conversion in the opposite direction using SDL_GetWindowID()
. We pass it the SDL_Window
pointer, and it returns the window ID associated with that SDL_Window
:
#include <SDL.h>
#include <iostream>
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* Window = SDL_CreateWindow(
"Window ID Example",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800,
600,
SDL_WINDOW_SHOWN
);
int WindowID = SDL_GetWindowID(Window);
std::cout << "The ID of the created window is: "
<< WindowID << '\n';
SDL_DestroyWindow(Window);
SDL_Quit();
return 0;
}
The ID of the created window is: 1
One scenario where this might be useful is when we’re using SDL’s event system for custom events within our game. SDL provides the SDL_UserEvent
type for this purpose, and it includes a windowID
member which we can provide if needed:
Uint32 GAME_OVER{SDL_RegisterEvents(1)};
SDL_Event MyEvent{GAME_OVER};
MyEvent.user.windowID = SDL_GetWindowID(Window);
SDL_PushEvent(&MyEvent);
We can then retrieve the SDL_Window
associated with the event within its handlers:
void HandleGameOverEvent(SDL_UserEvent& E){
SDL_Window* Window{
SDL_GetWindowFromID(E.windowID)};
// ...
}
We covered user events in a dedicated lesson earlier in the course:
In this lesson, we explored more of SDL’s window management systems, focusing on window events and unique identifiers. Key takeaways:
SDL_WindowEvent
captures specific window-related actions like moving, resizing, or minimizing.SDL_GetWindowFromID()
to retrieve an SDL_Window*
from a window ID and SDL_GetWindowID()
to find the ID associated with an SDL_Window*
.Discover how to monitor and respond to window state changes in SDL applications
Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games