4 * Copyright © 2003 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
28 #include "xdamageint.h"
30 XDamageExtInfo XDamageExtensionInfo;
32 const char XDamageExtensionName[] = DAMAGE_NAME;
35 XDamageCloseDisplay (Display *dpy, XExtCodes *codes);
38 XDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire);
41 XDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire);
44 * XDamageExtAddDisplay - add a display to this extension. (Replaces
47 static XDamageExtDisplayInfo *
48 XDamageExtAddDisplay (XDamageExtInfo *extinfo,
52 XDamageExtDisplayInfo *info;
55 info = (XDamageExtDisplayInfo *) Xmalloc (sizeof (XDamageExtDisplayInfo));
56 if (!info) return NULL;
59 info->codes = XInitExtension (dpy, ext_name);
62 * if the server has the extension, then we can initialize the
63 * appropriate function vectors
66 xDamageQueryVersionReply rep;
67 xDamageQueryVersionReq *req;
68 XESetCloseDisplay (dpy, info->codes->extension,
70 for (ev = info->codes->first_event;
71 ev < info->codes->first_event + XDamageNumberEvents;
74 XESetWireToEvent (dpy, ev, XDamageWireToEvent);
75 XESetEventToWire (dpy, ev, XDamageEventToWire);
78 * Get the version info
81 GetReq (DamageQueryVersion, req);
82 req->reqType = info->codes->major_opcode;
83 req->damageReqType = X_DamageQueryVersion;
84 req->majorVersion = DAMAGE_MAJOR;
85 req->minorVersion = DAMAGE_MINOR;
86 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue))
93 info->major_version = rep.majorVersion;
94 info->minor_version = rep.minorVersion;
97 /* The server doesn't have this extension.
98 * Use a private Xlib-internal extension to hang the close_display
99 * hook on so that the "cache" (extinfo->cur) is properly cleaned.
102 XExtCodes *codes = XAddExtension(dpy);
107 XESetCloseDisplay (dpy, codes->extension, XDamageCloseDisplay);
111 * now, chain it onto the list
113 _XLockMutex(_Xglobal_lock);
114 info->next = extinfo->head;
115 extinfo->head = info;
117 extinfo->ndisplays++;
118 _XUnlockMutex(_Xglobal_lock);
124 * XDamageExtRemoveDisplay - remove the indicated display from the
125 * extension object. (Replaces XextRemoveDisplay.)
128 XDamageExtRemoveDisplay (XDamageExtInfo *extinfo, Display *dpy)
130 XDamageExtDisplayInfo *info, *prev;
133 * locate this display and its back link so that it can be removed
135 _XLockMutex(_Xglobal_lock);
137 for (info = extinfo->head; info; info = info->next) {
138 if (info->display == dpy) break;
142 _XUnlockMutex(_Xglobal_lock);
143 return 0; /* hmm, actually an error */
147 * remove the display from the list; handles going to zero
150 prev->next = info->next;
152 extinfo->head = info->next;
154 extinfo->ndisplays--;
155 if (info == extinfo->cur) extinfo->cur = NULL; /* flush cache */
156 _XUnlockMutex(_Xglobal_lock);
158 Xfree ((char *) info);
163 * XDamageExtFindDisplay - look for a display in this extension; keeps a
164 * cache of the most-recently used for efficiency. (Replaces
167 static XDamageExtDisplayInfo *
168 XDamageExtFindDisplay (XDamageExtInfo *extinfo,
171 XDamageExtDisplayInfo *info;
174 * see if this was the most recently accessed display
176 if ((info = extinfo->cur) && info->display == dpy)
180 * look for display in list
182 _XLockMutex(_Xglobal_lock);
183 for (info = extinfo->head; info; info = info->next) {
184 if (info->display == dpy) {
185 extinfo->cur = info; /* cache most recently used */
186 _XUnlockMutex(_Xglobal_lock);
190 _XUnlockMutex(_Xglobal_lock);
195 XDamageExtDisplayInfo *
196 XDamageFindDisplay (Display *dpy)
198 XDamageExtDisplayInfo *info;
200 info = XDamageExtFindDisplay (&XDamageExtensionInfo, dpy);
202 info = XDamageExtAddDisplay (&XDamageExtensionInfo, dpy,
203 XDamageExtensionName);
208 XDamageCloseDisplay (Display *dpy, XExtCodes *codes)
210 return XDamageExtRemoveDisplay (&XDamageExtensionInfo, dpy);
214 XDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
216 XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy);
218 XDamageCheckExtension(dpy, info, False);
220 switch ((wire->u.u.type & 0x7F) - info->codes->first_event)
222 case XDamageNotify: {
223 XDamageNotifyEvent *aevent = (XDamageNotifyEvent *) event;
224 xDamageNotifyEvent *awire = (xDamageNotifyEvent *) wire;
226 aevent->type = awire->type & 0x7F;
227 aevent->serial = _XSetLastRequestRead(dpy,
228 (xGenericReply *) wire);
229 aevent->send_event = (awire->type & 0x80) != 0;
230 aevent->display = dpy;
231 aevent->drawable = awire->drawable;
232 aevent->damage = awire->damage;
233 aevent->level = awire->level;
234 aevent->timestamp = awire->timestamp;
235 aevent->area.x = awire->area.x;
236 aevent->area.y = awire->area.y;
237 aevent->area.width = awire->area.width;
238 aevent->area.height = awire->area.height;
239 aevent->geometry.x = awire->geometry.x;
240 aevent->geometry.y = awire->geometry.y;
241 aevent->geometry.width = awire->geometry.width;
242 aevent->geometry.height = awire->geometry.height;
250 XDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire)
252 XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy);
254 XDamageCheckExtension(dpy, info, False);
256 switch ((event->type & 0x7F) - info->codes->first_event)
258 case XDamageNotify: {
259 XDamageNotifyEvent *aevent;
260 xDamageNotifyEvent *awire;
261 awire = (xDamageNotifyEvent *) wire;
262 aevent = (XDamageNotifyEvent *) event;
263 awire->type = aevent->type | (aevent->send_event ? 0x80 : 0);
264 awire->drawable = aevent->drawable;
265 awire->damage = aevent->damage;
266 awire->level = aevent->level;
267 awire->timestamp = aevent->timestamp;
268 awire->area.x = aevent->area.x;
269 awire->area.y = aevent->area.y;
270 awire->area.width = aevent->area.width;
271 awire->area.height = aevent->area.height;
272 awire->geometry.x = aevent->geometry.x;
273 awire->geometry.y = aevent->geometry.y;
274 awire->geometry.width = aevent->geometry.width;
275 awire->geometry.height = aevent->geometry.height;
283 XDamageQueryExtension (Display *dpy, int *event_basep, int *error_basep)
285 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
287 if (XDamageHasExtension(info))
289 *event_basep = info->codes->first_event;
290 *error_basep = info->codes->first_error;
298 XDamageQueryVersion (Display *dpy,
302 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
304 XDamageCheckExtension (dpy, info, 0);
306 *major_versionp = info->major_version;
307 *minor_versionp = info->minor_version;
312 XDamageCreate (Display *dpy, Drawable drawable, int level)
314 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
315 xDamageCreateReq *req;
318 XDamageCheckExtension (dpy, info, 0);
320 GetReq (DamageCreate, req);
321 req->reqType = info->codes->major_opcode;
322 req->damageReqType = X_DamageCreate;
323 req->damage = damage = XAllocID (dpy);
324 req->drawable = drawable;
332 XDamageDestroy (Display *dpy, Damage damage)
334 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
335 xDamageDestroyReq *req;
337 XDamageSimpleCheckExtension (dpy, info);
339 GetReq (DamageDestroy, req);
340 req->reqType = info->codes->major_opcode;
341 req->damageReqType = X_DamageDestroy;
342 req->damage = damage;
348 XDamageSubtract (Display *dpy, Damage damage,
349 XserverRegion repair, XserverRegion parts)
351 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
352 xDamageSubtractReq *req;
354 XDamageSimpleCheckExtension (dpy, info);
356 GetReq (DamageSubtract, req);
357 req->reqType = info->codes->major_opcode;
358 req->damageReqType = X_DamageSubtract;
359 req->damage = damage;
360 req->repair = repair;
367 XDamagePost (Display *dpy, Drawable drawable, XserverRegion region)
369 XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
373 XDamageSimpleCheckExtension (dpy, info);
375 GetReq (DamagePost, req);
376 req->reqType = info->codes->major_opcode;
377 req->damageReqType = X_DamagePost;
378 req->drawable = drawable;
379 req->region = region;