[PATCH v2 2/2] user32/listbox: Handle Mouse Wheel scrolling for multi-column listboxes properly

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Aug 22 15:41:46 CDT 2018


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.

The calculation has also 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, so the float cast was useless. This
works fine because the multiplication is done before the division (parentheses
have been added to emphasize this point).

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22253
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---

v2: Use a signed variable to get rid of some casts.

 dlls/user32/listbox.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c
index 3f1396d..14a1dee 100644
--- a/dlls/user32/listbox.c
+++ b/dlls/user32/listbox.c
@@ -1993,9 +1993,11 @@ 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;
+    UINT tmp = 3;
 
-    SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
+    SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &tmp, 0);
+    pulScrollLines = tmp;
 
     /* if scrolling changes direction, ignore left overs */
     if ((delta < 0 && descr->wheel_remain < 0) ||
@@ -2006,10 +2008,21 @@ 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;
+        INT cLineScroll;
+        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 -= (cLineScroll * WHEEL_DELTA) / pulScrollLines;
+            cLineScroll *= descr->page_size;
+        }
+        else
+        {
+            pulScrollLines = min((UINT)descr->page_size, pulScrollLines);
+            cLineScroll = (pulScrollLines * descr->wheel_remain) / WHEEL_DELTA;
+            descr->wheel_remain -= (cLineScroll * WHEEL_DELTA) / pulScrollLines;
+        }
         LISTBOX_SetTopItem( descr, descr->top_item - cLineScroll, TRUE );
     }
     return 0;
-- 
1.9.1




More information about the wine-devel mailing list