4 * Copyright © 2003 Keith Packard
5 * Copyright © 2007 Eric Anholt
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Keith Packard not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. Keith Packard makes no
14 * representations about the suitability of this software for any purpose. It
15 * is provided "as is" without express or implied warranty.
17 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
29 #include "xdamageint.h"
31 XDamageExtInfo XDamageExtensionInfo;
33 const char XDamageExtensionName[] = DAMAGE_NAME;
36 XDamageCloseDisplay (Display *dpy, XExtCodes *codes);
39 XDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire);
42 XDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire);
45 * XDamageExtAddDisplay - add a display to this extension. (Replaces
48 static XDamageExtDisplayInfo *
49 XDamageExtAddDisplay (XDamageExtInfo *extinfo,
53 XDamageExtDisplayInfo *info;
56 info = (XDamageExtDisplayInfo *) Xmalloc (sizeof (XDamageExtDisplayInfo));
57 if (!info) return NULL;
60 info->codes = XInitExtension (dpy, ext_name);
63 * if the server has the extension, then we can initialize the
64 * appropriate function vectors
67 xDamageQueryVersionReply rep;
68 xDamageQueryVersionReq *req;
69 XESetCloseDisplay (dpy, info->codes->extension,
71 for (ev = info->codes->first_event;
72 ev < info->codes->first_event + XDamageNumberEvents;
75 XESetWireToEvent (dpy, ev, XDamageWireToEvent);
76 XESetEventToWire (dpy, ev, XDamageEventToWire);
79 * Get the version info
82 GetReq (DamageQueryVersion, req);
83 req->reqType = info->codes->major_opcode;
84 req->damageReqType = X_DamageQueryVersion;
85 req->majorVersion = DAMAGE_MAJOR;
86 req->minorVersion = DAMAGE_MINOR;
87 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue))
94 info->major_version = rep.majorVersion;
95 info->minor_version = rep.minorVersion;
99 /* The server doesn't have this extension.
100 * Use a private Xlib-internal extension to hang the close_display
101 * hook on so that the "cache" (extinfo->cur) is properly cleaned.
104 XExtCodes *codes = XAddExtension(dpy);
109 XESetCloseDisplay (dpy, codes->extension, XDamageCloseDisplay);
113 * now, chain it onto the list
115 _XLockMutex(_Xglobal_lock);
116 info->next = extinfo->head;
117 extinfo->head = info;
119 extinfo->ndisplays++;
120 _XUnlockMutex(_Xglobal_lock);
126 * XDamageExtRemoveDisplay - remove the indicated display from the
127 * extension object. (Replaces XextRemoveDisplay.)
130 XDamageExtRemoveDisplay (XDamageExtInfo *extinfo, Display *dpy)
132 XDamageExtDisplayInfo *info, *prev;
135 * locate this display and its back link so that it can be removed
137 _XLockMutex(_Xglobal_lock);
139 for (info = extinfo->head; info; info = info->next) {
140 if (info->display == dpy) break;
144 _XUnlockMutex(_Xglobal_lock);
145 return 0; /* hmm, actually an error */
149 * remove the display from the list; handles going to zero
152 prev->next = info->next;
154 extinfo->head = info->next;
156 extinfo->ndisplays--;
157 if (info == extinfo->cur) extinfo->cur = NULL; /* flush cache */
158 _XUnlockMutex(_Xglobal_lock);
160 Xfree ((char *) info);
165 * XDamageExtFindDisplay - look for a display in this extension; keeps a
166 * cache of the most-recently used for efficiency. (Replaces
169 static XDamageExtDisplayInfo *
170 XDamageExtFindDisplay (XDamageExtInfo *extinfo,
173 XDamageExtDisplayInfo *info;
176 * see if this was the most recently accessed display
178 if ((info = extinfo->cur) && info->display == dpy)
182 * look for display in list
184 _XLockMutex(_Xglobal_lock);
185 for (info = extinfo->head; info; info = info->next) {
186 if (info->display == dpy) {
187 extinfo->cur = info; /* cache most recently used */
188 _XUnlockMutex(_Xglobal_lock);
192 _XUnlockMutex(_Xglobal_lock);
197 XDamageExtDisplayInfo *
198 XDamageFindDisplay (Display *dpy)
200 XDamageExtDisplayInfo *info;
202 info = XDamageExtFindDisplay (&XDamageExtensionInfo, dpy);
204 info = XDamageExtAddDisplay (&XDamageExtensionInfo, dpy,
205 XDamageExtensionName);
210 XDamageCloseDisplay (Display *dpy, XExtCodes *codes)
212 return XDamageExtRemoveDisplay (&XDamageExtensionInfo, dpy);
216 XDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
218 XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy);
220 XDamageCheckExtension(dpy, info, False);
222 switch ((wire->u.u.type & 0x7F) - info->codes->first_event)
224 case XDamageNotify: {
225 XDamageNotifyEvent *aevent = (XDamageNotifyEvent *) event;
226 xDamageNotifyEvent *awire = (xDamageNotifyEvent *) wire;
228 aevent->type = awire->type & 0x7F;
229 aevent->serial = _XSetLastRequestRead(dpy,
230 (xGenericReply *) wire);
231 aevent->send_event = (awire->type & 0x80) != 0;
232 aevent->display = dpy;
233 aevent->drawable = awire->drawable;
234 aevent->damage = awire->damage;
235 aevent->level = awire->level & ~DamageNotifyMore;
236 aevent->more = (awire->level & DamageNotifyMore) ? True : False;
237 aevent->timestamp = awire->timestamp;
238 aevent->area.x = awire->area.x;
239 aevent->area.y = awire->area.y;
240 aevent->area.width = awire->area.width;
241 aevent->area.height = awire->area.height;
242 aevent->geometry.x = awire->geometry.x;
243 aevent->geometry.y = awire->geometry.y;
244 aevent->geometry.width = awire->geometry.width;
245 aevent->geometry.height = awire->geometry.height;
253 XDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire)
255 XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy);
257 XDamageCheckExtension(dpy, info, False);
259 switch ((event->type & 0x7F) - info->codes->first_event)
261 case XDamageNotify: {
262 XDamageNotifyEvent *aevent;
263 xDamageNotifyEvent *awire;
264 awire = (xDamageNotifyEvent *) wire;
265 aevent = (XDamageNotifyEvent *) event;
266 awire->type = aevent->type | (aevent->send_event ? 0x80 : 0);
267 awire->drawable = aevent->drawable;
268 awire->damage = aevent->damage;
269 awire->level = aevent->level | (aevent->more ? DamageNotifyMore : 0);
270 awire->timestamp = aevent->timestamp;
271 awire->area.x = aevent->area.x;
272 awire->area.y = aevent->area.y;
273 awire->area.width = aevent->area.width;
274 awire->area.height = aevent->area.height;
275 awire->geometry.x = aevent->geometry.x;
276 awire->geometry.y = aevent->geometry.y;
277 awire->geometry.width = aevent->geometry.width;
278 awire->geometry.height = aevent->geometry.height;
286 XDamageQueryExtension (Display *dpy,
287 int *event_base_return,
288 int *error_base_return)
290 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
292 if (XDamageHasExtension(info))
294 *event_base_return = info->codes->first_event;
295 *error_base_return = info->codes->first_error;
303 XDamageQueryVersion (Display *dpy,
304 int *major_version_return,
305 int *minor_version_return)
307 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
309 XDamageCheckExtension (dpy, info, 0);
311 *major_version_return = info->major_version;
312 *minor_version_return = info->minor_version;
317 XDamageCreate (Display *dpy, Drawable drawable, int level)
319 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
320 xDamageCreateReq *req;
323 XDamageCheckExtension (dpy, info, 0);
325 GetReq (DamageCreate, req);
326 req->reqType = info->codes->major_opcode;
327 req->damageReqType = X_DamageCreate;
328 req->damage = damage = XAllocID (dpy);
329 req->drawable = drawable;
337 XDamageDestroy (Display *dpy, Damage damage)
339 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
340 xDamageDestroyReq *req;
342 XDamageSimpleCheckExtension (dpy, info);
344 GetReq (DamageDestroy, req);
345 req->reqType = info->codes->major_opcode;
346 req->damageReqType = X_DamageDestroy;
347 req->damage = damage;
353 XDamageSubtract (Display *dpy, Damage damage,
354 XserverRegion repair, XserverRegion parts)
356 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
357 xDamageSubtractReq *req;
359 XDamageSimpleCheckExtension (dpy, info);
361 GetReq (DamageSubtract, req);
362 req->reqType = info->codes->major_opcode;
363 req->damageReqType = X_DamageSubtract;
364 req->damage = damage;
365 req->repair = repair;
372 XDamageAdd (Display *dpy, Drawable drawable, XserverRegion region)
374 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
377 XDamageSimpleCheckExtension (dpy, info);
379 GetReq (DamageAdd, req);
380 req->reqType = info->codes->major_opcode;
381 req->damageReqType = X_DamageAdd;
382 req->drawable = drawable;
383 req->region = region;