Change /opt/etc/X11/xkb to /etc/X11/xkb
[profile/ivi/xorg-x11-server.git] / composite / compext.c
1 /*
2  * Copyright © 2006 Sun Microsystems, Inc.  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 #include "xace.h"
50 #include "protocol-versions.h"
51
52 static CARD8    CompositeReqCode;
53 static DevPrivateKeyRec CompositeClientPrivateKeyRec;
54 #define CompositeClientPrivateKey (&CompositeClientPrivateKeyRec)
55 RESTYPE         CompositeClientWindowType;
56 RESTYPE         CompositeClientSubwindowsType;
57 RESTYPE         CompositeClientOverlayType;
58
59 typedef struct _CompositeClient {
60     int     major_version;
61     int     minor_version;
62 } CompositeClientRec, *CompositeClientPtr;
63
64 #define GetCompositeClient(pClient) ((CompositeClientPtr) \
65     dixLookupPrivate(&(pClient)->devPrivates, CompositeClientPrivateKey))
66
67 static void
68 CompositeClientCallback (CallbackListPtr        *list,
69                       pointer           closure,
70                       pointer           data)
71 {
72     NewClientInfoRec    *clientinfo = (NewClientInfoRec *) data;
73     ClientPtr           pClient = clientinfo->client;
74     CompositeClientPtr  pCompositeClient = GetCompositeClient (pClient);
75
76     pCompositeClient->major_version = 0;
77     pCompositeClient->minor_version = 0;
78 }
79
80 static int
81 FreeCompositeClientWindow (pointer value, XID ccwid)
82 {
83     WindowPtr   pWin = value;
84
85     compFreeClientWindow (pWin, ccwid);
86     return Success;
87 }
88
89 static int
90 FreeCompositeClientSubwindows (pointer value, XID ccwid)
91 {
92     WindowPtr   pWin = value;
93
94     compFreeClientSubwindows (pWin, ccwid);
95     return Success;
96 }
97
98 static int
99 FreeCompositeClientOverlay (pointer value, XID ccwid)
100 {
101     CompOverlayClientPtr pOc = (CompOverlayClientPtr) value;
102
103     compFreeOverlayClient (pOc);
104     return Success;
105 }
106
107 static int
108 ProcCompositeQueryVersion (ClientPtr client)
109 {
110     CompositeClientPtr pCompositeClient = GetCompositeClient (client);
111     xCompositeQueryVersionReply rep;
112     register int n;
113     REQUEST(xCompositeQueryVersionReq);
114
115     REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
116     rep.type = X_Reply;
117     rep.length = 0;
118     rep.sequenceNumber = client->sequence;
119     if (stuff->majorVersion < SERVER_COMPOSITE_MAJOR_VERSION) {
120         rep.majorVersion = stuff->majorVersion;
121         rep.minorVersion = stuff->minorVersion;
122     } else {
123         rep.majorVersion = SERVER_COMPOSITE_MAJOR_VERSION;
124         rep.minorVersion = SERVER_COMPOSITE_MINOR_VERSION;
125     }
126     pCompositeClient->major_version = rep.majorVersion;
127     pCompositeClient->minor_version = rep.minorVersion;
128     if (client->swapped) {
129         swaps(&rep.sequenceNumber, n);
130         swapl(&rep.length, n);
131         swapl(&rep.majorVersion, n);
132         swapl(&rep.minorVersion, n);
133     }
134     WriteToClient(client, sizeof(xCompositeQueryVersionReply), (char *)&rep);
135     return Success;
136 }
137
138 #define VERIFY_WINDOW(pWindow, wid, client, mode)                       \
139     do {                                                                \
140         int err;                                                        \
141         err = dixLookupResourceByType((pointer *) &pWindow, wid,        \
142                                       RT_WINDOW, client, mode);         \
143         if (err != Success) {                                           \
144             client->errorValue = wid;                                   \
145             return err;                                                 \
146         }                                                               \
147     } while (0)
148
149 static int
150 ProcCompositeRedirectWindow (ClientPtr client)
151 {
152     WindowPtr   pWin;
153     REQUEST(xCompositeRedirectWindowReq);
154
155     REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
156     VERIFY_WINDOW(pWin, stuff->window, client,
157                   DixSetAttrAccess|DixManageAccess|DixBlendAccess);
158
159     return compRedirectWindow (client, pWin, stuff->update);
160 }
161
162 static int
163 ProcCompositeRedirectSubwindows (ClientPtr client)
164 {
165     WindowPtr   pWin;
166     REQUEST(xCompositeRedirectSubwindowsReq);
167
168     REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
169     VERIFY_WINDOW(pWin, stuff->window, client,
170                   DixSetAttrAccess|DixManageAccess|DixBlendAccess);
171
172     return compRedirectSubwindows (client, pWin, stuff->update);
173 }
174
175 static int
176 ProcCompositeUnredirectWindow (ClientPtr client)
177 {
178     WindowPtr   pWin;
179     REQUEST(xCompositeUnredirectWindowReq);
180
181     REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
182     VERIFY_WINDOW(pWin, stuff->window, client,
183                   DixSetAttrAccess|DixManageAccess|DixBlendAccess);
184
185     return compUnredirectWindow (client, pWin, stuff->update);
186 }
187
188 static int
189 ProcCompositeUnredirectSubwindows (ClientPtr client)
190 {
191     WindowPtr   pWin;
192     REQUEST(xCompositeUnredirectSubwindowsReq);
193
194     REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
195     VERIFY_WINDOW(pWin, stuff->window, client,
196                   DixSetAttrAccess|DixManageAccess|DixBlendAccess);
197
198     return compUnredirectSubwindows (client, pWin, stuff->update);
199 }
200
201 static int
202 ProcCompositeCreateRegionFromBorderClip (ClientPtr client)
203 {
204     WindowPtr       pWin;
205     CompWindowPtr   cw;
206     RegionPtr       pBorderClip, pRegion;
207     REQUEST(xCompositeCreateRegionFromBorderClipReq);
208
209     REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
210     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
211     LEGAL_NEW_RESOURCE (stuff->region, client);
212     
213     cw = GetCompWindow (pWin);
214     if (cw)
215         pBorderClip = &cw->borderClip;
216     else
217         pBorderClip = &pWin->borderClip;
218     pRegion = XFixesRegionCopy (pBorderClip);
219     if (!pRegion)
220         return BadAlloc;
221     RegionTranslate(pRegion, -pWin->drawable.x, -pWin->drawable.y);
222     
223     if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
224         return BadAlloc;
225
226     return Success;
227 }
228
229 static int
230 ProcCompositeNameWindowPixmap (ClientPtr client)
231 {
232     WindowPtr       pWin;
233     CompWindowPtr   cw;
234     PixmapPtr       pPixmap;
235     int rc;
236     REQUEST(xCompositeNameWindowPixmapReq);
237
238     REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
239     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
240
241     if (!pWin->viewable)
242         return BadMatch;
243
244     LEGAL_NEW_RESOURCE (stuff->pixmap, client);
245     
246     cw = GetCompWindow (pWin);
247     if (!cw)
248         return BadMatch;
249
250     pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
251     if (!pPixmap)
252         return BadMatch;
253
254     /* security creation/labeling check */
255     rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
256                   pPixmap, RT_WINDOW, pWin, DixCreateAccess);
257     if (rc != Success)
258         return rc;
259
260     ++pPixmap->refcnt;
261
262     if (!AddResource (stuff->pixmap, RT_PIXMAP, (pointer) pPixmap))
263         return BadAlloc;
264
265     return Success;
266 }
267
268
269 static int
270 ProcCompositeGetOverlayWindow (ClientPtr client)
271 {
272     REQUEST(xCompositeGetOverlayWindowReq); 
273     xCompositeGetOverlayWindowReply rep;
274     WindowPtr pWin;
275     ScreenPtr pScreen;
276     CompScreenPtr cs;
277     CompOverlayClientPtr pOc;
278     int rc;
279
280     REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
281     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
282     pScreen = pWin->drawable.pScreen;
283
284     /* 
285      * Create an OverlayClient structure to mark this client's
286      * interest in the overlay window
287      */
288     pOc = compCreateOverlayClient(pScreen, client);
289     if (pOc == NULL)
290         return BadAlloc;
291
292     /*
293      * Make sure the overlay window exists
294      */
295     cs = GetCompScreen(pScreen);
296     if (cs->pOverlayWin == NULL)
297         if (!compCreateOverlayWindow(pScreen))
298         {
299             FreeResource (pOc->resource, RT_NONE);
300             return BadAlloc;
301         }
302
303     rc = XaceHook(XACE_RESOURCE_ACCESS, client, cs->pOverlayWin->drawable.id,
304                   RT_WINDOW, cs->pOverlayWin, RT_NONE, NULL, DixGetAttrAccess);
305     if (rc != Success)
306     {
307         FreeResource (pOc->resource, RT_NONE);
308         return rc;
309     }
310
311     rep.type = X_Reply;
312     rep.sequenceNumber = client->sequence;
313     rep.length = 0;
314     rep.overlayWin = cs->pOverlayWin->drawable.id;
315
316     if (client->swapped)
317     {
318         int n;
319         swaps(&rep.sequenceNumber, n);
320         swapl(&rep.length, n);
321         swapl(&rep.overlayWin, n);
322     }
323     (void) WriteToClient(client, sz_xCompositeGetOverlayWindowReply, (char *)&rep);
324
325     return Success;
326 }
327
328 static int
329 ProcCompositeReleaseOverlayWindow (ClientPtr client)
330 {
331     REQUEST(xCompositeReleaseOverlayWindowReq); 
332     WindowPtr pWin;
333     ScreenPtr pScreen;
334     CompOverlayClientPtr pOc;
335
336     REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
337     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
338     pScreen = pWin->drawable.pScreen;
339
340     /* 
341      * Has client queried a reference to the overlay window
342      * on this screen? If not, generate an error.
343      */
344     pOc = compFindOverlayClient (pWin->drawable.pScreen, client);
345     if (pOc == NULL)
346         return BadMatch;
347
348     /* The delete function will free the client structure */
349     FreeResource (pOc->resource, RT_NONE);
350
351     return Success;
352 }
353
354 static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
355     ProcCompositeQueryVersion,
356     ProcCompositeRedirectWindow,
357     ProcCompositeRedirectSubwindows,
358     ProcCompositeUnredirectWindow,
359     ProcCompositeUnredirectSubwindows,
360     ProcCompositeCreateRegionFromBorderClip,
361     ProcCompositeNameWindowPixmap,
362     ProcCompositeGetOverlayWindow,
363     ProcCompositeReleaseOverlayWindow,
364 };
365
366 static int
367 ProcCompositeDispatch (ClientPtr client)
368 {
369     REQUEST(xReq);
370     
371     if (stuff->data < CompositeNumberRequests)
372         return (*ProcCompositeVector[stuff->data]) (client);
373     else
374         return BadRequest;
375 }
376
377 static int
378 SProcCompositeQueryVersion (ClientPtr client)
379 {
380     int n;
381     REQUEST(xCompositeQueryVersionReq);
382
383     swaps(&stuff->length, n);
384     REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
385     swapl(&stuff->majorVersion, n);
386     swapl(&stuff->minorVersion, n);
387     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
388 }
389
390 static int
391 SProcCompositeRedirectWindow (ClientPtr client)
392 {
393     int n;
394     REQUEST(xCompositeRedirectWindowReq);
395
396     swaps(&stuff->length, n);
397     REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
398     swapl (&stuff->window, n);
399     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
400 }
401
402 static int
403 SProcCompositeRedirectSubwindows (ClientPtr client)
404 {
405     int n;
406     REQUEST(xCompositeRedirectSubwindowsReq);
407
408     swaps(&stuff->length, n);
409     REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
410     swapl (&stuff->window, n);
411     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
412 }
413
414 static int
415 SProcCompositeUnredirectWindow (ClientPtr client)
416 {
417     int n;
418     REQUEST(xCompositeUnredirectWindowReq);
419
420     swaps(&stuff->length, n);
421     REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
422     swapl (&stuff->window, n);
423     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
424 }
425
426 static int
427 SProcCompositeUnredirectSubwindows (ClientPtr client)
428 {
429     int n;
430     REQUEST(xCompositeUnredirectSubwindowsReq);
431
432     swaps(&stuff->length, n);
433     REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
434     swapl (&stuff->window, n);
435     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
436 }
437
438 static int
439 SProcCompositeCreateRegionFromBorderClip (ClientPtr client)
440 {
441     int n;
442     REQUEST(xCompositeCreateRegionFromBorderClipReq);
443
444     swaps(&stuff->length, n);
445     REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
446     swapl (&stuff->region, n);
447     swapl (&stuff->window, n);
448     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
449 }
450
451 static int
452 SProcCompositeNameWindowPixmap (ClientPtr client)
453 {
454     int n;
455     REQUEST(xCompositeNameWindowPixmapReq);
456
457     swaps(&stuff->length, n);
458     REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
459     swapl (&stuff->window, n);
460     swapl (&stuff->pixmap, n);
461     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
462 }
463
464 static int
465 SProcCompositeGetOverlayWindow (ClientPtr client)
466 {
467     int n;
468     REQUEST(xCompositeGetOverlayWindowReq);
469
470     swaps (&stuff->length, n);
471     REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
472     swapl(&stuff->window, n);
473     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
474 }
475
476 static int
477 SProcCompositeReleaseOverlayWindow (ClientPtr client)
478 {
479     int n;
480     REQUEST(xCompositeReleaseOverlayWindowReq);
481
482     swaps (&stuff->length, n);
483     REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
484     swapl(&stuff->window, n);
485     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
486 }
487
488 static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
489     SProcCompositeQueryVersion,
490     SProcCompositeRedirectWindow,
491     SProcCompositeRedirectSubwindows,
492     SProcCompositeUnredirectWindow,
493     SProcCompositeUnredirectSubwindows,
494     SProcCompositeCreateRegionFromBorderClip,
495     SProcCompositeNameWindowPixmap,
496     SProcCompositeGetOverlayWindow,
497     SProcCompositeReleaseOverlayWindow,
498 };
499
500 static int
501 SProcCompositeDispatch (ClientPtr client)
502 {
503     REQUEST(xReq);
504     
505     if (stuff->data < CompositeNumberRequests)
506         return (*SProcCompositeVector[stuff->data]) (client);
507     else
508         return BadRequest;
509 }
510
511 void
512 CompositeExtensionInit (void)
513 {
514     ExtensionEntry  *extEntry;
515     int             s;
516
517     /* Assume initialization is going to fail */
518     noCompositeExtension = TRUE;
519
520     for (s = 0; s < screenInfo.numScreens; s++) {
521         ScreenPtr pScreen = screenInfo.screens[s];
522         VisualPtr vis;
523
524         /* Composite on 8bpp pseudocolor root windows appears to fail, so
525          * just disable it on anything pseudocolor for safety.
526          */
527         for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++)
528             ;
529         if ((vis->class | DynamicClass) == PseudoColor)
530             return;
531
532         /* Ensure that Render is initialized, which is required for automatic
533          * compositing.
534          */
535         if (GetPictureScreenIfSet(pScreen) == NULL)
536             return;
537     }
538 #ifdef PANORAMIX
539     /* Xinerama's rewriting of window drawing before Composite gets to it
540      * breaks Composite.
541      */
542     if (!noPanoramiXExtension)
543         return;
544 #endif
545
546     CompositeClientWindowType = CreateNewResourceType
547         (FreeCompositeClientWindow, "CompositeClientWindow");
548     if (!CompositeClientWindowType)
549         return;
550
551     CompositeClientSubwindowsType = CreateNewResourceType
552         (FreeCompositeClientSubwindows, "CompositeClientSubwindows");
553     if (!CompositeClientSubwindowsType)
554         return;
555
556     CompositeClientOverlayType = CreateNewResourceType
557         (FreeCompositeClientOverlay, "CompositeClientOverlay");
558     if (!CompositeClientOverlayType)
559         return;
560
561     if (!dixRegisterPrivateKey(&CompositeClientPrivateKeyRec, PRIVATE_CLIENT,
562                                sizeof(CompositeClientRec)))
563         return;
564
565     if (!AddCallback (&ClientStateCallback, CompositeClientCallback, 0))
566         return;
567
568     for (s = 0; s < screenInfo.numScreens; s++)
569         if (!compScreenInit (screenInfo.screens[s]))
570             return;
571
572     extEntry = AddExtension (COMPOSITE_NAME, 0, 0,
573                              ProcCompositeDispatch, SProcCompositeDispatch,
574                              NULL, StandardMinorOpcode);
575     if (!extEntry)
576         return;
577     CompositeReqCode = (CARD8) extEntry->base;
578
579     miRegisterRedirectBorderClipProc (compSetRedirectBorderClip,
580                                       compGetRedirectBorderClip);
581
582     /* Initialization succeeded */
583     noCompositeExtension = FALSE;
584 }