Use the topmost parent that isn't clipping children as drawable,
to make sure parent siblings are not clipped.
This commit is contained in:
parent
b0f69948c6
commit
7b25ed534b
|
@ -59,16 +59,16 @@ DEFAULT_DEBUG_CHANNEL(x11drv);
|
||||||
*
|
*
|
||||||
* Clip all children of a given window out of the visible region
|
* Clip all children of a given window out of the visible region
|
||||||
*/
|
*/
|
||||||
static void clip_children( WND *win, HRGN hrgn, int whole_window )
|
static void clip_children( WND *win, WND *last, HRGN hrgn, int whole_window )
|
||||||
{
|
{
|
||||||
WND *ptr;
|
WND *ptr;
|
||||||
HRGN rectRgn;
|
HRGN rectRgn;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
/* first check if we have anything to do */
|
/* first check if we have anything to do */
|
||||||
for (ptr = win->child; ptr; ptr = ptr->next)
|
for (ptr = win->child; ptr != last; ptr = ptr->next)
|
||||||
if (ptr->dwStyle & WS_VISIBLE) break;
|
if (ptr->dwStyle & WS_VISIBLE) break;
|
||||||
if (!ptr) return; /* no children to clip */
|
if (ptr == last) return; /* no children to clip */
|
||||||
|
|
||||||
if (whole_window)
|
if (whole_window)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +78,7 @@ static void clip_children( WND *win, HRGN hrgn, int whole_window )
|
||||||
else x = y = 0;
|
else x = y = 0;
|
||||||
|
|
||||||
rectRgn = CreateRectRgn( 0, 0, 0, 0 );
|
rectRgn = CreateRectRgn( 0, 0, 0, 0 );
|
||||||
while (ptr)
|
while (ptr != last)
|
||||||
{
|
{
|
||||||
if (ptr->dwStyle & WS_VISIBLE)
|
if (ptr->dwStyle & WS_VISIBLE)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +98,7 @@ static void clip_children( WND *win, HRGN hrgn, int whole_window )
|
||||||
*
|
*
|
||||||
* Compute the visible region of a window
|
* Compute the visible region of a window
|
||||||
*/
|
*/
|
||||||
static HRGN get_visible_region( WND *win, UINT flags )
|
static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode )
|
||||||
{
|
{
|
||||||
HRGN rgn;
|
HRGN rgn;
|
||||||
RECT rect;
|
RECT rect;
|
||||||
|
@ -128,15 +128,30 @@ static HRGN get_visible_region( WND *win, UINT flags )
|
||||||
|
|
||||||
if (!(rgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) return 0;
|
if (!(rgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) return 0;
|
||||||
|
|
||||||
if (flags & DCX_CLIPCHILDREN)
|
if ((flags & DCX_CLIPCHILDREN) && (mode != ClipByChildren))
|
||||||
{
|
{
|
||||||
/* if we are clipping siblings and using the client area,
|
/* we need to clip children by hand */
|
||||||
* X will do the clipping for us; otherwise, we need to
|
clip_children( win, NULL, rgn, (flags & DCX_WINDOW) );
|
||||||
* clip children by hand here
|
|
||||||
*/
|
|
||||||
if ((flags & DCX_WINDOW) || !(flags & DCX_CLIPSIBLINGS))
|
|
||||||
clip_children( win, rgn, (flags & DCX_WINDOW) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (top && top != win) /* need to clip siblings of ancestors */
|
||||||
|
{
|
||||||
|
WND *ptr = win;
|
||||||
|
|
||||||
|
OffsetRgn( rgn, xoffset, yoffset );
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (ptr->dwStyle & WS_CLIPSIBLINGS) clip_children( ptr->parent, ptr, rgn, FALSE );
|
||||||
|
if (ptr == top) break;
|
||||||
|
ptr = ptr->parent;
|
||||||
|
OffsetRgn( rgn, ptr->rectClient.left, ptr->rectClient.top );
|
||||||
|
xoffset += ptr->rectClient.left;
|
||||||
|
yoffset += ptr->rectClient.top;
|
||||||
|
}
|
||||||
|
/* make it relative to the target window again */
|
||||||
|
OffsetRgn( rgn, -xoffset, -yoffset );
|
||||||
|
}
|
||||||
|
|
||||||
return rgn;
|
return rgn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +165,7 @@ static HRGN get_visible_region( WND *win, UINT flags )
|
||||||
BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
|
BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
|
||||||
{
|
{
|
||||||
WND *win = WIN_FindWndPtr( hwnd );
|
WND *win = WIN_FindWndPtr( hwnd );
|
||||||
|
WND *ptr, *top;
|
||||||
X11DRV_WND_DATA *data = win->pDriverData;
|
X11DRV_WND_DATA *data = win->pDriverData;
|
||||||
Drawable drawable;
|
Drawable drawable;
|
||||||
int org_x, org_y, mode = IncludeInferiors;
|
int org_x, org_y, mode = IncludeInferiors;
|
||||||
|
@ -157,7 +173,31 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
|
||||||
/* don't clip siblings if using parent clip region */
|
/* don't clip siblings if using parent clip region */
|
||||||
if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
|
if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
|
||||||
|
|
||||||
if (flags & DCX_CLIPSIBLINGS)
|
/* find the top parent in the hierarchy that isn't clipping siblings */
|
||||||
|
top = NULL;
|
||||||
|
for (ptr = win->parent; ptr && ptr->parent; ptr = ptr->parent)
|
||||||
|
if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) top = ptr;
|
||||||
|
|
||||||
|
if (!top && !(flags & DCX_CLIPSIBLINGS)) top = win;
|
||||||
|
|
||||||
|
if (top)
|
||||||
|
{
|
||||||
|
org_x = org_y = 0;
|
||||||
|
if (flags & DCX_WINDOW)
|
||||||
|
{
|
||||||
|
org_x = win->rectWindow.left - win->rectClient.left;
|
||||||
|
org_y = win->rectWindow.top - win->rectClient.top;
|
||||||
|
}
|
||||||
|
for (ptr = win; ptr != top->parent; ptr = ptr->parent)
|
||||||
|
{
|
||||||
|
org_x += ptr->rectClient.left;
|
||||||
|
org_y += ptr->rectClient.top;
|
||||||
|
}
|
||||||
|
/* have to use the parent so that we include siblings */
|
||||||
|
if (top->parent) drawable = get_client_window( top->parent );
|
||||||
|
else drawable = root_window;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (IsIconic( hwnd ))
|
if (IsIconic( hwnd ))
|
||||||
{
|
{
|
||||||
|
@ -179,22 +219,6 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
|
||||||
if (flags & DCX_CLIPCHILDREN) mode = ClipByChildren; /* can use X11 clipping */
|
if (flags & DCX_CLIPCHILDREN) mode = ClipByChildren; /* can use X11 clipping */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* not clipping siblings -> have to use parent client drawable */
|
|
||||||
if (win->parent) drawable = get_client_window( win->parent );
|
|
||||||
else drawable = root_window;
|
|
||||||
if (flags & DCX_WINDOW)
|
|
||||||
{
|
|
||||||
org_x = win->rectWindow.left;
|
|
||||||
org_y = win->rectWindow.top;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
org_x = win->rectClient.left;
|
|
||||||
org_y = win->rectClient.top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
X11DRV_SetDrawable( hdc, drawable, mode, org_x, org_y );
|
X11DRV_SetDrawable( hdc, drawable, mode, org_x, org_y );
|
||||||
|
|
||||||
|
@ -202,7 +226,7 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
|
||||||
SetHookFlags16( hdc, DCHF_VALIDATEVISRGN )) /* DC was dirty */
|
SetHookFlags16( hdc, DCHF_VALIDATEVISRGN )) /* DC was dirty */
|
||||||
{
|
{
|
||||||
/* need to recompute the visible region */
|
/* need to recompute the visible region */
|
||||||
HRGN visRgn = get_visible_region( win, flags );
|
HRGN visRgn = get_visible_region( win, top, flags, mode );
|
||||||
|
|
||||||
if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
|
if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
|
||||||
CombineRgn( visRgn, visRgn, hrgn, (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
|
CombineRgn( visRgn, visRgn, hrgn, (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
|
||||||
|
|
Loading…
Reference in New Issue