mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-23 16:16:36 +00:00
Viewport, Platform: Win32: Fixed handling of io.WantSetMousePos + added a bunch of comments. GLFW, SDL2: Added handling of io.WantSetMousePos. (#1542)
This commit is contained in:
parent
6eacddb50f
commit
d574604a5d
@ -120,7 +120,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||||||
// Setup back-end capabilities flags
|
// Setup back-end capabilities flags
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
//io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
||||||
#if GLFW_HAS_GLFW_HOVERED
|
#if GLFW_HAS_GLFW_HOVERED
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
|
||||||
@ -198,13 +198,8 @@ void ImGui_ImplGlfw_Shutdown()
|
|||||||
|
|
||||||
static void ImGui_ImplGlfw_UpdateMouse()
|
static void ImGui_ImplGlfw_UpdateMouse()
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
// Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
|
||||||
if (io.WantSetMousePos)
|
|
||||||
glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
const ImVec2 mouse_pos_backup = io.MousePos;
|
||||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
io.MousePosViewport = 0;
|
io.MousePosViewport = 0;
|
||||||
io.MouseHoveredViewport = 0;
|
io.MouseHoveredViewport = 0;
|
||||||
@ -224,10 +219,17 @@ static void ImGui_ImplGlfw_UpdateMouse()
|
|||||||
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
|
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
|
||||||
IM_ASSERT(window != NULL);
|
IM_ASSERT(window != NULL);
|
||||||
if (glfwGetWindowAttrib(window, GLFW_FOCUSED))
|
if (glfwGetWindowAttrib(window, GLFW_FOCUSED))
|
||||||
|
{
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
{
|
||||||
|
glfwSetCursorPos(window, (double)(mouse_pos_backup.x - viewport->Pos.x), (double)(mouse_pos_backup.y - viewport->Pos.y));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
double mouse_x, mouse_y;
|
double mouse_x, mouse_y;
|
||||||
glfwGetCursorPos(window, &mouse_x, &mouse_y);
|
glfwGetCursorPos(window, &mouse_x, &mouse_y);
|
||||||
io.MousePos = ImVec2((float)mouse_x + viewport->Pos.x, (float)mouse_y + viewport->Pos.y);
|
io.MousePos = ImVec2((float)mouse_x + viewport->Pos.x, (float)mouse_y + viewport->Pos.y);
|
||||||
|
}
|
||||||
io.MousePosViewport = viewport->ID;
|
io.MousePosViewport = viewport->ID;
|
||||||
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
|
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
|
||||||
io.MouseDown[i] |= glfwGetMouseButton(window, i) != 0;
|
io.MouseDown[i] |= glfwGetMouseButton(window, i) != 0;
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
// (the multi-viewports feature requires SDL features supported from SDL 2.0.5+)
|
// (the multi-viewports feature requires SDL features supported from SDL 2.0.5+)
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL_syswm.h>
|
#include <SDL_syswm.h>
|
||||||
|
#define SDL_HAS_WARP_MOUSE_GLOBAL SDL_VERSION_ATLEAST(2,0,4)
|
||||||
#define SDL_HAS_CAPTURE_MOUSE SDL_VERSION_ATLEAST(2,0,4)
|
#define SDL_HAS_CAPTURE_MOUSE SDL_VERSION_ATLEAST(2,0,4)
|
||||||
#define SDL_HAS_WINDOW_OPACITY SDL_VERSION_ATLEAST(2,0,5)
|
#define SDL_HAS_WINDOW_OPACITY SDL_VERSION_ATLEAST(2,0,5)
|
||||||
#define SDL_HAS_ALWAYS_ON_TOP SDL_VERSION_ATLEAST(2,0,5)
|
#define SDL_HAS_ALWAYS_ON_TOP SDL_VERSION_ATLEAST(2,0,5)
|
||||||
@ -131,6 +132,9 @@ bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
|
|||||||
// Setup back-end capabilities flags
|
// Setup back-end capabilities flags
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
|
#if SDL_HAS_WARP_MOUSE_GLOBAL
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
#endif
|
||||||
#if SDL_HAS_CAPTURE_MOUSE
|
#if SDL_HAS_CAPTURE_MOUSE
|
||||||
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
||||||
#endif
|
#endif
|
||||||
@ -196,10 +200,23 @@ void ImGui_ImplSDL2_Shutdown()
|
|||||||
static void ImGui_ImplSDL2_UpdateMouse()
|
static void ImGui_ImplSDL2_UpdateMouse()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
const ImVec2 mouse_pos_backup = io.MousePos;
|
||||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
io.MousePosViewport = 0;
|
io.MousePosViewport = 0;
|
||||||
io.MouseHoveredViewport = 0;
|
io.MouseHoveredViewport = 0;
|
||||||
|
|
||||||
|
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||||
|
// (When multi-viewports are enabled, all imgui positions are same as OS positions.)
|
||||||
|
#if SDL_HAS_WARP_MOUSE_GLOBAL
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
{
|
||||||
|
if ((io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) == 0)
|
||||||
|
SDL_WarpMouseInWindow(g_Window, (int)mouse_pos_backup.x, (int)mouse_pos_backup.y);
|
||||||
|
else
|
||||||
|
SDL_WarpMouseGlobal((int)mouse_pos_backup.x, (int)mouse_pos_backup.y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int mx, my;
|
int mx, my;
|
||||||
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
|
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
|
||||||
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.
|
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.
|
||||||
|
@ -120,38 +120,53 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This code supports multiple OS Windows mapped into different ImGui viewports,
|
// This code supports multiple OS Windows mapped into different ImGui viewports,
|
||||||
// So it is a little more complicated than your typical single-viewport binding code (which only needs to set io.MousePos from the WM_MOUSEMOVE handler)
|
// Because of that, it is a little more complicated than your typical single-viewport binding code.
|
||||||
// This is what imgui needs from the back-end to support multiple windows:
|
// A) In Single-viewport mode imgui needs:
|
||||||
// - io.MousePos = mouse position in absolute coordinate (e.g. io.MousePos == ImVec2(0,0) when it is on the upper-left of the primary monitor)
|
// - io.MousePos ............... mouse position, in client window coordinates (what you'd get from GetCursorPos+ScreenToClient() or from WM_MOUSEMOVE)
|
||||||
// - io.MousePosViewport = viewport which mouse position is based from (generally the focused/active/capturing viewport)
|
// io.MousePos is (0,0) when the mouse is on the upper-left corner of the application window.
|
||||||
// - io.MouseHoveredWindow = viewport which mouse is hovering, **regardless of it being the active/focused window**, **regardless of another window holding mouse captured**. [Optional]
|
// B) In Multi-viewport mode imgui needs: (when ImGuiConfigFlags_ViewportsEnable is set)
|
||||||
|
// - io.MousePos ............... mouse position, in OS absolute coordinates (what you'd get from GetCursorPos(), or from WM_MOUSEMOVE+viewport->Pos).
|
||||||
|
// io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor.
|
||||||
|
// - io.MousePosViewport ....... viewport which mouse position is based from (generally the focused/active/capturing viewport)
|
||||||
|
// - io.MouseHoveredViewport ... [optional] viewport which mouse is hovering, with _very_ specific/strict conditions (Read comments next to io.MouseHoveredViewport. This is _NOT_ easy to provide in many high-level engine because of how we handle the ImGuiViewportFlags_NoInputs flag)
|
||||||
// This function overwrite the value of io.MousePos normally updated by the WM_MOUSEMOVE handler.
|
// This function overwrite the value of io.MousePos normally updated by the WM_MOUSEMOVE handler.
|
||||||
// We keep the WM_MOUSEMOVE handling code so that WndProc function can be copied as-in in applications which do not need multiple OS windows support.
|
// We keep the WM_MOUSEMOVE handling code so that WndProc function can be copied as-in in applications which do not need multi-viewport support.
|
||||||
static void ImGui_ImplWin32_UpdateMousePos()
|
static void ImGui_ImplWin32_UpdateMousePos()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||||
|
// (When multi-viewports are enabled, all imgui positions are same as OS positions.)
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
{
|
||||||
|
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||||
|
if ((io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) == 0)
|
||||||
|
::ClientToScreen(g_hWnd, &pos);
|
||||||
|
::SetCursorPos(pos.x, pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
io.MousePosViewport = 0;
|
io.MousePosViewport = 0;
|
||||||
io.MouseHoveredViewport = 0;
|
io.MouseHoveredViewport = 0;
|
||||||
|
|
||||||
|
// Set mouse position and viewport
|
||||||
|
// (Note that ScreenToClient() and adding +viewport->Pos are mutually cancelling each others when we have multi-viewport enabled. In single-viewport mode, viewport->Pos will be zero)
|
||||||
POINT pos;
|
POINT pos;
|
||||||
if (!::GetCursorPos(&pos))
|
if (!::GetCursorPos(&pos))
|
||||||
return;
|
return;
|
||||||
|
if (HWND focused_hwnd = ::GetActiveWindow())
|
||||||
// Our back-end can tell which window is under the mouse cursor (not every back-end can), so pass that info to imgui
|
|
||||||
HWND hovered_hwnd = ::WindowFromPoint(pos);
|
|
||||||
if (hovered_hwnd)
|
|
||||||
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hovered_hwnd))
|
|
||||||
io.MouseHoveredViewport = viewport->ID;
|
|
||||||
|
|
||||||
// Convert mouse from screen position to window client position
|
|
||||||
HWND focused_hwnd = ::GetActiveWindow();
|
|
||||||
if (focused_hwnd != 0 && ::ScreenToClient(focused_hwnd, &pos))
|
|
||||||
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)focused_hwnd))
|
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)focused_hwnd))
|
||||||
{
|
{
|
||||||
io.MousePos = ImVec2(viewport->Pos.x + (float)pos.x, viewport->Pos.y + (float)pos.y);
|
POINT client_pos = pos;
|
||||||
|
::ScreenToClient(focused_hwnd, &client_pos);
|
||||||
|
io.MousePos = ImVec2(viewport->Pos.x + (float)client_pos.x, viewport->Pos.y + (float)client_pos.y);
|
||||||
io.MousePosViewport = viewport->ID;
|
io.MousePosViewport = viewport->ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Our back-end can tell which window is under the mouse cursor (not every back-end can), so pass that info to imgui
|
||||||
|
if (HWND hovered_hwnd = ::WindowFromPoint(pos))
|
||||||
|
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hovered_hwnd))
|
||||||
|
io.MouseHoveredViewport = viewport->ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplWin32_NewFrame()
|
void ImGui_ImplWin32_NewFrame()
|
||||||
@ -176,18 +191,10 @@ void ImGui_ImplWin32_NewFrame()
|
|||||||
io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||||
io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0;
|
io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0;
|
||||||
io.KeySuper = false;
|
io.KeySuper = false;
|
||||||
// io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
|
// io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below.
|
||||||
// io.MousePos : filled by WM_MOUSEMOVE events
|
|
||||||
// io.MouseDown : filled by WM_*BUTTON* events
|
|
||||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
|
||||||
|
|
||||||
// Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
// Update OS mouse position
|
||||||
if (io.WantSetMousePos)
|
ImGui_ImplWin32_UpdateMousePos();
|
||||||
{
|
|
||||||
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
|
||||||
::ClientToScreen(g_hWnd, &pos);
|
|
||||||
::SetCursorPos(pos.x, pos.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update OS mouse cursor with the cursor requested by imgui
|
// Update OS mouse cursor with the cursor requested by imgui
|
||||||
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||||
@ -197,8 +204,6 @@ void ImGui_ImplWin32_NewFrame()
|
|||||||
ImGui_ImplWin32_UpdateMouseCursor();
|
ImGui_ImplWin32_UpdateMouseCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui_ImplWin32_UpdateMousePos();
|
|
||||||
|
|
||||||
// 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.
|
// 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.
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user