@ -4248,204 +4248,6 @@ static bool IsWindowActiveAndVisible(ImGuiWindow* window)
return ( window - > Active ) & & ( ! window - > Hidden ) ;
}
static void UpdateAliasKey ( ImGuiKey key , bool v , float analog_value )
{
IM_ASSERT ( ImGui : : IsAliasKey ( key ) ) ;
ImGuiKeyData * key_data = ImGui : : GetKeyData ( key ) ;
key_data - > Down = v ;
key_data - > AnalogValue = analog_value ;
}
// [Internal] Do not use directly
static ImGuiKeyChord GetMergedModsFromKeys ( )
{
ImGuiKeyChord mods = 0 ;
if ( ImGui : : IsKeyDown ( ImGuiMod_Ctrl ) ) { mods | = ImGuiMod_Ctrl ; }
if ( ImGui : : IsKeyDown ( ImGuiMod_Shift ) ) { mods | = ImGuiMod_Shift ; }
if ( ImGui : : IsKeyDown ( ImGuiMod_Alt ) ) { mods | = ImGuiMod_Alt ; }
if ( ImGui : : IsKeyDown ( ImGuiMod_Super ) ) { mods | = ImGuiMod_Super ; }
return mods ;
}
static void ImGui : : UpdateKeyboardInputs ( )
{
ImGuiContext & g = * GImGui ;
ImGuiIO & io = g . IO ;
// Import legacy keys or verify they are not used
# ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
if ( io . BackendUsingLegacyKeyArrays = = 0 )
{
// Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written to externally.
for ( int n = 0 ; n < ImGuiKey_LegacyNativeKey_END ; n + + )
IM_ASSERT ( ( io . KeysDown [ n ] = = false | | IsKeyDown ( ( ImGuiKey ) n ) ) & & " Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both! " ) ;
}
else
{
if ( g . FrameCount = = 0 )
for ( int n = ImGuiKey_LegacyNativeKey_BEGIN ; n < ImGuiKey_LegacyNativeKey_END ; n + + )
IM_ASSERT ( g . IO . KeyMap [ n ] = = - 1 & & " Backend is not allowed to write to io.KeyMap[0..511]! " ) ;
// Build reverse KeyMap (Named -> Legacy)
for ( int n = ImGuiKey_NamedKey_BEGIN ; n < ImGuiKey_NamedKey_END ; n + + )
if ( io . KeyMap [ n ] ! = - 1 )
{
IM_ASSERT ( IsLegacyKey ( ( ImGuiKey ) io . KeyMap [ n ] ) ) ;
io . KeyMap [ io . KeyMap [ n ] ] = n ;
}
// Import legacy keys into new ones
for ( int n = ImGuiKey_LegacyNativeKey_BEGIN ; n < ImGuiKey_LegacyNativeKey_END ; n + + )
if ( io . KeysDown [ n ] | | io . BackendUsingLegacyKeyArrays = = 1 )
{
const ImGuiKey key = ( ImGuiKey ) ( io . KeyMap [ n ] ! = - 1 ? io . KeyMap [ n ] : n ) ;
IM_ASSERT ( io . KeyMap [ n ] = = - 1 | | IsNamedKey ( key ) ) ;
io . KeysData [ key ] . Down = io . KeysDown [ n ] ;
if ( key ! = n )
io . KeysDown [ key ] = io . KeysDown [ n ] ; // Allow legacy code using io.KeysDown[GetKeyIndex()] with old backends
io . BackendUsingLegacyKeyArrays = 1 ;
}
if ( io . BackendUsingLegacyKeyArrays = = 1 )
{
GetKeyData ( ImGuiMod_Ctrl ) - > Down = io . KeyCtrl ;
GetKeyData ( ImGuiMod_Shift ) - > Down = io . KeyShift ;
GetKeyData ( ImGuiMod_Alt ) - > Down = io . KeyAlt ;
GetKeyData ( ImGuiMod_Super ) - > Down = io . KeySuper ;
}
}
# ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
const bool nav_gamepad_active = ( io . ConfigFlags & ImGuiConfigFlags_NavEnableGamepad ) ! = 0 & & ( io . BackendFlags & ImGuiBackendFlags_HasGamepad ) ! = 0 ;
if ( io . BackendUsingLegacyNavInputArray & & nav_gamepad_active )
{
# define MAP_LEGACY_NAV_INPUT_TO_KEY1(_KEY, _NAV1) do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f); io.KeysData[_KEY].AnalogValue = io.NavInputs[_NAV1]; } while (0)
# define MAP_LEGACY_NAV_INPUT_TO_KEY2(_KEY, _NAV1, _NAV2) do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f) || (io.NavInputs[_NAV2] > 0.0f); io.KeysData[_KEY].AnalogValue = ImMax(io.NavInputs[_NAV1], io.NavInputs[_NAV2]); } while (0)
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadFaceDown , ImGuiNavInput_Activate ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadFaceRight , ImGuiNavInput_Cancel ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadFaceLeft , ImGuiNavInput_Menu ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadFaceUp , ImGuiNavInput_Input ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadDpadLeft , ImGuiNavInput_DpadLeft ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadDpadRight , ImGuiNavInput_DpadRight ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadDpadUp , ImGuiNavInput_DpadUp ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadDpadDown , ImGuiNavInput_DpadDown ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY2 ( ImGuiKey_GamepadL1 , ImGuiNavInput_FocusPrev , ImGuiNavInput_TweakSlow ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY2 ( ImGuiKey_GamepadR1 , ImGuiNavInput_FocusNext , ImGuiNavInput_TweakFast ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadLStickLeft , ImGuiNavInput_LStickLeft ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadLStickRight , ImGuiNavInput_LStickRight ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadLStickUp , ImGuiNavInput_LStickUp ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadLStickDown , ImGuiNavInput_LStickDown ) ;
# undef NAV_MAP_KEY
}
# endif
# endif
// Update aliases
for ( int n = 0 ; n < ImGuiMouseButton_COUNT ; n + + )
UpdateAliasKey ( MouseButtonToKey ( n ) , io . MouseDown [ n ] , io . MouseDown [ n ] ? 1.0f : 0.0f ) ;
UpdateAliasKey ( ImGuiKey_MouseWheelX , io . MouseWheelH ! = 0.0f , io . MouseWheelH ) ;
UpdateAliasKey ( ImGuiKey_MouseWheelY , io . MouseWheel ! = 0.0f , io . MouseWheel ) ;
// Synchronize io.KeyMods and io.KeyXXX values.
// - New backends (1.87+): send io.AddKeyEvent(ImGuiMod_XXX) -> -> (here) deriving io.KeyMods + io.KeyXXX from key array.
// - Legacy backends: set io.KeyXXX bools -> (above) set key array from io.KeyXXX -> (here) deriving io.KeyMods + io.KeyXXX from key array.
// So with legacy backends the 4 values will do a unnecessary back-and-forth but it makes the code simpler and future facing.
io . KeyMods = GetMergedModsFromKeys ( ) ;
io . KeyCtrl = ( io . KeyMods & ImGuiMod_Ctrl ) ! = 0 ;
io . KeyShift = ( io . KeyMods & ImGuiMod_Shift ) ! = 0 ;
io . KeyAlt = ( io . KeyMods & ImGuiMod_Alt ) ! = 0 ;
io . KeySuper = ( io . KeyMods & ImGuiMod_Super ) ! = 0 ;
// Clear gamepad data if disabled
if ( ( io . BackendFlags & ImGuiBackendFlags_HasGamepad ) = = 0 )
for ( int i = ImGuiKey_Gamepad_BEGIN ; i < ImGuiKey_Gamepad_END ; i + + )
{
io . KeysData [ i - ImGuiKey_KeysData_OFFSET ] . Down = false ;
io . KeysData [ i - ImGuiKey_KeysData_OFFSET ] . AnalogValue = 0.0f ;
}
// Update keys
for ( int i = 0 ; i < ImGuiKey_KeysData_SIZE ; i + + )
{
ImGuiKeyData * key_data = & io . KeysData [ i ] ;
key_data - > DownDurationPrev = key_data - > DownDuration ;
key_data - > DownDuration = key_data - > Down ? ( key_data - > DownDuration < 0.0f ? 0.0f : key_data - > DownDuration + io . DeltaTime ) : - 1.0f ;
}
// Update keys/input owner (named keys only): one entry per key
for ( ImGuiKey key = ImGuiKey_NamedKey_BEGIN ; key < ImGuiKey_NamedKey_END ; key = ( ImGuiKey ) ( key + 1 ) )
{
ImGuiKeyData * key_data = & io . KeysData [ key - ImGuiKey_KeysData_OFFSET ] ;
ImGuiKeyOwnerData * owner_data = & g . KeysOwnerData [ key - ImGuiKey_NamedKey_BEGIN ] ;
owner_data - > OwnerCurr = owner_data - > OwnerNext ;
if ( ! key_data - > Down ) // Important: ownership is released on the frame after a release. Ensure a 'MouseDown -> CloseWindow -> MouseUp' chain doesn't lead to someone else seeing the MouseUp.
owner_data - > OwnerNext = ImGuiKeyOwner_None ;
owner_data - > LockThisFrame = owner_data - > LockUntilRelease = owner_data - > LockUntilRelease & & key_data - > Down ; // Clear LockUntilRelease when key is not Down anymore
}
UpdateKeyRoutingTable ( & g . KeysRoutingTable ) ;
}
static void ImGui : : UpdateMouseInputs ( )
{
ImGuiContext & g = * GImGui ;
ImGuiIO & io = g . IO ;
// Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
if ( IsMousePosValid ( & io . MousePos ) )
io . MousePos = g . MouseLastValidPos = ImFloorSigned ( io . MousePos ) ;
// If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
if ( IsMousePosValid ( & io . MousePos ) & & IsMousePosValid ( & io . MousePosPrev ) )
io . MouseDelta = io . MousePos - io . MousePosPrev ;
else
io . MouseDelta = ImVec2 ( 0.0f , 0.0f ) ;
// If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
if ( io . MouseDelta . x ! = 0.0f | | io . MouseDelta . y ! = 0.0f )
g . NavDisableMouseHover = false ;
io . MousePosPrev = io . MousePos ;
for ( int i = 0 ; i < IM_ARRAYSIZE ( io . MouseDown ) ; i + + )
{
io . MouseClicked [ i ] = io . MouseDown [ i ] & & io . MouseDownDuration [ i ] < 0.0f ;
io . MouseClickedCount [ i ] = 0 ; // Will be filled below
io . MouseReleased [ i ] = ! io . MouseDown [ i ] & & io . MouseDownDuration [ i ] > = 0.0f ;
io . MouseDownDurationPrev [ i ] = io . MouseDownDuration [ i ] ;
io . MouseDownDuration [ i ] = io . MouseDown [ i ] ? ( io . MouseDownDuration [ i ] < 0.0f ? 0.0f : io . MouseDownDuration [ i ] + io . DeltaTime ) : - 1.0f ;
if ( io . MouseClicked [ i ] )
{
bool is_repeated_click = false ;
if ( ( float ) ( g . Time - io . MouseClickedTime [ i ] ) < io . MouseDoubleClickTime )
{
ImVec2 delta_from_click_pos = IsMousePosValid ( & io . MousePos ) ? ( io . MousePos - io . MouseClickedPos [ i ] ) : ImVec2 ( 0.0f , 0.0f ) ;
if ( ImLengthSqr ( delta_from_click_pos ) < io . MouseDoubleClickMaxDist * io . MouseDoubleClickMaxDist )
is_repeated_click = true ;
}
if ( is_repeated_click )
io . MouseClickedLastCount [ i ] + + ;
else
io . MouseClickedLastCount [ i ] = 1 ;
io . MouseClickedTime [ i ] = g . Time ;
io . MouseClickedPos [ i ] = io . MousePos ;
io . MouseClickedCount [ i ] = io . MouseClickedLastCount [ i ] ;
io . MouseDragMaxDistanceSqr [ i ] = 0.0f ;
}
else if ( io . MouseDown [ i ] )
{
// Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold
float delta_sqr_click_pos = IsMousePosValid ( & io . MousePos ) ? ImLengthSqr ( io . MousePos - io . MouseClickedPos [ i ] ) : 0.0f ;
io . MouseDragMaxDistanceSqr [ i ] = ImMax ( io . MouseDragMaxDistanceSqr [ i ] , delta_sqr_click_pos ) ;
}
// We provide io.MouseDoubleClicked[] as a legacy service
io . MouseDoubleClicked [ i ] = ( io . MouseClickedCount [ i ] = = 2 ) ;
// Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
if ( io . MouseClicked [ i ] )
g . NavDisableMouseHover = false ;
}
}
// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
void ImGui : : UpdateHoveredWindowAndCaptureFlags ( )
{
@ -7772,6 +7574,11 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
// - GetMouseCursor()
// - SetMouseCursor()
//-----------------------------------------------------------------------------
// - UpdateAliasKey()
// - GetMergedModsFromKeys()
// - UpdateKeyboardInputs()
// - UpdateMouseInputs()
//-----------------------------------------------------------------------------
// - LockWheelingWindow [Internal]
// - FindBestWheelingWindow [Internal]
// - UpdateMouseWheel() [Internal]
@ -8360,6 +8167,204 @@ void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
g . MouseCursor = cursor_type ;
}
static void UpdateAliasKey ( ImGuiKey key , bool v , float analog_value )
{
IM_ASSERT ( ImGui : : IsAliasKey ( key ) ) ;
ImGuiKeyData * key_data = ImGui : : GetKeyData ( key ) ;
key_data - > Down = v ;
key_data - > AnalogValue = analog_value ;
}
// [Internal] Do not use directly
static ImGuiKeyChord GetMergedModsFromKeys ( )
{
ImGuiKeyChord mods = 0 ;
if ( ImGui : : IsKeyDown ( ImGuiMod_Ctrl ) ) { mods | = ImGuiMod_Ctrl ; }
if ( ImGui : : IsKeyDown ( ImGuiMod_Shift ) ) { mods | = ImGuiMod_Shift ; }
if ( ImGui : : IsKeyDown ( ImGuiMod_Alt ) ) { mods | = ImGuiMod_Alt ; }
if ( ImGui : : IsKeyDown ( ImGuiMod_Super ) ) { mods | = ImGuiMod_Super ; }
return mods ;
}
static void ImGui : : UpdateKeyboardInputs ( )
{
ImGuiContext & g = * GImGui ;
ImGuiIO & io = g . IO ;
// Import legacy keys or verify they are not used
# ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
if ( io . BackendUsingLegacyKeyArrays = = 0 )
{
// Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written to externally.
for ( int n = 0 ; n < ImGuiKey_LegacyNativeKey_END ; n + + )
IM_ASSERT ( ( io . KeysDown [ n ] = = false | | IsKeyDown ( ( ImGuiKey ) n ) ) & & " Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both! " ) ;
}
else
{
if ( g . FrameCount = = 0 )
for ( int n = ImGuiKey_LegacyNativeKey_BEGIN ; n < ImGuiKey_LegacyNativeKey_END ; n + + )
IM_ASSERT ( g . IO . KeyMap [ n ] = = - 1 & & " Backend is not allowed to write to io.KeyMap[0..511]! " ) ;
// Build reverse KeyMap (Named -> Legacy)
for ( int n = ImGuiKey_NamedKey_BEGIN ; n < ImGuiKey_NamedKey_END ; n + + )
if ( io . KeyMap [ n ] ! = - 1 )
{
IM_ASSERT ( IsLegacyKey ( ( ImGuiKey ) io . KeyMap [ n ] ) ) ;
io . KeyMap [ io . KeyMap [ n ] ] = n ;
}
// Import legacy keys into new ones
for ( int n = ImGuiKey_LegacyNativeKey_BEGIN ; n < ImGuiKey_LegacyNativeKey_END ; n + + )
if ( io . KeysDown [ n ] | | io . BackendUsingLegacyKeyArrays = = 1 )
{
const ImGuiKey key = ( ImGuiKey ) ( io . KeyMap [ n ] ! = - 1 ? io . KeyMap [ n ] : n ) ;
IM_ASSERT ( io . KeyMap [ n ] = = - 1 | | IsNamedKey ( key ) ) ;
io . KeysData [ key ] . Down = io . KeysDown [ n ] ;
if ( key ! = n )
io . KeysDown [ key ] = io . KeysDown [ n ] ; // Allow legacy code using io.KeysDown[GetKeyIndex()] with old backends
io . BackendUsingLegacyKeyArrays = 1 ;
}
if ( io . BackendUsingLegacyKeyArrays = = 1 )
{
GetKeyData ( ImGuiMod_Ctrl ) - > Down = io . KeyCtrl ;
GetKeyData ( ImGuiMod_Shift ) - > Down = io . KeyShift ;
GetKeyData ( ImGuiMod_Alt ) - > Down = io . KeyAlt ;
GetKeyData ( ImGuiMod_Super ) - > Down = io . KeySuper ;
}
}
# ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
const bool nav_gamepad_active = ( io . ConfigFlags & ImGuiConfigFlags_NavEnableGamepad ) ! = 0 & & ( io . BackendFlags & ImGuiBackendFlags_HasGamepad ) ! = 0 ;
if ( io . BackendUsingLegacyNavInputArray & & nav_gamepad_active )
{
# define MAP_LEGACY_NAV_INPUT_TO_KEY1(_KEY, _NAV1) do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f); io.KeysData[_KEY].AnalogValue = io.NavInputs[_NAV1]; } while (0)
# define MAP_LEGACY_NAV_INPUT_TO_KEY2(_KEY, _NAV1, _NAV2) do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f) || (io.NavInputs[_NAV2] > 0.0f); io.KeysData[_KEY].AnalogValue = ImMax(io.NavInputs[_NAV1], io.NavInputs[_NAV2]); } while (0)
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadFaceDown , ImGuiNavInput_Activate ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadFaceRight , ImGuiNavInput_Cancel ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadFaceLeft , ImGuiNavInput_Menu ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadFaceUp , ImGuiNavInput_Input ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadDpadLeft , ImGuiNavInput_DpadLeft ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadDpadRight , ImGuiNavInput_DpadRight ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadDpadUp , ImGuiNavInput_DpadUp ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadDpadDown , ImGuiNavInput_DpadDown ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY2 ( ImGuiKey_GamepadL1 , ImGuiNavInput_FocusPrev , ImGuiNavInput_TweakSlow ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY2 ( ImGuiKey_GamepadR1 , ImGuiNavInput_FocusNext , ImGuiNavInput_TweakFast ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadLStickLeft , ImGuiNavInput_LStickLeft ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadLStickRight , ImGuiNavInput_LStickRight ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadLStickUp , ImGuiNavInput_LStickUp ) ;
MAP_LEGACY_NAV_INPUT_TO_KEY1 ( ImGuiKey_GamepadLStickDown , ImGuiNavInput_LStickDown ) ;
# undef NAV_MAP_KEY
}
# endif
# endif
// Update aliases
for ( int n = 0 ; n < ImGuiMouseButton_COUNT ; n + + )
UpdateAliasKey ( MouseButtonToKey ( n ) , io . MouseDown [ n ] , io . MouseDown [ n ] ? 1.0f : 0.0f ) ;
UpdateAliasKey ( ImGuiKey_MouseWheelX , io . MouseWheelH ! = 0.0f , io . MouseWheelH ) ;
UpdateAliasKey ( ImGuiKey_MouseWheelY , io . MouseWheel ! = 0.0f , io . MouseWheel ) ;
// Synchronize io.KeyMods and io.KeyXXX values.
// - New backends (1.87+): send io.AddKeyEvent(ImGuiMod_XXX) -> -> (here) deriving io.KeyMods + io.KeyXXX from key array.
// - Legacy backends: set io.KeyXXX bools -> (above) set key array from io.KeyXXX -> (here) deriving io.KeyMods + io.KeyXXX from key array.
// So with legacy backends the 4 values will do a unnecessary back-and-forth but it makes the code simpler and future facing.
io . KeyMods = GetMergedModsFromKeys ( ) ;
io . KeyCtrl = ( io . KeyMods & ImGuiMod_Ctrl ) ! = 0 ;
io . KeyShift = ( io . KeyMods & ImGuiMod_Shift ) ! = 0 ;
io . KeyAlt = ( io . KeyMods & ImGuiMod_Alt ) ! = 0 ;
io . KeySuper = ( io . KeyMods & ImGuiMod_Super ) ! = 0 ;
// Clear gamepad data if disabled
if ( ( io . BackendFlags & ImGuiBackendFlags_HasGamepad ) = = 0 )
for ( int i = ImGuiKey_Gamepad_BEGIN ; i < ImGuiKey_Gamepad_END ; i + + )
{
io . KeysData [ i - ImGuiKey_KeysData_OFFSET ] . Down = false ;
io . KeysData [ i - ImGuiKey_KeysData_OFFSET ] . AnalogValue = 0.0f ;
}
// Update keys
for ( int i = 0 ; i < ImGuiKey_KeysData_SIZE ; i + + )
{
ImGuiKeyData * key_data = & io . KeysData [ i ] ;
key_data - > DownDurationPrev = key_data - > DownDuration ;
key_data - > DownDuration = key_data - > Down ? ( key_data - > DownDuration < 0.0f ? 0.0f : key_data - > DownDuration + io . DeltaTime ) : - 1.0f ;
}
// Update keys/input owner (named keys only): one entry per key
for ( ImGuiKey key = ImGuiKey_NamedKey_BEGIN ; key < ImGuiKey_NamedKey_END ; key = ( ImGuiKey ) ( key + 1 ) )
{
ImGuiKeyData * key_data = & io . KeysData [ key - ImGuiKey_KeysData_OFFSET ] ;
ImGuiKeyOwnerData * owner_data = & g . KeysOwnerData [ key - ImGuiKey_NamedKey_BEGIN ] ;
owner_data - > OwnerCurr = owner_data - > OwnerNext ;
if ( ! key_data - > Down ) // Important: ownership is released on the frame after a release. Ensure a 'MouseDown -> CloseWindow -> MouseUp' chain doesn't lead to someone else seeing the MouseUp.
owner_data - > OwnerNext = ImGuiKeyOwner_None ;
owner_data - > LockThisFrame = owner_data - > LockUntilRelease = owner_data - > LockUntilRelease & & key_data - > Down ; // Clear LockUntilRelease when key is not Down anymore
}
UpdateKeyRoutingTable ( & g . KeysRoutingTable ) ;
}
static void ImGui : : UpdateMouseInputs ( )
{
ImGuiContext & g = * GImGui ;
ImGuiIO & io = g . IO ;
// Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
if ( IsMousePosValid ( & io . MousePos ) )
io . MousePos = g . MouseLastValidPos = ImFloorSigned ( io . MousePos ) ;
// If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
if ( IsMousePosValid ( & io . MousePos ) & & IsMousePosValid ( & io . MousePosPrev ) )
io . MouseDelta = io . MousePos - io . MousePosPrev ;
else
io . MouseDelta = ImVec2 ( 0.0f , 0.0f ) ;
// If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
if ( io . MouseDelta . x ! = 0.0f | | io . MouseDelta . y ! = 0.0f )
g . NavDisableMouseHover = false ;
io . MousePosPrev = io . MousePos ;
for ( int i = 0 ; i < IM_ARRAYSIZE ( io . MouseDown ) ; i + + )
{
io . MouseClicked [ i ] = io . MouseDown [ i ] & & io . MouseDownDuration [ i ] < 0.0f ;
io . MouseClickedCount [ i ] = 0 ; // Will be filled below
io . MouseReleased [ i ] = ! io . MouseDown [ i ] & & io . MouseDownDuration [ i ] > = 0.0f ;
io . MouseDownDurationPrev [ i ] = io . MouseDownDuration [ i ] ;
io . MouseDownDuration [ i ] = io . MouseDown [ i ] ? ( io . MouseDownDuration [ i ] < 0.0f ? 0.0f : io . MouseDownDuration [ i ] + io . DeltaTime ) : - 1.0f ;
if ( io . MouseClicked [ i ] )
{
bool is_repeated_click = false ;
if ( ( float ) ( g . Time - io . MouseClickedTime [ i ] ) < io . MouseDoubleClickTime )
{
ImVec2 delta_from_click_pos = IsMousePosValid ( & io . MousePos ) ? ( io . MousePos - io . MouseClickedPos [ i ] ) : ImVec2 ( 0.0f , 0.0f ) ;
if ( ImLengthSqr ( delta_from_click_pos ) < io . MouseDoubleClickMaxDist * io . MouseDoubleClickMaxDist )
is_repeated_click = true ;
}
if ( is_repeated_click )
io . MouseClickedLastCount [ i ] + + ;
else
io . MouseClickedLastCount [ i ] = 1 ;
io . MouseClickedTime [ i ] = g . Time ;
io . MouseClickedPos [ i ] = io . MousePos ;
io . MouseClickedCount [ i ] = io . MouseClickedLastCount [ i ] ;
io . MouseDragMaxDistanceSqr [ i ] = 0.0f ;
}
else if ( io . MouseDown [ i ] )
{
// Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold
float delta_sqr_click_pos = IsMousePosValid ( & io . MousePos ) ? ImLengthSqr ( io . MousePos - io . MouseClickedPos [ i ] ) : 0.0f ;
io . MouseDragMaxDistanceSqr [ i ] = ImMax ( io . MouseDragMaxDistanceSqr [ i ] , delta_sqr_click_pos ) ;
}
// We provide io.MouseDoubleClicked[] as a legacy service
io . MouseDoubleClicked [ i ] = ( io . MouseClickedCount [ i ] = = 2 ) ;
// Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
if ( io . MouseClicked [ i ] )
g . NavDisableMouseHover = false ;
}
}
static void LockWheelingWindow ( ImGuiWindow * window , float wheel_amount )
{
ImGuiContext & g = * GImGui ;