Managing Mouse Focus
Learn how to track and respond to mouse focus events in SDL3, including handling multiple windows and customizing focus-related click behavior.
In desktop environments, users can have multiple windows open at once. On most platforms, only a single window can have input focus at a time, which is typically gained by the user clicking on the window:

This is referred to as input focus, and we covered it in more detail in our earlier lesson on keyboard input: .
In this lesson, we'll introduce the related concept of mouse focus. A window has mouse focus if the user's pointer is currently hovering over it. The window with mouse focus is not necessarily the same as the window with input focus.
Starting Point
This lesson builds upon our previous work. To keep the focus on mouse focus, the starting point below uses a minimal main.cpp and Window.h. We've removed the scroll-specific event handling from the previous lesson.
Files
Tracking Mouse Focus Using the Event Loop
Let's begin with a basic application loop. When a window gains or loses mouse focus, SDL dispatches top-level events that we can detect in our event loop.
We can check if an event is related to a window gaining or losing focus by comparing the type of the SDL_Event to SDL_EVENT_WINDOW_MOUSE_ENTER or SDL_EVENT_WINDOW_MOUSE_LEAVE respectively:
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;
SDL_Event E;
bool IsRunning = true;
while (IsRunning) {
while (SDL_PollEvent(&E)) {
if (E.type == SDL_EVENT_WINDOW_MOUSE_ENTER) {
std::cout << "Mouse Entered Window\n";
} else if (E.type == SDL_EVENT_WINDOW_MOUSE_LEAVE) {
std::cout << "Mouse Left Window\n";
} else if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
GameWindow.Render();
GameWindow.Update();
}
SDL_Quit();
return 0;
}Mouse Entered Window
Mouse Left WindowUsing SDL_GetWindowFlags()
As with most things in SDL, we don't need to monitor events to retrieve the state of its internally-managed objects, like an SDL_Window. Instead, we can directly query the state of those objects at any time.
SDL_Window objects keep track of whether or not they have focus within their window flags. As we covered in the previous chapter, we can access those flags by passing the SDL_Window pointer to SDL_GetWindowFlags():
SDL_Window* Window{SDL_CreateWindow(
"Some Window",
700, 300, 0
)};
SDL_WindowFlags Flags{
SDL_GetWindowFlags(Window)
};The SDL_WindowFlags type is a bit mask. We can examine the state of any flag using the & operator. SDL provides the SDL_WINDOW_MOUSE_FOCUS helper to give us easy access to the flag that tracks whether the window has mouse focus:
bool hasFocus{
(SDL_GetWindowFlags(Window) &
SDL_WINDOW_MOUSE_FOCUS) != 0
};In practice, this state-checking approach is appropriate when we need to check if the window has focus as part of our reaction to some other event.
The following example checks if our window has mouse focus when the user presses a keyboard button:
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
void LogFocus(SDL_Window* Window) {
std::cout << "\nMouse focus: ";
if (SDL_GetWindowFlags(Window) &
SDL_WINDOW_MOUSE_FOCUS) {
std::cout << "yes";
} else {
std::cout << "no";
}
}
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) {
LogFocus(GameWindow.GetRaw());
} else if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
GameWindow.Render();
GameWindow.Update();
}
SDL_Quit();
return 0;
}Mouse focus: no
Mouse focus: no
Mouse focus: yesIn the following example, we create a timer that checks every second (1,000 milliseconds) if our window has mouse focus:
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
Uint32 MonitorWindow(
void* Win, SDL_TimerID timerID, Uint32 interval
) {
auto* Window{static_cast<SDL_Window*>(Win)};
if ((SDL_GetWindowFlags(Window) &
SDL_WINDOW_MOUSE_FOCUS) != 0) {
std::cout << "Focus\n";
} else {
std::cout << "No Focus\n";
}
return interval;
}
int main(int, char**) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
SDL_AddTimer(1000, MonitorWindow,
GameWindow.GetRaw());
SDL_Event E;
bool IsRunning = true;
while (IsRunning) {
while (SDL_PollEvent(&E)) {
if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
GameWindow.Render();
GameWindow.Update();
}
SDL_Quit();
return 0;
}No Focus
Focus
FocusUsing SDL_GetMouseFocus()
SDL also provides the SDL_GetMouseFocus() function, which returns the SDL_Window* with mouse focus, or a nullptr if no window has focus.
This example is very similar to the previous one, except we've updated our implementation to use SDL_GetMouseFocus() instead of SDL_GetWindowFlags().
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
Uint32 MonitorWindow(
void* Win, SDL_TimerID timerID, Uint32 interval
) {
auto* Window{static_cast<SDL_Window*>(Win)};
if (Window == SDL_GetMouseFocus()) {
std::cout << "Focus\n";
} else {
std::cout << "No Focus\n";
}
return interval;
}
int main(int, char**) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
SDL_AddTimer(1000, MonitorWindow,
GameWindow.GetRaw());
SDL_Event E;
bool IsRunning = true;
while (IsRunning) {
while (SDL_PollEvent(&E)) {
if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
GameWindow.Render();
GameWindow.Update();
}
SDL_Quit();
return 0;
}No Focus
Focus
FocusWhilst the SDL_GetWindowFlags() example lets us determine if a specific window has focus, SDL_GetMouseFocus() is primarily useful when we want to know which window has focus. This is typically used in applications where we manage multiple windows, including utility windows.
The following program creates two windows and, on every iteration of our application loop, reports which one of them has mouse focus:
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 Window1;
Window Window2;
SDL_Event E;
bool IsRunning = true;
while (IsRunning) {
while (SDL_PollEvent(&E)) {
if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
SDL_Window* Focused{SDL_GetMouseFocus()};
if (Focused == Window1.GetRaw()) {
std::cout << "Window 1 has focus\n";
} else if (Focused == Window2.GetRaw()) {
std::cout << "Window 2 has focus\n";
} else {
std::cout << "Neither has focus\n";
}
Window1.Render();
Window2.Render();
Window1.Update();
Window2.Update();
}
SDL_Quit();
return 0;
}Window 1 has focus
Window 1 has focus
Neither has focus
Window 2 has focusClick Events when Switching Input Focus
The most common way a user will switch their input focus is by left-clicking on the window with their mouse. By default, SDL does not report these clicks - you won't get a mouse click event when the user clicks to set input focus to your window.
This is typically a sensible default for games. For example, if we're working on a first-person shooter, we want players to be able to switch focus to our window by clicking on it, and we won't want that click to also fire their weapon.
However, we can change this behavior by setting the SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH hint to "1":
src/main.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <iostream>
#include "Window.h"
int main(int, char**) {
SDL_SetHint(
SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,
"1"
);
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_FOCUS_GAINED) {
std::cout << "Got an Input Focus Event\n";
} else if (E.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (E.button.button == SDL_BUTTON_LEFT) {
std::cout << "Also got a Click Event\n";
}
} else if (E.type == SDL_EVENT_QUIT) {
IsRunning = false;
}
}
GameWindow.Render();
GameWindow.Update();
}
SDL_Quit();
return 0;
}Got an Input Focus Event
Also got a Click EventWe can set it to "0" to restore the default behavior:
SDL_SetHint(
SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,
"0"
);Summary
Mouse focus management is important for handling mouse interaction, particularly multi-window applications. Here are the key topics covered:
- Use
SDL_EVENT_WINDOW_MOUSE_ENTERandSDL_EVENT_WINDOW_MOUSE_LEAVEto detect when the mouse enters or leaves a window. - Check window focus state using
SDL_GetWindowFlags()and theSDL_WINDOW_MOUSE_FOCUSflag. - Use
SDL_GetMouseFocus()to determine which window currently has mouse focus. - Customize click-through behavior during focus changes with
SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH.
Mouse Input Constraints
Implement mouse constraints in SDL3 to control cursor movement using window grabs and rectangular bounds