Glusoft

Display and Manage Multiple Windows with SDL3

display multiple windows with SDL3

Initialiations

Number of windows

#define WINDOW_COUNT 3

The windows and renderers arrays

SDL_Init(SDL_INIT_VIDEO);

SDL_Window* windows[WINDOW_COUNT];
SDL_Renderer* renderers[WINDOW_COUNT];
const char* titles[WINDOW_COUNT] = {"First Window", "Second Window", "Third Window"};

We can fill the arrays with a loop, we can the same functions as before.

// Create multiple windows and their renderers
for (int i = 0; i < WINDOW_COUNT; i++) {
    windows[i] = SDL_CreateWindow(titles[i], 320, 240, SDL_WINDOW_RESIZABLE);
    if (!windows[i]) {
        SDL_Log("Failed to create window %d: %s", i, SDL_GetError());
        return 1;
    }

    renderers[i] = SDL_CreateRenderer(windows[i], NULL);
    if (!renderers[i]) {
        SDL_Log("Failed to create renderer %d: %s", i, SDL_GetError());
        return 1;
    }
}

The main loop

Here are all the code for the main loop.

The event loop

The event loop is common for the three windows we will see next how to have separate event loops.

To catch the event for the other windows we use the event type SDL_EVENT_WINDOW_CLOSE_REQUESTED.

while (SDL_PollEvent(&e)) {
    if (e.type == SDL_EVENT_QUIT) {
        running = false;
    }
    if (e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
        running = false;
    }
}

The rendering

We draw a rectangle in each window to have something.

// Render each window with different color
for (int i = 0; i < WINDOW_COUNT; i++) {
    SDL_SetRenderDrawColor(renderers[i], 100 * i, 100, 255 - 100 * i, 255);
    SDL_RenderClear(renderers[i]);

    // Draw something simple
    SDL_SetRenderDrawColor(renderers[i], 255, 255, 255, 255);
    SDL_FRect rect = {60, 50, 200, 100};
    SDL_RenderFillRect(renderers[i], &rect);

    SDL_RenderPresent(renderers[i]);
}

The cleanup

Don't forget to destroy the windows after exiting the main loop

for (int i = 0; i < WINDOW_COUNT; i++) {
    SDL_DestroyRenderer(renderers[i]);
    SDL_DestroyWindow(windows[i]);
}

Multiple Events loops

AppWindow struct

We will use the windows id to identify each windows, to stores them we will use a struct:

typedef struct {
    SDL_Window* window;
    SDL_Renderer* renderer;
    Uint32 windowID;
    SDL_Color bgColor;
} AppWindow;

Initialize each window

Same thing we create a window and a renderer, we also get the id with SDL_GetWindowID.

AppWindow windows[WINDOW_COUNT];

// Initialize each window
for (int i = 0; i < WINDOW_COUNT; i++) {
    char title[32];
    snprintf(title, sizeof(title), "Window %d", i + 1);

    windows[i].window = SDL_CreateWindow(title, 320, 240, SDL_WINDOW_RESIZABLE);
    if (!windows[i].window) {
        SDL_Log("Failed to create window: %s", SDL_GetError());
        return 1;
    }

    windows[i].renderer = SDL_CreateRenderer(windows[i].window, NULL);
    if (!windows[i].renderer) {
        SDL_Log("Failed to create renderer: %s", SDL_GetError());
        return 1;
    }

    windows[i].windowID = SDL_GetWindowID(windows[i].window);
    windows[i].bgColor = (SDL_Color){(Uint8)(100 * i), 100, (Uint8)(255 - 100 * i), 255};
}

The multiple events loop

In reality we are polling the event only one time, but we use the window id to differentiate the events.

To test everything is working well, we display a message when the mouse is moving.

while (SDL_PollEvent(&e)) {
    if (e.type == SDL_EVENT_QUIT) {
        running = false;
    }

    // Per-window event handling
    if (e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
        for (int i = 0; i < WINDOW_COUNT; i++) {
            if (e.window.windowID == windows[i].windowID) {
                SDL_Log("Close requested for window %d", i + 1);
                running = false;
            }
        }
    }

    if (e.type == SDL_EVENT_MOUSE_MOTION) {
        for (int i = 0; i < WINDOW_COUNT; i++) {
            if (e.motion.windowID == windows[i].windowID) {
                SDL_Log("Mouse moved in window %d: x=%d y=%d", i + 1, e.motion.x, e.motion.y);
            }
        }
    }
}

The rendering

Don't forget to render everything like before.

for (int i = 0; i < WINDOW_COUNT; i++) {
    SDL_SetRenderDrawColor(windows[i].renderer,
                            windows[i].bgColor.r,
                            windows[i].bgColor.g,
                            windows[i].bgColor.b,
                            255);
    SDL_RenderClear(windows[i].renderer);

    SDL_SetRenderDrawColor(windows[i].renderer, 255, 255, 255, 255);
    SDL_FRect rect = {60, 50, 200, 100};
    SDL_RenderFillRect(windows[i].renderer, &rect);

    SDL_RenderPresent(windows[i].renderer);
}

Download the full project : Display and Manage Multiple Windows with SDL3

Need another OS ? => Windows, Mac, Linux