Backends: support for multiple imgui context with little testing (#586, #1851, #2004, #3012, #3934, #4141)

I believe more renderer backends should work. GLFW/Win32/SDL/Vulkan probably have many issues.
diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp
index 760f36f..19de969 100644
--- a/backends/imgui_impl_dx10.cpp
+++ b/backends/imgui_impl_dx10.cpp
@@ -62,11 +62,11 @@
     ImGui_ImplDX10_Data()       { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplDX10_Data* g_Data;
-static ImGui_ImplDX10_Data* ImGui_ImplDX10_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX10_Data); return g_Data; }
-static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; }
-static void                 ImGui_ImplDX10_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplDX10_Data*     ImGui_ImplDX10_CreateBackendData()  { return IM_NEW(ImGui_ImplDX10_Data)(); }
+static ImGui_ImplDX10_Data*     ImGui_ImplDX10_GetBackendData()     { return (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData; }
+static void                     ImGui_ImplDX10_DestroyBackendData() { IM_DELETE(ImGui_ImplDX10_GetBackendData()); }
 
 struct VERTEX_CONSTANT_BUFFER
 {
diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index 867fb7a..a5f9f21 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -63,11 +63,11 @@
     ImGui_ImplDX11_Data()       { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplDX11_Data* g_Data;
-static ImGui_ImplDX11_Data* ImGui_ImplDX11_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX11_Data); return g_Data; }
-static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; }
-static void                 ImGui_ImplDX11_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplDX11_Data*     ImGui_ImplDX11_CreateBackendData()  { return IM_NEW(ImGui_ImplDX11_Data)(); }
+static ImGui_ImplDX11_Data*     ImGui_ImplDX11_GetBackendData()     { return (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData; }
+static void                     ImGui_ImplDX11_DestroyBackendData() { IM_DELETE(ImGui_ImplDX11_GetBackendData()); }
 
 struct VERTEX_CONSTANT_BUFFER
 {
diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index c7dcca1..079c515 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -74,11 +74,11 @@
     ImGui_ImplDX12_Data()           { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplDX12_Data* g_Data;
-static ImGui_ImplDX12_Data* ImGui_ImplDX12_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX12_Data); return g_Data; }
-static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; }
-static void                 ImGui_ImplDX12_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplDX12_Data*     ImGui_ImplDX12_CreateBackendData()  { return IM_NEW(ImGui_ImplDX12_Data)(); }
+static ImGui_ImplDX12_Data*     ImGui_ImplDX12_GetBackendData()     { return (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData; }
+static void                     ImGui_ImplDX12_DestroyBackendData() { IM_DELETE(ImGui_ImplDX12_GetBackendData()); }
 
 template<typename T>
 static void SafeRelease(T*& res)
diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp
index a2d426d..07c35ea 100644
--- a/backends/imgui_impl_dx9.cpp
+++ b/backends/imgui_impl_dx9.cpp
@@ -49,11 +49,11 @@
     ImGui_ImplDX9_Data()        { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplDX9_Data*  g_Data;
-static ImGui_ImplDX9_Data*  ImGui_ImplDX9_CreateBackendData()   { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX9_Data); return g_Data; }
-static ImGui_ImplDX9_Data*  ImGui_ImplDX9_GetBackendData()      { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; }
-static void                 ImGui_ImplDX9_DestroyBackendData()  { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplDX9_Data*      ImGui_ImplDX9_CreateBackendData()   { return IM_NEW(ImGui_ImplDX9_Data)(); }
+static ImGui_ImplDX9_Data*      ImGui_ImplDX9_GetBackendData()      { return (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData; }
+static void                     ImGui_ImplDX9_DestroyBackendData()  { IM_DELETE(ImGui_ImplDX9_GetBackendData()); }
 
 struct CUSTOMVERTEX
 {
diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index 07b61df..cc3c58f 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -86,11 +86,13 @@
     ImGui_ImplGlfw_Data()   { memset(this, 0, sizeof(*this)); }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplGlfw_Data* g_Data;
-static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplGlfw_Data); return g_Data; }
-static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; }
-static void                 ImGui_ImplGlfw_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
+// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
+static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_CreateBackendData()  { return IM_NEW(ImGui_ImplGlfw_Data)(); }
+static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()     { return (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData; }
+static void                 ImGui_ImplGlfw_DestroyBackendData() { IM_DELETE(ImGui_ImplGlfw_GetBackendData()); }
 
 // Functions
 static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp
index e45c042..5a39edf 100644
--- a/backends/imgui_impl_opengl2.cpp
+++ b/backends/imgui_impl_opengl2.cpp
@@ -63,11 +63,11 @@
     ImGui_ImplOpenGL2_Data() { memset(this, 0, sizeof(*this)); }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplOpenGL2_Data*  g_Data;
-static ImGui_ImplOpenGL2_Data*  ImGui_ImplOpenGL2_CreateBackendData()   { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplOpenGL2_Data); return g_Data; }
-static ImGui_ImplOpenGL2_Data*  ImGui_ImplOpenGL2_GetBackendData()      { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; }
-static void                     ImGui_ImplOpenGL2_DestroyBackendData()  { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplOpenGL2_Data*  ImGui_ImplOpenGL2_CreateBackendData()   { return IM_NEW(ImGui_ImplOpenGL2_Data)(); }
+static ImGui_ImplOpenGL2_Data*  ImGui_ImplOpenGL2_GetBackendData()      { return (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData; }
+static void                     ImGui_ImplOpenGL2_DestroyBackendData()  { IM_DELETE(ImGui_ImplOpenGL2_GetBackendData()); }
 
 // Functions
 bool    ImGui_ImplOpenGL2_Init()
diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index ee0fd6f..2204b33 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -189,11 +189,11 @@
     ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplOpenGL3_Data*  g_Data;
-static ImGui_ImplOpenGL3_Data*  ImGui_ImplOpenGL3_CreateBackendData()   { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplOpenGL3_Data); return g_Data; }
-static ImGui_ImplOpenGL3_Data*  ImGui_ImplOpenGL3_GetBackendData()      { IM_ASSERT(ImGui::GetCurrentContext() != NULL); return g_Data; }
-static void                     ImGui_ImplOpenGL3_DestroyBackendData()  { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplOpenGL3_Data*  ImGui_ImplOpenGL3_CreateBackendData()   { return IM_NEW(ImGui_ImplOpenGL3_Data)(); }
+static ImGui_ImplOpenGL3_Data*  ImGui_ImplOpenGL3_GetBackendData()      { return (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData; }
+static void                     ImGui_ImplOpenGL3_DestroyBackendData()  { IM_DELETE(ImGui_ImplOpenGL3_GetBackendData()); }
 
 // Functions
 bool    ImGui_ImplOpenGL3_Init(const char* glsl_version)
diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp
index 9392216..c7c28e0 100644
--- a/backends/imgui_impl_sdl.cpp
+++ b/backends/imgui_impl_sdl.cpp
@@ -69,14 +69,16 @@
     char*       ClipboardTextData;
     bool        MouseCanUseGlobalState;
 
-    ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); }
+    ImGui_ImplSDL2_Data()   { memset(this, 0, sizeof(*this)); }
 };
 
-// Wrapping access to backend data data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplSDL2_Data* g_Data;
-static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplSDL2_Data); return g_Data; }
-static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; }
-static void                 ImGui_ImplSDL2_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
+// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
+static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_CreateBackendData()  { return IM_NEW(ImGui_ImplSDL2_Data)(); }
+static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()     { return (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData; }
+static void                 ImGui_ImplSDL2_DestroyBackendData() { IM_DELETE(ImGui_ImplSDL2_GetBackendData()); }
 
 // Functions
 static const char* ImGui_ImplSDL2_GetClipboardText(void*)
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index f5d63b2..5f2a192 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -110,11 +110,12 @@
     }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplVulkan_Data*   g_Data;
-static ImGui_ImplVulkan_Data*   ImGui_ImplVulkan_CreateBackendData()    { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplVulkan_Data); return g_Data; }
-static ImGui_ImplVulkan_Data*   ImGui_ImplVulkan_GetBackendData()       { return ImGui::GetCurrentContext() ? g_Data : NULL; }
-static void                     ImGui_ImplVulkan_DestroyBackendData()   { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not tested and probably dysfunctional in this backend.
+static ImGui_ImplVulkan_Data*   ImGui_ImplVulkan_CreateBackendData()    { return IM_NEW(ImGui_ImplVulkan_Data)(); }
+static ImGui_ImplVulkan_Data*   ImGui_ImplVulkan_GetBackendData()       { return (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData; }
+static void                     ImGui_ImplVulkan_DestroyBackendData()   { IM_DELETE(ImGui_ImplVulkan_GetBackendData()); }
 
 // Forward Declarations
 bool ImGui_ImplVulkan_CreateDeviceObjects();
diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index edd6635..09d1270 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -82,11 +82,13 @@
     ImGui_ImplWin32_Data()      { memset(this, 0, sizeof(*this)); }
 };
 
-// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData)
-static ImGui_ImplWin32_Data*    g_Data;
-static ImGui_ImplWin32_Data*    ImGui_ImplWin32_CreateBackendData()     { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplWin32_Data); return g_Data; }
-static ImGui_ImplWin32_Data*    ImGui_ImplWin32_GetBackendData()        { return ImGui::GetCurrentContext() ? g_Data : NULL; }
-static void                     ImGui_ImplWin32_DestroyBackendData()    { IM_DELETE(g_Data); g_Data = NULL; }
+// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
+// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
+static ImGui_ImplWin32_Data*    ImGui_ImplWin32_CreateBackendData()     { return IM_NEW(ImGui_ImplWin32_Data)(); }
+static ImGui_ImplWin32_Data*    ImGui_ImplWin32_GetBackendData()        { return (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData; }
+static void                     ImGui_ImplWin32_DestroyBackendData()    { IM_DELETE(ImGui_ImplWin32_GetBackendData()); }
 
 // Functions
 bool    ImGui_ImplWin32_Init(void* hwnd)
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 995307e..aeb6dd4 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -55,8 +55,11 @@
 - Demo: Fixed requirement in 1.83 to link with imgui_demo.cpp if IMGUI_DISABLE_METRICS_WINDOW is not set. (#4171)
   Normally the right way to disable compiling the demo is to set IMGUI_DISABLE_DEMO_WINDOWS, but we want to avoid
   implying that the file is required.
-- Backends: Reorganized most backends (Win32, SDL, GLFW, OpenGL2/3, DX9/10/11/12, Vulkan, Allegro) to pull data
-  from a single structure to facilitate usage with multiple-contexts. (#586, #1851, #2004, #3012, #3934, #4141)
+- Backends: Reorganized most backends (Win32, SDL, GLFW, OpenGL2/3, DX9/10/11/12, Vulkan, Allegro) to pull their
+  data from a single structure stored inside the main Dear ImGui context. This facilitate/allow usage of standard
+  backends with multiple-contexts BUT is only partially tested and not well supported. It is generally advised to
+  instead use the multi-viewports feature of docking branch where a single Dear ImGui context can be used accross
+  multiple windows. (#586, #1851, #2004, #3012, #3934, #4141)
 - Backends: Win32: Rework to handle certains Windows 8.1/10 features without a manifest. (#4200, #4191)
   - ImGui_ImplWin32_GetDpiScaleForMonitor() will handle per-monitor DPI on Windows 10 without a manifest.
   - ImGui_ImplWin32_EnableDpiAwareness() will call SetProcessDpiAwareness() fallback on Windows 8.1 without a manifest.