At 09:16 AM 6/28/00 -0400, you wrote: <snip> >I think a better approach to avoid the extra repaint (and possibly remove >some flickers) will be to use WM_SYNCPAINT message. > >On an ExposeEvent: >a. Service thread invalidate the expose event. >b. Send a WM_SYNCPAINT message to the application. lParam is pointing on the >expose rectangle. > >On reception of an WM_SYNCPAINT in def window proc: >a. Check if the rectangle pointed by lParam is still part of the invalid >region (or update region) >b. If so, erase the background (WM_ERASEBKGND) and repaint the non client >area (WM_NCPAINT) > >With this solution, the WM_ERASEBKGND and WM_NCPAINT, will always be sent by >the application thread, and we should avoid the race condition. Thanks for your explanation. I'm a bit late in replying <g>, but I wanted to test your idea. I have tried a quick and dirty implementation of WM_SYNCPAINT and it seems to work as you intend. I have not seen any nasty side-effect on any program I use. Some paintings have a different order, it seems that a few splash screen are not painted as fast as before, but no crash or obvious mis-paintings. There is certainly still work to do, but I think that you are right and the result will be worth the bother. >I must admit, because of the lack of documentation on WM_SYNCPAINT, I'm not >quite sure it's exactly the way this message should be used. As all this is undocumented, the exact way Windows is passing the update rectangle is maybe not very important. I have done it in a childishly simple way, I wonder if it's worth much trouble to emulate the thing exactly here... Gerard
Index: windows/defwnd.c =================================================================== RCS file: /home/wine/wine/windows/defwnd.c,v retrieving revision 1.30 diff -u -r1.30 defwnd.c --- windows/defwnd.c 2000/07/10 12:09:31 1.30 +++ windows/defwnd.c 2000/07/13 18:31:11 @@ -227,6 +227,17 @@ case WM_NCPAINT: return NC_HandleNCPaint( wndPtr->hwndSelf, (HRGN)wParam ); + case WM_SYNCPAINT: + { + RECT r; + GetRgnBox( (HRGN) wParam, &r); + RedrawWindow( wndPtr->hwndSelf, &r, 0, + RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE | + (lParam ? 0 : RDW_ERASENOW) ); + DeleteObject( (HRGN) wParam); + } + break; + case WM_NCHITTEST: return NC_HandleNCHitTest( wndPtr->hwndSelf, MAKEPOINT16(lParam) ); Index: windows/x11drv/event.c =================================================================== RCS file: /home/wine/wine/windows/x11drv/event.c,v retrieving revision 1.70 diff -u -r1.70 event.c --- windows/x11drv/event.c 2000/06/08 19:21:06 1.70 +++ windows/x11drv/event.c 2000/07/13 18:31:14 @@ -637,10 +637,8 @@ rect.right = rect.left + event->width; rect.bottom = rect.top + event->height; WIN_ReleaseWndPtr(pWnd); - - Callout.RedrawWindow( hWnd, &rect, 0, - RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE | - (event->count ? 0 : RDW_ERASENOW) ); + + PostMessageA( hWnd, WM_SYNCPAINT, CreateRectRgnIndirect(&rect), event->count ); }