Moved hrgnUpdate from client to window coordinates, made nonclient
painting depend on the update region, reworked SetWindowPos() and
RedrawWindow() to speed up update region calculation, made -desktop
work properly, added WM_CANCELMODE here and there, fixed several
window activation bugs that crept in since the last time.
diff --git a/windows/dce.c b/windows/dce.c
index a2e9175..e9d1de7 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -222,8 +222,9 @@
* DCE_InvalidateDCE
*
* It is called from SetWindowPos() - we have to mark as dirty all busy
- * DCE's for windows that have pWnd->parent as an ansector and whose client
- * rect intersects with specified update rectangle.
+ * DCEs for windows that have pWnd->parent as an ansector and whose client
+ * rect intersects with specified update rectangle. In addition, pWnd->parent
+ * DCEs may need to be updated if DCX_CLIPCHILDREN flag is set.
*/
BOOL DCE_InvalidateDCE(WND* pWnd, const RECT* pRectUpdate)
{
@@ -248,17 +249,25 @@
{
WND* wndCurrent = WIN_FindWndPtr(dce->hwndCurrent);
- if( wndCurrent && wndCurrent != WIN_GetDesktop() )
+ if( wndCurrent )
{
WND* wnd = NULL;
INT xoffset = 0, yoffset = 0;
if( (wndCurrent == wndScope) && !(dce->DCXflags & DCX_CLIPCHILDREN) )
{
+ /* child window positions don't bother us */
WIN_ReleaseWndPtr(wndCurrent);
continue;
}
+ if( !Options.desktopGeometry && wndCurrent == WIN_GetDesktop() )
+ {
+ /* don't bother with fake desktop */
+ WIN_ReleaseDesktop();
+ continue;
+ }
+
/* check if DCE window is within the z-order scope */
for( wnd = WIN_LockWndPtr(wndCurrent); wnd; WIN_UpdateWndPtr(&wnd,wnd->parent))
@@ -305,7 +314,6 @@
}
}
WIN_ReleaseWndPtr(wndCurrent);
- WIN_ReleaseDesktop();
}
} /* dce list */
}
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 0a71f83..5b7ba08 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -11,6 +11,7 @@
#include "sysmetrics.h"
#include "user.h"
#include "heap.h"
+#include "dce.h"
#include "cursoricon.h"
#include "dialog.h"
#include "menu.h"
@@ -1563,7 +1564,8 @@
TRACE(nonclient, "%04x %d\n", hwnd, active );
- if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
+ if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
+ ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
wndPtr->rectClient.top-wndPtr->rectWindow.top,
@@ -1665,7 +1667,7 @@
BOOL suppress_menupaint )
{
HDC hdc;
- RECT rect;
+ RECT rfuzz, rect, rectClip;
BOOL active;
HWND hwnd = wndPtr->hwndSelf;
@@ -1676,7 +1678,15 @@
TRACE(nonclient, "%04x %d\n", hwnd, active );
- if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
+ /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in the call to
+ * GetDCEx implying that it is allowed not to use it either. However, the suggested
+ * GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN) will cause clipRgn to be deleted
+ * after ReleaseDC(). Now, how is the "system" supposed to tell what happened?
+ */
+
+ if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
+ ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
+
if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
wndPtr->rectClient.top-wndPtr->rectWindow.top,
@@ -1692,6 +1702,14 @@
rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
+ if( clip > 1 )
+ GetRgnBox( clip, &rectClip );
+ else
+ {
+ clip = 0;
+ rectClip = rect;
+ }
+
SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
if(!(wndPtr->flags & WIN_MANAGED)) {
@@ -1716,8 +1734,9 @@
r.bottom = rect.top + sysMetrics[SM_CYCAPTION];
rect.top += sysMetrics[SM_CYCAPTION];
}
- NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
- wndPtr->dwExStyle, active);
+ if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
+ NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
+ wndPtr->dwExStyle, active);
}
}
diff --git a/windows/painting.c b/windows/painting.c
index 8ca4063..5cc8d3f 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -2,12 +2,11 @@
* Window painting functions
*
* Copyright 1993, 1994, 1995 Alexandre Julliard
+ * 1999 Alex Korobka
*
- * FIXME: Do not repaint full nonclient area all the time. Instead, compute
- * intersection with hrgnUpdate (which should be moved from client to
- * window coords as well, lookup 'the pain' comment in the winpos.c).
*/
+#include "region.h"
#include "win.h"
#include "queue.h"
#include "dce.h"
@@ -15,74 +14,98 @@
#include "debug.h"
#include "wine/winuser16.h"
+/* client rect in window coordinates */
+
+#define GETCLIENTRECTW( wnd, r ) (r).left = (wnd)->rectClient.left - (wnd)->rectWindow.left; \
+ (r).top = (wnd)->rectClient.top - (wnd)->rectWindow.top; \
+ (r).right = (wnd)->rectClient.right - (wnd)->rectWindow.left; \
+ (r).bottom = (wnd)->rectClient.bottom - (wnd)->rectWindow.top
+
/* Last CTLCOLOR id */
#define CTLCOLOR_MAX CTLCOLOR_STATIC
-/***********************************************************************
- * WIN_UpdateNCArea
- *
- */
-void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate)
-{
- POINT16 pt = {0, 0};
- HRGN hClip = 1;
- TRACE(nonclient,"hwnd %04x, hrgnUpdate %04x\n",
- wnd->hwndSelf, wnd->hrgnUpdate );
+/***********************************************************************
+ * WIN_UpdateNCRgn
+ *
+ * NOTE: Caller is responsible for the returned region.
+ */
+HRGN WIN_UpdateNCRgn(WND* wnd, BOOL bUpdate, BOOL bForceEntire )
+{
+ HRGN hClip = 0;
+
+ TRACE(nonclient,"hwnd %04x, hrgnUpdate %04x, ncf %i\n",
+ wnd->hwndSelf, wnd->hrgnUpdate, (wnd->flags & WIN_NEEDS_NCPAINT)!=0 );
/* desktop window doesn't have nonclient area */
if(wnd == WIN_GetDesktop())
{
wnd->flags &= ~WIN_NEEDS_NCPAINT;
WIN_ReleaseDesktop();
- return;
+ return 0;
}
WIN_ReleaseDesktop();
- if( wnd->hrgnUpdate > 1 )
+ if ((wnd->hwndSelf == GetActiveWindow()) &&
+ !(wnd->flags & WIN_NCACTIVATED) )
{
- ClientToScreen16(wnd->hwndSelf, &pt);
-
- hClip = CreateRectRgn( 0, 0, 0, 0 );
- if (!CombineRgn( hClip, wnd->hrgnUpdate, 0, RGN_COPY ))
- {
- DeleteObject(hClip);
- hClip = 1;
- }
- else
- OffsetRgn( hClip, pt.x, pt.y );
-
- if (bUpdate)
- {
- /* exclude non-client area from update region */
- HRGN hrgn = CreateRectRgn( 0, 0,
- wnd->rectClient.right - wnd->rectClient.left,
- wnd->rectClient.bottom - wnd->rectClient.top);
-
- if (hrgn && (CombineRgn( wnd->hrgnUpdate, wnd->hrgnUpdate,
- hrgn, RGN_AND) == NULLREGION))
- {
- DeleteObject( wnd->hrgnUpdate );
- wnd->hrgnUpdate = 1;
- }
-
- DeleteObject( hrgn );
- }
+ wnd->flags |= WIN_NCACTIVATED;
+ bForceEntire = TRUE;
}
+ if( (wnd->flags & WIN_NEEDS_NCPAINT) && wnd->hrgnUpdate )
+ {
+ RECT r, r2, r3;
+
+ 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 )
+ {
+ GetRgnBox( wnd->hrgnUpdate, &r3 );
+ if( IsRectEmpty( &r3 ) )
+ {
+ /* delete 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;
+ }
+ }
+ }
+ else /* entire client rect */
+ wnd->hrgnUpdate = CreateRectRgnIndirect( &r );
+ }
+
+ if(!hClip && bForceEntire ) hClip = 1;
wnd->flags &= ~WIN_NEEDS_NCPAINT;
- if ((wnd->hwndSelf == GetActiveWindow()) &&
- !(wnd->flags & WIN_NCACTIVATED))
- {
- wnd->flags |= WIN_NCACTIVATED;
- if( hClip > 1) DeleteObject( hClip );
- hClip = 1;
- }
+ if( hClip )
+ SendMessageA( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
- if (hClip) SendMessage16( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
-
- if (hClip > 1) DeleteObject( hClip );
+ return hClip;
}
@@ -100,10 +123,10 @@
wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
- if (wndPtr->flags & WIN_NEEDS_NCPAINT) WIN_UpdateNCArea( wndPtr, TRUE );
+ if( (hrgnUpdate = WIN_UpdateNCRgn( wndPtr, FALSE, FALSE )) > 1 )
+ DeleteObject( hrgnUpdate );
- if (((hrgnUpdate = wndPtr->hrgnUpdate) != 0) ||
- (wndPtr->flags & WIN_INTERNAL_PAINT))
+ if( ((hrgnUpdate = wndPtr->hrgnUpdate) != 0) || (wndPtr->flags & WIN_INTERNAL_PAINT))
QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
wndPtr->hrgnUpdate = 0;
@@ -113,20 +136,19 @@
TRACE(win,"hrgnUpdate = %04x, \n", hrgnUpdate);
- /* When bIcon is TRUE hrgnUpdate is automatically in window coordinates
- * (because rectClient == rectWindow for WS_MINIMIZE windows).
- */
-
if (wndPtr->class->style & CS_PARENTDC)
{
/* Don't clip the output to the update region for CS_PARENTDC window */
- if(hrgnUpdate > 1)
+ if( hrgnUpdate > 1 )
DeleteObject(hrgnUpdate);
lps->hdc = GetDCEx16( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE |
(bIcon ? DCX_WINDOW : 0) );
}
else
{
+ if( hrgnUpdate )
+ 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) );
@@ -143,7 +165,7 @@
GetClipBox16( lps->hdc, &lps->rcPaint );
-TRACE(win,"box = (%i,%i - %i,%i)\n", lps->rcPaint.left, lps->rcPaint.top,
+ TRACE(win,"box = (%i,%i - %i,%i)\n", lps->rcPaint.left, lps->rcPaint.top,
lps->rcPaint.right, lps->rcPaint.bottom );
if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
@@ -285,14 +307,14 @@
* LOWORD(lParam) = hrgnClip
* HIWORD(lParam) = hwndSkip (not used; always NULL)
*
- * All in all, a prime candidate for a rewrite.
*/
BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
- HRGN hrgnUpdate, UINT flags, UINT control )
+ HRGN hrgnUpdate, UINT flags, UINT ex )
{
BOOL bIcon;
- HRGN hrgn;
- RECT rectClient;
+ HRGN hrgn = 0, hrgn2 = 0;
+ RECT r, r2;
+ POINT pt;
WND* wndPtr;
WND **list, **ppWnd;
@@ -307,110 +329,165 @@
bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
if (rectUpdate)
{
- TRACE(win, "%04x %d,%d-%d,%d %04x flags=%04x\n",
- hwnd, rectUpdate->left, rectUpdate->top,
- rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags );
+ 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
{
- TRACE(win, "%04x NULL %04x flags=%04x\n", hwnd, hrgnUpdate, flags);
+ 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);
}
- GetClientRect( hwnd, &rectClient );
+ if( flags & RDW_FRAME )
+ r = wndPtr->rectWindow;
+ else
+ r = wndPtr->rectClient;
+ if( ex & RDW_EX_XYWINDOW )
+ OffsetRect( &r, -wndPtr->rectWindow.left, -wndPtr->rectWindow.top );
+ else
+ OffsetRect( &r, -wndPtr->rectClient.left, -wndPtr->rectClient.top );
- if (flags & RDW_INVALIDATE) /* Invalidate */
+ /* 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 */
{
- int rgnNotEmpty = COMPLEXREGION;
+ BOOL bHasUpdateRgn = (BOOL)wndPtr->hrgnUpdate;
- if (wndPtr->hrgnUpdate > 1) /* Is there already an update region? */
- {
- if ((hrgn = hrgnUpdate) == 0)
- hrgn = CreateRectRgnIndirect( rectUpdate ? rectUpdate :
- &rectClient );
- rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
- hrgn, RGN_OR );
- if (!hrgnUpdate) DeleteObject( hrgn );
- }
- else /* No update region yet */
- {
- if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
- QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
- if (hrgnUpdate)
- {
- wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
- rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, hrgnUpdate,
- 0, RGN_COPY );
- }
- else wndPtr->hrgnUpdate = CreateRectRgnIndirect( rectUpdate ?
- rectUpdate : &rectClient );
- }
-
- if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
+ /* wndPtr->hrgnUpdate is in window coordinates, parameters are
+ * in client coordinates unless RDW_EX_XYWINDOW is set.
+ */
- /* restrict update region to client area (FIXME: correct?) */
- if (wndPtr->hrgnUpdate)
- {
- HRGN clientRgn = CreateRectRgnIndirect( &rectClient );
- rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, clientRgn,
- wndPtr->hrgnUpdate, RGN_AND );
- DeleteObject( clientRgn );
- }
+ if( hrgnUpdate )
+ {
+ hrgn = REGION_CropRgn( 0, hrgnUpdate, &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt );
+ GetRgnBox( hrgn, &r2 );
+ if( IsRectEmpty( &r2 ) )
+ goto END;
- /* check for bogus update region */
- if ( rgnNotEmpty == NULLREGION )
- {
- wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
- DeleteObject( wndPtr->hrgnUpdate );
- wndPtr->hrgnUpdate=0;
- if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
- QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
- }
- else
- if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
+ 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 );
+ }
+ else if( rectUpdate )
+ {
+ if( !IntersectRect( &r2, &r, rectUpdate ) )
+ goto END;
+ if( !(ex & RDW_EX_XYWINDOW) )
+ OffsetRect( &r2, pt.x, pt.y );
+
+rect2i: /* r2 contains a rect to add to the update region */
+
+ hrgn = CreateRectRgnIndirect( &r2 );
+ if( wndPtr->hrgnUpdate == 0 )
+ wndPtr->hrgnUpdate = CreateRectRgnIndirect( &r2 );
+ else
+ if( wndPtr->hrgnUpdate > 1 )
+ REGION_UnionRectWithRgn( wndPtr->hrgnUpdate, &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 */
+ 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 */
+ else if (flags & RDW_VALIDATE) /* ------------------------- Validate */
{
- /* We need an update region in order to validate anything */
- if (wndPtr->hrgnUpdate > 1)
+ if (wndPtr->hrgnUpdate) /* need an update region in order to validate anything */
{
- if (!hrgnUpdate && !rectUpdate)
+ 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 );
+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 */
{
- /* Special case: validate everything */
- DeleteObject( wndPtr->hrgnUpdate );
- wndPtr->hrgnUpdate = 0;
+ 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;
}
- else
- {
- if ((hrgn = hrgnUpdate) == 0)
- hrgn = CreateRectRgnIndirect( rectUpdate );
- if (CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
- hrgn, RGN_DIFF ) == NULLREGION)
- {
- DeleteObject( wndPtr->hrgnUpdate );
- wndPtr->hrgnUpdate = 0;
- }
- if (!hrgnUpdate) DeleteObject( hrgn );
- }
- if (!wndPtr->hrgnUpdate) /* No more update region */
- if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
+
+ 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;
}
- /* Set/clear internal paint flag */
+ /* At this point hrgn contains new update region in window coordinates */
+
+ /* Set/clear internal paint flag */
if (flags & RDW_INTERNALPAINT)
{
- if ( wndPtr->hrgnUpdate <= 1 && !(wndPtr->flags & WIN_INTERNAL_PAINT))
+ 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 <= 1 && (wndPtr->flags & WIN_INTERNAL_PAINT))
+ if ( !wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
wndPtr->flags &= ~WIN_INTERNAL_PAINT;
}
@@ -422,17 +499,29 @@
if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
SendMessage16( hwnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 );
}
- else if (flags & RDW_ERASENOW)
+ else if ((flags & RDW_ERASENOW) || (ex & RDW_EX_TOPFRAME))
{
- if (wndPtr->flags & WIN_NEEDS_NCPAINT)
- WIN_UpdateNCArea( wndPtr, FALSE);
+ hrgn2 = WIN_UpdateNCRgn( wndPtr, TRUE, (ex & RDW_EX_TOPFRAME) );
- if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
+ if( wndPtr->flags & WIN_NEEDS_ERASEBKGND )
{
- HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
- DCX_INTERSECTRGN | DCX_USESTYLE |
- DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
- (bIcon ? DCX_WINDOW : 0) );
+ HDC hdc;
+
+ if( hrgn2 > 1 )
+ {
+ OffsetRgn( hrgn2, -pt.x, -pt.y );
+ GetRgnBox( hrgn2, &r2 );
+ }
+ 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
@@ -456,47 +545,40 @@
((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) &&
!(wndPtr->dwStyle & WS_MINIMIZE) )
{
- if ( hrgnUpdate || rectUpdate )
+ if( hrgnUpdate || rectUpdate )
{
- if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 )))
- {
- WIN_ReleaseWndPtr(wndPtr);
- return TRUE;
- }
- if( !hrgnUpdate )
- {
- control |= (RDW_C_DELETEHRGN | RDW_C_USEHRGN);
- if( !(hrgnUpdate = CreateRectRgnIndirect( rectUpdate )) )
- {
- DeleteObject( hrgn );
- WIN_ReleaseWndPtr(wndPtr);
- return TRUE;
- }
- }
+ if( hrgn2 <= 1 )
+ hrgn2 = (ex & RDW_EX_USEHRGN) ? hrgnUpdate : 0;
+
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)
{
- SetRectRgn( hrgn,
- wndPtr->rectWindow.left, wndPtr->rectWindow.top,
- wndPtr->rectWindow.right, wndPtr->rectWindow.bottom );
- if (CombineRgn( hrgn, hrgn, hrgnUpdate, RGN_AND ))
+ 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 ) )
{
- OffsetRgn( hrgn, -wndPtr->rectClient.left,
- -wndPtr->rectClient.top );
- PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn, flags,
- RDW_C_USEHRGN );
+ PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn2, flags,
+ RDW_EX_USEHRGN | RDW_EX_XYWINDOW );
}
}
}
WIN_ReleaseWinArray(list);
}
- DeleteObject( hrgn );
- if (control & RDW_C_DELETEHRGN) DeleteObject( hrgnUpdate );
}
else
{
@@ -513,6 +595,12 @@
}
}
+
+END:
+ if( hrgn2 > 1 && (hrgn2 != hrgnUpdate) )
+ DeleteObject( hrgn2 );
+ if( hrgn > 1 && (hrgn != hrgnUpdate) )
+ DeleteObject( hrgn );
WIN_ReleaseWndPtr(wndPtr);
return TRUE;
}
@@ -680,9 +768,16 @@
}
}
}
- else SetRectEmpty( rect );
+ else
+ if( wndPtr->hrgnUpdate == 1 )
+ {
+ GetClientRect( hwnd, rect );
+ if (erase) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_ERASENOW | RDW_NOCHILDREN );
+ }
+ else
+ SetRectEmpty( rect );
}
- retvalue = (wndPtr->hrgnUpdate > 1);
+ retvalue = (wndPtr->hrgnUpdate >= 1);
END:
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
@@ -699,7 +794,7 @@
/***********************************************************************
- * GetUpdateRgn32 (USER32.298)
+ * GetUpdateRgn (USER32.298)
*/
INT WINAPI GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
{
@@ -707,13 +802,25 @@
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return ERROR;
- if (wndPtr->hrgnUpdate <= 1)
+ if (wndPtr->hrgnUpdate == 0)
{
SetRectRgn( hrgn, 0, 0, 0, 0 );
retval = NULLREGION;
goto END;
}
- retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
+ else
+ if (wndPtr->hrgnUpdate == 1)
+ {
+ SetRectRgn( hrgn, 0, 0, wndPtr->rectClient.right - wndPtr->rectClient.left,
+ wndPtr->rectClient.bottom - wndPtr->rectClient.top );
+ retval = SIMPLEREGION;
+ }
+ else
+ {
+ retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
+ OffsetRgn( hrgn, wndPtr->rectWindow.left - wndPtr->rectClient.left,
+ wndPtr->rectWindow.top - wndPtr->rectClient.top );
+ }
if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
END:
WIN_ReleaseWndPtr(wndPtr);
@@ -745,10 +852,14 @@
INT ret;
HRGN hrgn = CreateRectRgn(wndPtr->rectWindow.left - wndPtr->rectClient.left,
wndPtr->rectWindow.top - wndPtr->rectClient.top,
- wndPtr->rectClient.right - wndPtr->rectClient.left,
- wndPtr->rectClient.bottom - wndPtr->rectClient.top);
+ wndPtr->rectWindow.right - wndPtr->rectClient.left,
+ wndPtr->rectWindow.bottom - wndPtr->rectClient.top);
if( wndPtr->hrgnUpdate > 1 )
+ {
CombineRgn(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY);
+ OffsetRgn(hrgn, wndPtr->rectWindow.left - wndPtr->rectClient.left,
+ wndPtr->rectWindow.top - wndPtr->rectClient.top );
+ }
/* do ugly coordinate translations in dce.c */
diff --git a/windows/scroll.c b/windows/scroll.c
index bba77af..ddf6d7c 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -275,7 +275,7 @@
if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
{
if (dc->w.hVisRgn) {
- wnd->pDriver->pScrollWindow(wnd,dc,dx,dy,&rc,bUpdate);
+ wnd->pDriver->pSurfaceCopy(wnd,dc,dx,dy,&rc,bUpdate);
if( bUpdate )
{
diff --git a/windows/ttydrv/init.c b/windows/ttydrv/init.c
index a5203d7..b7e6396 100644
--- a/windows/ttydrv/init.c
+++ b/windows/ttydrv/init.c
@@ -81,6 +81,7 @@
TTYDRV_WND_PostSizeMove,
TTYDRV_WND_ScrollWindow,
TTYDRV_WND_SetDrawable,
+ TTYDRV_WND_SetHostAttr,
TTYDRV_WND_IsSelfClipping
};
diff --git a/windows/ttydrv/wnd.c b/windows/ttydrv/wnd.c
index da2b184..7085ac9 100644
--- a/windows/ttydrv/wnd.c
+++ b/windows/ttydrv/wnd.c
@@ -117,6 +117,14 @@
}
/***********************************************************************
+ * TTYDRV_WND_SetHostAttr
+ */
+BOOL TTYDRV_WND_SetHostAttr(WND *wndPtr, INT attr, INT value)
+{
+ return FALSE;
+}
+
+/***********************************************************************
* TTYDRV_WND_IsSelfClipping
*/
BOOL TTYDRV_WND_IsSelfClipping(WND *wndPtr)
diff --git a/windows/win.c b/windows/win.c
index 2970fb9..5cf69a4 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -1666,14 +1666,24 @@
{
/* Enable window */
wndPtr->dwStyle &= ~WS_DISABLED;
+
+ if( wndPtr->flags & WIN_NATIVE )
+ wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
+
SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
retvalue = TRUE;
goto end;
}
else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
{
+ SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
+
/* Disable window */
wndPtr->dwStyle |= WS_DISABLED;
+
+ if( wndPtr->flags & WIN_NATIVE )
+ wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
+
if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
{
SetFocus( 0 ); /* A disabled window can't have the focus */
diff --git a/windows/winpos.c b/windows/winpos.c
index dbe7ec1..910fb4a 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -2,7 +2,7 @@
* Window position related functions.
*
* Copyright 1993, 1994, 1995 Alexandre Julliard
- * 1995, 1996 Alex Korobka
+ * 1995, 1996, 1999 Alex Korobka
*/
#include "x11drv.h"
@@ -12,6 +12,7 @@
#include "heap.h"
#include "module.h"
#include "user.h"
+#include "region.h"
#include "win.h"
#include "hook.h"
#include "message.h"
@@ -46,10 +47,8 @@
#define PLACE_MAX 0x0002
#define PLACE_RECT 0x0004
-#define SMC_NOCOPY 0x0001
-#define SMC_NOPARENTERASE 0x0002
-#define SMC_DRAWFRAME 0x0004
-#define SMC_SETXPOS 0x0008
+#define SWP_EX_NOCOPY 0x0001
+#define SWP_EX_PAINTSELF 0x0002
/* ----- internal variables ----- */
@@ -396,7 +395,14 @@
if( wndScope->flags & WIN_MANAGED )
{
- /* this prevents mouse clicks from going "through" scrollbars in managed mode */
+ /* In managed mode we have to check wndScope first as it is also
+ * a window which received the mouse event. */
+
+ if( wndScope->dwStyle & WS_DISABLED )
+ {
+ retvalue = HTERROR;
+ goto end;
+ }
if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
goto hittest;
@@ -1688,6 +1694,9 @@
if ( pNewActiveQueue )
PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
}
+ else /* have to do this or MDI frame activation goes to hell */
+ if( pOldActiveQueue )
+ PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
/* send palette messages */
if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
@@ -1875,13 +1884,10 @@
*/
BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
{
- WND *wndPtr = WIN_FindWndPtr(hWnd);
- WND *wndTemp;
+ WND *wndPtr, *wndTemp;
BOOL retvalue;
HWND hwndActive = 0;
- if( !wndPtr ) return FALSE;
-
/* Get current active window from the active queue */
if ( hActiveQueue )
{
@@ -1894,11 +1900,10 @@
}
if (!hWnd)
- {
- retvalue = WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
- goto end;
- }
+ return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
+ wndPtr = WIN_FindWndPtr(hWnd);
+ if( !wndPtr ) return FALSE;
/* child windows get WM_CHILDACTIVATE message */
if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
@@ -1907,20 +1912,6 @@
goto end;
}
- /* owned popups imply owner activation - not sure */
- if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
- (wndPtr->owner->dwStyle & WS_VISIBLE ) &&
- !(wndPtr->owner->dwStyle & WS_DISABLED ))
- {
- WIN_UpdateWndPtr(&wndPtr,wndPtr->owner);
- if (!wndPtr)
- {
- retvalue = FALSE;
- goto end;
- }
- hWnd = wndPtr->hwndSelf;
- }
-
if( hWnd == hwndActive )
{
retvalue = FALSE;
@@ -2025,291 +2016,322 @@
return 0;
}
-
/***********************************************************************
- * WINPOS_MoveWindowZOrder
- *
- * Move a window in Z order, invalidating everything that needs it.
- * Only necessary for windows without associated X window.
- */
-static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
-{
- BOOL movingUp;
- WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
-
- /* We have two possible cases:
- * - The window is moving up: we have to invalidate all areas
- * of the window that were covered by other windows
- * - The window is moving down: we have to invalidate areas
- * of other windows covered by this one.
- */
-
- if (hwndAfter == HWND_TOP)
- {
- movingUp = TRUE;
- }
- else if (hwndAfter == HWND_BOTTOM)
- {
- if (!wndPtr->next) goto END; /* Already at the bottom */
- movingUp = FALSE;
- }
- else
- {
- if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) goto END;
- if (wndPtr->next == pWndAfter)
- {
- WIN_ReleaseWndPtr(pWndAfter);
- goto END; /* Already placed right */
- }
-
- /* Determine which window we encounter first in Z-order */
- pWndCur = WIN_LockWndPtr(wndPtr->parent->child);
- while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
- {
- WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
- }
- movingUp = (pWndCur == pWndAfter);
- WIN_ReleaseWndPtr(pWndCur);
- WIN_ReleaseWndPtr(pWndAfter);
- }
-
- if (movingUp)
- {
- WND *pWndPrevAfter = WIN_LockWndPtr(wndPtr->next);
- WIN_UnlinkWindow( hwnd );
- WIN_LinkWindow( hwnd, hwndAfter );
- pWndCur = WIN_LockWndPtr(wndPtr->next);
- while (pWndCur != pWndPrevAfter)
- {
- RECT rect = { pWndCur->rectWindow.left,
- pWndCur->rectWindow.top,
- pWndCur->rectWindow.right,
- pWndCur->rectWindow.bottom };
- OffsetRect( &rect, -wndPtr->rectClient.left,
- -wndPtr->rectClient.top );
- PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
- RDW_FRAME | RDW_ERASE, 0 );
- WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
- }
- WIN_ReleaseWndPtr(pWndPrevAfter);
- }
- else /* Moving down */
- {
- pWndCur = WIN_LockWndPtr(wndPtr->next);
- WIN_UnlinkWindow( hwnd );
- WIN_LinkWindow( hwnd, hwndAfter );
- while (pWndCur != wndPtr)
- {
- RECT rect = { pWndCur->rectWindow.left,
- pWndCur->rectWindow.top,
- pWndCur->rectWindow.right,
- pWndCur->rectWindow.bottom };
- OffsetRect( &rect, -pWndCur->rectClient.left,
- -pWndCur->rectClient.top );
- PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
- RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
- WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
- }
- }
-END:
- WIN_ReleaseWndPtr(wndPtr);
-}
-
-/***********************************************************************
- * WINPOS_ReorderOwnedPopups
+ * SWP_DoOwnedPopups
*
* fix Z order taking into account owned popups -
* basically we need to maintain them above the window that owns them
+ *
+ * FIXME: hide/show owned popups when owner visibility changes.
*/
-HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter,WND* wndPtr,WORD flags)
+static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
{
- WND* pDesktop = WIN_GetDesktop();
- WND* w = WIN_LockWndPtr(pDesktop->child);
+ WND* w = WIN_LockWndPtr(pDesktop->child);
- if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
- {
- /* implement "local z-order" between the top and owner window */
+ WARN(win, "(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
- HWND hwndLocalPrev = HWND_TOP;
-
- if( hwndInsertAfter != HWND_TOP )
- {
- while( w != wndPtr->owner )
- {
- if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
- if( hwndLocalPrev == hwndInsertAfter ) break;
- WIN_UpdateWndPtr(&w,w->next);
- }
- hwndInsertAfter = hwndLocalPrev;
- }
-
- }
- else if( wndPtr->dwStyle & WS_CHILD )
- goto END;
-
- WIN_UpdateWndPtr(&w,pDesktop->child);
-
- while( w )
- {
- if( w == wndPtr ) break;
-
- if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
+ if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
{
- SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
- SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
- hwndInsertAfter = w->hwndSelf;
+ /* make sure this popup stays above the owner */
+
+ HWND hwndLocalPrev = HWND_TOP;
+
+ if( hwndInsertAfter != HWND_TOP )
+ {
+ while( w != wndPtr->owner )
+ {
+ if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
+ if( hwndLocalPrev == hwndInsertAfter ) break;
+ WIN_UpdateWndPtr(&w,w->next);
+ }
+ hwndInsertAfter = hwndLocalPrev;
+ }
}
- WIN_UpdateWndPtr(&w,w->next);
- }
+ else if( wndPtr->dwStyle & WS_CHILD )
+ goto END;
+
+ WIN_UpdateWndPtr(&w, pDesktop->child);
+
+ while( w )
+ {
+ if( w == wndPtr ) break;
+
+ if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
+ {
+ SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
+ hwndInsertAfter = w->hwndSelf;
+ }
+ WIN_UpdateWndPtr(&w, w->next);
+ }
END:
- WIN_ReleaseWndPtr(w);
- WIN_ReleaseDesktop();
- return hwndInsertAfter;
+ WIN_ReleaseWndPtr(w);
+ return hwndInsertAfter;
}
/***********************************************************************
- * WINPOS_SizeMoveClean
+ * SWP_CopyValidBits
*
* Make window look nice without excessive repainting
*
- * the pain:
- *
- * visible regions are in window coordinates
- * update regions are in window client coordinates
+ * visible and update regions are in window coordinates
* client and window rectangles are in parent client coordinates
*
- * FIXME: Move visible and update regions to the same coordinate system
- * (either parent client or window). This is a lot of work though.
+ * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
+ * window rects have the same origin.
+ *
+ * Returns: uFlags and a dirty region in *pVisRgn.
*/
-static UINT WINPOS_SizeMoveClean( WND* Wnd, HRGN oldVisRgn,
- LPRECT lpOldWndRect,
- LPRECT lpOldClientRect, UINT uFlags )
+static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
+ LPRECT lpOldWndRect,
+ LPRECT lpOldClientRect, UINT uFlags )
{
- HRGN newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS,0,0);
- HRGN dirtyRgn = CreateRectRgn(0,0,0,0);
- int other, my;
+ RECT r;
+ HRGN newVisRgn, dirtyRgn;
+ INT my = COMPLEXREGION;
- TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
+ TRACE(win,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
Wnd->rectWindow.left, Wnd->rectWindow.top,
Wnd->rectWindow.right, Wnd->rectWindow.bottom,
lpOldWndRect->left, lpOldWndRect->top,
- lpOldWndRect->right, lpOldWndRect->bottom);
+ lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
Wnd->rectClient.left, Wnd->rectClient.top,
Wnd->rectClient.right, Wnd->rectClient.bottom,
lpOldClientRect->left, lpOldClientRect->top,
lpOldClientRect->right,lpOldClientRect->bottom );
- if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
- (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
- uFlags |= SMC_DRAWFRAME;
+ if( Wnd->hrgnUpdate == 1 )
+ uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
- CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
+ newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
+ dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
- if( !(uFlags & SMC_NOCOPY) )
- CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND );
+ if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
+ my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
- /* map regions to the parent client area */
-
- OffsetRgn( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
- OffsetRgn( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
+ if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
+ {
+nocopy:
- /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
+ TRACE(win,"\twon't copy anything!\n");
- other = CombineRgn(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
+ /* set dirtyRgn to the sum of old and new visible regions
+ * in parent client coordinates */
- /* map visible region to the Wnd client area */
+ OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
+ OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
- OffsetRgn( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
- Wnd->rectWindow.top - Wnd->rectClient.top );
+ CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
+ }
+ else /* copy valid bits to a new location */
+ {
+ INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
+ HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
- /* substract previously invalidated region from the Wnd visible region */
+ /* subtract already invalid region inside Wnd from the dst region */
- my = (Wnd->hrgnUpdate > 1) ? CombineRgn( newVisRgn, newVisRgn,
- Wnd->hrgnUpdate, RGN_DIFF)
- : COMPLEXREGION;
+ if( Wnd->hrgnUpdate )
+ if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
+ goto nocopy;
- if( uFlags & SMC_NOCOPY ) /* invalidate Wnd visible region */
- {
- if (my != NULLREGION)
- PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
- RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
- else if(uFlags & SMC_DRAWFRAME)
- Wnd->flags |= WIN_NEEDS_NCPAINT;
- }
- else /* bitblt old client area */
- {
- HDC hDC;
- int update;
- HRGN updateRgn;
- int xfrom,yfrom,xto,yto,width,height;
+ /* check if entire window can be copied */
- if( uFlags & SMC_DRAWFRAME )
- {
- /* copy only client area, frame will be redrawn anyway */
+ ow = lpOldWndRect->right - lpOldWndRect->left;
+ oh = lpOldWndRect->bottom - lpOldWndRect->top;
+ nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
+ nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
- xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
- xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
- width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
- updateRgn = CreateRectRgn( 0, 0, width, height );
- CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
- SetRectRgn( updateRgn, 0, 0, Wnd->rectClient.right - xto,
- Wnd->rectClient.bottom - yto );
- }
+ ocw = lpOldClientRect->right - lpOldClientRect->left;
+ och = lpOldClientRect->bottom - lpOldClientRect->top;
+ ncw = Wnd->rectClient.right - Wnd->rectClient.left;
+ nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
+
+ if( (ocw != ncw) || (och != nch) ||
+ ( ow != nw) || ( oh != nw) ||
+ ((lpOldClientRect->top - lpOldWndRect->top) !=
+ (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
+ ((lpOldClientRect->left - lpOldWndRect->left) !=
+ (Wnd->rectClient.left - Wnd->rectWindow.left)) )
+ {
+ dx = Wnd->rectClient.left - lpOldClientRect->left;
+ dy = Wnd->rectClient.top - lpOldClientRect->top;
+
+ /* restrict valid bits to the common client rect */
+
+ r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
+ r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
+ r.right = r.left + MIN( ocw, ncw );
+ r.bottom = r.top + MIN( och, nch );
+
+ REGION_CropRgn( hrgnValid, hrgnValid, &r,
+ (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
+ GetRgnBox( hrgnValid, &r );
+ if( IsRectEmpty( &r ) )
+ goto nocopy;
+ r = *lpOldClientRect;
+ }
else
- {
- xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
- xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
- width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
- updateRgn = CreateRectRgn( xto - Wnd->rectClient.left,
- yto - Wnd->rectClient.top,
- Wnd->rectWindow.right - Wnd->rectClient.left,
- Wnd->rectWindow.bottom - Wnd->rectClient.top );
- }
+ {
+ dx = Wnd->rectWindow.left - lpOldWndRect->left;
+ dy = Wnd->rectWindow.top - lpOldWndRect->top;
+ if( !(uFlags & SWP_EX_PAINTSELF) )
+ OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
+ r = *lpOldWndRect;
+ }
- CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
+ if( !(uFlags & SWP_EX_PAINTSELF) )
+ {
+ /* Move remaining regions to parent coordinates */
+ OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
+ OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
+ }
+ else
+ OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
- /* substract new visRgn from target rect to get a region that won't be copied */
+ TRACE(win,"\tcomputing dirty region!\n");
- update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
+ /* Compute combined dirty region (old + new - valid) */
+ CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
+ CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
- /* Blt valid bits using parent window DC */
+ /* Blt valid bits, r is the rect to copy */
- if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
- {
-
- /* compute clipping region in parent client coordinates */
+ if( dx || dy )
+ {
+ 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 );
+ if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
+ {
+ if( oh > nh ) r.bottom = r.top + nh;
+ if( ow < nw ) r.right = r.left + nw;
- OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
- CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
+ Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
- hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn,
- DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
- DCX_CACHE | DCX_CLIPSIBLINGS);
+ GDI_HEAP_UNLOCK( hDC );
+ }
+ ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
+ Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
+ }
+ }
- BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
- ReleaseDC( Wnd->parent->hwndSelf, hDC);
- }
+ /* *pVisRgn now points to the invalidated region */
- if( update != NULLREGION )
- PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
- RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
- else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
- DeleteObject( updateRgn );
- }
-
- /* erase uncovered areas */
-
- if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
- PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
- RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
- DeleteObject(dirtyRgn);
DeleteObject(newVisRgn);
+ DeleteObject(dirtyRgn);
return uFlags;
}
/***********************************************************************
+ * SWP_DoSimpleFrameChanged
+ */
+static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pNewClientRect, RECT* pOldClientRect )
+{
+ WORD wErase = 0;
+ RECT rect;
+
+ if( pNewClientRect->right > pOldClientRect->right ) /* redraw exposed client area on the right */
+ {
+ rect.top = 0; rect.bottom = pNewClientRect->bottom - pNewClientRect->top;
+ rect.left = pOldClientRect->right - pNewClientRect->left;
+ rect.right = pNewClientRect->right - pNewClientRect->left;
+ wErase = 1;
+ PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
+ RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME );
+ }
+ if( pNewClientRect->bottom > pOldClientRect->bottom ) /* redraw exposed client area on the bottom */
+ {
+ rect.left = 0; rect.right = ((wErase)? pOldClientRect->right : pNewClientRect->right) - pNewClientRect->left;
+ rect.top = pOldClientRect->bottom - pNewClientRect->top;
+ rect.bottom = pNewClientRect->bottom - pNewClientRect->top;
+ wErase = 1;
+ PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
+ RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME );
+ }
+ if( !wErase ) /* IMMEDIATELY update the nonclient area */
+ {
+ HRGN h;
+ if( (h = WIN_UpdateNCRgn(wndPtr, TRUE, TRUE)) > 1) DeleteObject( h );
+ }
+}
+
+/***********************************************************************
+ * SWP_DoWinPosChanging
+ */
+static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
+ RECT* pNewWindowRect, RECT* pNewClientRect )
+{
+ /* Send WM_WINDOWPOSCHANGING message */
+
+ if (!(pWinpos->flags & SWP_NOSENDCHANGING))
+ SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
+
+ /* Calculate new position and size */
+
+ *pNewWindowRect = wndPtr->rectWindow;
+ *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
+ : wndPtr->rectClient;
+
+ if (!(pWinpos->flags & SWP_NOSIZE))
+ {
+ pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
+ pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
+ }
+ if (!(pWinpos->flags & SWP_NOMOVE))
+ {
+ pNewWindowRect->left = pWinpos->x;
+ pNewWindowRect->top = pWinpos->y;
+ pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
+ pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
+
+ OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
+ pWinpos->y - wndPtr->rectWindow.top );
+ }
+
+ pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
+ return TRUE;
+}
+
+/***********************************************************************
+ * SWP_DoNCCalcSize
+ */
+static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
+ RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
+{
+ UINT wvrFlags = 0;
+
+ /* Send WM_NCCALCSIZE message to get new client area */
+ if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
+ {
+ wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
+ &wndPtr->rectWindow, &wndPtr->rectClient,
+ pWinpos, pNewClientRect );
+
+ /* FIXME: WVR_ALIGNxxx */
+
+ if( pNewClientRect->left != wndPtr->rectClient.left ||
+ pNewClientRect->top != wndPtr->rectClient.top )
+ pWinpos->flags &= ~SWP_NOCLIENTMOVE;
+
+ if( (pNewClientRect->right - pNewClientRect->left !=
+ wndPtr->rectClient.right - wndPtr->rectClient.left) ||
+ (pNewClientRect->bottom - pNewClientRect->top !=
+ wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
+ pWinpos->flags &= ~SWP_NOCLIENTSIZE;
+ }
+ else
+ if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
+ pNewClientRect->top != wndPtr->rectClient.top) )
+ pWinpos->flags &= ~SWP_NOCLIENTMOVE;
+ return wvrFlags;
+}
+
+/***********************************************************************
* SetWindowPos (USER.2)
*/
BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
@@ -2324,15 +2346,14 @@
BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
INT x, INT y, INT cx, INT cy, WORD flags)
{
- WINDOWPOS winpos;
+ WINDOWPOS winpos;
WND * wndPtr,*wndTemp;
- RECT newWindowRect, newClientRect, oldWindowRect;
+ RECT newWindowRect, newClientRect;
+ RECT oldWindowRect, oldClientRect;
HRGN visRgn = 0;
- HWND tempInsertAfter= 0;
- int result = 0;
- UINT uFlags = 0;
- BOOL resync = FALSE,retvalue;
- HWND hwndActive = 0;
+ UINT wvrFlags = 0, uFlags = 0;
+ BOOL retvalue, resync = FALSE;
+ HWND hwndActive = 0;
/* Get current active window from the active queue */
if ( hActiveQueue )
@@ -2345,58 +2366,60 @@
}
}
- TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
+ TRACE(win,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
hwnd, x, y, x+cx, y+cy, flags);
+
+ /* ------------------------------------------------------------------------ CHECKS */
+
/* Check window handle */
if (hwnd == GetDesktopWindow()) return FALSE;
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+ TRACE(win,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
+ wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
+
+ /* Fix redundant flags */
+
if(wndPtr->dwStyle & WS_VISIBLE)
flags &= ~SWP_SHOWWINDOW;
else
{
- uFlags |= SMC_NOPARENTERASE;
+ if (!(flags & SWP_SHOWWINDOW))
+ flags |= SWP_NOREDRAW;
flags &= ~SWP_HIDEWINDOW;
- if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
}
-/* Check for windows that may not be resized
- FIXME: this should be done only for Windows 3.0 programs
- if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
- flags |= SWP_NOSIZE | SWP_NOMOVE;
-*/
- /* Check dimensions */
+ if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
- if (cx <= 0) cx = 1;
- if (cy <= 0) cy = 1;
-
- /* Check flags */
-
- if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
(wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
flags |= SWP_NOSIZE; /* Already the right size */
+
if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
flags |= SWP_NOMOVE; /* Already the right position */
+ if (hwnd == hwndActive)
+ flags |= SWP_NOACTIVATE; /* Already active */
+ else
+ {
+ if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
+ {
+ flags &= ~SWP_NOZORDER;
+ hwndInsertAfter = HWND_TOP;
+ goto Pos;
+ }
+ }
+
/* Check hwndInsertAfter */
- if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
- {
- /* Ignore TOPMOST flags when activating a window */
- /* _and_ moving it in Z order. */
- if ((hwndInsertAfter == HWND_TOPMOST) ||
- (hwndInsertAfter == HWND_NOTOPMOST))
- hwndInsertAfter = HWND_TOP;
- }
- /* TOPMOST not supported yet */
+ /* FIXME: TOPMOST not supported yet */
if ((hwndInsertAfter == HWND_TOPMOST) ||
(hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
/* hwndInsertAfter must be a sibling of the window */
if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
- {
+ {
WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
if( wnd ) {
@@ -2409,16 +2432,10 @@
if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
}
WIN_ReleaseWndPtr(wnd);
- }
- else if (!X11DRV_WND_GetXWindow(wndPtr))
- {
- /* FIXME: the following optimization is no good for "X-ed" windows */
- if (hwndInsertAfter == HWND_TOP)
- flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
- else /* HWND_BOTTOM */
- flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
}
+Pos: /* ------------------------------------------------------------------------ MAIN part */
+
/* Fill the WINDOWPOS structure */
winpos.hwnd = hwnd;
@@ -2429,90 +2446,49 @@
winpos.cy = cy;
winpos.flags = flags;
- /* Send WM_WINDOWPOSCHANGING message */
+ SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
- if (!(winpos.flags & SWP_NOSENDCHANGING))
- SendMessageA( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
-
- /* Calculate new position and size */
-
- newWindowRect = wndPtr->rectWindow;
- newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
- : wndPtr->rectClient;
-
- if (!(winpos.flags & SWP_NOSIZE))
+ if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
{
- newWindowRect.right = newWindowRect.left + winpos.cx;
- newWindowRect.bottom = newWindowRect.top + winpos.cy;
- }
- if (!(winpos.flags & SWP_NOMOVE))
- {
- newWindowRect.left = winpos.x;
- newWindowRect.top = winpos.y;
- newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
- newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
-
- OffsetRect( &newClientRect, winpos.x - wndPtr->rectWindow.left,
- winpos.y - wndPtr->rectWindow.top );
- }
-
- winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
-
- /* Reposition window in Z order */
-
- if (!(winpos.flags & SWP_NOZORDER))
- {
- /* reorder owned popups if hwnd is top-level window
- */
if( wndPtr->parent == WIN_GetDesktop() )
- {
- hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
- wndPtr, winpos.flags );
- }
- WIN_ReleaseDesktop();
-
- if (X11DRV_WND_GetXWindow(wndPtr))
-
- {
- WIN_UnlinkWindow( winpos.hwnd );
- WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
- }
- else
- WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
+ hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
+ hwndInsertAfter, winpos.flags );
+ WIN_ReleaseDesktop();
}
- if ( !X11DRV_WND_GetXWindow(wndPtr) && !(winpos.flags & SWP_NOREDRAW) &&
- ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED))
- != (SWP_NOMOVE | SWP_NOSIZE)) )
- visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
-
- /* Send WM_NCCALCSIZE message to get new client area */
- if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
+ if(!(wndPtr->flags & WIN_NATIVE) )
{
- result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
- &wndPtr->rectWindow, &wndPtr->rectClient,
- &winpos, &newClientRect );
+ if( hwndInsertAfter == HWND_TOP )
+ winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
+ else
+ if( hwndInsertAfter == HWND_BOTTOM )
+ winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
+ else
+ if( !(winpos.flags & SWP_NOZORDER) )
+ if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
+ winpos.flags |= SWP_NOZORDER;
- /* FIXME: WVR_ALIGNxxx */
+ if( !(winpos.flags & SWP_NOREDRAW) &&
+ ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
+ != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
+ {
+ /* get a previous visible region for SWP_CopyValidBits() */
- if( newClientRect.left != wndPtr->rectClient.left ||
- newClientRect.top != wndPtr->rectClient.top )
- winpos.flags &= ~SWP_NOCLIENTMOVE;
-
- if( (newClientRect.right - newClientRect.left !=
- wndPtr->rectClient.right - wndPtr->rectClient.left) ||
- (newClientRect.bottom - newClientRect.top !=
- wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
- winpos.flags &= ~SWP_NOCLIENTSIZE;
+ visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
+ }
}
- else
- if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
- newClientRect.top != wndPtr->rectClient.top) )
- winpos.flags &= ~SWP_NOCLIENTMOVE;
- /* Update active DCEs
- * TODO: Optimize conditions that trigger DCE update.
- */
+ /* Common operations */
+
+ SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
+
+ if(!(winpos.flags & SWP_NOZORDER))
+ {
+ WIN_UnlinkWindow( winpos.hwnd );
+ WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
+ }
+
+ /* Reset active DCEs */
if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
wndPtr->dwStyle & WS_VISIBLE) ||
@@ -2524,199 +2500,209 @@
DCE_InvalidateDCE(wndPtr, &rect);
}
- /* change geometry */
-
oldWindowRect = wndPtr->rectWindow;
+ oldClientRect = wndPtr->rectClient;
- if (X11DRV_WND_GetXWindow(wndPtr))
+ if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
{
- RECT oldClientRect = wndPtr->rectClient;
-
- tempInsertAfter = winpos.hwndInsertAfter;
+ BOOL bCallDriver = TRUE;
+ HWND tempInsertAfter = winpos.hwndInsertAfter;
winpos.hwndInsertAfter = hwndInsertAfter;
- /* postpone geometry change */
-
- if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
- {
- wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
- winpos.hwndInsertAfter = tempInsertAfter;
- }
- else uFlags |= SMC_SETXPOS;
-
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
- if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
+ 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) ||
- (winpos.flags & SWP_NOCOPYBITS) )
+ /* This is the only place where we need to force repainting of the contents
+ of windows created by the host window system, all other cases go through the
+ expose event handling */
+
+ if( (winpos.flags & SWP_FRAMECHANGED) )
+ {
+ INT x, y;
+
+ 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( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
+ (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) )
+ SWP_DoSimpleFrameChanged(wndPtr, &newClientRect, &oldClientRect );
+ 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, SWP_EX_PAINTSELF);
+ }
+ }
+ }
+ }
+
+ if( bCallDriver )
+ {
+ if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
{
- /* if the client area moved as a result of WM_NCCALCSIZE returning
- * obscure WVR_ALIGNxxx flags then we simply redraw the whole thing
- *
- * TODO: use WINPOS_SizeMoveClean() if there is no SWP_NOCOPYBITS
- */
+ if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
+ (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) )
+ {
+ if( !(wndPtr->flags & WIN_MANAGED) ) /* force outer frame redraw */
+ {
+ HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
+ newWindowRect.bottom - newWindowRect.top);
+ RECT rcn = newClientRect;
+ RECT rco = oldClientRect;
- PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
- RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
+ 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
- if( winpos.flags & SWP_FRAMECHANGED )
- {
- WORD wErase = 0;
- RECT rect;
+ wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
+ winpos.hwndInsertAfter = tempInsertAfter;
+ }
- if( newClientRect.right > oldClientRect.right ) /* redraw exposed client area on the right */
- {
- rect.top = 0; rect.bottom = newClientRect.bottom - newClientRect.top;
- rect.left = oldClientRect.right - newClientRect.left;
- rect.right = newClientRect.right - newClientRect.left;
- wErase = 1;
- PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
- RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
+ if( winpos.flags & SWP_SHOWWINDOW )
+ {
+ HWND focus, curr;
+
+ wndPtr->dwStyle |= WS_VISIBLE;
+
+ if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
+
+ /* focus was set to unmapped window, reset host focus
+ * since the window is now visible */
+
+ focus = curr = GetFocus();
+ while (curr)
+ {
+ if (curr == hwnd)
+ {
+ WND *pFocus = WIN_FindWndPtr( focus );
+ if (pFocus)
+ pFocus->pDriver->pSetFocus(pFocus);
+ WIN_ReleaseWndPtr(pFocus);
+ break;
+ }
+ curr = GetParent(curr);
}
- if( newClientRect.bottom > oldClientRect.bottom ) /* redraw exposed client area on the bottom */
- {
- rect.left = 0; rect.right = ((wErase)?oldClientRect.right:newClientRect.right) - newClientRect.left;
- rect.top = oldClientRect.bottom - newClientRect.top;
- rect.bottom = newClientRect.bottom - newClientRect.top;
- wErase = 1;
- PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
- RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
- }
- if( !wErase ) /* just update the nonclient area */
- // the previous command (wndPtr->flags |= WIN_NEEDS_NCPAINT)
- // was not enough. Absolutly need a non client update at this point
- // Cannot wait for the next WM_PAINT message, particularly in the menu-bar redrawing
- WIN_UpdateNCArea(wndPtr,TRUE);
- }
}
- uFlags |= SMC_NOPARENTERASE; /* X windows do not have eraseable parents */
}
- else /* not an X window */
+ else /* -------------------------------------------- emulated window */
{
- RECT oldClientRect = wndPtr->rectClient;
-
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
if( oldClientRect.bottom - oldClientRect.top ==
- newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
+ newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
if( oldClientRect.right - oldClientRect.left ==
- newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
+ newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
- if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
- {
- uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
- (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
- uFlags |= (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
-
- if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
- uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect,
- &oldClientRect, uFlags);
- else
- {
- /* adjust the frame and do not erase the parent */
-
- if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
- if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
- }
- }
- DeleteObject(visRgn);
- }
-
- if (flags & SWP_SHOWWINDOW)
- {
- wndPtr->dwStyle |= WS_VISIBLE;
- if (X11DRV_WND_GetXWindow(wndPtr))
- {
- HWND focus, curr;
-
- wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
- if( uFlags & SMC_SETXPOS )
+ if( winpos.flags & SWP_SHOWWINDOW )
{
- winpos.hwndInsertAfter = tempInsertAfter;
+ wndPtr->dwStyle |= WS_VISIBLE;
+ uFlags |= SWP_EX_PAINTSELF;
+ visRgn = 1;
}
-
- if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
-
- /* If focus was set to an unmapped window, reset X focus now */
- focus = curr = GetFocus();
- while (curr) {
- if (curr == hwnd) {
- WND *pFocus = WIN_FindWndPtr( focus );
- if (pFocus)
- pFocus->pDriver->pSetFocus(pFocus);
- WIN_ReleaseWndPtr(pFocus);
- break;
+ else if( !(winpos.flags & SWP_NOREDRAW) )
+ {
+ if( winpos.flags & SWP_HIDEWINDOW )
+ {
+ if( visRgn > 1 ) /* map to parent */
+ OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
+ else
+ visRgn = 0;
}
- curr = GetParent(curr);
+ else
+ {
+ uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
+ (wvrFlags >= WVR_HREDRAW && wvrFlags < WVR_VALIDRECTS)) ? SWP_EX_NOCOPY : 0;
+
+ if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
+ uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
+ &oldClientRect, uFlags);
+ else
+ {
+ if( winpos.flags & SWP_FRAMECHANGED )
+ SWP_DoSimpleFrameChanged( wndPtr, &newClientRect, &oldClientRect );
+ if( visRgn )
+ {
+ DeleteObject( visRgn );
+ visRgn = 0;
+ }
+ }
+ }
}
- }
- else
- {
- if (!(flags & SWP_NOREDRAW))
- PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
- RDW_INVALIDATE | RDW_ALLCHILDREN |
- RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
- }
}
- else if (flags & SWP_HIDEWINDOW)
+
+ if( winpos.flags & SWP_HIDEWINDOW )
{
- wndPtr->dwStyle &= ~WS_VISIBLE;
- if (X11DRV_WND_GetXWindow(wndPtr))
- {
- wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
- if( uFlags & SMC_SETXPOS )
- {
- winpos.hwndInsertAfter = tempInsertAfter;
- }
- }
- else
- {
- if (!(flags & SWP_NOREDRAW))
- PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
- 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
- RDW_ERASE | RDW_ERASENOW, 0 );
- uFlags |= SMC_NOPARENTERASE;
- }
+ wndPtr->dwStyle &= ~WS_VISIBLE;
if (hwnd == CARET_GetHwnd()) DestroyCaret();
- /* FIXME: This will cause the window to be activated irrespective
- * of whether it is owned by the same thread.
- * Should this behaviour be allowed in SetWindowPos?
- */
+ /* FIXME: This will cause the window to be activated irrespective
+ * of whether it is owned by the same thread. Has to be done
+ * asynchronously.
+ */
+
if (winpos.hwnd == hwndActive)
WINPOS_ActivateOtherWindow( wndPtr );
}
+ /* ------------------------------------------------------------------------ FINAL */
+
/* Activate the window */
if (!(flags & SWP_NOACTIVATE))
WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
- /* Repaint the window */
-
- if (X11DRV_WND_GetXWindow(wndPtr))
- EVENT_Synchronize(); /* Wait for all expose events */
+ if (wndPtr->flags & WIN_NATIVE)
+ EVENT_Synchronize(); /* Synchronize with the host window system */
if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
wndTemp = WIN_GetDesktop();
- if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
- PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
- else if( wndPtr->parent == wndTemp && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
+
+ /* repaint invalidated region (if any) */
+
+ if( visRgn )
{
- PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
+ if( !(winpos.flags & SWP_NOREDRAW) )
+ {
+ if( uFlags & SWP_EX_PAINTSELF )
+ {
+ PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
+ ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
+ RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
+ }
+ else
+ {
+ PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
+ ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
+ RDW_ALLCHILDREN, RDW_EX_USEHRGN );
+ }
+ }
+ if( visRgn != 1 )
+ DeleteObject( visRgn );
}
+
WIN_ReleaseDesktop();
/* And last, send the WM_WINDOWPOSCHANGED message */
diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c
index 0abcbb4..711bc22 100644
--- a/windows/x11drv/event.c
+++ b/windows/x11drv/event.c
@@ -520,8 +520,7 @@
/***********************************************************************
* EVENT_QueryZOrder
*
- * Try to synchronize internal z-order with the window manager's.
- * Probably a futile endeavor.
+ * Synchronize internal z-order with the window manager's.
*/
static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
{
@@ -540,19 +539,25 @@
static Window __get_common_ancestor( Window A, Window B,
Window** children, unsigned* total )
{
- /* find the real root window */
+ /* find the real root window */
- Window root, *childrenB;
- unsigned totalB;
+ Window root, *childrenB;
+ unsigned totalB;
- do
+ do
{
- if( *children ) TSXFree( *children );
TSXQueryTree( display, A, &root, &A, children, total );
TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
if( childrenB ) TSXFree( childrenB );
+ if( *children ) TSXFree( *children );
} while( A != B && A && B );
- return ( A && B ) ? A : 0 ;
+
+ if( A && B )
+ {
+ TSXQueryTree( display, A, &root, &B, children, total );
+ return A;
+ }
+ return 0 ;
}
static Window __get_top_decoration( Window w, Window ancestor )
@@ -573,7 +578,7 @@
static unsigned __td_lookup( Window w, Window* list, unsigned max )
{
unsigned i;
- for( i = 0; i < max; i++ ) if( list[i] == w ) break;
+ for( i = max - 1; i >= 0; i-- ) if( list[i] == w ) break;
return i;
}
@@ -591,32 +596,42 @@
X11DRV_WND_GetXWindow(pWnd),
&children, &total );
if( parent && children )
- {
+ {
+ /* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
+
w = __get_top_decoration( X11DRV_WND_GetXWindow(pWndCheck), parent );
- if( w != children[total - 1] )
- {
+
+ if( w != children[total-1] ) /* check if at the top */
+ {
+ /* X child at index 0 is at the bottom, at index total-1 is at the top */
check = __td_lookup( w, children, total );
best = total;
+
for( pWnd = pWndZ; pWnd; pWnd = pWnd->next )
- {
+ {
+ /* go through all windows in Wine z-order... */
+
if( pWnd != pWndCheck )
- {
+ {
if( !(pWnd->flags & WIN_MANAGED) ||
!(w = __get_top_decoration( X11DRV_WND_GetXWindow(pWnd), parent )) )
continue;
pos = __td_lookup( w, children, total );
if( pos < best && pos > check )
- {
+ {
+ /* find a nearest Wine window precedes
+ * pWndCheck in the real z-order... */
best = pos;
hwndInsertAfter = pWnd->hwndSelf;
- }
- if( check - best == 1 ) break;
- }
- }
- WIN_UnlinkWindow( pWndCheck->hwndSelf );
- WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
- }
- }
+ }
+ if( best - check == 1 ) break;
+ }
+ }
+ /* and link pWndCheck right behind it in the local z-order */
+ }
+ WIN_UnlinkWindow( pWndCheck->hwndSelf );
+ WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
+ }
if( children ) TSXFree( children );
return bRet;
}
@@ -867,14 +882,17 @@
*/
static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
{
- if (event->detail != NotifyPointer)
+ if (event->detail != NotifyPointer)
{
- HWND hwnd = pWnd->hwndSelf;
-
- if (hwnd == GetActiveWindow())
- WINPOS_ChangeActiveWindow( 0, FALSE );
- if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
- SetFocus( 0 );
+ HWND hwnd = pWnd->hwndSelf;
+
+ if (hwnd == GetActiveWindow())
+ {
+ SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
+ WINPOS_ChangeActiveWindow( 0, FALSE );
+ }
+ if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
+ SetFocus( 0 );
}
}
@@ -910,13 +928,13 @@
if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight,
&border, &depth )) return;
if (win == X11DRV_GetXRootWindow())
- {
+ {
*px = *py = 0;
return;
- }
+ }
for (;;)
- {
+ {
if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children))
return;
TSXFree( children );
@@ -926,7 +944,7 @@
&width, &height, &border, &depth )) return;
*px += xpos;
*py += ypos;
- }
+ }
}
@@ -940,7 +958,7 @@
{
WINDOWPOS winpos;
RECT newWindowRect, newClientRect;
- HRGN hrgnOldPos, hrgnNewPos;
+ RECT oldWindowRect, oldClientRect;
Window above = event->above;
int x, y;
unsigned int width, height;
@@ -953,6 +971,9 @@
*/
EVENT_GetGeometry( event->window, &x, &y, &width, &height );
+TRACE(win, "%04x adjusted to (%i,%i)-(%i,%i)\n", pWnd->hwndSelf,
+ x, y, x + width, y + height );
+
/* Fill WINDOWPOS struct */
winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER;
winpos.hwnd = pWnd->hwndSelf;
@@ -991,15 +1012,20 @@
if (!IsWindow( winpos.hwnd )) return;
- hrgnOldPos = CreateRectRgnIndirect( &pWnd->rectWindow );
- hrgnNewPos = CreateRectRgnIndirect( &newWindowRect );
- CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
- DeleteObject(hrgnOldPos);
- DeleteObject(hrgnNewPos);
-
+ oldWindowRect = pWnd->rectWindow;
+ oldClientRect = pWnd->rectClient;
+
/* Set new size and position */
pWnd->rectWindow = newWindowRect;
pWnd->rectClient = newClientRect;
+
+ /* FIXME: Copy valid bits */
+
+ if( oldClientRect.top - oldWindowRect.top != newClientRect.top - newWindowRect.top ||
+ oldClientRect.left - oldWindowRect.left != newClientRect.left - newWindowRect.left )
+ RedrawWindow( winpos.hwnd, 0, NULL, RDW_FRAME | RDW_ALLCHILDREN |
+ RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW );
+
SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
if (!IsWindow( winpos.hwnd )) return;
diff --git a/windows/x11drv/init.c b/windows/x11drv/init.c
index e7ac2db..ead5570 100644
--- a/windows/x11drv/init.c
+++ b/windows/x11drv/init.c
@@ -84,8 +84,9 @@
X11DRV_WND_SetFocus,
X11DRV_WND_PreSizeMove,
X11DRV_WND_PostSizeMove,
- X11DRV_WND_ScrollWindow,
+ X11DRV_WND_SurfaceCopy,
X11DRV_WND_SetDrawable,
+ X11DRV_WND_SetHostAttr,
X11DRV_WND_IsSelfClipping
};
diff --git a/windows/x11drv/wnd.c b/windows/x11drv/wnd.c
index a6485bd..fece839 100644
--- a/windows/x11drv/wnd.c
+++ b/windows/x11drv/wnd.c
@@ -170,7 +170,9 @@
if (!(cs->style & WS_CHILD) &&
(X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display)))
- {
+ {
+ Window wGroupLeader;
+ XWMHints* wm_hints;
XSetWindowAttributes win_attr;
if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
@@ -191,10 +193,15 @@
FocusChangeMask;
win_attr.override_redirect = TRUE;
}
+ wndPtr->flags |= WIN_NATIVE;
+
+ win_attr.bit_gravity = BGNorthWest;
win_attr.colormap = X11DRV_COLOR_GetColormap();
win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
win_attr.cursor = X11DRV_MOUSE_XCursor;
+
+ ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = BGNorthWest;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
TSXCreateWindow( display,
X11DRV_WND_GetXRootWindow(wndPtr),
@@ -203,9 +210,10 @@
InputOutput, CopyFromParent,
CWEventMask | CWOverrideRedirect |
CWColormap | CWCursor | CWSaveUnder |
- CWBackingStore, &win_attr );
+ CWBackingStore | CWBitGravity,
+ &win_attr );
- if(!X11DRV_WND_GetXWindow(wndPtr))
+ if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
return FALSE;
if (wndPtr->flags & WIN_MANAGED) {
@@ -233,14 +241,36 @@
}
if (cs->hwndParent) /* Get window owner */
- {
+ {
+ Window w;
WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
- Window win = X11DRV_WND_FindXWindow( tmpWnd );
- if (win) TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), win );
+
+ w = X11DRV_WND_FindXWindow( tmpWnd );
+ if (w != None)
+ {
+ TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
+ wGroupLeader = w;
+ }
WIN_ReleaseWndPtr(tmpWnd);
- }
+ }
+
+ wm_hints = TSXAllocWMHints();
+ {
+ wm_hints->flags = InputHint | StateHint | WindowGroupHint;
+ wm_hints->input = True;
+ if( wndPtr->dwStyle & WS_VISIBLE )
+ wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE &&
+ wndPtr->flags & WIN_MANAGED ) ?
+ IconicState : NormalState;
+ else
+ wm_hints->initial_state = WithdrawnState;
+ wm_hints->window_group = wGroupLeader;
+
+ TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
+ TSXFree(wm_hints);
+ }
X11DRV_WND_RegisterWindow( wndPtr );
- }
+ }
return TRUE;
}
@@ -400,26 +430,26 @@
*
* SetWindowPos() for an X window. Used by the real SetWindowPos().
*/
-void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bSMC_SETXPOS)
+void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
{
- XWindowChanges winChanges;
- int changeMask = 0;
- WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
+ XWindowChanges winChanges;
+ int changeMask = 0;
+ WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
- if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happend!!! */
+ if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happend!!! */
- if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
+ if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
{
if(X11DRV_WND_GetXWindow(wndPtr))
TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
}
- if(bSMC_SETXPOS)
+ if(bChangePos)
{
if ( !(winpos->flags & SWP_NOSIZE))
{
- winChanges.width = winpos->cx;
- winChanges.height = winpos->cy;
+ winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
+ winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
changeMask |= CWWidth | CWHeight;
/* Tweak dialog window size hints */
@@ -477,11 +507,11 @@
}
}
- if ( winpos->flags & SWP_SHOWWINDOW )
+ if ( winpos->flags & SWP_SHOWWINDOW )
{
if(X11DRV_WND_GetXWindow(wndPtr)) TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
}
- WIN_ReleaseWndPtr(winposPtr);
+ WIN_ReleaseWndPtr(winposPtr);
}
/*****************************************************************
@@ -555,31 +585,32 @@
}
/*****************************************************************
- * X11DRV_WND_ScrollWindow
+ * X11DRV_WND_SurfaceCopy
+ *
+ * Copies rect to (rect.left + dx, rect.top + dy).
*/
-void X11DRV_WND_ScrollWindow(
- WND *wndPtr, DC *dcPtr, INT dx, INT dy,
- const RECT *rect, BOOL bUpdate)
+void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy,
+ const RECT *rect, BOOL bUpdate)
{
- X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
- POINT dst, src;
+ X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
+ POINT dst, src;
- dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
- dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
+ dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
+ dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
- if (bUpdate) /* handles non-Wine windows hanging over the scrolled area */
- TSXSetGraphicsExposures( display, physDev->gc, True );
- TSXSetFunction( display, physDev->gc, GXcopy );
- TSXCopyArea( display, physDev->drawable, physDev->drawable,
- physDev->gc, src.x, src.y,
- rect->right - rect->left,
- rect->bottom - rect->top,
- dst.x, dst.y );
- if (bUpdate)
- TSXSetGraphicsExposures( display, physDev->gc, False );
+ if (bUpdate) /* handles non-Wine windows hanging over the copied area */
+ TSXSetGraphicsExposures( display, physDev->gc, True );
+ TSXSetFunction( display, physDev->gc, GXcopy );
+ TSXCopyArea( display, physDev->drawable, physDev->drawable,
+ physDev->gc, src.x, src.y,
+ rect->right - rect->left,
+ rect->bottom - rect->top,
+ dst.x, dst.y );
+ if (bUpdate)
+ TSXSetGraphicsExposures( display, physDev->gc, False );
- if (bUpdate) /* Make sure exposure events have been processed */
- EVENT_Synchronize();
+ if (bUpdate) /* Make sure exposure events have been processed */
+ EVENT_Synchronize();
}
/***********************************************************************
@@ -634,6 +665,50 @@
}
/***********************************************************************
+ * X11DRV_WND_SetHostAttr
+ */
+BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
+{
+ Window w;
+
+ if( (w = X11DRV_WND_GetXWindow(wnd)) )
+ {
+ XSetWindowAttributes win_attr;
+
+ switch( ha )
+ {
+ case HAK_BITGRAVITY:
+
+ if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
+ {
+ win_attr.bit_gravity = value;
+ ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
+ TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
+ }
+ return TRUE;
+
+ case HAK_ACCEPTFOCUS:
+
+ if( (wnd->flags & WIN_MANAGED) )
+ {
+ XWMHints* wm_hints = TSXAllocWMHints();
+
+ if( wm_hints )
+ {
+ wm_hints->flags = InputHint;
+ wm_hints->input = value;
+ TSXSetWMHints( display, X11DRV_WND_GetXWindow(wnd), wm_hints );
+ TSXFree( wm_hints );
+ return TRUE;
+ }
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+
+/***********************************************************************
* X11DRV_WND_IsSelfClipping
*/
BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)