imgui_impl_win32.cpp (imgui-1.86) | : | imgui_impl_win32.cpp (imgui-1.87) | ||
---|---|---|---|---|
// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) | // dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) | |||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan. .) | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan. .) | |||
// Implemented features: | // Implemented features: | |||
// [X] Platform: Clipboard support (for Win32 this is actually part of core dea r imgui) | // [X] Platform: Clipboard support (for Win32 this is actually part of core dea r imgui) | |||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlag | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() | |||
s |= ImGuiConfigFlags_NoMouseCursorChange'. | function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(Im | |||
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImG | GuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_O | |||
ui::IsKeyPressed(VK_SPACE). | BSOLETE_KEYIO is set] | |||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFl ags_NavEnableGamepad'. | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFl ags_NavEnableGamepad'. | |||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlag s |= ImGuiConfigFlags_NoMouseCursorChange'. | ||||
// You can use unmodified imgui_impl_* files in your project. See examples/ fold er for examples of using this. | // You can use unmodified imgui_impl_* files in your project. See examples/ fold er for examples of using this. | |||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | |||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | |||
// Read online: https://github.com/ocornut/imgui/tree/master/docs | // Read online: https://github.com/ocornut/imgui/tree/master/docs | |||
#include "imgui.h" | #include "imgui.h" | |||
#include "imgui_impl_win32.h" | #include "imgui_impl_win32.h" | |||
#ifndef WIN32_LEAN_AND_MEAN | #ifndef WIN32_LEAN_AND_MEAN | |||
#define WIN32_LEAN_AND_MEAN | #define WIN32_LEAN_AND_MEAN | |||
#endif | #endif | |||
#include <windows.h> | #include <windows.h> | |||
#include <windowsx.h> // GET_X_LPARAM(), GET_Y_LPARAM() | ||||
#include <tchar.h> | #include <tchar.h> | |||
#include <dwmapi.h> | #include <dwmapi.h> | |||
// Configuration flags to add in your imconfig.h file: | // Configuration flags to add in your imconfig.h file: | |||
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad suppo rt. This was meaningful before <1.81 but we now load XInput dynamically so the o ption is now less relevant. | //#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad suppo rt. This was meaningful before <1.81 but we now load XInput dynamically so the o ption is now less relevant. | |||
// Using XInput for gamepad (will load DLL dynamically) | // Using XInput for gamepad (will load DLL dynamically) | |||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | |||
#include <xinput.h> | #include <xinput.h> | |||
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILIT IES*); | typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILIT IES*); | |||
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); | typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); | |||
#endif | #endif | |||
// 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) | |||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two wee | ||||
ks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusio | ||||
n. | ||||
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, | ||||
instead of writing directly to io.NavInputs[]. | ||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEven | ||||
t(), io.AddMouseWheelEvent() API (1.87+). | ||||
// 2022-01-17: Inputs: always update key mods next and before a key event (not | ||||
in NewFrame) to fix input queue with very low framerates. | ||||
// 2022-01-12: Inputs: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + f | ||||
allback to provide it when focused but not hovered/captured. More standard and w | ||||
ill allow us to pass it to future input queue API. | ||||
// 2022-01-12: Inputs: Maintain our own copy of MouseButtonsDown mask instead o | ||||
f using ImGui::IsAnyMouseDown() which will be obsoleted. | ||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io. | ||||
SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. | ||||
// 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMEN U/VK_RMENU for completeness. | // 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMEN U/VK_RMENU for completeness. | |||
// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages. | // 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages. | |||
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus. | // 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus. | |||
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform wi ndow is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAV E events). | // 2021-07-29: Inputs: MousePos is correctly reported when the host platform wi ndow is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAV E events). | |||
// 2021-06-29: Reorganized backend to pull data from a single structure to faci litate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). | // 2021-06-29: Reorganized backend to pull data from a single structure to faci litate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). | |||
// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_G etDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per -monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1). | // 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_G etDpiScaleForMonitor() 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_KILLF OCUS). | // 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLF OCUS). | |||
// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studi o users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). | // 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studi o users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). | |||
// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get Set ProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1. | // 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get Set ProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1. | |||
// 2021-01-25: Inputs: Dynamically loading XInput DLL. | // 2021-01-25: Inputs: Dynamically loading XInput DLL. | |||
skipping to change at line 76 | skipping to change at line 84 | |||
// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. | // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. | |||
// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the V K_MENU key can be read. | // 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the V K_MENU key can be read. | |||
// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mous e positions outside the client area when dragging. | // 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mous e positions outside the client area when dragging. | |||
// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCurso r is set. | // 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCurso r is set. | |||
struct ImGui_ImplWin32_Data | struct ImGui_ImplWin32_Data | |||
{ | { | |||
HWND hWnd; | HWND hWnd; | |||
HWND MouseHwnd; | HWND MouseHwnd; | |||
bool MouseTracked; | bool MouseTracked; | |||
int MouseButtonsDown; | ||||
INT64 Time; | INT64 Time; | |||
INT64 TicksPerSecond; | INT64 TicksPerSecond; | |||
ImGuiMouseCursor LastMouseCursor; | ImGuiMouseCursor LastMouseCursor; | |||
bool HasGamepad; | bool HasGamepad; | |||
bool WantUpdateHasGamepad; | bool WantUpdateHasGamepad; | |||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | |||
HMODULE XInputDLL; | HMODULE XInputDLL; | |||
PFN_XInputGetCapabilities XInputGetCapabilities; | PFN_XInputGetCapabilities XInputGetCapabilities; | |||
PFN_XInputGetState XInputGetState; | PFN_XInputGetState XInputGetState; | |||
skipping to change at line 125 | skipping to change at line 134 | |||
io.BackendPlatformName = "imgui_impl_win32"; | io.BackendPlatformName = "imgui_impl_win32"; | |||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can hono r GetMouseCursor() values (optional) | io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can hono r GetMouseCursor() values (optional) | |||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can hono r io.WantSetMousePos requests (optional, rarely used) | io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can hono r io.WantSetMousePos requests (optional, rarely used) | |||
bd->hWnd = (HWND)hwnd; | bd->hWnd = (HWND)hwnd; | |||
bd->WantUpdateHasGamepad = true; | bd->WantUpdateHasGamepad = true; | |||
bd->TicksPerSecond = perf_frequency; | bd->TicksPerSecond = perf_frequency; | |||
bd->Time = perf_counter; | bd->Time = perf_counter; | |||
bd->LastMouseCursor = ImGuiMouseCursor_COUNT; | bd->LastMouseCursor = ImGuiMouseCursor_COUNT; | |||
io.ImeWindowHandle = hwnd; | // Set platform dependent data in viewport | |||
ImGui::GetMainViewport()->PlatformHandleRaw = (void*)hwnd; | ||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.K | ||||
eysDown[] array that we will update during the application lifetime. | ||||
io.KeyMap[ImGuiKey_Tab] = VK_TAB; | ||||
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; | ||||
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; | ||||
io.KeyMap[ImGuiKey_UpArrow] = VK_UP; | ||||
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; | ||||
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; | ||||
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; | ||||
io.KeyMap[ImGuiKey_Home] = VK_HOME; | ||||
io.KeyMap[ImGuiKey_End] = VK_END; | ||||
io.KeyMap[ImGuiKey_Insert] = VK_INSERT; | ||||
io.KeyMap[ImGuiKey_Delete] = VK_DELETE; | ||||
io.KeyMap[ImGuiKey_Backspace] = VK_BACK; | ||||
io.KeyMap[ImGuiKey_Space] = VK_SPACE; | ||||
io.KeyMap[ImGuiKey_Enter] = VK_RETURN; | ||||
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; | ||||
io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN; | ||||
io.KeyMap[ImGuiKey_A] = 'A'; | ||||
io.KeyMap[ImGuiKey_C] = 'C'; | ||||
io.KeyMap[ImGuiKey_V] = 'V'; | ||||
io.KeyMap[ImGuiKey_X] = 'X'; | ||||
io.KeyMap[ImGuiKey_Y] = 'Y'; | ||||
io.KeyMap[ImGuiKey_Z] = 'Z'; | ||||
// Dynamically load XInput library | // Dynamically load XInput library | |||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | |||
const char* xinput_dll_names[] = | const char* xinput_dll_names[] = | |||
{ | { | |||
"xinput1_4.dll", // Windows 8+ | "xinput1_4.dll", // Windows 8+ | |||
"xinput1_3.dll", // DirectX SDK | "xinput1_3.dll", // DirectX SDK | |||
"xinput9_1_0.dll", // Windows Vista, Windows 7 | "xinput9_1_0.dll", // Windows Vista, Windows 7 | |||
"xinput1_2.dll", // DirectX SDK | "xinput1_2.dll", // DirectX SDK | |||
"xinput1_1.dll" // DirectX SDK | "xinput1_1.dll" // DirectX SDK | |||
skipping to change at line 224 | skipping to change at line 210 | |||
case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; | case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; | |||
case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; | case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; | |||
case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; | case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; | |||
case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; | case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; | |||
} | } | |||
::SetCursor(::LoadCursor(NULL, win32_cursor)); | ::SetCursor(::LoadCursor(NULL, win32_cursor)); | |||
} | } | |||
return true; | return true; | |||
} | } | |||
static void ImGui_ImplWin32_UpdateMousePos() | static bool IsVkDown(int vk) | |||
{ | ||||
return (::GetKeyState(vk) & 0x8000) != 0; | ||||
} | ||||
static void ImGui_ImplWin32_AddKeyEvent(ImGuiKey key, bool down, int native_keyc | ||||
ode, int native_scancode = -1) | ||||
{ | { | |||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | ||||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
IM_ASSERT(bd->hWnd != 0); | io.AddKeyEvent(key, down); | |||
io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To suppor | ||||
t legacy indexing (<1.87 user code) | ||||
IM_UNUSED(native_scancode); | ||||
} | ||||
const ImVec2 mouse_pos_prev = io.MousePos; | static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds() | |||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); | { | |||
// 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)) | ||||
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, false, VK_LSHIFT); | ||||
if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT)) | ||||
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, false, VK_RSHIFT); | ||||
// Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Wi | ||||
n+V on some setups, according to GLFW). | ||||
if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN)) | ||||
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftSuper, false, VK_LWIN); | ||||
if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN)) | ||||
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightSuper, false, VK_RWIN); | ||||
} | ||||
// Obtain focused and hovered window. We forward mouse input when focused or | static void ImGui_ImplWin32_UpdateKeyModifiers() | |||
when hovered (and no other window is capturing) | { | |||
HWND focused_window = ::GetForegroundWindow(); | ImGuiIO& io = ImGui::GetIO(); | |||
HWND hovered_window = bd->MouseHwnd; | io.AddKeyEvent(ImGuiKey_ModCtrl, IsVkDown(VK_CONTROL)); | |||
HWND mouse_window = NULL; | io.AddKeyEvent(ImGuiKey_ModShift, IsVkDown(VK_SHIFT)); | |||
if (hovered_window && (hovered_window == bd->hWnd || ::IsChild(hovered_windo | io.AddKeyEvent(ImGuiKey_ModAlt, IsVkDown(VK_MENU)); | |||
w, bd->hWnd))) | io.AddKeyEvent(ImGuiKey_ModSuper, IsVkDown(VK_APPS)); | |||
mouse_window = hovered_window; | } | |||
else if (focused_window && (focused_window == bd->hWnd || ::IsChild(focused_ | ||||
window, bd->hWnd))) | static void ImGui_ImplWin32_UpdateMouseData() | |||
mouse_window = focused_window; | { | |||
if (mouse_window == NULL) | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | |||
return; | ImGuiIO& io = ImGui::GetIO(); | |||
IM_ASSERT(bd->hWnd != 0); | ||||
// Set OS mouse position from Dear ImGui if requested (rarely used, only whe | const bool is_app_focused = (::GetForegroundWindow() == bd->hWnd); | |||
n ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) | if (is_app_focused) | |||
if (io.WantSetMousePos) | ||||
{ | { | |||
POINT pos = { (int)mouse_pos_prev.x, (int)mouse_pos_prev.y }; | // (Optional) Set OS mouse position from Dear ImGui if requested (rarely | |||
if (::ClientToScreen(bd->hWnd, &pos)) | used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) | |||
::SetCursorPos(pos.x, pos.y); | if (io.WantSetMousePos) | |||
} | { | |||
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; | ||||
if (::ClientToScreen(bd->hWnd, &pos)) | ||||
::SetCursorPos(pos.x, pos.y); | ||||
} | ||||
// Set Dear ImGui mouse position from OS position | // (Optional) Fallback to provide mouse position when focused (WM_MOUSEM | |||
POINT pos; | OVE already provides this when hovered or captured) | |||
if (::GetCursorPos(&pos) && ::ScreenToClient(mouse_window, &pos)) | if (!io.WantSetMousePos && !bd->MouseTracked) | |||
io.MousePos = ImVec2((float)pos.x, (float)pos.y); | { | |||
POINT pos; | ||||
if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos)) | ||||
io.AddMousePosEvent((float)pos.x, (float)pos.y); | ||||
} | ||||
} | ||||
} | } | |||
// Gamepad navigation mapping | // Gamepad navigation mapping | |||
static void ImGui_ImplWin32_UpdateGamepads() | static void ImGui_ImplWin32_UpdateGamepads() | |||
{ | { | |||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | |||
memset(io.NavInputs, 0, sizeof(io.NavInputs)); | ||||
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) | if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) | |||
return; | return; | |||
// Calling XInputGetState() every frame on disconnected gamepads is unfortun ately too slow. | // Calling XInputGetState() every frame on disconnected gamepads is unfortun ately too slow. | |||
// Instead we refresh gamepad availability by calling XInputGetCapabilities( ) _only_ after receiving WM_DEVICECHANGE. | // Instead we refresh gamepad availability by calling XInputGetCapabilities( ) _only_ after receiving WM_DEVICECHANGE. | |||
if (bd->WantUpdateHasGamepad) | if (bd->WantUpdateHasGamepad) | |||
{ | { | |||
XINPUT_CAPABILITIES caps; | XINPUT_CAPABILITIES caps = {}; | |||
bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities( 0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; | bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities( 0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; | |||
bd->WantUpdateHasGamepad = false; | bd->WantUpdateHasGamepad = false; | |||
} | } | |||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; | io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; | |||
XINPUT_STATE xinput_state; | XINPUT_STATE xinput_state; | |||
if (bd->HasGamepad && bd->XInputGetState && bd->XInputGetState(0, &xinput_st | XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; | |||
ate) == ERROR_SUCCESS) | if (!bd->HasGamepad || bd->XInputGetState == NULL || bd->XInputGetState(0, & | |||
{ | xinput_state) != ERROR_SUCCESS) | |||
const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; | return; | |||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad; | io.BackendFlags |= ImGuiBackendFlags_HasGamepad; | |||
#define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (ga | #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1. | |||
mepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; } | 0f : V) | |||
#define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - | #define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepa | |||
V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs | d.wButtons & BUTTON_ENUM) != 0); } | |||
[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; } | #define MAP_ANALOG(KEY_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) | |||
MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); | / (float)(V1 - V0); io.AddKeyAnalogEvent(KEY_NO, vn > 0.10f, IM_SATURATE(vn)); | |||
// Cross / A | } | |||
MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); | MAP_BUTTON(ImGuiKey_GamepadStart, XINPUT_GAMEPAD_START); | |||
// Circle / B | MAP_BUTTON(ImGuiKey_GamepadBack, XINPUT_GAMEPAD_BACK); | |||
MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); | MAP_BUTTON(ImGuiKey_GamepadFaceDown, XINPUT_GAMEPAD_A); | |||
// Square / X | MAP_BUTTON(ImGuiKey_GamepadFaceRight, XINPUT_GAMEPAD_B); | |||
MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); | MAP_BUTTON(ImGuiKey_GamepadFaceLeft, XINPUT_GAMEPAD_X); | |||
// Triangle / Y | MAP_BUTTON(ImGuiKey_GamepadFaceUp, XINPUT_GAMEPAD_Y); | |||
MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); | MAP_BUTTON(ImGuiKey_GamepadDpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); | |||
// D-Pad Left | MAP_BUTTON(ImGuiKey_GamepadDpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); | |||
MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); | MAP_BUTTON(ImGuiKey_GamepadDpadUp, XINPUT_GAMEPAD_DPAD_UP); | |||
// D-Pad Right | MAP_BUTTON(ImGuiKey_GamepadDpadDown, XINPUT_GAMEPAD_DPAD_DOWN); | |||
MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); | MAP_BUTTON(ImGuiKey_GamepadL1, XINPUT_GAMEPAD_LEFT_SHOULDER); | |||
// D-Pad Up | MAP_BUTTON(ImGuiKey_GamepadR1, XINPUT_GAMEPAD_RIGHT_SHOULDER); | |||
MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); | MAP_ANALOG(ImGuiKey_GamepadL2, gamepad.bLeftTrigger, XINPUT_GAM | |||
// D-Pad Down | EPAD_TRIGGER_THRESHOLD, 255); | |||
MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); | MAP_ANALOG(ImGuiKey_GamepadR2, gamepad.bRightTrigger, XINPUT_GA | |||
// L1 / LB | MEPAD_TRIGGER_THRESHOLD, 255); | |||
MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); | MAP_BUTTON(ImGuiKey_GamepadL3, XINPUT_GAMEPAD_LEFT_THUMB); | |||
// R1 / RB | MAP_BUTTON(ImGuiKey_GamepadR3, XINPUT_GAMEPAD_RIGHT_THUMB); | |||
MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); | MAP_ANALOG(ImGuiKey_GamepadLStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPA | |||
// L1 / LB | D_LEFT_THUMB_DEADZONE, -32768); | |||
MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); | MAP_ANALOG(ImGuiKey_GamepadLStickRight, gamepad.sThumbLX, +XINPUT_GAMEPA | |||
// R1 / RB | D_LEFT_THUMB_DEADZONE, +32767); | |||
MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEP | MAP_ANALOG(ImGuiKey_GamepadLStickUp, gamepad.sThumbLY, +XINPUT_GAMEPA | |||
AD_LEFT_THUMB_DEADZONE, -32768); | D_LEFT_THUMB_DEADZONE, +32767); | |||
MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEP | MAP_ANALOG(ImGuiKey_GamepadLStickDown, gamepad.sThumbLY, -XINPUT_GAMEPA | |||
AD_LEFT_THUMB_DEADZONE, +32767); | D_LEFT_THUMB_DEADZONE, -32768); | |||
MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEP | MAP_ANALOG(ImGuiKey_GamepadRStickLeft, gamepad.sThumbRX, -XINPUT_GAMEPA | |||
AD_LEFT_THUMB_DEADZONE, +32767); | D_LEFT_THUMB_DEADZONE, -32768); | |||
MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEP | MAP_ANALOG(ImGuiKey_GamepadRStickRight, gamepad.sThumbRX, +XINPUT_GAMEPA | |||
AD_LEFT_THUMB_DEADZONE, -32767); | D_LEFT_THUMB_DEADZONE, +32767); | |||
#undef MAP_BUTTON | MAP_ANALOG(ImGuiKey_GamepadRStickUp, gamepad.sThumbRY, +XINPUT_GAMEPA | |||
#undef MAP_ANALOG | D_LEFT_THUMB_DEADZONE, +32767); | |||
} | MAP_ANALOG(ImGuiKey_GamepadRStickDown, gamepad.sThumbRY, -XINPUT_GAMEPA | |||
D_LEFT_THUMB_DEADZONE, -32768); | ||||
#undef MAP_BUTTON | ||||
#undef MAP_ANALOG | ||||
#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | |||
} | } | |||
void ImGui_ImplWin32_NewFrame() | void ImGui_ImplWin32_NewFrame() | |||
{ | { | |||
ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | |||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | |||
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplWin32_Init()?"); | IM_ASSERT(bd != NULL && "Did you call ImGui_ImplWin32_Init()?"); | |||
// Setup display size (every frame to accommodate for window resizing) | // Setup display size (every frame to accommodate for window resizing) | |||
skipping to change at line 326 | skipping to change at line 349 | |||
::GetClientRect(bd->hWnd, &rect); | ::GetClientRect(bd->hWnd, &rect); | |||
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); | |||
// Setup time step | // Setup time step | |||
INT64 current_time = 0; | INT64 current_time = 0; | |||
::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); | ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); | |||
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond; | io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond; | |||
bd->Time = current_time; | bd->Time = current_time; | |||
// Update OS mouse position | // Update OS mouse position | |||
ImGui_ImplWin32_UpdateMousePos(); | ImGui_ImplWin32_UpdateMouseData(); | |||
// Process workarounds for known Windows key handling issues | ||||
ImGui_ImplWin32_ProcessKeyEventsWorkarounds(); | ||||
// 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(); | |||
} | } | |||
// Update game controllers (if enabled and available) | // Update game controllers (if enabled and available) | |||
ImGui_ImplWin32_UpdateGamepads(); | ImGui_ImplWin32_UpdateGamepads(); | |||
} | } | |||
// There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EX | ||||
TENDED, we assign it an arbitrary value to make code more readable (VK_ codes go | ||||
up to 255) | ||||
#define IM_VK_KEYPAD_ENTER (VK_RETURN + 256) | ||||
// Map VK_xxx to ImGuiKey_xxx. | ||||
static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam) | ||||
{ | ||||
switch (wParam) | ||||
{ | ||||
case VK_TAB: return ImGuiKey_Tab; | ||||
case VK_LEFT: return ImGuiKey_LeftArrow; | ||||
case VK_RIGHT: return ImGuiKey_RightArrow; | ||||
case VK_UP: return ImGuiKey_UpArrow; | ||||
case VK_DOWN: return ImGuiKey_DownArrow; | ||||
case VK_PRIOR: return ImGuiKey_PageUp; | ||||
case VK_NEXT: return ImGuiKey_PageDown; | ||||
case VK_HOME: return ImGuiKey_Home; | ||||
case VK_END: return ImGuiKey_End; | ||||
case VK_INSERT: return ImGuiKey_Insert; | ||||
case VK_DELETE: return ImGuiKey_Delete; | ||||
case VK_BACK: return ImGuiKey_Backspace; | ||||
case VK_SPACE: return ImGuiKey_Space; | ||||
case VK_RETURN: return ImGuiKey_Enter; | ||||
case VK_ESCAPE: return ImGuiKey_Escape; | ||||
case VK_OEM_7: return ImGuiKey_Apostrophe; | ||||
case VK_OEM_COMMA: return ImGuiKey_Comma; | ||||
case VK_OEM_MINUS: return ImGuiKey_Minus; | ||||
case VK_OEM_PERIOD: return ImGuiKey_Period; | ||||
case VK_OEM_2: return ImGuiKey_Slash; | ||||
case VK_OEM_1: return ImGuiKey_Semicolon; | ||||
case VK_OEM_PLUS: return ImGuiKey_Equal; | ||||
case VK_OEM_4: return ImGuiKey_LeftBracket; | ||||
case VK_OEM_5: return ImGuiKey_Backslash; | ||||
case VK_OEM_6: return ImGuiKey_RightBracket; | ||||
case VK_OEM_3: return ImGuiKey_GraveAccent; | ||||
case VK_CAPITAL: return ImGuiKey_CapsLock; | ||||
case VK_SCROLL: return ImGuiKey_ScrollLock; | ||||
case VK_NUMLOCK: return ImGuiKey_NumLock; | ||||
case VK_SNAPSHOT: return ImGuiKey_PrintScreen; | ||||
case VK_PAUSE: return ImGuiKey_Pause; | ||||
case VK_NUMPAD0: return ImGuiKey_Keypad0; | ||||
case VK_NUMPAD1: return ImGuiKey_Keypad1; | ||||
case VK_NUMPAD2: return ImGuiKey_Keypad2; | ||||
case VK_NUMPAD3: return ImGuiKey_Keypad3; | ||||
case VK_NUMPAD4: return ImGuiKey_Keypad4; | ||||
case VK_NUMPAD5: return ImGuiKey_Keypad5; | ||||
case VK_NUMPAD6: return ImGuiKey_Keypad6; | ||||
case VK_NUMPAD7: return ImGuiKey_Keypad7; | ||||
case VK_NUMPAD8: return ImGuiKey_Keypad8; | ||||
case VK_NUMPAD9: return ImGuiKey_Keypad9; | ||||
case VK_DECIMAL: return ImGuiKey_KeypadDecimal; | ||||
case VK_DIVIDE: return ImGuiKey_KeypadDivide; | ||||
case VK_MULTIPLY: return ImGuiKey_KeypadMultiply; | ||||
case VK_SUBTRACT: return ImGuiKey_KeypadSubtract; | ||||
case VK_ADD: return ImGuiKey_KeypadAdd; | ||||
case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter; | ||||
case VK_LSHIFT: return ImGuiKey_LeftShift; | ||||
case VK_LCONTROL: return ImGuiKey_LeftCtrl; | ||||
case VK_LMENU: return ImGuiKey_LeftAlt; | ||||
case VK_LWIN: return ImGuiKey_LeftSuper; | ||||
case VK_RSHIFT: return ImGuiKey_RightShift; | ||||
case VK_RCONTROL: return ImGuiKey_RightCtrl; | ||||
case VK_RMENU: return ImGuiKey_RightAlt; | ||||
case VK_RWIN: return ImGuiKey_RightSuper; | ||||
case VK_APPS: return ImGuiKey_Menu; | ||||
case '0': return ImGuiKey_0; | ||||
case '1': return ImGuiKey_1; | ||||
case '2': return ImGuiKey_2; | ||||
case '3': return ImGuiKey_3; | ||||
case '4': return ImGuiKey_4; | ||||
case '5': return ImGuiKey_5; | ||||
case '6': return ImGuiKey_6; | ||||
case '7': return ImGuiKey_7; | ||||
case '8': return ImGuiKey_8; | ||||
case '9': return ImGuiKey_9; | ||||
case 'A': return ImGuiKey_A; | ||||
case 'B': return ImGuiKey_B; | ||||
case 'C': return ImGuiKey_C; | ||||
case 'D': return ImGuiKey_D; | ||||
case 'E': return ImGuiKey_E; | ||||
case 'F': return ImGuiKey_F; | ||||
case 'G': return ImGuiKey_G; | ||||
case 'H': return ImGuiKey_H; | ||||
case 'I': return ImGuiKey_I; | ||||
case 'J': return ImGuiKey_J; | ||||
case 'K': return ImGuiKey_K; | ||||
case 'L': return ImGuiKey_L; | ||||
case 'M': return ImGuiKey_M; | ||||
case 'N': return ImGuiKey_N; | ||||
case 'O': return ImGuiKey_O; | ||||
case 'P': return ImGuiKey_P; | ||||
case 'Q': return ImGuiKey_Q; | ||||
case 'R': return ImGuiKey_R; | ||||
case 'S': return ImGuiKey_S; | ||||
case 'T': return ImGuiKey_T; | ||||
case 'U': return ImGuiKey_U; | ||||
case 'V': return ImGuiKey_V; | ||||
case 'W': return ImGuiKey_W; | ||||
case 'X': return ImGuiKey_X; | ||||
case 'Y': return ImGuiKey_Y; | ||||
case 'Z': return ImGuiKey_Z; | ||||
case VK_F1: return ImGuiKey_F1; | ||||
case VK_F2: return ImGuiKey_F2; | ||||
case VK_F3: return ImGuiKey_F3; | ||||
case VK_F4: return ImGuiKey_F4; | ||||
case VK_F5: return ImGuiKey_F5; | ||||
case VK_F6: return ImGuiKey_F6; | ||||
case VK_F7: return ImGuiKey_F7; | ||||
case VK_F8: return ImGuiKey_F8; | ||||
case VK_F9: return ImGuiKey_F9; | ||||
case VK_F10: return ImGuiKey_F10; | ||||
case VK_F11: return ImGuiKey_F11; | ||||
case VK_F12: return ImGuiKey_F12; | ||||
default: return ImGuiKey_None; | ||||
} | ||||
} | ||||
// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WIN NT/WINVER versions. | // Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WIN NT/WINVER versions. | |||
#ifndef WM_MOUSEHWHEEL | #ifndef WM_MOUSEHWHEEL | |||
#define WM_MOUSEHWHEEL 0x020E | #define WM_MOUSEHWHEEL 0x020E | |||
#endif | #endif | |||
#ifndef DBT_DEVNODES_CHANGED | #ifndef DBT_DEVNODES_CHANGED | |||
#define DBT_DEVNODES_CHANGED 0x0007 | #define DBT_DEVNODES_CHANGED 0x0007 | |||
#endif | #endif | |||
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.) | // Win32 message handler (process Win32 mouse/keyboard inputs, etc.) | |||
// Call from your application's message handler. | // Call from your application's message handler. | |||
skipping to change at line 379 | skipping to change at line 521 | |||
{ | { | |||
case WM_MOUSEMOVE: | case WM_MOUSEMOVE: | |||
// We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE eve nts | // We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE eve nts | |||
bd->MouseHwnd = hwnd; | bd->MouseHwnd = hwnd; | |||
if (!bd->MouseTracked) | if (!bd->MouseTracked) | |||
{ | { | |||
TRACKMOUSEEVENT tme = { sizeof(tme), TME_LEAVE, hwnd, 0 }; | TRACKMOUSEEVENT tme = { sizeof(tme), TME_LEAVE, hwnd, 0 }; | |||
::TrackMouseEvent(&tme); | ::TrackMouseEvent(&tme); | |||
bd->MouseTracked = true; | bd->MouseTracked = true; | |||
} | } | |||
io.AddMousePosEvent((float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lPa ram)); | ||||
break; | break; | |||
case WM_MOUSELEAVE: | case WM_MOUSELEAVE: | |||
if (bd->MouseHwnd == hwnd) | if (bd->MouseHwnd == hwnd) | |||
bd->MouseHwnd = NULL; | bd->MouseHwnd = NULL; | |||
bd->MouseTracked = false; | bd->MouseTracked = false; | |||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); | ||||
break; | break; | |||
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: | case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: | |||
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: | case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: | |||
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: | case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: | |||
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: | case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: | |||
{ | { | |||
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_XB UTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } | if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XB UTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } | |||
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) | if (bd->MouseButtonsDown == 0 && ::GetCapture() == NULL) | |||
::SetCapture(hwnd); | ::SetCapture(hwnd); | |||
io.MouseDown[button] = true; | bd->MouseButtonsDown |= 1 << button; | |||
io.AddMouseButtonEvent(button, true); | ||||
return 0; | return 0; | |||
} | } | |||
case WM_LBUTTONUP: | case WM_LBUTTONUP: | |||
case WM_RBUTTONUP: | case WM_RBUTTONUP: | |||
case WM_MBUTTONUP: | case WM_MBUTTONUP: | |||
case WM_XBUTTONUP: | case WM_XBUTTONUP: | |||
{ | { | |||
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; } | |||
if (msg == WM_MBUTTONUP) { button = 2; } | if (msg == WM_MBUTTONUP) { button = 2; } | |||
if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTT ON1) ? 3 : 4; } | if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTT ON1) ? 3 : 4; } | |||
io.MouseDown[button] = false; | bd->MouseButtonsDown &= ~(1 << button); | |||
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) | if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd) | |||
::ReleaseCapture(); | ::ReleaseCapture(); | |||
io.AddMouseButtonEvent(button, false); | ||||
return 0; | return 0; | |||
} | } | |||
case WM_MOUSEWHEEL: | case WM_MOUSEWHEEL: | |||
io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DE LTA; | io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (flo at)WHEEL_DELTA); | |||
return 0; | return 0; | |||
case WM_MOUSEHWHEEL: | case WM_MOUSEHWHEEL: | |||
io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_D ELTA; | io.AddMouseWheelEvent((float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHE EL_DELTA, 0.0f); | |||
return 0; | return 0; | |||
case WM_KEYDOWN: | case WM_KEYDOWN: | |||
case WM_KEYUP: | case WM_KEYUP: | |||
case WM_SYSKEYDOWN: | case WM_SYSKEYDOWN: | |||
case WM_SYSKEYUP: | case WM_SYSKEYUP: | |||
{ | { | |||
bool down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN); | const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN); | |||
if (wParam < 256) | if (wParam < 256) | |||
io.KeysDown[wParam] = down; | ||||
if (wParam == VK_CONTROL) | ||||
{ | { | |||
io.KeysDown[VK_LCONTROL] = ((::GetKeyState(VK_LCONTROL) & 0x8000) != | // Submit modifiers | |||
0); | ImGui_ImplWin32_UpdateKeyModifiers(); | |||
io.KeysDown[VK_RCONTROL] = ((::GetKeyState(VK_RCONTROL) & 0x8000) != | ||||
0); | // Obtain virtual key code | |||
io.KeyCtrl = io.KeysDown[VK_LCONTROL] || io.KeysDown[VK_RCONTROL]; | // (keypad enter doesn't have its own... VK_RETURN with KF_EXTENDED | |||
} | flag means keypad enter, see IM_VK_KEYPAD_ENTER definition for details, it is ma | |||
if (wParam == VK_SHIFT) | pped to ImGuiKey_KeyPadEnter.) | |||
{ | int vk = (int)wParam; | |||
io.KeysDown[VK_LSHIFT] = ((::GetKeyState(VK_LSHIFT) & 0x8000) != 0); | if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED)) | |||
io.KeysDown[VK_RSHIFT] = ((::GetKeyState(VK_RSHIFT) & 0x8000) != 0); | vk = IM_VK_KEYPAD_ENTER; | |||
io.KeyShift = io.KeysDown[VK_LSHIFT] || io.KeysDown[VK_RS | ||||
HIFT]; | // Submit key event | |||
} | const ImGuiKey key = ImGui_ImplWin32_VirtualKeyToImGuiKey(vk); | |||
if (wParam == VK_MENU) | const int scancode = (int)LOBYTE(HIWORD(lParam)); | |||
{ | if (key != ImGuiKey_None) | |||
io.KeysDown[VK_LMENU] = ((::GetKeyState(VK_LMENU) & 0x8000) != 0); | ImGui_ImplWin32_AddKeyEvent(key, is_key_down, vk, scancode); | |||
io.KeysDown[VK_RMENU] = ((::GetKeyState(VK_RMENU) & 0x8000) != 0); | ||||
io.KeyAlt = io.KeysDown[VK_LMENU] || io.KeysDown[VK_RMEN | // Submit individual left/right modifier events | |||
U]; | if (vk == VK_SHIFT) | |||
{ | ||||
// Important: Shift keys tend to get stuck when pressed together | ||||
, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkaro | ||||
unds() | ||||
if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKey | ||||
Event(ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); } | ||||
if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKey | ||||
Event(ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); } | ||||
} | ||||
else if (vk == VK_CONTROL) | ||||
{ | ||||
if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddK | ||||
eyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); } | ||||
if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddK | ||||
eyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); } | ||||
} | ||||
else if (vk == VK_MENU) | ||||
{ | ||||
if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyE | ||||
vent(ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); } | ||||
if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyE | ||||
vent(ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); } | ||||
} | ||||
} | } | |||
return 0; | return 0; | |||
} | } | |||
case WM_SETFOCUS: | case WM_SETFOCUS: | |||
case WM_KILLFOCUS: | case WM_KILLFOCUS: | |||
io.AddFocusEvent(msg == WM_SETFOCUS); | io.AddFocusEvent(msg == WM_SETFOCUS); | |||
return 0; | return 0; | |||
case WM_CHAR: | case WM_CHAR: | |||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters. | // You can also use ToAscii()+GetKeyboardState() to retrieve characters. | |||
if (wParam > 0 && wParam < 0x10000) | if (wParam > 0 && wParam < 0x10000) | |||
End of changes. 31 change blocks. | ||||
135 lines changed or deleted | 310 lines changed or added |