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.
This commit is contained in:
Alex Korobka 1999-03-28 09:37:57 +00:00 committed by Alexandre Julliard
parent 073e3bc9e5
commit 4f1ac05dea
23 changed files with 1340 additions and 837 deletions

View File

@ -3791,6 +3791,10 @@ BOOL WINAPI DrawMenuBar( HWND hWnd )
*/
void WINAPI EndMenu(void)
{
/*
* FIXME: NOT ENOUGH! This has to cancel menu tracking right away.
*/
fEndMenu = TRUE;
}

View File

@ -378,6 +378,7 @@ typedef struct _ScanLineListBlock {
extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj );
extern BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect );
extern HRGN REGION_CropRgn( HRGN hDst, HRGN hSrc, const RECT *lpRect, const POINT *lpPt );
extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y );
extern BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc );

View File

@ -16,6 +16,7 @@
#include "windef.h"
#ifdef HAVE_LIBXXF86VM
#define XMD_H
#define INT32 INT
#include <X11/Xlib.h>
#include <X11/extensions/xf86vmode.h>

View File

@ -38,6 +38,7 @@ extern Region TSXPolygonRegion(XPoint*, int, int);
extern int TSXRectInRegion(Region, int, int, unsigned int, unsigned int);
extern int TSXSaveContext(Display*, XID, XContext, const char*);
extern int TSXSetClassHint(Display*, Window, XClassHint*);
extern int TSXSetWMHints(Display*, Window, XWMHints*);
extern void TSXSetWMProperties(Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
extern void TSXSetWMSizeHints(Display*, Window, XSizeHints*, Atom);
extern int TSXSetRegion(Display*, GC, Region);

View File

@ -121,6 +121,7 @@ extern void TTYDRV_WND_PreSizeMove(struct tagWND *wndPtr);
extern void TTYDRV_WND_PostSizeMove(struct tagWND *wndPtr);
extern void TTYDRV_WND_ScrollWindow(struct tagWND *wndPtr, struct tagDC *dcPtr, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
extern void TTYDRV_WND_SetDrawable(struct tagWND *wndPtr, struct tagDC *dc, WORD flags, BOOL bSetClipOrigin);
extern BOOL TTYDRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value);
extern BOOL TTYDRV_WND_IsSelfClipping(struct tagWND *wndPtr);
#endif /* !defined(__WINE_TTYDRV_H) */

View File

@ -44,8 +44,10 @@ typedef enum
} BUILTIN_CLASS32;
/* PAINT_RedrawWindow() control flags */
#define RDW_C_USEHRGN 0x0001
#define RDW_C_DELETEHRGN 0x0002
#define RDW_EX_USEHRGN 0x0001
#define RDW_EX_DELETEHRGN 0x0002
#define RDW_EX_XYWINDOW 0x0004
#define RDW_EX_TOPFRAME 0x0010
struct tagCLASS;
struct tagDCE;
@ -86,6 +88,25 @@ typedef struct tagWND
DWORD wExtra[1]; /* Window extra bytes */
} WND;
/* Host attributes */
#define HAK_BITGRAVITY 1
#define HAK_ACCEPTFOCUS 2
/* Bit Gravity */
#define BGForget 0
#define BGNorthWest 1
#define BGNorth 2
#define BGNorthEast 3
#define BGWest 4
#define BGCenter 5
#define BGEast 6
#define BGSouthWest 7
#define BGSouth 8
#define BGSouthEast 9
#define BGStatic 10
typedef struct _WND_DRIVER
{
void (*pInitialize)(WND *);
@ -100,8 +121,9 @@ typedef struct _WND_DRIVER
void (*pSetFocus)(WND *);
void (*pPreSizeMove)(WND *);
void (*pPostSizeMove)(WND *);
void (*pScrollWindow)(WND *, struct tagDC *, INT, INT, const RECT *, BOOL);
void (*pSurfaceCopy)(WND *, struct tagDC *, INT, INT, const RECT *, BOOL);
void (*pSetDrawable)(WND *, struct tagDC *, WORD, BOOL);
BOOL (*pSetHostAttr)(WND *, INT haKey, INT value);
BOOL (*pIsSelfClipping)(WND *);
} WND_DRIVER;
@ -119,13 +141,12 @@ typedef struct
#define WIN_NEEDS_NCPAINT 0x0004 /* WM_NCPAINT must be sent to window */
#define WIN_RESTORE_MAX 0x0008 /* Maximize when restoring */
#define WIN_INTERNAL_PAINT 0x0010 /* Internal WM_PAINT message pending */
/* Used to have WIN_NO_REDRAW 0x0020 here */
#define WIN_NATIVE 0x0020 /* Directly mapped to the window provided by the driver */
#define WIN_NEED_SIZE 0x0040 /* Internal WM_SIZE is needed */
#define WIN_NCACTIVATED 0x0080 /* last WM_NCACTIVATE was positive */
#define WIN_MANAGED 0x0100 /* Window managed by the X wm */
#define WIN_MANAGED 0x0100 /* Window managed by the window system */
#define WIN_ISDIALOG 0x0200 /* Window is a dialog */
#define WIN_ISWIN32 0x0400 /* Understands Win32 messages */
#define WIN_SAVEUNDER_OVERRIDE 0x0800
/* BuildWinArray() flags */
#define BWA_SKIPDISABLED 0x0001
@ -170,7 +191,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 void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate);
extern HRGN WIN_UpdateNCRgn(WND* wnd, BOOL bUpdate, BOOL bForce); /* windows/painting.c */
/* controls/widgets.c */

View File

@ -328,6 +328,7 @@ extern struct _WND_DRIVER X11DRV_WND_Driver;
typedef struct _X11DRV_WND_DATA {
Window window;
int bit_gravity;
} X11DRV_WND_DATA;
extern Window X11DRV_WND_GetXWindow(struct tagWND *wndPtr);
@ -347,8 +348,9 @@ extern void X11DRV_WND_SetText(struct tagWND *wndPtr, LPCSTR text);
extern void X11DRV_WND_SetFocus(struct tagWND *wndPtr);
extern void X11DRV_WND_PreSizeMove(struct tagWND *wndPtr);
extern void X11DRV_WND_PostSizeMove(struct tagWND *wndPtr);
extern void X11DRV_WND_ScrollWindow(struct tagWND *wndPtr, struct tagDC *dcPtr, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
extern void X11DRV_WND_SurfaceCopy(struct tagWND *wndPtr, struct tagDC *dcPtr, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
extern void X11DRV_WND_SetDrawable(struct tagWND *wndPtr, struct tagDC *dc, WORD flags, BOOL bSetClipOrigin);
extern BOOL X11DRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value);
extern BOOL X11DRV_WND_IsSelfClipping(struct tagWND *wndPtr);
#endif /* __WINE_X11DRV_H */

View File

@ -4,6 +4,7 @@
*
* Copyright 1993, 1994, 1995 Alexandre Julliard
* Modifications and additions: Copyright 1998 Huw Davies
* 1999 Alex Korobka
*
*/
@ -99,6 +100,7 @@ static void REGION_SubtractRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2)
static void REGION_XorRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn);
#define RGN_DEFAULT_RECTS 2
/***********************************************************************
* REGION_DumpRegion
@ -117,19 +119,20 @@ static void REGION_DumpRegion(WINEREGION *pReg)
return;
}
/***********************************************************************
* REGION_AllocWineRegion
* Create a new empty WINEREGION.
*/
static WINEREGION *REGION_AllocWineRegion( void )
static WINEREGION *REGION_AllocWineRegion( INT n )
{
WINEREGION *pReg;
if ((pReg = HeapAlloc(SystemHeap, 0, sizeof( WINEREGION ))))
{
if ((pReg->rects = HeapAlloc(SystemHeap, 0, sizeof( RECT ))))
if ((pReg->rects = HeapAlloc(SystemHeap, 0, n * sizeof( RECT ))))
{
pReg->size = 1;
pReg->size = n;
EMPTY_REGION(pReg);
return pReg;
}
@ -138,11 +141,12 @@ static WINEREGION *REGION_AllocWineRegion( void )
return NULL;
}
/***********************************************************************
* REGION_CreateRegion
* Create a new empty region.
*/
static HRGN REGION_CreateRegion(void)
static HRGN REGION_CreateRegion( INT n )
{
HRGN hrgn;
RGNOBJ *obj;
@ -150,7 +154,7 @@ static HRGN REGION_CreateRegion(void)
if(!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
return 0;
obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
if(!(obj->rgn = REGION_AllocWineRegion())) {
if(!(obj->rgn = REGION_AllocWineRegion(n))) {
GDI_FreeObject( hrgn );
return 0;
}
@ -158,6 +162,7 @@ static HRGN REGION_CreateRegion(void)
return hrgn;
}
/***********************************************************************
* REGION_DestroyWineRegion
*/
@ -194,14 +199,14 @@ INT WINAPI OffsetRgn( HRGN hrgn, INT x, INT y )
{
RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
if (obj)
if (obj && (x || y))
{
INT ret;
int nbox = obj->rgn->numRects;
RECT *pbox = obj->rgn->rects;
TRACE(region, " %04x %d,%d\n", hrgn, x, y );
if(nbox && (x || y)) {
if(nbox) {
while(nbox--) {
pbox->left += x;
pbox->right += x;
@ -264,7 +269,7 @@ HRGN16 WINAPI CreateRectRgn16(INT16 left, INT16 top, INT16 right, INT16 bottom)
{
HRGN16 hrgn;
if (!(hrgn = (HRGN16)REGION_CreateRegion()))
if (!(hrgn = (HRGN16)REGION_CreateRegion(RGN_DEFAULT_RECTS)))
return 0;
TRACE(region, "\n");
SetRectRgn16(hrgn, left, top, right, bottom);
@ -279,7 +284,9 @@ HRGN WINAPI CreateRectRgn(INT left, INT top, INT right, INT bottom)
{
HRGN hrgn;
if (!(hrgn = REGION_CreateRegion()))
/* Allocate 2 rects by default to reduce the number of reallocs */
if (!(hrgn = REGION_CreateRegion(RGN_DEFAULT_RECTS)))
return 0;
TRACE(region, "\n");
SetRectRgn(hrgn, left, top, right, bottom);
@ -399,7 +406,8 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
/* Create region */
if (!(hrgn = REGION_CreateRegion())) return 0;
d = (ellipse_height < 128) ? ((3 * ellipse_height) >> 2) : 64;
if (!(hrgn = REGION_CreateRegion(d))) return 0;
obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
TRACE(region,"(%d,%d-%d,%d %dx%d): ret=%04x\n",
left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
@ -574,34 +582,38 @@ DWORD WINAPI GetRegionData16(HRGN16 hrgn, DWORD count, LPRGNDATA rgndata)
*/
HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA* rgndata)
{
HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
HRGN hrgn;
TRACE(region, " %p %ld %p = ", lpXform, dwCount, rgndata );
if( lpXform )
WARN(region, "(Xform not implemented - ignored) ");
if( rgndata->rdh.iType != RDH_RECTANGLES )
{
/* FIXME: We can use CreatePolyPolygonRgn() here
* for trapezoidal data */
WARN(region, "(Unsupported region data) ");
goto fail;
}
if( (hrgn = REGION_CreateRegion( rgndata->rdh.nCount )) )
{
RECT *pCurRect, *pEndRect;
TRACE(region, " %p %ld %p. Returning %04x\n",
lpXform, dwCount, rgndata, hrgn);
if(!hrgn)
{
WARN(region, "Can't create a region!\n");
return 0;
}
if(lpXform)
WARN(region, "Xform not implemented - ignoring\n");
if(rgndata->rdh.iType != RDH_RECTANGLES)
{
WARN(region, "Type not RDH_RECTANGLES\n");
GDI_HEAP_UNLOCK( hrgn );
DeleteObject( hrgn );
return 0;
}
RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
REGION_UnionRectWithRegion( pCurRect, obj->rgn );
GDI_HEAP_UNLOCK( hrgn );
TRACE(region,"%04x\n", hrgn );
return hrgn;
}
fail:
WARN(region, "Failed\n");
return 0;
}
/***********************************************************************
@ -1402,7 +1414,7 @@ static void REGION_RegionOp(
* Only do this stuff if the number of rectangles allocated is more than
* twice the number of rectangles in the region (a simple optimization...).
*/
if (newReg->numRects < (newReg->size >> 1))
if ((newReg->numRects < (newReg->size >> 1)) && (newReg->numRects > 2))
{
if (REGION_NOT_EMPTY(newReg))
{
@ -1916,8 +1928,8 @@ static void REGION_XorRegion(WINEREGION *dr, WINEREGION *sra,
{
WINEREGION *tra, *trb;
if ((! (tra = REGION_AllocWineRegion())) ||
(! (trb = REGION_AllocWineRegion())))
if ((! (tra = REGION_AllocWineRegion(sra->numRects + 1))) ||
(! (trb = REGION_AllocWineRegion(srb->numRects + 1))))
return;
REGION_SubtractRegion(tra,sra,srb);
REGION_SubtractRegion(trb,srb,sra);
@ -2357,7 +2369,7 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
int numFullPtBlocks = 0;
INT poly, total;
if(!(hrgn = REGION_CreateRegion()))
if(!(hrgn = REGION_CreateRegion(nbpolygons)))
return 0;
obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
region = obj->rgn;
@ -2568,3 +2580,205 @@ HRGN WINAPI GetRandomRgn(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3)
return 0;
}
/***********************************************************************
* REGION_CropAndOffsetRegion
*/
static BOOL REGION_CropAndOffsetRegion(const POINT* off, const RECT *rect, WINEREGION *rgnSrc, WINEREGION* rgnDst)
{
if( IsRectEmpty(rect) || !EXTENTCHECK(rect, &rgnSrc->extents) )
{
empty:
if( !rgnDst->rects )
{
rgnDst->rects = HeapAlloc(SystemHeap, 0, sizeof( RECT ));
if( rgnDst->rects )
rgnDst->size = 1;
else
return FALSE;
}
TRACE(region,"cropped to empty!\n");
EMPTY_REGION(rgnDst);
}
else /* region box and clipping rect appear to intersect */
{
RECT *lpr;
INT i, j, clipa, clipb;
INT left = rgnSrc->extents.right + off->x;
INT right = rgnSrc->extents.left + off->x;
for( clipa = 0; rgnSrc->rects[clipa].bottom <= rect->top; clipa++ )
; /* skip bands above the clipping rectangle */
for( clipb = clipa; clipb < rgnSrc->numRects; clipb++ )
if( rgnSrc->rects[clipb].top >= rect->bottom )
break; /* and below it */
/* clipa - index of the first rect in the first intersecting band
* clipb - index of the last rect in the last intersecting band
*/
if((rgnDst != rgnSrc) && (rgnDst->size < (i = (clipb - clipa))))
{
rgnDst->rects = HeapReAlloc( SystemHeap, 0,
rgnDst->rects, i * sizeof(RECT));
if( !rgnDst->rects ) return FALSE;
rgnDst->size = i;
}
if( TRACE_ON(region) )
{
REGION_DumpRegion( rgnSrc );
TRACE(region,"\tclipa = %i, clipb = %i\n", clipa, clipb );
}
for( i = clipa, j = 0; i < clipb ; i++ )
{
/* i - src index, j - dst index, j is always <= i for obvious reasons */
lpr = rgnSrc->rects + i;
if( lpr->left < rect->right && lpr->right > rect->left )
{
rgnDst->rects[j].top = lpr->top + off->y;
rgnDst->rects[j].bottom = lpr->bottom + off->y;
rgnDst->rects[j].left = ((lpr->left > rect->left) ? lpr->left : rect->left) + off->x;
rgnDst->rects[j].right = ((lpr->right < rect->right) ? lpr->right : rect->right) + off->x;
if( rgnDst->rects[j].left < left ) left = rgnDst->rects[j].left;
if( rgnDst->rects[j].right > right ) right = rgnDst->rects[j].right;
j++;
}
}
if( j == 0 ) goto empty;
rgnDst->extents.left = left;
rgnDst->extents.right = right;
left = rect->top + off->y;
right = rect->bottom + off->y;
rgnDst->numRects = j--;
for( i = 0; i <= j; i++ ) /* fixup top band */
if( rgnDst->rects[i].top < left )
rgnDst->rects[i].top = left;
else
break;
for( i = j; i >= 0; i-- ) /* fixup bottom band */
if( rgnDst->rects[i].bottom > right )
rgnDst->rects[i].bottom = right;
else
break;
rgnDst->extents.top = rgnDst->rects[0].top;
rgnDst->extents.bottom = rgnDst->rects[j].bottom;
rgnDst->type = (j >= 1) ? COMPLEXREGION : SIMPLEREGION;
if( TRACE_ON(region) )
{
TRACE(region,"result:\n");
REGION_DumpRegion( rgnDst );
}
}
return TRUE;
}
/***********************************************************************
* REGION_CropRgn
*
*
* hSrc: Region to crop and offset.
* lpRect: Clipping rectangle.
* lpPt: Points to offset the cropped region. Can be NULL.
*
* 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).
*
* Returns: hDst if success, 0 otherwise.
*/
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 );
if( hDst == 0 ) hDst = h;
CombineRgn( hDst, hSrc, h, RGN_AND );
if( lpPt )
OffsetRgn( hDst, lpPt->x, lpPt->y );
if( hDst != h )
DeleteObject( h );
return hDst;
*/
RGNOBJ *objSrc = (RGNOBJ *) GDI_HEAP_LOCK( hSrc );
if(objSrc)
{
RGNOBJ *objDst;
WINEREGION *rgnDst;
if( hDst )
{
objDst = (RGNOBJ *) GDI_HEAP_LOCK( hDst );
rgnDst = objDst->rgn;
}
else
{
rgnDst = HeapAlloc(SystemHeap, 0, sizeof( WINEREGION ));
if( rgnDst )
{
rgnDst->size = rgnDst->numRects = 0;
rgnDst->rects = NULL; /* back end will allocate exact number */
}
}
if( rgnDst )
{
POINT pt = { 0, 0 };
if( !lpPt ) lpPt = &pt;
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 );
if( REGION_CropAndOffsetRegion( lpPt, lpRect, objSrc->rgn, rgnDst ) == FALSE )
{
if( hDst ) /* existing rgn */
{
GDI_HEAP_UNLOCK(hDst);
hDst = 0;
goto done;
}
goto fail;
}
else if( hDst == 0 )
{
if(!(hDst = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
{
fail:
if( rgnDst->rects )
HeapFree( SystemHeap, 0, rgnDst->rects );
HeapFree( SystemHeap, 0, rgnDst );
goto done;
}
objDst = (RGNOBJ *) GDI_HEAP_LOCK( hDst );
objDst->rgn = rgnDst;
}
GDI_HEAP_UNLOCK(hDst);
}
else hDst = 0;
done:
GDI_HEAP_UNLOCK(hSrc);
return hDst;
}
return 0;
}

View File

@ -69,7 +69,7 @@ foreach $name (@dolist) {
if($name eq "xf86vmode") {
$x11_incl = "#include <X11/Xlib.h>\n";
$extensions_dir = "extensions/";
$pre_file = "#include \"wintypes.h\"\n#ifdef HAVE_LIBXXF86VM\n#define XMD_H\n";
$pre_file = "#include \"windef.h\"\n#ifdef HAVE_LIBXXF86VM\n#define XMD_H\n#define INT32 INT\n";
$post_file = "#endif /* defined(HAVE_LIBXXF86VM) */\n";
}

View File

@ -131,6 +131,7 @@ XSetSelectionOwner
XSetSubwindowMode
XSetTransientForHint
XSetWindowColormap
XSetWMHints
XSetWMProperties
XSetWMProtocols
XSetWMSizeHints

View File

@ -11,7 +11,8 @@
#include "windef.h"
#ifdef HAVE_LIBXXF86VM
#define XMD_H
typedef int INT32;
#define INT32 INT
#include <X11/Xlib.h>
#include <X11/extensions/xf86vmode.h>
#include "debug.h"

View File

@ -235,6 +235,17 @@ int TSXSetClassHint(Display* a0, Window a1, XClassHint* a2)
return r;
}
int TSXSetWMHints(Display* a0, Window a1, XWMHints* a2)
{
int r;
TRACE(x11, "Call XSetWMHints\n");
EnterCriticalSection( &X11DRV_CritSection );
r = XSetWMHints(a0, a1, a2);
LeaveCriticalSection( &X11DRV_CritSection );
TRACE(x11, "Ret XSetWMHints\n");
return r;
}
void TSXSetWMProperties(Display* a0, Window a1, XTextProperty* a2, XTextProperty* a3, char** a4, int a5, XSizeHints* a6, XWMHints* a7, XClassHint* a8)
{
TRACE(x11, "Call XSetWMProperties\n");

View File

@ -222,8 +222,9 @@ static INT DCE_ReleaseDC( DCE* dce )
* 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 @@ BOOL DCE_InvalidateDCE(WND* pWnd, const RECT* pRectUpdate)
{
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 @@ BOOL DCE_InvalidateDCE(WND* pWnd, const RECT* pRectUpdate)
}
}
WIN_ReleaseWndPtr(wndCurrent);
WIN_ReleaseDesktop();
}
} /* dce list */
}

View File

@ -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 @@ void NC_DoNCPaint( WND* wndPtr, HRGN clip, BOOL suppress_menupaint )
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 @@ void NC_DoNCPaint95(
BOOL suppress_menupaint )
{
HDC hdc;
RECT rect;
RECT rfuzz, rect, rectClip;
BOOL active;
HWND hwnd = wndPtr->hwndSelf;
@ -1676,7 +1678,15 @@ void NC_DoNCPaint95(
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 @@ void NC_DoNCPaint95(
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,6 +1734,7 @@ void NC_DoNCPaint95(
r.bottom = rect.top + sysMetrics[SM_CYCAPTION];
rect.top += sysMetrics[SM_CYCAPTION];
}
if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
wndPtr->dwExStyle, active);
}

View File

@ -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 )
{
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_NEEDS_NCPAINT;
if ((wnd->hwndSelf == GetActiveWindow()) &&
!(wnd->flags & WIN_NCACTIVATED))
!(wnd->flags & WIN_NCACTIVATED) )
{
wnd->flags |= WIN_NCACTIVATED;
if( hClip > 1) DeleteObject( hClip );
hClip = 1;
bForceEntire = TRUE;
}
if (hClip) SendMessage16( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
if( (wnd->flags & WIN_NEEDS_NCPAINT) && wnd->hrgnUpdate )
{
RECT r, r2, r3;
if (hClip > 1) DeleteObject( hClip );
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( hClip )
SendMessageA( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
return hClip;
}
@ -100,10 +123,10 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
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 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
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 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
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 @@ END:
* 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 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
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 */
{
int rgnNotEmpty = COMPLEXREGION;
/* r is the rectangle we crop the supplied update rgn/rect with */
if (wndPtr->hrgnUpdate > 1) /* Is there already an update region? */
GETCLIENTRECTW( wndPtr, r2 );
pt.x = r2.left; pt.y = r2.top;
if (flags & RDW_INVALIDATE) /* ------------------------- Invalidate */
{
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 */
BOOL bHasUpdateRgn = (BOOL)wndPtr->hrgnUpdate;
/* wndPtr->hrgnUpdate is in window coordinates, parameters are
* in client coordinates unless RDW_EX_XYWINDOW is set.
*/
if( hrgnUpdate )
{
if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
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 );
rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, hrgnUpdate,
0, RGN_COPY );
}
else wndPtr->hrgnUpdate = CreateRectRgnIndirect( rectUpdate ?
rectUpdate : &rectClient );
}
if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
/* 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 );
}
/* 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 );
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 )
{
/* Special case: validate everything */
DeleteObject( wndPtr->hrgnUpdate );
wndPtr->hrgnUpdate = 0;
if( hrgnUpdate )
{
hrgn = REGION_CropRgn( hrgn, hrgnUpdate, &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt );
GetRgnBox( hrgn, &r2 );
if( IsRectEmpty( &r2 ) )
goto END;
}
else
{
if ((hrgn = hrgnUpdate) == 0)
hrgn = CreateRectRgnIndirect( rectUpdate );
if (CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
hrgn, RGN_DIFF ) == NULLREGION)
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;
}
if (!hrgnUpdate) DeleteObject( hrgn );
}
if (!wndPtr->hrgnUpdate) /* No more update region */
if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
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 <= 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,14 +499,26 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
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,
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) );
@ -456,47 +545,40 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
((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 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
}
}
END:
if( hrgn2 > 1 && (hrgn2 != hrgnUpdate) )
DeleteObject( hrgn2 );
if( hrgn > 1 && (hrgn != hrgnUpdate) )
DeleteObject( hrgn );
WIN_ReleaseWndPtr(wndPtr);
return TRUE;
}
@ -680,9 +768,16 @@ BOOL WINAPI GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
}
}
}
else SetRectEmpty( rect );
else
if( wndPtr->hrgnUpdate == 1 )
{
GetClientRect( hwnd, rect );
if (erase) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_ERASENOW | RDW_NOCHILDREN );
}
retvalue = (wndPtr->hrgnUpdate > 1);
else
SetRectEmpty( rect );
}
retvalue = (wndPtr->hrgnUpdate >= 1);
END:
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
@ -699,7 +794,7 @@ INT16 WINAPI GetUpdateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
/***********************************************************************
* GetUpdateRgn32 (USER32.298)
* GetUpdateRgn (USER32.298)
*/
INT WINAPI GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
{
@ -707,13 +802,25 @@ INT WINAPI GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
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;
}
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 WINAPI ExcludeUpdateRgn( HDC hdc, HWND hwnd )
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 */

View File

@ -275,7 +275,7 @@ rc.left, rc.top, rc.right, rc.bottom, (UINT16)flags );
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 )
{

View File

@ -81,6 +81,7 @@ WND_DRIVER TTYDRV_WND_Driver =
TTYDRV_WND_PostSizeMove,
TTYDRV_WND_ScrollWindow,
TTYDRV_WND_SetDrawable,
TTYDRV_WND_SetHostAttr,
TTYDRV_WND_IsSelfClipping
};

View File

@ -116,6 +116,14 @@ void TTYDRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin
{
}
/***********************************************************************
* TTYDRV_WND_SetHostAttr
*/
BOOL TTYDRV_WND_SetHostAttr(WND *wndPtr, INT attr, INT value)
{
return FALSE;
}
/***********************************************************************
* TTYDRV_WND_IsSelfClipping
*/

View File

@ -1666,14 +1666,24 @@ BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
{
/* 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 */

File diff suppressed because it is too large Load Diff

View File

@ -520,8 +520,7 @@ static void EVENT_ProcessEvent( XEvent *event )
/***********************************************************************
* 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 )
{
@ -547,12 +546,18 @@ static Window __get_common_ancestor( Window A, Window B,
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 Window __get_top_decoration( Window w, Window ancestor )
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;
}
@ -592,13 +597,20 @@ static BOOL EVENT_QueryZOrder( WND* pWndCheck )
&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) ||
@ -607,16 +619,19 @@ static BOOL EVENT_QueryZOrder( WND* pWndCheck )
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;
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;
}
@ -872,7 +887,10 @@ static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
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 );
}
@ -940,7 +958,7 @@ static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
{
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 @@ static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
*/
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 @@ static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
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;

View File

@ -84,8 +84,9 @@ WND_DRIVER X11DRV_WND_Driver =
X11DRV_WND_SetFocus,
X11DRV_WND_PreSizeMove,
X11DRV_WND_PostSizeMove,
X11DRV_WND_ScrollWindow,
X11DRV_WND_SurfaceCopy,
X11DRV_WND_SetDrawable,
X11DRV_WND_SetHostAttr,
X11DRV_WND_IsSelfClipping
};

View File

@ -171,6 +171,8 @@ BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BO
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 @@ BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BO
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 @@ BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BO
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) {
@ -234,11 +242,33 @@ BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BO
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,7 +430,7 @@ static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
*
* 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;
@ -414,12 +444,12 @@ void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bSMC_SET
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 */
@ -555,10 +585,11 @@ void X11DRV_WND_PostSizeMove(WND *wndPtr)
}
/*****************************************************************
* 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,
void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy,
const RECT *rect, BOOL bUpdate)
{
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
@ -567,7 +598,7 @@ void X11DRV_WND_ScrollWindow(
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 */
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,
@ -633,6 +664,50 @@ void X11DRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin
}
}
/***********************************************************************
* 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
*/