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) void WINAPI EndMenu(void)
{ {
/*
* FIXME: NOT ENOUGH! This has to cancel menu tracking right away.
*/
fEndMenu = TRUE; fEndMenu = TRUE;
} }

View File

@ -378,6 +378,7 @@ typedef struct _ScanLineListBlock {
extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj ); extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj );
extern BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect ); 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_FrameRgn( HRGN dest, HRGN src, INT x, INT y );
extern BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc ); extern BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc );

View File

@ -16,6 +16,7 @@
#include "windef.h" #include "windef.h"
#ifdef HAVE_LIBXXF86VM #ifdef HAVE_LIBXXF86VM
#define XMD_H #define XMD_H
#define INT32 INT
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/extensions/xf86vmode.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 TSXRectInRegion(Region, int, int, unsigned int, unsigned int);
extern int TSXSaveContext(Display*, XID, XContext, const char*); extern int TSXSaveContext(Display*, XID, XContext, const char*);
extern int TSXSetClassHint(Display*, Window, XClassHint*); 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 TSXSetWMProperties(Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
extern void TSXSetWMSizeHints(Display*, Window, XSizeHints*, Atom); extern void TSXSetWMSizeHints(Display*, Window, XSizeHints*, Atom);
extern int TSXSetRegion(Display*, GC, Region); 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_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_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 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); extern BOOL TTYDRV_WND_IsSelfClipping(struct tagWND *wndPtr);
#endif /* !defined(__WINE_TTYDRV_H) */ #endif /* !defined(__WINE_TTYDRV_H) */

View File

@ -44,8 +44,10 @@ typedef enum
} BUILTIN_CLASS32; } BUILTIN_CLASS32;
/* PAINT_RedrawWindow() control flags */ /* PAINT_RedrawWindow() control flags */
#define RDW_C_USEHRGN 0x0001 #define RDW_EX_USEHRGN 0x0001
#define RDW_C_DELETEHRGN 0x0002 #define RDW_EX_DELETEHRGN 0x0002
#define RDW_EX_XYWINDOW 0x0004
#define RDW_EX_TOPFRAME 0x0010
struct tagCLASS; struct tagCLASS;
struct tagDCE; struct tagDCE;
@ -86,6 +88,25 @@ typedef struct tagWND
DWORD wExtra[1]; /* Window extra bytes */ DWORD wExtra[1]; /* Window extra bytes */
} WND; } 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 typedef struct _WND_DRIVER
{ {
void (*pInitialize)(WND *); void (*pInitialize)(WND *);
@ -100,8 +121,9 @@ typedef struct _WND_DRIVER
void (*pSetFocus)(WND *); void (*pSetFocus)(WND *);
void (*pPreSizeMove)(WND *); void (*pPreSizeMove)(WND *);
void (*pPostSizeMove)(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); void (*pSetDrawable)(WND *, struct tagDC *, WORD, BOOL);
BOOL (*pSetHostAttr)(WND *, INT haKey, INT value);
BOOL (*pIsSelfClipping)(WND *); BOOL (*pIsSelfClipping)(WND *);
} WND_DRIVER; } WND_DRIVER;
@ -119,13 +141,12 @@ typedef struct
#define WIN_NEEDS_NCPAINT 0x0004 /* WM_NCPAINT must be sent to window */ #define WIN_NEEDS_NCPAINT 0x0004 /* WM_NCPAINT must be sent to window */
#define WIN_RESTORE_MAX 0x0008 /* Maximize when restoring */ #define WIN_RESTORE_MAX 0x0008 /* Maximize when restoring */
#define WIN_INTERNAL_PAINT 0x0010 /* Internal WM_PAINT message pending */ #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_NEED_SIZE 0x0040 /* Internal WM_SIZE is needed */
#define WIN_NCACTIVATED 0x0080 /* last WM_NCACTIVATE was positive */ #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_ISDIALOG 0x0200 /* Window is a dialog */
#define WIN_ISWIN32 0x0400 /* Understands Win32 messages */ #define WIN_ISWIN32 0x0400 /* Understands Win32 messages */
#define WIN_SAVEUNDER_OVERRIDE 0x0800
/* BuildWinArray() flags */ /* BuildWinArray() flags */
#define BWA_SKIPDISABLED 0x0001 #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, extern BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
HRGN hrgnUpdate, UINT flags, HRGN hrgnUpdate, UINT flags,
UINT control ); /* windows/painting.c */ 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 */ /* controls/widgets.c */

View File

@ -328,6 +328,7 @@ extern struct _WND_DRIVER X11DRV_WND_Driver;
typedef struct _X11DRV_WND_DATA { typedef struct _X11DRV_WND_DATA {
Window window; Window window;
int bit_gravity;
} X11DRV_WND_DATA; } X11DRV_WND_DATA;
extern Window X11DRV_WND_GetXWindow(struct tagWND *wndPtr); 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_SetFocus(struct tagWND *wndPtr);
extern void X11DRV_WND_PreSizeMove(struct tagWND *wndPtr); extern void X11DRV_WND_PreSizeMove(struct tagWND *wndPtr);
extern void X11DRV_WND_PostSizeMove(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 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); extern BOOL X11DRV_WND_IsSelfClipping(struct tagWND *wndPtr);
#endif /* __WINE_X11DRV_H */ #endif /* __WINE_X11DRV_H */

View File

@ -4,6 +4,7 @@
* *
* Copyright 1993, 1994, 1995 Alexandre Julliard * Copyright 1993, 1994, 1995 Alexandre Julliard
* Modifications and additions: Copyright 1998 Huw Davies * 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_XorRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn); static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn);
#define RGN_DEFAULT_RECTS 2
/*********************************************************************** /***********************************************************************
* REGION_DumpRegion * REGION_DumpRegion
@ -117,47 +119,50 @@ static void REGION_DumpRegion(WINEREGION *pReg)
return; return;
} }
/*********************************************************************** /***********************************************************************
* REGION_AllocWineRegion * REGION_AllocWineRegion
* Create a new empty WINEREGION. * Create a new empty WINEREGION.
*/ */
static WINEREGION *REGION_AllocWineRegion( void ) static WINEREGION *REGION_AllocWineRegion( INT n )
{ {
WINEREGION *pReg; WINEREGION *pReg;
if ((pReg = HeapAlloc(SystemHeap, 0, sizeof( WINEREGION )))) 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); EMPTY_REGION(pReg);
return pReg; return pReg;
} }
HeapFree(SystemHeap, 0, pReg); HeapFree(SystemHeap, 0, pReg);
} }
return NULL; return NULL;
} }
/*********************************************************************** /***********************************************************************
* REGION_CreateRegion * REGION_CreateRegion
* Create a new empty region. * Create a new empty region.
*/ */
static HRGN REGION_CreateRegion(void) static HRGN REGION_CreateRegion( INT n )
{ {
HRGN hrgn; HRGN hrgn;
RGNOBJ *obj; RGNOBJ *obj;
if(!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) if(!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
return 0; return 0;
obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn ); obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
if(!(obj->rgn = REGION_AllocWineRegion())) { if(!(obj->rgn = REGION_AllocWineRegion(n))) {
GDI_FreeObject( hrgn ); GDI_FreeObject( hrgn );
return 0; return 0;
} }
GDI_HEAP_UNLOCK( hrgn ); GDI_HEAP_UNLOCK( hrgn );
return hrgn; return hrgn;
} }
/*********************************************************************** /***********************************************************************
* REGION_DestroyWineRegion * REGION_DestroyWineRegion
*/ */
@ -194,14 +199,14 @@ INT WINAPI OffsetRgn( HRGN hrgn, INT x, INT y )
{ {
RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ); RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
if (obj) if (obj && (x || y))
{ {
INT ret; INT ret;
int nbox = obj->rgn->numRects; int nbox = obj->rgn->numRects;
RECT *pbox = obj->rgn->rects; RECT *pbox = obj->rgn->rects;
TRACE(region, " %04x %d,%d\n", hrgn, x, y ); TRACE(region, " %04x %d,%d\n", hrgn, x, y );
if(nbox && (x || y)) { if(nbox) {
while(nbox--) { while(nbox--) {
pbox->left += x; pbox->left += x;
pbox->right += x; pbox->right += x;
@ -264,7 +269,7 @@ HRGN16 WINAPI CreateRectRgn16(INT16 left, INT16 top, INT16 right, INT16 bottom)
{ {
HRGN16 hrgn; HRGN16 hrgn;
if (!(hrgn = (HRGN16)REGION_CreateRegion())) if (!(hrgn = (HRGN16)REGION_CreateRegion(RGN_DEFAULT_RECTS)))
return 0; return 0;
TRACE(region, "\n"); TRACE(region, "\n");
SetRectRgn16(hrgn, left, top, right, bottom); SetRectRgn16(hrgn, left, top, right, bottom);
@ -279,7 +284,9 @@ HRGN WINAPI CreateRectRgn(INT left, INT top, INT right, INT bottom)
{ {
HRGN hrgn; 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; return 0;
TRACE(region, "\n"); TRACE(region, "\n");
SetRectRgn(hrgn, left, top, right, bottom); SetRectRgn(hrgn, left, top, right, bottom);
@ -399,7 +406,8 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
/* Create region */ /* 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 ); obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
TRACE(region,"(%d,%d-%d,%d %dx%d): ret=%04x\n", TRACE(region,"(%d,%d-%d,%d %dx%d): ret=%04x\n",
left, top, right, bottom, ellipse_width, ellipse_height, hrgn ); 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 WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA* rgndata)
{ {
HRGN hrgn = CreateRectRgn(0, 0, 0, 0); HRGN hrgn;
RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
RECT *pCurRect, *pEndRect;
TRACE(region, " %p %ld %p. Returning %04x\n", TRACE(region, " %p %ld %p = ", lpXform, dwCount, rgndata );
lpXform, dwCount, rgndata, hrgn);
if(!hrgn) if( lpXform )
{ WARN(region, "(Xform not implemented - ignored) ");
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) if( rgndata->rdh.iType != RDH_RECTANGLES )
{ {
WARN(region, "Type not RDH_RECTANGLES\n"); /* FIXME: We can use CreatePolyPolygonRgn() here
GDI_HEAP_UNLOCK( hrgn ); * for trapezoidal data */
DeleteObject( hrgn );
return 0; WARN(region, "(Unsupported region data) ");
goto fail;
} }
pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount; if( (hrgn = REGION_CreateRegion( rgndata->rdh.nCount )) )
for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++) {
REGION_UnionRectWithRegion( pCurRect, obj->rgn ); RECT *pCurRect, *pEndRect;
RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
GDI_HEAP_UNLOCK( hrgn ); pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
return hrgn; 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 * Only do this stuff if the number of rectangles allocated is more than
* twice the number of rectangles in the region (a simple optimization...). * 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)) if (REGION_NOT_EMPTY(newReg))
{ {
@ -1916,8 +1928,8 @@ static void REGION_XorRegion(WINEREGION *dr, WINEREGION *sra,
{ {
WINEREGION *tra, *trb; WINEREGION *tra, *trb;
if ((! (tra = REGION_AllocWineRegion())) || if ((! (tra = REGION_AllocWineRegion(sra->numRects + 1))) ||
(! (trb = REGION_AllocWineRegion()))) (! (trb = REGION_AllocWineRegion(srb->numRects + 1))))
return; return;
REGION_SubtractRegion(tra,sra,srb); REGION_SubtractRegion(tra,sra,srb);
REGION_SubtractRegion(trb,srb,sra); REGION_SubtractRegion(trb,srb,sra);
@ -2357,7 +2369,7 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
int numFullPtBlocks = 0; int numFullPtBlocks = 0;
INT poly, total; INT poly, total;
if(!(hrgn = REGION_CreateRegion())) if(!(hrgn = REGION_CreateRegion(nbpolygons)))
return 0; return 0;
obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ); obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
region = obj->rgn; region = obj->rgn;
@ -2568,3 +2580,205 @@ HRGN WINAPI GetRandomRgn(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3)
return 0; 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") { if($name eq "xf86vmode") {
$x11_incl = "#include <X11/Xlib.h>\n"; $x11_incl = "#include <X11/Xlib.h>\n";
$extensions_dir = "extensions/"; $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"; $post_file = "#endif /* defined(HAVE_LIBXXF86VM) */\n";
} }

View File

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

View File

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

View File

@ -235,6 +235,17 @@ int TSXSetClassHint(Display* a0, Window a1, XClassHint* a2)
return r; 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) 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"); TRACE(x11, "Call XSetWMProperties\n");

View File

@ -222,8 +222,9 @@ static INT DCE_ReleaseDC( DCE* dce )
* DCE_InvalidateDCE * DCE_InvalidateDCE
* *
* It is called from SetWindowPos() - we have to mark as dirty all busy * 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 * DCEs for windows that have pWnd->parent as an ansector and whose client
* rect intersects with specified update rectangle. * 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) 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); WND* wndCurrent = WIN_FindWndPtr(dce->hwndCurrent);
if( wndCurrent && wndCurrent != WIN_GetDesktop() ) if( wndCurrent )
{ {
WND* wnd = NULL; WND* wnd = NULL;
INT xoffset = 0, yoffset = 0; INT xoffset = 0, yoffset = 0;
if( (wndCurrent == wndScope) && !(dce->DCXflags & DCX_CLIPCHILDREN) ) if( (wndCurrent == wndScope) && !(dce->DCXflags & DCX_CLIPCHILDREN) )
{ {
/* child window positions don't bother us */
WIN_ReleaseWndPtr(wndCurrent); WIN_ReleaseWndPtr(wndCurrent);
continue; 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 */ /* check if DCE window is within the z-order scope */
for( wnd = WIN_LockWndPtr(wndCurrent); wnd; WIN_UpdateWndPtr(&wnd,wnd->parent)) 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_ReleaseWndPtr(wndCurrent);
WIN_ReleaseDesktop();
} }
} /* dce list */ } /* dce list */
} }

View File

@ -11,6 +11,7 @@
#include "sysmetrics.h" #include "sysmetrics.h"
#include "user.h" #include "user.h"
#include "heap.h" #include "heap.h"
#include "dce.h"
#include "cursoricon.h" #include "cursoricon.h"
#include "dialog.h" #include "dialog.h"
#include "menu.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 ); 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, if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
wndPtr->rectClient.top-wndPtr->rectWindow.top, wndPtr->rectClient.top-wndPtr->rectWindow.top,
@ -1665,7 +1667,7 @@ void NC_DoNCPaint95(
BOOL suppress_menupaint ) BOOL suppress_menupaint )
{ {
HDC hdc; HDC hdc;
RECT rect; RECT rfuzz, rect, rectClip;
BOOL active; BOOL active;
HWND hwnd = wndPtr->hwndSelf; HWND hwnd = wndPtr->hwndSelf;
@ -1676,7 +1678,15 @@ void NC_DoNCPaint95(
TRACE(nonclient, "%04x %d\n", hwnd, active ); 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, if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
wndPtr->rectClient.top-wndPtr->rectWindow.top, wndPtr->rectClient.top-wndPtr->rectWindow.top,
@ -1692,6 +1702,14 @@ void NC_DoNCPaint95(
rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left; rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top; rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
if( clip > 1 )
GetRgnBox( clip, &rectClip );
else
{
clip = 0;
rectClip = rect;
}
SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) ); SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
if(!(wndPtr->flags & WIN_MANAGED)) { if(!(wndPtr->flags & WIN_MANAGED)) {
@ -1716,8 +1734,9 @@ void NC_DoNCPaint95(
r.bottom = rect.top + sysMetrics[SM_CYCAPTION]; r.bottom = rect.top + sysMetrics[SM_CYCAPTION];
rect.top += sysMetrics[SM_CYCAPTION]; rect.top += sysMetrics[SM_CYCAPTION];
} }
NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle, if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
wndPtr->dwExStyle, active); NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
wndPtr->dwExStyle, active);
} }
} }

View File

@ -2,12 +2,11 @@
* Window painting functions * Window painting functions
* *
* Copyright 1993, 1994, 1995 Alexandre Julliard * 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 "win.h"
#include "queue.h" #include "queue.h"
#include "dce.h" #include "dce.h"
@ -15,74 +14,98 @@
#include "debug.h" #include "debug.h"
#include "wine/winuser16.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 */ /* Last CTLCOLOR id */
#define CTLCOLOR_MAX CTLCOLOR_STATIC #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 */ /* desktop window doesn't have nonclient area */
if(wnd == WIN_GetDesktop()) if(wnd == WIN_GetDesktop())
{ {
wnd->flags &= ~WIN_NEEDS_NCPAINT; wnd->flags &= ~WIN_NEEDS_NCPAINT;
WIN_ReleaseDesktop(); WIN_ReleaseDesktop();
return; return 0;
} }
WIN_ReleaseDesktop(); WIN_ReleaseDesktop();
if( wnd->hrgnUpdate > 1 ) if ((wnd->hwndSelf == GetActiveWindow()) &&
!(wnd->flags & WIN_NCACTIVATED) )
{ {
ClientToScreen16(wnd->hwndSelf, &pt); wnd->flags |= WIN_NCACTIVATED;
bForceEntire = TRUE;
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 );
}
} }
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; wnd->flags &= ~WIN_NEEDS_NCPAINT;
if ((wnd->hwndSelf == GetActiveWindow()) && if( hClip )
!(wnd->flags & WIN_NCACTIVATED)) SendMessageA( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
{
wnd->flags |= WIN_NCACTIVATED;
if( hClip > 1) DeleteObject( hClip );
hClip = 1;
}
if (hClip) SendMessage16( wnd->hwndSelf, WM_NCPAINT, hClip, 0L ); return hClip;
if (hClip > 1) DeleteObject( hClip );
} }
@ -100,10 +123,10 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT; 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) || if( ((hrgnUpdate = wndPtr->hrgnUpdate) != 0) || (wndPtr->flags & WIN_INTERNAL_PAINT))
(wndPtr->flags & WIN_INTERNAL_PAINT))
QUEUE_DecPaintCount( wndPtr->hmemTaskQ ); QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
wndPtr->hrgnUpdate = 0; wndPtr->hrgnUpdate = 0;
@ -113,20 +136,19 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
TRACE(win,"hrgnUpdate = %04x, \n", hrgnUpdate); 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) if (wndPtr->class->style & CS_PARENTDC)
{ {
/* Don't clip the output to the update region for CS_PARENTDC window */ /* Don't clip the output to the update region for CS_PARENTDC window */
if(hrgnUpdate > 1) if( hrgnUpdate > 1 )
DeleteObject(hrgnUpdate); DeleteObject(hrgnUpdate);
lps->hdc = GetDCEx16( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE | lps->hdc = GetDCEx16( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE |
(bIcon ? DCX_WINDOW : 0) ); (bIcon ? DCX_WINDOW : 0) );
} }
else else
{ {
if( hrgnUpdate )
OffsetRgn( hrgnUpdate, wndPtr->rectWindow.left - wndPtr->rectClient.left,
wndPtr->rectWindow.top - wndPtr->rectClient.top );
lps->hdc = GetDCEx16(hwnd, hrgnUpdate, DCX_INTERSECTRGN | lps->hdc = GetDCEx16(hwnd, hrgnUpdate, DCX_INTERSECTRGN |
DCX_WINDOWPAINT | DCX_USESTYLE | DCX_WINDOWPAINT | DCX_USESTYLE |
(bIcon ? DCX_WINDOW : 0) ); (bIcon ? DCX_WINDOW : 0) );
@ -143,7 +165,7 @@ HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
GetClipBox16( lps->hdc, &lps->rcPaint ); 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 ); lps->rcPaint.right, lps->rcPaint.bottom );
if (wndPtr->flags & WIN_NEEDS_ERASEBKGND) if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
@ -285,14 +307,14 @@ END:
* LOWORD(lParam) = hrgnClip * LOWORD(lParam) = hrgnClip
* HIWORD(lParam) = hwndSkip (not used; always NULL) * HIWORD(lParam) = hwndSkip (not used; always NULL)
* *
* All in all, a prime candidate for a rewrite.
*/ */
BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate, BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
HRGN hrgnUpdate, UINT flags, UINT control ) HRGN hrgnUpdate, UINT flags, UINT ex )
{ {
BOOL bIcon; BOOL bIcon;
HRGN hrgn; HRGN hrgn = 0, hrgn2 = 0;
RECT rectClient; RECT r, r2;
POINT pt;
WND* wndPtr; WND* wndPtr;
WND **list, **ppWnd; WND **list, **ppWnd;
@ -307,110 +329,165 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon); bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
if (rectUpdate) if (rectUpdate)
{ {
TRACE(win, "%04x %d,%d-%d,%d %04x flags=%04x\n", TRACE(win, "%04x (%04x) %d,%d-%d,%d %04x flags=%04x, exflags=%04x\n",
hwnd, rectUpdate->left, rectUpdate->top, hwnd, wndPtr->hrgnUpdate, rectUpdate->left, rectUpdate->top,
rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags ); rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags, ex );
} }
else 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? */ /* wndPtr->hrgnUpdate is in window coordinates, parameters are
{ * in client coordinates unless RDW_EX_XYWINDOW is set.
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;
/* restrict update region to client area (FIXME: correct?) */ if( hrgnUpdate )
if (wndPtr->hrgnUpdate) {
{ hrgn = REGION_CropRgn( 0, hrgnUpdate, &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt );
HRGN clientRgn = CreateRectRgnIndirect( &rectClient ); GetRgnBox( hrgn, &r2 );
rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, clientRgn, if( IsRectEmpty( &r2 ) )
wndPtr->hrgnUpdate, RGN_AND ); goto END;
DeleteObject( clientRgn );
}
/* check for bogus update region */ if( wndPtr->hrgnUpdate == 0 )
if ( rgnNotEmpty == NULLREGION ) {
{ wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND; CombineRgn( wndPtr->hrgnUpdate, hrgn, 0, RGN_COPY );
DeleteObject( wndPtr->hrgnUpdate ); }
wndPtr->hrgnUpdate=0; else
if (!(wndPtr->flags & WIN_INTERNAL_PAINT)) if( wndPtr->hrgnUpdate > 1 )
QUEUE_DecPaintCount( wndPtr->hmemTaskQ ); CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hrgn, RGN_OR );
} }
else else if( rectUpdate )
if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND; {
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 */ 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) /* need an update region in order to validate anything */
if (wndPtr->hrgnUpdate > 1)
{ {
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 */ wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
DeleteObject( wndPtr->hrgnUpdate );
wndPtr->hrgnUpdate = 0; 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 (!wndPtr->hrgnUpdate && /* No more update region */
if ((hrgn = hrgnUpdate) == 0) !(wndPtr->flags & WIN_INTERNAL_PAINT) )
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))
QUEUE_DecPaintCount( wndPtr->hmemTaskQ ); QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
} }
if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT; if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND; 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 (flags & RDW_INTERNALPAINT)
{ {
if ( wndPtr->hrgnUpdate <= 1 && !(wndPtr->flags & WIN_INTERNAL_PAINT)) if ( !wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
QUEUE_IncPaintCount( wndPtr->hmemTaskQ ); QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
wndPtr->flags |= WIN_INTERNAL_PAINT; wndPtr->flags |= WIN_INTERNAL_PAINT;
} }
else if (flags & RDW_NOINTERNALPAINT) 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 ); QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
wndPtr->flags &= ~WIN_INTERNAL_PAINT; wndPtr->flags &= ~WIN_INTERNAL_PAINT;
} }
@ -422,17 +499,29 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */ if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
SendMessage16( hwnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 ); 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) hrgn2 = WIN_UpdateNCRgn( wndPtr, TRUE, (ex & RDW_EX_TOPFRAME) );
WIN_UpdateNCArea( wndPtr, FALSE);
if (wndPtr->flags & WIN_NEEDS_ERASEBKGND) if( wndPtr->flags & WIN_NEEDS_ERASEBKGND )
{ {
HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate, HDC hdc;
DCX_INTERSECTRGN | DCX_USESTYLE |
DCX_KEEPCLIPRGN | DCX_WINDOWPAINT | if( hrgn2 > 1 )
(bIcon ? DCX_WINDOW : 0) ); {
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 (hdc)
{ {
if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND
@ -456,47 +545,40 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) && ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) &&
!(wndPtr->dwStyle & WS_MINIMIZE) ) !(wndPtr->dwStyle & WS_MINIMIZE) )
{ {
if ( hrgnUpdate || rectUpdate ) if( hrgnUpdate || rectUpdate )
{ {
if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 ))) if( hrgn2 <= 1 )
{ hrgn2 = (ex & RDW_EX_USEHRGN) ? hrgnUpdate : 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( (list = WIN_BuildWinArray( wndPtr, 0, NULL )) ) if( (list = WIN_BuildWinArray( wndPtr, 0, NULL )) )
{ {
POINT delta = pt;
for (ppWnd = list; *ppWnd; ppWnd++) for (ppWnd = list; *ppWnd; ppWnd++)
{ {
WIN_UpdateWndPtr(&wndPtr,*ppWnd); WIN_UpdateWndPtr(&wndPtr,*ppWnd);
if (!IsWindow(wndPtr->hwndSelf)) continue; if (!IsWindow(wndPtr->hwndSelf)) continue;
if (wndPtr->dwStyle & WS_VISIBLE) if (wndPtr->dwStyle & WS_VISIBLE)
{ {
SetRectRgn( hrgn, r.left = wndPtr->rectWindow.left + delta.x;
wndPtr->rectWindow.left, wndPtr->rectWindow.top, r.top = wndPtr->rectWindow.top + delta.y;
wndPtr->rectWindow.right, wndPtr->rectWindow.bottom ); r.right = wndPtr->rectWindow.right + delta.x;
if (CombineRgn( hrgn, hrgn, hrgnUpdate, RGN_AND )) 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, PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn2, flags,
-wndPtr->rectClient.top ); RDW_EX_USEHRGN | RDW_EX_XYWINDOW );
PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn, flags,
RDW_C_USEHRGN );
} }
} }
} }
WIN_ReleaseWinArray(list); WIN_ReleaseWinArray(list);
} }
DeleteObject( hrgn );
if (control & RDW_C_DELETEHRGN) DeleteObject( hrgnUpdate );
} }
else 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); WIN_ReleaseWndPtr(wndPtr);
return TRUE; 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 );
}
else
SetRectEmpty( rect );
} }
retvalue = (wndPtr->hrgnUpdate > 1); retvalue = (wndPtr->hrgnUpdate >= 1);
END: END:
WIN_ReleaseWndPtr(wndPtr); WIN_ReleaseWndPtr(wndPtr);
return retvalue; 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 ) 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 ); WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return ERROR; if (!wndPtr) return ERROR;
if (wndPtr->hrgnUpdate <= 1) if (wndPtr->hrgnUpdate == 0)
{ {
SetRectRgn( hrgn, 0, 0, 0, 0 ); SetRectRgn( hrgn, 0, 0, 0, 0 );
retval = NULLREGION; retval = NULLREGION;
goto END; 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 ); if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
END: END:
WIN_ReleaseWndPtr(wndPtr); WIN_ReleaseWndPtr(wndPtr);
@ -745,10 +852,14 @@ INT WINAPI ExcludeUpdateRgn( HDC hdc, HWND hwnd )
INT ret; INT ret;
HRGN hrgn = CreateRectRgn(wndPtr->rectWindow.left - wndPtr->rectClient.left, HRGN hrgn = CreateRectRgn(wndPtr->rectWindow.left - wndPtr->rectClient.left,
wndPtr->rectWindow.top - wndPtr->rectClient.top, wndPtr->rectWindow.top - wndPtr->rectClient.top,
wndPtr->rectClient.right - wndPtr->rectClient.left, wndPtr->rectWindow.right - wndPtr->rectClient.left,
wndPtr->rectClient.bottom - wndPtr->rectClient.top); wndPtr->rectWindow.bottom - wndPtr->rectClient.top);
if( wndPtr->hrgnUpdate > 1 ) if( wndPtr->hrgnUpdate > 1 )
{
CombineRgn(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY); 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 */ /* 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 = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
{ {
if (dc->w.hVisRgn) { if (dc->w.hVisRgn) {
wnd->pDriver->pScrollWindow(wnd,dc,dx,dy,&rc,bUpdate); wnd->pDriver->pSurfaceCopy(wnd,dc,dx,dy,&rc,bUpdate);
if( bUpdate ) if( bUpdate )
{ {

View File

@ -81,6 +81,7 @@ WND_DRIVER TTYDRV_WND_Driver =
TTYDRV_WND_PostSizeMove, TTYDRV_WND_PostSizeMove,
TTYDRV_WND_ScrollWindow, TTYDRV_WND_ScrollWindow,
TTYDRV_WND_SetDrawable, TTYDRV_WND_SetDrawable,
TTYDRV_WND_SetHostAttr,
TTYDRV_WND_IsSelfClipping 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 * TTYDRV_WND_IsSelfClipping
*/ */

View File

@ -1666,14 +1666,24 @@ BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
{ {
/* Enable window */ /* Enable window */
wndPtr->dwStyle &= ~WS_DISABLED; wndPtr->dwStyle &= ~WS_DISABLED;
if( wndPtr->flags & WIN_NATIVE )
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
SendMessageA( hwnd, WM_ENABLE, TRUE, 0 ); SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
retvalue = TRUE; retvalue = TRUE;
goto end; goto end;
} }
else if (!enable && !(wndPtr->dwStyle & WS_DISABLED)) else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
{ {
SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
/* Disable window */ /* Disable window */
wndPtr->dwStyle |= WS_DISABLED; wndPtr->dwStyle |= WS_DISABLED;
if( wndPtr->flags & WIN_NATIVE )
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() )) if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
{ {
SetFocus( 0 ); /* A disabled window can't have the focus */ 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 * EVENT_QueryZOrder
* *
* Try to synchronize internal z-order with the window manager's. * Synchronize internal z-order with the window manager's.
* Probably a futile endeavor.
*/ */
static BOOL __check_query_condition( WND** pWndA, WND** pWndB ) static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
{ {
@ -540,19 +539,25 @@ static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
static Window __get_common_ancestor( Window A, Window B, static Window __get_common_ancestor( Window A, Window B,
Window** children, unsigned* total ) Window** children, unsigned* total )
{ {
/* find the real root window */ /* find the real root window */
Window root, *childrenB; Window root, *childrenB;
unsigned totalB; unsigned totalB;
do do
{ {
if( *children ) TSXFree( *children );
TSXQueryTree( display, A, &root, &A, children, total ); TSXQueryTree( display, A, &root, &A, children, total );
TSXQueryTree( display, B, &root, &B, &childrenB, &totalB ); TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
if( childrenB ) TSXFree( childrenB ); if( childrenB ) TSXFree( childrenB );
if( *children ) TSXFree( *children );
} while( A != B && A && B ); } 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 ) 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 ) static unsigned __td_lookup( Window w, Window* list, unsigned max )
{ {
unsigned i; 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; return i;
} }
@ -591,32 +596,42 @@ static BOOL EVENT_QueryZOrder( WND* pWndCheck )
X11DRV_WND_GetXWindow(pWnd), X11DRV_WND_GetXWindow(pWnd),
&children, &total ); &children, &total );
if( parent && children ) 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 ); 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 ); check = __td_lookup( w, children, total );
best = total; best = total;
for( pWnd = pWndZ; pWnd; pWnd = pWnd->next ) for( pWnd = pWndZ; pWnd; pWnd = pWnd->next )
{ {
/* go through all windows in Wine z-order... */
if( pWnd != pWndCheck ) if( pWnd != pWndCheck )
{ {
if( !(pWnd->flags & WIN_MANAGED) || if( !(pWnd->flags & WIN_MANAGED) ||
!(w = __get_top_decoration( X11DRV_WND_GetXWindow(pWnd), parent )) ) !(w = __get_top_decoration( X11DRV_WND_GetXWindow(pWnd), parent )) )
continue; continue;
pos = __td_lookup( w, children, total ); pos = __td_lookup( w, children, total );
if( pos < best && pos > check ) if( pos < best && pos > check )
{ {
/* find a nearest Wine window precedes
* pWndCheck in the real z-order... */
best = pos; best = pos;
hwndInsertAfter = pWnd->hwndSelf; hwndInsertAfter = pWnd->hwndSelf;
} }
if( check - best == 1 ) break; if( best - check == 1 ) break;
} }
} }
WIN_UnlinkWindow( pWndCheck->hwndSelf ); /* and link pWndCheck right behind it in the local z-order */
WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter); }
} WIN_UnlinkWindow( pWndCheck->hwndSelf );
} WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
}
if( children ) TSXFree( children ); if( children ) TSXFree( children );
return bRet; return bRet;
} }
@ -867,14 +882,17 @@ static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event )
*/ */
static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event ) static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
{ {
if (event->detail != NotifyPointer) if (event->detail != NotifyPointer)
{ {
HWND hwnd = pWnd->hwndSelf; HWND hwnd = pWnd->hwndSelf;
if (hwnd == GetActiveWindow()) if (hwnd == GetActiveWindow())
WINPOS_ChangeActiveWindow( 0, FALSE ); {
if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
SetFocus( 0 ); WINPOS_ChangeActiveWindow( 0, FALSE );
}
if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
SetFocus( 0 );
} }
} }
@ -910,13 +928,13 @@ static void EVENT_GetGeometry( Window win, int *px, int *py,
if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight, if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight,
&border, &depth )) return; &border, &depth )) return;
if (win == X11DRV_GetXRootWindow()) if (win == X11DRV_GetXRootWindow())
{ {
*px = *py = 0; *px = *py = 0;
return; return;
} }
for (;;) for (;;)
{ {
if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children)) if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children))
return; return;
TSXFree( children ); TSXFree( children );
@ -926,7 +944,7 @@ static void EVENT_GetGeometry( Window win, int *px, int *py,
&width, &height, &border, &depth )) return; &width, &height, &border, &depth )) return;
*px += xpos; *px += xpos;
*py += ypos; *py += ypos;
} }
} }
@ -940,7 +958,7 @@ static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
{ {
WINDOWPOS winpos; WINDOWPOS winpos;
RECT newWindowRect, newClientRect; RECT newWindowRect, newClientRect;
HRGN hrgnOldPos, hrgnNewPos; RECT oldWindowRect, oldClientRect;
Window above = event->above; Window above = event->above;
int x, y; int x, y;
unsigned int width, height; unsigned int width, height;
@ -953,6 +971,9 @@ static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
*/ */
EVENT_GetGeometry( event->window, &x, &y, &width, &height ); 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 */ /* Fill WINDOWPOS struct */
winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER; winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER;
winpos.hwnd = pWnd->hwndSelf; winpos.hwnd = pWnd->hwndSelf;
@ -991,15 +1012,20 @@ static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
if (!IsWindow( winpos.hwnd )) return; if (!IsWindow( winpos.hwnd )) return;
hrgnOldPos = CreateRectRgnIndirect( &pWnd->rectWindow ); oldWindowRect = pWnd->rectWindow;
hrgnNewPos = CreateRectRgnIndirect( &newWindowRect ); oldClientRect = pWnd->rectClient;
CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
DeleteObject(hrgnOldPos);
DeleteObject(hrgnNewPos);
/* Set new size and position */ /* Set new size and position */
pWnd->rectWindow = newWindowRect; pWnd->rectWindow = newWindowRect;
pWnd->rectClient = newClientRect; 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 ); SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
if (!IsWindow( winpos.hwnd )) return; if (!IsWindow( winpos.hwnd )) return;

View File

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

View File

@ -170,7 +170,9 @@ BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BO
if (!(cs->style & WS_CHILD) && if (!(cs->style & WS_CHILD) &&
(X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display))) (X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display)))
{ {
Window wGroupLeader;
XWMHints* wm_hints;
XSetWindowAttributes win_attr; XSetWindowAttributes win_attr;
if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) || 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; FocusChangeMask;
win_attr.override_redirect = TRUE; win_attr.override_redirect = TRUE;
} }
wndPtr->flags |= WIN_NATIVE;
win_attr.bit_gravity = BGNorthWest;
win_attr.colormap = X11DRV_COLOR_GetColormap(); win_attr.colormap = X11DRV_COLOR_GetColormap();
win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful; win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0); win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
win_attr.cursor = X11DRV_MOUSE_XCursor; win_attr.cursor = X11DRV_MOUSE_XCursor;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = BGNorthWest;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
TSXCreateWindow( display, TSXCreateWindow( display,
X11DRV_WND_GetXRootWindow(wndPtr), X11DRV_WND_GetXRootWindow(wndPtr),
@ -203,9 +210,10 @@ BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BO
InputOutput, CopyFromParent, InputOutput, CopyFromParent,
CWEventMask | CWOverrideRedirect | CWEventMask | CWOverrideRedirect |
CWColormap | CWCursor | CWSaveUnder | CWColormap | CWCursor | CWSaveUnder |
CWBackingStore, &win_attr ); CWBackingStore | CWBitGravity,
&win_attr );
if(!X11DRV_WND_GetXWindow(wndPtr)) if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
return FALSE; return FALSE;
if (wndPtr->flags & WIN_MANAGED) { if (wndPtr->flags & WIN_MANAGED) {
@ -233,14 +241,36 @@ BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BO
} }
if (cs->hwndParent) /* Get window owner */ if (cs->hwndParent) /* Get window owner */
{ {
Window w;
WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent); 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); 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 ); X11DRV_WND_RegisterWindow( wndPtr );
} }
return TRUE; return TRUE;
} }
@ -400,26 +430,26 @@ static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
* *
* SetWindowPos() for an X window. Used by the real SetWindowPos(). * 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; XWindowChanges winChanges;
int changeMask = 0; int changeMask = 0;
WND *winposPtr = WIN_FindWndPtr( winpos->hwnd ); 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)) if(X11DRV_WND_GetXWindow(wndPtr))
TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) ); TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
} }
if(bSMC_SETXPOS) if(bChangePos)
{ {
if ( !(winpos->flags & SWP_NOSIZE)) if ( !(winpos->flags & SWP_NOSIZE))
{ {
winChanges.width = winpos->cx; winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
winChanges.height = winpos->cy; winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
changeMask |= CWWidth | CWHeight; changeMask |= CWWidth | CWHeight;
/* Tweak dialog window size hints */ /* Tweak dialog window size hints */
@ -477,11 +507,11 @@ void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bSMC_SET
} }
} }
if ( winpos->flags & SWP_SHOWWINDOW ) if ( winpos->flags & SWP_SHOWWINDOW )
{ {
if(X11DRV_WND_GetXWindow(wndPtr)) TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) ); if(X11DRV_WND_GetXWindow(wndPtr)) TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
} }
WIN_ReleaseWndPtr(winposPtr); WIN_ReleaseWndPtr(winposPtr);
} }
/***************************************************************** /*****************************************************************
@ -555,31 +585,32 @@ 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( void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy,
WND *wndPtr, DC *dcPtr, INT dx, INT dy, const RECT *rect, BOOL bUpdate)
const RECT *rect, BOOL bUpdate)
{ {
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev; X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
POINT dst, src; POINT dst, src;
dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx; dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy; 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 ); TSXSetGraphicsExposures( display, physDev->gc, True );
TSXSetFunction( display, physDev->gc, GXcopy ); TSXSetFunction( display, physDev->gc, GXcopy );
TSXCopyArea( display, physDev->drawable, physDev->drawable, TSXCopyArea( display, physDev->drawable, physDev->drawable,
physDev->gc, src.x, src.y, physDev->gc, src.x, src.y,
rect->right - rect->left, rect->right - rect->left,
rect->bottom - rect->top, rect->bottom - rect->top,
dst.x, dst.y ); dst.x, dst.y );
if (bUpdate) if (bUpdate)
TSXSetGraphicsExposures( display, physDev->gc, False ); TSXSetGraphicsExposures( display, physDev->gc, False );
if (bUpdate) /* Make sure exposure events have been processed */ if (bUpdate) /* Make sure exposure events have been processed */
EVENT_Synchronize(); EVENT_Synchronize();
} }
/*********************************************************************** /***********************************************************************
@ -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 * X11DRV_WND_IsSelfClipping
*/ */