1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-11-28 01:20:55 +01:00

Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_win32.cpp
This commit is contained in:
ocornut 2024-10-28 17:27:38 +01:00
commit 9d6ec825cb
8 changed files with 82 additions and 68 deletions

View File

@ -905,13 +905,15 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
// Create shaders // Create shaders
const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader }; const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER); GLuint vert_handle;
GL_CALL(vert_handle = glCreateShader(GL_VERTEX_SHADER));
glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr); glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr);
glCompileShader(vert_handle); glCompileShader(vert_handle);
CheckShader(vert_handle, "vertex shader"); CheckShader(vert_handle, "vertex shader");
const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader }; const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER); GLuint frag_handle;
GL_CALL(frag_handle = glCreateShader(GL_FRAGMENT_SHADER));
glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr); glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr);
glCompileShader(frag_handle); glCompileShader(frag_handle);
CheckShader(frag_handle, "fragment shader"); CheckShader(frag_handle, "fragment shader");

View File

@ -143,12 +143,16 @@ static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData()
{ {
return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
} }
static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData(ImGuiIO& io)
{
return (ImGui_ImplWin32_Data*)io.BackendPlatformUserData;
}
// Functions // Functions
static void ImGui_ImplWin32_UpdateKeyboardCodePage() static void ImGui_ImplWin32_UpdateKeyboardCodePage(ImGuiIO& io)
{ {
// Retrieve keyboard code page, required for handling of non-Unicode Windows. // Retrieve keyboard code page, required for handling of non-Unicode Windows.
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
HKL keyboard_layout = ::GetKeyboardLayout(0); HKL keyboard_layout = ::GetKeyboardLayout(0);
LCID keyboard_lcid = MAKELCID(HIWORD(keyboard_layout), SORT_DEFAULT); LCID keyboard_lcid = MAKELCID(HIWORD(keyboard_layout), SORT_DEFAULT);
if (::GetLocaleInfoA(keyboard_lcid, (LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE), (LPSTR)&bd->KeyboardCodePage, sizeof(bd->KeyboardCodePage)) == 0) if (::GetLocaleInfoA(keyboard_lcid, (LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE), (LPSTR)&bd->KeyboardCodePage, sizeof(bd->KeyboardCodePage)) == 0)
@ -180,7 +184,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
bd->TicksPerSecond = perf_frequency; bd->TicksPerSecond = perf_frequency;
bd->Time = perf_counter; bd->Time = perf_counter;
bd->LastMouseCursor = ImGuiMouseCursor_COUNT; bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
ImGui_ImplWin32_UpdateKeyboardCodePage(); ImGui_ImplWin32_UpdateKeyboardCodePage(io);
// Update monitor a first time during init // Update monitor a first time during init
ImGui_ImplWin32_UpdateMonitors(); ImGui_ImplWin32_UpdateMonitors();
@ -249,13 +253,11 @@ void ImGui_ImplWin32_Shutdown()
IM_DELETE(bd); IM_DELETE(bd);
} }
static bool ImGui_ImplWin32_UpdateMouseCursor() static bool ImGui_ImplWin32_UpdateMouseCursor(ImGuiIO& io, ImGuiMouseCursor imgui_cursor)
{ {
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return false; return false;
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
{ {
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
@ -287,32 +289,30 @@ static bool IsVkDown(int vk)
return (::GetKeyState(vk) & 0x8000) != 0; return (::GetKeyState(vk) & 0x8000) != 0;
} }
static void ImGui_ImplWin32_AddKeyEvent(ImGuiKey key, bool down, int native_keycode, int native_scancode = -1) static void ImGui_ImplWin32_AddKeyEvent(ImGuiIO& io, ImGuiKey key, bool down, int native_keycode, int native_scancode = -1)
{ {
ImGuiIO& io = ImGui::GetIO();
io.AddKeyEvent(key, down); io.AddKeyEvent(key, down);
io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To support legacy indexing (<1.87 user code) io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To support legacy indexing (<1.87 user code)
IM_UNUSED(native_scancode); IM_UNUSED(native_scancode);
} }
static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds() static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds(ImGuiIO& io)
{ {
// Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one. // Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one.
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && !IsVkDown(VK_LSHIFT)) if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && !IsVkDown(VK_LSHIFT))
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, false, VK_LSHIFT); ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftShift, false, VK_LSHIFT);
if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT)) if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT))
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, false, VK_RSHIFT); ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightShift, false, VK_RSHIFT);
// Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Win+V on some setups, according to GLFW). // Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Win+V on some setups, according to GLFW).
if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN)) if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN))
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftSuper, false, VK_LWIN); ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftSuper, false, VK_LWIN);
if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN)) if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN))
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightSuper, false, VK_RWIN); ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightSuper, false, VK_RWIN);
} }
static void ImGui_ImplWin32_UpdateKeyModifiers() static void ImGui_ImplWin32_UpdateKeyModifiers(ImGuiIO& io)
{ {
ImGuiIO& io = ImGui::GetIO();
io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL)); io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL));
io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT)); io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT));
io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU)); io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU));
@ -329,10 +329,9 @@ static ImGuiViewport* ImGui_ImplWin32_FindViewportByPlatformHandle(HWND hwnd)
// 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() static void ImGui_ImplWin32_UpdateMouseData(ImGuiIO& io)
{ {
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(bd->hWnd != 0); IM_ASSERT(bd->hWnd != 0);
POINT mouse_screen_pos; POINT mouse_screen_pos;
@ -383,11 +382,10 @@ static void ImGui_ImplWin32_UpdateMouseData()
} }
// Gamepad navigation mapping // Gamepad navigation mapping
static void ImGui_ImplWin32_UpdateGamepads() static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
{ {
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
ImGuiIO& io = ImGui::GetIO(); ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
//if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. //if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
// return; // return;
@ -436,7 +434,9 @@ static void ImGui_ImplWin32_UpdateGamepads()
MAP_ANALOG(ImGuiKey_GamepadRStickDown, gamepad.sThumbRY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); MAP_ANALOG(ImGuiKey_GamepadRStickDown, gamepad.sThumbRY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
#undef MAP_BUTTON #undef MAP_BUTTON
#undef MAP_ANALOG #undef MAP_ANALOG
#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD #else // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
IM_UNUSED(io);
#endif
} }
static BOOL CALLBACK ImGui_ImplWin32_UpdateMonitors_EnumFunc(HMONITOR monitor, HDC, LPRECT, LPARAM) static BOOL CALLBACK ImGui_ImplWin32_UpdateMonitors_EnumFunc(HMONITOR monitor, HDC, LPRECT, LPARAM)
@ -490,21 +490,21 @@ void ImGui_ImplWin32_NewFrame()
bd->Time = current_time; bd->Time = current_time;
// Update OS mouse position // Update OS mouse position
ImGui_ImplWin32_UpdateMouseData(); ImGui_ImplWin32_UpdateMouseData(io);
// Process workarounds for known Windows key handling issues // Process workarounds for known Windows key handling issues
ImGui_ImplWin32_ProcessKeyEventsWorkarounds(); ImGui_ImplWin32_ProcessKeyEventsWorkarounds(io);
// 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();
if (bd->LastMouseCursor != mouse_cursor) if (bd->LastMouseCursor != mouse_cursor)
{ {
bd->LastMouseCursor = mouse_cursor; bd->LastMouseCursor = mouse_cursor;
ImGui_ImplWin32_UpdateMouseCursor(); ImGui_ImplWin32_UpdateMouseCursor(io, mouse_cursor);
} }
// Update game controllers (if enabled and available) // Update game controllers (if enabled and available)
ImGui_ImplWin32_UpdateGamepads(); ImGui_ImplWin32_UpdateGamepads(io);
} }
// Map VK_xxx to ImGuiKey_xxx. // Map VK_xxx to ImGuiKey_xxx.
@ -647,22 +647,10 @@ ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam)
#define DBT_DEVNODES_CHANGED 0x0007 #define DBT_DEVNODES_CHANGED 0x0007
#endif #endif
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.) // Helper to obtain the source of mouse messages.
// Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags.
// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
#if 0
// 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);
#endif
// See https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages // 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. // 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() static ImGuiMouseSource ImGui_ImplWin32_GetMouseSourceFromMessageExtraInfo()
{ {
LPARAM extra_info = ::GetMessageExtraInfo(); LPARAM extra_info = ::GetMessageExtraInfo();
if ((extra_info & 0xFFFFFF80) == 0xFF515700) if ((extra_info & 0xFFFFFF80) == 0xFF515700)
@ -672,22 +660,40 @@ static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
return ImGuiMouseSource_Mouse; return ImGuiMouseSource_Mouse;
} }
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
// Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags.
// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
// Copy either 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); // Use ImGui::GetCurrentContext()
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, ImGuiIO& io); // Doesn't use ImGui::GetCurrentContext()
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)
{ {
// Most backends don't have silent checks like this one, but we need it because WndProc are called early in CreateWindow(). // Most backends don't have silent checks like this one, but we need it because WndProc are called early in CreateWindow().
// We silently allow both context or just only backend data to be nullptr. // We silently allow both context or just only backend data to be nullptr.
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); if (ImGui::GetCurrentContext() == NULL)
if (bd == nullptr)
return 0; return 0;
ImGuiIO& io = ImGui::GetIO(); return ImGui_ImplWin32_WndProcHandlerEx(hwnd, msg, wParam, lParam, ImGui::GetIO());
}
// This version is in theory thread-safe in the sense that no path should access ImGui::GetCurrentContext().
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ImGuiIO& io)
{
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
if (bd == NULL)
return 0;
switch (msg) switch (msg)
{ {
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
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(); ImGuiMouseSource mouse_source = ImGui_ImplWin32_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)
@ -737,14 +743,14 @@ 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(); ImGuiMouseSource mouse_source = ImGui_ImplWin32_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; }
if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr) if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr)
::SetCapture(hwnd); ::SetCapture(hwnd); // Allow us to read mouse coordinates when dragging mouse outside of our window bounds.
bd->MouseButtonsDown |= 1 << button; bd->MouseButtonsDown |= 1 << button;
io.AddMouseSourceEvent(mouse_source); io.AddMouseSourceEvent(mouse_source);
io.AddMouseButtonEvent(button, true); io.AddMouseButtonEvent(button, true);
@ -755,7 +761,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(); ImGuiMouseSource mouse_source = ImGui_ImplWin32_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; }
@ -783,7 +789,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
if (wParam < 256) if (wParam < 256)
{ {
// Submit modifiers // Submit modifiers
ImGui_ImplWin32_UpdateKeyModifiers(); ImGui_ImplWin32_UpdateKeyModifiers(io);
// Obtain virtual key code and convert to ImGuiKey // Obtain virtual key code and convert to ImGuiKey
const ImGuiKey key = ImGui_ImplWin32_KeyEventToImGuiKey(wParam, lParam); const ImGuiKey key = ImGui_ImplWin32_KeyEventToImGuiKey(wParam, lParam);
@ -792,28 +798,28 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
// Special behavior for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit the key down event. // Special behavior for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit the key down event.
if (key == ImGuiKey_PrintScreen && !is_key_down) if (key == ImGuiKey_PrintScreen && !is_key_down)
ImGui_ImplWin32_AddKeyEvent(key, true, vk, scancode); ImGui_ImplWin32_AddKeyEvent(io, key, true, vk, scancode);
// Submit key event // Submit key event
if (key != ImGuiKey_None) if (key != ImGuiKey_None)
ImGui_ImplWin32_AddKeyEvent(key, is_key_down, vk, scancode); ImGui_ImplWin32_AddKeyEvent(io, key, is_key_down, vk, scancode);
// Submit individual left/right modifier events // Submit individual left/right modifier events
if (vk == VK_SHIFT) if (vk == VK_SHIFT)
{ {
// Important: Shift keys tend to get stuck when pressed together, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkarounds() // Important: Shift keys tend to get stuck when pressed together, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkarounds()
if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); } if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); }
if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); } if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); }
} }
else if (vk == VK_CONTROL) else if (vk == VK_CONTROL)
{ {
if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); } if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); }
if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); } if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); }
} }
else if (vk == VK_MENU) else if (vk == VK_MENU)
{ {
if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); } if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); }
if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); } if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); }
} }
} }
return 0; return 0;
@ -823,7 +829,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
io.AddFocusEvent(msg == WM_SETFOCUS); io.AddFocusEvent(msg == WM_SETFOCUS);
return 0; return 0;
case WM_INPUTLANGCHANGE: case WM_INPUTLANGCHANGE:
ImGui_ImplWin32_UpdateKeyboardCodePage(); ImGui_ImplWin32_UpdateKeyboardCodePage(io);
return 0; return 0;
case WM_CHAR: case WM_CHAR:
if (::IsWindowUnicode(hwnd)) if (::IsWindowUnicode(hwnd))
@ -841,7 +847,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
return 0; return 0;
case WM_SETCURSOR: case WM_SETCURSOR:
// This is required to restore cursor when transitioning from e.g resize borders to client area. // This is required to restore cursor when transitioning from e.g resize borders to client area.
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor(io, bd->LastMouseCursor))
return 1; return 1;
return 0; return 0;
case WM_DEVICECHANGE: case WM_DEVICECHANGE:

View File

@ -43,6 +43,8 @@ Breaking changes:
Other changes: Other changes:
- Selectable: selected Selectables use ImGuiCol_Header instead of an arbitrary lerp
between _Header and _HeaderHovered which was introduced v1.91 (#8106, #1861)
- Backends: DX12: Unmap() call specify written range. The range is informational and - Backends: DX12: Unmap() call specify written range. The range is informational and
may be used by debug tools. may be used by debug tools.
- Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the - Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the

View File

@ -4855,6 +4855,13 @@ ImGuiIO& ImGui::GetIO()
return GImGui->IO; return GImGui->IO;
} }
// This variant exists to facilitate backends experimenting with multi-threaded parallel context. (#8069, #6293, #5856)
ImGuiIO& ImGui::GetIOEx(ImGuiContext* ctx)
{
IM_ASSERT(ctx != NULL);
return ctx->IO;
}
ImGuiPlatformIO& ImGui::GetPlatformIO() ImGuiPlatformIO& ImGui::GetPlatformIO()
{ {
IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext()?"); IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext()?");

View File

@ -2326,7 +2326,7 @@ struct ImGuiIO
// Keyboard/Gamepad Navigation options // Keyboard/Gamepad Navigation options
bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout. bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
bool ConfigNavMoveSetMousePos; // = false // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. bool ConfigNavMoveSetMousePos; // = false // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true.
bool ConfigNavCaptureKeyboard; // = true // Sets io.WantCaptureKeyboard when io.NavActive is set. bool ConfigNavCaptureKeyboard; // = true // Sets io.WantCaptureKeyboard when io.NavActive is set.
bool ConfigNavEscapeClearFocusItem; // = true // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on. bool ConfigNavEscapeClearFocusItem; // = true // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on.
bool ConfigNavEscapeClearFocusWindow;// = false // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem). bool ConfigNavEscapeClearFocusWindow;// = false // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem).

View File

@ -10518,7 +10518,7 @@ struct ExampleAssetsBrowser
// Rendering parameters // Rendering parameters
const ImU32 icon_type_overlay_colors[3] = { 0, IM_COL32(200, 70, 70, 255), IM_COL32(70, 170, 70, 255) }; const ImU32 icon_type_overlay_colors[3] = { 0, IM_COL32(200, 70, 70, 255), IM_COL32(70, 170, 70, 255) };
const ImU32 icon_bg_color = ImGui::GetColorU32(ImGuiCol_MenuBarBg); const ImU32 icon_bg_color = ImGui::GetColorU32(IM_COL32(35, 35, 35, 220));
const ImVec2 icon_type_overlay_size = ImVec2(4.0f, 4.0f); const ImVec2 icon_type_overlay_size = ImVec2(4.0f, 4.0f);
const bool display_label = (LayoutItemSize.x >= ImGui::CalcTextSize("999").x); const bool display_label = (LayoutItemSize.x >= ImGui::CalcTextSize("999").x);

View File

@ -3171,6 +3171,7 @@ 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);
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);

View File

@ -7024,12 +7024,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
const bool highlighted = hovered || (flags & ImGuiSelectableFlags_Highlight); const bool highlighted = hovered || (flags & ImGuiSelectableFlags_Highlight);
if (highlighted || selected) if (highlighted || selected)
{ {
// FIXME-MULTISELECT: Styling: Color for 'selected' elements? ImGuiCol_HeaderSelected // Between 1.91.0 and 1.91.4 we made selected Selectable use an arbitrary lerp between _Header and _HeaderHovered. Removed that now. (#8106)
ImU32 col; ImU32 col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
if (selected && !highlighted)
col = GetColorU32(ImLerp(GetStyleColorVec4(ImGuiCol_Header), GetStyleColorVec4(ImGuiCol_HeaderHovered), 0.5f));
else
col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
RenderFrame(bb.Min, bb.Max, col, false, 0.0f); RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
} }
if (g.NavId == id) if (g.NavId == id)