Multi-column listboxes scroll horizontally, so each wheel tick must go an entire page at a time instead of an item at a time. But we have to limit the amount of scrolling in this case to avoid "jumping over" columns, if the window is too small. This matches Windows behavior.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22253 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
These notes apply to all the patches in the series. The calculation has been simplified to just integer arithmetic in all cases, since the division (the only operation with a fractional result) was immediately truncated to integer anyway and didn't help with overflow either, because the line that assigns to descr->wheel_remain operates on integers, so if it overflowed in the initial float operation, it would overflow on this line anyway.
In other words, the current code didn't protect from overflow, so we can simply get rid of the float cast (WHEEL_DELTA is too small for overflow to be a concern, though).
dlls/comctl32/listbox.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/dlls/comctl32/listbox.c b/dlls/comctl32/listbox.c index 8fd556c..991baac 100644 --- a/dlls/comctl32/listbox.c +++ b/dlls/comctl32/listbox.c @@ -2068,7 +2068,7 @@ static LRESULT LISTBOX_HandleHScroll( LB_DESCR *descr, WORD scrollReq, WORD pos
static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta ) { - UINT pulScrollLines = 3; + INT pulScrollLines = 3;
SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
@@ -2082,9 +2082,20 @@ static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta ) if (descr->wheel_remain && pulScrollLines) { int cLineScroll; - pulScrollLines = min((UINT) descr->page_size, pulScrollLines); - cLineScroll = pulScrollLines * (float)descr->wheel_remain / WHEEL_DELTA; - descr->wheel_remain -= WHEEL_DELTA * cLineScroll / (int)pulScrollLines; + if (descr->style & LBS_MULTICOLUMN) + { + pulScrollLines = min((UINT)descr->width / descr->column_width, pulScrollLines); + pulScrollLines = max(1u, pulScrollLines); + cLineScroll = (pulScrollLines * descr->wheel_remain) / WHEEL_DELTA; + descr->wheel_remain -= (WHEEL_DELTA * cLineScroll) / pulScrollLines; + cLineScroll *= descr->page_size; + } + else + { + pulScrollLines = min((UINT)descr->page_size, pulScrollLines); + cLineScroll = (pulScrollLines * descr->wheel_remain) / WHEEL_DELTA; + descr->wheel_remain -= (WHEEL_DELTA * cLineScroll) / pulScrollLines; + } LISTBOX_SetTopItem( descr, descr->top_item - cLineScroll, TRUE ); } return 0;