Fixes menu update in Diablo 1.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/user32/painting.c | 26 +++++++++++- dlls/user32/tests/win.c | 94 +++++++++++++++++++++++++++++++++++++++++ dlls/user32/win.h | 1 + 3 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index 313c5fa1e6..6ab53a2372 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -725,7 +725,20 @@ static BOOL send_erase( HWND hwnd, UINT flags, HRGN client_rgn, { /* don't erase if the clip box is empty */ if (type != NULLREGION) + { + WND *wnd_ptr; + need_erase = !SendMessageW( hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0 ); + if ((wnd_ptr = WIN_GetPtr( hwnd )) && wnd_ptr != WND_OTHER_PROCESS && wnd_ptr != WND_DESKTOP) + { + if (need_erase) + wnd_ptr->flags |= WIN_PS_NEED_ERASE_BKGND; + else + wnd_ptr->flags &= ~WIN_PS_NEED_ERASE_BKGND; + + WIN_ReleasePtr( wnd_ptr ); + } + } } if (!hdc_ret) release_dc( hwnd, hdc, TRUE ); } @@ -943,6 +956,7 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps ) BOOL erase; RECT rect; UINT flags = UPDATE_NONCLIENT | UPDATE_ERASE | UPDATE_PAINT | UPDATE_INTERNALPAINT | UPDATE_NOCHILDREN; + WND *wnd_ptr;
HideCaret( hwnd );
@@ -957,7 +971,17 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps ) release_dc( hwnd, hdc, TRUE ); return 0; } - lps->fErase = erase; + + if (!(wnd_ptr = WIN_GetPtr( hwnd )) || wnd_ptr == WND_OTHER_PROCESS || wnd_ptr == WND_DESKTOP) + { + lps->fErase = erase; + } + else + { + lps->fErase = !!(wnd_ptr->flags & WIN_PS_NEED_ERASE_BKGND); + WIN_ReleasePtr( wnd_ptr ); + } + lps->rcPaint = rect; lps->hdc = hdc; return hdc; diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 25d643f54a..c02af08a90 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -11830,6 +11830,99 @@ static void test_other_process_window(const char *argv0) DestroyWindow(hwnd); }
+static BOOL test_paintstruct_erase_bkgnd; +static BOOL test_paintstruct_wm_erasebkgnd_received; +static BOOL test_paintstruct_wm_paint_received, test_paintstruct_ferase; + +static LRESULT WINAPI paintstruct_erase_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + switch (msg) + { + case WM_ERASEBKGND: + { + test_paintstruct_wm_erasebkgnd_received = TRUE; + return test_paintstruct_erase_bkgnd; + } + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc; + + test_paintstruct_wm_paint_received = TRUE; + hdc = BeginPaint(hwnd, &ps); + ok(!!hdc, "Null hdc.\n"); + test_paintstruct_ferase = ps.fErase; + EndPaint(hwnd, &ps); + return 0; + } + } + return DefWindowProcA(hwnd, msg, wparam, lparam); +} + +static void test_paintstruct_erase(void) +{ + WNDCLASSA cls; + HWND hwnd; + BOOL ret; + + cls.style = 0; + cls.lpfnWndProc = paintstruct_erase_window_procA; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(0); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "paintstruct_erase_class"; + ret = RegisterClassA(&cls); + ok(ret, "Failed to register a test class.\n"); + + test_paintstruct_wm_paint_received = test_paintstruct_wm_erasebkgnd_received = FALSE; + test_paintstruct_erase_bkgnd = FALSE; + hwnd = CreateWindowExA(0, "paintstruct_erase_class", NULL, WS_POPUP | WS_VISIBLE, + 100, 100, 100, 100, 0, 0, NULL, NULL); + ok(!!hwnd, "CreateWindowEx failed.\n"); + + flush_events(TRUE); + ok(test_paintstruct_wm_erasebkgnd_received, "WM_ERASEBKGND not received.\n"); + ok(test_paintstruct_wm_paint_received, "WM_PAINT not received.\n"); + ok(test_paintstruct_ferase, "Unexpected fErase %#x.\n", test_paintstruct_ferase); + + test_paintstruct_wm_paint_received = test_paintstruct_wm_erasebkgnd_received = FALSE; + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + flush_events(TRUE); + ok(!test_paintstruct_wm_erasebkgnd_received, "WM_ERASEBKGND received.\n"); + ok(test_paintstruct_wm_paint_received, "WM_PAINT not received.\n"); + ok(test_paintstruct_ferase, "Unexpected fErase %#x.\n", test_paintstruct_ferase); + + test_paintstruct_wm_paint_received = test_paintstruct_wm_erasebkgnd_received = FALSE; + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + flush_events(TRUE); + ok(!test_paintstruct_wm_erasebkgnd_received, "WM_ERASEBKGND received.\n"); + ok(test_paintstruct_wm_paint_received, "WM_PAINT not received.\n"); + ok(test_paintstruct_ferase, "Unexpected fErase %#x.\n", test_paintstruct_ferase); + + test_paintstruct_erase_bkgnd = TRUE; + test_paintstruct_wm_paint_received = test_paintstruct_wm_erasebkgnd_received = FALSE; + RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); + flush_events(TRUE); + ok(test_paintstruct_wm_erasebkgnd_received, "WM_ERASEBKGND not received.\n"); + ok(test_paintstruct_wm_paint_received, "WM_PAINT not received.\n"); + ok(!test_paintstruct_ferase, "Unexpected fErase %#x.\n", test_paintstruct_ferase); + + test_paintstruct_wm_paint_received = test_paintstruct_wm_erasebkgnd_received = FALSE; + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + flush_events(TRUE); + ok(!test_paintstruct_wm_erasebkgnd_received, "WM_ERASEBKGND received.\n"); + ok(test_paintstruct_wm_paint_received, "WM_PAINT not received.\n"); + ok(!test_paintstruct_ferase, "Unexpected fErase %#x.\n", test_paintstruct_ferase); + + DestroyWindow(hwnd); + UnregisterClassA("paintstruct_erase_class", GetModuleHandleA(NULL)); +} + START_TEST(win) { char **argv; @@ -11995,6 +12088,7 @@ START_TEST(win) test_window_placement(); test_arrange_iconic_windows(); test_other_process_window(argv[0]); + test_paintstruct_erase();
/* add the tests above this line */ if (hhook) UnhookWindowsHookEx(hhook); diff --git a/dlls/user32/win.h b/dlls/user32/win.h index 1f51fd6331..eecfa20eea 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -79,6 +79,7 @@ typedef struct tagWND #define WIN_NEEDS_SHOW_OWNEDPOPUP 0x0020 /* WM_SHOWWINDOW:SC_SHOW must be sent in the next ShowOwnedPopup call */ #define WIN_CHILDREN_MOVED 0x0040 /* children may have moved, ignore stored positions */ #define WIN_HAS_IME_WIN 0x0080 /* the window has been registered with imm32 */ +#define WIN_PS_NEED_ERASE_BKGND 0x0100 /* Need to set fErase in PAINTSTRUCT */
/* Window functions */ extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=69084
Your paranoid android.
=== w1064v1809 (32 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 0003004E win.c:3188: Test failed: GetActiveWindow() = 0003004E win.c:3889: Test failed: hwnd 00020174/00050176 message 0737 win.c:3894: Test failed: hwnd 00050176/00050176 message 0202 win.c:3899: Test failed: hwnd 00050176/00050176 message 0203
=== w1064v1809_2scr (32 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 000301CA win.c:3167: Test failed: GetFocus() = 00000000 win.c:3179: Test failed: GetFocus() = 00000000 win.c:3182: Test failed: GetFocus() = 00000000 win.c:3185: Test failed: GetFocus() = 00000000 win.c:3188: Test failed: GetActiveWindow() = 000301CA win.c:3192: Test failed: GetFocus() = 00000000 win.c:3195: Test failed: GetFocus() = 00000000 win.c:3889: Test failed: hwnd 000201A2/000B0328 message 0737 win.c:3894: Test failed: hwnd 000B0328/000B0328 message 0202 win.c:3899: Test failed: hwnd 000B0328/000B0328 message 0203 win.c:3903: Test failed: message 0202 available
=== w1064v1809_ar (32 bit report) ===
user32: win.c:9436: Test failed: didn't get start_event win.c:9440: Test failed: WindowFromPoint returned 000302C6, expected 00000000 win.c:9448: Test failed: WindowFromPoint returned 000302C6, expected 00000000 win.c:9451: Test failed: Timed out waiting for the child process win.c:9349: Test failed: WindowFromPoint returned 000202DE, expected 000302C6 win.c:9353: Test failed: CreateWindowEx failed win.c:8325: monitorwi (0,0)-(10n.24,768)c:9356: Test failed: WindowFromPoin, work (0,0)-(t ret1024,728) win.c:9362: Test failed: CreateWindowEx failed win.c:9377: Test failed: transparent window didn't get WM_NCHITTEST message win.c:9378: Test failed: button under static window didn't get WM_LBUTTONUP
=== w1064v1809_he (32 bit report) ===
user32: win.c:9451: Test failed: Timed out waiting for the child process
=== w1064v1809_ja (32 bit report) ===
user32: win.c:3724: Test failed: message 0738 available win.c:3849: Test failed: hwnd 000202F2 message 7fff win.c:3928: Test failed: hwnd 000202F2/00130084 message 7fff win.c:3931: Test failed: hwnd 000202F2/00130084 message 7fff
=== w1064v1809_zh_CN (32 bit report) ===
user32: win.c:9451: Test failed: Timed out waiting for the child process win.c:3849: Test failed: hwnd 0002037C message 0282 win.c:3928: Test failed: hwnd 0002037C/003B03D8 message 0282 win.c:3931: Test failed: hwnd 0002037C/003B03D8 message 0282
=== w1064v1809 (64 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 000000000003004E win.c:3167: Test failed: GetFocus() = 0000000000000000 win.c:3179: Test failed: GetFocus() = 0000000000000000 win.c:3182: Test failed: GetFocus() = 0000000000000000 win.c:3185: Test failed: GetFocus() = 0000000000000000 win.c:3188: Test failed: GetActiveWindow() = 000000000003004E win.c:3192: Test failed: GetFocus() = 0000000000000000 win.c:3195: Test failed: GetFocus() = 0000000000000000 win.c:3889: Test failed: hwnd 0000000000020174/00000000001402CE message 0737 win.c:3894: Test failed: hwnd 00000000001402CE/00000000001402CE message 0202 win.c:3899: Test failed: hwnd 00000000001402CE/00000000001402CE message 0203 win.c:3903: Test failed: message 0202 available