/*
|
/*
|
* 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 GsSetClipWindow
|
* DYNAMICREGIONS GsSetClipWindow
|
*/
|
*/
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include "serv.h"
|
#include "serv.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. The clipping is not done if it is already up to
|
* area of the window. The clipping is not done if it is already up to
|
* date of if the window is not outputtable.
|
* date of if the window is not outputtable.
|
*/
|
*/
|
void
|
void
|
GsSetClipWindow(GR_WINDOW *wp, MWCLIPREGION *userregion, int flags)
|
GsSetClipWindow(GR_WINDOW *wp, MWCLIPREGION *userregion, int flags)
|
{
|
{
|
GR_WINDOW *orgwp; /* original window pointer */
|
GR_WINDOW *orgwp; /* original window pointer */
|
GR_WINDOW *pwp; /* parent window */
|
GR_WINDOW *pwp; /* parent window */
|
GR_WINDOW *sibwp; /* sibling windows */
|
GR_WINDOW *sibwp; /* sibling windows */
|
GR_COORD minx; /* minimum clip x coordinate */
|
GR_COORD minx; /* minimum clip x coordinate */
|
GR_COORD miny; /* minimum clip y coordinate */
|
GR_COORD miny; /* minimum clip y coordinate */
|
GR_COORD maxx; /* maximum clip x coordinate */
|
GR_COORD maxx; /* maximum clip x coordinate */
|
GR_COORD maxy; /* maximum clip y coordinate */
|
GR_COORD maxy; /* maximum clip y coordinate */
|
GR_COORD diff; /* difference in coordinates */
|
GR_COORD diff; /* difference in coordinates */
|
GR_SIZE bs; /* border size */
|
GR_SIZE bs; /* border size */
|
GR_COORD x, y, width, height;
|
GR_COORD x, y, width, height;
|
MWCLIPREGION *vis, *r;
|
MWCLIPREGION *vis, *r;
|
|
|
if (wp->unmapcount || !wp->output)
|
if (wp->unmapcount || !wp->output)
|
return;
|
return;
|
|
|
clipwp = wp;
|
clipwp = wp;
|
|
|
/*
|
/*
|
* 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.
|
*/
|
*/
|
x = wp->x;
|
x = wp->x;
|
y = wp->y;
|
y = wp->y;
|
width = wp->width;
|
width = wp->width;
|
height = wp->height;
|
height = wp->height;
|
|
|
/*
|
/*
|
* 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.
|
* that shows through all of those parent windows.
|
*/
|
*/
|
pwp = wp;
|
pwp = wp;
|
while (pwp != rootwp) {
|
while (pwp != rootwp) {
|
pwp = pwp->parent;
|
pwp = pwp->parent;
|
|
|
diff = pwp->x - x;
|
diff = pwp->x - x;
|
if (diff > 0) {
|
if (diff > 0) {
|
width -= diff;
|
width -= diff;
|
x = pwp->x;
|
x = pwp->x;
|
}
|
}
|
|
|
diff = (pwp->x + pwp->width) - (x + width);
|
diff = (pwp->x + pwp->width) - (x + width);
|
if (diff < 0)
|
if (diff < 0)
|
width += diff;
|
width += diff;
|
|
|
diff = pwp->y - y;
|
diff = pwp->y - y;
|
if (diff > 0) {
|
if (diff > 0) {
|
height -= diff;
|
height -= diff;
|
y = pwp->y;
|
y = pwp->y;
|
}
|
}
|
|
|
diff = (pwp->y + pwp->height) - (y + height);
|
diff = (pwp->y + pwp->height) - (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(clipwp->psd, NULL);
|
GdSetClipRegion(clipwp->psd, NULL);
|
return;
|
return;
|
}
|
}
|
|
|
/*
|
/*
|
* Allocate region to clipped size of window
|
* Allocate region to 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.
|
* our parents.
|
*/
|
*/
|
orgwp = wp;
|
orgwp = wp;
|
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 (!(flags & GR_MODE_EXCLUDECHILDREN))
|
if (!(flags & GR_MODE_EXCLUDECHILDREN))
|
/* 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 {
|
sibwp = pwp->children; /* clip siblings*/
|
sibwp = pwp->children; /* clip siblings*/
|
}
|
}
|
|
|
for (; sibwp != wp; sibwp = sibwp->siblings) {
|
for (; sibwp != wp; sibwp = sibwp->siblings) {
|
if (sibwp->unmapcount || !sibwp->output)
|
if (sibwp->unmapcount || !sibwp->output)
|
continue;
|
continue;
|
|
|
bs = sibwp->bordersize;
|
bs = sibwp->bordersize;
|
minx = sibwp->x - bs;
|
minx = sibwp->x - bs;
|
miny = sibwp->y - bs;
|
miny = sibwp->y - bs;
|
maxx = sibwp->x + sibwp->width + bs;
|
maxx = sibwp->x + sibwp->width + bs;
|
maxy = sibwp->y + sibwp->height + bs;
|
maxy = sibwp->y + sibwp->height + bs;
|
|
|
GdSetRectRegion(r, minx, miny, maxx, maxy);
|
GdSetRectRegion(r, minx, miny, maxx, maxy);
|
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;
|
}
|
}
|
|
|
wp = orgwp;
|
wp = orgwp;
|
/*
|
/*
|
* If not the root window, clip all children.
|
* If not the root window, clip all children.
|
* (Root window's children are are clipped above)
|
* (Root window's children are are clipped above)
|
*/
|
*/
|
if(wp != rootwp && !(flags & GR_MODE_EXCLUDECHILDREN)) {
|
if(wp != rootwp && !(flags & GR_MODE_EXCLUDECHILDREN)) {
|
for (sibwp=wp->children; sibwp; sibwp = sibwp->siblings) {
|
for (sibwp=wp->children; sibwp; sibwp = sibwp->siblings) {
|
if (sibwp->unmapcount || !sibwp->output)
|
if (sibwp->unmapcount || !sibwp->output)
|
continue;
|
continue;
|
|
|
bs = sibwp->bordersize;
|
bs = sibwp->bordersize;
|
minx = sibwp->x - bs;
|
minx = sibwp->x - bs;
|
miny = sibwp->y - bs;
|
miny = sibwp->y - bs;
|
maxx = sibwp->x + sibwp->width + bs;
|
maxx = sibwp->x + sibwp->width + bs;
|
maxy = sibwp->y + sibwp->height + bs;
|
maxy = sibwp->y + sibwp->height + bs;
|
|
|
GdSetRectRegion(r, minx, miny, maxx, maxy);
|
GdSetRectRegion(r, minx, miny, maxx, maxy);
|
GdSubtractRegion(vis, vis, r);
|
GdSubtractRegion(vis, vis, r);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Intersect with user region, if set.
|
* Intersect with user region, if set.
|
*/
|
*/
|
if (userregion) {
|
if (userregion) {
|
/* temporarily offset region by window coordinates*/
|
/* temporarily offset region by window coordinates*/
|
GdOffsetRegion(userregion, wp->x, wp->y);
|
GdOffsetRegion(userregion, wp->x, wp->y);
|
GdIntersectRegion(vis, vis, userregion);
|
GdIntersectRegion(vis, vis, userregion);
|
GdOffsetRegion(userregion, -wp->x, -wp->y);
|
GdOffsetRegion(userregion, -wp->x, -wp->y);
|
}
|
}
|
|
|
/*
|
/*
|
* Set the clip region (later destroy handled by GdSetClipRegion)
|
* Set the clip region (later destroy handled by GdSetClipRegion)
|
*/
|
*/
|
GdSetClipRegion(clipwp->psd, vis);
|
GdSetClipRegion(clipwp->psd, vis);
|
|
|
/*
|
/*
|
* Destroy temp region
|
* Destroy temp region
|
*/
|
*/
|
GdDestroyRegion(r);
|
GdDestroyRegion(r);
|
}
|
}
|
|
|