From: Paul Gofman pgofman@codeweavers.com
--- dlls/user32/tests/win.c | 59 ++++++++++++++++++++++++++++++++++++ dlls/win32u/dce.c | 2 +- dlls/win32u/message.c | 2 +- dlls/win32u/win32u_private.h | 1 + 4 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 4c2af09d0c6..9ad10090902 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -6126,11 +6126,16 @@ static void test_AdjustWindowRect(void)
/* Global variables to trigger exit from loop */ static int redrawComplete, WMPAINT_count; +static HANDLE redraw_call_complete_event;
static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { + case WM_NCPAINT: + if (redraw_call_complete_event) + WaitForSingleObject(redraw_call_complete_event, INFINITE); + break; case WM_PAINT: WMPAINT_count++; if (WMPAINT_count > 10 && redrawComplete == 0) { @@ -6144,11 +6149,50 @@ static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LP return DefWindowProcA(hwnd, msg, wparam, lparam); }
+struct rdw_window_thread_param +{ + HANDLE ready_event; + HANDLE done_event; + HWND hwnd; +}; + +static DWORD WINAPI rdw_window_thread(void *param) +{ + struct rdw_window_thread_param *p = param; + DWORD ret; + MSG msg; + + p->hwnd = CreateWindowA("RedrawWindowClass", "Main Window", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, 100, 100, NULL, NULL, 0, NULL); + ShowWindow(p->hwnd, SW_MINIMIZE); + redrawComplete = FALSE; + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) + DispatchMessageA(&msg); + + redraw_call_complete_event = p->done_event; + SetEvent(p->ready_event); + while ((ret = MsgWaitForMultipleObjects(1, &p->done_event, FALSE, INFINITE, QS_SENDMESSAGE)) != WAIT_OBJECT_0) + { + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) + { + ok(msg.message != WM_NCPAINT, "got WM_NCPAINT.\n"); + DispatchMessageA(&msg); + } + } + redraw_call_complete_event = NULL; + WaitForSingleObject(redraw_call_complete_event, INFINITE); + + DestroyWindow(p->hwnd); + return 0; +} + /* Ensure we exit from RedrawNow regardless of invalidated area */ static void test_redrawnow(void) { + struct rdw_window_thread_param p; WNDCLASSA cls; HWND hwndMain; + HANDLE thread; BOOL ret;
cls.style = CS_DBLCLKS; @@ -6178,6 +6222,21 @@ static void test_redrawnow(void)
/* clean up */ DestroyWindow( hwndMain); + + /* When on the other thread, WM_NCPAINT is delivered through window proc but RedrawWindow does + * not wait for that. */ + p.ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + p.done_event = CreateEventW(NULL, TRUE, FALSE, NULL); + WMPAINT_count = 0; + thread = CreateThread(NULL, 0, rdw_window_thread, &p, 0, NULL); + WaitForSingleObject(p.ready_event, INFINITE); + + ret = RedrawWindow(p.hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN | RDW_ERASENOW | RDW_FRAME); + ok(ret, "ret %d.\n", ret); + + SetEvent(p.done_event); + WaitForSingleObject(thread, INFINITE); + CloseHandle(thread); }
struct parentdc_stat { diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 9041b5bbaaf..a3f48d623b0 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -1197,7 +1197,7 @@ static HRGN send_ncpaint( HWND hwnd, HWND *child, UINT *flags ) if (style & WS_VSCROLL) set_standard_scroll_painted( hwnd, SB_VERT, FALSE );
- send_message( hwnd, WM_NCPAINT, (WPARAM)whole_rgn, 0 ); + send_notify_message( hwnd, WM_NCPAINT, (WPARAM)whole_rgn, 0, FALSE ); } if (whole_rgn > (HRGN)1) NtGdiDeleteObjectApp( whole_rgn ); } diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 0045c8a54c0..5ee4d9a85fc 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2806,7 +2806,7 @@ LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) }
/* see SendNotifyMessageW */ -static BOOL send_notify_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) +BOOL send_notify_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) { struct send_message_info info;
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index a0b3e8c2e9e..ac164811142 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -447,6 +447,7 @@ extern LRESULT send_internal_message_timeout( DWORD dest_pid, DWORD dest_tid, UI extern LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; extern LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT flags, UINT timeout, PDWORD_PTR res_ptr, BOOL ansi ); +extern BOOL send_notify_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) DECLSPEC_HIDDEN;
/* rawinput.c */ extern BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) DECLSPEC_HIDDEN;