Clipper: further mitigation/improvements for abnormally large contents ranges (larger than e.g. 2^31). (#3609, #8215)

This commit is contained in:
ocornut
2025-05-30 21:11:23 +02:00
parent 87a6443c5b
commit c53c9a8644
3 changed files with 11 additions and 3 deletions

View File

@@ -108,6 +108,7 @@ Other changes:
- TextLinkOpenURL(): added bool return value on click. (#8645, #8451, #7660) - TextLinkOpenURL(): added bool return value on click. (#8645, #8451, #7660)
- Scroll: fixed contents size, scrollbar visibility and scrolling resetting issues - Scroll: fixed contents size, scrollbar visibility and scrolling resetting issues
with abnormally large contents ranges. (#3609, #8215) with abnormally large contents ranges. (#3609, #8215)
- Clipper: some mitigation/improvements for abnormally large contents ranges. (#3609, #8215)
- Nav: fixed assertion when holding gamepad FaceLeft/West button to open - Nav: fixed assertion when holding gamepad FaceLeft/West button to open
CTRL+Tab windowing + pressing a keyboard key. (#8525) CTRL+Tab windowing + pressing a keyboard key. (#8525)
- Error Handling: added better error report and recovery for extraneous - Error Handling: added better error report and recovery for extraneous

View File

@@ -3195,10 +3195,17 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
if (table) if (table)
IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y); IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
clipper->ItemsHeight = (window->DC.CursorPos.y - clipper->StartPosY) / (float)(clipper->DisplayEnd - clipper->DisplayStart); bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision((float)clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
if (affected_by_floating_point_precision) if (affected_by_floating_point_precision)
{
// Mitigation/hack for very large range: assume last time height constitute line height.
clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries.
window->DC.CursorPos.y = (float)(clipper->StartPosY + clipper->ItemsHeight);
}
else
{
clipper->ItemsHeight = (float)(window->DC.CursorPos.y - clipper->StartPosY) / (float)(clipper->DisplayEnd - clipper->DisplayStart);
}
if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX) // Accept that no item have been submitted if in indeterminate mode. if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX) // Accept that no item have been submitted if in indeterminate mode.
return false; return false;
IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!");

View File

@@ -2708,7 +2708,7 @@ struct ImGuiListClipper
int DisplayEnd; // End of items to display (exclusive) int DisplayEnd; // End of items to display (exclusive)
int ItemsCount; // [Internal] Number of items int ItemsCount; // [Internal] Number of items
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed double StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows. double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows.
void* TempData; // [Internal] Internal data void* TempData; // [Internal] Internal data