From: Fabian Maurer Subject: [PATCH 1/2] user32: Fix WM_NCPAINT for windows crossing screen boarders and add tests Message-Id: <20161222200117.8483-1-dark.shadow4@web.de> Date: Thu, 22 Dec 2016 21:01:16 +0100 Windows that are partially off-screen still receive WM_NCPAINT with wParam==1 instead of an actual HRGN Signed-off-by: Fabian Maurer --- dlls/user32/painting.c | 10 ++++++++++ dlls/user32/tests/msg.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index 622dcad845..62d29bdfe5 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -662,7 +662,17 @@ static HRGN send_ncpaint( HWND hwnd, HWND *child, UINT *flags ) if (type == SIMPLEREGION) { RECT window; + LONG screenx = GetSystemMetrics(SM_CXSCREEN); + LONG screeny = GetSystemMetrics(SM_CYSCREEN); + GetWindowRect( hwnd, &window ); + + /* Clamp the window region to screen bounds */ + if(window.right > screenx) window.right = screenx; + if(window.bottom > screeny) window.bottom = screeny; + if(window.left < 0) window.left = 0; + if(window.top < 0) window.top = 0; + if (EqualRect( &window, &update )) { DeleteObject( whole_rgn ); diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 45b5222deb..f01314cf51 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -905,6 +905,39 @@ static const struct message WmShowVisiblePopupSeq_2[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { 0 } }; +/* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location) + */ +static const struct message WmShowPopupExtremeLocationSeq[] = { + { 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_WINDOWPOSCHANGED, sent|optional }, /* optional, wrongly sent in wine */ + { WM_NCPAINT, sent|wparam, 1 }, + { WM_ERASEBKGND, sent }, + { WM_WINDOWPOSCHANGED, sent|optional }, /* optional, correct behavior, we check this in a different test */ + /* ocasionally received on test machines */ + { WM_NCPAINT, sent|optional }, + { WM_ERASEBKGND, sent|optional }, + { 0 } +}; /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) * for a popup window with WS_VISIBLE style set */ @@ -4826,6 +4859,15 @@ static void test_messages(void) DestroyWindow(hwnd); ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE); + /* Test message sequence for extreme position and size */ + flush_sequence(); + hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, + -10, -10, 10000, 10000, NULL, 0, 0, NULL ); + ok (hwnd != 0, "Failed to create popup window\n"); + RedrawWindow(hwnd, NULL, 0, RDW_ERASENOW); /* currently needed to avoid another issue */ + ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", 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"); -- 2.11.0