Managing Window Position
Learn how to control and monitor the position of SDL windows on screen
In this lesson, we'll explore SDL3's window positioning capabilities, from setting initial window locations to handling dynamic repositioning. We'll cover:
- How to set window positions explicitly using properties, or use special values that dynamically position our window based on the environment our program is run on.
- Retrieving the current location of our window.
- Moving windows programmatically, including how to shift a window based on its current position.
- Detecting when the user moves our window, so we can respond appropriately.
Starting Point
This lesson builds on our earlier work. To focus on window positioning, we will start with a minimal project containing a Window
class and a main
function with a basic application loop.
Files
Initial Window Position
In SDL3, the simplified SDL_CreateWindow()
function no longer accepts position arguments. To specify a window's initial position, we must use the more powerful SDL_CreateWindowWithProperties()
function. This approach uses SDL's properties system to configure the window.
First, we create a properties set with SDL_CreateProperties()
. Then, we set the desired x
and y
coordinates using SDL_SetNumberProperty()
with the appropriate property names: SDL_PROP_WINDOW_CREATE_X_NUMBER
and SDL_PROP_WINDOW_CREATE_Y_NUMBER
.
Below, we create a window 100 points from the left edge of the screen and 200 points from the top edge:
SDL_PropertiesID props{SDL_CreateProperties()};
SDL_SetStringProperty(props,
SDL_PROP_WINDOW_CREATE_TITLE_STRING, "Hello Window"
);
SDL_SetNumberProperty(props,
SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, 700
);
SDL_SetNumberProperty(props,
SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, 300
);
SDL_SetNumberProperty(props,
SDL_PROP_WINDOW_CREATE_X_NUMBER, 100
);
SDL_SetNumberProperty(props,
SDL_PROP_WINDOW_CREATE_Y_NUMBER, 200
);
SDL_Window* Window{
SDL_CreateWindowWithProperties(props)
};
SDL_DestroyProperties(props);
Using SDL_WINDOWPOS_UNDEFINED
In most cases, we don't need to be this specific. We can let the platform decide the best place to open the window by using the special value SDL_WINDOWPOS_UNDEFINED
.
This is a sensible default, as platforms often have smart placement strategies, like opening the window near the cursor or remembering its last position.
SDL_SetNumberProperty(props,
SDL_PROP_WINDOW_CREATE_X_NUMBER,
SDL_WINDOWPOS_UNDEFINED);
SDL_SetNumberProperty(props,
SDL_PROP_WINDOW_CREATE_Y_NUMBER,
SDL_WINDOWPOS_UNDEFINED);
Using SDL_WINDOWPOS_CENTERED
Alternatively, we can use SDL_WINDOWPOS_CENTERED
to have SDL automatically center the window on the primary display. SDL calculates the correct coordinates based on the monitor and window dimensions.
Below, we create a window that is centered both horizontally and vertically:
SDL_SetNumberProperty(props,
SDL_PROP_WINDOW_CREATE_X_NUMBER,
SDL_WINDOWPOS_CENTERED);
SDL_SetNumberProperty(props,
SDL_PROP_WINDOW_CREATE_Y_NUMBER,
SDL_WINDOWPOS_CENTERED);
Getting the Window Position
While we can specify an initial position, users can move the window by dragging its title bar. To get the current position of a window, we pass its SDL_Window
pointer to SDL_GetWindowPosition()
. We also provide pointers to two integers that SDL will update with the window's x
and y
coordinates:
int x, y;
SDL_GetWindowPosition(Window, &x, &y);
Here's a complete example:
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
int main(int, char**) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
int x, y;
SDL_GetWindowPosition(
GameWindow.GetRaw(), &x, &y
);
std::cout << "Position: "
<< x << ", " << y << '\n';
while (IsRunning) {/*...*/}
SDL_Quit();
return 0;
}
Position: 930, 570
If we only care about one dimension, we can pass a nullptr
for the other:
// We only care about horizontal position
int x;
SDL_GetWindowPosition(Window, &x, nullptr);
// We only care about vertical position
int y;
SDL_GetWindowPosition(Window, nullptr, &y);
Window Movement Events and SDL_EVENT_WINDOW_MOVED
While SDL_GetWindowPosition()
allows us to retrieve the position at any time, reacting to movement is often better handled through the event loop.
When a window is moved, SDL dispatches a top-level event with the type SDL_EVENT_WINDOW_MOVED
. We can detect this directly in our event loop:
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
void HandleWindowEvent(const SDL_WindowEvent& E) {
if (E.type == SDL_EVENT_WINDOW_MOVED) {
std::cout << "Window Moved\n";
}
}
int main(int, char**) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
SDL_Event E;
bool IsRunning = true;
while (IsRunning) {
while (SDL_PollEvent(&E)) {
if (E.type >= SDL_EVENT_WINDOW_FIRST &&
E.type <= SDL_EVENT_WINDOW_LAST
) {
HandleWindowEvent(E.window);
} else if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
GameWindow.Render();
GameWindow.Update();
}
SDL_Quit();
return 0;
}
Window Moved
The data1
and data2
members of the SDL_WindowEvent
struct (E.window
) contain the new horizontal and vertical positions of the window, respectively:
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
void HandleWindowEvent(const SDL_WindowEvent& E) {
if (E.type == SDL_EVENT_WINDOW_MOVED) {
std::cout << "Window Moved: "
<< E.data1 << ", " << E.data2 << '\n';
}
}
int main(int, char**) {/*...*/}
Window Moved: 506, 281
Programmatically Moving a Window
We can update the position of an SDL_Window
at any time using SDL_SetWindowPosition()
. This function takes the SDL_Window*
as its first argument, followed by the new x
and y
coordinates.
Let's add this capability to our custom Window
class by introducing a Move()
method:
src/Window.h
#pragma once
#include <SDL3/SDL.h>
class Window {
public:
//...
void Move(int x, int y) {
SDL_SetWindowPosition(SDLWindow, x, y);
}
//...
};
Just like when we create a window, we can use SDL_WINDOWPOS_UNDEFINED
to let the platform decide the best position, or SDL_WINDOWPOS_CENTERED
to center it. Below, we move the window to the center of the screen when the user presses the spacebar:
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
void HandleKeydownEvent(
const SDL_KeyboardEvent& E, Window& Window
) {
if (E.key == SDLK_SPACE) {
Window.Move(
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED
);
}
}
int main(int, char**) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
SDL_Event E;
bool IsRunning = true;
while (IsRunning) {
while (SDL_PollEvent(&E)) {
if (E.type == SDL_EVENT_KEY_DOWN) {
HandleKeydownEvent(E.key, GameWindow);
} else if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
GameWindow.Render();
GameWindow.Update();
}
SDL_Quit();
return 0;
}
Relative Moving
Often, we'll want to move a window relative to its current position rather than to an absolute screen coordinate. To do this, we can combine SDL_GetWindowPosition()
and SDL_SetWindowPosition()
.
Updating our Window
class to support relative moving might look something like this:
src/Window.h
#pragma once
#include <SDL3/SDL.h>
class Window {
public:
//...
void MoveRelative(int DeltaX, int DeltaY) {
int CurrentX, CurrentY;
SDL_GetWindowPosition(
SDLWindow, &CurrentX, &CurrentY
);
SDL_SetWindowPosition(
SDLWindow,
CurrentX + DeltaX,
CurrentY + DeltaY
);
}
//...
};
In the following example, we use this new method to let the user move the window with their arrow keys:
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
void HandleKeydownEvent(
const SDL_KeyboardEvent& E, Window& GameWindow
) {
if (E.key == SDLK_LEFT) {
GameWindow.MoveRelative(-10, 0);
} else if (E.key == SDLK_RIGHT) {
GameWindow.MoveRelative(10, 0);
} else if (E.key == SDLK_UP) {
GameWindow.MoveRelative(0, -10);
} else if (E.key == SDLK_DOWN) {
GameWindow.MoveRelative(0, 10);
}
}
int main(int, char**) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
SDL_Event E;
bool IsRunning = true;
while (IsRunning) {
while (SDL_PollEvent(&E)) {
if (E.type == SDL_EVENT_KEY_DOWN) {
HandleKeydownEvent(E.key, GameWindow);
} else if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
GameWindow.Render();
GameWindow.Update();
}
SDL_Quit();
return 0;
}
Summary
In this lesson, we've covered the fundamentals of window positioning. We've learned how to control window placement both at creation and during runtime, respond to window movement events, and implement relative movement. Key takeaways:
- Initial window position in SDL3 is set using
SDL_CreateWindowWithProperties()
. - Special values like
SDL_WINDOWPOS_UNDEFINED
andSDL_WINDOWPOS_CENTERED
provide automated placement options. SDL_GetWindowPosition()
lets us query a window's current location.SDL_SetWindowPosition()
allows for programmatic window movement.- Window movement events (
SDL_EVENT_WINDOW_MOVED
) help us track user-initiated window changes. - Relative movement can be implemented by combining position getting and setting.
Window Sizing
Learn how to resize, constrain, and manage SDL3 windows