From 98447497b777b371fa5a59a5d1a0f1714a944843 Mon Sep 17 00:00:00 2001 From: Alex Korobka Date: Sat, 8 May 1999 17:57:09 +0000 Subject: [PATCH] Rearranged PAINT_RedrawWindow() so that it first recursively updates invalid regions and only then starts sending out messages. This should help with reentrancy during message processing and now it needs just one (or none) scratch region for all there is to do. Also, small fixes for SetWindowPos(). --- include/win.h | 9 +- objects/region.c | 71 +++- windows/dce.c | 2 +- windows/painting.c | 722 +++++++++++++++++++++++++---------------- windows/win.c | 2 +- windows/winpos.c | 167 +++++----- windows/x11drv/event.c | 3 +- 7 files changed, 600 insertions(+), 376 deletions(-) diff --git a/include/win.h b/include/win.h index e15fb09a7b5..4ce56c1c5ae 100644 --- a/include/win.h +++ b/include/win.h @@ -157,6 +157,12 @@ typedef struct #define BWA_SKIPOWNED 0x0004 #define BWA_SKIPICONIC 0x0008 + /* WIN_UpdateNCRgn() flags */ +#define UNC_CHECK 0x0001 +#define UNC_ENTIRE 0x0002 +#define UNC_REGION 0x0004 +#define UNC_UPDATE 0x0008 + /* Window functions */ extern void WIN_Init( void ); extern void WIN_LockWnds(); @@ -195,8 +201,7 @@ extern void PROPERTY_RemoveWindowProps( WND *pWnd ); /* windows/propert extern BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate, HRGN hrgnUpdate, UINT flags, UINT control ); /* windows/painting.c */ -extern HRGN WIN_UpdateNCRgn(WND* wnd, BOOL bUpdate, BOOL bForce); /* windows/painting.c */ - +extern HRGN WIN_UpdateNCRgn(WND* wnd, HRGN hRgn, UINT flags); /* windows/painting.c */ /* controls/widgets.c */ extern BOOL WIDGETS_Init( void ); diff --git a/objects/region.c b/objects/region.c index 1eb605457fb..f945a3efc8b 100644 --- a/objects/region.c +++ b/objects/region.c @@ -89,7 +89,7 @@ SOFTWARE. #include "heap.h" #include "dc.h" -DEFAULT_DEBUG_CHANNEL(region) +DEFAULT_DEBUG_CHANNEL(region) typedef void (*voidProcp)(); @@ -2588,14 +2588,51 @@ HRGN WINAPI GetRandomRgn(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3) */ static BOOL REGION_CropAndOffsetRegion(const POINT* off, const RECT *rect, WINEREGION *rgnSrc, WINEREGION* rgnDst) { - if( IsRectEmpty(rect) || !EXTENTCHECK(rect, &rgnSrc->extents) ) + if( !rect ) /* just copy and offset */ + { + if( rgnDst == rgnSrc ) + { + if( off->x || off->y ) + rect = rgnDst->rects; + else + return TRUE; + } + else + rect = HeapReAlloc( SystemHeap, 0, rgnDst->rects, + rgnSrc->size * sizeof( RECT )); + if( rect ) + { + INT i; + + if( rgnDst != rgnSrc ) + memcpy( rgnDst, rgnSrc, sizeof( WINEREGION )); + + if( off->x || off->y ) + { + for( i = 0; i < rgnDst->numRects; i++ ) + { + rect[i].left = rgnSrc->rects[i].left + off->x; + rect[i].right = rgnSrc->rects[i].right + off->x; + rect[i].top = rgnSrc->rects[i].top + off->y; + rect[i].bottom = rgnSrc->rects[i].bottom + off->y; + } + OffsetRect( &rgnDst->extents, off->x, off->y ); + } + else + memcpy( rect, rgnSrc->rects, rgnDst->numRects * sizeof( RECT )); + rgnDst->rects = rect; + } + else + return FALSE; + } + else if( IsRectEmpty(rect) || !EXTENTCHECK(rect, &rgnSrc->extents) ) { empty: if( !rgnDst->rects ) { - rgnDst->rects = HeapAlloc(SystemHeap, 0, sizeof( RECT )); + rgnDst->rects = HeapAlloc(SystemHeap, 0, RGN_DEFAULT_RECTS * sizeof( RECT )); if( rgnDst->rects ) - rgnDst->size = 1; + rgnDst->size = RGN_DEFAULT_RECTS; else return FALSE; } @@ -2695,11 +2732,12 @@ empty: * * * hSrc: Region to crop and offset. - * lpRect: Clipping rectangle. - * lpPt: Points to offset the cropped region. Can be NULL. + * lpRect: Clipping rectangle. Can be NULL (no clipping). + * lpPt: Points to offset the cropped region. Can be NULL (no offset). * - * hDst: Region to hold the result (if 0 a new region is created). - * Allowed to be the same region as hSrc (in place, no extra memory needed). + * hDst: Region to hold the result (a new region is created if it's 0). + * Allowed to be the same region as hSrc in which case everyhting + * will be done in place, with no memory reallocations. * * Returns: hDst if success, 0 otherwise. */ @@ -2707,9 +2745,17 @@ HRGN REGION_CropRgn( HRGN hDst, HRGN hSrc, const RECT *lpRect, const POINT *lpPt { /* Optimization of the following generic code: - HRGN h = CreateRectRgn( lpRect->left, lpRect->top, lpRect->right, lpRect->bottom ); + HRGN h; + + if( lpRect ) + h = CreateRectRgn( lpRect->left, lpRect->top, lpRect->right, lpRect->bottom ); + else + h = CreateRectRgn( 0, 0, 0, 0 ); if( hDst == 0 ) hDst = h; - CombineRgn( hDst, hSrc, h, RGN_AND ); + if( lpRect ) + CombineRgn( hDst, hSrc, h, RGN_AND ); + else + CombineRgn( hDst, hSrc, 0, RGN_COPY ); if( lpPt ) OffsetRgn( hDst, lpPt->x, lpPt->y ); if( hDst != h ) @@ -2746,8 +2792,11 @@ HRGN REGION_CropRgn( HRGN hDst, HRGN hSrc, const RECT *lpRect, const POINT *lpPt if( !lpPt ) lpPt = &pt; - TRACE(region, "src %p -> dst %p (%i,%i)-(%i,%i) by (%li,%li)\n", objSrc->rgn, rgnDst, + if( lpRect ) + TRACE(region, "src %p -> dst %p (%i,%i)-(%i,%i) by (%li,%li)\n", objSrc->rgn, rgnDst, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, lpPt->x, lpPt->y ); + else + TRACE(region, "src %p -> dst %p by (%li,%li)\n", objSrc->rgn, rgnDst, lpPt->x, lpPt->y ); if( REGION_CropAndOffsetRegion( lpPt, lpRect, objSrc->rgn, rgnDst ) == FALSE ) { diff --git a/windows/dce.c b/windows/dce.c index 2f4c171a03a..191fb4cb980 100644 --- a/windows/dce.c +++ b/windows/dce.c @@ -378,7 +378,7 @@ static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect ) INT xoffset = lprect->left; INT yoffset = lprect->top; - while (wndPtr->dwStyle & WS_CHILD) + while( !(wndPtr->flags & WIN_NATIVE) ) { wndPtr = WIN_LockWndPtr(wndPtr->parent); diff --git a/windows/painting.c b/windows/painting.c index f3a3236dccf..27f1f1a869a 100644 --- a/windows/painting.c +++ b/windows/painting.c @@ -3,7 +3,6 @@ * * Copyright 1993, 1994, 1995 Alexandre Julliard * 1999 Alex Korobka - * */ #include "region.h" @@ -31,84 +30,133 @@ DECLARE_DEBUG_CHANNEL(win) /*********************************************************************** * WIN_UpdateNCRgn * - * NOTE: Caller is responsible for the returned region. + * Things to do: + * Send WM_NCPAINT if required (when nonclient is invalid or UNC_ENTIRE flag is set) + * Crop hrgnUpdate to a client rect, especially if it 1. + * If UNC_REGION is set return update region for the client rect. + * + * NOTE: UNC_REGION is mainly for the RDW_Paint() chunk that sends WM_ERASEBKGND message. + * The trick is that when the returned region handle may be different from hRgn. + * In this case the old hRgn must be considered gone. BUT, if the returned value + * is 1 then the hRgn is preserved and RDW_Paint() will have to get + * a DC without extra clipping region. */ -HRGN WIN_UpdateNCRgn(WND* wnd, BOOL bUpdate, BOOL bForceEntire ) +HRGN WIN_UpdateNCRgn(WND* wnd, HRGN hRgn, UINT uncFlags ) { - HRGN hClip = 0; + RECT r; + HRGN hClip = 0; + HRGN hrgnRet = 0; - TRACE_(nonclient)("hwnd %04x, hrgnUpdate %04x, ncf %i\n", - wnd->hwndSelf, wnd->hrgnUpdate, (wnd->flags & WIN_NEEDS_NCPAINT)!=0 ); + TRACE_(nonclient)("hwnd %04x [%04x] hrgn %04x, unc %04x, ncf %i\n", + wnd->hwndSelf, wnd->hrgnUpdate, hRgn, uncFlags, wnd->flags & WIN_NEEDS_NCPAINT); - /* desktop window doesn't have nonclient area */ + /* desktop window doesn't have a nonclient area */ if(wnd == WIN_GetDesktop()) { wnd->flags &= ~WIN_NEEDS_NCPAINT; + if( wnd->hrgnUpdate > 1 ) + hrgnRet = REGION_CropRgn( hRgn, wnd->hrgnUpdate, NULL, NULL ); + else + { + hrgnRet = wnd->hrgnUpdate; + } WIN_ReleaseDesktop(); - return 0; + return hrgnRet; } WIN_ReleaseDesktop(); - if ((wnd->hwndSelf == GetActiveWindow()) && + if ((wnd->hwndSelf == GetForegroundWindow()) && !(wnd->flags & WIN_NCACTIVATED) ) { wnd->flags |= WIN_NCACTIVATED; - bForceEntire = TRUE; + uncFlags |= UNC_ENTIRE; } - if( (wnd->flags & WIN_NEEDS_NCPAINT) && wnd->hrgnUpdate ) + if( wnd->flags & WIN_NEEDS_NCPAINT ) { - RECT r, r2, r3; + RECT r2, r3; - GETCLIENTRECTW( wnd, r ); + wnd->flags &= ~WIN_NEEDS_NCPAINT; + GETCLIENTRECTW( wnd, r ); - TRACE_(nonclient)("\tclient box (%i,%i-%i,%i)\n", r.left, r.top, r.right, r.bottom ); - - if( wnd->hrgnUpdate > 1 ) - { - GetRgnBox( wnd->hrgnUpdate, &r2 ); - UnionRect( &r3, &r2, &r ); - if( r3.left != r.left || r3.top != r.top || - r3.right != r.right || r3.bottom != r.bottom ) - { - hClip = CreateRectRgn( 0, 0, 0, 0 ); - CombineRgn( hClip, wnd->hrgnUpdate, 0, RGN_COPY ); - } - } - else - hClip = wnd->hrgnUpdate; - - if( wnd->hrgnUpdate > 1 ) - { - REGION_CropRgn( wnd->hrgnUpdate, wnd->hrgnUpdate, &r, NULL ); - - if( bUpdate ) + TRACE_(nonclient)( "\tclient box (%i,%i-%i,%i), hrgnUpdate %04x\n", + r.left, r.top, r.right, r.bottom, wnd->hrgnUpdate ); + if( wnd->hrgnUpdate > 1 ) { - GetRgnBox( wnd->hrgnUpdate, &r3 ); - if( IsRectEmpty( &r3 ) ) - { - /* delete update region since all invalid - * parts were in the nonclient area */ + /* Check if update rgn overlaps with nonclient area */ - DeleteObject( wnd->hrgnUpdate ); - wnd->hrgnUpdate = 0; - if(!(wnd->flags & WIN_INTERNAL_PAINT)) - QUEUE_DecPaintCount( wnd->hmemTaskQ ); - wnd->flags &= ~WIN_NEEDS_ERASEBKGND; + GetRgnBox( wnd->hrgnUpdate, &r2 ); + UnionRect( &r3, &r2, &r ); + if( r3.left != r.left || r3.top != r.top || + r3.right != r.right || r3.bottom != r.bottom ) /* it does */ + { + /* crop hrgnUpdate, save old one in hClip - the only + * case that places a valid region handle in hClip */ + + hClip = wnd->hrgnUpdate; + wnd->hrgnUpdate = REGION_CropRgn( hRgn, hClip, &r, NULL ); + if( uncFlags & UNC_REGION ) hrgnRet = hClip; } + + if( uncFlags & UNC_CHECK ) + { + GetRgnBox( wnd->hrgnUpdate, &r3 ); + if( IsRectEmpty( &r3 ) ) + { + /* delete the update region since all invalid + * parts were in the nonclient area */ + + DeleteObject( wnd->hrgnUpdate ); + wnd->hrgnUpdate = 0; + if(!(wnd->flags & WIN_INTERNAL_PAINT)) + QUEUE_DecPaintCount( wnd->hmemTaskQ ); + + wnd->flags &= ~WIN_NEEDS_ERASEBKGND; + } + } + + if(!hClip && wnd->hrgnUpdate ) goto copyrgn; } + else + if( wnd->hrgnUpdate == 1 )/* entire window */ + { + if( uncFlags & UNC_UPDATE ) wnd->hrgnUpdate = CreateRectRgnIndirect( &r ); + if( uncFlags & UNC_REGION ) hrgnRet = 1; + uncFlags |= UNC_ENTIRE; + } + } + else /* no WM_NCPAINT unless forced */ + { + if( wnd->hrgnUpdate > 1 ) + { +copyrgn: + if( uncFlags & UNC_REGION ) + hrgnRet = REGION_CropRgn( hRgn, wnd->hrgnUpdate, NULL, NULL ); + } + else + if( wnd->hrgnUpdate == 1 && (uncFlags & UNC_UPDATE) ) + { + GETCLIENTRECTW( wnd, r ); + wnd->hrgnUpdate = CreateRectRgnIndirect( &r ); + if( uncFlags & UNC_REGION ) hrgnRet = 1; } - else /* entire client rect */ - wnd->hrgnUpdate = CreateRectRgnIndirect( &r ); } - if(!hClip && bForceEntire ) hClip = 1; - wnd->flags &= ~WIN_NEEDS_NCPAINT; + if(!hClip && (uncFlags & UNC_ENTIRE) ) + { + /* still don't do anything if there is no nonclient area */ + hClip = (memcmp( &wnd->rectWindow, &wnd->rectClient, sizeof(RECT) ) != 0); + } - if( hClip ) + if( hClip ) /* NOTE: WM_NCPAINT allows wParam to be 1 */ + { SendMessageA( wnd->hwndSelf, WM_NCPAINT, hClip, 0L ); + if( (hClip > 1)&& (hClip != hRgn) && (hClip != hrgnRet) ) DeleteObject( hClip ); + } - return hClip; + TRACE_(nonclient)("returning %04x (hClip = %04x, hrgnUpdate = %04x)\n", hrgnRet, hClip, wnd->hrgnUpdate ); + + return hrgnRet; } @@ -126,8 +174,8 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps ) wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT; - if( (hrgnUpdate = WIN_UpdateNCRgn( wndPtr, FALSE, FALSE )) > 1 ) - DeleteObject( hrgnUpdate ); + /* send WM_NCPAINT and make sure hrgnUpdate is a valid rgn handle */ + WIN_UpdateNCRgn( wndPtr, 0, UNC_UPDATE ); if( ((hrgnUpdate = wndPtr->hrgnUpdate) != 0) || (wndPtr->flags & WIN_INTERNAL_PAINT)) QUEUE_DecPaintCount( wndPtr->hmemTaskQ ); @@ -142,19 +190,19 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps ) if (wndPtr->class->style & CS_PARENTDC) { /* Don't clip the output to the update region for CS_PARENTDC window */ - if( hrgnUpdate > 1 ) + if( hrgnUpdate ) DeleteObject(hrgnUpdate); lps->hdc = GetDCEx16( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE | (bIcon ? DCX_WINDOW : 0) ); } else { - if( hrgnUpdate ) + if( hrgnUpdate ) /* convert to client coordinates */ OffsetRgn( hrgnUpdate, wndPtr->rectWindow.left - wndPtr->rectClient.left, wndPtr->rectWindow.top - wndPtr->rectClient.top ); lps->hdc = GetDCEx16(hwnd, hrgnUpdate, DCX_INTERSECTRGN | - DCX_WINDOWPAINT | DCX_USESTYLE | - (bIcon ? DCX_WINDOW : 0) ); + DCX_WINDOWPAINT | DCX_USESTYLE | (bIcon ? DCX_WINDOW : 0) ); + /* ReleaseDC() in EndPaint() will delete the region */ } TRACE_(win)("hdc = %04x\n", lps->hdc); @@ -292,318 +340,418 @@ HBRUSH16 WINAPI GetControlBrush16( HWND16 hwnd, HDC16 hdc, UINT16 ctlType ) END: WIN_ReleaseWndPtr(wndPtr); return retvalue; - } +} +int i; /*********************************************************************** - * PAINT_RedrawWindow + * RDW_UpdateRgns [RedrawWindow() helper] * + * Walks the window tree and adds/removes parts of the hRgn to/from update + * regions of windows that overlap it. Also, manages internal paint flags. + * + * NOTE: Walks the window tree so the caller must lock it. + * MUST preserve hRgn (can modify but then has to restore). + */ +static void RDW_UpdateRgns( WND* wndPtr, HRGN hRgn, UINT flags ) +{ + /* + * Called only when one of the following is set: + * (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) + */ + + BOOL bHadOne = wndPtr->hrgnUpdate && hRgn; + RECT r = {0, 0, wndPtr->rectWindow.right - wndPtr->rectWindow.left, + wndPtr->rectWindow.bottom - wndPtr->rectWindow.top }; + BOOL bChildren = ( wndPtr->child && !(flags & RDW_NOCHILDREN) && !(wndPtr->dwStyle & WS_MINIMIZE) + && ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) ); + + TRACE_(win)("\thwnd %04x [%04x] -> hrgn [%04x], flags [%04x]\n", wndPtr->hwndSelf, wndPtr->hrgnUpdate, hRgn, flags ); + + if( flags & RDW_INVALIDATE ) + { + if( hRgn > 1 ) + { + switch( wndPtr->hrgnUpdate ) + { + default: + CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hRgn, RGN_OR ); + /* fall through */ + case 0: + wndPtr->hrgnUpdate = REGION_CropRgn( wndPtr->hrgnUpdate, + wndPtr->hrgnUpdate ? wndPtr->hrgnUpdate : hRgn, + &r, NULL ); + if( !bHadOne ) + { + GetRgnBox( wndPtr->hrgnUpdate, &r ); + if( IsRectEmpty( &r ) ) + { + DeleteObject( wndPtr->hrgnUpdate ); + wndPtr->hrgnUpdate = 0; + goto OUT; + } + } + break; + + case 1: /* already an entire window */ + } + } + else if( hRgn == 1 ) + { + if( wndPtr->hrgnUpdate > 1 ) + DeleteObject( wndPtr->hrgnUpdate ); + wndPtr->hrgnUpdate = 1; + } + else + hRgn = wndPtr->hrgnUpdate; /* this is a trick that depends on code in PAINT_RedrawWindow() */ + + if( !bHadOne && !(wndPtr->flags & WIN_INTERNAL_PAINT) ) + QUEUE_IncPaintCount( wndPtr->hmemTaskQ ); + + if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT; + if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND; + flags |= RDW_FRAME; + } + else if( flags & RDW_VALIDATE ) + { + if( wndPtr->hrgnUpdate ) + { + if( hRgn > 1 ) + { + if( wndPtr->hrgnUpdate == 1 ) + wndPtr->hrgnUpdate = CreateRectRgnIndirect( &r ); + + if( CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hRgn, RGN_DIFF ) + == NULLREGION ) + goto EMPTY; + } + else /* validate everything */ + { + if( wndPtr->hrgnUpdate > 1 ) + { +EMPTY: + DeleteObject( wndPtr->hrgnUpdate ); + } + wndPtr->hrgnUpdate = 0; + } + + if( !wndPtr->hrgnUpdate ) + { + wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND; + if( !(wndPtr->flags & WIN_INTERNAL_PAINT) ) + QUEUE_DecPaintCount( wndPtr->hmemTaskQ ); + } + } + + if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT; + if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND; + } + + /* in/validate child windows that intersect with the region if it + * is a valid handle. */ + + if( flags & (RDW_INVALIDATE | RDW_VALIDATE) ) + { + if( hRgn > 1 && bChildren ) + { + WND* wnd = wndPtr->child; + POINT ptClient = { wndPtr->rectClient.left - wndPtr->rectWindow.left, + wndPtr->rectClient.top - wndPtr->rectWindow.top }; + POINT ptTotal, prevOrigin = {0,0}; + + for( ptTotal.x = ptTotal.y = 0; wnd; wnd = wnd->next ) + { + if( wnd->dwStyle & WS_VISIBLE ) + { + POINT ptOffset; + + r.left = wnd->rectWindow.left + ptClient.x; + r.right = wnd->rectWindow.right + ptClient.x; + r.top = wnd->rectWindow.top + ptClient.y; + r.bottom = wnd->rectWindow.bottom + ptClient.y; + + ptOffset.x = r.left - prevOrigin.x; + ptOffset.y = r.top - prevOrigin.y; + OffsetRect( &r, -ptTotal.x, -ptTotal.y ); + + if( RectInRegion( hRgn, &r ) ) + { + OffsetRgn( hRgn, -ptOffset.x, -ptOffset.y ); + RDW_UpdateRgns( wnd, hRgn, flags ); + prevOrigin.x = r.left + ptTotal.x; + prevOrigin.y = r.top + ptTotal.y; + ptTotal.x += ptOffset.x; + ptTotal.y += ptOffset.y; + } + } + } + OffsetRgn( hRgn, ptTotal.x, ptTotal.y ); + bChildren = 0; + } + } + + /* handle hRgn == 1 (alias for entire window) and/or internal paint recursion */ + + if( bChildren ) + { + WND* wnd; + for( wnd = wndPtr->child; wnd; wnd = wnd->next ) + if( wnd->dwStyle & WS_VISIBLE ) + RDW_UpdateRgns( wnd, hRgn, flags ); + } + +OUT: + + /* Set/clear internal paint flag */ + + if (flags & RDW_INTERNALPAINT) + { + if ( !wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT)) + QUEUE_IncPaintCount( wndPtr->hmemTaskQ ); + wndPtr->flags |= WIN_INTERNAL_PAINT; + } + else if (flags & RDW_NOINTERNALPAINT) + { + if ( !wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT)) + QUEUE_DecPaintCount( wndPtr->hmemTaskQ ); + wndPtr->flags &= ~WIN_INTERNAL_PAINT; + } +} + +/*********************************************************************** + * RDW_Paint [RedrawWindow() helper] + * + * Walks the window tree and paints/erases windows that have + * nonzero update regions according to redraw flags. hrgn is a scratch + * region passed down during recursion. Must not be 1. + * + */ +static HRGN RDW_Paint( WND* wndPtr, HRGN hrgn, UINT flags, UINT ex ) +{ +/* NOTE: wndPtr is locked by caller. + * * FIXME: Windows uses WM_SYNCPAINT to cut down the number of intertask - * SendMessage() calls. This is a comment inside DefWindowProc() source + * SendMessage() calls. This is a comment inside DefWindowProc() source * from 16-bit SDK: * * This message avoids lots of inter-app message traffic * by switching to the other task and continuing the * recursion there. - * + * * wParam = flags * LOWORD(lParam) = hrgnClip * HIWORD(lParam) = hwndSkip (not used; always NULL) * + */ + HDC hDC; + HWND hWnd = wndPtr->hwndSelf; + BOOL bIcon = ((wndPtr->dwStyle & WS_MINIMIZE) && wndPtr->class->hIcon); + + /* Erase/update the window itself ... */ + + TRACE_(win)("\thwnd %04x [%04x] -> hrgn [%04x], flags [%04x]\n", hWnd, wndPtr->hrgnUpdate, hrgn, flags ); + + if (flags & RDW_UPDATENOW) + { + if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */ + SendMessage16( hWnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 ); + } + else if ((flags & RDW_ERASENOW) || (ex & RDW_EX_TOPFRAME)) + { + UINT dcx = DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN | DCX_WINDOWPAINT; + HRGN hrgnRet = WIN_UpdateNCRgn( wndPtr, hrgn, UNC_REGION | UNC_CHECK | + ((ex & RDW_EX_TOPFRAME) ? UNC_ENTIRE : 0) ); + if( hrgnRet ) + { + if( hrgnRet > 1 ) hrgn = hrgnRet; else hrgnRet = 0; /* entire client */ + if( wndPtr->flags & WIN_NEEDS_ERASEBKGND ) + { + if( bIcon ) dcx |= DCX_WINDOW; + else + if( hrgnRet ) + OffsetRgn( hrgnRet, wndPtr->rectWindow.left - wndPtr->rectClient.left, + wndPtr->rectWindow.top - wndPtr->rectClient.top); + else + dcx &= ~DCX_INTERSECTRGN; + if (( hDC = GetDCEx( hWnd, hrgnRet, dcx )) ) + { + if (SendMessage16( hWnd, (bIcon) ? WM_ICONERASEBKGND + : WM_ERASEBKGND, (WPARAM16)hDC, 0 )) + wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND; + ReleaseDC( hWnd, hDC ); + } + } + } + } + + if( !IsWindow(hWnd) ) return hrgn; + ex &= ~RDW_EX_TOPFRAME; + + /* ... and its child windows */ + + if( wndPtr->child && !(flags & RDW_NOCHILDREN) && !(wndPtr->dwStyle & WS_MINIMIZE) + && ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) ) + { + WND** list, **ppWnd; + + if( (list = WIN_BuildWinArray( wndPtr, 0, NULL )) ) + { + for (ppWnd = list; *ppWnd; ppWnd++) + { + WIN_UpdateWndPtr(&wndPtr,*ppWnd); + if (!IsWindow(wndPtr->hwndSelf)) continue; + if ( (wndPtr->dwStyle & WS_VISIBLE) && + (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT)) ) + hrgn = RDW_Paint( wndPtr, hrgn, flags, ex ); + } + WIN_ReleaseWinArray(list); + } + } + + return hrgn; +} + +/*********************************************************************** + * PAINT_RedrawWindow + * */ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate, HRGN hrgnUpdate, UINT flags, UINT ex ) { - BOOL bIcon; - HRGN hrgn = 0, hrgn2 = 0; + HRGN hRgn = 0; RECT r, r2; POINT pt; WND* wndPtr; - WND **list, **ppWnd; if (!hwnd) hwnd = GetDesktopWindow(); if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE; + + /* check if the window or its parents are visible/not minimized */ + if (!WIN_IsWindowDrawable( wndPtr, !(flags & RDW_FRAME) ) ) { WIN_ReleaseWndPtr(wndPtr); - return TRUE; /* No redraw needed */ + return TRUE; } - bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon); - if (rectUpdate) + if (TRACE_ON(win)) { - TRACE_(win)("%04x (%04x) %d,%d-%d,%d %04x flags=%04x, exflags=%04x\n", - hwnd, wndPtr->hrgnUpdate, rectUpdate->left, rectUpdate->top, - rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags, ex ); - } - else - { - if( hrgnUpdate ) GetRgnBox( hrgnUpdate, &r ); - else SetRectEmpty( &r ); - TRACE_(win)("%04x (%04x) NULL %04x box (%i,%i-%i,%i) flags=%04x, exflags=%04x\n", - hwnd, wndPtr->hrgnUpdate, hrgnUpdate, r.left, r.top, r.right, r.bottom, flags, ex); + if( hrgnUpdate ) + { + GetRgnBox( hrgnUpdate, &r ); + TRACE_(win)( "%04x (%04x) NULL %04x box (%i,%i-%i,%i) flags=%04x, exflags=%04x\n", + hwnd, wndPtr->hrgnUpdate, hrgnUpdate, r.left, r.top, r.right, r.bottom, flags, ex); + } + else + { + if( rectUpdate ) + r = *rectUpdate; + else + SetRectEmpty( &r ); + TRACE_(win)( "%04x (%04x) %s %d,%d-%d,%d %04x flags=%04x, exflags=%04x\n", + hwnd, wndPtr->hrgnUpdate, rectUpdate ? "rect" : "NULL", r.left, + r.top, r.right, r.bottom, hrgnUpdate, flags, ex ); + } } + /* prepare an update region in window coordinates */ + if( flags & RDW_FRAME ) r = wndPtr->rectWindow; else r = wndPtr->rectClient; + if( ex & RDW_EX_XYWINDOW ) + { + pt.x = pt.y = 0; OffsetRect( &r, -wndPtr->rectWindow.left, -wndPtr->rectWindow.top ); + } else + { + pt.x = wndPtr->rectClient.left - wndPtr->rectWindow.left; + pt.y = wndPtr->rectClient.top - wndPtr->rectWindow.top; OffsetRect( &r, -wndPtr->rectClient.left, -wndPtr->rectClient.top ); - - /* r is the rectangle we crop the supplied update rgn/rect with */ - - GETCLIENTRECTW( wndPtr, r2 ); - pt.x = r2.left; pt.y = r2.top; + } if (flags & RDW_INVALIDATE) /* ------------------------- Invalidate */ { - BOOL bHasUpdateRgn = (BOOL)wndPtr->hrgnUpdate; - - /* wndPtr->hrgnUpdate is in window coordinates, parameters are - * in client coordinates unless RDW_EX_XYWINDOW is set. + /* If the window doesn't have hrgnUpdate we leave hRgn zero + * and put a new region straight into wndPtr->hrgnUpdate + * so that RDW_UpdateRgns() won't have to do any extra work. */ if( hrgnUpdate ) { - hrgn = REGION_CropRgn( 0, hrgnUpdate, &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt ); - GetRgnBox( hrgn, &r2 ); - if( IsRectEmpty( &r2 ) ) - goto END; - - if( wndPtr->hrgnUpdate == 0 ) - { - wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ); - CombineRgn( wndPtr->hrgnUpdate, hrgn, 0, RGN_COPY ); - } - else - if( wndPtr->hrgnUpdate > 1 ) - CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hrgn, RGN_OR ); + if( wndPtr->hrgnUpdate ) + hRgn = REGION_CropRgn( 0, hrgnUpdate, NULL, &pt ); + else + wndPtr->hrgnUpdate = REGION_CropRgn( 0, hrgnUpdate, &r, &pt ); } else if( rectUpdate ) { - if( !IntersectRect( &r2, &r, rectUpdate ) ) - goto END; - if( !(ex & RDW_EX_XYWINDOW) ) - OffsetRect( &r2, pt.x, pt.y ); + if( !IntersectRect( &r2, &r, rectUpdate ) ) goto END; + OffsetRect( &r2, pt.x, pt.y ); -rect2i: /* r2 contains a rect to add to the update region */ - - hrgn = CreateRectRgnIndirect( &r2 ); +rect2i: if( wndPtr->hrgnUpdate == 0 ) wndPtr->hrgnUpdate = CreateRectRgnIndirect( &r2 ); else - if( wndPtr->hrgnUpdate > 1 ) - REGION_UnionRectWithRgn( wndPtr->hrgnUpdate, &r2 ); + hRgn = CreateRectRgnIndirect( &r2 ); } else /* entire window or client depending on RDW_FRAME */ { - hrgn = 1; if( flags & RDW_FRAME ) { if( wndPtr->hrgnUpdate ) DeleteObject( wndPtr->hrgnUpdate ); wndPtr->hrgnUpdate = 1; } - else /* by default r2 contains client rect in window coordinates */ + else + { + GETCLIENTRECTW( wndPtr, r2 ); goto rect2i; + } } - - if( !bHasUpdateRgn && wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT)) - QUEUE_IncPaintCount( wndPtr->hmemTaskQ ); - - if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT; - if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND; - flags |= RDW_FRAME; /* Force children frame invalidation */ } else if (flags & RDW_VALIDATE) /* ------------------------- Validate */ { - if (wndPtr->hrgnUpdate) /* need an update region in order to validate anything */ - { - if( hrgnUpdate || rectUpdate ) - { - if( hrgnUpdate ) - { - hrgn = REGION_CropRgn( hrgn, hrgnUpdate, &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt ); - GetRgnBox( hrgn, &r2 ); - if( IsRectEmpty( &r2 ) ) - goto END; - } - else - { - if( !IntersectRect( &r2, &r, rectUpdate ) ) - goto END; - if( !(ex & RDW_EX_XYWINDOW) ) - OffsetRect( &r2, pt.x, pt.y ); + /* In this we cannot leave with zero hRgn */ + if( hrgnUpdate ) + { + hRgn = REGION_CropRgn( hRgn, hrgnUpdate, &r, &pt ); + GetRgnBox( hRgn, &r2 ); + if( IsRectEmpty( &r2 ) ) goto END; + } + else if( rectUpdate ) + { + if( !IntersectRect( &r2, &r, rectUpdate ) ) goto END; + OffsetRect( &r2, pt.x, pt.y ); rect2v: - hrgn = CreateRectRgnIndirect( &r2 ); - } - - if( wndPtr->hrgnUpdate == 1 ) - { - wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, - wndPtr->rectWindow.right - wndPtr->rectWindow.left, - wndPtr->rectWindow.bottom - wndPtr->rectWindow.top ); - } - - if( CombineRgn( wndPtr->hrgnUpdate, - wndPtr->hrgnUpdate, hrgn, RGN_DIFF ) == NULLREGION ) - { - DeleteObject( wndPtr->hrgnUpdate ); - wndPtr->hrgnUpdate = 0; - } - } - else /* entire window or client depending on RDW_FRAME */ - { - wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND; - - hrgn = 1; - if( flags & RDW_FRAME ) - { - if( wndPtr->hrgnUpdate != 1 ) - DeleteObject( wndPtr->hrgnUpdate ); - wndPtr->hrgnUpdate = 0; - } - else /* by default r2 contains client rect in window coordinates */ - goto rect2v; - } - - if (!wndPtr->hrgnUpdate && /* No more update region */ - !(wndPtr->flags & WIN_INTERNAL_PAINT) ) - QUEUE_DecPaintCount( wndPtr->hmemTaskQ ); - } - if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT; - if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND; - } - - /* At this point hrgn contains new update region in window coordinates */ - - /* Set/clear internal paint flag */ - - if (flags & RDW_INTERNALPAINT) - { - if ( !wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT)) - QUEUE_IncPaintCount( wndPtr->hmemTaskQ ); - wndPtr->flags |= WIN_INTERNAL_PAINT; - } - else if (flags & RDW_NOINTERNALPAINT) - { - if ( !wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT)) - QUEUE_DecPaintCount( wndPtr->hmemTaskQ ); - wndPtr->flags &= ~WIN_INTERNAL_PAINT; - } - - /* Erase/update window */ - - if (flags & RDW_UPDATENOW) - { - if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */ - SendMessage16( hwnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 ); - } - else if ((flags & RDW_ERASENOW) || (ex & RDW_EX_TOPFRAME)) - { - hrgn2 = WIN_UpdateNCRgn( wndPtr, TRUE, (ex & RDW_EX_TOPFRAME) ); - - if( wndPtr->flags & WIN_NEEDS_ERASEBKGND ) + hRgn = CreateRectRgnIndirect( &r2 ); + } + else /* entire window or client depending on RDW_FRAME */ { - HDC hdc; - - if( hrgn2 > 1 ) - { - OffsetRgn( hrgn2, -pt.x, -pt.y ); - GetRgnBox( hrgn2, &r2 ); - } + if( flags & RDW_FRAME ) + hRgn = 1; else { - hrgn2 = CreateRectRgn( 0, 0, 0, 0 ); - CombineRgn( hrgn2, wndPtr->hrgnUpdate, 0, RGN_COPY ); - OffsetRgn( hrgn2, -pt.x, -pt.y ); - } - hdc = GetDCEx( hwnd, hrgn2, - DCX_INTERSECTRGN | DCX_USESTYLE | - DCX_KEEPCLIPRGN | DCX_WINDOWPAINT | - (bIcon ? DCX_WINDOW : 0) ); - if (hdc) - { - if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND - : WM_ERASEBKGND, - (WPARAM16)hdc, 0 )) - wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND; - ReleaseDC( hwnd, hdc ); + GETCLIENTRECTW( wndPtr, r2 ); + goto rect2v; } } } - if ( !IsWindow( hwnd ) ) - { - WIN_ReleaseWndPtr(wndPtr); - return TRUE; - } + /* At this point hRgn is either an update region in window coordinates or 1 or 0 */ - /* Recursively process children */ + RDW_UpdateRgns( wndPtr, hRgn, flags ); - if (!(flags & RDW_NOCHILDREN) && - ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) && - !(wndPtr->dwStyle & WS_MINIMIZE) ) - { - if( hrgnUpdate || rectUpdate ) - { - if( hrgn2 <= 1 ) - hrgn2 = (ex & RDW_EX_USEHRGN) ? hrgnUpdate : 0; + /* Erase/update windows, from now on hRgn is a scratch region */ - if( (list = WIN_BuildWinArray( wndPtr, 0, NULL )) ) - { - POINT delta = pt; - - for (ppWnd = list; *ppWnd; ppWnd++) - { - WIN_UpdateWndPtr(&wndPtr,*ppWnd); - if (!IsWindow(wndPtr->hwndSelf)) continue; - if (wndPtr->dwStyle & WS_VISIBLE) - { - r.left = wndPtr->rectWindow.left + delta.x; - r.top = wndPtr->rectWindow.top + delta.y; - r.right = wndPtr->rectWindow.right + delta.x; - r.bottom = wndPtr->rectWindow.bottom + delta.y; - - pt.x = -r.left; pt.y = -r.top; - - hrgn2 = REGION_CropRgn( hrgn2, hrgn, &r, &pt ); - - GetRgnBox( hrgn2, &r2 ); - if( !IsRectEmpty( &r2 ) ) - { - PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn2, flags, - RDW_EX_USEHRGN | RDW_EX_XYWINDOW ); - } - } - } - WIN_ReleaseWinArray(list); - } - } - else - { - if( (list = WIN_BuildWinArray( wndPtr, 0, NULL )) ) - { - for (ppWnd = list; *ppWnd; ppWnd++) - { - WIN_UpdateWndPtr(&wndPtr,*ppWnd); - if (IsWindow( wndPtr->hwndSelf )) - PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, flags, 0 ); - } - WIN_ReleaseWinArray(list); - } - } - - } + hRgn = RDW_Paint( wndPtr, (hRgn == 1) ? 0 : hRgn, flags, ex ); END: - if( hrgn2 > 1 && (hrgn2 != hrgnUpdate) ) - DeleteObject( hrgn2 ); - if( hrgn > 1 && (hrgn != hrgnUpdate) ) - DeleteObject( hrgn ); + if( hRgn > 1 && (hRgn != hrgnUpdate) ) + DeleteObject(hRgn ); WIN_ReleaseWndPtr(wndPtr); return TRUE; } diff --git a/windows/win.c b/windows/win.c index b32c33d155c..ec4e749544b 100644 --- a/windows/win.c +++ b/windows/win.c @@ -658,7 +658,7 @@ BOOL WIN_CreateDesktopWindow(void) pWndDesktop->pProp = NULL; pWndDesktop->wIDmenu = 0; pWndDesktop->helpContext = 0; - pWndDesktop->flags = 0; + pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0; pWndDesktop->hSysMenu = 0; pWndDesktop->userdata = 0; pWndDesktop->winproc = (WNDPROC16)class->winproc; diff --git a/windows/winpos.c b/windows/winpos.c index 4200fff772e..b729de06ce1 100644 --- a/windows/winpos.c +++ b/windows/winpos.c @@ -50,6 +50,7 @@ DEFAULT_DEBUG_CHANNEL(win) #define SWP_EX_NOCOPY 0x0001 #define SWP_EX_PAINTSELF 0x0002 +#define SWP_EX_NONCLIENT 0x0004 #define MINMAX_NOSWP 0x00010000 @@ -1148,15 +1149,12 @@ void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos, UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect ) { UINT swpFlags = 0; - POINT pt; - POINT size; + POINT pt, size; LPINTERNALPOS lpPos; TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd ); - size.x = wndPtr->rectWindow.left; - size.y = wndPtr->rectWindow.top; - + size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top; lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow ); if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd)) @@ -1702,8 +1700,8 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus) * (global active queue may have changed) */ pTempActiveQueue = QUEUE_Lock( hActiveQueue ); - if(!pTempActiveQueue) - goto CLEANUP_END; + if(!pTempActiveQueue) + goto CLEANUP_END; hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData ); QUEUE_Unlock( pTempActiveQueue ); @@ -2172,7 +2170,7 @@ nocopy: nch = Wnd->rectClient.bottom - Wnd->rectClient.top; if( (ocw != ncw) || (och != nch) || - ( ow != nw) || ( oh != nw) || + ( ow != nw) || ( oh != nh) || ((lpOldClientRect->top - lpOldWndRect->top) != (Wnd->rectClient.top - Wnd->rectWindow.top)) || ((lpOldClientRect->left - lpOldWndRect->left) != @@ -2223,18 +2221,35 @@ nocopy: if( dx || dy ) { + RECT rClip; + HDC hDC; DC* dc; - HDC hDC = ( uFlags & SWP_EX_PAINTSELF) - ? GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE | - DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS ) - : GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE | - DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS ); + + /* get DC and clip rect with drawable rect to avoid superfluous expose events + from copying clipped areas */ + + if( uFlags & SWP_EX_PAINTSELF ) + { + hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE | + DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS ); + rClip.right = nw; rClip.bottom = nh; + } + else + { + hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE | + DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS ); + rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left; + rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top; + } + rClip.left = rClip.top = 0; + if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) ) { if( oh > nh ) r.bottom = r.top + nh; if( ow < nw ) r.right = r.left + nw; - Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE ); + if( IntersectRect( &r, &r, &rClip ) ) + Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE ); GDI_HEAP_UNLOCK( hDC ); } @@ -2264,7 +2279,11 @@ static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD sw if( !(swpFlags & SWP_NOCLIENTSIZE) ) { - /* FIXME: WVR alignment flags */ + /* Client rect changed its position/size, most likely a scrollar + * was added/removed. + * + * FIXME: WVR alignment flags + */ if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */ { @@ -2312,7 +2331,9 @@ redraw: RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN ); } else - hrgn = WIN_UpdateNCRgn(wndPtr, TRUE, TRUE); + { + WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE); + } if( hrgn > 1 ) DeleteObject( hrgn ); @@ -2526,7 +2547,7 @@ Pos: /* ----------------------------------------------------------------------- if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf ) winpos.flags |= SWP_NOZORDER; - if( !(winpos.flags & SWP_NOREDRAW) && + if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) && ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) ) { @@ -2542,13 +2563,8 @@ Pos: /* ----------------------------------------------------------------------- if(!(winpos.flags & SWP_NOZORDER)) { - /* upon window creation (while processing WM_NCCREATE), wndPtr->parent is set correctly - * but wndPtr is not yet in wndPtr->parent->child list - * in those cases (SetWindowPos called while processing WM_NCCREATE), - * do not unlink/link winPtr in parent->child - */ - if ( WIN_UnlinkWindow( winpos.hwnd ) ) - WIN_LinkWindow( winpos.hwnd, hwndInsertAfter ); + WIN_UnlinkWindow( winpos.hwnd ); + WIN_LinkWindow( winpos.hwnd, hwndInsertAfter ); } /* Reset active DCEs */ @@ -2574,9 +2590,17 @@ Pos: /* ----------------------------------------------------------------------- if( oldClientRect.right - oldClientRect.left == newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW; - uFlags |= ((winpos.flags & SWP_NOCOPYBITS) || - (!(winpos.flags & SWP_NOCLIENTSIZE) && - (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS))) ? SWP_EX_NOCOPY : 0; + if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) && + (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) ) + { + uFlags |= SWP_EX_NOCOPY; + } +/* + * Use this later in CopyValidBits() + * + else if( 0 ) + uFlags |= SWP_EX_NONCLIENT; + */ /* FIXME: actually do something with WVR_VALIDRECTS */ @@ -2596,66 +2620,63 @@ Pos: /* ----------------------------------------------------------------------- of windows created by the host window system, all other cases go through the expose event handling */ - if( (winpos.flags & SWP_FRAMECHANGED) ) + if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) ) { - INT x, y; + cx = newWindowRect.right - newWindowRect.left; + cy = newWindowRect.bottom - newWindowRect.top; - if( (x = (newWindowRect.right - newWindowRect.left)) == (oldWindowRect.right - oldWindowRect.left) && - (y = (newWindowRect.bottom - newWindowRect.top)) == (oldWindowRect.bottom - oldWindowRect.top) ) + wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE); + winpos.hwndInsertAfter = tempInsertAfter; + bCallDriver = FALSE; + + if( winpos.flags & SWP_NOCLIENTMOVE ) + SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags ); + else { + /* client area moved but window extents remained the same, copy valid bits */ - wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE); - winpos.hwndInsertAfter = tempInsertAfter; - bCallDriver = FALSE; - - if( winpos.flags & SWP_NOCLIENTMOVE ) - SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags ); - else - { - /* client area moved but window extents remained the same, copy valid bits */ - - visRgn = CreateRectRgn( 0, 0, x, y ); - uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect, - uFlags | SWP_EX_PAINTSELF ); - } + visRgn = CreateRectRgn( 0, 0, cx, cy ); + uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect, + uFlags | SWP_EX_PAINTSELF ); } } } if( bCallDriver ) { - if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) ) - { - if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) && - (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) && - !(uFlags & SWP_EX_NOCOPY) ) + if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) ) { - /* The origin of the client rect didn't move so we can try to repaint - * only the nonclient area by setting bit gravity hint for the host window system. - */ - - if( !(wndPtr->flags & WIN_MANAGED) ) + if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) && + (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) && + !(uFlags & SWP_EX_NOCOPY) ) { - HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left, - newWindowRect.bottom - newWindowRect.top); - RECT rcn = newClientRect; - RECT rco = oldClientRect; + /* The origin of the client rect didn't move so we can try to repaint + * only the nonclient area by setting bit gravity hint for the host window system. + */ - OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top ); - OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top ); - IntersectRect( &rcn, &rcn, &rco ); - visRgn = CreateRectRgnIndirect( &rcn ); - CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF ); - DeleteObject( hrgn ); - uFlags = SWP_EX_PAINTSELF; - } - wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest ); + if( !(wndPtr->flags & WIN_MANAGED) ) + { + HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left, + newWindowRect.bottom - newWindowRect.top); + RECT rcn = newClientRect; + RECT rco = oldClientRect; + + OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top ); + OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top ); + IntersectRect( &rcn, &rcn, &rco ); + visRgn = CreateRectRgnIndirect( &rcn ); + CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF ); + DeleteObject( hrgn ); + uFlags = SWP_EX_PAINTSELF; + } + wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest ); + } + else + wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget ); } - else - wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget ); - } - wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE); - winpos.hwndInsertAfter = tempInsertAfter; + + wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE); + winpos.hwndInsertAfter = tempInsertAfter; } if( winpos.flags & SWP_SHOWWINDOW ) diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c index 1628fca0ff7..730d43f195e 100644 --- a/windows/x11drv/event.c +++ b/windows/x11drv/event.c @@ -1518,7 +1518,8 @@ void EVENT_UnmapNotify( HWND hWnd, XUnmapEvent *event ) if (pWnd->flags & WIN_MANAGED) { EndMenu(); - pWnd->dwStyle |= WS_MINIMIZE; + if( pWnd->dwStyle & WS_VISIBLE ) + pWnd->dwStyle |= WS_MINIMIZE; } WIN_ReleaseWndPtr(pWnd); }