/*
|
/*
|
* Copyright (c) 2000 Greg Haerr <greg@censoft.com>
|
* Copyright (c) 2000 Greg Haerr <greg@censoft.com>
|
* Portions Copyright (c) 1991 David I. Bell
|
* Portions Copyright (c) 1991 David I. Bell
|
* Permission is granted to use, distribute, or modify this source,
|
* Permission is granted to use, distribute, or modify this source,
|
* provided that this copyright notice remains intact.
|
* provided that this copyright notice remains intact.
|
*
|
*
|
* DYNAMICREGIONS MwSetClipWindow
|
* DYNAMICREGIONS MwSetClipWindow
|
*/
|
*/
|
#include "windows.h"
|
#include "windows.h"
|
#include "wintern.h"
|
#include "wintern.h"
|
|
|
/*
|
/*
|
* Set the clip rectangles for a window taking into account other
|
* Set the clip rectangles for a window taking into account other
|
* windows that may be obscuring it. The windows that may be obscuring
|
* windows that may be obscuring it. The windows that may be obscuring
|
* this one are the siblings of each direct ancestor which are higher
|
* this one are the siblings of each direct ancestor which are higher
|
* in priority than those ancestors. Also, each parent limits the visible
|
* in priority than those ancestors. Also, each parent limits the visible
|
* area of the window.
|
* area of the window.
|
*/
|
*/
|
void
|
void
|
MwSetClipWindow(HDC hdc)
|
MwSetClipWindow(HDC hdc)
|
{
|
{
|
HWND wp = hdc->hwnd;
|
HWND wp = hdc->hwnd;
|
HWND pwp; /* parent window */
|
HWND pwp; /* parent window */
|
HWND sibwp; /* sibling windows */
|
HWND sibwp; /* sibling windows */
|
MWCOORD diff; /* difference in coordinates */
|
MWCOORD diff; /* difference in coordinates */
|
PRECT prc; /* client or window rectangle*/
|
PRECT prc; /* client or window rectangle*/
|
MWCLIPREGION *vis, *r;
|
MWCLIPREGION *vis, *r;
|
MWCOORD x, y, width, height;
|
MWCOORD x, y, width, height;
|
|
|
/*
|
/*
|
* Start with the rectangle for the complete window.
|
* Start with the rectangle for the complete window.
|
* We will then cut pieces out of it as needed.
|
* We will then cut pieces out of it as needed.
|
*/
|
*/
|
prc = MwIsClientDC(hdc)? &wp->clirect: &wp->winrect;
|
prc = MwIsClientDC(hdc)? &wp->clirect: &wp->winrect;
|
x = prc->left;
|
x = prc->left;
|
y = prc->top;
|
y = prc->top;
|
width = prc->right - prc->left;
|
width = prc->right - prc->left;
|
height = prc->bottom - prc->top;
|
height = prc->bottom - prc->top;
|
|
|
/*
|
/*
|
* First walk upwards through all parent windows,
|
* First walk upwards through all parent windows,
|
* and restrict the visible part of this window to the part
|
* and restrict the visible part of this window to the part
|
* that shows through all of those parent windows client areas.
|
* that shows through all of those parent windows client areas.
|
*/
|
*/
|
pwp = wp;
|
pwp = wp;
|
while (pwp != rootwp) {
|
while (pwp != rootwp) {
|
pwp = pwp->parent;
|
pwp = pwp->parent;
|
|
|
diff = pwp->clirect.left - x;
|
diff = pwp->clirect.left - x;
|
if (diff > 0) {
|
if (diff > 0) {
|
width -= diff;
|
width -= diff;
|
x = pwp->clirect.left;
|
x = pwp->clirect.left;
|
}
|
}
|
|
|
diff = pwp->clirect.right - (x + width);
|
diff = pwp->clirect.right - (x + width);
|
if (diff < 0)
|
if (diff < 0)
|
width += diff;
|
width += diff;
|
|
|
diff = pwp->clirect.top - y;
|
diff = pwp->clirect.top - y;
|
if (diff > 0) {
|
if (diff > 0) {
|
height -= diff;
|
height -= diff;
|
y = pwp->clirect.top;
|
y = pwp->clirect.top;
|
}
|
}
|
|
|
diff = pwp->clirect.bottom - (y + height);
|
diff = pwp->clirect.bottom - (y + height);
|
if (diff < 0)
|
if (diff < 0)
|
height += diff;
|
height += diff;
|
}
|
}
|
|
|
/*
|
/*
|
* If the window is completely clipped out of view, then
|
* If the window is completely clipped out of view, then
|
* set the clipping region to indicate that.
|
* set the clipping region to indicate that.
|
*/
|
*/
|
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
GdSetClipRegion(hdc->psd, NULL);
|
GdSetClipRegion(hdc->psd, NULL);
|
return;
|
return;
|
}
|
}
|
|
|
/*
|
/*
|
* Allocate initial vis region to parent-clipped size of window
|
* Allocate initial vis region to parent-clipped size of window
|
*/
|
*/
|
vis = GdAllocRectRegion(x, y, x+width, y+height);
|
vis = GdAllocRectRegion(x, y, x+width, y+height);
|
|
|
/*
|
/*
|
* Allocate temp region
|
* Allocate temp region
|
*/
|
*/
|
r = GdAllocRegion();
|
r = GdAllocRegion();
|
|
|
/*
|
/*
|
* Now examine all windows that obscure this window, and
|
* Now examine all windows that obscure this window, and
|
* for each obscuration, break up the clip rectangles into
|
* for each obscuration, break up the clip rectangles into
|
* the smaller pieces that are still visible. The windows
|
* the smaller pieces that are still visible. The windows
|
* that can obscure us are the earlier siblings of all of
|
* that can obscure us are the earlier siblings of all of
|
* our parents. When clipping the root window, search all children.
|
* our parents. When clipping the root window, search all children.
|
*/
|
*/
|
pwp = wp;
|
pwp = wp;
|
while (pwp != NULL) {
|
while (pwp != NULL) {
|
wp = pwp;
|
wp = pwp;
|
pwp = wp->parent;
|
pwp = wp->parent;
|
if(!pwp) {
|
if(!pwp) {
|
/* We're clipping the root window*/
|
/* We're clipping the root window*/
|
if(hdc->flags & DCX_CLIPCHILDREN)
|
if(hdc->flags & DCX_CLIPCHILDREN)
|
/* start with root's children*/
|
/* start with root's children*/
|
sibwp = rootwp->children;
|
sibwp = rootwp->children;
|
else sibwp = NULL; /* no search*/
|
else sibwp = NULL; /* no search*/
|
wp = NULL; /* search all root's children*/
|
wp = NULL; /* search all root's children*/
|
} else {
|
} else {
|
if(hdc->flags & DCX_CLIPSIBLINGS)
|
if(hdc->flags & DCX_CLIPSIBLINGS)
|
sibwp = pwp->children;
|
sibwp = pwp->children;
|
else sibwp = wp; /* no search*/
|
else sibwp = wp; /* no search*/
|
}
|
}
|
for (; sibwp != wp; sibwp = sibwp->siblings) {
|
for (; sibwp != wp; sibwp = sibwp->siblings) {
|
if (sibwp->unmapcount)
|
if (sibwp->unmapcount)
|
continue;
|
continue;
|
|
|
GdSetRectRegionIndirect(r, &sibwp->winrect);
|
GdSetRectRegionIndirect(r, &sibwp->winrect);
|
GdSubtractRegion(vis, vis, r);
|
GdSubtractRegion(vis, vis, r);
|
}
|
}
|
|
|
/* if not clipping the root window, stop when you reach it*/
|
/* if not clipping the root window, stop when you reach it*/
|
if(pwp == rootwp)
|
if(pwp == rootwp)
|
break;
|
break;
|
}
|
}
|
|
|
/*
|
/*
|
* If not the root window and we're going to be drawing
|
* If not the root window and we're going to be drawing
|
* in the client area, clip all children. This is
|
* in the client area, clip all children. This is
|
* required for non-special paint handling for child windows.
|
* required for non-special paint handling for child windows.
|
* Non-client dc's don't clip children in order to get
|
* Non-client dc's don't clip children in order to get
|
* proper border clipping in the case of border-clipped children.
|
* proper border clipping in the case of border-clipped children.
|
*/
|
*/
|
wp = hdc->hwnd;
|
wp = hdc->hwnd;
|
if(wp != rootwp && MwIsClientDC(hdc)) {
|
if(wp != rootwp && MwIsClientDC(hdc)) {
|
for (sibwp=wp->children; sibwp; sibwp = sibwp->siblings) {
|
for (sibwp=wp->children; sibwp; sibwp = sibwp->siblings) {
|
if (sibwp->unmapcount)
|
if (sibwp->unmapcount)
|
continue;
|
continue;
|
|
|
GdSetRectRegionIndirect(r, &sibwp->winrect);
|
GdSetRectRegionIndirect(r, &sibwp->winrect);
|
GdSubtractRegion(vis, vis, r);
|
GdSubtractRegion(vis, vis, r);
|
}
|
}
|
}
|
}
|
|
|
#if UPDATEREGIONS
|
#if UPDATEREGIONS
|
/*
|
/*
|
* Intersect with update region, unless requested not to.
|
* Intersect with update region, unless requested not to.
|
*/
|
*/
|
if(!(hdc->flags & DCX_EXCLUDEUPDATE))
|
if(!(hdc->flags & DCX_EXCLUDEUPDATE))
|
GdIntersectRegion(vis, vis, wp->update);
|
GdIntersectRegion(vis, vis, wp->update);
|
#endif
|
#endif
|
/*
|
/*
|
* Intersect with user region, if set.
|
* Intersect with user region, if set.
|
*/
|
*/
|
if (hdc->region)
|
if (hdc->region)
|
GdIntersectRegion(vis, vis, hdc->region->rgn);
|
GdIntersectRegion(vis, vis, hdc->region->rgn);
|
/*
|
/*
|
* Set the clip region (later destroy handled by GdSetClipRegion)
|
* Set the clip region (later destroy handled by GdSetClipRegion)
|
*/
|
*/
|
GdSetClipRegion(hdc->psd, vis);
|
GdSetClipRegion(hdc->psd, vis);
|
|
|
/*
|
/*
|
* Destroy temp region
|
* Destroy temp region
|
*/
|
*/
|
GdDestroyRegion(r);
|
GdDestroyRegion(r);
|
}
|
}
|
|
|