diff --git a/internal/core/model.rs b/internal/core/model.rs index cf878791028..e477d7388d9 100644 --- a/internal/core/model.rs +++ b/internal/core/model.rs @@ -1073,6 +1073,7 @@ impl Repeater { (inner.offset, first_item_y + vp_y) }; + let mut loop_count = 0; loop { // If there is a gap before the new_offset and the beginning of the visible viewport, // try to fill it with items. First look at items that are before new_offset in the @@ -1154,15 +1155,12 @@ impl Repeater { inner.instances.push((RepeatedInstanceState::Clean, Some(new_instance))); idx += 1; } - if y < listview_height && vp_y < zero { + if y < listview_height && vp_y < zero && loop_count < 3 { assert!(idx >= row_count); // we reached the end of the model, and we still have room. scroll a bit up. - let new_vp_y = vp_y + (listview_height - y); - // check that we actually did scroll (for very large lists we can exceed the precision of f32 and have an infinite loop) - if new_vp_y != vp_y { - vp_y = new_vp_y; - continue; - } + vp_y += listview_height - y; + loop_count += 1; + continue; } // Let's cleanup the instances that are not shown. diff --git a/tests/cases/elements/listview-millions.slint b/tests/cases/elements/listview-millions.slint index e3939dbf1d0..a5c3c4ec37e 100644 --- a/tests/cases/elements/listview-millions.slint +++ b/tests/cases/elements/listview-millions.slint @@ -72,6 +72,10 @@ assert_eq!(clicked.borrow().as_slice(), &[210000012]); slint_testing::send_mouse_click(&instance, 5., 263.); slint_testing::send_mouse_click(&instance, 5., 239.); assert_eq!(clicked.borrow().as_slice(), &[210000012, 210000013, 210000011]); + +// go all the way to the end, it shouldn't crash or loop forever +instance.set_viewport_y(-20. * (2130000000. - 5.)); +slint_testing::send_mouse_click(&instance, 5., 250.); ``` ```cpp @@ -124,6 +128,10 @@ assert.deepEqual(clicked, [210000012]); slintlib.private_api.send_mouse_click(instance, 5., 263.); slintlib.private_api.send_mouse_click(instance, 5., 239.); assert.deepEqual(clicked, [210000012, 210000013, 210000011]); + +// go all the way to the end, it shouldn't crash or loop forever +instance.viewport_y=(-20. * (2130000000. - 5.)); +slintlib.private_api.send_mouse_click(instance, 5., 250.); ```