Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright (c) 2006, Oracle and/or its affiliates.
      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 /*
     24  * Copyright  2003 Keith Packard
     25  *
     26  * Permission to use, copy, modify, distribute, and sell this software and its
     27  * documentation for any purpose is hereby granted without fee, provided that
     28  * the above copyright notice appear in all copies and that both that
     29  * copyright notice and this permission notice appear in supporting
     30  * documentation, and that the name of Keith Packard not be used in
     31  * advertising or publicity pertaining to distribution of the software without
     32  * specific, written prior permission.  Keith Packard makes no
     33  * representations about the suitability of this software for any purpose.  It
     34  * is provided "as is" without express or implied warranty.
     35  *
     36  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     37  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     38  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     39  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     40  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     41  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     42  * PERFORMANCE OF THIS SOFTWARE.
     43  */
     44 
     45 #include "xcompositeint.h"
     46 
     47 XCompositeExtInfo XCompositeExtensionInfo;
     48 
     49 const char XCompositeExtensionName[] = COMPOSITE_NAME;
     50 
     51 /*
     52  * XCompositeExtRemoveDisplay - remove the indicated display from the
     53  * extension object. (Replaces XextRemoveDisplay.)
     54  */
     55 static int
     56 XCompositeExtRemoveDisplay (XCompositeExtInfo *extinfo, const Display *dpy)
     57 {
     58     XCompositeExtDisplayInfo *info, *prev;
     59 
     60     /*
     61      * locate this display and its back link so that it can be removed
     62      */
     63     _XLockMutex(_Xglobal_lock);
     64     prev = NULL;
     65     for (info = extinfo->head; info; info = info->next) {
     66 	if (info->display == dpy) break;
     67 	prev = info;
     68     }
     69     if (!info) {
     70 	_XUnlockMutex(_Xglobal_lock);
     71 	return 0;		/* hmm, actually an error */
     72     }
     73 
     74     /*
     75      * remove the display from the list; handles going to zero
     76      */
     77     if (prev)
     78 	prev->next = info->next;
     79     else
     80 	extinfo->head = info->next;
     81 
     82     extinfo->ndisplays--;
     83     if (info == extinfo->cur) extinfo->cur = NULL;  /* flush cache */
     84     _XUnlockMutex(_Xglobal_lock);
     85 
     86     Xfree (info);
     87     return 1;
     88 }
     89 
     90 static int
     91 XCompositeCloseDisplay (Display *dpy, _X_UNUSED XExtCodes *codes)
     92 {
     93     return XCompositeExtRemoveDisplay (&XCompositeExtensionInfo, dpy);
     94 }
     95 
     96 /*
     97  * XCompositeExtAddDisplay - add a display to this extension. (Replaces
     98  * XextAddDisplay)
     99  */
    100 static XCompositeExtDisplayInfo *
    101 XCompositeExtAddDisplay (XCompositeExtInfo	*extinfo,
    102 			 Display		*dpy,
    103 			 const char		*ext_name)
    104 {
    105     XCompositeExtDisplayInfo    *info;
    106 
    107     info = Xmalloc (sizeof (XCompositeExtDisplayInfo));
    108     if (!info) return NULL;
    109     info->display = dpy;
    110 
    111     info->codes = XInitExtension (dpy, ext_name);
    112 
    113     /*
    114      * if the server has the extension, then we can initialize the
    115      * appropriate function vectors
    116      */
    117     if (info->codes) {
    118 	xCompositeQueryVersionReply	rep;
    119 	xCompositeQueryVersionReq	*req;
    120         XESetCloseDisplay (dpy, info->codes->extension,
    121                            XCompositeCloseDisplay);
    122 	/*
    123 	 * Get the version info
    124 	 */
    125 	LockDisplay (dpy);
    126 	GetReq (CompositeQueryVersion, req);
    127 	req->reqType = (CARD8) info->codes->major_opcode;
    128 	req->compositeReqType = X_CompositeQueryVersion;
    129 	req->majorVersion = COMPOSITE_MAJOR;
    130 	req->minorVersion = COMPOSITE_MINOR;
    131 	if (!_XReply (dpy, (xReply *) &rep, 0, xTrue))
    132 	{
    133 	    UnlockDisplay (dpy);
    134 	    SyncHandle ();
    135 	    Xfree(info);
    136 	    return NULL;
    137 	}
    138 	info->major_version = (int) rep.majorVersion;
    139 	info->minor_version = (int) rep.minorVersion;
    140 	UnlockDisplay (dpy);
    141 	SyncHandle ();
    142     } else {
    143 	/* The server doesn't have this extension.
    144 	 * Use a private Xlib-internal extension to hang the close_display
    145 	 * hook on so that the "cache" (extinfo->cur) is properly cleaned.
    146 	 * (XBUG 7955)
    147 	 */
    148 	XExtCodes *codes = XAddExtension(dpy);
    149 	if (!codes) {
    150 	    Xfree(info);
    151 	    return NULL;
    152 	}
    153         XESetCloseDisplay (dpy, codes->extension, XCompositeCloseDisplay);
    154     }
    155 
    156     /*
    157      * now, chain it onto the list
    158      */
    159     _XLockMutex(_Xglobal_lock);
    160     info->next = extinfo->head;
    161     extinfo->head = info;
    162     extinfo->cur = info;
    163     extinfo->ndisplays++;
    164     _XUnlockMutex(_Xglobal_lock);
    165     return info;
    166 }
    167 
    168 /*
    169  * XCompositeExtFindDisplay - look for a display in this extension; keeps a
    170  * cache of the most-recently used for efficiency. (Replaces
    171  * XextFindDisplay.)
    172  */
    173 static XCompositeExtDisplayInfo *
    174 XCompositeExtFindDisplay (XCompositeExtInfo *extinfo,
    175 			  const Display	    *dpy)
    176 {
    177     XCompositeExtDisplayInfo *info;
    178 
    179     /*
    180      * see if this was the most recently accessed display
    181      */
    182     if ((info = extinfo->cur) && info->display == dpy)
    183 	return info;
    184 
    185     /*
    186      * look for display in list
    187      */
    188     _XLockMutex(_Xglobal_lock);
    189     for (info = extinfo->head; info; info = info->next) {
    190 	if (info->display == dpy) {
    191 	    extinfo->cur = info;     /* cache most recently used */
    192 	    _XUnlockMutex(_Xglobal_lock);
    193 	    return info;
    194 	}
    195     }
    196     _XUnlockMutex(_Xglobal_lock);
    197 
    198     return NULL;
    199 }
    200 
    201 XCompositeExtDisplayInfo *
    202 XCompositeFindDisplay (Display *dpy)
    203 {
    204     XCompositeExtDisplayInfo *info;
    205 
    206     info = XCompositeExtFindDisplay (&XCompositeExtensionInfo, dpy);
    207     if (!info)
    208 	info = XCompositeExtAddDisplay (&XCompositeExtensionInfo, dpy,
    209 				    XCompositeExtensionName);
    210     return info;
    211 }
    212 
    213 
    214 Bool
    215 XCompositeQueryExtension (Display *dpy,
    216 			  int *event_base_return,
    217 			  int *error_base_return)
    218 {
    219     XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy);
    220 
    221     if (XCompositeHasExtension(info))
    222     {
    223 	*event_base_return = info->codes->first_event;
    224 	*error_base_return = info->codes->first_error;
    225 	return True;
    226     }
    227     else
    228 	return False;
    229 }
    230 
    231 Status
    232 XCompositeQueryVersion (Display *dpy,
    233 		    int	    *major_version_return,
    234 		    int	    *minor_version_return)
    235 {
    236     XCompositeExtDisplayInfo	*info = XCompositeFindDisplay (dpy);
    237 
    238     XCompositeCheckExtension (dpy, info, 0);
    239     *major_version_return = info->major_version;
    240     *minor_version_return = info->minor_version;
    241     return 1;
    242 }
    243 
    244 int
    245 XCompositeVersion (void)
    246 {
    247     return XCOMPOSITE_VERSION;
    248 }
    249 
    250 void
    251 XCompositeRedirectWindow (Display *dpy, Window window, int update)
    252 {
    253     XCompositeExtDisplayInfo	    *info = XCompositeFindDisplay (dpy);
    254     xCompositeRedirectWindowReq	    *req;
    255 
    256     XCompositeSimpleCheckExtension (dpy, info);
    257     LockDisplay (dpy);
    258     GetReq (CompositeRedirectWindow, req);
    259     req->reqType = (CARD8) info->codes->major_opcode;
    260     req->compositeReqType = X_CompositeRedirectWindow;
    261     req->window = (CARD32) window;
    262     req->update = (CARD8) update;
    263     UnlockDisplay (dpy);
    264     SyncHandle ();
    265 }
    266 
    267 void
    268 XCompositeRedirectSubwindows (Display *dpy, Window window, int update)
    269 {
    270     XCompositeExtDisplayInfo	    *info = XCompositeFindDisplay (dpy);
    271     xCompositeRedirectSubwindowsReq *req;
    272 
    273     XCompositeSimpleCheckExtension (dpy, info);
    274     LockDisplay (dpy);
    275     GetReq (CompositeRedirectSubwindows, req);
    276     req->reqType = (CARD8) info->codes->major_opcode;
    277     req->compositeReqType = X_CompositeRedirectSubwindows;
    278     req->window = (CARD32) window;
    279     req->update = (CARD8) update;
    280     UnlockDisplay (dpy);
    281     SyncHandle ();
    282 }
    283 
    284 void
    285 XCompositeUnredirectWindow (Display *dpy, Window window, int update)
    286 {
    287     XCompositeExtDisplayInfo	    *info = XCompositeFindDisplay (dpy);
    288     xCompositeUnredirectWindowReq   *req;
    289 
    290     XCompositeSimpleCheckExtension (dpy, info);
    291     LockDisplay (dpy);
    292     GetReq (CompositeUnredirectWindow, req);
    293     req->reqType = (CARD8) info->codes->major_opcode;
    294     req->compositeReqType = X_CompositeUnredirectWindow;
    295     req->window = (CARD32) window;
    296     req->update = (CARD8) update;
    297     UnlockDisplay (dpy);
    298     SyncHandle ();
    299 }
    300 
    301 void
    302 XCompositeUnredirectSubwindows (Display *dpy, Window window, int update)
    303 {
    304     XCompositeExtDisplayInfo		*info = XCompositeFindDisplay (dpy);
    305     xCompositeUnredirectSubwindowsReq	*req;
    306 
    307     XCompositeSimpleCheckExtension (dpy, info);
    308     LockDisplay (dpy);
    309     GetReq (CompositeUnredirectSubwindows, req);
    310     req->reqType = (CARD8) info->codes->major_opcode;
    311     req->compositeReqType = X_CompositeUnredirectSubwindows;
    312     req->window = (CARD32) window;
    313     req->update = (CARD8) update;
    314     UnlockDisplay (dpy);
    315     SyncHandle ();
    316 }
    317 
    318 XserverRegion
    319 XCompositeCreateRegionFromBorderClip (Display *dpy, Window window)
    320 {
    321     XCompositeExtDisplayInfo		    *info = XCompositeFindDisplay (dpy);
    322     xCompositeCreateRegionFromBorderClipReq *req;
    323     XserverRegion			    region;
    324 
    325     XCompositeCheckExtension (dpy, info, 0);
    326     LockDisplay (dpy);
    327     GetReq (CompositeCreateRegionFromBorderClip, req);
    328     req->reqType = (CARD8) info->codes->major_opcode;
    329     req->compositeReqType = X_CompositeCreateRegionFromBorderClip;
    330     req->window = (CARD32) window;
    331     region = XAllocID (dpy);
    332     req->region = (CARD32) region;
    333     UnlockDisplay (dpy);
    334     SyncHandle ();
    335     return region;
    336 }
    337 
    338 Pixmap
    339 XCompositeNameWindowPixmap (Display *dpy, Window window)
    340 {
    341     XCompositeExtDisplayInfo	    *info = XCompositeFindDisplay (dpy);
    342     xCompositeNameWindowPixmapReq   *req;
    343     Pixmap			    pixmap;
    344 
    345     XCompositeCheckExtension (dpy, info, 0);
    346     LockDisplay (dpy);
    347     GetReq (CompositeNameWindowPixmap, req);
    348     req->reqType = (CARD8) info->codes->major_opcode;
    349     req->compositeReqType = X_CompositeNameWindowPixmap;
    350     req->window = (CARD32) window;
    351     pixmap = XAllocID (dpy);
    352     req->pixmap = (CARD32) pixmap;
    353     UnlockDisplay (dpy);
    354     SyncHandle ();
    355     return pixmap;
    356 }
    357 
    358 Window
    359 XCompositeGetOverlayWindow (Display *dpy, Window window)
    360 {
    361     XCompositeExtDisplayInfo	    *info = XCompositeFindDisplay (dpy);
    362     xCompositeGetOverlayWindowReq   *req;
    363     xCompositeGetOverlayWindowReply rep;
    364 
    365     XCompositeCheckExtension (dpy, info, 0);
    366     LockDisplay (dpy);
    367     GetReq (CompositeGetOverlayWindow, req);
    368     req->reqType = (CARD8) info->codes->major_opcode;
    369     req->compositeReqType = X_CompositeGetOverlayWindow;
    370     req->window = (CARD32) window;
    371     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
    372     {
    373 	UnlockDisplay (dpy);
    374 	SyncHandle ();
    375 	return 0;
    376     }
    377 
    378     UnlockDisplay (dpy);
    379     SyncHandle ();
    380 
    381     return rep.overlayWin;
    382 }
    383 
    384 void
    385 XCompositeReleaseOverlayWindow (Display *dpy, Window window)
    386 {
    387     XCompositeExtDisplayInfo	    *info = XCompositeFindDisplay (dpy);
    388     xCompositeReleaseOverlayWindowReq   *req;
    389 
    390     XCompositeSimpleCheckExtension (dpy, info);
    391     LockDisplay (dpy);
    392     GetReq (CompositeReleaseOverlayWindow, req);
    393     req->reqType = (CARD8) info->codes->major_opcode;
    394     req->compositeReqType = X_CompositeReleaseOverlayWindow;
    395     req->window = (CARD32) window;
    396     UnlockDisplay (dpy);
    397     SyncHandle ();
    398 }
    399