[resend PATCH] user32: Set PAINTSTRUCT fErase field depending on the last WM_ERASEBKGND result.
Paul Gofman
gofmanp at gmail.com
Tue Apr 7 03:51:36 CDT 2020
Fixes menu update in Diablo 1.
Signed-off-by: Paul Gofman <gofmanp at 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;
--
2.25.2
More information about the wine-devel
mailing list