Window Events and Window IDs

Discover how to monitor and respond to window state changes in SDL applications
This lesson is part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, Unlimited Access
Abstract art representing computer programming
Ryan McCombe
Ryan McCombe
Updated

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

Example: Mouse Entering and Leaving Window

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();
  }
}

Window IDs

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:

Summary

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.
  • Window IDs uniquely identify SDL windows.
  • Use SDL_GetWindowFromID() to retrieve an SDL_Window* from a window ID and SDL_GetWindowID() to find the ID associated with an SDL_Window*.

Was this lesson useful?

Next Lesson

Managing Window Position

Learn how to control and monitor the position of SDL windows on screen
Abstract art representing computer programming
Ryan McCombe
Ryan McCombe
Updated
Lesson Contents

Window Events and Window IDs

Discover how to monitor and respond to window state changes in SDL applications

sdl2-promo.jpg
This lesson is part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, Unlimited Access
Window Management
  • 60.GPUs and Rasterization
  • 61.SDL Renderers
sdl2-promo.jpg
This lesson is part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 62 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Next Lesson

Managing Window Position

Learn how to control and monitor the position of SDL windows on screen
Abstract art representing computer programming
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved