Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xnest / Window.c
CommitLineData
a09e091a
JB
1/*
2
3Copyright 1993 by Davor Matic
4
5Permission to use, copy, modify, distribute, and sell this software
6and its documentation for any purpose is hereby granted without fee,
7provided that the above copyright notice appear in all copies and that
8both that copyright notice and this permission notice appear in
9supporting documentation. Davor Matic makes no representations about
10the suitability of this software for any purpose. It is provided "as
11is" without express or implied warranty.
12
13*/
14
15#ifdef HAVE_XNEST_CONFIG_H
16#include <xnest-config.h>
17#endif
18
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"
28
29#include "mi.h"
30
31#include "Xnest.h"
32
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"
41
42DevPrivateKeyRec xnestWindowPrivateKeyRec;
43
44static int
45xnestFindWindowMatch(WindowPtr pWin, pointer ptr)
46{
47 xnestWindowMatch *wm = (xnestWindowMatch *) ptr;
48
49 if (wm->window == xnestWindow(pWin)) {
50 wm->pWin = pWin;
51 return WT_STOPWALKING;
52 }
53 else
54 return WT_WALKCHILDREN;
55}
56
57WindowPtr
58xnestWindowPtr(Window window)
59{
60 xnestWindowMatch wm;
61 int i;
62
63 wm.pWin = NullWindow;
64 wm.window = window;
65
66 for (i = 0; i < xnestNumScreens; i++) {
67 WalkTree(screenInfo.screens[i], xnestFindWindowMatch, (pointer) &wm);
68 if (wm.pWin)
69 break;
70 }
71
72 return wm.pWin;
73}
74
75Bool
76xnestCreateWindow(WindowPtr pWin)
77{
78 unsigned long mask;
79 XSetWindowAttributes attributes;
80 Visual *visual;
81 ColormapPtr pCmap;
82
83 if (pWin->drawable.class == InputOnly) {
84 mask = 0L;
85 visual = CopyFromParent;
86 }
87 else {
88 mask = CWEventMask | CWBackingStore;
89 attributes.event_mask = ExposureMask;
90 attributes.backing_store = NotUseful;
91
92 if (pWin->parent) {
93 if (pWin->optional &&
94 pWin->optional->visual != wVisual(pWin->parent)) {
95 visual =
96 xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
97 mask |= CWColormap;
98 if (pWin->optional->colormap) {
99 dixLookupResourceByType((pointer *) &pCmap, wColormap(pWin),
100 RT_COLORMAP, serverClient,
101 DixUseAccess);
102 attributes.colormap = xnestColormap(pCmap);
103 }
104 else
105 attributes.colormap = xnestDefaultVisualColormap(visual);
106 }
107 else
108 visual = CopyFromParent;
109 }
110 else { /* root windows have their own colormaps at creation time */
111 visual = xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
112 dixLookupResourceByType((pointer *) &pCmap, wColormap(pWin),
113 RT_COLORMAP, serverClient, DixUseAccess);
114 mask |= CWColormap;
115 attributes.colormap = xnestColormap(pCmap);
116 }
117 }
118
119 xnestWindowPriv(pWin)->window = XCreateWindow(xnestDisplay,
120 xnestWindowParent(pWin),
121 pWin->origin.x -
122 wBorderWidth(pWin),
123 pWin->origin.y -
124 wBorderWidth(pWin),
125 pWin->drawable.width,
126 pWin->drawable.height,
127 pWin->borderWidth,
128 pWin->drawable.depth,
129 pWin->drawable.class,
130 visual, mask, &attributes);
131 xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin);
132 xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
133 xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
134 xnestWindowPriv(pWin)->width = pWin->drawable.width;
135 xnestWindowPriv(pWin)->height = pWin->drawable.height;
136 xnestWindowPriv(pWin)->border_width = pWin->borderWidth;
137 xnestWindowPriv(pWin)->sibling_above = None;
138 if (pWin->nextSib)
139 xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin);
140 xnestWindowPriv(pWin)->bounding_shape = RegionCreate(NULL, 1);
141 xnestWindowPriv(pWin)->clip_shape = RegionCreate(NULL, 1);
142
143 if (!pWin->parent) /* only the root window will have the right colormap */
144 xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
145
146 return True;
147}
148
149Bool
150xnestDestroyWindow(WindowPtr pWin)
151{
152 if (pWin->nextSib)
153 xnestWindowPriv(pWin->nextSib)->sibling_above =
154 xnestWindowPriv(pWin)->sibling_above;
155 RegionDestroy(xnestWindowPriv(pWin)->bounding_shape);
156 RegionDestroy(xnestWindowPriv(pWin)->clip_shape);
157 XDestroyWindow(xnestDisplay, xnestWindow(pWin));
158 xnestWindowPriv(pWin)->window = None;
159
160 if (pWin->optional && pWin->optional->colormap && pWin->parent)
161 xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
162
163 return True;
164}
165
166Bool
167xnestPositionWindow(WindowPtr pWin, int x, int y)
168{
169 xnestConfigureWindow(pWin,
170 CWParent |
171 CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
172
173 return True;
174}
175
176void
177xnestConfigureWindow(WindowPtr pWin, unsigned int mask)
178{
179 unsigned int valuemask;
180 XWindowChanges values;
181
182 if (mask & CWParent &&
183 xnestWindowPriv(pWin)->parent != xnestWindowParent(pWin)) {
184 XReparentWindow(xnestDisplay, xnestWindow(pWin),
185 xnestWindowParent(pWin),
186 pWin->origin.x - wBorderWidth(pWin),
187 pWin->origin.y - wBorderWidth(pWin));
188 xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin);
189 xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
190 xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
191 xnestWindowPriv(pWin)->sibling_above = None;
192 if (pWin->nextSib)
193 xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin);
194 }
195
196 valuemask = 0;
197
198 if (mask & CWX &&
199 xnestWindowPriv(pWin)->x != pWin->origin.x - wBorderWidth(pWin)) {
200 valuemask |= CWX;
201 values.x =
202 xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
203 }
204
205 if (mask & CWY &&
206 xnestWindowPriv(pWin)->y != pWin->origin.y - wBorderWidth(pWin)) {
207 valuemask |= CWY;
208 values.y =
209 xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
210 }
211
212 if (mask & CWWidth && xnestWindowPriv(pWin)->width != pWin->drawable.width) {
213 valuemask |= CWWidth;
214 values.width = xnestWindowPriv(pWin)->width = pWin->drawable.width;
215 }
216
217 if (mask & CWHeight &&
218 xnestWindowPriv(pWin)->height != pWin->drawable.height) {
219 valuemask |= CWHeight;
220 values.height = xnestWindowPriv(pWin)->height = pWin->drawable.height;
221 }
222
223 if (mask & CWBorderWidth &&
224 xnestWindowPriv(pWin)->border_width != pWin->borderWidth) {
225 valuemask |= CWBorderWidth;
226 values.border_width =
227 xnestWindowPriv(pWin)->border_width = pWin->borderWidth;
228 }
229
230 if (valuemask)
231 XConfigureWindow(xnestDisplay, xnestWindow(pWin), valuemask, &values);
232
233 if (mask & CWStackingOrder &&
234 xnestWindowPriv(pWin)->sibling_above != xnestWindowSiblingAbove(pWin)) {
235 WindowPtr pSib;
236
237 /* find the top sibling */
238 for (pSib = pWin; pSib->prevSib != NullWindow; pSib = pSib->prevSib);
239
240 /* the top sibling */
241 valuemask = CWStackMode;
242 values.stack_mode = Above;
243 XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask, &values);
244 xnestWindowPriv(pSib)->sibling_above = None;
245
246 /* the rest of siblings */
247 for (pSib = pSib->nextSib; pSib != NullWindow; pSib = pSib->nextSib) {
248 valuemask = CWSibling | CWStackMode;
249 values.sibling = xnestWindowSiblingAbove(pSib);
250 values.stack_mode = Below;
251 XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask,
252 &values);
253 xnestWindowPriv(pSib)->sibling_above =
254 xnestWindowSiblingAbove(pSib);
255 }
256 }
257}
258
259Bool
260xnestChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
261{
262 XSetWindowAttributes attributes;
263
264 if (mask & CWBackPixmap)
265 switch (pWin->backgroundState) {
266 case None:
267 attributes.background_pixmap = None;
268 break;
269
270 case ParentRelative:
271 attributes.background_pixmap = ParentRelative;
272 break;
273
274 case BackgroundPixmap:
275 attributes.background_pixmap = xnestPixmap(pWin->background.pixmap);
276 break;
277
278 case BackgroundPixel:
279 mask &= ~CWBackPixmap;
280 break;
281 }
282
283 if (mask & CWBackPixel) {
284 if (pWin->backgroundState == BackgroundPixel)
285 attributes.background_pixel = xnestPixel(pWin->background.pixel);
286 else
287 mask &= ~CWBackPixel;
288 }
289
290 if (mask & CWBorderPixmap) {
291 if (pWin->borderIsPixel)
292 mask &= ~CWBorderPixmap;
293 else
294 attributes.border_pixmap = xnestPixmap(pWin->border.pixmap);
295 }
296
297 if (mask & CWBorderPixel) {
298 if (pWin->borderIsPixel)
299 attributes.border_pixel = xnestPixel(pWin->border.pixel);
300 else
301 mask &= ~CWBorderPixel;
302 }
303
304 if (mask & CWBitGravity)
305 attributes.bit_gravity = pWin->bitGravity;
306
307 if (mask & CWWinGravity) /* dix does this for us */
308 mask &= ~CWWinGravity;
309
310 if (mask & CWBackingStore) /* this is really not useful */
311 mask &= ~CWBackingStore;
312
313 if (mask & CWBackingPlanes) /* this is really not useful */
314 mask &= ~CWBackingPlanes;
315
316 if (mask & CWBackingPixel) /* this is really not useful */
317 mask &= ~CWBackingPixel;
318
319 if (mask & CWOverrideRedirect)
320 attributes.override_redirect = pWin->overrideRedirect;
321
322 if (mask & CWSaveUnder) /* this is really not useful */
323 mask &= ~CWSaveUnder;
324
325 if (mask & CWEventMask) /* events are handled elsewhere */
326 mask &= ~CWEventMask;
327
328 if (mask & CWDontPropagate) /* events are handled elsewhere */
329 mask &= ~CWDontPropagate;
330
331 if (mask & CWColormap) {
332 ColormapPtr pCmap;
333
334 dixLookupResourceByType((pointer *) &pCmap, wColormap(pWin),
335 RT_COLORMAP, serverClient, DixUseAccess);
336
337 attributes.colormap = xnestColormap(pCmap);
338
339 xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
340 }
341
342 if (mask & CWCursor) /* this is handeled in cursor code */
343 mask &= ~CWCursor;
344
345 if (mask)
346 XChangeWindowAttributes(xnestDisplay, xnestWindow(pWin),
347 mask, &attributes);
348
349 return True;
350}
351
352Bool
353xnestRealizeWindow(WindowPtr pWin)
354{
355 xnestConfigureWindow(pWin, CWStackingOrder);
356 xnestShapeWindow(pWin);
357 XMapWindow(xnestDisplay, xnestWindow(pWin));
358
359 return True;
360}
361
362Bool
363xnestUnrealizeWindow(WindowPtr pWin)
364{
365 XUnmapWindow(xnestDisplay, xnestWindow(pWin));
366
367 return True;
368}
369
370void
371xnestCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion)
372{
373}
374
375void
376xnestClipNotify(WindowPtr pWin, int dx, int dy)
377{
378 xnestConfigureWindow(pWin, CWStackingOrder);
379 xnestShapeWindow(pWin);
380}
381
382static Bool
383xnestWindowExposurePredicate(Display * display, XEvent * event, XPointer ptr)
384{
385 return (event->type == Expose && event->xexpose.window == *(Window *) ptr);
386}
387
388void
389xnestWindowExposures(WindowPtr pWin, RegionPtr pRgn, RegionPtr other_exposed)
390{
391 XEvent event;
392 Window window;
393 BoxRec Box;
394
395 XSync(xnestDisplay, False);
396
397 window = xnestWindow(pWin);
398
399 while (XCheckIfEvent(xnestDisplay, &event,
400 xnestWindowExposurePredicate, (char *) &window)) {
401
402 Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + event.xexpose.x;
403 Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + event.xexpose.y;
404 Box.x2 = Box.x1 + event.xexpose.width;
405 Box.y2 = Box.y1 + event.xexpose.height;
406
407 event.xexpose.type = ProcessedExpose;
408
409 if (RegionContainsRect(pRgn, &Box) != rgnIN)
410 XPutBackEvent(xnestDisplay, &event);
411 }
412
413 miWindowExposures(pWin, pRgn, other_exposed);
414}
415
416void
417xnestSetShape(WindowPtr pWin, int kind)
418{
419 xnestShapeWindow(pWin);
420 miSetShape(pWin, kind);
421}
422
423static Bool
424xnestRegionEqual(RegionPtr pReg1, RegionPtr pReg2)
425{
426 BoxPtr pBox1, pBox2;
427 unsigned int n1, n2;
428
429 if (pReg1 == pReg2)
430 return True;
431
432 if (pReg1 == NullRegion || pReg2 == NullRegion)
433 return False;
434
435 pBox1 = RegionRects(pReg1);
436 n1 = RegionNumRects(pReg1);
437
438 pBox2 = RegionRects(pReg2);
439 n2 = RegionNumRects(pReg2);
440
441 if (n1 != n2)
442 return False;
443
444 if (pBox1 == pBox2)
445 return True;
446
447 if (memcmp(pBox1, pBox2, n1 * sizeof(BoxRec)))
448 return False;
449
450 return True;
451}
452
453void
454xnestShapeWindow(WindowPtr pWin)
455{
456 Region reg;
457 BoxPtr pBox;
458 XRectangle rect;
459 int i;
460
461 if (!xnestRegionEqual(xnestWindowPriv(pWin)->bounding_shape,
462 wBoundingShape(pWin))) {
463
464 if (wBoundingShape(pWin)) {
465 RegionCopy(xnestWindowPriv(pWin)->bounding_shape,
466 wBoundingShape(pWin));
467
468 reg = XCreateRegion();
469 pBox = RegionRects(xnestWindowPriv(pWin)->bounding_shape);
470 for (i = 0;
471 i < RegionNumRects(xnestWindowPriv(pWin)->bounding_shape);
472 i++) {
473 rect.x = pBox[i].x1;
474 rect.y = pBox[i].y1;
475 rect.width = pBox[i].x2 - pBox[i].x1;
476 rect.height = pBox[i].y2 - pBox[i].y1;
477 XUnionRectWithRegion(&rect, reg, reg);
478 }
479 XShapeCombineRegion(xnestDisplay, xnestWindow(pWin),
480 ShapeBounding, 0, 0, reg, ShapeSet);
481 XDestroyRegion(reg);
482 }
483 else {
484 RegionEmpty(xnestWindowPriv(pWin)->bounding_shape);
485
486 XShapeCombineMask(xnestDisplay, xnestWindow(pWin),
487 ShapeBounding, 0, 0, None, ShapeSet);
488 }
489 }
490
491 if (!xnestRegionEqual(xnestWindowPriv(pWin)->clip_shape, wClipShape(pWin))) {
492
493 if (wClipShape(pWin)) {
494 RegionCopy(xnestWindowPriv(pWin)->clip_shape, wClipShape(pWin));
495
496 reg = XCreateRegion();
497 pBox = RegionRects(xnestWindowPriv(pWin)->clip_shape);
498 for (i = 0;
499 i < RegionNumRects(xnestWindowPriv(pWin)->clip_shape); i++) {
500 rect.x = pBox[i].x1;
501 rect.y = pBox[i].y1;
502 rect.width = pBox[i].x2 - pBox[i].x1;
503 rect.height = pBox[i].y2 - pBox[i].y1;
504 XUnionRectWithRegion(&rect, reg, reg);
505 }
506 XShapeCombineRegion(xnestDisplay, xnestWindow(pWin),
507 ShapeClip, 0, 0, reg, ShapeSet);
508 XDestroyRegion(reg);
509 }
510 else {
511 RegionEmpty(xnestWindowPriv(pWin)->clip_shape);
512
513 XShapeCombineMask(xnestDisplay, xnestWindow(pWin),
514 ShapeClip, 0, 0, None, ShapeSet);
515 }
516 }
517}