1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-11-12 02:00:58 +01:00

Backends: Win32/SDL2/SDL3/GLFW: Added support for io.AddMouseSourceEvent(). (#2334, #2702)

SDL doesn't distinguish Pen yet, but we don't need it as much as TouchScreen which will alter trickling.
This commit is contained in:
ocornut 2023-04-04 19:43:51 +02:00
parent a16f99c6a2
commit f070497cbd
9 changed files with 91 additions and 3 deletions

View File

@ -5,6 +5,7 @@
// Implemented features: // Implemented features:
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
@ -16,6 +17,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen on Windows ONLY, using a custom WndProc hook. (#2702)
// 2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034) // 2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034)
// 2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240) // 2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240)
// 2023-02-03: Emscripten: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096) // 2023-02-03: Emscripten: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096)
@ -127,6 +129,9 @@ struct ImGui_ImplGlfw_Data
GLFWkeyfun PrevUserCallbackKey; GLFWkeyfun PrevUserCallbackKey;
GLFWcharfun PrevUserCallbackChar; GLFWcharfun PrevUserCallbackChar;
GLFWmonitorfun PrevUserCallbackMonitor; GLFWmonitorfun PrevUserCallbackMonitor;
#ifdef _WIN32
WNDPROC GlfwWndProc;
#endif
ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); } ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); }
}; };
@ -444,6 +449,35 @@ static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEven
} }
#endif #endif
#ifdef _WIN32
// GLFW doesn't allow to distinguish Mouse vs TouchScreen vs Pen.
// Add support for Win32 (based on imgui_impl_win32), because we rely on _TouchScreen info to trickle inputs differently.
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
{
LPARAM extra_info = ::GetMessageExtraInfo();
if ((extra_info & 0xFFFFFF80) == 0xFF515700)
return ImGuiMouseSource_Pen;
if ((extra_info & 0xFFFFFF80) == 0xFF515780)
return ImGuiMouseSource_TouchScreen;
return ImGuiMouseSource_Mouse;
}
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
switch (msg)
{
case WM_MOUSEMOVE: case WM_NCMOUSEMOVE:
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_LBUTTONUP:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP:
ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
break;
}
return ::CallWindowProc(bd->GlfwWndProc, hWnd, msg, wParam, lParam);
}
#endif
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window) void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
{ {
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
@ -562,6 +596,13 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
IM_UNUSED(main_viewport); IM_UNUSED(main_viewport);
#endif #endif
// Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32
bd->GlfwWndProc = (WNDPROC)::GetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC);
IM_ASSERT(bd->GlfwWndProc != NULL);
::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif
bd->ClientApi = client_api; bd->ClientApi = client_api;
return true; return true;
} }
@ -593,6 +634,13 @@ void ImGui_ImplGlfw_Shutdown()
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
glfwDestroyCursor(bd->MouseCursors[cursor_n]); glfwDestroyCursor(bd->MouseCursors[cursor_n]);
// Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->GlfwWndProc);
bd->GlfwWndProc = NULL;
#endif
io.BackendPlatformName = nullptr; io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr; io.BackendPlatformUserData = nullptr;
IM_DELETE(bd); IM_DELETE(bd);

View File

@ -4,6 +4,7 @@
// Implemented features: // Implemented features:
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).

View File

@ -5,6 +5,7 @@
// Implemented features: // Implemented features:
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
@ -17,6 +18,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702)
// 2023-02-23: Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. (#6189, #6114, #3644) // 2023-02-23: Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. (#6189, #6114, #3644)
// 2023-02-07: Implement IME handler (io.SetPlatformImeDataFn will call SDL_SetTextInputRect()/SDL_StartTextInput()). // 2023-02-07: Implement IME handler (io.SetPlatformImeDataFn will call SDL_SetTextInputRect()/SDL_StartTextInput()).
// 2023-02-07: *BREAKING CHANGE* Renamed this backend file from imgui_impl_sdl.cpp/.h to imgui_impl_sdl2.cpp/.h in prevision for the future release of SDL3. // 2023-02-07: *BREAKING CHANGE* Renamed this backend file from imgui_impl_sdl.cpp/.h to imgui_impl_sdl2.cpp/.h in prevision for the future release of SDL3.
@ -289,6 +291,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
{ {
ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y);
io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); io.AddMousePosEvent(mouse_pos.x, mouse_pos.y);
return true; return true;
} }
@ -305,6 +308,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
wheel_x /= 100.0f; wheel_x /= 100.0f;
#endif #endif
io.AddMouseSourceEvent(event->wheel.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
io.AddMouseWheelEvent(wheel_x, wheel_y); io.AddMouseWheelEvent(wheel_x, wheel_y);
return true; return true;
} }
@ -319,6 +323,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; } if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; }
if (mouse_button == -1) if (mouse_button == -1)
break; break;
io.AddMouseSourceEvent(event->button.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN)); io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN));
bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button)); bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
return true; return true;

View File

@ -4,6 +4,7 @@
// Implemented features: // Implemented features:
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.

View File

@ -5,6 +5,7 @@
// Implemented features: // Implemented features:
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
@ -18,6 +19,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702)
// 2023-02-23: Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. (#6189, #6114, #3644) // 2023-02-23: Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. (#6189, #6114, #3644)
// 2023-02-07: Forked "imgui_impl_sdl2" into "imgui_impl_sdl3". Removed version checks for old feature. Refer to imgui_impl_sdl2.cpp for older changelog. // 2023-02-07: Forked "imgui_impl_sdl2" into "imgui_impl_sdl3". Removed version checks for old feature. Refer to imgui_impl_sdl2.cpp for older changelog.
@ -239,6 +241,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
case SDL_EVENT_MOUSE_MOTION: case SDL_EVENT_MOUSE_MOTION:
{ {
ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y);
io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); io.AddMousePosEvent(mouse_pos.x, mouse_pos.y);
return true; return true;
} }
@ -250,6 +253,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
wheel_x /= 100.0f; wheel_x /= 100.0f;
#endif #endif
io.AddMouseSourceEvent(event->wheel.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
io.AddMouseWheelEvent(wheel_x, wheel_y); io.AddMouseWheelEvent(wheel_x, wheel_y);
return true; return true;
} }
@ -264,6 +268,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; } if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; }
if (mouse_button == -1) if (mouse_button == -1)
break; break;
io.AddMouseSourceEvent(event->button.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
io.AddMouseButtonEvent(mouse_button, (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN)); io.AddMouseButtonEvent(mouse_button, (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN));
bd->MouseButtonsDown = (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button)); bd->MouseButtonsDown = (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
return true; return true;
@ -368,7 +373,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer)
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered. // Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application. // (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click: // It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
// you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED) // you can ignore SDL_EVENT_MOUSE_BUTTON_DOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
#ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH #ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
#endif #endif
@ -432,7 +437,7 @@ static void ImGui_ImplSDL3_UpdateMouseData()
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
// We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below) // We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
// 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() 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_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE);
@ -447,7 +452,7 @@ static void ImGui_ImplSDL3_UpdateMouseData()
if (io.WantSetMousePos) if (io.WantSetMousePos)
SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y); SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y);
// (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) // (Optional) Fallback to provide mouse position when focused (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured)
if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0) if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0)
{ {
// 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) // 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)

View File

@ -5,6 +5,7 @@
// Implemented features: // Implemented features:
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.

View File

@ -3,6 +3,7 @@
// Implemented features: // Implemented features:
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
@ -34,6 +35,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen. (#2702)
// 2023-02-15: Inputs: Use WM_NCMOUSEMOVE / WM_NCMOUSELEAVE to track mouse position over non-client area (e.g. OS decorations) when app is not focused. (#6045, #6162) // 2023-02-15: Inputs: Use WM_NCMOUSEMOVE / WM_NCMOUSELEAVE to track mouse position over non-client area (e.g. OS decorations) when app is not focused. (#6045, #6162)
// 2023-02-02: Inputs: Flipping WM_MOUSEHWHEEL (horizontal mouse-wheel) value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463) // 2023-02-02: Inputs: Flipping WM_MOUSEHWHEEL (horizontal mouse-wheel) value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
@ -506,6 +508,19 @@ static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam)
// Copy this line into your .cpp file to forward declare the function. // Copy this line into your .cpp file to forward declare the function.
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
#endif #endif
// See https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages
// Prefer to call this at the top of the message handler to avoid the possibility of other Win32 calls interfering with this.
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
{
LPARAM extra_info = ::GetMessageExtraInfo();
if ((extra_info & 0xFFFFFF80) == 0xFF515700)
return ImGuiMouseSource_Pen;
if ((extra_info & 0xFFFFFF80) == 0xFF515780)
return ImGuiMouseSource_TouchScreen;
return ImGuiMouseSource_Mouse;
}
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
if (ImGui::GetCurrentContext() == nullptr) if (ImGui::GetCurrentContext() == nullptr)
@ -520,6 +535,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
case WM_NCMOUSEMOVE: case WM_NCMOUSEMOVE:
{ {
// We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events // We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
const int area = (msg == WM_MOUSEMOVE) ? 1 : 2; const int area = (msg == WM_MOUSEMOVE) ? 1 : 2;
bd->MouseHwnd = hwnd; bd->MouseHwnd = hwnd;
if (bd->MouseTrackedArea != area) if (bd->MouseTrackedArea != area)
@ -534,6 +550,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) }; POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) };
if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates. if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates.
break; break;
io.AddMouseSourceEvent(mouse_source);
io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y); io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y);
break; break;
} }
@ -555,6 +572,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
{ {
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
int button = 0; int button = 0;
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; } if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
@ -563,6 +581,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr) if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr)
::SetCapture(hwnd); ::SetCapture(hwnd);
bd->MouseButtonsDown |= 1 << button; bd->MouseButtonsDown |= 1 << button;
io.AddMouseSourceEvent(mouse_source);
io.AddMouseButtonEvent(button, true); io.AddMouseButtonEvent(button, true);
return 0; return 0;
} }
@ -571,6 +590,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
case WM_MBUTTONUP: case WM_MBUTTONUP:
case WM_XBUTTONUP: case WM_XBUTTONUP:
{ {
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
int button = 0; int button = 0;
if (msg == WM_LBUTTONUP) { button = 0; } if (msg == WM_LBUTTONUP) { button = 0; }
if (msg == WM_RBUTTONUP) { button = 1; } if (msg == WM_RBUTTONUP) { button = 1; }
@ -579,6 +599,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
bd->MouseButtonsDown &= ~(1 << button); bd->MouseButtonsDown &= ~(1 << button);
if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd) if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd)
::ReleaseCapture(); ::ReleaseCapture();
io.AddMouseSourceEvent(mouse_source);
io.AddMouseButtonEvent(button, false); io.AddMouseButtonEvent(button, false);
return 0; return 0;
} }

View File

@ -3,6 +3,7 @@
// Implemented features: // Implemented features:
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.

View File

@ -65,6 +65,11 @@ Other changes:
- Backends: OpenGL3: Fixed GL loader crash when GL_VERSION returns NULL. (#6154, #4445, #3530) - Backends: OpenGL3: Fixed GL loader crash when GL_VERSION returns NULL. (#6154, #4445, #3530)
- Backends: OpenGL3: Properly restoring "no shader program bound" if it was the case prior to - Backends: OpenGL3: Properly restoring "no shader program bound" if it was the case prior to
running the rendering function. (#6267, #6220, #6224) [@BrunoLevy] running the rendering function. (#6267, #6220, #6224) [@BrunoLevy]
- Backends: Win32: Added support for io.AddMouseSourceEvent() to discriminate Mouse/TouchScreen/Pen. (#2334, #2702)
- Backends: SDL2/SDL3: Added support for io.AddMouseSourceEvent() to discriminate Mouse/TouchScreen.
This is relying on SDL passing SDL_TOUCH_MOUSEID in the event's 'which' field. (#2334, #2702)
- Backends: GLFW: Added support on Win32 only for io.AddMouseSourceEvent() to discriminate
Mouse/TouchScreen/Pen. (#2334, #2702)
- Backends: GLFW: Fixed key modifiers handling on secondary viewports. (#6248, #6034) [@aiekick] - Backends: GLFW: Fixed key modifiers handling on secondary viewports. (#6248, #6034) [@aiekick]
- Examples: Windows: Added 'misc/debuggers/imgui.natstepfilter' file to all Visual Studio projects, - Examples: Windows: Added 'misc/debuggers/imgui.natstepfilter' file to all Visual Studio projects,
now that VS 2022 17.6 Preview 2 support adding Debug Step Filter spec files into projects. now that VS 2022 17.6 Preview 2 support adding Debug Step Filter spec files into projects.