mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-23 21:09:01 +08:00
Backends: Win32: Fixed a crash when multiple processes are running with multi-viewports, caused by misusage of GetProp(). (#8162, #8069)
Some checks failed
Some checks failed
Amend fedf45c77
This commit is contained in:
parent
cdf21f6773
commit
dad1047b04
@ -23,6 +23,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)
|
||||||
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2024-11-21: [Docking] Fixed a crash when multiple processes are running with multi-viewports, caused by misusage of GetProp(). (#8162, #8069)
|
||||||
// 2024-10-28: [Docking] Rely on property stored inside HWND to retrieve context/viewport, should facilitate attempt to use this for parallel contexts. (#8069)
|
// 2024-10-28: [Docking] Rely on property stored inside HWND to retrieve context/viewport, should facilitate attempt to use this for parallel contexts. (#8069)
|
||||||
// 2024-09-16: [Docking] Inputs: fixed an issue where a viewport destroyed while clicking would hog mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971)
|
// 2024-09-16: [Docking] Inputs: fixed an issue where a viewport destroyed while clicking would hog mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971)
|
||||||
// 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768)
|
// 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768)
|
||||||
@ -192,8 +193,10 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
|
|||||||
// Our mouse update function expect PlatformHandle to be filled for the main viewport
|
// Our mouse update function expect PlatformHandle to be filled for the main viewport
|
||||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||||
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)bd->hWnd;
|
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)bd->hWnd;
|
||||||
|
|
||||||
|
// Be aware that GetPropA()/SetPropA() may be accessed from other processes.
|
||||||
|
// So as we store a pointer in IMGUI_CONTEXT we need to make sure we only call GetPropA() on windows owned by our process.
|
||||||
::SetPropA(bd->hWnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext());
|
::SetPropA(bd->hWnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext());
|
||||||
::SetPropA(bd->hWnd, "IMGUI_VIEWPORT", main_viewport);
|
|
||||||
ImGui_ImplWin32_InitMultiViewportSupport(platform_has_own_dc);
|
ImGui_ImplWin32_InitMultiViewportSupport(platform_has_own_dc);
|
||||||
|
|
||||||
// Dynamically load XInput library
|
// Dynamically load XInput library
|
||||||
@ -238,7 +241,6 @@ void ImGui_ImplWin32_Shutdown()
|
|||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
::SetPropA(bd->hWnd, "IMGUI_CONTEXT", nullptr);
|
::SetPropA(bd->hWnd, "IMGUI_CONTEXT", nullptr);
|
||||||
::SetPropA(bd->hWnd, "IMGUI_VIEWPORT", nullptr);
|
|
||||||
ImGui_ImplWin32_ShutdownMultiViewportSupport();
|
ImGui_ImplWin32_ShutdownMultiViewportSupport();
|
||||||
|
|
||||||
// Unload XInput library
|
// Unload XInput library
|
||||||
@ -319,17 +321,20 @@ static void ImGui_ImplWin32_UpdateKeyModifiers(ImGuiIO& io)
|
|||||||
io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_LWIN) || IsVkDown(VK_RWIN));
|
io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_LWIN) || IsVkDown(VK_RWIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImGuiViewport* ImGui_ImplWin32_FindViewportByPlatformHandle(HWND hwnd)
|
static ImGuiViewport* ImGui_ImplWin32_FindViewportByPlatformHandle(ImGuiPlatformIO& platform_io, HWND hwnd)
|
||||||
{
|
{
|
||||||
// We could use ImGui::FindViewportByPlatformHandle() but GetPropA() gets us closer to parallel multi-contexts,
|
// We cannot use ImGui::FindViewportByPlatformHandle() because it doesn't take a context.
|
||||||
// until we can pass an explicit context to FindViewportByPlatformHandle().
|
// When called from ImGui_ImplWin32_WndProcHandler_PlatformWindow() we don't assume that context is bound.
|
||||||
//return ImGui::FindViewportByPlatformHandle((void*)hwnd);
|
//return ImGui::FindViewportByPlatformHandle((void*)hwnd);
|
||||||
return (ImGuiViewport*)::GetPropA(hwnd, "IMGUI_VIEWPORT");
|
for (ImGuiViewport* viewport : platform_io.Viewports)
|
||||||
|
if (viewport->PlatformHandle == hwnd)
|
||||||
|
return viewport;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This code supports multi-viewports (multiple OS Windows mapped into different Dear ImGui viewports)
|
// This code supports multi-viewports (multiple OS Windows mapped into different Dear ImGui viewports)
|
||||||
// Because of that, it is a little more complicated than your typical single-viewport binding code!
|
// Because of that, it is a little more complicated than your typical single-viewport binding code!
|
||||||
static void ImGui_ImplWin32_UpdateMouseData(ImGuiIO& io)
|
static void ImGui_ImplWin32_UpdateMouseData(ImGuiIO& io, ImGuiPlatformIO& platform_io)
|
||||||
{
|
{
|
||||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
|
||||||
IM_ASSERT(bd->hWnd != 0);
|
IM_ASSERT(bd->hWnd != 0);
|
||||||
@ -338,7 +343,7 @@ static void ImGui_ImplWin32_UpdateMouseData(ImGuiIO& io)
|
|||||||
bool has_mouse_screen_pos = ::GetCursorPos(&mouse_screen_pos) != 0;
|
bool has_mouse_screen_pos = ::GetCursorPos(&mouse_screen_pos) != 0;
|
||||||
|
|
||||||
HWND focused_window = ::GetForegroundWindow();
|
HWND focused_window = ::GetForegroundWindow();
|
||||||
const bool is_app_focused = (focused_window && (focused_window == bd->hWnd || ::IsChild(focused_window, bd->hWnd) || ImGui_ImplWin32_FindViewportByPlatformHandle(focused_window)));
|
const bool is_app_focused = (focused_window && (focused_window == bd->hWnd || ::IsChild(focused_window, bd->hWnd) || ImGui_ImplWin32_FindViewportByPlatformHandle(platform_io, focused_window)));
|
||||||
if (is_app_focused)
|
if (is_app_focused)
|
||||||
{
|
{
|
||||||
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
|
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
|
||||||
@ -376,7 +381,7 @@ static void ImGui_ImplWin32_UpdateMouseData(ImGuiIO& io)
|
|||||||
ImGuiID mouse_viewport_id = 0;
|
ImGuiID mouse_viewport_id = 0;
|
||||||
if (has_mouse_screen_pos)
|
if (has_mouse_screen_pos)
|
||||||
if (HWND hovered_hwnd = ::WindowFromPoint(mouse_screen_pos))
|
if (HWND hovered_hwnd = ::WindowFromPoint(mouse_screen_pos))
|
||||||
if (ImGuiViewport* viewport = ImGui_ImplWin32_FindViewportByPlatformHandle(hovered_hwnd))
|
if (ImGuiViewport* viewport = ImGui_ImplWin32_FindViewportByPlatformHandle(platform_io, hovered_hwnd))
|
||||||
mouse_viewport_id = viewport->ID;
|
mouse_viewport_id = viewport->ID;
|
||||||
io.AddMouseViewportEvent(mouse_viewport_id);
|
io.AddMouseViewportEvent(mouse_viewport_id);
|
||||||
}
|
}
|
||||||
@ -475,6 +480,7 @@ void ImGui_ImplWin32_NewFrame()
|
|||||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized? Did you call ImGui_ImplWin32_Init()?");
|
IM_ASSERT(bd != nullptr && "Context or backend not initialized? Did you call ImGui_ImplWin32_Init()?");
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
|
||||||
// Setup display size (every frame to accommodate for window resizing)
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
RECT rect = { 0, 0, 0, 0 };
|
RECT rect = { 0, 0, 0, 0 };
|
||||||
@ -490,7 +496,7 @@ void ImGui_ImplWin32_NewFrame()
|
|||||||
bd->Time = current_time;
|
bd->Time = current_time;
|
||||||
|
|
||||||
// Update OS mouse position
|
// Update OS mouse position
|
||||||
ImGui_ImplWin32_UpdateMouseData(io);
|
ImGui_ImplWin32_UpdateMouseData(io, platform_io);
|
||||||
|
|
||||||
// Process workarounds for known Windows key handling issues
|
// Process workarounds for known Windows key handling issues
|
||||||
ImGui_ImplWin32_ProcessKeyEventsWorkarounds(io);
|
ImGui_ImplWin32_ProcessKeyEventsWorkarounds(io);
|
||||||
@ -1091,7 +1097,6 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
|
|||||||
|
|
||||||
// Secondary viewports store their imgui context
|
// Secondary viewports store their imgui context
|
||||||
::SetPropA(vd->Hwnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext());
|
::SetPropA(vd->Hwnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext());
|
||||||
::SetPropA(vd->Hwnd, "IMGUI_VIEWPORT", viewport);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport)
|
static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport)
|
||||||
@ -1303,7 +1308,7 @@ static void ImGui_ImplWin32_OnChangedViewport(ImGuiViewport* viewport)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ImGui { extern ImGuiIO& GetIOEx(ImGuiContext*); }
|
namespace ImGui { extern ImGuiIO& GetIOEx(ImGuiContext*); extern ImGuiPlatformIO& GetPlatformIOEx(ImGuiContext*); }
|
||||||
|
|
||||||
static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
@ -1313,10 +1318,11 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd,
|
|||||||
return DefWindowProc(hWnd, msg, wParam, lParam); // unlike ImGui_ImplWin32_WndProcHandler() we are called directly by Windows, we can't just return 0.
|
return DefWindowProc(hWnd, msg, wParam, lParam); // unlike ImGui_ImplWin32_WndProcHandler() we are called directly by Windows, we can't just return 0.
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIOEx(ctx);
|
ImGuiIO& io = ImGui::GetIOEx(ctx);
|
||||||
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIOEx(ctx);
|
||||||
LRESULT result = 0;
|
LRESULT result = 0;
|
||||||
if (ImGui_ImplWin32_WndProcHandlerEx(hWnd, msg, wParam, lParam, io))
|
if (ImGui_ImplWin32_WndProcHandlerEx(hWnd, msg, wParam, lParam, io))
|
||||||
result = true;
|
result = true;
|
||||||
else if (ImGuiViewport* viewport = ImGui_ImplWin32_FindViewportByPlatformHandle(hWnd))
|
else if (ImGuiViewport* viewport = ImGui_ImplWin32_FindViewportByPlatformHandle(platform_io, hWnd))
|
||||||
{
|
{
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
|
@ -64,6 +64,10 @@ Other changes:
|
|||||||
|
|
||||||
Docking+Viewports Branch:
|
Docking+Viewports Branch:
|
||||||
|
|
||||||
|
- Backends: Win32: Fixed a crash/regression in 1.91.5 when running two processes
|
||||||
|
with multi-viewports (was using GetProp() to query property which could have
|
||||||
|
belonged to another process). (#8162, #8069) [@sammyfreg, @ocornut]
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
VERSION 1.91.5 (Released 2024-11-07)
|
VERSION 1.91.5 (Released 2024-11-07)
|
||||||
|
@ -4856,6 +4856,13 @@ ImGuiPlatformIO& ImGui::GetPlatformIO()
|
|||||||
return GImGui->PlatformIO;
|
return GImGui->PlatformIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This variant exists to facilitate backends experimenting with multi-threaded parallel context. (#8069, #6293, #5856)
|
||||||
|
ImGuiPlatformIO& ImGui::GetPlatformIOEx(ImGuiContext* ctx)
|
||||||
|
{
|
||||||
|
IM_ASSERT(ctx != NULL);
|
||||||
|
return ctx->PlatformIO;
|
||||||
|
}
|
||||||
|
|
||||||
// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame()
|
// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame()
|
||||||
ImDrawData* ImGui::GetDrawData()
|
ImDrawData* ImGui::GetDrawData()
|
||||||
{
|
{
|
||||||
|
@ -3184,7 +3184,8 @@ namespace ImGui
|
|||||||
// If this ever crashes because g.CurrentWindow is NULL, it means that either:
|
// If this ever crashes because g.CurrentWindow is NULL, it means that either:
|
||||||
// - ImGui::NewFrame() has never been called, which is illegal.
|
// - ImGui::NewFrame() has never been called, which is illegal.
|
||||||
// - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
|
// - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
|
||||||
IMGUI_API ImGuiIO& GetIOEx(ImGuiContext* ctx);
|
IMGUI_API ImGuiIO& GetIOEx(ImGuiContext* ctx);
|
||||||
|
IMGUI_API ImGuiPlatformIO& GetPlatformIOEx(ImGuiContext* ctx);
|
||||||
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
|
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
|
||||||
inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
|
inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
|
||||||
IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
|
IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
|
||||||
|
Loading…
Reference in New Issue
Block a user