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 /*
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
XCompositeExtRemoveDisplay(XCompositeExtInfo * extinfo,Display * dpy)56 XCompositeExtRemoveDisplay (XCompositeExtInfo *extinfo, 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 ((char *) info);
87 return 1;
88 }
89
90 static int
XCompositeCloseDisplay(Display * dpy,XExtCodes * codes)91 XCompositeCloseDisplay (Display *dpy, 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 *
XCompositeExtAddDisplay(XCompositeExtInfo * extinfo,Display * dpy,const char * ext_name)101 XCompositeExtAddDisplay (XCompositeExtInfo *extinfo,
102 Display *dpy,
103 const char *ext_name)
104 {
105 XCompositeExtDisplayInfo *info;
106
107 info = (XCompositeExtDisplayInfo *) 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 = 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 = rep.majorVersion;
139 info->minor_version = 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 *
XCompositeExtFindDisplay(XCompositeExtInfo * extinfo,Display * dpy)174 XCompositeExtFindDisplay (XCompositeExtInfo *extinfo,
175 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 *
XCompositeFindDisplay(Display * dpy)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
XCompositeQueryExtension(Display * dpy,int * event_base_return,int * error_base_return)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
XCompositeQueryVersion(Display * dpy,int * major_version_return,int * minor_version_return)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
XCompositeVersion(void)245 XCompositeVersion (void)
246 {
247 return XCOMPOSITE_VERSION;
248 }
249
250 void
XCompositeRedirectWindow(Display * dpy,Window window,int update)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 = info->codes->major_opcode;
260 req->compositeReqType = X_CompositeRedirectWindow;
261 req->window = window;
262 req->update = update;
263 UnlockDisplay (dpy);
264 SyncHandle ();
265 }
266
267 void
XCompositeRedirectSubwindows(Display * dpy,Window window,int update)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 = info->codes->major_opcode;
277 req->compositeReqType = X_CompositeRedirectSubwindows;
278 req->window = window;
279 req->update = update;
280 UnlockDisplay (dpy);
281 SyncHandle ();
282 }
283
284 void
XCompositeUnredirectWindow(Display * dpy,Window window,int update)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 = info->codes->major_opcode;
294 req->compositeReqType = X_CompositeUnredirectWindow;
295 req->window = window;
296 req->update = update;
297 UnlockDisplay (dpy);
298 SyncHandle ();
299 }
300
301 void
XCompositeUnredirectSubwindows(Display * dpy,Window window,int update)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 = info->codes->major_opcode;
311 req->compositeReqType = X_CompositeUnredirectSubwindows;
312 req->window = window;
313 req->update = update;
314 UnlockDisplay (dpy);
315 SyncHandle ();
316 }
317
318 XserverRegion
XCompositeCreateRegionFromBorderClip(Display * dpy,Window window)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 = info->codes->major_opcode;
329 req->compositeReqType = X_CompositeCreateRegionFromBorderClip;
330 req->window = window;
331 region = req->region = XAllocID (dpy);
332 UnlockDisplay (dpy);
333 SyncHandle ();
334 return region;
335 }
336
337 Pixmap
XCompositeNameWindowPixmap(Display * dpy,Window window)338 XCompositeNameWindowPixmap (Display *dpy, Window window)
339 {
340 XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy);
341 xCompositeNameWindowPixmapReq *req;
342 Pixmap pixmap;
343
344 XCompositeCheckExtension (dpy, info, 0);
345 LockDisplay (dpy);
346 GetReq (CompositeNameWindowPixmap, req);
347 req->reqType = info->codes->major_opcode;
348 req->compositeReqType = X_CompositeNameWindowPixmap;
349 req->window = window;
350 pixmap = req->pixmap = XAllocID (dpy);
351 UnlockDisplay (dpy);
352 SyncHandle ();
353 return pixmap;
354 }
355
356 Window
XCompositeGetOverlayWindow(Display * dpy,Window window)357 XCompositeGetOverlayWindow (Display *dpy, Window window)
358 {
359 XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy);
360 xCompositeGetOverlayWindowReq *req;
361 xCompositeGetOverlayWindowReply rep;
362
363 XCompositeCheckExtension (dpy, info, 0);
364 LockDisplay (dpy);
365 GetReq (CompositeGetOverlayWindow, req);
366 req->reqType = info->codes->major_opcode;
367 req->compositeReqType = X_CompositeGetOverlayWindow;
368 req->window = window;
369 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
370 {
371 UnlockDisplay (dpy);
372 SyncHandle ();
373 return 0;
374 }
375
376 UnlockDisplay (dpy);
377 SyncHandle ();
378
379 return rep.overlayWin;
380 }
381
382 void
XCompositeReleaseOverlayWindow(Display * dpy,Window window)383 XCompositeReleaseOverlayWindow (Display *dpy, Window window)
384 {
385 XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy);
386 xCompositeReleaseOverlayWindowReq *req;
387
388 XCompositeSimpleCheckExtension (dpy, info);
389 LockDisplay (dpy);
390 GetReq (CompositeReleaseOverlayWindow, req);
391 req->reqType = info->codes->major_opcode;
392 req->compositeReqType = X_CompositeReleaseOverlayWindow;
393 req->window = window;
394 UnlockDisplay (dpy);
395 SyncHandle ();
396 }
397