[PATCH 0/2] MR8327: comctl32/listview: Always set the initial background mode to TRANSPARENT.
Comctl32 v5 listview sets the initial background mix mode to TRANSPARENT. Comctl32 v6 listview sets it to OPAQUE. Use TRANSPARENT for both v5 and v6 for now. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/8327
From: Zhiyi Zhang <zzhang(a)codeweavers.com> --- dlls/comctl32/tests/listview.c | 104 ++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c index b767106e97a..386fde36939 100644 --- a/dlls/comctl32/tests/listview.c +++ b/dlls/comctl32/tests/listview.c @@ -2083,6 +2083,7 @@ static void test_redraw(void) static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee); + int mode; if(message == WM_NOTIFY) { NMHDR *nmhdr = (NMHDR*)lParam; @@ -2102,9 +2103,15 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM switch(nmlvcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: + mode = GetBkMode(nmlvcd->nmcd.hdc); + todo_wine + ok(mode == TRANSPARENT, "Got unexpected mode.\n"); SetBkColor(nmlvcd->nmcd.hdc, c0ffee); return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPREPAINT: + mode = GetBkMode(nmlvcd->nmcd.hdc); + todo_wine + ok(mode == TRANSPARENT, "Got unexpected mode.\n"); clr = GetBkColor(nmlvcd->nmcd.hdc); todo_wine_if(nmlvcd->iSubItem) ok(clr == c0ffee, "Unexpected background color %#lx.\n", clr); @@ -2112,6 +2119,9 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM nmlvcd->clrText = RGB(0, 255, 0); return CDRF_NOTIFYSUBITEMDRAW|CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPREPAINT | CDDS_SUBITEM: + mode = GetBkMode(nmlvcd->nmcd.hdc); + todo_wine + ok(mode == TRANSPARENT, "Got unexpected mode.\n"); clr = GetBkColor(nmlvcd->nmcd.hdc); ok(nmlvcd->clrTextBk == CLR_DEFAULT, "Unexpected text background %#lx.\n", nmlvcd->clrTextBk); ok(nmlvcd->clrText == RGB(0, 255, 0), "Unexpected text color %#lx.\n", nmlvcd->clrText); @@ -2122,6 +2132,9 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM ok(clr == c0ffee, "clr=%.8lx\n", clr); return CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM: + mode = GetBkMode(nmlvcd->nmcd.hdc); + todo_wine + ok(mode == TRANSPARENT, "Got unexpected mode.\n"); clr = GetBkColor(nmlvcd->nmcd.hdc); if (showsel_always && is_selected) ok(clr == GetSysColor(COLOR_3DFACE), "Unexpected background color %#lx.\n", clr); @@ -2144,62 +2157,73 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM static void test_customdraw(void) { + static const COLORREF test_colors[] = {CLR_DEFAULT, CLR_NONE, RGB(255, 0, 0)}; HWND hwnd; WNDPROC oldwndproc; LVITEMA item; + int i; - hwnd = create_listview_control(LVS_REPORT); + for (i = 0; i < ARRAY_SIZE(test_colors); i++) + { + winetest_push_context("color %#x", i); - insert_column(hwnd, 0); - insert_column(hwnd, 1); - insert_item(hwnd, 0); + hwnd = create_listview_control(LVS_REPORT); - oldwndproc = (WNDPROC)SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, - (LONG_PTR)cd_wndproc); + insert_column(hwnd, 0); + insert_column(hwnd, 1); + insert_item(hwnd, 0); + SendMessageA(hwnd, LVM_SETTEXTBKCOLOR, 0, test_colors[i]); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); + oldwndproc = (WNDPROC)SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, + (LONG_PTR)cd_wndproc); - /* message tests */ - flush_sequences(sequences, NUM_MSG_SEQUENCES); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT", FALSE); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); - /* Check colors when item is selected. */ - item.mask = LVIF_STATE; - item.stateMask = LVIS_SELECTED; - item.state = LVIS_SELECTED; - SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); + /* message tests */ + flush_sequences(sequences, NUM_MSG_SEQUENCES); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT", FALSE); - flush_sequences(sequences, NUM_MSG_SEQUENCES); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, - "parent customdraw, item selected, LVS_REPORT, selection", FALSE); + /* Check colors when item is selected. */ + item.mask = LVIF_STATE; + item.stateMask = LVIS_SELECTED; + item.state = LVIS_SELECTED; + SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); - SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | LVS_SHOWSELALWAYS); - flush_sequences(sequences, NUM_MSG_SEQUENCES); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, - "parent customdraw, item selected, LVS_SHOWSELALWAYS, LVS_REPORT", FALSE); + flush_sequences(sequences, NUM_MSG_SEQUENCES); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, + "parent customdraw, item selected, LVS_REPORT, selection", FALSE); - DestroyWindow(hwnd); + SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | LVS_SHOWSELALWAYS); + flush_sequences(sequences, NUM_MSG_SEQUENCES); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, + "parent customdraw, item selected, LVS_SHOWSELALWAYS, LVS_REPORT", FALSE); - hwnd = create_listview_control(LVS_LIST); + DestroyWindow(hwnd); - insert_column(hwnd, 0); - insert_column(hwnd, 1); - insert_item(hwnd, 0); + hwnd = create_listview_control(LVS_LIST); - flush_sequences(sequences, NUM_MSG_SEQUENCES); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_list_cd_seq, "parent customdraw, LVS_LIST", FALSE); + insert_column(hwnd, 0); + insert_column(hwnd, 1); + insert_item(hwnd, 0); + SendMessageA(hwnd, LVM_SETTEXTBKCOLOR, 0, test_colors[i]); - SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc); - DestroyWindow(hwnd); + flush_sequences(sequences, NUM_MSG_SEQUENCES); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_list_cd_seq, "parent customdraw, LVS_LIST", FALSE); + + SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc); + DestroyWindow(hwnd); + + winetest_pop_context(); + } } static void test_icon_spacing(void) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8327
From: Zhiyi Zhang <zzhang(a)codeweavers.com> Comctl32 v5 listview sets the initial background mix mode to TRANSPARENT. Comctl32 v6 listview sets it to OPAQUE. Use TRANSPARENT for both v5 and v6 for now. --- dlls/comctl32/listview.c | 10 +++------- dlls/comctl32/tests/listview.c | 4 ---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index 31f8a933e56..c5709cf2a4b 100644 --- a/dlls/comctl32/listview.c +++ b/dlls/comctl32/listview.c @@ -1120,13 +1120,7 @@ static void prepaint_setup (const LISTVIEW_INFO *infoPtr, HDC hdc, const NMLVCUS textcolor = comctl32_color.clrWindowText; /* Set the text attributes */ - if (backcolor != CLR_NONE) - { - SetBkMode(hdc, OPAQUE); - SetBkColor(hdc, backcolor); - } - else - SetBkMode(hdc, TRANSPARENT); + SetBkColor(hdc, backcolor); SetTextColor(hdc, textcolor); } @@ -5271,6 +5265,8 @@ static void LISTVIEW_Refresh(LISTVIEW_INFO *infoPtr, HDC hdc, const RECT *prcEra GetClientRect(infoPtr->hwndSelf, &rcClient); customdraw_fill(&nmlvcd, infoPtr, hdc, &rcClient, 0); + /* v5 sets the initial background mix mode to TRANSPARENT while v6 uses OPAQUE. */ + SetBkMode(hdc, TRANSPARENT); cdmode = notify_customdraw(infoPtr, CDDS_PREPAINT, &nmlvcd); if (cdmode & CDRF_SKIPDEFAULT) goto enddraw; diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c index 386fde36939..bf5afd694c3 100644 --- a/dlls/comctl32/tests/listview.c +++ b/dlls/comctl32/tests/listview.c @@ -2104,13 +2104,11 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM switch(nmlvcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: mode = GetBkMode(nmlvcd->nmcd.hdc); - todo_wine ok(mode == TRANSPARENT, "Got unexpected mode.\n"); SetBkColor(nmlvcd->nmcd.hdc, c0ffee); return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPREPAINT: mode = GetBkMode(nmlvcd->nmcd.hdc); - todo_wine ok(mode == TRANSPARENT, "Got unexpected mode.\n"); clr = GetBkColor(nmlvcd->nmcd.hdc); todo_wine_if(nmlvcd->iSubItem) @@ -2120,7 +2118,6 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM return CDRF_NOTIFYSUBITEMDRAW|CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPREPAINT | CDDS_SUBITEM: mode = GetBkMode(nmlvcd->nmcd.hdc); - todo_wine ok(mode == TRANSPARENT, "Got unexpected mode.\n"); clr = GetBkColor(nmlvcd->nmcd.hdc); ok(nmlvcd->clrTextBk == CLR_DEFAULT, "Unexpected text background %#lx.\n", nmlvcd->clrTextBk); @@ -2133,7 +2130,6 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM return CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM: mode = GetBkMode(nmlvcd->nmcd.hdc); - todo_wine ok(mode == TRANSPARENT, "Got unexpected mode.\n"); clr = GetBkColor(nmlvcd->nmcd.hdc); if (showsel_always && is_selected) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8327
Nikolay Sivov (@nsivov) commented about dlls/comctl32/listview.c:
GetClientRect(infoPtr->hwndSelf, &rcClient); customdraw_fill(&nmlvcd, infoPtr, hdc, &rcClient, 0); + /* v5 sets the initial background mix mode to TRANSPARENT while v6 uses OPAQUE. */ + SetBkMode(hdc, TRANSPARENT); cdmode = notify_customdraw(infoPtr, CDDS_PREPAINT, &nmlvcd); if (cdmode & CDRF_SKIPDEFAULT) goto enddraw;
I don't think we can do that unconditionally, a lot of application were never tested with v5 and very likely depend on such differences. I know that we don't run some of the painting tests on v6 at the moment. Splitting them up and having a separate test for background mode that runs on v5 and v6 is what we should do. We might do a separate v6 build in theory, but I suspect that will be avoided for as long as possible. It should be enough to check for windows class in current context in WM_NCCREATE (and maybe for actual class name too if it's possible to use versioned name directly, I don't remember). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/8327#note_106700
participants (3)
-
Nikolay Sivov (@nsivov) -
Zhiyi Zhang -
Zhiyi Zhang (@zhiyi)