Ok, I need advice on this one...
I have been purely testing on windows, no wine involvement, to see what happens when I do various things.
My test program doesn't do anything in the WM_PAINT handler at all. This results in the machine sitting at 100% CPU processing WM_PAINT messages.
1. Changing the WM_PAINT process to post another user message, results in alternating message posted and WM_PAINT messages, ie normal user message processing is occurring
2. Posting a user message inside the user message handler, results in WM_PAINT being driven, followed by looping processing the user messages - ie WM_PAINT messages are not on the message queue
3. RedrawWindow with update now jumps straight into the message routine with a WM_PAINT, but if we do nothing in that routine, it does indeed proceed to the line after the RedrawWindow call. Wine never leaves the updatenow processing because it loops until the whole region is validated.
I believe staying in the updatenow code in wine is incorrect. I think what happens is that when the message dispatch loop gets an empty queue and the window has an invalid region, then a WM_PAINT is returned.
So... Can we / I please remove the loop? :-))
What other tests can I do under windows to confirm the behaviour?
Jason
"Ann and Jason Edmeades" us@the-edmeades.demon.co.uk writes:
I believe staying in the updatenow code in wine is incorrect. I think what happens is that when the message dispatch loop gets an empty queue and the window has an invalid region, then a WM_PAINT is returned.
So... Can we / I please remove the loop? :-))
Sure you can, you just need to figure out a way to do that without breaking something else ;-)
I believe staying in the updatenow code in wine is incorrect. I think
what
happens is that when the message dispatch loop gets an empty queue and
the
window has an invalid region, then a WM_PAINT is returned.
So... Can we / I please remove the loop? :-))
Sure you can, you just need to figure out a way to do that without breaking something else ;-)
Woohoo... Should be easy then!
From forum updates it appears Notes, Unreal2, UT2003, UT2004, Empire Earth
and MS Office 2003 for a start are all affected by this problem, and testing seems to confirm its wrong, so I would start by changing it with a patch and see what breaks, since we have no evidence anything will as far as I know.
But first I'll have a play under wine to compare my testing results with my suggested patch and see what breaks...
Unfortunately I cant really think of a 'test' I can add into the wine tests for this as most of the testing was under windows since wine just loops!
Thanks Jason
"Ann and Jason Edmeades" us@the-edmeades.demon.co.uk writes:
But first I'll have a play under wine to compare my testing results with my suggested patch and see what breaks...
Unfortunately I cant really think of a 'test' I can add into the wine tests for this as most of the testing was under windows since wine just loops!
It only loops if the window procedure doesn't validate the window, so what you can do for instance is to have a window proc that does nothing the first 10 times around, and on the 11th call signals an error and validates the window to break the loop.
It only loops if the window procedure doesn't validate the window, so what you can do for instance is to have a window proc that does nothing the first 10 times around, and on the 11th call signals an error and validates the window to break the loop.
Would something like this suffice?
/* Global variables to trigger exit from loop */ static int redrawComplete = 0; static long WMPAINT_count = 0;
static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_PAINT: trace("doing WM_PAINT %d\n", WMPAINT_count); WMPAINT_count++; if (WMPAINT_count > 10 && redrawComplete == 0) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); return 1; } return 0; break; } return DefWindowProc(hwnd, msg, wparam, lparam); }
/* Ensure we exit from RedrawNow regardless of invalidated area */ static void test_redrawnow() {
WNDCLASSA cls; HWND hwndMain;
cls.style = CS_DBLCLKS; cls.lpfnWndProc = redraw_window_procA; cls.cbClsExtra = 0; cls.cbWndExtra = 0; cls.hInstance = GetModuleHandleA(0); cls.hIcon = 0; cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); cls.hbrBackground = GetStockObject(WHITE_BRUSH); cls.lpszMenuName = NULL; cls.lpszClassName = "RedrawWindowClass";
if(!RegisterClassA(&cls)) { trace("Register failed %d\n", GetLastError()); return; }
hwndMain = CreateWindowA("RedrawWindowClass", "Main Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, 0, NULL);
ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count); ShowWindow(hwndMain, SW_SHOW); ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count); Sleep(10000); ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count); RedrawWindow(hwndMain, NULL,NULL,RDW_UPDATENOW | RDW_ALLCHILDREN); ok( WMPAINT_count == 1, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count); redrawComplete = TRUE; ok( WMPAINT_count < 10, "RedrawWindow (RDW_UPDATENOW) never completed (%d)\n", WMPAINT_count);
/* clean up */ DestroyWindow( hwndMain); }
Passes under XP, fails under wine (without patch) - Havent got win95,98 or 2k to test with
Jason