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