tizen 2.4 release
[framework/uifw/xorg/server/xorg-server.git] / composite / compwindow.c
1 /*
2  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Copyright © 2003 Keith Packard
24  *
25  * Permission to use, copy, modify, distribute, and sell this software and its
26  * documentation for any purpose is hereby granted without fee, provided that
27  * the above copyright notice appear in all copies and that both that
28  * copyright notice and this permission notice appear in supporting
29  * documentation, and that the name of Keith Packard not be used in
30  * advertising or publicity pertaining to distribution of the software without
31  * specific, written prior permission.  Keith Packard makes no
32  * representations about the suitability of this software for any purpose.  It
33  * is provided "as is" without express or implied warranty.
34  *
35  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
36  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
37  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
38  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
39  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
40  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
41  * PERFORMANCE OF THIS SOFTWARE.
42  */
43
44 #ifdef HAVE_DIX_CONFIG_H
45 #include <dix-config.h>
46 #endif
47
48 #include "compint.h"
49
50 #ifdef PANORAMIX
51 #include "panoramiXsrv.h"
52 #endif
53
54 #ifdef _F_STEREOSCOPIC_LEFT_BUFFER_COODINATE_
55 static int prefered_w = 0 ;
56 static int prefered_h = 0 ;
57
58 #define IS_NOT_SET 0
59 #define IS_SET 1
60 #endif  // _F_STEREOSCOPIC_LEFT_BUFFER_COODINATE_
61
62 #ifdef ENABLE_DLOG
63 #define LOG_TAG "XORG_PIXMAP"
64 #include <dlog.h>
65 #endif
66
67 #ifdef COMPOSITE_DEBUG
68 static int
69 compCheckWindow(WindowPtr pWin, void *data)
70 {
71     ScreenPtr pScreen = pWin->drawable.pScreen;
72     PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin);
73     PixmapPtr pParentPixmap =
74         pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0;
75     PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen);
76
77     if (!pWin->parent) {
78         assert(pWin->redirectDraw == RedirectDrawNone);
79         assert(pWinPixmap == pScreenPixmap);
80     }
81     else if (pWin->redirectDraw != RedirectDrawNone) {
82         assert(pWinPixmap != pParentPixmap);
83         assert(pWinPixmap != pScreenPixmap);
84     }
85     else {
86         assert(pWinPixmap == pParentPixmap);
87     }
88     assert(0 < pWinPixmap->refcnt && pWinPixmap->refcnt < 3);
89     assert(0 < pScreenPixmap->refcnt && pScreenPixmap->refcnt < 3);
90     if (pParentPixmap)
91         assert(0 <= pParentPixmap->refcnt && pParentPixmap->refcnt < 3);
92     return WT_WALKCHILDREN;
93 }
94
95 void
96 compCheckTree(ScreenPtr pScreen)
97 {
98     WalkTree(pScreen, compCheckWindow, 0);
99 }
100 #endif
101
102 typedef struct _compPixmapVisit {
103     WindowPtr pWindow;
104     PixmapPtr pPixmap;
105 } CompPixmapVisitRec, *CompPixmapVisitPtr;
106
107 static Bool
108 compRepaintBorder(ClientPtr pClient, void *closure)
109 {
110     WindowPtr pWindow;
111     int rc =
112         dixLookupWindow(&pWindow, (XID) (intptr_t) closure, pClient,
113                         DixWriteAccess);
114
115     if (rc == Success) {
116         RegionRec exposed;
117
118         RegionNull(&exposed);
119         RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize);
120         miPaintWindow(pWindow, &exposed, PW_BORDER);
121         RegionUninit(&exposed);
122     }
123     return TRUE;
124 }
125
126 static int
127 compSetPixmapVisitWindow(WindowPtr pWindow, void *data)
128 {
129     CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data;
130     ScreenPtr pScreen = pWindow->drawable.pScreen;
131
132     if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone)
133         return WT_DONTWALKCHILDREN;
134     (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap);
135     /*
136      * Recompute winSize and borderSize.  This is duplicate effort
137      * when resizing pixmaps, but necessary when changing redirection.
138      * Might be nice to fix this.
139      */
140     SetWinSize(pWindow);
141     SetBorderSize(pWindow);
142     if (HasBorder(pWindow))
143         QueueWorkProc(compRepaintBorder, serverClient,
144                       (void *) (intptr_t) pWindow->drawable.id);
145     return WT_WALKCHILDREN;
146 }
147
148 void
149 compSetPixmap(WindowPtr pWindow, PixmapPtr pPixmap)
150 {
151     CompPixmapVisitRec visitRec;
152
153     visitRec.pWindow = pWindow;
154     visitRec.pPixmap = pPixmap;
155     TraverseTree(pWindow, compSetPixmapVisitWindow, (void *) &visitRec);
156     compCheckTree(pWindow->drawable.pScreen);
157 }
158
159 Bool
160 compCheckRedirect(WindowPtr pWin)
161 {
162     CompWindowPtr cw = GetCompWindow(pWin);
163     CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
164     Bool should;
165     ScreenPtr pScreen = NULL;
166     PixmapPtr pPixmap = NULL;
167     Bool ret = FALSE;
168
169     should = pWin->realized && (pWin->drawable.class != InputOnly) &&
170         (cw != NULL) && (pWin->parent != NULL);
171
172     /* Never redirect the overlay window */
173     if (cs->pOverlayWin != NULL) {
174         if (pWin == cs->pOverlayWin) {
175             should = FALSE;
176         }
177     }
178
179     if (should != (pWin->redirectDraw != RedirectDrawNone)) {
180         if (should) {
181             ret = compAllocPixmap(pWin);
182             pScreen = pWin->drawable.pScreen;
183             pPixmap = (*pScreen->GetWindowPixmap) (pWin);
184
185 #ifdef ENABLE_DLOG
186             SLOG(LOG_INFO, "XORG_PIXMAP", "pix_id:%p, pixmap:%p (%dx%d) refcnt:%d win_id:%p win:%p (%dx%d) view:%d\n",
187                 pPixmap->drawable.id,
188                 pPixmap,
189                 pPixmap->drawable.width,
190                 pPixmap->drawable.height,
191                 pPixmap->refcnt,
192                 pWin->drawable.id,
193                 pWin,
194                 pWin->drawable.width,
195                 pWin->drawable.height,
196                 pWin->viewable);
197 #endif
198
199             return ret;
200         }
201         else {
202             pScreen = pWin->drawable.pScreen;
203             pPixmap = (*pScreen->GetWindowPixmap) (pWin);
204
205             compSetParentPixmap(pWin);
206             compRestoreWindow(pWin, pPixmap);
207
208 #ifdef ENABLE_DLOG
209             SLOG(LOG_INFO, "XORG_PIXMAP", "pix_id:%p, pixmap:%p (%dx%d) refcnt:%d-1 win_id:%p win:%p (%dx%d) view:%d\n",
210                 pPixmap->drawable.id,
211                 pPixmap,
212                 pPixmap->drawable.width,
213                 pPixmap->drawable.height,
214                 pPixmap->refcnt,
215                 pWin->drawable.id,
216                 pWin,
217                 pWin->drawable.width,
218                 pWin->drawable.height,
219                 pWin->viewable);
220
221 #endif
222             (*pScreen->DestroyPixmap) (pPixmap);
223         }
224     }
225     else if (should) {
226         if (cw->update == CompositeRedirectAutomatic)
227             pWin->redirectDraw = RedirectDrawAutomatic;
228         else
229             pWin->redirectDraw = RedirectDrawManual;
230     }
231
232 #ifdef ENABLE_DLOG
233     if (!pPixmap) {
234         pScreen = pWin->drawable.pScreen;
235         pPixmap = (*pScreen->GetWindowPixmap) (pWin);
236     }
237
238     SLOG(LOG_INFO, "XORG_PIXMAP", "pix_id:%p, pixmap:%p (%dx%d) refcnt:%d win_id:%p win:%p (%dx%d) view:%d\n",
239         pPixmap->drawable.id,
240         pPixmap,
241         pPixmap->drawable.width,
242         pPixmap->drawable.height,
243         pPixmap->refcnt,
244         pWin->drawable.id,
245         pWin,
246         pWin->drawable.width,
247         pWin->drawable.height,
248         pWin->viewable);
249 #endif
250
251     return TRUE;
252 }
253
254 static int
255 updateOverlayWindow(ScreenPtr pScreen)
256 {
257     CompScreenPtr cs;
258     WindowPtr pWin;             /* overlay window */
259     XID vlist[2];
260     int w = pScreen->width;
261     int h = pScreen->height;
262
263 #ifdef PANORAMIX
264     if (!noPanoramiXExtension) {
265         w = PanoramiXPixWidth;
266         h = PanoramiXPixHeight;
267     }
268 #endif
269
270     cs = GetCompScreen(pScreen);
271     if ((pWin = cs->pOverlayWin) != NULL) {
272         if ((pWin->drawable.width == w) && (pWin->drawable.height == h))
273             return Success;
274
275         /* Let's resize the overlay window. */
276         vlist[0] = w;
277         vlist[1] = h;
278         return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin));
279     }
280
281     /* Let's be on the safe side and not assume an overlay window is
282        always allocated. */
283     return Success;
284 }
285
286 Bool
287 compPositionWindow(WindowPtr pWin, int x, int y)
288 {
289     ScreenPtr pScreen = pWin->drawable.pScreen;
290     CompScreenPtr cs = GetCompScreen(pScreen);
291     Bool ret = TRUE;
292
293     pScreen->PositionWindow = cs->PositionWindow;
294     /*
295      * "Shouldn't need this as all possible places should be wrapped
296      *
297      compCheckRedirect (pWin);
298      */
299 #ifdef COMPOSITE_DEBUG
300     if ((pWin->redirectDraw != RedirectDrawNone) !=
301         (pWin->viewable && (GetCompWindow(pWin) != NULL)))
302         OsAbort();
303 #endif
304     if (pWin->redirectDraw != RedirectDrawNone) {
305         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
306         int bw = wBorderWidth(pWin);
307         int nx = pWin->drawable.x - bw;
308         int ny = pWin->drawable.y - bw;
309
310         if (pPixmap->screen_x != nx || pPixmap->screen_y != ny) {
311             pPixmap->screen_x = nx;
312             pPixmap->screen_y = ny;
313             pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
314         }
315     }
316
317     if (!(*pScreen->PositionWindow) (pWin, x, y))
318         ret = FALSE;
319     cs->PositionWindow = pScreen->PositionWindow;
320     pScreen->PositionWindow = compPositionWindow;
321     compCheckTree(pWin->drawable.pScreen);
322     if (updateOverlayWindow(pScreen) != Success)
323         ret = FALSE;
324     return ret;
325 }
326
327 Bool
328 compRealizeWindow(WindowPtr pWin)
329 {
330     ScreenPtr pScreen = pWin->drawable.pScreen;
331     CompScreenPtr cs = GetCompScreen(pScreen);
332     Bool ret = TRUE;
333
334     pScreen->RealizeWindow = cs->RealizeWindow;
335     compCheckRedirect(pWin);
336     if (!(*pScreen->RealizeWindow) (pWin))
337         ret = FALSE;
338     cs->RealizeWindow = pScreen->RealizeWindow;
339     pScreen->RealizeWindow = compRealizeWindow;
340     compCheckTree(pWin->drawable.pScreen);
341     return ret;
342 }
343
344 Bool
345 compUnrealizeWindow(WindowPtr pWin)
346 {
347     ScreenPtr pScreen = pWin->drawable.pScreen;
348     CompScreenPtr cs = GetCompScreen(pScreen);
349     Bool ret = TRUE;
350
351     pScreen->UnrealizeWindow = cs->UnrealizeWindow;
352     compCheckRedirect(pWin);
353     if (!(*pScreen->UnrealizeWindow) (pWin))
354         ret = FALSE;
355     cs->UnrealizeWindow = pScreen->UnrealizeWindow;
356     pScreen->UnrealizeWindow = compUnrealizeWindow;
357     compCheckTree(pWin->drawable.pScreen);
358     return ret;
359 }
360
361 /*
362  * Called after the borderClip for the window has settled down
363  * We use this to make sure our extra borderClip has the right origin
364  */
365
366 void
367 compClipNotify(WindowPtr pWin, int dx, int dy)
368 {
369     ScreenPtr pScreen = pWin->drawable.pScreen;
370     CompScreenPtr cs = GetCompScreen(pScreen);
371     CompWindowPtr cw = GetCompWindow(pWin);
372
373     if (cw) {
374         if (cw->borderClipX != pWin->drawable.x ||
375             cw->borderClipY != pWin->drawable.y) {
376             RegionTranslate(&cw->borderClip,
377                             pWin->drawable.x - cw->borderClipX,
378                             pWin->drawable.y - cw->borderClipY);
379             cw->borderClipX = pWin->drawable.x;
380             cw->borderClipY = pWin->drawable.y;
381         }
382     }
383     if (cs->ClipNotify) {
384         pScreen->ClipNotify = cs->ClipNotify;
385         (*pScreen->ClipNotify) (pWin, dx, dy);
386         cs->ClipNotify = pScreen->ClipNotify;
387         pScreen->ClipNotify = compClipNotify;
388     }
389 }
390
391 /*
392  * Returns TRUE if the window needs server-provided automatic redirect,
393  * which is true if the child and parent aren't both regular or ARGB visuals
394  */
395
396 static Bool
397 compIsAlternateVisual(ScreenPtr pScreen, XID visual)
398 {
399     CompScreenPtr cs = GetCompScreen(pScreen);
400     int i;
401
402     for (i = 0; i < cs->numAlternateVisuals; i++)
403         if (cs->alternateVisuals[i] == visual)
404             return TRUE;
405     return FALSE;
406 }
407
408 static Bool
409 compIsImplicitRedirectException(ScreenPtr pScreen,
410                                 XID parentVisual, XID winVisual)
411 {
412     CompScreenPtr cs = GetCompScreen(pScreen);
413     int i;
414
415     for (i = 0; i < cs->numImplicitRedirectExceptions; i++)
416         if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual &&
417             cs->implicitRedirectExceptions[i].winVisual == winVisual)
418             return TRUE;
419
420     return FALSE;
421 }
422
423 static Bool
424 compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
425 {
426 #ifdef _F_NO_IMPLICIT_REDIRECT_
427     /*
428     Xserver redirect windows inside when the visuals(ex.depth) between parent of a window and the window is different.
429     Do not check the visuals between them in the composite extension when xserver redirect a window.
430     This make the 32 depth window get the root pixmap when compositor unredirect the 32 depth toplevel window.
431     */
432     return FALSE;
433 #endif
434     if (pParent) {
435         ScreenPtr pScreen = pWin->drawable.pScreen;
436         XID winVisual = wVisual(pWin);
437         XID parentVisual = wVisual(pParent);
438
439         if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual))
440             return FALSE;
441
442         if (winVisual != parentVisual &&
443             (compIsAlternateVisual(pScreen, winVisual) ||
444              compIsAlternateVisual(pScreen, parentVisual)))
445             return TRUE;
446     }
447     return FALSE;
448 }
449
450 static void
451 compFreeOldPixmap(WindowPtr pWin)
452 {
453     ScreenPtr pScreen = pWin->drawable.pScreen;
454
455     if (pWin->redirectDraw != RedirectDrawNone) {
456         CompWindowPtr cw = GetCompWindow(pWin);
457
458         if (cw->pOldPixmap) {
459 #ifdef ENABLE_DLOG
460             SLOG(LOG_INFO, "XORG_PIXMAP", "pix_id:%p, pixmap:%p (%dx%d) refcnt:%d-1 win_id:%p win:%p (%dx%d) view:%d\n",
461                 cw->pOldPixmap->drawable.id,
462                 cw->pOldPixmap,
463                 cw->pOldPixmap->drawable.width,
464                 cw->pOldPixmap->drawable.height,
465                 cw->pOldPixmap->refcnt,
466                 pWin->drawable.id,
467                 pWin,
468                 pWin->drawable.width,
469                 pWin->drawable.height,
470                 pWin->viewable);
471
472 #endif
473             (*pScreen->DestroyPixmap) (cw->pOldPixmap);
474             cw->pOldPixmap = NullPixmap;
475         }
476     }
477 }
478
479 void
480 compMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
481 {
482     ScreenPtr pScreen = pWin->drawable.pScreen;
483     CompScreenPtr cs = GetCompScreen(pScreen);
484
485     pScreen->MoveWindow = cs->MoveWindow;
486     (*pScreen->MoveWindow) (pWin, x, y, pSib, kind);
487     cs->MoveWindow = pScreen->MoveWindow;
488     pScreen->MoveWindow = compMoveWindow;
489
490     compFreeOldPixmap(pWin);
491     compCheckTree(pScreen);
492 }
493
494 void
495 compResizeWindow(WindowPtr pWin, int x, int y,
496                  unsigned int w, unsigned int h, WindowPtr pSib)
497 {
498     ScreenPtr pScreen = pWin->drawable.pScreen;
499     CompScreenPtr cs = GetCompScreen(pScreen);
500
501     pScreen->ResizeWindow = cs->ResizeWindow;
502     (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
503     cs->ResizeWindow = pScreen->ResizeWindow;
504     pScreen->ResizeWindow = compResizeWindow;
505
506     compFreeOldPixmap(pWin);
507     compCheckTree(pWin->drawable.pScreen);
508 }
509
510 void
511 compChangeBorderWidth(WindowPtr pWin, unsigned int bw)
512 {
513     ScreenPtr pScreen = pWin->drawable.pScreen;
514     CompScreenPtr cs = GetCompScreen(pScreen);
515
516     pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
517     (*pScreen->ChangeBorderWidth) (pWin, bw);
518     cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
519     pScreen->ChangeBorderWidth = compChangeBorderWidth;
520
521     compFreeOldPixmap(pWin);
522     compCheckTree(pWin->drawable.pScreen);
523 }
524
525 void
526 compReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
527 {
528     ScreenPtr pScreen = pWin->drawable.pScreen;
529     CompScreenPtr cs = GetCompScreen(pScreen);
530
531     pScreen->ReparentWindow = cs->ReparentWindow;
532     /*
533      * Remove any implicit redirect due to synthesized visual
534      */
535     if (compImplicitRedirect(pWin, pPriorParent))
536         compUnredirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
537     /*
538      * Handle subwindows redirection
539      */
540     compUnredirectOneSubwindow(pPriorParent, pWin);
541     compRedirectOneSubwindow(pWin->parent, pWin);
542     /*
543      * Add any implict redirect due to synthesized visual
544      */
545     if (compImplicitRedirect(pWin, pWin->parent))
546         compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
547
548     /*
549      * Allocate any necessary redirect pixmap
550      * (this actually should never be true; pWin is always unmapped)
551      */
552     compCheckRedirect(pWin);
553
554     /*
555      * Reset pixmap pointers as appropriate
556      */
557     if (pWin->parent && pWin->redirectDraw == RedirectDrawNone)
558         compSetPixmap(pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
559     /*
560      * Call down to next function
561      */
562     if (pScreen->ReparentWindow)
563         (*pScreen->ReparentWindow) (pWin, pPriorParent);
564     cs->ReparentWindow = pScreen->ReparentWindow;
565     pScreen->ReparentWindow = compReparentWindow;
566     compCheckTree(pWin->drawable.pScreen);
567 }
568
569 void
570 compCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
571 {
572     ScreenPtr pScreen = pWin->drawable.pScreen;
573     CompScreenPtr cs = GetCompScreen(pScreen);
574     int dx = 0, dy = 0;
575
576     if (pWin->redirectDraw != RedirectDrawNone) {
577         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
578         CompWindowPtr cw = GetCompWindow(pWin);
579
580         assert(cw->oldx != COMP_ORIGIN_INVALID);
581         assert(cw->oldy != COMP_ORIGIN_INVALID);
582         if (cw->pOldPixmap) {
583             /*
584              * Ok, the old bits are available in pOldPixmap and
585              * need to be copied to pNewPixmap.
586              */
587             RegionRec rgnDst;
588             GCPtr pGC;
589
590             dx = ptOldOrg.x - pWin->drawable.x;
591             dy = ptOldOrg.y - pWin->drawable.y;
592             RegionTranslate(prgnSrc, -dx, -dy);
593
594             RegionNull(&rgnDst);
595
596             RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
597
598             RegionTranslate(&rgnDst, -pPixmap->screen_x, -pPixmap->screen_y);
599
600             dx = dx + pPixmap->screen_x - cw->oldx;
601             dy = dy + pPixmap->screen_y - cw->oldy;
602             pGC = GetScratchGC(pPixmap->drawable.depth, pScreen);
603             if (pGC) {
604                 BoxPtr pBox = RegionRects(&rgnDst);
605                 int nBox = RegionNumRects(&rgnDst);
606
607                 ValidateGC(&pPixmap->drawable, pGC);
608                 while (nBox--) {
609                     (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable,
610                                                   &pPixmap->drawable,
611                                                   pGC,
612                                                   pBox->x1 + dx, pBox->y1 + dy,
613                                                   pBox->x2 - pBox->x1,
614                                                   pBox->y2 - pBox->y1,
615                                                   pBox->x1, pBox->y1);
616                     pBox++;
617                 }
618                 FreeScratchGC(pGC);
619             }
620             RegionUninit(&rgnDst);
621             return;
622         }
623         dx = pPixmap->screen_x - cw->oldx;
624         dy = pPixmap->screen_y - cw->oldy;
625         ptOldOrg.x += dx;
626         ptOldOrg.y += dy;
627     }
628
629     pScreen->CopyWindow = cs->CopyWindow;
630     if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y) {
631         if (dx || dy)
632             RegionTranslate(prgnSrc, dx, dy);
633         (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
634         if (dx || dy)
635             RegionTranslate(prgnSrc, -dx, -dy);
636     }
637     else {
638         ptOldOrg.x -= dx;
639         ptOldOrg.y -= dy;
640         RegionTranslate(prgnSrc,
641                         pWin->drawable.x - ptOldOrg.x,
642                         pWin->drawable.y - ptOldOrg.y);
643         DamageDamageRegion(&pWin->drawable, prgnSrc);
644     }
645     cs->CopyWindow = pScreen->CopyWindow;
646     pScreen->CopyWindow = compCopyWindow;
647     compCheckTree(pWin->drawable.pScreen);
648 }
649
650 Bool
651 compCreateWindow(WindowPtr pWin)
652 {
653     ScreenPtr pScreen = pWin->drawable.pScreen;
654     CompScreenPtr cs = GetCompScreen(pScreen);
655     Bool ret;
656
657     pScreen->CreateWindow = cs->CreateWindow;
658     ret = (*pScreen->CreateWindow) (pWin);
659     if (pWin->parent && ret) {
660         CompSubwindowsPtr csw = GetCompSubwindows(pWin->parent);
661         CompClientWindowPtr ccw;
662
663         (*pScreen->SetWindowPixmap) (pWin,
664                                      (*pScreen->GetWindowPixmap) (pWin->
665                                                                   parent));
666         if (csw)
667             for (ccw = csw->clients; ccw; ccw = ccw->next)
668                 compRedirectWindow(clients[CLIENT_ID(ccw->id)],
669                                    pWin, ccw->update);
670         if (compImplicitRedirect(pWin, pWin->parent))
671             compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
672     }
673     cs->CreateWindow = pScreen->CreateWindow;
674     pScreen->CreateWindow = compCreateWindow;
675     compCheckTree(pWin->drawable.pScreen);
676     return ret;
677 }
678
679 Bool
680 compDestroyWindow(WindowPtr pWin)
681 {
682     ScreenPtr pScreen = pWin->drawable.pScreen;
683     CompScreenPtr cs = GetCompScreen(pScreen);
684     CompWindowPtr cw;
685     CompSubwindowsPtr csw;
686     Bool ret;
687
688     pScreen->DestroyWindow = cs->DestroyWindow;
689     while ((cw = GetCompWindow(pWin)))
690         FreeResource(cw->clients->id, RT_NONE);
691     while ((csw = GetCompSubwindows(pWin)))
692         FreeResource(csw->clients->id, RT_NONE);
693
694     if (pWin->redirectDraw != RedirectDrawNone) {
695         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
696
697         compSetParentPixmap(pWin);
698 #ifdef ENABLE_DLOG
699         SLOG(LOG_INFO, "XORG_PIXMAP", "pix_id:%p, pixmap:%p (%dx%d) refcnt:%d-1 win_id:%p win:%p (%dx%d) view:%d\n",
700             pPixmap->drawable.id,
701             pPixmap,
702             pPixmap->drawable.width,
703             pPixmap->drawable.height,
704             pPixmap->refcnt,
705             pWin->drawable.id,
706             pWin,
707             pWin->drawable.width,
708             pWin->drawable.height,
709             pWin->viewable);
710 #endif
711         (*pScreen->DestroyPixmap) (pPixmap);
712     }
713     ret = (*pScreen->DestroyWindow) (pWin);
714     cs->DestroyWindow = pScreen->DestroyWindow;
715     pScreen->DestroyWindow = compDestroyWindow;
716 /*    compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
717     return ret;
718 }
719
720 void
721 compSetRedirectBorderClip(WindowPtr pWin, RegionPtr pRegion)
722 {
723     CompWindowPtr cw = GetCompWindow(pWin);
724     RegionRec damage;
725
726     RegionNull(&damage);
727     /*
728      * Align old border clip with new border clip
729      */
730     RegionTranslate(&cw->borderClip,
731                     pWin->drawable.x - cw->borderClipX,
732                     pWin->drawable.y - cw->borderClipY);
733     /*
734      * Compute newly visible portion of window for repaint
735      */
736     RegionSubtract(&damage, pRegion, &cw->borderClip);
737     /*
738      * Report that as damaged so it will be redrawn
739      */
740     DamageDamageRegion(&pWin->drawable, &damage);
741     RegionUninit(&damage);
742     /*
743      * Save the new border clip region
744      */
745     RegionCopy(&cw->borderClip, pRegion);
746     cw->borderClipX = pWin->drawable.x;
747     cw->borderClipY = pWin->drawable.y;
748 }
749
750 RegionPtr
751 compGetRedirectBorderClip(WindowPtr pWin)
752 {
753     CompWindowPtr cw = GetCompWindow(pWin);
754
755     return &cw->borderClip;
756 }
757
758 static void
759 compWindowUpdateAutomatic(WindowPtr pWin)
760 {
761     CompWindowPtr cw = GetCompWindow(pWin);
762     ScreenPtr pScreen = pWin->drawable.pScreen;
763     WindowPtr pParent = pWin->parent;
764     PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin);
765     PictFormatPtr pSrcFormat = PictureWindowFormat(pWin);
766     PictFormatPtr pDstFormat = PictureWindowFormat(pWin->parent);
767     PicturePtr pSrcPicture = NULL;
768     PicturePtr pDstPicture = NULL;
769     int error;
770     RegionPtr pRegion = DamageRegion(cw->damage);
771     XID subwindowMode = IncludeInferiors;
772
773     if (pSrcFormat)
774         pSrcPicture = CreatePicture(0, &pSrcPixmap->drawable,
775                                    pSrcFormat,
776                                    0, 0,
777                                    serverClient,
778                                    &error);
779
780     if (pDstFormat)
781         pDstPicture = CreatePicture(0, &pParent->drawable,
782                                    pDstFormat,
783                                    CPSubwindowMode,
784                                    &subwindowMode,
785                                    serverClient,
786                                    &error);
787
788     /*
789      * First move the region from window to screen coordinates
790      */
791     RegionTranslate(pRegion, pWin->drawable.x, pWin->drawable.y);
792
793     /*
794      * Clip against the "real" border clip
795      */
796     RegionIntersect(pRegion, pRegion, &cw->borderClip);
797
798     /*
799      * Now translate from screen to dest coordinates
800      */
801     RegionTranslate(pRegion, -pParent->drawable.x, -pParent->drawable.y);
802
803     /*
804      * Clip the picture
805      */
806     if (pDstPicture)
807         SetPictureClipRegion(pDstPicture, 0, 0, pRegion);
808
809     /*
810      * And paint
811      */
812     if (pSrcPicture && pDstPicture)
813         CompositePicture(PictOpSrc, pSrcPicture, 0, pDstPicture,
814                          0, 0,      /* src_x, src_y */
815                          0, 0,      /* msk_x, msk_y */
816                          pSrcPixmap->screen_x - pParent->drawable.x,
817                          pSrcPixmap->screen_y - pParent->drawable.y,
818                          pSrcPixmap->drawable.width, pSrcPixmap->drawable.height);
819     if (pSrcPicture)
820         FreePicture(pSrcPicture, 0);
821     if (pDstPicture)
822         FreePicture(pDstPicture, 0);
823     /*
824      * Empty the damage region.  This has the nice effect of
825      * rendering the translations above harmless
826      */
827     DamageEmpty(cw->damage);
828 }
829
830 static void
831 compPaintWindowToParent(WindowPtr pWin)
832 {
833     compPaintChildrenToWindow(pWin);
834
835     if (pWin->redirectDraw != RedirectDrawNone) {
836         CompWindowPtr cw = GetCompWindow(pWin);
837
838         if (cw->damaged) {
839             compWindowUpdateAutomatic(pWin);
840             cw->damaged = FALSE;
841         }
842     }
843 }
844
845 void
846 compPaintChildrenToWindow(WindowPtr pWin)
847 {
848     WindowPtr pChild;
849
850     if (!pWin->damagedDescendants)
851         return;
852
853     for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
854         compPaintWindowToParent(pChild);
855
856     pWin->damagedDescendants = FALSE;
857 }
858
859 WindowPtr
860 CompositeRealChildHead(WindowPtr pWin)
861 {
862     WindowPtr pChild, pChildBefore;
863     CompScreenPtr cs;
864
865     if (!pWin->parent &&
866         (screenIsSaved == SCREEN_SAVER_ON) &&
867         (HasSaverWindow(pWin->drawable.pScreen))) {
868
869         /* First child is the screen saver; see if next child is the overlay */
870         pChildBefore = pWin->firstChild;
871         pChild = pChildBefore->nextSib;
872
873     }
874     else {
875         pChildBefore = NullWindow;
876         pChild = pWin->firstChild;
877     }
878
879     if (!pChild) {
880         return NullWindow;
881     }
882
883     cs = GetCompScreen(pWin->drawable.pScreen);
884     if (pChild == cs->pOverlayWin) {
885         return pChild;
886     }
887     else {
888         return pChildBefore;
889     }
890 }
891
892 int
893 compConfigNotify(WindowPtr pWin, int x, int y, int w, int h,
894                  int bw, WindowPtr pSib)
895 {
896     ScreenPtr pScreen = pWin->drawable.pScreen;
897     CompScreenPtr cs = GetCompScreen(pScreen);
898     Bool ret = 0;
899     WindowPtr pParent = pWin->parent;
900     int draw_x, draw_y;
901     Bool alloc_ret;
902
903     if (cs->ConfigNotify) {
904         pScreen->ConfigNotify = cs->ConfigNotify;
905         ret = (*pScreen->ConfigNotify) (pWin, x, y, w, h, bw, pSib);
906         cs->ConfigNotify = pScreen->ConfigNotify;
907         pScreen->ConfigNotify = compConfigNotify;
908
909         if (ret)
910             return ret;
911     }
912
913     if (pWin->redirectDraw == RedirectDrawNone)
914         return Success;
915
916     compCheckTree(pScreen);
917
918     draw_x = pParent->drawable.x + x + bw;
919     draw_y = pParent->drawable.y + y + bw;
920     alloc_ret = compReallocPixmap(pWin, draw_x, draw_y, w, h, bw);
921
922     if (alloc_ret == FALSE)
923         return BadAlloc;
924     return Success;
925 }
926
927 #ifdef _F_INPUT_REDIRECTION_
928 static void
929 print_matrix(char* name, pixman_transform_t* t)
930 {
931 #ifdef _PRINT_INPUT_REDIRECT_MATRIX_
932         int i;
933         ErrorF("[%s] %s = \n", __FUNCTION__, name);
934         for(i=0; i<3; i++)
935         {
936                 ErrorF("\t%5.2f  %5.2f  %5.2f\n"
937                         , pixman_fixed_to_double(t->matrix[i][0])
938                         , pixman_fixed_to_double(t->matrix[i][1])
939                         , pixman_fixed_to_double(t->matrix[i][2]));
940         }
941 #endif //_PRINT_INPUT_REDIRECT_MATRIX_
942 }
943
944 typedef struct {
945     CompositeSetTransformPtr SetTransform;
946 } CompositeScreenRec, *CompositeScreenPtr;
947
948 static DevPrivateKeyRec compositePrivateKeyRec;
949 #define compositePrivatePrivateKey (&compositePrivateKeyRec)
950
951 static CompositeScreenPtr
952 CompositeGetScreen(ScreenPtr pScreen)
953 {
954     if (!dixPrivateKeyRegistered(compositePrivatePrivateKey))
955         return NULL;
956     return dixLookupPrivate(&pScreen->devPrivates, compositePrivatePrivateKey);
957 }
958
959 Bool
960 CompositeScreenInit (ScreenPtr pScreen, CompositeInfoPtr info)
961 {
962     CompositeScreenPtr cs = NULL;
963
964     if (!pScreen || !info)
965         return FALSE;
966
967     if (!dixRegisterPrivateKey(&compositePrivateKeyRec, PRIVATE_SCREEN, 0))
968         return FALSE;
969
970     cs = calloc(1, sizeof *cs);
971     if (!cs)
972         return FALSE;
973
974     cs->SetTransform = info->SetTransform;
975
976     dixSetPrivate(&pScreen->devPrivates, compositePrivatePrivateKey, cs);
977
978     ErrorF ("[%s] setup complete\n", __FUNCTION__);
979
980     return TRUE;
981 }
982
983 void
984 CompositeCloseScreen (ScreenPtr pScreen)
985 {
986     CompositeScreenPtr cs = CompositeGetScreen(pScreen);
987
988     if (cs)
989         free (cs);
990 }
991
992 Bool
993 CompositeGetTransformPoint (WindowPtr pChild,
994                          int      x,
995                          int      y,
996                          int      *tx,
997                          int      *ty)
998 {
999     CompWindowPtr cw = GetCompWindow (pChild);
1000
1001     if (cw && cw->pTransform)
1002     {
1003         PictVector v;
1004         v.vector[0] = IntToxFixed(x);
1005         v.vector[1] = IntToxFixed(y);
1006         v.vector[2] = xFixed1;
1007
1008         if(pixman_transform_point(cw->pTransform, &v))
1009         {
1010             *tx = xFixedToInt(v.vector[0]);
1011             *ty = xFixedToInt(v.vector[1]);
1012             return TRUE;
1013         }
1014         else
1015         {
1016             ErrorF("[%s] Failed on pixman_transform_point()\n", __FUNCTION__);
1017         }
1018     }
1019
1020     *tx = x;
1021     *ty = y;
1022
1023     /* There is no mesh, handle events like normal */
1024     if (!cw || !cw->pTransform)
1025        return TRUE;
1026
1027     return FALSE;
1028 }
1029
1030 Bool
1031 CompositeGetInvTransformPoint (WindowPtr pChild,
1032                          int      x,
1033                          int      y,
1034                          int      *tx,
1035                          int      *ty)
1036 {
1037     if(!pChild)
1038         return FALSE;
1039     CompWindowPtr cw = GetCompWindow (pChild);
1040
1041     if (cw && cw->pInvTransform)
1042     {
1043         PictVector v;
1044         v.vector[0] = IntToxFixed(x);
1045         v.vector[1] = IntToxFixed(y);
1046         v.vector[2] = xFixed1;
1047
1048         if(pixman_transform_point(cw->pInvTransform, &v))
1049         {
1050             *tx = xFixedToInt(v.vector[0]);
1051             *ty = xFixedToInt(v.vector[1]);
1052             return TRUE;
1053         }
1054         else
1055         {
1056             ErrorF("[%s] Failed on pixman_transform_point(cw->pInvTransform, &v)\n",__FUNCTION__);
1057         }
1058     }
1059
1060     *tx = x;
1061     *ty = y;
1062
1063     /* There is no mesh, handle events like normal */
1064     if (!cw || !cw->pInvTransform)
1065     {
1066        return TRUE;
1067     }
1068
1069     return FALSE;
1070 }
1071
1072 void
1073 CompositeXYScreenToWindowRootCoordinate (WindowPtr pWin,
1074                                         int       x,
1075                                         int       y,
1076                                         int       *rootX,
1077                                         int       *rootY)
1078 {
1079     if (!pWin->parent)
1080     {
1081        *rootX = x;
1082        *rootY = y;
1083     }
1084     else
1085     {
1086        CompositeXYScreenToWindowRootCoordinate (pWin->parent, x, y, &x, &y);
1087        CompositeGetInvTransformPoint(pWin, x, y, rootX, rootY);
1088     }
1089 }
1090
1091 void
1092 CompositeXYScreenFromWindowRootCoordinate (WindowPtr pWin,
1093                                           int       x,
1094                                           int       y,
1095                                           int       *screenX,
1096                                           int       *screenY)
1097 {
1098 #ifdef _F_STEREOSCOPIC_LEFT_BUFFER_COODINATE_
1099     static Bool preferred_resolution_set = IS_NOT_SET;
1100     if(!preferred_resolution_set)
1101     {
1102         ScreenPtr pScreen = pWin->drawable.pScreen;
1103         WindowPtr rootWin = pScreen->root;
1104         prefered_w = rootWin->drawable.width ;
1105         prefered_h = rootWin->drawable.height ;
1106         preferred_resolution_set = IS_SET;
1107     }
1108 #endif
1109
1110     if (!pWin->parent)
1111     {
1112        *screenX = x;
1113        *screenY = y;
1114     }
1115     else
1116     {
1117        CompositeGetTransformPoint(pWin, x, y, &x, &y);
1118        CompositeXYScreenFromWindowRootCoordinate (pWin->parent,
1119                                                   x, y, screenX, screenY);
1120     }
1121 }
1122
1123 #ifdef _F_STEREOSCOPIC_LEFT_BUFFER_COODINATE_
1124 void
1125 CompositeXYScreenFromWindowLeftBufferCoordinate (WindowPtr pWin,
1126                                           int       x,
1127                                           int       y,
1128                                           int       *screenX,
1129                                           int       *screenY)
1130 {
1131
1132     CompositeXYScreenFromWindowRootCoordinate (pWin,x, y, screenX, screenY);
1133
1134     int fbW, fbH ;
1135     ScreenPtr pScreen = pWin->drawable.pScreen;
1136     WindowPtr rootWin = pScreen->root;
1137     fbW = rootWin->drawable.width ;
1138     fbH = rootWin->drawable.height ;
1139
1140     *screenX = (*screenX * prefered_w)/fbW ;
1141     *screenY = (*screenY * prefered_h)/fbH ;
1142
1143
1144 }
1145 #endif
1146
1147 int
1148 CompositeSetCoordinateTransform (ClientPtr pClient,
1149                                      WindowPtr pWin,
1150                                      PictTransformPtr pTransform)
1151 {
1152     CompSubwindowsPtr   csw = NULL;
1153     CompWindowPtr      cw = NULL;
1154     CompClientWindowPtr        ccw;
1155     PictTransform inv;
1156     CompositeScreenPtr cs = CompositeGetScreen(pWin->drawable.pScreen);
1157
1158     if (!dixPrivateKeyRegistered(CompSubwindowsPrivateKey))
1159     {
1160         ErrorF("[%s:%d] Failed to CompSubwindowsPrivateKey\n", __FUNCTION__, __LINE__);
1161         return BadAccess;
1162     }
1163
1164     csw = GetCompSubwindows (pWin->parent);
1165
1166     if (!dixPrivateKeyRegistered(CompWindowPrivateKey))
1167     {
1168         ErrorF("[%s:%d] Failed to CompWindowPrivateKey\n", __FUNCTION__, __LINE__);
1169         return BadAccess;
1170     }
1171
1172     cw = GetCompWindow (pWin);
1173
1174     /*
1175      * sub-window must be Manual update
1176      */
1177     if (!csw || csw->update != CompositeRedirectManual)
1178     {
1179         ErrorF("[%s] BadAccess : !csw || csw->update != CompositeRedirectManual\n", __FUNCTION__);
1180         return BadAccess;
1181     }
1182
1183     /*
1184      * must be Manual update client
1185      */
1186     for (ccw = csw->clients; ccw; ccw = ccw->next)
1187        if (ccw->update == CompositeRedirectManual &&
1188            CLIENT_ID (ccw->id) != pClient->index)
1189        {
1190            ErrorF("[%s] BadAccess : CLIENT_ID (ccw->id) != pClient->index\n", __FUNCTION__);
1191            return BadAccess;
1192        }
1193
1194     if (pTransform && pixman_transform_is_identity(pTransform))
1195     {
1196 #ifdef _PRINT_INPUT_REDIRECT_MATRIX_
1197         ErrorF("[%s] pTransform=0 : pTransform && pixman_transform_is_identity(pTransform)\n", __FUNCTION__);
1198 #endif //_PRINT_INPUT_REDIRECT_MATRIX_
1199         pTransform = 0;
1200     }
1201
1202     if (pTransform)
1203         print_matrix("pTransform", pTransform);
1204 #ifdef _PRINT_INPUT_REDIRECT_MATRIX_
1205     else
1206         ErrorF("[%s] pTransform or pTransform->matrix is NULL !\n", __FUNCTION__);
1207 #endif //_PRINT_INPUT_REDIRECT_MATRIX_
1208
1209     if (pTransform && !pixman_transform_invert(&inv, pTransform))
1210     {
1211         ErrorF("[%s] BadRequest : !pixman_transform_invert(&inv, pTransform)\n", __FUNCTION__);
1212         return BadRequest;
1213     }
1214
1215     if (pTransform)
1216     {
1217        if (!cw->pTransform)
1218        {
1219            cw->pTransform = (PictTransform *) xalloc (sizeof (PictTransform));
1220            if (!cw->pTransform)
1221            {
1222                ErrorF("[%s] BadAlloc : !cw->pTransform\n", __FUNCTION__);
1223                return BadAlloc;
1224            }
1225        }
1226
1227        if (!cw->pInvTransform)
1228        {
1229            cw->pInvTransform = (PictTransform *) xalloc (sizeof (PictTransform));
1230            if (!cw->pInvTransform)
1231            {
1232                ErrorF("[%s] BadAlloc : !cw->pInvTransform\n", __FUNCTION__);
1233                return BadAlloc;
1234            }
1235        }
1236
1237        *cw->pTransform = *pTransform;
1238        *cw->pInvTransform = inv;
1239
1240        print_matrix("CW:transform", cw->pTransform);
1241        print_matrix("CW:inv transform", cw->pInvTransform);
1242     }
1243     else
1244     {
1245        if (cw->pTransform)
1246        {
1247            xfree (cw->pTransform);
1248            cw->pTransform = 0;
1249        }
1250
1251        if (cw->pInvTransform)
1252        {
1253            xfree(cw->pInvTransform);
1254            cw->pInvTransform = 0;
1255        }
1256     }
1257
1258     if (cs && cs->SetTransform)
1259     {
1260         int ret = cs->SetTransform(pWin, pTransform);
1261
1262         if (ret != Success)
1263         {
1264             ErrorF("[%s] SetTransform return %d \n", __FUNCTION__, ret);
1265             return BadImplementation;
1266         }
1267     }
1268
1269     CheckCursorConfinement(pWin);
1270
1271     return 0;
1272 }
1273 #endif //_F_INPUT_REDIRECTION_