From: Fabian Maurer Subject: [PATCH 2/2] user32: Send WM_NCPAINT and WM_ERASEBKGND when window is shown and add tests Message-Id: <20161222200117.8483-2-dark.shadow4@web.de> Date: Thu, 22 Dec 2016 21:01:17 +0100 In-Reply-To: <20161222200117.8483-1-dark.shadow4@web.de> References: <20161222200117.8483-1-dark.shadow4@web.de> Fixes Bug 2624 and 6682 Signed-off-by: Fabian Maurer --- dlls/user32/tests/msg.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ dlls/user32/winpos.c | 7 ++++ 2 files changed, 109 insertions(+) diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index f01314cf51..c95133f791 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -938,6 +938,79 @@ static const struct message WmShowPopupExtremeLocationSeq[] = { { WM_ERASEBKGND, sent|optional }, { 0 } }; +/* CreateWindow (for a popup window with WS_VISIBLE style set) + */ +static const struct message WmShowPopupFirstDrawSeq_1[] = { + { HCBT_CREATEWND, hook }, + { WM_NCCREATE, sent }, + { WM_NCCALCSIZE, sent|wparam, 0 }, + { WM_CREATE, sent }, + { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_SIZE, sent|wparam, SIZE_RESTORED }, + { WM_MOVE, sent }, + { WM_SHOWWINDOW, sent|wparam, 1 }, + { WM_WINDOWPOSCHANGING, sent }, + { HCBT_ACTIVATE, hook }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_QUERYNEWPALETTE, sent|optional }, + { WM_ACTIVATEAPP, sent }, + { WM_NCACTIVATE, sent }, + { WM_ACTIVATE, sent }, + { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, + { HCBT_SETFOCUS, hook }, + { WM_SETFOCUS, sent|defwinproc }, + { WM_NCPAINT, sent|wparam, 1 }, + { WM_ERASEBKGND, sent }, + { WM_WINDOWPOSCHANGED, sent }, + { WM_PAINT, sent }, + /* ocasionally received on test machines */ + { WM_NCPAINT, sent|beginpaint|optional }, + { WM_ERASEBKGND, sent|beginpaint|optional }, + { 0 } +}; +/* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED)) + */ +static const struct message WmShowPopupFirstDrawSeq_2[] = { + { HCBT_CREATEWND, hook }, + { WM_NCCREATE, sent }, + { WM_NCCALCSIZE, sent|wparam, 0 }, + { WM_CREATE, sent }, + { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_SIZE, sent|wparam, SIZE_RESTORED }, + { WM_MOVE, sent }, + { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, + { WM_GETMINMAXINFO, sent }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_STATECHANGED|SWP_SHOWWINDOW|SWP_FRAMECHANGED }, + { WM_NCCALCSIZE, sent|wparam, TRUE }, + { HCBT_ACTIVATE, hook }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_NCPAINT, sent|optional|wparam, 1 }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional }, + { WM_QUERYNEWPALETTE, sent|optional }, + { WM_ACTIVATEAPP, sent }, + { WM_NCACTIVATE, sent }, + { WM_ACTIVATE, sent }, + { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, + { HCBT_SETFOCUS, hook }, + { WM_SETFOCUS, sent|defwinproc }, + { WM_NCPAINT, sent|wparam, 1 }, + { WM_ERASEBKGND, sent }, + { WM_WINDOWPOSCHANGED, sent }, + { WM_MOVE, sent|defwinproc }, + { WM_SIZE, sent|defwinproc, 0 }, + { WM_PAINT, sent}, + /* ocasionally received on test machines */ + { WM_NCPAINT, sent|beginpaint|optional }, + { WM_ERASEBKGND, sent|beginpaint|optional }, + { 0 } +}; /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) * for a popup window with WS_VISIBLE style set */ @@ -4868,6 +4941,35 @@ static void test_messages(void) ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", FALSE); DestroyWindow(hwnd); + /* Test if window is correctly drawn when first shown - visible, redraw */ + flush_sequence(); + hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, + 10, 10, 100, 100, NULL, 0, 0, NULL ); + ok (hwnd != 0, "Failed to create popup window\n"); + RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); + ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_visible", FALSE); + DestroyWindow(hwnd); + + /* Test if window is correctly drawn when first shown - invisible, show, message */ + flush_sequence(); + hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, + 10, 10, 100, 100, NULL, 0, 0, NULL ); + ok (hwnd != 0, "Failed to create popup window\n"); + ShowWindow(hwnd, SW_SHOW); + SendMessageW(hwnd, WM_PAINT, 0, 0); + ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_show", FALSE); + DestroyWindow(hwnd); + + /* Test if window is correctly drawn when first shown - invisible, show maximized, redraw */ + flush_sequence(); + hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, + 10, 10, 100, 100, NULL, 0, 0, NULL ); + ok (hwnd != 0, "Failed to create popup window\n"); + ShowWindow(hwnd, SW_SHOWMAXIMIZED); + RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); + ok_sequence(WmShowPopupFirstDrawSeq_2, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE); + DestroyWindow(hwnd); + hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n"); diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 2fa194fa1c..0d5351e5f4 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -2254,6 +2254,13 @@ BOOL USER_SetWindowPos( WINDOWPOS * winpos ) SetForegroundWindow( winpos->hwnd ); } + /* Give newly shown windows a chance to redraw, skip unchanged windows to not send too many messages */ + if(orig_flags & SWP_SHOWWINDOW && + ((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)) + { + RedrawWindow( winpos->hwnd, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); + } + /* And last, send the WM_WINDOWPOSCHANGED message */ TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS); -- 2.11.0