Extracted from https://gitlab.winehq.org/wine/wine/-/merge_requests/5665.
-- v2: user32/tests: Add a message test for listbox redrawing after LB_SETCOUNT. user32/tests: Test BeginPaint() clipbox of cropped window with CS_PARENTDC.
From: Jinoh Kang jinoh.kang.kr@gmail.com
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/user32/tests/dce.c | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/dlls/user32/tests/dce.c b/dlls/user32/tests/dce.c index 18f31e3708c..09c6dd0da54 100644 --- a/dlls/user32/tests/dce.c +++ b/dlls/user32/tests/dce.c @@ -525,6 +525,55 @@ static void test_begin_paint(void) ReleaseDC( hwnd_parent, hdc ); }
+static void test_cropped_parentdc_paint_clipbox(void) +{ + /* Use WS_BORDER to differentiate window and client rects */ + const UINT common_style = WS_VISIBLE | WS_BORDER; + HWND hwnd_toplevel, hwnd_container, hwnd_child; + RECT parent_rect, expect_rect, toplevel_rect, rect; + POINT dot_pos = { 10, 10 }; + PAINTSTRUCT ps; + COLORREF cr; + HDC hdc; + + hwnd_toplevel = CreateWindowA( "static", NULL, WS_OVERLAPPED | common_style, + 400, 200, 100, 100, NULL, NULL, NULL, NULL ); + + /* Container window extends "outside" the top-level window (hence cropped) */ + hwnd_container = CreateWindowA( "static", NULL, WS_CHILD | common_style, + -40, -40, 180, 180, hwnd_toplevel, NULL, NULL, NULL ); + + hwnd_child = CreateWindowA( "parentdc_class", NULL, WS_CHILD | common_style, + 50, 50, 3, 3, hwnd_container, NULL, NULL, NULL ); + + RedrawWindow( hwnd_toplevel, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE ); + RedrawWindow( hwnd_child, NULL, 0, RDW_INVALIDATE ); + + hdc = BeginPaint( hwnd_child, &ps ); + GetClipBox( hdc, &rect ); + cr = SetPixel( hdc, dot_pos.x, dot_pos.y, RGB(255, 0, 0) ); + ok( cr != -1, "error drawing outside of window client area\n" ); + EndPaint( hwnd_child, &ps ); + + GetClientRect( hwnd_toplevel, &toplevel_rect ); + MapWindowPoints( hwnd_toplevel, hwnd_container, (POINT *)&toplevel_rect, 2); + GetClientRect( hwnd_container, &parent_rect ); + IntersectRect( &expect_rect, &toplevel_rect, &parent_rect ); + + MapWindowPoints( hwnd_child, hwnd_container, (POINT *)&rect, 2 ); + todo_wine + ok( EqualRect( &rect, &expect_rect ), "rect = %s, expected %s\n", + wine_dbgstr_rect( &rect ), wine_dbgstr_rect( &expect_rect ) ); + + hdc = GetDC( hwnd_container ); + MapWindowPoints( hwnd_child, hwnd_container, &dot_pos, 1 ); + todo_wine + ok( GetPixel( hdc, dot_pos.x, dot_pos.y ) == cr, "error drawing outside of window client area\n" ); + ReleaseDC( hwnd_container, hdc ); + + DestroyWindow( hwnd_toplevel ); +} + /* test ScrollWindow with window DCs */ static void test_scroll_window(void) { @@ -780,6 +829,7 @@ START_TEST(dce) test_parameters(); test_dc_visrgn(); test_begin_paint(); + test_cropped_parentdc_paint_clipbox(); test_scroll_window(); test_invisible_create(); test_dc_layout();
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/user32/tests/msg.c | 71 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 19d08196c1a..4f639097ba7 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -2374,6 +2374,7 @@ static BOOL after_end_dialog, test_def_id, paint_loop_done, wm_copydata_done; static int sequence_cnt, sequence_size; static struct recvd_message* sequence; static int log_all_parent_messages; +static int log_painting_messages; static CRITICAL_SECTION sequence_cs;
/* user32 functions */ @@ -17229,6 +17230,25 @@ static const struct message wm_lb_dblclick_0[] = { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, { 0 } }; +static const struct message wm_lb_setcount[] = +{ + { LB_SETCOUNT, sent|wparam|lparam, 100, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, + { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, + { WM_ERASEBKGND, sent|parent }, + { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, + { WM_SIZE, sent|defwinproc }, + { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, + { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam|msg_todo, OBJID_VSCROLL, 0 }, + { WM_USER, sent|wparam|lparam, 0, 0 }, + { WM_NCPAINT, sent|wparam|lparam, 1, 0 }, + { WM_ERASEBKGND, sent }, + { WM_CTLCOLORLISTBOX, sent|parent }, + { WM_USER+1, sent|wparam|lparam, 0, 0 }, + { 0 } +};
#define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
@@ -17241,10 +17261,11 @@ static LRESULT WINAPI listbox_hook_proc(HWND hwnd, UINT message, WPARAM wp, LPAR struct recvd_message msg;
/* do not log painting messages */ - if (message != WM_PAINT && + if ((log_painting_messages || + (message != WM_PAINT && message != WM_NCPAINT && message != WM_SYNCPAINT && - message != WM_ERASEBKGND && + message != WM_ERASEBKGND)) && message != WM_NCHITTEST && message != WM_GETTEXT && !ignore_message( message )) @@ -17289,11 +17310,57 @@ static void check_lb_state_dbg(HWND listbox, int count, int cur_sel,
static void test_listbox_messages(void) { + PAINTSTRUCT ps; + RECT rc, rc1; HWND parent, listbox; LRESULT ret;
parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); + + /* test listbox redrawing after LB_SETCOUNT */ + listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, + LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VSCROLL | WS_VISIBLE, + 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); + listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); + + UpdateWindow(listbox); + + check_lb_state(listbox, 0, LB_ERR, 0, 0); + + flush_sequence(); + + log_all_parent_messages++; + log_painting_messages++; + + ret = GetWindowLongA(listbox, GWL_STYLE); + ok((ret & (WS_VSCROLL | WS_HSCROLL)) == 0, "Listbox should not have scroll bars\n"); + + ret = SendMessageA(listbox, LB_SETCOUNT, 100, 0); + ok(ret == 0, "got %Id\n", ret); + ret = GetWindowLongA(listbox, GWL_STYLE); + ok((ret & (WS_VSCROLL | WS_HSCROLL)) == WS_VSCROLL, "Listbox should have vertical scroll bar\n"); + + SendMessageA(listbox, WM_USER, 0, 0); /* Mark */ + BeginPaint(listbox, &ps); + GetClientRect(parent, &rc1); + MapWindowPoints(parent, listbox, (POINT *)&rc1, 2); + GetClipBox(ps.hdc, &rc); + todo_wine + ok(EqualRect(&rc, &rc1), "hdc clipbox %s != parent client rect %s\n", wine_dbgstr_rect(&rc), wine_dbgstr_rect(&rc1)); + GetClientRect(listbox, &rc); + ok(EqualRect(&ps.rcPaint, &rc), "rcPaint %s != listbox client rect %s\n", wine_dbgstr_rect(&ps.rcPaint), wine_dbgstr_rect(&rc)); + EndPaint(listbox, &ps); + SendMessageA(listbox, WM_USER+1, 0, 0); /* Mark */ + + ok_sequence(wm_lb_setcount, "LB_SETCOUNT", FALSE); + flush_sequence(); + + log_painting_messages--; + log_all_parent_messages--; + + DestroyWindow(listbox); + /* with LBS_HASSTRINGS */ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE,
On Mon May 5 06:50:10 2025 +0000, Jinoh Kang wrote:
Fails on testbot https://testbot.winehq.org/JobDetails.pl?Key=158164
msg.c:17356: Test succeeded inside todo block: LB_SETCOUNT: 7: got winevent_hook 0x800e as expected
Many thanks for noticing this. Should be fixed in v2.
On Mon May 5 06:50:10 2025 +0000, Dmitry Timoshkov wrote:
Many thanks for noticing this. Should be fixed in v2.
I'm not sure actually. Testbot and GitLab CI disagrees on what tests should fail.
This is how GitLab CI fails now:
``` msg.c:17356:32.309 Test failed: LB_SETCOUNT: 4: the msg 0x0014 was expected, but got msg 0x0085 instead msg.c:17356:32.309 Test failed: LB_SETCOUNT: 5: the msg 0x0047 was expected, but got msg 0x0085 instead msg.c:17356:32.309 Test failed: LB_SETCOUNT: 6: the msg 0x0005 was expected, but got msg 0x0085 instead msg.c:17356:32.309 Test failed: LB_SETCOUNT: 7: the winevent_hook 0x800e was expected, but got msg 0x0085 instead msg.c:17356:32.309 Test failed: LB_SETCOUNT: 8: the winevent_hook 0x800b was expected, but got msg 0x0085 instead msg.c:17356:32.310 Test failed: LB_SETCOUNT: 10: the msg 0x0400 was expected, but got msg 0x0085 instead msg.c:17356:32.310 Test failed: LB_SETCOUNT: 11: in msg 0x0085 expecting wParam 0x1 got 0x5040082 msg.c:17356:32.310 Test failed: LB_SETCOUNT: 11: the msg 0x0085 was expected in child msg.c:17356:32.310 Test failed: LB_SETCOUNT: 12: the msg 0x0014 was expected in child msg.c:17356:32.310 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0047 instead msg.c:17356:32.310 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0005 instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got winevent_hook 0x800e instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got winevent_hook 0x800b instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0400 instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0085 instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0014 instead msg.c:8186:32.361 Test marked todo: WM_SETFOCUS on a ComboBox: 3: the msg 0x0111 was expected, but got ms ```
meanwhile testbot succeeds: https://testbot.winehq.org/JobDetails.pl?Key=158168
so maybe the test is a bit too strict and some messages in the sequence should be left omitted or something.
On Mon May 5 13:17:08 2025 +0000, Jinoh Kang wrote:
I'm not sure actually. Testbot and GitLab CI disagrees on what tests should fail. This is how GitLab CI fails now:
msg.c:17356:32.309 Test failed: LB_SETCOUNT: 4: the msg 0x0014 was expected, but got msg 0x0085 instead msg.c:17356:32.309 Test failed: LB_SETCOUNT: 5: the msg 0x0047 was expected, but got msg 0x0085 instead msg.c:17356:32.309 Test failed: LB_SETCOUNT: 6: the msg 0x0005 was expected, but got msg 0x0085 instead msg.c:17356:32.309 Test failed: LB_SETCOUNT: 7: the winevent_hook 0x800e was expected, but got msg 0x0085 instead msg.c:17356:32.309 Test failed: LB_SETCOUNT: 8: the winevent_hook 0x800b was expected, but got msg 0x0085 instead msg.c:17356:32.310 Test failed: LB_SETCOUNT: 10: the msg 0x0400 was expected, but got msg 0x0085 instead msg.c:17356:32.310 Test failed: LB_SETCOUNT: 11: in msg 0x0085 expecting wParam 0x1 got 0x5040082 msg.c:17356:32.310 Test failed: LB_SETCOUNT: 11: the msg 0x0085 was expected in child msg.c:17356:32.310 Test failed: LB_SETCOUNT: 12: the msg 0x0014 was expected in child msg.c:17356:32.310 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0047 instead msg.c:17356:32.310 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0005 instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got winevent_hook 0x800e instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got winevent_hook 0x800b instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0400 instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0085 instead msg.c:17356:32.311 Test failed: LB_SETCOUNT: 13: the msg 0x0134 was expected, but got msg 0x0014 instead msg.c:8186:32.361 Test marked todo: WM_SETFOCUS on a ComboBox: 3: the msg 0x0111 was expected, but got ms
meanwhile testbot succeeds: https://testbot.winehq.org/JobDetails.pl?Key=158168 so maybe the test is a bit too strict and some messages in the sequence should be left omitted or something.
I don't see these failures locally, and gitlab CI doesn't seem to me like a reliable enough reference.
On Mon May 5 14:16:38 2025 +0000, Dmitry Timoshkov wrote:
I don't see these failures locally, and gitlab CI doesn't seem to me like a reliable enough reference.
Fixing it doesn't seem difficult, just insert an optional `WM_NCPAINT` before `WM_ERASEBKGND` at index 4.