diff options
-rw-r--r-- | include/X11/extensions/Xdamage.h | 68 | ||||
-rw-r--r-- | src/Xdamage.c | 362 | ||||
-rw-r--r-- | src/xdamageint.h | 66 |
3 files changed, 496 insertions, 0 deletions
diff --git a/include/X11/extensions/Xdamage.h b/include/X11/extensions/Xdamage.h new file mode 100644 index 0000000..dc796fe --- /dev/null +++ b/include/X11/extensions/Xdamage.h @@ -0,0 +1,68 @@ +/* + * $Id$ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _XDAMAGE_H_ +#define _XDAMAGE_H_ + +#include <X11/extensions/damagewire.h> +#include <X11/extensions/Xfixes.h> +#include <X11/Xfuncproto.h> + +typedef XID Damage; + +typedef struct { + int type; /* event base */ + unsigned long serial; + Bool send_event; + Display *display; + Drawable drawable; + Damage damage; + int level; + Bool more; /* more events will be delivered immediately */ + Time timestamp; + XRectangle area; + XRectangle geometry; +} XDamageNotifyEvent; + +_XFUNCPROTOBEGIN + +Bool XDamageQueryExtension (Display *dpy, int *event_basep, int *error_basep); + +Status XDamageQueryVersion (Display *dpy, + int *major_versionp, + int *minor_versionp); + +Damage +XDamageCreate (Display *dpy, Drawable drawable, int level); + +void +XDamageDestroy (Display *dpy, Damage damage); + +void +XDamageSubtract (Display *dpy, Damage damage, + XserverRegion repair, XserverRegion parts); + +_XFUNCPROTOEND + +#endif /* _XDAMAGE_H_ */ diff --git a/src/Xdamage.c b/src/Xdamage.c new file mode 100644 index 0000000..8c899b1 --- /dev/null +++ b/src/Xdamage.c @@ -0,0 +1,362 @@ +/* + * $Id$ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xdamageint.h" + +XDamageExtInfo XDamageExtensionInfo; + +const char XDamageExtensionName[] = DAMAGE_NAME; + +static int +XDamageCloseDisplay (Display *dpy, XExtCodes *codes); + +static Bool +XDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire); + +static Status +XDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire); + +/* + * XDamageExtAddDisplay - add a display to this extension. (Replaces + * XextAddDisplay) + */ +static XDamageExtDisplayInfo * +XDamageExtAddDisplay (XDamageExtInfo *extinfo, + Display *dpy, + const char *ext_name) +{ + XDamageExtDisplayInfo *info; + int ev; + + info = (XDamageExtDisplayInfo *) Xmalloc (sizeof (XDamageExtDisplayInfo)); + if (!info) return NULL; + info->display = dpy; + + info->codes = XInitExtension (dpy, ext_name); + + /* + * if the server has the extension, then we can initialize the + * appropriate function vectors + */ + if (info->codes) { + xDamageQueryVersionReply rep; + xDamageQueryVersionReq *req; + XESetCloseDisplay (dpy, info->codes->extension, + XDamageCloseDisplay); + for (ev = info->codes->first_event; + ev < info->codes->first_event + XDamageNumberEvents; + ev++) + { + XESetWireToEvent (dpy, ev, XDamageWireToEvent); + XESetEventToWire (dpy, ev, XDamageEventToWire); + } + /* + * Get the version info + */ + LockDisplay (dpy); + GetReq (DamageQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->damageReqType = X_DamageQueryVersion; + req->majorVersion = DAMAGE_MAJOR; + req->minorVersion = DAMAGE_MINOR; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) + { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + info->major_version = rep.majorVersion; + info->minor_version = rep.minorVersion; + UnlockDisplay (dpy); + } else { + /* The server doesn't have this extension. + * Use a private Xlib-internal extension to hang the close_display + * hook on so that the "cache" (extinfo->cur) is properly cleaned. + * (XBUG 7955) + */ + XExtCodes *codes = XAddExtension(dpy); + if (!codes) { + XFree(info); + return NULL; + } + XESetCloseDisplay (dpy, codes->extension, XDamageCloseDisplay); + } + + /* + * now, chain it onto the list + */ + _XLockMutex(_Xglobal_lock); + info->next = extinfo->head; + extinfo->head = info; + extinfo->cur = info; + extinfo->ndisplays++; + _XUnlockMutex(_Xglobal_lock); + return info; +} + + +/* + * XDamageExtRemoveDisplay - remove the indicated display from the + * extension object. (Replaces XextRemoveDisplay.) + */ +static int +XDamageExtRemoveDisplay (XDamageExtInfo *extinfo, Display *dpy) +{ + XDamageExtDisplayInfo *info, *prev; + + /* + * locate this display and its back link so that it can be removed + */ + _XLockMutex(_Xglobal_lock); + prev = NULL; + for (info = extinfo->head; info; info = info->next) { + if (info->display == dpy) break; + prev = info; + } + if (!info) { + _XUnlockMutex(_Xglobal_lock); + return 0; /* hmm, actually an error */ + } + + /* + * remove the display from the list; handles going to zero + */ + if (prev) + prev->next = info->next; + else + extinfo->head = info->next; + + extinfo->ndisplays--; + if (info == extinfo->cur) extinfo->cur = NULL; /* flush cache */ + _XUnlockMutex(_Xglobal_lock); + + Xfree ((char *) info); + return 1; +} + +/* + * XDamageExtFindDisplay - look for a display in this extension; keeps a + * cache of the most-recently used for efficiency. (Replaces + * XextFindDisplay.) + */ +static XDamageExtDisplayInfo * +XDamageExtFindDisplay (XDamageExtInfo *extinfo, + Display *dpy) +{ + XDamageExtDisplayInfo *info; + + /* + * see if this was the most recently accessed display + */ + if ((info = extinfo->cur) && info->display == dpy) + return info; + + /* + * look for display in list + */ + _XLockMutex(_Xglobal_lock); + for (info = extinfo->head; info; info = info->next) { + if (info->display == dpy) { + extinfo->cur = info; /* cache most recently used */ + _XUnlockMutex(_Xglobal_lock); + return info; + } + } + _XUnlockMutex(_Xglobal_lock); + + return NULL; +} + +XDamageExtDisplayInfo * +XDamageFindDisplay (Display *dpy) +{ + XDamageExtDisplayInfo *info; + + info = XDamageExtFindDisplay (&XDamageExtensionInfo, dpy); + if (!info) + info = XDamageExtAddDisplay (&XDamageExtensionInfo, dpy, + XDamageExtensionName); + return info; +} + +static int +XDamageCloseDisplay (Display *dpy, XExtCodes *codes) +{ + return XDamageExtRemoveDisplay (&XDamageExtensionInfo, dpy); +} + +static Bool +XDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire) +{ + XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy); + + XDamageCheckExtension(dpy, info, False); + + switch ((wire->u.u.type & 0x7F) - info->codes->first_event) + { + case XDamageNotify: { + XDamageNotifyEvent *aevent = (XDamageNotifyEvent *) event; + xDamageNotifyEvent *awire = (xDamageNotifyEvent *) wire; + + aevent->type = awire->type & 0x7F; + aevent->serial = _XSetLastRequestRead(dpy, + (xGenericReply *) wire); + aevent->send_event = (awire->type & 0x80) != 0; + aevent->display = dpy; + aevent->drawable = awire->drawable; + aevent->damage = awire->damage; + aevent->level = awire->level; + aevent->timestamp = awire->timestamp; + aevent->area.x = awire->area.x; + aevent->area.y = awire->area.y; + aevent->area.width = awire->area.width; + aevent->area.height = awire->area.height; + aevent->geometry.x = awire->geometry.x; + aevent->geometry.y = awire->geometry.y; + aevent->geometry.width = awire->geometry.width; + aevent->geometry.height = awire->geometry.height; + return True; + } + } + return False; +} + +static Status +XDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire) +{ + XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy); + + XDamageCheckExtension(dpy, info, False); + + switch ((event->type & 0x7F) - info->codes->first_event) + { + case XDamageNotify: { + XDamageNotifyEvent *aevent; + xDamageNotifyEvent *awire; + awire = (xDamageNotifyEvent *) wire; + aevent = (XDamageNotifyEvent *) event; + awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); + awire->drawable = aevent->drawable; + awire->damage = aevent->damage; + awire->level = aevent->level; + awire->timestamp = aevent->timestamp; + awire->area.x = aevent->area.x; + awire->area.y = aevent->area.y; + awire->area.width = aevent->area.width; + awire->area.height = aevent->area.height; + awire->geometry.x = aevent->geometry.x; + awire->geometry.y = aevent->geometry.y; + awire->geometry.width = aevent->geometry.width; + awire->geometry.height = aevent->geometry.height; + return True; + } + } + return False; +} + +Bool +XDamageQueryExtension (Display *dpy, int *event_basep, int *error_basep) +{ + XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); + + if (XDamageHasExtension(info)) + { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } + else + return False; +} + +Status +XDamageQueryVersion (Display *dpy, + int *major_versionp, + int *minor_versionp) +{ + XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); + + XDamageCheckExtension (dpy, info, 0); + + *major_versionp = info->major_version; + *minor_versionp = info->minor_version; + UnlockDisplay (dpy); + SyncHandle (); + return 1; +} + +Damage +XDamageCreate (Display *dpy, Drawable drawable, int level) +{ + XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); + xDamageCreateReq *req; + Damage damage; + + XDamageCheckExtension (dpy, info, 0); + LockDisplay (dpy); + GetReq (DamageCreate, req); + req->reqType = info->codes->major_opcode; + req->damageReqType = X_DamageCreate; + req->damage = damage = XAllocID (dpy); + req->drawable = drawable; + req->level = level; + UnlockDisplay (dpy); + SyncHandle (); + return damage; +} + +void +XDamageDestroy (Display *dpy, Damage damage) +{ + XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); + xDamageDestroyReq *req; + + XDamageSimpleCheckExtension (dpy, info); + LockDisplay (dpy); + GetReq (DamageDestroy, req); + req->reqType = info->codes->major_opcode; + req->damageReqType = X_DamageDestroy; + req->damage = damage; + UnlockDisplay (dpy); + SyncHandle (); +} + +void +XDamageSubtract (Display *dpy, Damage damage, + XserverRegion repair, XserverRegion parts) +{ + XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); + xDamageSubtractReq *req; + + XDamageSimpleCheckExtension (dpy, info); + LockDisplay (dpy); + GetReq (DamageSubtract, req); + req->reqType = info->codes->major_opcode; + req->damageReqType = X_DamageSubtract; + req->damage = damage; + req->repair = repair; + req->parts = parts; + UnlockDisplay (dpy); + SyncHandle (); +} diff --git a/src/xdamageint.h b/src/xdamageint.h new file mode 100644 index 0000000..8c64ca2 --- /dev/null +++ b/src/xdamageint.h @@ -0,0 +1,66 @@ +/* + * $Id$ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _XDAMAGEINT_H_ +#define _XDAMAGEINT_H_ + +#define NEED_EVENTS +#define NEED_REPLIES +#include <stdio.h> +#include <X11/Xlib.h> +#include <X11/Xlibint.h> +#include <X11/Xutil.h> +#include <X11/extensions/damageproto.h> +#include "Xdamage.h" + +typedef struct _XDamageExtDisplayInfo { + struct _XDamageExtDisplayInfo *next; /* keep a linked list */ + Display *display; /* which display this is */ + XExtCodes *codes; /* the extension protocol codes */ + int major_version; /* -1 means we don't know */ + int minor_version; /* -1 means we don't know */ +} XDamageExtDisplayInfo; + +/* replaces XExtensionInfo */ +typedef struct _XDamageExtInfo { + XDamageExtDisplayInfo *head; /* start of the list */ + XDamageExtDisplayInfo *cur; /* most recently used */ + int ndisplays; /* number of displays */ +} XDamageExtInfo; + +extern XDamageExtInfo XDamageExtensionInfo; +extern const char XDamageExtensionName[]; + +XDamageExtDisplayInfo * +XDamageFindDisplay (Display *dpy); + +#define XDamageHasExtension(i) ((i) && ((i)->codes)) + +#define XDamageCheckExtension(dpy,i,val) \ + if (!XDamageHasExtension(i)) { return val; } + +#define XDamageSimpleCheckExtension(dpy,i) \ + if (!XDamageHasExtension(i)) { return; } + +#endif /* _XDAMAGEINT_H_ */ |