|
@@ -18,6 +18,7 @@
|
|
|
|
|
|
// CHANGELOG
|
|
|
// (minor and older changes stripped away, please see git history for details)
|
|
|
+// 2022-01-12: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API.
|
|
|
// 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted.
|
|
|
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
|
|
// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.
|
|
@@ -233,6 +234,11 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
|
|
|
|
|
switch (event->type)
|
|
|
{
|
|
|
+ case SDL_MOUSEMOTION:
|
|
|
+ {
|
|
|
+ io.MousePos = ImVec2((float)event->motion.x, (float)event->motion.y);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
case SDL_MOUSEWHEEL:
|
|
|
{
|
|
|
if (event->wheel.x > 0) io.MouseWheelH += 1;
|
|
@@ -270,6 +276,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
|
|
}
|
|
|
case SDL_WINDOWEVENT:
|
|
|
{
|
|
|
+ if (event->window.event == SDL_WINDOWEVENT_LEAVE)
|
|
|
+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
|
|
if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
|
|
|
io.AddFocusEvent(true);
|
|
|
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
|
|
@@ -391,61 +399,42 @@ void ImGui_ImplSDL2_Shutdown()
|
|
|
IM_DELETE(bd);
|
|
|
}
|
|
|
|
|
|
-static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
|
|
|
+static void ImGui_ImplSDL2_UpdateMouseData()
|
|
|
{
|
|
|
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
|
|
- ImVec2 mouse_pos_prev = io.MousePos;
|
|
|
- io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
|
|
-
|
|
|
- // Update mouse buttons
|
|
|
- int mouse_x_local, mouse_y_local;
|
|
|
- Uint32 mouse_buttons = SDL_GetMouseState(&mouse_x_local, &mouse_y_local);
|
|
|
- io.MouseDown[0] = bd->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.
|
|
|
- io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
|
|
- io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
|
|
- bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false;
|
|
|
-
|
|
|
- // Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing)
|
|
|
+ // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below)
|
|
|
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
|
|
- SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
|
|
- SDL_Window* hovered_window = SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH ? SDL_GetMouseFocus() : NULL; // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH.
|
|
|
- SDL_Window* mouse_window = NULL;
|
|
|
- if (hovered_window && bd->Window == hovered_window)
|
|
|
- mouse_window = hovered_window;
|
|
|
- else if (focused_window && bd->Window == focused_window)
|
|
|
- mouse_window = focused_window;
|
|
|
-
|
|
|
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
|
|
|
SDL_CaptureMouse(bd->MouseButtonsDown != 0 ? SDL_TRUE : SDL_FALSE);
|
|
|
+ SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
|
|
+ const bool is_app_focused = (bd->Window == focused_window);
|
|
|
#else
|
|
|
- // SDL 2.0.3 and non-windowed systems: single-viewport only
|
|
|
- SDL_Window* mouse_window = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) ? bd->Window : NULL;
|
|
|
+ const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
|
|
|
#endif
|
|
|
-
|
|
|
- if (mouse_window == NULL)
|
|
|
- return;
|
|
|
-
|
|
|
- // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
|
|
- if (io.WantSetMousePos)
|
|
|
- SDL_WarpMouseInWindow(bd->Window, (int)mouse_pos_prev.x, (int)mouse_pos_prev.y);
|
|
|
-
|
|
|
- // Set Dear ImGui mouse position from OS position + get buttons. (this is the common behavior)
|
|
|
- if (bd->MouseCanUseGlobalState)
|
|
|
- {
|
|
|
- // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
|
|
|
- // Unlike local position obtained earlier this will be valid when straying out of bounds.
|
|
|
- int mouse_x_global, mouse_y_global;
|
|
|
- SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
|
|
|
- int window_x, window_y;
|
|
|
- SDL_GetWindowPosition(mouse_window, &window_x, &window_y);
|
|
|
- io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
|
|
|
- }
|
|
|
- else
|
|
|
+ if (is_app_focused)
|
|
|
{
|
|
|
- io.MousePos = ImVec2((float)mouse_x_local, (float)mouse_y_local);
|
|
|
+ // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
|
|
+ if (io.WantSetMousePos)
|
|
|
+ SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);
|
|
|
+
|
|
|
+ // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured)
|
|
|
+ if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0)
|
|
|
+ {
|
|
|
+ int window_x, window_y, mouse_x_global, mouse_y_global;
|
|
|
+ SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
|
|
|
+ SDL_GetWindowPosition(focused_window, &window_x, &window_y);
|
|
|
+ io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ // Update buttons
|
|
|
+ Uint32 mouse_buttons = SDL_GetMouseState(NULL, NULL);
|
|
|
+ io.MouseDown[0] = bd->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.
|
|
|
+ io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
|
|
+ io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
|
|
+ bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false;
|
|
|
}
|
|
|
|
|
|
static void ImGui_ImplSDL2_UpdateMouseCursor()
|
|
@@ -545,10 +534,8 @@ void ImGui_ImplSDL2_NewFrame()
|
|
|
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
|
|
|
bd->Time = current_time;
|
|
|
|
|
|
- // Update key modifiers
|
|
|
ImGui_ImplSDL2_UpdateKeyModifiers();
|
|
|
-
|
|
|
- ImGui_ImplSDL2_UpdateMousePosAndButtons();
|
|
|
+ ImGui_ImplSDL2_UpdateMouseData();
|
|
|
ImGui_ImplSDL2_UpdateMouseCursor();
|
|
|
|
|
|
// Update game controllers (if enabled and available)
|