Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xnest / Window.c
blobf87a1baa79f88edeb1e72ed10dcb68098f8cc69a
1 /*
3 Copyright 1993 by Davor Matic
5 Permission to use, copy, modify, distribute, and sell this software
6 and its documentation for any purpose is hereby granted without fee,
7 provided that the above copyright notice appear in all copies and that
8 both that copyright notice and this permission notice appear in
9 supporting documentation. Davor Matic makes no representations about
10 the suitability of this software for any purpose. It is provided "as
11 is" without express or implied warranty.
15 #ifdef HAVE_XNEST_CONFIG_H
16 #include <xnest-config.h>
17 #endif
19 #include <X11/X.h>
20 #include <X11/Xproto.h>
21 #include "gcstruct.h"
22 #include "window.h"
23 #include "windowstr.h"
24 #include "pixmapstr.h"
25 #include "colormapst.h"
26 #include "scrnintstr.h"
27 #include "region.h"
29 #include "mi.h"
31 #include "Xnest.h"
33 #include "Display.h"
34 #include "Screen.h"
35 #include "XNGC.h"
36 #include "Drawable.h"
37 #include "Color.h"
38 #include "Visual.h"
39 #include "Events.h"
40 #include "Args.h"
42 int xnestWindowPrivateIndex;
44 static int
45 xnestFindWindowMatch(WindowPtr pWin, pointer ptr)
47 xnestWindowMatch *wm = (xnestWindowMatch *)ptr;
48 if (wm->window == xnestWindow(pWin)) {
49 wm->pWin = pWin;
50 return WT_STOPWALKING;
52 else
53 return WT_WALKCHILDREN;
56 WindowPtr
57 xnestWindowPtr(Window window)
59 xnestWindowMatch wm;
60 int i;
62 wm.pWin = NullWindow;
63 wm.window = window;
65 for (i = 0; i < xnestNumScreens; i++) {
66 WalkTree(screenInfo.screens[i], xnestFindWindowMatch, (pointer) &wm);
67 if (wm.pWin) break;
70 return wm.pWin;
73 Bool
74 xnestCreateWindow(WindowPtr pWin)
76 unsigned long mask;
77 XSetWindowAttributes attributes;
78 Visual *visual;
79 ColormapPtr pCmap;
81 if (pWin->drawable.class == InputOnly) {
82 mask = 0L;
83 visual = CopyFromParent;
85 else {
86 mask = CWEventMask | CWBackingStore;
87 attributes.event_mask = ExposureMask;
88 attributes.backing_store = NotUseful;
90 if (pWin->parent) {
91 if (pWin->optional && pWin->optional->visual != wVisual(pWin->parent)) {
92 visual = xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
93 mask |= CWColormap;
94 if (pWin->optional->colormap) {
95 pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
96 attributes.colormap = xnestColormap(pCmap);
98 else
99 attributes.colormap = xnestDefaultVisualColormap(visual);
101 else
102 visual = CopyFromParent;
104 else { /* root windows have their own colormaps at creation time */
105 visual = xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
106 pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
107 mask |= CWColormap;
108 attributes.colormap = xnestColormap(pCmap);
112 xnestWindowPriv(pWin)->window = XCreateWindow(xnestDisplay,
113 xnestWindowParent(pWin),
114 pWin->origin.x -
115 wBorderWidth(pWin),
116 pWin->origin.y -
117 wBorderWidth(pWin),
118 pWin->drawable.width,
119 pWin->drawable.height,
120 pWin->borderWidth,
121 pWin->drawable.depth,
122 pWin->drawable.class,
123 visual,
124 mask, &attributes);
125 xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin);
126 xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
127 xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
128 xnestWindowPriv(pWin)->width = pWin->drawable.width;
129 xnestWindowPriv(pWin)->height = pWin->drawable.height;
130 xnestWindowPriv(pWin)->border_width = pWin->borderWidth;
131 xnestWindowPriv(pWin)->sibling_above = None;
132 if (pWin->nextSib)
133 xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin);
134 #ifdef SHAPE
135 xnestWindowPriv(pWin)->bounding_shape =
136 REGION_CREATE(pWin->drawable.pScreen, NULL, 1);
137 xnestWindowPriv(pWin)->clip_shape =
138 REGION_CREATE(pWin->drawable.pScreen, NULL, 1);
139 #endif /* SHAPE */
141 if (!pWin->parent) /* only the root window will have the right colormap */
142 xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
144 return True;
147 Bool
148 xnestDestroyWindow(WindowPtr pWin)
150 if (pWin->nextSib)
151 xnestWindowPriv(pWin->nextSib)->sibling_above =
152 xnestWindowPriv(pWin)->sibling_above;
153 #ifdef SHAPE
154 REGION_DESTROY(pWin->drawable.pScreen,
155 xnestWindowPriv(pWin)->bounding_shape);
156 REGION_DESTROY(pWin->drawable.pScreen,
157 xnestWindowPriv(pWin)->clip_shape);
158 #endif
159 XDestroyWindow(xnestDisplay, xnestWindow(pWin));
160 xnestWindowPriv(pWin)->window = None;
162 if (pWin->optional && pWin->optional->colormap && pWin->parent)
163 xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
165 return True;
168 Bool
169 xnestPositionWindow(WindowPtr pWin, int x, int y)
171 xnestConfigureWindow(pWin,
172 CWParent |
173 CWX | CWY |
174 CWWidth | CWHeight |
175 CWBorderWidth);
177 return True;
180 void
181 xnestConfigureWindow(WindowPtr pWin, unsigned int mask)
183 unsigned int valuemask;
184 XWindowChanges values;
186 if (mask & CWParent &&
187 xnestWindowPriv(pWin)->parent != xnestWindowParent(pWin)) {
188 XReparentWindow(xnestDisplay, xnestWindow(pWin),
189 xnestWindowParent(pWin),
190 pWin->origin.x - wBorderWidth(pWin),
191 pWin->origin.y - wBorderWidth(pWin));
192 xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin);
193 xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
194 xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
195 xnestWindowPriv(pWin)->sibling_above = None;
196 if (pWin->nextSib)
197 xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin);
200 valuemask = 0;
202 if (mask & CWX &&
203 xnestWindowPriv(pWin)->x != pWin->origin.x - wBorderWidth(pWin)) {
204 valuemask |= CWX;
205 values.x =
206 xnestWindowPriv(pWin)->x =
207 pWin->origin.x - wBorderWidth(pWin);
210 if (mask & CWY &&
211 xnestWindowPriv(pWin)->y != pWin->origin.y - wBorderWidth(pWin)) {
212 valuemask |= CWY;
213 values.y =
214 xnestWindowPriv(pWin)->y =
215 pWin->origin.y - wBorderWidth(pWin);
218 if (mask & CWWidth &&
219 xnestWindowPriv(pWin)->width != pWin->drawable.width) {
220 valuemask |= CWWidth;
221 values.width =
222 xnestWindowPriv(pWin)->width =
223 pWin->drawable.width;
226 if (mask & CWHeight &&
227 xnestWindowPriv(pWin)->height != pWin->drawable.height) {
228 valuemask |= CWHeight;
229 values.height =
230 xnestWindowPriv(pWin)->height =
231 pWin->drawable.height;
234 if (mask & CWBorderWidth &&
235 xnestWindowPriv(pWin)->border_width != pWin->borderWidth) {
236 valuemask |= CWBorderWidth;
237 values.border_width =
238 xnestWindowPriv(pWin)->border_width =
239 pWin->borderWidth;
242 if (valuemask)
243 XConfigureWindow(xnestDisplay, xnestWindow(pWin), valuemask, &values);
245 if (mask & CWStackingOrder &&
246 xnestWindowPriv(pWin)->sibling_above != xnestWindowSiblingAbove(pWin)) {
247 WindowPtr pSib;
249 /* find the top sibling */
250 for (pSib = pWin; pSib->prevSib != NullWindow; pSib = pSib->prevSib);
252 /* the top sibling */
253 valuemask = CWStackMode;
254 values.stack_mode = Above;
255 XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask, &values);
256 xnestWindowPriv(pSib)->sibling_above = None;
258 /* the rest of siblings */
259 for (pSib = pSib->nextSib; pSib != NullWindow; pSib = pSib->nextSib) {
260 valuemask = CWSibling | CWStackMode;
261 values.sibling = xnestWindowSiblingAbove(pSib);
262 values.stack_mode = Below;
263 XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask, &values);
264 xnestWindowPriv(pSib)->sibling_above = xnestWindowSiblingAbove(pSib);
269 Bool
270 xnestChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
272 XSetWindowAttributes attributes;
274 if (mask & CWBackPixmap)
275 switch (pWin->backgroundState) {
276 case None:
277 attributes.background_pixmap = None;
278 break;
280 case ParentRelative:
281 attributes.background_pixmap = ParentRelative;
282 break;
284 case BackgroundPixmap:
285 attributes.background_pixmap = xnestPixmap(pWin->background.pixmap);
286 break;
288 case BackgroundPixel:
289 mask &= ~CWBackPixmap;
290 break;
293 if (mask & CWBackPixel) {
294 if (pWin->backgroundState == BackgroundPixel)
295 attributes.background_pixel = xnestPixel(pWin->background.pixel);
296 else
297 mask &= ~CWBackPixel;
300 if (mask & CWBorderPixmap) {
301 if (pWin->borderIsPixel)
302 mask &= ~CWBorderPixmap;
303 else
304 attributes.border_pixmap = xnestPixmap(pWin->border.pixmap);
307 if (mask & CWBorderPixel) {
308 if (pWin->borderIsPixel)
309 attributes.border_pixel = xnestPixel(pWin->border.pixel);
310 else
311 mask &= ~CWBorderPixel;
314 if (mask & CWBitGravity)
315 attributes.bit_gravity = pWin->bitGravity;
317 if (mask & CWWinGravity) /* dix does this for us */
318 mask &= ~CWWinGravity;
320 if (mask & CWBackingStore) /* this is really not useful */
321 mask &= ~CWBackingStore;
323 if (mask & CWBackingPlanes) /* this is really not useful */
324 mask &= ~CWBackingPlanes;
326 if (mask & CWBackingPixel) /* this is really not useful */
327 mask &= ~CWBackingPixel;
329 if (mask & CWOverrideRedirect)
330 attributes.override_redirect = pWin->overrideRedirect;
332 if (mask & CWSaveUnder) /* this is really not useful */
333 mask &= ~CWSaveUnder;
335 if (mask & CWEventMask) /* events are handled elsewhere */
336 mask &= ~CWEventMask;
338 if (mask & CWDontPropagate) /* events are handled elsewhere */
339 mask &= ~CWDontPropagate;
341 if (mask & CWColormap) {
342 ColormapPtr pCmap;
344 pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
346 attributes.colormap = xnestColormap(pCmap);
348 xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
351 if (mask & CWCursor) /* this is handeled in cursor code */
352 mask &= ~CWCursor;
354 if (mask)
355 XChangeWindowAttributes(xnestDisplay, xnestWindow(pWin),
356 mask, &attributes);
358 return True;
361 Bool
362 xnestRealizeWindow(WindowPtr pWin)
364 xnestConfigureWindow(pWin, CWStackingOrder);
365 #ifdef SHAPE
366 xnestShapeWindow(pWin);
367 #endif /* SHAPE */
368 XMapWindow(xnestDisplay, xnestWindow(pWin));
370 return True;
373 Bool
374 xnestUnrealizeWindow(WindowPtr pWin)
376 XUnmapWindow(xnestDisplay, xnestWindow(pWin));
378 return True;
381 void
382 xnestPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what)
384 int i;
385 BoxPtr pBox;
387 xnestConfigureWindow(pWin, CWWidth | CWHeight);
389 pBox = REGION_RECTS(pRegion);
390 for (i = 0; i < REGION_NUM_RECTS(pRegion); i++)
391 XClearArea(xnestDisplay, xnestWindow(pWin),
392 pBox[i].x1 - pWin->drawable.x,
393 pBox[i].y1 - pWin->drawable.y,
394 pBox[i].x2 - pBox[i].x1,
395 pBox[i].y2 - pBox[i].y1,
396 False);
399 void
400 xnestPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what)
402 xnestConfigureWindow(pWin, CWBorderWidth);
405 void
406 xnestCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion)
410 void
411 xnestClipNotify(WindowPtr pWin, int dx, int dy)
413 xnestConfigureWindow(pWin, CWStackingOrder);
414 #ifdef SHAPE
415 xnestShapeWindow(pWin);
416 #endif /* SHAPE */
419 static Bool
420 xnestWindowExposurePredicate(Display *display, XEvent *event, XPointer ptr)
422 return (event->type == Expose && event->xexpose.window == *(Window *)ptr);
425 void
426 xnestWindowExposures(WindowPtr pWin, RegionPtr pRgn, RegionPtr other_exposed)
428 XEvent event;
429 Window window;
430 BoxRec Box;
432 XSync(xnestDisplay, False);
434 window = xnestWindow(pWin);
436 while (XCheckIfEvent(xnestDisplay, &event,
437 xnestWindowExposurePredicate, (char *)&window)) {
439 Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + event.xexpose.x;
440 Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + event.xexpose.y;
441 Box.x2 = Box.x1 + event.xexpose.width;
442 Box.y2 = Box.y1 + event.xexpose.height;
444 event.xexpose.type = ProcessedExpose;
446 if (RECT_IN_REGION(pWin->drawable.pScreen, pRgn, &Box) != rgnIN)
447 XPutBackEvent(xnestDisplay, &event);
450 miWindowExposures(pWin, pRgn, other_exposed);
453 #ifdef SHAPE
454 void
455 xnestSetShape(WindowPtr pWin)
457 xnestShapeWindow(pWin);
458 miSetShape(pWin);
461 static Bool
462 xnestRegionEqual(RegionPtr pReg1, RegionPtr pReg2)
464 BoxPtr pBox1, pBox2;
465 unsigned int n1, n2;
467 if (pReg1 == pReg2) return True;
469 if (pReg1 == NullRegion || pReg2 == NullRegion) return False;
471 pBox1 = REGION_RECTS(pReg1);
472 n1 = REGION_NUM_RECTS(pReg1);
474 pBox2 = REGION_RECTS(pReg2);
475 n2 = REGION_NUM_RECTS(pReg2);
477 if (n1 != n2) return False;
479 if (pBox1 == pBox2) return True;
481 if (memcmp(pBox1, pBox2, n1 * sizeof(BoxRec))) return False;
483 return True;
486 void
487 xnestShapeWindow(WindowPtr pWin)
489 Region reg;
490 BoxPtr pBox;
491 XRectangle rect;
492 int i;
494 if (!xnestRegionEqual(xnestWindowPriv(pWin)->bounding_shape,
495 wBoundingShape(pWin))) {
497 if (wBoundingShape(pWin)) {
498 REGION_COPY(pWin->drawable.pScreen,
499 xnestWindowPriv(pWin)->bounding_shape, wBoundingShape(pWin));
501 reg = XCreateRegion();
502 pBox = REGION_RECTS(xnestWindowPriv(pWin)->bounding_shape);
503 for (i = 0;
504 i < REGION_NUM_RECTS(xnestWindowPriv(pWin)->bounding_shape);
505 i++) {
506 rect.x = pBox[i].x1;
507 rect.y = pBox[i].y1;
508 rect.width = pBox[i].x2 - pBox[i].x1;
509 rect.height = pBox[i].y2 - pBox[i].y1;
510 XUnionRectWithRegion(&rect, reg, reg);
512 XShapeCombineRegion(xnestDisplay, xnestWindow(pWin),
513 ShapeBounding, 0, 0, reg, ShapeSet);
514 XDestroyRegion(reg);
516 else {
517 REGION_EMPTY(pWin->drawable.pScreen,
518 xnestWindowPriv(pWin)->bounding_shape);
520 XShapeCombineMask(xnestDisplay, xnestWindow(pWin),
521 ShapeBounding, 0, 0, None, ShapeSet);
525 if (!xnestRegionEqual(xnestWindowPriv(pWin)->clip_shape,
526 wClipShape(pWin))) {
528 if (wClipShape(pWin)) {
529 REGION_COPY(pWin->drawable.pScreen,
530 xnestWindowPriv(pWin)->clip_shape, wClipShape(pWin));
532 reg = XCreateRegion();
533 pBox = REGION_RECTS(xnestWindowPriv(pWin)->clip_shape);
534 for (i = 0;
535 i < REGION_NUM_RECTS(xnestWindowPriv(pWin)->clip_shape);
536 i++) {
537 rect.x = pBox[i].x1;
538 rect.y = pBox[i].y1;
539 rect.width = pBox[i].x2 - pBox[i].x1;
540 rect.height = pBox[i].y2 - pBox[i].y1;
541 XUnionRectWithRegion(&rect, reg, reg);
543 XShapeCombineRegion(xnestDisplay, xnestWindow(pWin),
544 ShapeClip, 0, 0, reg, ShapeSet);
545 XDestroyRegion(reg);
547 else {
548 REGION_EMPTY(pWin->drawable.pScreen,
549 xnestWindowPriv(pWin)->clip_shape);
551 XShapeCombineMask(xnestDisplay, xnestWindow(pWin),
552 ShapeClip, 0, 0, None, ShapeSet);
556 #endif /* SHAPE */