@ -4367,13 +4367,58 @@ static void LockWheelingWindow(ImGuiWindow* window, float wheel_amount)
IMGUI_DEBUG_LOG_IO ( " LockWheelingWindow() \" %s \" \n " , window ? window - > Name : " NULL " ) ;
g . WheelingWindow = window ;
g . WheelingWindowRefMousePos = g . IO . MousePos ;
if ( window = = NULL )
{
g . WheelingWindowStartFrame = - 1 ;
g . WheelingAxisAvg = ImVec2 ( 0.0f , 0.0f ) ;
}
}
static ImGuiWindow * FindBestWheelingWindow ( const ImVec2 & wheel )
{
// For each axis, find window in the hierarchy that may want to use scrolling
ImGuiContext & g = * GImGui ;
ImGuiWindow * windows [ 2 ] = { NULL , NULL } ;
for ( int axis = 0 ; axis < 2 ; axis + + )
if ( wheel [ axis ] ! = 0.0f )
for ( ImGuiWindow * window = windows [ axis ] = g . HoveredWindow ; window - > Flags & ImGuiWindowFlags_ChildWindow ; window = windows [ axis ] = window - > ParentWindow )
{
// Bubble up into parent window if:
// - a child window doesn't allow any scrolling.
// - a child window has the ImGuiWindowFlags_NoScrollWithMouse flag.
//// - a child window doesn't need scrolling because it is already at the edge for the direction we are going in (FIXME-WIP)
const bool has_scrolling = ( window - > ScrollMax [ axis ] ! = 0.0f ) ;
const bool inputs_disabled = ( window - > Flags & ImGuiWindowFlags_NoScrollWithMouse ) & & ! ( window - > Flags & ImGuiWindowFlags_NoMouseInputs ) ;
//const bool scrolling_past_limits = (wheel_v < 0.0f) ? (window->Scroll[axis] <= 0.0f) : (window->Scroll[axis] >= window->ScrollMax[axis]);
if ( has_scrolling & & ! inputs_disabled ) // && !scrolling_past_limits)
break ; // select this window
}
if ( windows [ 0 ] = = NULL & & windows [ 1 ] = = NULL )
return NULL ;
// If there's only one window or only one axis then there's no ambiguity
if ( windows [ 0 ] = = windows [ 1 ] | | windows [ 0 ] = = NULL | | windows [ 1 ] = = NULL )
return windows [ 1 ] ? windows [ 1 ] : windows [ 0 ] ;
// If candidate are different windows we need to decide which one to prioritize
// - First frame: only find a winner if one axis is zero.
// - Subsequent frames: only find a winner when one is more than the other.
if ( g . WheelingWindowStartFrame = = - 1 )
g . WheelingWindowStartFrame = g . FrameCount ;
if ( ( g . WheelingWindowStartFrame = = g . FrameCount & & wheel . x ! = 0.0f & & wheel . y ! = 0.0f ) | | ( g . WheelingAxisAvg . x = = g . WheelingAxisAvg . y ) )
{
g . WheelingWindowWheelRemainder = wheel ;
return NULL ;
}
return ( g . WheelingAxisAvg . x > g . WheelingAxisAvg . y ) ? windows [ 0 ] : windows [ 1 ] ;
}
void ImGui : : UpdateMouseWheel ( )
{
ImGuiContext & g = * GImGui ;
// Reset the locked window if we move the mouse or after the timer elapses
// Reset the locked window if we move the mouse or after the timer elapses.
// FIXME: Ideally we could refactor to have one timer for "changing window w/ same axis" and a shorter timer for "changing window or axis w/ other axis" (#3795)
if ( g . WheelingWindow ! = NULL )
{
g . WheelingWindowReleaseTimer - = g . IO . DeltaTime ;
@ -4386,8 +4431,6 @@ void ImGui::UpdateMouseWheel()
ImVec2 wheel ;
wheel . x = TestKeyOwner ( ImGuiKey_MouseWheelX , ImGuiKeyOwner_None ) ? g . IO . MouseWheelH : 0.0f ;
wheel . y = TestKeyOwner ( ImGuiKey_MouseWheelY , ImGuiKeyOwner_None ) ? g . IO . MouseWheel : 0.0f ;
if ( wheel . x = = 0.0f & & wheel . y = = 0.0f )
return ;
//IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y);
ImGuiWindow * mouse_window = g . WheelingWindow ? g . WheelingWindow : g . HoveredWindow ;
@ -4425,39 +4468,41 @@ void ImGui::UpdateMouseWheel()
wheel . y = 0.0f ;
}
// Vertical Mouse Wheel scrolling
// Bubble up into parent window if:
// - a child window doesn't allow any scrolling.
// - a child window doesn't need scrolling because it is already at the edge for the direction we are going in.
// - a child window has the ImGuiWindowFlags_NoScrollWithMouse flag.
if ( wheel . y ! = 0.0f )
{
ImGuiWindow * window = mouse_window ;
while ( ( window - > Flags & ImGuiWindowFlags_ChildWindow ) & & ( ( window - > ScrollMax . y = = 0.0f ) | | ( ( window - > Flags & ImGuiWindowFlags_NoScrollWithMouse ) & & ! ( window - > Flags & ImGuiWindowFlags_NoMouseInputs ) ) ) )
window = window - > ParentWindow ;
if ( ! ( window - > Flags & ImGuiWindowFlags_NoScrollWithMouse ) & & ! ( window - > Flags & ImGuiWindowFlags_NoMouseInputs ) )
{
LockWheelingWindow ( mouse_window , wheel . y ) ;
float max_step = window - > InnerRect . GetHeight ( ) * 0.67f ;
float scroll_step = ImFloor ( ImMin ( 5 * window - > CalcFontSize ( ) , max_step ) ) ;
SetScrollY ( window , window - > Scroll . y - wheel . y * scroll_step ) ;
}
}
// Maintain a rough average of moving magnitude on both axises
// FIXME: should by based on wall clock time rather than frame-counter
g . WheelingAxisAvg . x = ImExponentialMovingAverage ( g . WheelingAxisAvg . x , ImAbs ( wheel . x ) , 30 ) ;
g . WheelingAxisAvg . y = ImExponentialMovingAverage ( g . WheelingAxisAvg . y , ImAbs ( wheel . y ) , 30 ) ;
// Horizontal Mouse Wheel scrolling, or Vertical Mouse Wheel w/ Shift held
if ( wheel . x ! = 0.0f )
{
ImGuiWindow * window = mouse_window ;
while ( ( window - > Flags & ImGuiWindowFlags_ChildWindow ) & & ( ( window - > ScrollMax . x = = 0.0f ) | | ( ( window - > Flags & ImGuiWindowFlags_NoScrollWithMouse ) & & ! ( window - > Flags & ImGuiWindowFlags_NoMouseInputs ) ) ) )
window = window - > ParentWindow ;
// In the rare situation where FindBestWheelingWindow() had to defer first frame of wheeling due to ambiguous main axis, reinject it now.
wheel + = g . WheelingWindowWheelRemainder ;
g . WheelingWindowWheelRemainder = ImVec2 ( 0.0f , 0.0f ) ;
if ( wheel . x = = 0.0f & & wheel . y = = 0.0f )
return ;
// Mouse wheel scrolling: find target and apply
// - don't renew lock if axis doesn't apply on the window.
// - select a main axis when both axises are being moved.
if ( ImGuiWindow * window = ( g . WheelingWindow ? g . WheelingWindow : FindBestWheelingWindow ( wheel ) ) )
if ( ! ( window - > Flags & ImGuiWindowFlags_NoScrollWithMouse ) & & ! ( window - > Flags & ImGuiWindowFlags_NoMouseInputs ) )
{
LockWheelingWindow ( mouse_window , wheel . x ) ;
float max_step = window - > InnerRect . GetWidth ( ) * 0.67f ;
float scroll_step = ImFloor ( ImMin ( 2 * window - > CalcFontSize ( ) , max_step ) ) ;
SetScrollX ( window , window - > Scroll . x - wheel . x * scroll_step ) ;
bool do_scroll [ 2 ] = { wheel . x ! = 0.0f & & window - > ScrollMax . x ! = 0.0f , wheel . y ! = 0.0f & & window - > ScrollMax . y ! = 0.0f } ;
if ( do_scroll [ ImGuiAxis_X ] & & do_scroll [ ImGuiAxis_Y ] )
do_scroll [ ( g . WheelingAxisAvg . x > g . WheelingAxisAvg . y ) ? ImGuiAxis_Y : ImGuiAxis_X ] = false ;
if ( do_scroll [ ImGuiAxis_X ] )
{
LockWheelingWindow ( window , wheel . x ) ;
float max_step = window - > InnerRect . GetWidth ( ) * 0.67f ;
float scroll_step = ImFloor ( ImMin ( 2 * window - > CalcFontSize ( ) , max_step ) ) ;
SetScrollX ( window , window - > Scroll . x - wheel . x * scroll_step ) ;
}
if ( do_scroll [ ImGuiAxis_Y ] )
{
LockWheelingWindow ( window , wheel . y ) ;
float max_step = window - > InnerRect . GetHeight ( ) * 0.67f ;
float scroll_step = ImFloor ( ImMin ( 5 * window - > CalcFontSize ( ) , max_step ) ) ;
SetScrollY ( window , window - > Scroll . y - wheel . y * scroll_step ) ;
}
}
}
}
// 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)
@ -8427,7 +8472,7 @@ static void DebugPrintInputEvent(const char* prefix, const ImGuiInputEvent* e)
ImGuiContext & g = * GImGui ;
if ( e - > Type = = ImGuiInputEventType_MousePos ) { if ( e - > MousePos . PosX = = - FLT_MAX & & e - > MousePos . PosY = = - FLT_MAX ) IMGUI_DEBUG_LOG_IO ( " %s: MousePos (-FLT_MAX, -FLT_MAX) \n " , prefix ) ; else IMGUI_DEBUG_LOG_IO ( " %s: MousePos (%.1f, %.1f) \ n " , prefix, e->MousePos.PosX, e->MousePos.PosY) ; return ; }
if ( e - > Type = = ImGuiInputEventType_MouseButton ) { IMGUI_DEBUG_LOG_IO ( " %s: MouseButton %d %s \n " , prefix , e - > MouseButton . Button , e - > MouseButton . Down ? " Down " : " Up " ) ; return ; }
if ( e - > Type = = ImGuiInputEventType_MouseWheel ) { IMGUI_DEBUG_LOG_IO ( " %s: MouseWheel (%.1f, %.1 f) \n " , prefix , e - > MouseWheel . WheelX , e - > MouseWheel . WheelY ) ; return ; }
if ( e - > Type = = ImGuiInputEventType_MouseWheel ) { IMGUI_DEBUG_LOG_IO ( " %s: MouseWheel (%.3f, %.3 f) \n " , prefix , e - > MouseWheel . WheelX , e - > MouseWheel . WheelY ) ; return ; }
if ( e - > Type = = ImGuiInputEventType_Key ) { IMGUI_DEBUG_LOG_IO ( " %s: Key \" %s \" %s \n " , prefix , ImGui : : GetKeyName ( e - > Key . Key ) , e - > Key . Down ? " Down " : " Up " ) ; return ; }
if ( e - > Type = = ImGuiInputEventType_Text ) { IMGUI_DEBUG_LOG_IO ( " %s: Text: %c (U+%08X) \n " , prefix , e - > Text . Char , e - > Text . Char ) ; return ; }
if ( e - > Type = = ImGuiInputEventType_Focus ) { IMGUI_DEBUG_LOG_IO ( " %s: AppFocused %d \n " , prefix , e - > AppFocused . Focused ) ; return ; }
@ -13409,6 +13454,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text ( " NavWindowingTarget: '%s' " , g . NavWindowingTarget ? g . NavWindowingTarget - > Name : " NULL " ) ;
Unindent ( ) ;
Text ( " MOUSE WHEELING " ) ;
Indent ( ) ;
Text ( " WheelingWindow: '%s' " , g . WheelingWindow ? g . WheelingWindow - > Name : " NULL " ) ;
Text ( " WheelingWindowReleaseTimer: %.2f " , g . WheelingWindowReleaseTimer ) ;
Text ( " WheelingAxisAvg[] = { %.3f, %.3f }, Main Axis: %s " , g . WheelingAxisAvg . x , g . WheelingAxisAvg . y , ( g . WheelingAxisAvg . x > g . WheelingAxisAvg . y ) ? " X " : ( g . WheelingAxisAvg . x < g . WheelingAxisAvg . y ) ? " Y " : " <none> " ) ;
Unindent ( ) ;
TreePop ( ) ;
}