@ -3,9 +3,9 @@
// Implemented features:
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder 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.
@ -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)
// 2022-01-10: Inputs: calling new io.AddKeyEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
// 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness.
// 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.
@ -125,30 +126,6 @@ bool ImGui_ImplWin32_Init(void* 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.KeysDown[] 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
# ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
const char * xinput_dll_names [ ] =
@ -222,6 +199,43 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
return true ;
}
static bool IsVkDown ( int vk )
{
return ( : : GetKeyState ( vk ) & 0x8000 ) ! = 0 ;
}
static void ImGui_ImplWin32_AddKeyEvent ( ImGuiKey key , bool down , int native_keycode , int native_scancode = - 1 )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . AddKeyEvent ( key , down ) ;
io . SetKeyEventNativeData ( key , native_keycode , native_scancode ) ; // To support legacy indexing (<1.87 user code)
IM_UNUSED ( native_scancode ) ;
}
static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds ( )
{
// 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 Win+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 ) ;
}
static void ImGui_ImplWin32_UpdateKeyModifiers ( )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . KeyShift = IsVkDown ( VK_LSHIFT ) | | IsVkDown ( VK_RSHIFT ) ;
io . KeyCtrl = IsVkDown ( VK_LCONTROL ) | | IsVkDown ( VK_RCONTROL ) ;
io . KeyAlt = IsVkDown ( VK_LMENU ) | | IsVkDown ( VK_RMENU ) ;
io . KeySuper = IsVkDown ( VK_LWIN ) | | IsVkDown ( VK_RWIN ) ;
}
static void ImGui_ImplWin32_UpdateMousePos ( )
{
ImGui_ImplWin32_Data * bd = ImGui_ImplWin32_GetBackendData ( ) ;
@ -323,6 +337,12 @@ void ImGui_ImplWin32_NewFrame()
io . DeltaTime = ( float ) ( current_time - bd - > Time ) / bd - > TicksPerSecond ;
bd - > Time = current_time ;
// Process workarounds for known Windows key handling issues
ImGui_ImplWin32_ProcessKeyEventsWorkarounds ( ) ;
// Update key modifiers
ImGui_ImplWin32_UpdateKeyModifiers ( ) ;
// Update OS mouse position
ImGui_ImplWin32_UpdateMousePos ( ) ;
@ -338,6 +358,122 @@ void ImGui_ImplWin32_NewFrame()
ImGui_ImplWin32_UpdateGamepads ( ) ;
}
// There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED, 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_LeftControl ;
case VK_LMENU : return ImGuiKey_LeftAlt ;
case VK_LWIN : return ImGuiKey_LeftSuper ;
case VK_RSHIFT : return ImGuiKey_RightShift ;
case VK_RCONTROL : return ImGuiKey_RightControl ;
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_WINNT/WINVER versions.
# ifndef WM_MOUSEHWHEEL
# define WM_MOUSEHWHEEL 0x020E
@ -424,26 +560,39 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
case WM_SYSKEYDOWN :
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 )
io . KeysDown [ wParam ] = down ;
if ( wParam = = VK_CONTROL )
{
io . KeysDown [ VK_LCONTROL ] = ( ( : : GetKeyState ( VK_LCONTROL ) & 0x8000 ) ! = 0 ) ;
io . KeysDown [ VK_RCONTROL ] = ( ( : : GetKeyState ( VK_RCONTROL ) & 0x8000 ) ! = 0 ) ;
io . KeyCtrl = io . KeysDown [ VK_LCONTROL ] | | io . KeysDown [ VK_RCONTROL ] ;
// Obtain virtual key code
// (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 mapped to ImGuiKey_KeyPadEnter.)
int vk = ( int ) wParam ;
if ( ( wParam = = VK_RETURN ) & & ( HIWORD ( lParam ) & KF_EXTENDED ) )
vk = IM_VK_KEYPAD_ENTER ;
// Submit key event
const ImGuiKey key = ImGui_ImplWin32_VirtualKeyToImGuiKey ( vk ) ;
const int scancode = ( int ) LOBYTE ( HIWORD ( lParam ) ) ;
if ( key ! = ImGuiKey_None )
ImGui_ImplWin32_AddKeyEvent ( key , is_key_down , vk , scancode ) ;
// Submit individual left/right modifier events
if ( vk = = VK_SHIFT )
{
// 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_RSHIFT ) = = is_key_down ) { ImGui_ImplWin32_AddKeyEvent ( ImGuiKey_RightShift , is_key_down , VK_RSHIFT , scancode ) ; }
}
if ( wParam = = VK_SHIFT )
else if ( vk = = VK_CONTROL )
{
io . KeysDown [ VK_LSHIFT ] = ( ( : : GetKeyState ( VK_LSHIFT ) & 0x8000 ) ! = 0 ) ;
io . KeysDown [ VK_RSHIFT ] = ( ( : : GetKeyState ( VK_RSHIFT ) & 0x8000 ) ! = 0 ) ;
io . KeyShift = io . KeysDown [ VK_LSHIFT ] | | io . KeysDown [ VK_RSHIFT ] ;
if ( IsVkDown ( VK_LCONTROL ) = = is_key_down ) { ImGui_ImplWin32_AddKeyEvent ( ImGuiKey_LeftControl , is_key_down , VK_LCONTROL , scancode ) ; }
if ( IsVkDown ( VK_RCONTROL ) = = is_key_down ) { ImGui_ImplWin32_AddKeyEvent ( ImGuiKey_RightControl , is_key_down , VK_RCONTROL , scancode ) ; }
}
if ( wParam = = VK_MENU )
else if ( vk = = VK_MENU )
{
io . KeysDown [ VK_LMENU ] = ( ( : : GetKeyState ( VK_LMENU ) & 0x8000 ) ! = 0 ) ;
io . KeysDown [ VK_RMENU ] = ( ( : : GetKeyState ( VK_RMENU ) & 0x8000 ) ! = 0 ) ;
io . KeyAlt = io . KeysDown [ VK_LMENU ] | | io . KeysDown [ VK_RMENU ] ;
if ( IsVkDown ( VK_LMENU ) = = is_key_down ) { ImGui_ImplWin32_AddKeyEvent ( 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 ) ; }
}
}
return 0 ;
}