When the listview expands or collapses an item it notifies the parent using the TVN_ITEMEXPANDING message. The parent can return true on this message and it prevents the treeview from expanding or collapsing the item. WINE does not let you deny TVN_ITEMEXPANDING by returning true.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53727
-- v10: comctl32/treeview: Allow treeview parent to deny treeview expansion. comctl32/tests: Add test to check if treeview expansion can be denied.
From: Jacob Czekalla jczekalla@codeweavers.com
--- dlls/comctl32/tests/treeview.c | 59 ++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-)
diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c index db4cc4fda71..5dd4fe12bdc 100644 --- a/dlls/comctl32/tests/treeview.c +++ b/dlls/comctl32/tests/treeview.c @@ -51,6 +51,7 @@ static const char *g_endedit_overwrite_contents; static char *g_endedit_overwrite_ptr; static HFONT g_customdraw_font; static BOOL g_v6; +static int g_reject_tvn_itemexpanding = 0;
#define NUM_MSG_SEQUENCES 3 #define TREEVIEW_SEQ_INDEX 0 @@ -1361,7 +1362,11 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, } case TVN_ITEMEXPANDINGA: { - UINT newmask = pTreeView->itemNew.mask & ~TVIF_CHILDREN; + UINT newmask; + + if (g_reject_tvn_itemexpanding) + return TRUE; + newmask = pTreeView->itemNew.mask & ~TVIF_CHILDREN; ok(newmask == (TVIF_HANDLE | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_PARAM | TVIF_STATE), "got wrong mask %x\n", pTreeView->itemNew.mask); @@ -1837,6 +1842,7 @@ static void test_expandnotify(void) HWND hTree; BOOL ret; TVITEMA item; + RECT rc;
hTree = create_treeview_control(0); fill_tree(hTree); @@ -1898,6 +1904,55 @@ static void test_expandnotify(void)
DestroyWindow(hTree);
+ /* check that expansion can be denied by parent */ + hTree = create_treeview_control(0); + fill_tree(hTree); + + g_reject_tvn_itemexpanding = 1; + memset(&item, 0, sizeof(item)); + item.mask = TVIF_STATE; + item.hItem = hRoot; + + SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)item.hItem); + g_reject_tvn_itemexpanding = 0; + + /* check if it's expanded */ + item.state = 0; + SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item); + todo_wine ok(!(item.state & TVIS_EXPANDED), "expected no expansion\n"); + + DestroyWindow(hTree); + + hTree = create_treeview_control(0); + fill_tree(hTree); + + memset(&item, 0, sizeof(item)); + item.hItem = hRoot; + item.mask = TVIF_STATE; + + SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)item.hItem); + + item.state = TVIS_EXPANDED; + SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item); + todo_wine ok(item.state & TVIS_EXPANDED, "expected expansion\n"); + + memset(&item, 0, sizeof(item)); + item.hItem = hRoot; + item.mask = TVIF_STATE; + *((HTREEITEM *)&rc) = item.hItem; + g_reject_tvn_itemexpanding = 1; + + /* simulate double click to get around TVIS_EXPANDEDONCE */ + SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc); + SendMessageA(hTree, WM_LBUTTONDBLCLK, MK_LBUTTON, MAKELPARAM(rc.left + ((rc.right - rc.left) / 2), rc.top + ((rc.bottom - rc.top) / 2))); + + item.state = TVIS_EXPANDED; + ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item); + todo_wine ok(item.state & TVIS_EXPANDED, "expected expansion\n"); + g_reject_tvn_itemexpanding = 0; + + DestroyWindow(hTree); + /* test TVM_GETITEMRECT inside TVN_ITEMEXPANDED notification */ hTree = create_treeview_control(0); fill_tree(hTree); @@ -3152,4 +3207,4 @@ START_TEST(treeview) test_TVM_SORTCHILDREN();
unload_v6_module(ctx_cookie, hCtx); -} +} \ No newline at end of file
From: Jacob Czekalla jczekalla@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53727 --- dlls/comctl32/tests/treeview.c | 6 +++--- dlls/comctl32/treeview.c | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c index 5dd4fe12bdc..a822fe4d0e6 100644 --- a/dlls/comctl32/tests/treeview.c +++ b/dlls/comctl32/tests/treeview.c @@ -1919,7 +1919,7 @@ static void test_expandnotify(void) /* check if it's expanded */ item.state = 0; SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item); - todo_wine ok(!(item.state & TVIS_EXPANDED), "expected no expansion\n"); + ok(!(item.state & TVIS_EXPANDED), "expected no expansion\n");
DestroyWindow(hTree);
@@ -1934,7 +1934,7 @@ static void test_expandnotify(void)
item.state = TVIS_EXPANDED; SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item); - todo_wine ok(item.state & TVIS_EXPANDED, "expected expansion\n"); + ok(item.state & TVIS_EXPANDED, "expected expansion\n");
memset(&item, 0, sizeof(item)); item.hItem = hRoot; @@ -1948,7 +1948,7 @@ static void test_expandnotify(void)
item.state = TVIS_EXPANDED; ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item); - todo_wine ok(item.state & TVIS_EXPANDED, "expected expansion\n"); + ok(item.state & TVIS_EXPANDED, "expected expansion\n"); g_reject_tvn_itemexpanding = 0;
DestroyWindow(hTree); diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c index e2a4280f131..b200bc7853e 100644 --- a/dlls/comctl32/treeview.c +++ b/dlls/comctl32/treeview.c @@ -3348,10 +3348,10 @@ static BOOL TREEVIEW_SendExpanding(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, UINT action) { - return !TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action, - TVIF_HANDLE | TVIF_STATE | TVIF_PARAM - | TVIF_IMAGE | TVIF_SELECTEDIMAGE, - 0, item); + return TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action, + TVIF_HANDLE | TVIF_STATE | TVIF_PARAM + | TVIF_IMAGE | TVIF_SELECTEDIMAGE, + 0, item); }
static VOID @@ -3383,8 +3383,8 @@ TREEVIEW_Collapse(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, if (!TREEVIEW_HasChildren(infoPtr, item)) return FALSE;
- if (bUser) - TREEVIEW_SendExpanding(infoPtr, item, action); + if (bUser && TREEVIEW_SendExpanding(infoPtr, item, action)) + return TRUE;
if (item->firstChild == NULL) return FALSE; @@ -3513,11 +3513,11 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, !(item->state & TVIS_EXPANDEDONCE)); if (sendsNotifications) { - if (!TREEVIEW_SendExpanding(infoPtr, item, TVE_EXPAND)) - { - TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n"); - return FALSE; - } + if (TREEVIEW_SendExpanding(infoPtr, item, TVE_EXPAND)) + { + TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n"); + return TRUE; + } } if (!item->firstChild) return FALSE;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147745
Your paranoid android.
=== debian11b (64 bit WoW report) ===
kernel32: comm.c:1586: Test failed: Unexpected time 1001, expected around 500
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000000E800DA, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/treeview.c:
!(item->state & TVIS_EXPANDEDONCE)); if (sendsNotifications) {
- if (!TREEVIEW_SendExpanding(infoPtr, item, TVE_EXPAND))
- {
TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n");
return FALSE;
- }
if (TREEVIEW_SendExpanding(infoPtr, item, TVE_EXPAND))
{
TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n");
return TRUE;
}
The indent width should be 4.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/treeview.c:
- /* check that expansion can be denied by parent */
- hTree = create_treeview_control(0);
- fill_tree(hTree);
- g_reject_tvn_itemexpanding = 1;
- memset(&item, 0, sizeof(item));
- item.mask = TVIF_STATE;
- item.hItem = hRoot;
- SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)item.hItem);
- g_reject_tvn_itemexpanding = 0;
- /* check if it's expanded */
- item.state = 0;
- SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
Please check the result from TVM_GETITEMA.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/treeview.c:
DestroyWindow(hTree);
- /* check that expansion can be denied by parent */
- hTree = create_treeview_control(0);
- fill_tree(hTree);
- g_reject_tvn_itemexpanding = 1;
- memset(&item, 0, sizeof(item));
- item.mask = TVIF_STATE;
You should set stateMask as well. Not setting it relies on an undocumented behavior. "If you are retrieving an item's state, set the bits of the stateMask member to indicate the bits to be returned in the state member."
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/treeview.c:
- /* check if it's expanded */
- item.state = 0;
- SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
- todo_wine ok(!(item.state & TVIS_EXPANDED), "expected no expansion\n");
- DestroyWindow(hTree);
- hTree = create_treeview_control(0);
- fill_tree(hTree);
- memset(&item, 0, sizeof(item));
- item.hItem = hRoot;
- item.mask = TVIF_STATE;
- SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)item.hItem);
I don't see TVE_COLLAPSE get tested. You should test expand and collapse when g_reject_tvn_itemexpanding is TRUE.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/treeview.c:
- item.hItem = hRoot;
- item.mask = TVIF_STATE;
- SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)item.hItem);
- item.state = TVIS_EXPANDED;
- SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
- todo_wine ok(item.state & TVIS_EXPANDED, "expected expansion\n");
- memset(&item, 0, sizeof(item));
- item.hItem = hRoot;
- item.mask = TVIF_STATE;
- *((HTREEITEM *)&rc) = item.hItem;
- g_reject_tvn_itemexpanding = 1;
- /* simulate double click to get around TVIS_EXPANDEDONCE */
If you test TVE_COLLAPSE, I don't think you need to send a double-click.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/treeview.c:
test_TVM_SORTCHILDREN(); unload_v6_module(ctx_cookie, hCtx);
-} +}
There should be a new line at the end.
On Thu Aug 15 10:00:39 2024 +0000, Zhiyi Zhang wrote:
If you test TVE_COLLAPSE, I don't think you need to send a double-click.
I tried sending TVE_COLLAPSE, but it didn't work because of the TVIS_EXPANDEDONCE flag. The TVN_ITEMEXPANDING message was not getting sent.
On Thu Aug 15 10:00:41 2024 +0000, Zhiyi Zhang wrote:
There should be a new line at the end.
I was wondering why it was like that, but couldn't figure it out.