mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-06 04:58:47 +02:00
Backends: moved global to a data structure to facilitate support for multi-contexts. (#586, #1851, #2004, #3012, #3934, #4141)
This is NOT enable multi-contexts for any backends - in order to make this commit as harmless as possible, while containing all the cruft/renaming -
This commit is contained in:
@ -33,6 +33,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-06-08: Fix ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
|
||||
// 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS).
|
||||
// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi).
|
||||
@ -63,35 +64,54 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
||||
// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging.
|
||||
// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set.
|
||||
|
||||
// Win32 Data
|
||||
static HWND g_hWnd = NULL;
|
||||
static INT64 g_Time = 0;
|
||||
static INT64 g_TicksPerSecond = 0;
|
||||
static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT;
|
||||
static bool g_HasGamepad = false;
|
||||
static bool g_WantUpdateHasGamepad = true;
|
||||
struct ImGui_ImplWin32_Data
|
||||
{
|
||||
HWND hWnd;
|
||||
INT64 Time;
|
||||
INT64 TicksPerSecond;
|
||||
ImGuiMouseCursor LastMouseCursor;
|
||||
bool HasGamepad;
|
||||
bool WantUpdateHasGamepad;
|
||||
|
||||
// XInput DLL and functions
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
static HMODULE g_XInputDLL = NULL;
|
||||
static PFN_XInputGetCapabilities g_XInputGetCapabilities = NULL;
|
||||
static PFN_XInputGetState g_XInputGetState = NULL;
|
||||
HMODULE XInputDLL;
|
||||
PFN_XInputGetCapabilities XInputGetCapabilities;
|
||||
PFN_XInputGetState XInputGetState;
|
||||
#endif
|
||||
|
||||
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; }
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplWin32_Init(void* hwnd)
|
||||
{
|
||||
if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&g_TicksPerSecond))
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
|
||||
|
||||
INT64 perf_frequency, perf_counter;
|
||||
if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency))
|
||||
return false;
|
||||
if (!::QueryPerformanceCounter((LARGE_INTEGER*)&g_Time))
|
||||
if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter))
|
||||
return false;
|
||||
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_CreateBackendData();
|
||||
bd->hWnd = (HWND)hwnd;
|
||||
bd->WantUpdateHasGamepad = true;
|
||||
bd->TicksPerSecond = perf_frequency;
|
||||
bd->Time = perf_counter;
|
||||
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
|
||||
|
||||
// Setup backend capabilities flags
|
||||
g_hWnd = (HWND)hwnd;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = "imgui_impl_win32";
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
io.BackendPlatformName = "imgui_impl_win32";
|
||||
io.ImeWindowHandle = hwnd;
|
||||
|
||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
|
||||
@ -131,9 +151,9 @@ bool ImGui_ImplWin32_Init(void* hwnd)
|
||||
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
|
||||
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
|
||||
{
|
||||
g_XInputDLL = dll;
|
||||
g_XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
|
||||
g_XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
|
||||
bd->XInputDLL = dll;
|
||||
bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
|
||||
bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
|
||||
break;
|
||||
}
|
||||
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
@ -143,21 +163,18 @@ bool ImGui_ImplWin32_Init(void* hwnd)
|
||||
|
||||
void ImGui_ImplWin32_Shutdown()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
|
||||
// Unload XInput library
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
if (g_XInputDLL)
|
||||
::FreeLibrary(g_XInputDLL);
|
||||
g_XInputDLL = NULL;
|
||||
g_XInputGetCapabilities = NULL;
|
||||
g_XInputGetState = NULL;
|
||||
if (bd->XInputDLL)
|
||||
::FreeLibrary(bd->XInputDLL);
|
||||
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
|
||||
g_hWnd = NULL;
|
||||
g_Time = 0;
|
||||
g_TicksPerSecond = 0;
|
||||
g_LastMouseCursor = ImGuiMouseCursor_COUNT;
|
||||
g_HasGamepad = false;
|
||||
g_WantUpdateHasGamepad = true;
|
||||
io.BackendPlatformName = NULL;
|
||||
io.BackendPlatformUserData = NULL;
|
||||
ImGui_ImplWin32_DestroyBackendData();
|
||||
}
|
||||
|
||||
static bool ImGui_ImplWin32_UpdateMouseCursor()
|
||||
@ -196,13 +213,14 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
|
||||
static void ImGui_ImplWin32_UpdateMousePos()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(g_hWnd != 0);
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
IM_ASSERT(bd->hWnd != 0);
|
||||
|
||||
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||
if (io.WantSetMousePos)
|
||||
{
|
||||
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||
if (::ClientToScreen(g_hWnd, &pos))
|
||||
if (::ClientToScreen(bd->hWnd, &pos))
|
||||
::SetCursorPos(pos.x, pos.y);
|
||||
}
|
||||
|
||||
@ -210,8 +228,8 @@ static void ImGui_ImplWin32_UpdateMousePos()
|
||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||
POINT pos;
|
||||
if (HWND active_window = ::GetForegroundWindow())
|
||||
if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd))
|
||||
if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos))
|
||||
if (active_window == bd->hWnd || ::IsChild(active_window, bd->hWnd))
|
||||
if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos))
|
||||
io.MousePos = ImVec2((float)pos.x, (float)pos.y);
|
||||
}
|
||||
|
||||
@ -220,22 +238,23 @@ static void ImGui_ImplWin32_UpdateGamepads()
|
||||
{
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
memset(io.NavInputs, 0, sizeof(io.NavInputs));
|
||||
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
|
||||
return;
|
||||
|
||||
// Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
|
||||
// Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.
|
||||
if (g_WantUpdateHasGamepad)
|
||||
if (bd->WantUpdateHasGamepad)
|
||||
{
|
||||
XINPUT_CAPABILITIES caps;
|
||||
g_HasGamepad = g_XInputGetCapabilities ? (g_XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
|
||||
g_WantUpdateHasGamepad = false;
|
||||
bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
|
||||
bd->WantUpdateHasGamepad = false;
|
||||
}
|
||||
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
XINPUT_STATE xinput_state;
|
||||
if (g_HasGamepad && g_XInputGetState && g_XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
|
||||
if (bd->HasGamepad && bd->XInputGetState && bd->XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
|
||||
{
|
||||
const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
@ -267,17 +286,18 @@ static void ImGui_ImplWin32_UpdateGamepads()
|
||||
void ImGui_ImplWin32_NewFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
RECT rect = { 0, 0, 0, 0 };
|
||||
::GetClientRect(g_hWnd, &rect);
|
||||
::GetClientRect(bd->hWnd, &rect);
|
||||
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
|
||||
|
||||
// Setup time step
|
||||
INT64 current_time = 0;
|
||||
::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
|
||||
g_Time = current_time;
|
||||
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
|
||||
bd->Time = current_time;
|
||||
|
||||
// Read keyboard modifiers inputs
|
||||
io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
@ -291,9 +311,9 @@ void ImGui_ImplWin32_NewFrame()
|
||||
|
||||
// Update OS mouse cursor with the cursor requested by imgui
|
||||
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||
if (g_LastMouseCursor != mouse_cursor)
|
||||
if (bd->LastMouseCursor != mouse_cursor)
|
||||
{
|
||||
g_LastMouseCursor = mouse_cursor;
|
||||
bd->LastMouseCursor = mouse_cursor;
|
||||
ImGui_ImplWin32_UpdateMouseCursor();
|
||||
}
|
||||
|
||||
@ -327,6 +347,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
|
||||
return 0;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
|
||||
@ -389,7 +411,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
|
||||
return 0;
|
||||
case WM_DEVICECHANGE:
|
||||
if ((UINT)wParam == DBT_DEVNODES_CHANGED)
|
||||
g_WantUpdateHasGamepad = true;
|
||||
bd->WantUpdateHasGamepad = true;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user