[PATCH] comctl32: Improve hit testing and invalidation for sub items.

Jim Mussared jim.mussared at gmail.com
Tue Sep 18 02:35:41 CDT 2018


These fixes are for "Vectric Cut2D" which uses listview to show
document layers. See referenced bug for more details. The layer list
uses clickable subitems for:
 - toggling visibility of the layer
 - color swatch (click to edit color)
 - menu (click to show the right-click menu)
 (all of these are activated on mouse up)

At the moment, the sub items are not clickable in Wine. Additionally,
they do not update when the layer changes state.

This patch fixes three things:
 - When hit testing, the sub items's coordinates are relative to the
 item. So the mouse coordinate (opt) will be outside the bounds of the
 item (rcBounds), and fail the hit test.
 Skip this check when not doing a selection hit test (which applies to
 mouse up).
 - InvalidateItem only invalidates the region of the primary item. Now
 also invalidate all sub-items.
 - InvalidateSubItem calculated the position of the subitem
 incorrectly (it's offset by the left edge of the main item).

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=44794
Signed-off-by: Jim Mussared <jim.mussared at gmail.com>
---
 dlls/comctl32/listview.c | 41 ++++++++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 777b40f2fe..1440581f71 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -1725,38 +1725,46 @@ static inline BOOL is_redrawing(const
LISTVIEW_INFO *infoPtr)

 static inline void LISTVIEW_InvalidateRect(const LISTVIEW_INFO
*infoPtr, const RECT* rect)
 {
-    if(!is_redrawing(infoPtr)) return;
+    if(!is_redrawing(infoPtr)) return;
     TRACE(" invalidating rect=%s\n", wine_dbgstr_rect(rect));
     InvalidateRect(infoPtr->hwndSelf, rect, TRUE);
 }

-static inline void LISTVIEW_InvalidateItem(const LISTVIEW_INFO
*infoPtr, INT nItem)
-{
-    RECT rcBox;
-
-    if (!is_redrawing(infoPtr) || nItem < 0 || nItem >= infoPtr->nItemCount)
-        return;
-
-    LISTVIEW_GetItemBox(infoPtr, nItem, &rcBox);
-    LISTVIEW_InvalidateRect(infoPtr, &rcBox);
-}
-
 static inline void LISTVIEW_InvalidateSubItem(const LISTVIEW_INFO
*infoPtr, INT nItem, INT nSubItem)
 {
     POINT Origin, Position;
     RECT rcBox;
-
-    if(!is_redrawing(infoPtr)) return;
+
+    if(!is_redrawing(infoPtr)) return;
     assert (infoPtr->uView == LV_VIEW_DETAILS);
     LISTVIEW_GetOrigin(infoPtr, &Origin);
     LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position);
     LISTVIEW_GetHeaderRect(infoPtr, nSubItem, &rcBox);
     rcBox.top = 0;
     rcBox.bottom = infoPtr->nItemHeight;
-    OffsetRect(&rcBox, Origin.x + Position.x, Origin.y + Position.y);
+    OffsetRect(&rcBox, Origin.x, Origin.y + Position.y);
     LISTVIEW_InvalidateRect(infoPtr, &rcBox);
 }

+static inline void LISTVIEW_InvalidateItem(const LISTVIEW_INFO
*infoPtr, INT nItem)
+{
+    RECT rcBox;
+
+    if (!is_redrawing(infoPtr) || nItem < 0 || nItem >= infoPtr->nItemCount)
+        return;
+
+    LISTVIEW_GetItemBox(infoPtr, nItem, &rcBox);
+    LISTVIEW_InvalidateRect(infoPtr, &rcBox);
+
+    /* Additionally invalidate all other sub-items.
+       The first sub-item is handled by GetItemBox above. */
+    if (infoPtr->uView == LV_VIEW_DETAILS) {
+        INT nSubItem;
+       for (nSubItem = 1; nSubItem <
DPA_GetPtrCount(infoPtr->hdpaColumns); nSubItem++)
+            LISTVIEW_InvalidateSubItem(infoPtr, nItem, nSubItem);
+    }
+}
+
 static inline void LISTVIEW_InvalidateList(const LISTVIEW_INFO *infoPtr)
 {
     LISTVIEW_InvalidateRect(infoPtr, NULL);
@@ -7741,8 +7749,9 @@ static INT LISTVIEW_HitTest(const LISTVIEW_INFO
*infoPtr, LPLVHITTESTINFO lpht,
         UnionRect(&rcBounds, &rcIcon, &rcLabel);
         UnionRect(&rcBounds, &rcBounds, &rcState);
     }
+
     TRACE("rcBounds=%s\n", wine_dbgstr_rect(&rcBounds));
-    if (!PtInRect(&rcBounds, opt)) return -1;
+    if (select && !PtInRect(&rcBounds, opt)) return -1;

     /* That's a special case - row rectangle is used as item rectangle and
        returned flags contain all item parts. */
--
2.19.0



More information about the wine-devel mailing list