Delay WM_NCPAINT message until the "painter's algorithm" kicks in.

This commit is contained in:
Francis Beaudet 1999-07-18 15:38:29 +00:00 committed by Alexandre Julliard
parent ba296e3898
commit c37dd06f78
2 changed files with 103 additions and 5 deletions

View File

@ -49,6 +49,7 @@ typedef enum
#define RDW_EX_DELETEHRGN 0x0002
#define RDW_EX_XYWINDOW 0x0004
#define RDW_EX_TOPFRAME 0x0010
#define RDW_EX_DELAY_NCPAINT 0x0020
struct tagCLASS;
struct tagDCE;
@ -163,6 +164,8 @@ typedef struct
#define UNC_ENTIRE 0x0002
#define UNC_REGION 0x0004
#define UNC_UPDATE 0x0008
#define UNC_DELAY_NCPAINT 0x0010
#define UNC_IN_BEGINPAINT 0x0020
/* Window functions */
extern void WIN_Init( void );

View File

@ -27,6 +27,84 @@ DECLARE_DEBUG_CHANNEL(win)
#define CTLCOLOR_MAX CTLCOLOR_STATIC
/***********************************************************************
* WIN_HaveToDelayNCPAINT
*
* Currently, in the Wine painting mechanism, the WM_NCPAINT message
* is generated as soon as a region intersecting the non-client area
* of a window is invalidated.
*
* This technique will work fine for all windows whose parents
* have the WS_CLIPCHILDREN style. When the parents have that style,
* they are not going to override the contents of their children.
* However, when the parent doesn't have that style, Windows relies
* on a "painter's algorithm" to display the contents of the windows.
* That is, windows are painted from back to front. This includes the
* non-client area.
*
* This method looks at the current state of a window to determine
* if the sending of the WM_NCPAINT message should be delayed until
* the BeginPaint call.
*
* PARAMS:
* wndPtr - A Locked window pointer to the window we're
* examining.
* uncFlags - This is the flag passed to the WIN_UpdateNCRgn
* function. This is a shortcut for the cases when
* we already know when to avoid scanning all the
* parents of a window. If you already know that this
* window's NCPAINT should be delayed, set the
* UNC_DELAY_NCPAINT flag for this parameter.
*
* This shortcut behavior is implemented in the
* RDW_Paint() method.
*
*/
static BOOL WIN_HaveToDelayNCPAINT(
WND* wndPtr,
UINT uncFlags)
{
WND* parentWnd = NULL;
/*
* Test the shortcut first. (duh)
*/
if (uncFlags & UNC_DELAY_NCPAINT)
return TRUE;
/*
* The UNC_IN_BEGINPAINT flag is set in the BeginPaint
* method only. This is another shortcut to avoid going
* up the parent's chain of the window to finally
* figure-out that none of them has an invalid region.
*/
if (uncFlags & UNC_IN_BEGINPAINT)
return FALSE;
/*
* Scan all the parents of this window to find a window
* that doesn't have the WS_CLIPCHILDREN style and that
* has an invalid region.
*/
parentWnd = WIN_LockWndPtr(wndPtr->parent);
while (parentWnd!=NULL)
{
if ( ((parentWnd->dwStyle & WS_CLIPCHILDREN) == 0) &&
(parentWnd->hrgnUpdate != 0) )
{
WIN_ReleaseWndPtr(parentWnd);
return TRUE;
}
WIN_UpdateWndPtr(&parentWnd, parentWnd->parent);
}
WIN_ReleaseWndPtr(parentWnd);
return FALSE;
}
/***********************************************************************
* WIN_UpdateNCRgn
*
@ -72,7 +150,11 @@ HRGN WIN_UpdateNCRgn(WND* wnd, HRGN hRgn, UINT uncFlags )
uncFlags |= UNC_ENTIRE;
}
if( wnd->flags & WIN_NEEDS_NCPAINT )
/*
* If the window's non-client area needs to be painted,
*/
if ( ( wnd->flags & WIN_NEEDS_NCPAINT ) &&
!WIN_HaveToDelayNCPAINT(wnd, uncFlags) )
{
RECT r2, r3;
@ -184,7 +266,7 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
/* send WM_NCPAINT and make sure hrgnUpdate is a valid rgn handle */
WIN_UpdateNCRgn( wndPtr, 0, UNC_UPDATE );
WIN_UpdateNCRgn( wndPtr, 0, UNC_UPDATE | UNC_IN_BEGINPAINT);
/*
* Make sure the window is still a window. All window locks are suspended
@ -626,6 +708,13 @@ static HRGN RDW_Paint( WND* wndPtr, HRGN hrgn, UINT flags, UINT ex )
TRACE_(win)("\thwnd %04x [%04x] -> hrgn [%04x], flags [%04x]\n", hWnd, wndPtr->hrgnUpdate, hrgn, flags );
/*
* Check if this window should delay it's processing of WM_NCPAINT.
* See WIN_HaveToDelayNCPAINT for a description of the mechanism
*/
if ((ex & RDW_EX_DELAY_NCPAINT) || WIN_HaveToDelayNCPAINT(wndPtr, 0) )
ex |= RDW_EX_DELAY_NCPAINT;
if (flags & RDW_UPDATENOW)
{
if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
@ -634,8 +723,14 @@ static HRGN RDW_Paint( WND* wndPtr, HRGN hrgn, UINT flags, UINT ex )
else if ((flags & RDW_ERASENOW) || (ex & RDW_EX_TOPFRAME))
{
UINT dcx = DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN | DCX_WINDOWPAINT | DCX_CACHE;
HRGN hrgnRet = WIN_UpdateNCRgn( wndPtr, hrgn, UNC_REGION | UNC_CHECK |
((ex & RDW_EX_TOPFRAME) ? UNC_ENTIRE : 0) );
HRGN hrgnRet;
hrgnRet = WIN_UpdateNCRgn(wndPtr,
hrgn,
UNC_REGION | UNC_CHECK |
((ex & RDW_EX_TOPFRAME) ? UNC_ENTIRE : 0) |
((ex & RDW_EX_DELAY_NCPAINT) ? UNC_DELAY_NCPAINT : 0) );
if( hrgnRet )
{
if( hrgnRet > 1 ) hrgn = hrgnRet; else hrgnRet = 0; /* entire client */