Skip to content

Commit 1cdd110

Browse files
committed
Backends: SDL2: Mouse position is correctly reported when the host platform window is hovered but not focused. (#2445, #3751, #4377)
(requires SDL 2.0.5 because SDL_GetMouseFocus() is only usable with SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH).
1 parent c720075 commit 1cdd110

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

backends/imgui_impl_sdl.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// dear imgui: Platform Backend for SDL2
22
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
33
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
4-
// (Requires: SDL 2.0. Prefer SDL 2.0.4+ for full feature support.)
4+
// (Prefer SDL 2.0.5+ for full feature support.)
55

66
// Implemented features:
77
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
@@ -18,7 +18,8 @@
1818

1919
// CHANGELOG
2020
// (minor and older changes stripped away, please see git history for details)
21-
// 2021-06:29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
21+
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)
22+
// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
2223
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
2324
// 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950)
2425
// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
@@ -59,6 +60,7 @@
5960
#endif
6061

6162
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_VERSION_ATLEAST(2,0,4)
63+
#define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5)
6264
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
6365

6466
struct ImGui_ImplSDL2_Data
@@ -220,6 +222,15 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window)
220222
(void)window;
221223
#endif
222224

225+
// Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
226+
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
227+
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
228+
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
229+
// you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
230+
#if SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH
231+
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
232+
#endif
233+
223234
return true;
224235
}
225236

@@ -284,16 +295,22 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
284295
bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false;
285296

286297
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
287-
SDL_Window* focused_window = SDL_GetKeyboardFocus();
288-
if (bd->Window == focused_window)
298+
SDL_Window* focused_window = SDL_GetKeyboardFocus(); // Mouse position won't be reported unless window is focused.
299+
#if SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH
300+
SDL_Window* hovered_window = SDL_GetMouseFocus(); // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH enabled.
301+
SDL_Window* mouse_window = (bd->Window == focused_window || bd->Window == hovered_window) ? bd->Window : NULL;
302+
#else
303+
SDL_Window* mouse_window = (bd->Window == focused_window) ? bd->Window : NULL;
304+
#endif
305+
if (mouse_window != NULL)
289306
{
290307
if (bd->MouseCanUseGlobalState)
291308
{
292309
// SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
293310
// The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
294311
// Won't use this workaround on SDL backends that have no global mouse position, like Wayland or RPI
295312
int wx, wy;
296-
SDL_GetWindowPosition(focused_window, &wx, &wy);
313+
SDL_GetWindowPosition(mouse_window, &wx, &wy);
297314
SDL_GetGlobalMouseState(&mx, &my);
298315
mx -= wx;
299316
my -= wy;
@@ -306,6 +323,7 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
306323
bool any_mouse_button_down = ImGui::IsAnyMouseDown();
307324
SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
308325
#else
326+
// SDL 2.0.3 and non-windowed systems
309327
if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS)
310328
io.MousePos = ImVec2((float)mx, (float)my);
311329
#endif

docs/CHANGELOG.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ Breaking Changes:
3939

4040
- Backends: SDL2: removed unnecessary SDL_Window* parameter from ImGui_ImplSDL2_NewFrame(). (#3244) [@funchal]
4141
Kept inline redirection function (will obsolete).
42+
- Backends: SDL2: backend needs to set 'SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1")' in order to
43+
receive mouse clicks events on window focus, otherwise SDL doesn't emit the event. (#3751, #4377, #2445)
44+
This is unfortunately a global SDL setting, so enabling it _might_ have a side-effect on your application.
45+
It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
46+
you can ignore SDL_MOUSEBUTTONDOWN that events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED event).
4247
- Commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019):
4348
- ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList()
4449
- ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder
@@ -88,6 +93,8 @@ Other Changes:
8893
- ImGui_ImplWin32_EnableDpiAwareness() will call SetProcessDpiAwareness() fallback on Windows 8.1 without a manifest.
8994
- Backends: Win32: IME functions are disabled by default for non-Visual Studio compilers (MinGW etc.). Enable with
9095
'#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS' for those compilers. Undo change from 1.82. (#2590, #738, #4185, #4301)
96+
- Backends: SDL2: Mouse position is correctly reported when the host platform window is hovered but not focused.
97+
(requires SDL 2.0.5+ as SDL_GetMouseFocus() is only usable with SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH). (#3751, #4377, #2445)
9198
- Backends: DX9: Explicitly disable texture state stages after >= 1. (#4268) [@NZJenkins]
9299
- Backends: DX12: Fix texture casting crash on 32-bit systems (introduced on 2021/05/19 and v1.83) + added comments
93100
about building on 32-bit systems. (#4225) [@kingofthebongo2008]
@@ -163,7 +170,7 @@ Other Changes:
163170
- ImDrawList: Fixed PathArcTo() regression from 1.82 preventing use of counter-clockwise angles. (#4030, #3491) [@thedmd]
164171
- Demo: Improved popups demo and comments.
165172
- Metrics: Added "Fonts" section with same information as available in "Style Editor">"Fonts".
166-
- Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly,
173+
- Backends: SDL2: Rework global mouse pos availability check listing supported platforms explicitly,
167174
effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx]
168175
- Backends: Win32: Clearing keyboard down array when losing focus (WM_KILLFOCUS). (#2062, #3532, #3961)
169176
[@1025798851]

0 commit comments

Comments
 (0)