@@ -177,8 +177,12 @@ static bool ImGui_ImplSdlGL3_Init(SDL_Window* window)
177177 // Create bgfx imgui objects
178178 GPImGui::Get ()->imguiInit ();
179179
180- // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
180+ // Setup back-end capabilities flags
181181 ImGuiIO& io = ImGui::GetIO ();
182+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
183+ io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
184+
185+ // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
182186 io.KeyMap [ImGuiKey_Tab] = SDL_SCANCODE_TAB ;
183187 io.KeyMap [ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT ;
184188 io.KeyMap [ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT ;
@@ -212,6 +216,7 @@ static bool ImGui_ImplSdlGL3_Init(SDL_Window* window)
212216 g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor (SDL_SYSTEM_CURSOR_SIZEWE );
213217 g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor (SDL_SYSTEM_CURSOR_SIZENESW );
214218 g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor (SDL_SYSTEM_CURSOR_SIZENWSE );
219+ g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor (SDL_SYSTEM_CURSOR_HAND );
215220
216221#ifdef _WIN32
217222 SDL_SysWMinfo wmInfo;
@@ -225,66 +230,94 @@ static bool ImGui_ImplSdlGL3_Init(SDL_Window* window)
225230 return true ;
226231}
227232
228- static void ImGui_ImplSdlGL3_NewFrame (SDL_Window* window )
233+ static void ImGui_ImplSDL2_UpdateMousePosAndButtons ( )
229234{
230235 ImGuiIO& io = ImGui::GetIO ();
231236
232- // Setup display size (every frame to accommodate for window resizing)
233- int w, h;
234- int display_w, display_h;
235- SDL_GetWindowSize (window, &w, &h);
236- SDL_GL_GetDrawableSize (window, &display_w, &display_h);
237- io.DisplaySize = ImVec2 ((float )w, (float )h);
238- io.DisplayFramebufferScale = ImVec2 (w > 0 ? ((float )display_w / w) : 0 , h > 0 ? ((float )display_h / h) : 0 );
239-
240- // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
241- /* static Uint64 frequency = SDL_GetPerformanceFrequency();
242- Uint64 current_time = SDL_GetPerformanceCounter();
243- io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);
244- g_Time = current_time;*/
237+ // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
238+ if (io.WantSetMousePos )
239+ SDL_WarpMouseInWindow (__window, (int )io.MousePos .x , (int )io.MousePos .y );
240+ else
241+ io.MousePos = ImVec2 (-FLT_MAX , -FLT_MAX );
245242
246- // Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler)
247243 int mx, my;
248244 Uint32 mouse_buttons = SDL_GetMouseState (&mx, &my);
249- io.MousePos = ImVec2 (-FLT_MAX , -FLT_MAX );
250245 io.MouseDown [0 ] = g_MousePressed[0 ] || (mouse_buttons & SDL_BUTTON (SDL_BUTTON_LEFT )) != 0 ; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
251246 io.MouseDown [1 ] = g_MousePressed[1 ] || (mouse_buttons & SDL_BUTTON (SDL_BUTTON_RIGHT )) != 0 ;
252247 io.MouseDown [2 ] = g_MousePressed[2 ] || (mouse_buttons & SDL_BUTTON (SDL_BUTTON_MIDDLE )) != 0 ;
253248 g_MousePressed[0 ] = g_MousePressed[1 ] = g_MousePressed[2 ] = false ;
254249
255- // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016)
256- #if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4)
257- if ((SDL_GetWindowFlags (window) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_MOUSE_CAPTURE )) != 0 )
250+ #if SDL_HAS_CAPTURE_MOUSE && !defined(__EMSCRIPTEN__)
251+ SDL_Window* focused_window = SDL_GetKeyboardFocus ();
252+ if (g_Window == focused_window)
253+ {
254+ // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
255+ // 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.
256+ int wx, wy;
257+ SDL_GetWindowPosition (focused_window, &wx, &wy);
258+ SDL_GetGlobalMouseState (&mx, &my);
259+ mx -= wx;
260+ my -= wy;
258261 io.MousePos = ImVec2 ((float )mx, (float )my);
259- bool any_mouse_button_down = false ;
260- for (int n = 0 ; n < IM_ARRAYSIZE (io.MouseDown ); n++)
261- any_mouse_button_down |= io.MouseDown [n];
262- if (any_mouse_button_down && (SDL_GetWindowFlags (window) & SDL_WINDOW_MOUSE_CAPTURE ) == 0 )
263- SDL_CaptureMouse (SDL_TRUE );
264- if (!any_mouse_button_down && (SDL_GetWindowFlags (window) & SDL_WINDOW_MOUSE_CAPTURE ) != 0 )
265- SDL_CaptureMouse (SDL_FALSE );
262+ }
263+
264+ // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
265+ // The function is only supported from SDL 2.0.4 (released Jan 2016)
266+ bool any_mouse_button_down = ImGui::IsAnyMouseDown ();
267+ SDL_CaptureMouse (any_mouse_button_down ? SDL_TRUE : SDL_FALSE );
266268#else
267- if (( SDL_GetWindowFlags (window ) & SDL_WINDOW_INPUT_FOCUS ) != 0 )
269+ if (SDL_GetWindowFlags (__window ) & SDL_WINDOW_INPUT_FOCUS )
268270 io.MousePos = ImVec2 ((float )mx, (float )my);
269271#endif
272+ }
273+
274+ static void ImGui_ImplSDL2_UpdateMouseCursor ()
275+ {
276+ ImGuiIO& io = ImGui::GetIO ();
277+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
278+ return ;
270279
271- // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor
272- ImGuiMouseCursor cursor = ImGui::GetMouseCursor ();
273- if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None)
280+ ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor ();
281+ if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
274282 {
275- SDL_ShowCursor (0 );
283+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
284+ SDL_ShowCursor (SDL_FALSE );
276285 }
277286 else
278287 {
279- SDL_SetCursor (g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
280- SDL_ShowCursor (1 );
288+ // Show OS mouse cursor
289+ SDL_SetCursor (g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
290+ SDL_ShowCursor (SDL_TRUE );
281291 }
292+ }
282293
283- // fix issue when debugging (mouse was still captured by sdl and we cannot use it in debugger)
284- SDL_CaptureMouse (SDL_FALSE );
294+ static void ImGui_ImplSdlGL3_NewFrame (SDL_Window* window)
295+ {
296+ ImGuiIO& io = ImGui::GetIO ();
297+ IM_ASSERT (io.Fonts ->IsBuilt ()); // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame()
298+
299+ // Setup display size (every frame to accommodate for window resizing)
300+ int w, h;
301+ int display_w, display_h;
302+ SDL_GetWindowSize (window, &w, &h);
303+ SDL_GL_GetDrawableSize (window, &display_w, &display_h);
304+ io.DisplaySize = ImVec2 ((float )w, (float )h);
305+ io.DisplayFramebufferScale = ImVec2 (w > 0 ? ((float )display_w / w) : 0 , h > 0 ? ((float )display_h / h) : 0 );
306+
307+ // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
308+ static Uint64 frequency = SDL_GetPerformanceFrequency ();
309+ Uint64 current_time = SDL_GetPerformanceCounter ();
310+ io.DeltaTime = g_Time > 0 ? (float )((double )(current_time - g_Time) / frequency) : (float )(1 .0f / 60 .0f );
311+ g_Time = current_time;
312+
313+ ImGui_ImplSDL2_UpdateMousePosAndButtons ();
314+ ImGui_ImplSDL2_UpdateMouseCursor ();
285315
286316 // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
287317 ImGui::NewFrame ();
318+
319+ // fix issue when debugging (mouse was still captured by sdl and we cannot use it in debugger)
320+ // SDL_CaptureMouse(SDL_FALSE);
288321}
289322
290323// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
0 commit comments