809 lines
26 KiB
C
809 lines
26 KiB
C
|
|
||
|
/***********************************************************
|
||
|
|
||
|
Copyright 1987, 1998 The Open Group
|
||
|
|
||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||
|
documentation for any purpose is hereby granted without fee, provided that
|
||
|
the above copyright notice appear in all copies and that both that
|
||
|
copyright notice and this permission notice appear in supporting
|
||
|
documentation.
|
||
|
|
||
|
The above copyright notice and this permission notice shall be included in
|
||
|
all copies or substantial portions of the Software.
|
||
|
|
||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
|
||
|
Except as contained in this notice, the name of The Open Group shall not be
|
||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||
|
in this Software without prior written authorization from The Open Group.
|
||
|
|
||
|
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
|
||
|
|
||
|
All Rights Reserved
|
||
|
|
||
|
Permission to use, copy, modify, and distribute this software and its
|
||
|
documentation for any purpose and without fee is hereby granted,
|
||
|
provided that the above copyright notice appear in all copies and that
|
||
|
both that copyright notice and this permission notice appear in
|
||
|
supporting documentation, and that the name of Digital not be
|
||
|
used in advertising or publicity pertaining to distribution of the
|
||
|
software without specific, written prior permission.
|
||
|
|
||
|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
||
|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||
|
SOFTWARE.
|
||
|
|
||
|
******************************************************************/
|
||
|
#ifdef HAVE_DIX_CONFIG_H
|
||
|
#include <dix-config.h>
|
||
|
#endif
|
||
|
|
||
|
#include <X11/X.h>
|
||
|
#include <X11/extensions/shapeconst.h>
|
||
|
#include "regionstr.h"
|
||
|
#include "region.h"
|
||
|
#include "mi.h"
|
||
|
#include "windowstr.h"
|
||
|
#include "scrnintstr.h"
|
||
|
#include "pixmapstr.h"
|
||
|
#include "mivalidate.h"
|
||
|
#include "inputstr.h"
|
||
|
|
||
|
void
|
||
|
miClearToBackground(WindowPtr pWin,
|
||
|
int x, int y, int w, int h, Bool generateExposures)
|
||
|
{
|
||
|
BoxRec box;
|
||
|
RegionRec reg;
|
||
|
BoxPtr extents;
|
||
|
int x1, y1, x2, y2;
|
||
|
|
||
|
/* compute everything using ints to avoid overflow */
|
||
|
|
||
|
x1 = pWin->drawable.x + x;
|
||
|
y1 = pWin->drawable.y + y;
|
||
|
if (w)
|
||
|
x2 = x1 + (int) w;
|
||
|
else
|
||
|
x2 = x1 + (int) pWin->drawable.width - (int) x;
|
||
|
if (h)
|
||
|
y2 = y1 + h;
|
||
|
else
|
||
|
y2 = y1 + (int) pWin->drawable.height - (int) y;
|
||
|
|
||
|
extents = &pWin->clipList.extents;
|
||
|
|
||
|
/* clip the resulting rectangle to the window clipList extents. This
|
||
|
* makes sure that the result will fit in a box, given that the
|
||
|
* screen is < 32768 on a side.
|
||
|
*/
|
||
|
|
||
|
if (x1 < extents->x1)
|
||
|
x1 = extents->x1;
|
||
|
if (x2 > extents->x2)
|
||
|
x2 = extents->x2;
|
||
|
if (y1 < extents->y1)
|
||
|
y1 = extents->y1;
|
||
|
if (y2 > extents->y2)
|
||
|
y2 = extents->y2;
|
||
|
|
||
|
if (x2 <= x1 || y2 <= y1) {
|
||
|
x2 = x1 = 0;
|
||
|
y2 = y1 = 0;
|
||
|
}
|
||
|
|
||
|
box.x1 = x1;
|
||
|
box.x2 = x2;
|
||
|
box.y1 = y1;
|
||
|
box.y2 = y2;
|
||
|
|
||
|
RegionInit(®, &box, 1);
|
||
|
|
||
|
RegionIntersect(®, ®, &pWin->clipList);
|
||
|
if (generateExposures)
|
||
|
(*pWin->drawable.pScreen->WindowExposures) (pWin, ®);
|
||
|
else if (pWin->backgroundState != None)
|
||
|
pWin->drawable.pScreen->PaintWindow(pWin, ®, PW_BACKGROUND);
|
||
|
RegionUninit(®);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
miMarkWindow(WindowPtr pWin)
|
||
|
{
|
||
|
ValidatePtr val;
|
||
|
|
||
|
if (pWin->valdata)
|
||
|
return;
|
||
|
val = (ValidatePtr) xnfalloc(sizeof(ValidateRec));
|
||
|
val->before.oldAbsCorner.x = pWin->drawable.x;
|
||
|
val->before.oldAbsCorner.y = pWin->drawable.y;
|
||
|
val->before.borderVisible = NullRegion;
|
||
|
val->before.resized = FALSE;
|
||
|
pWin->valdata = val;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
|
||
|
{
|
||
|
BoxPtr box;
|
||
|
WindowPtr pChild, pLast;
|
||
|
Bool anyMarked = FALSE;
|
||
|
MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow;
|
||
|
|
||
|
/* single layered systems are easy */
|
||
|
if (ppLayerWin)
|
||
|
*ppLayerWin = pWin;
|
||
|
|
||
|
if (pWin == pFirst) {
|
||
|
/* Blindly mark pWin and all of its inferiors. This is a slight
|
||
|
* overkill if there are mapped windows that outside pWin's border,
|
||
|
* but it's better than wasting time on RectIn checks.
|
||
|
*/
|
||
|
pChild = pWin;
|
||
|
while (1) {
|
||
|
if (pChild->viewable) {
|
||
|
if (RegionBroken(&pChild->winSize))
|
||
|
SetWinSize(pChild);
|
||
|
if (RegionBroken(&pChild->borderSize))
|
||
|
SetBorderSize(pChild);
|
||
|
(*MarkWindow) (pChild);
|
||
|
if (pChild->firstChild) {
|
||
|
pChild = pChild->firstChild;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
while (!pChild->nextSib && (pChild != pWin))
|
||
|
pChild = pChild->parent;
|
||
|
if (pChild == pWin)
|
||
|
break;
|
||
|
pChild = pChild->nextSib;
|
||
|
}
|
||
|
anyMarked = TRUE;
|
||
|
pFirst = pFirst->nextSib;
|
||
|
}
|
||
|
if ((pChild = pFirst)) {
|
||
|
box = RegionExtents(&pWin->borderSize);
|
||
|
pLast = pChild->parent->lastChild;
|
||
|
while (1) {
|
||
|
if (pChild->viewable) {
|
||
|
if (RegionBroken(&pChild->winSize))
|
||
|
SetWinSize(pChild);
|
||
|
if (RegionBroken(&pChild->borderSize))
|
||
|
SetBorderSize(pChild);
|
||
|
if (RegionContainsRect(&pChild->borderSize, box)) {
|
||
|
(*MarkWindow) (pChild);
|
||
|
anyMarked = TRUE;
|
||
|
if (pChild->firstChild) {
|
||
|
pChild = pChild->firstChild;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (!pChild->nextSib && (pChild != pLast))
|
||
|
pChild = pChild->parent;
|
||
|
if (pChild == pLast)
|
||
|
break;
|
||
|
pChild = pChild->nextSib;
|
||
|
}
|
||
|
}
|
||
|
if (anyMarked)
|
||
|
(*MarkWindow) (pWin->parent);
|
||
|
return anyMarked;
|
||
|
}
|
||
|
|
||
|
/*****
|
||
|
* miHandleValidateExposures(pWin)
|
||
|
* starting at pWin, draw background in any windows that have exposure
|
||
|
* regions, translate the regions, restore any backing store,
|
||
|
* and then send any regions still exposed to the client
|
||
|
*****/
|
||
|
void
|
||
|
miHandleValidateExposures(WindowPtr pWin)
|
||
|
{
|
||
|
WindowPtr pChild;
|
||
|
ValidatePtr val;
|
||
|
WindowExposuresProcPtr WindowExposures;
|
||
|
|
||
|
pChild = pWin;
|
||
|
WindowExposures = pChild->drawable.pScreen->WindowExposures;
|
||
|
while (1) {
|
||
|
if ((val = pChild->valdata)) {
|
||
|
if (RegionNotEmpty(&val->after.borderExposed))
|
||
|
pWin->drawable.pScreen->PaintWindow(pChild,
|
||
|
&val->after.borderExposed,
|
||
|
PW_BORDER);
|
||
|
RegionUninit(&val->after.borderExposed);
|
||
|
(*WindowExposures) (pChild, &val->after.exposed);
|
||
|
RegionUninit(&val->after.exposed);
|
||
|
free(val);
|
||
|
pChild->valdata = NULL;
|
||
|
if (pChild->firstChild) {
|
||
|
pChild = pChild->firstChild;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
while (!pChild->nextSib && (pChild != pWin))
|
||
|
pChild = pChild->parent;
|
||
|
if (pChild == pWin)
|
||
|
break;
|
||
|
pChild = pChild->nextSib;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
|
||
|
{
|
||
|
WindowPtr pParent;
|
||
|
Bool WasViewable = (Bool) (pWin->viewable);
|
||
|
short bw;
|
||
|
RegionPtr oldRegion = NULL;
|
||
|
DDXPointRec oldpt;
|
||
|
Bool anyMarked = FALSE;
|
||
|
ScreenPtr pScreen;
|
||
|
WindowPtr windowToValidate;
|
||
|
WindowPtr pLayerWin;
|
||
|
|
||
|
/* if this is a root window, can't be moved */
|
||
|
if (!(pParent = pWin->parent))
|
||
|
return;
|
||
|
pScreen = pWin->drawable.pScreen;
|
||
|
bw = wBorderWidth(pWin);
|
||
|
|
||
|
oldpt.x = pWin->drawable.x;
|
||
|
oldpt.y = pWin->drawable.y;
|
||
|
if (WasViewable) {
|
||
|
oldRegion = RegionCreate(NullBox, 1);
|
||
|
RegionCopy(oldRegion, &pWin->borderClip);
|
||
|
anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
|
||
|
}
|
||
|
pWin->origin.x = x + (int) bw;
|
||
|
pWin->origin.y = y + (int) bw;
|
||
|
x = pWin->drawable.x = pParent->drawable.x + x + (int) bw;
|
||
|
y = pWin->drawable.y = pParent->drawable.y + y + (int) bw;
|
||
|
|
||
|
SetWinSize(pWin);
|
||
|
SetBorderSize(pWin);
|
||
|
|
||
|
(*pScreen->PositionWindow) (pWin, x, y);
|
||
|
|
||
|
windowToValidate = MoveWindowInStack(pWin, pNextSib);
|
||
|
|
||
|
ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
|
||
|
|
||
|
if (WasViewable) {
|
||
|
if (pLayerWin == pWin)
|
||
|
anyMarked |= (*pScreen->MarkOverlappedWindows)
|
||
|
(pWin, windowToValidate, NULL);
|
||
|
else
|
||
|
anyMarked |= (*pScreen->MarkOverlappedWindows)
|
||
|
(pWin, pLayerWin, NULL);
|
||
|
|
||
|
if (anyMarked) {
|
||
|
(*pScreen->ValidateTree) (pLayerWin->parent, NullWindow, kind);
|
||
|
(*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, oldRegion);
|
||
|
RegionDestroy(oldRegion);
|
||
|
/* XXX need to retile border if ParentRelative origin */
|
||
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
||
|
if (pScreen->PostValidateTree)
|
||
|
(*pScreen->PostValidateTree) (pLayerWin->parent, NULL, kind);
|
||
|
}
|
||
|
}
|
||
|
if (pWin->realized)
|
||
|
WindowsRestructured();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* pValid is a region of the screen which has been
|
||
|
* successfully copied -- recomputed exposed regions for affected windows
|
||
|
*/
|
||
|
|
||
|
static int
|
||
|
miRecomputeExposures(WindowPtr pWin, void *value)
|
||
|
{ /* must conform to VisitWindowProcPtr */
|
||
|
RegionPtr pValid = (RegionPtr) value;
|
||
|
|
||
|
if (pWin->valdata) {
|
||
|
#ifdef COMPOSITE
|
||
|
/*
|
||
|
* Redirected windows are not affected by parent window
|
||
|
* gravity manipulations, so don't recompute their
|
||
|
* exposed areas here.
|
||
|
*/
|
||
|
if (pWin->redirectDraw != RedirectDrawNone)
|
||
|
return WT_DONTWALKCHILDREN;
|
||
|
#endif
|
||
|
/*
|
||
|
* compute exposed regions of this window
|
||
|
*/
|
||
|
RegionSubtract(&pWin->valdata->after.exposed, &pWin->clipList, pValid);
|
||
|
/*
|
||
|
* compute exposed regions of the border
|
||
|
*/
|
||
|
RegionSubtract(&pWin->valdata->after.borderExposed,
|
||
|
&pWin->borderClip, &pWin->winSize);
|
||
|
RegionSubtract(&pWin->valdata->after.borderExposed,
|
||
|
&pWin->valdata->after.borderExposed, pValid);
|
||
|
return WT_WALKCHILDREN;
|
||
|
}
|
||
|
return WT_NOMATCH;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
miResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h,
|
||
|
WindowPtr pSib)
|
||
|
{
|
||
|
WindowPtr pParent;
|
||
|
Bool WasViewable = (Bool) (pWin->viewable);
|
||
|
unsigned short width = pWin->drawable.width, height = pWin->drawable.height;
|
||
|
short oldx = pWin->drawable.x, oldy = pWin->drawable.y;
|
||
|
int bw = wBorderWidth(pWin);
|
||
|
short dw, dh;
|
||
|
DDXPointRec oldpt;
|
||
|
RegionPtr oldRegion = NULL;
|
||
|
Bool anyMarked = FALSE;
|
||
|
ScreenPtr pScreen;
|
||
|
WindowPtr pFirstChange;
|
||
|
WindowPtr pChild;
|
||
|
RegionPtr gravitate[StaticGravity + 1];
|
||
|
unsigned g;
|
||
|
int nx, ny; /* destination x,y */
|
||
|
int newx, newy; /* new inner window position */
|
||
|
RegionPtr pRegion = NULL;
|
||
|
RegionPtr destClip; /* portions of destination already written */
|
||
|
RegionPtr oldWinClip = NULL; /* old clip list for window */
|
||
|
RegionPtr borderVisible = NullRegion; /* visible area of the border */
|
||
|
Bool shrunk = FALSE; /* shrunk in an inner dimension */
|
||
|
Bool moved = FALSE; /* window position changed */
|
||
|
WindowPtr pLayerWin;
|
||
|
|
||
|
/* if this is a root window, can't be resized */
|
||
|
if (!(pParent = pWin->parent))
|
||
|
return;
|
||
|
|
||
|
pScreen = pWin->drawable.pScreen;
|
||
|
newx = pParent->drawable.x + x + bw;
|
||
|
newy = pParent->drawable.y + y + bw;
|
||
|
if (WasViewable) {
|
||
|
anyMarked = FALSE;
|
||
|
/*
|
||
|
* save the visible region of the window
|
||
|
*/
|
||
|
oldRegion = RegionCreate(NullBox, 1);
|
||
|
RegionCopy(oldRegion, &pWin->winSize);
|
||
|
|
||
|
/*
|
||
|
* categorize child windows into regions to be moved
|
||
|
*/
|
||
|
for (g = 0; g <= StaticGravity; g++)
|
||
|
gravitate[g] = (RegionPtr) NULL;
|
||
|
for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
|
||
|
g = pChild->winGravity;
|
||
|
if (g != UnmapGravity) {
|
||
|
if (!gravitate[g])
|
||
|
gravitate[g] = RegionCreate(NullBox, 1);
|
||
|
RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip);
|
||
|
}
|
||
|
else {
|
||
|
UnmapWindow(pChild, TRUE);
|
||
|
anyMarked = TRUE;
|
||
|
}
|
||
|
}
|
||
|
anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
|
||
|
|
||
|
oldWinClip = NULL;
|
||
|
if (pWin->bitGravity != ForgetGravity) {
|
||
|
oldWinClip = RegionCreate(NullBox, 1);
|
||
|
RegionCopy(oldWinClip, &pWin->clipList);
|
||
|
}
|
||
|
/*
|
||
|
* if the window is changing size, borderExposed
|
||
|
* can't be computed correctly without some help.
|
||
|
*/
|
||
|
if (pWin->drawable.height > h || pWin->drawable.width > w)
|
||
|
shrunk = TRUE;
|
||
|
|
||
|
if (newx != oldx || newy != oldy)
|
||
|
moved = TRUE;
|
||
|
|
||
|
if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
|
||
|
HasBorder(pWin)) {
|
||
|
borderVisible = RegionCreate(NullBox, 1);
|
||
|
/* for tiled borders, we punt and draw the whole thing */
|
||
|
if (pWin->borderIsPixel || !moved) {
|
||
|
if (shrunk || moved)
|
||
|
RegionSubtract(borderVisible,
|
||
|
&pWin->borderClip, &pWin->winSize);
|
||
|
else
|
||
|
RegionCopy(borderVisible, &pWin->borderClip);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
pWin->origin.x = x + bw;
|
||
|
pWin->origin.y = y + bw;
|
||
|
pWin->drawable.height = h;
|
||
|
pWin->drawable.width = w;
|
||
|
|
||
|
x = pWin->drawable.x = newx;
|
||
|
y = pWin->drawable.y = newy;
|
||
|
|
||
|
SetWinSize(pWin);
|
||
|
SetBorderSize(pWin);
|
||
|
|
||
|
dw = (int) w - (int) width;
|
||
|
dh = (int) h - (int) height;
|
||
|
ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
|
||
|
|
||
|
/* let the hardware adjust background and border pixmaps, if any */
|
||
|
(*pScreen->PositionWindow) (pWin, x, y);
|
||
|
|
||
|
pFirstChange = MoveWindowInStack(pWin, pSib);
|
||
|
|
||
|
if (WasViewable) {
|
||
|
pRegion = RegionCreate(NullBox, 1);
|
||
|
|
||
|
if (pLayerWin == pWin)
|
||
|
anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange,
|
||
|
NULL);
|
||
|
else
|
||
|
anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin,
|
||
|
NULL);
|
||
|
|
||
|
if (pWin->valdata) {
|
||
|
pWin->valdata->before.resized = TRUE;
|
||
|
pWin->valdata->before.borderVisible = borderVisible;
|
||
|
}
|
||
|
|
||
|
if (anyMarked)
|
||
|
(*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, VTOther);
|
||
|
/*
|
||
|
* the entire window is trashed unless bitGravity
|
||
|
* recovers portions of it
|
||
|
*/
|
||
|
RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
|
||
|
}
|
||
|
|
||
|
GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
|
||
|
|
||
|
if (WasViewable) {
|
||
|
/* avoid the border */
|
||
|
if (HasBorder(pWin)) {
|
||
|
int offx, offy, dx, dy;
|
||
|
|
||
|
/* kruft to avoid double translates for each gravity */
|
||
|
offx = 0;
|
||
|
offy = 0;
|
||
|
for (g = 0; g <= StaticGravity; g++) {
|
||
|
if (!gravitate[g])
|
||
|
continue;
|
||
|
|
||
|
/* align winSize to gravitate[g].
|
||
|
* winSize is in new coordinates,
|
||
|
* gravitate[g] is still in old coordinates */
|
||
|
GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);
|
||
|
|
||
|
dx = (oldx - nx) - offx;
|
||
|
dy = (oldy - ny) - offy;
|
||
|
if (dx || dy) {
|
||
|
RegionTranslate(&pWin->winSize, dx, dy);
|
||
|
offx += dx;
|
||
|
offy += dy;
|
||
|
}
|
||
|
RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize);
|
||
|
}
|
||
|
/* get winSize back where it belongs */
|
||
|
if (offx || offy)
|
||
|
RegionTranslate(&pWin->winSize, -offx, -offy);
|
||
|
}
|
||
|
/*
|
||
|
* add screen bits to the appropriate bucket
|
||
|
*/
|
||
|
|
||
|
if (oldWinClip) {
|
||
|
/*
|
||
|
* clip to new clipList
|
||
|
*/
|
||
|
RegionCopy(pRegion, oldWinClip);
|
||
|
RegionTranslate(pRegion, nx - oldx, ny - oldy);
|
||
|
RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
|
||
|
/*
|
||
|
* don't step on any gravity bits which will be copied after this
|
||
|
* region. Note -- this assumes that the regions will be copied
|
||
|
* in gravity order.
|
||
|
*/
|
||
|
for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
|
||
|
if (gravitate[g])
|
||
|
RegionSubtract(oldWinClip, oldWinClip, gravitate[g]);
|
||
|
}
|
||
|
RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
|
||
|
g = pWin->bitGravity;
|
||
|
if (!gravitate[g])
|
||
|
gravitate[g] = oldWinClip;
|
||
|
else {
|
||
|
RegionUnion(gravitate[g], gravitate[g], oldWinClip);
|
||
|
RegionDestroy(oldWinClip);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* move the bits on the screen
|
||
|
*/
|
||
|
|
||
|
destClip = NULL;
|
||
|
|
||
|
for (g = 0; g <= StaticGravity; g++) {
|
||
|
if (!gravitate[g])
|
||
|
continue;
|
||
|
|
||
|
GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);
|
||
|
|
||
|
oldpt.x = oldx + (x - nx);
|
||
|
oldpt.y = oldy + (y - ny);
|
||
|
|
||
|
/* Note that gravitate[g] is *translated* by CopyWindow */
|
||
|
|
||
|
/* only copy the remaining useful bits */
|
||
|
|
||
|
RegionIntersect(gravitate[g], gravitate[g], oldRegion);
|
||
|
|
||
|
/* clip to not overwrite already copied areas */
|
||
|
|
||
|
if (destClip) {
|
||
|
RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
|
||
|
RegionSubtract(gravitate[g], gravitate[g], destClip);
|
||
|
RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
|
||
|
}
|
||
|
|
||
|
/* and move those bits */
|
||
|
|
||
|
if (oldpt.x != x || oldpt.y != y
|
||
|
#ifdef COMPOSITE
|
||
|
|| pWin->redirectDraw
|
||
|
#endif
|
||
|
) {
|
||
|
(*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt,
|
||
|
gravitate[g]);
|
||
|
}
|
||
|
|
||
|
/* remove any overwritten bits from the remaining useful bits */
|
||
|
|
||
|
RegionSubtract(oldRegion, oldRegion, gravitate[g]);
|
||
|
|
||
|
/*
|
||
|
* recompute exposed regions of child windows
|
||
|
*/
|
||
|
|
||
|
for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
|
||
|
if (pChild->winGravity != g)
|
||
|
continue;
|
||
|
RegionIntersect(pRegion, &pChild->borderClip, gravitate[g]);
|
||
|
TraverseTree(pChild, miRecomputeExposures, (void *) pRegion);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* remove the successfully copied regions of the
|
||
|
* window from its exposed region
|
||
|
*/
|
||
|
|
||
|
if (g == pWin->bitGravity)
|
||
|
RegionSubtract(&pWin->valdata->after.exposed,
|
||
|
&pWin->valdata->after.exposed, gravitate[g]);
|
||
|
if (!destClip)
|
||
|
destClip = gravitate[g];
|
||
|
else {
|
||
|
RegionUnion(destClip, destClip, gravitate[g]);
|
||
|
RegionDestroy(gravitate[g]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegionDestroy(oldRegion);
|
||
|
RegionDestroy(pRegion);
|
||
|
if (destClip)
|
||
|
RegionDestroy(destClip);
|
||
|
if (anyMarked) {
|
||
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
||
|
if (pScreen->PostValidateTree)
|
||
|
(*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange,
|
||
|
VTOther);
|
||
|
}
|
||
|
}
|
||
|
if (pWin->realized)
|
||
|
WindowsRestructured();
|
||
|
}
|
||
|
|
||
|
WindowPtr
|
||
|
miGetLayerWindow(WindowPtr pWin)
|
||
|
{
|
||
|
return pWin->firstChild;
|
||
|
}
|
||
|
|
||
|
/******
|
||
|
*
|
||
|
* miSetShape
|
||
|
* The border/window shape has changed. Recompute winSize/borderSize
|
||
|
* and send appropriate exposure events
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
miSetShape(WindowPtr pWin, int kind)
|
||
|
{
|
||
|
Bool WasViewable = (Bool) (pWin->viewable);
|
||
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
||
|
Bool anyMarked = FALSE;
|
||
|
WindowPtr pLayerWin;
|
||
|
|
||
|
if (kind != ShapeInput) {
|
||
|
if (WasViewable) {
|
||
|
anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
|
||
|
&pLayerWin);
|
||
|
if (pWin->valdata) {
|
||
|
if (HasBorder(pWin)) {
|
||
|
RegionPtr borderVisible;
|
||
|
|
||
|
borderVisible = RegionCreate(NullBox, 1);
|
||
|
RegionSubtract(borderVisible,
|
||
|
&pWin->borderClip, &pWin->winSize);
|
||
|
pWin->valdata->before.borderVisible = borderVisible;
|
||
|
}
|
||
|
pWin->valdata->before.resized = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetWinSize(pWin);
|
||
|
SetBorderSize(pWin);
|
||
|
|
||
|
ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
|
||
|
|
||
|
if (WasViewable) {
|
||
|
anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
|
||
|
|
||
|
if (anyMarked) {
|
||
|
(*pScreen->ValidateTree) (pLayerWin->parent, NullWindow,
|
||
|
VTOther);
|
||
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
||
|
if (pScreen->PostValidateTree)
|
||
|
(*pScreen->PostValidateTree) (pLayerWin->parent, NULL,
|
||
|
VTOther);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (pWin->realized)
|
||
|
WindowsRestructured();
|
||
|
CheckCursorConfinement(pWin);
|
||
|
}
|
||
|
|
||
|
/* Keeps the same inside(!) origin */
|
||
|
|
||
|
void
|
||
|
miChangeBorderWidth(WindowPtr pWin, unsigned int width)
|
||
|
{
|
||
|
int oldwidth;
|
||
|
Bool anyMarked = FALSE;
|
||
|
ScreenPtr pScreen;
|
||
|
Bool WasViewable = (Bool) (pWin->viewable);
|
||
|
Bool HadBorder;
|
||
|
WindowPtr pLayerWin;
|
||
|
|
||
|
oldwidth = wBorderWidth(pWin);
|
||
|
if (oldwidth == width)
|
||
|
return;
|
||
|
HadBorder = HasBorder(pWin);
|
||
|
pScreen = pWin->drawable.pScreen;
|
||
|
if (WasViewable && width < oldwidth)
|
||
|
anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
|
||
|
|
||
|
pWin->borderWidth = width;
|
||
|
SetBorderSize(pWin);
|
||
|
|
||
|
if (WasViewable) {
|
||
|
if (width > oldwidth) {
|
||
|
anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
|
||
|
&pLayerWin);
|
||
|
/*
|
||
|
* save the old border visible region to correctly compute
|
||
|
* borderExposed.
|
||
|
*/
|
||
|
if (pWin->valdata && HadBorder) {
|
||
|
RegionPtr borderVisible;
|
||
|
|
||
|
borderVisible = RegionCreate(NULL, 1);
|
||
|
RegionSubtract(borderVisible,
|
||
|
&pWin->borderClip, &pWin->winSize);
|
||
|
pWin->valdata->before.borderVisible = borderVisible;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (anyMarked) {
|
||
|
(*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
|
||
|
(*pScreen->HandleExposures) (pLayerWin->parent);
|
||
|
if (pScreen->PostValidateTree)
|
||
|
(*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin,
|
||
|
VTOther);
|
||
|
}
|
||
|
}
|
||
|
if (pWin->realized)
|
||
|
WindowsRestructured();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure)
|
||
|
{
|
||
|
if ((pChild != pWin) || fromConfigure) {
|
||
|
RegionEmpty(&pChild->clipList);
|
||
|
if (pChild->drawable.pScreen->ClipNotify)
|
||
|
(*pChild->drawable.pScreen->ClipNotify) (pChild, 0, 0);
|
||
|
RegionEmpty(&pChild->borderClip);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WindowPtr
|
||
|
miSpriteTrace(SpritePtr pSprite, int x, int y)
|
||
|
{
|
||
|
WindowPtr pWin;
|
||
|
BoxRec box;
|
||
|
|
||
|
pWin = DeepestSpriteWin(pSprite)->firstChild;
|
||
|
while (pWin) {
|
||
|
if ((pWin->mapped) &&
|
||
|
(x >= pWin->drawable.x - wBorderWidth(pWin)) &&
|
||
|
(x < pWin->drawable.x + (int) pWin->drawable.width +
|
||
|
wBorderWidth(pWin)) &&
|
||
|
(y >= pWin->drawable.y - wBorderWidth(pWin)) &&
|
||
|
(y < pWin->drawable.y + (int) pWin->drawable.height +
|
||
|
wBorderWidth(pWin))
|
||
|
/* When a window is shaped, a further check
|
||
|
* is made to see if the point is inside
|
||
|
* borderSize
|
||
|
*/
|
||
|
&& (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
|
||
|
&& (!wInputShape(pWin) ||
|
||
|
RegionContainsPoint(wInputShape(pWin),
|
||
|
x - pWin->drawable.x,
|
||
|
y - pWin->drawable.y, &box))
|
||
|
/* In rootless mode windows may be offscreen, even when
|
||
|
* they're in X's stack. (E.g. if the native window system
|
||
|
* implements some form of virtual desktop system).
|
||
|
*/
|
||
|
&& !pWin->unhittable) {
|
||
|
if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
|
||
|
pSprite->spriteTraceSize += 10;
|
||
|
pSprite->spriteTrace = reallocarray(pSprite->spriteTrace,
|
||
|
pSprite->spriteTraceSize,
|
||
|
sizeof(WindowPtr));
|
||
|
}
|
||
|
pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
|
||
|
pWin = pWin->firstChild;
|
||
|
}
|
||
|
else
|
||
|
pWin = pWin->nextSib;
|
||
|
}
|
||
|
return DeepestSpriteWin(pSprite);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Traversed from the root window to the window at the position x/y. While
|
||
|
* traversing, it sets up the traversal history in the spriteTrace array.
|
||
|
* After completing, the spriteTrace history is set in the following way:
|
||
|
* spriteTrace[0] ... root window
|
||
|
* spriteTrace[1] ... top level window that encloses x/y
|
||
|
* ...
|
||
|
* spriteTrace[spriteTraceGood - 1] ... window at x/y
|
||
|
*
|
||
|
* @returns the window at the given coordinates.
|
||
|
*/
|
||
|
WindowPtr
|
||
|
miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y)
|
||
|
{
|
||
|
pSprite->spriteTraceGood = 1; /* root window still there */
|
||
|
return miSpriteTrace(pSprite, x, y);
|
||
|
}
|