#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define NEED_EVENTS
#define NEED_REPLIES
#include <stdio.h>
#include <X11/extensions/geproto.h>
#include <X11/extensions/ge.h>
#include <X11/Xlibint.h>
#include <X11/extensions/extutil.h>
#include <X11/extensions/Xge.h>
typedef struct {
int present;
short major_version;
short minor_version;
} XGEVersionRec;
typedef struct _XGEExtNode {
int extension;
XExtensionHooks* hooks;
struct _XGEExtNode* next;
} XGEExtNode, *XGEExtList;
typedef struct _XGEData {
XEvent data;
XGEVersionRec *vers;
XGEExtList extensions;
} XGEData;
extern XExtDisplayInfo* _xgeFindDisplay(Display*);
static Bool _xgeWireToEvent(Display*, XEvent*, xEvent*);
Status _xgeEventToWire(Display*, XEvent*, xEvent*);
static int _xgeDpyClose(Display*, XExtCodes*);
static XGEVersionRec* _xgeGetExtensionVersion(Display*,
_Xconst char*,
XExtDisplayInfo*);
static Bool _xgeCheckExtension(Display* dpy, XExtDisplayInfo* info);
static XExtensionInfo *xge_info;
static char xge_extension_name[] = GE_NAME;
static XExtensionHooks xge_extension_hooks = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
_xgeDpyClose,
_xgeWireToEvent,
_xgeEventToWire,
NULL,
NULL,
};
XExtDisplayInfo *_xgeFindDisplay(Display *dpy)
{
XExtDisplayInfo *dpyinfo;
if (!xge_info)
{
if (!(xge_info = XextCreateExtension()))
return NULL;
}
if (!(dpyinfo = XextFindDisplay (xge_info, dpy)))
{
dpyinfo = XextAddDisplay (xge_info,
dpy,
xge_extension_name,
&xge_extension_hooks,
0 ,
NULL);
XESetWireToEvent (dpy,
GenericEvent,
xge_extension_hooks.wire_to_event);
XESetEventToWire (dpy,
GenericEvent,
xge_extension_hooks.event_to_wire);
}
return dpyinfo;
}
Bool
_xgeCheckExtInit(Display* dpy, XExtDisplayInfo* info)
{
LockDisplay(dpy);
if(!_xgeCheckExtension(dpy, info))
{
goto cleanup;
}
if (!info->data)
{
XGEData* data = (XGEData*)Xmalloc(sizeof(XGEData));
if (!data) {
goto cleanup;
}
data->vers =
_xgeGetExtensionVersion(dpy, "Generic Event Extension", info);
data->extensions = NULL;
info->data = (XPointer)data;
}
UnlockDisplay(dpy);
return True;
cleanup:
UnlockDisplay(dpy);
return False;
}
static Bool
_xgeCheckExtension(Display* dpy, XExtDisplayInfo* info)
{
return XextHasExtension(info);
}
static XGEVersionRec*
_xgeGetExtensionVersion(Display* dpy,
_Xconst char* name,
XExtDisplayInfo*info)
{
xGEQueryVersionReply rep;
xGEQueryVersionReq *req;
XGEVersionRec *vers;
GetReq(GEQueryVersion, req);
req->reqType = info->codes->major_opcode;
req->ReqType = X_GEQueryVersion;
req->majorVersion = GE_MAJOR;
req->minorVersion = GE_MINOR;
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue))
{
Xfree(info);
return NULL;
}
vers = (XGEVersionRec*)Xmalloc(sizeof(XGEVersionRec));
vers->major_version = rep.majorVersion;
vers->minor_version = rep.minorVersion;
return vers;
}
static int
_xgeDpyClose(Display* dpy, XExtCodes* codes)
{
XExtDisplayInfo *info = _xgeFindDisplay(dpy);
if (info->data != NULL) {
XGEData* xge_data = (XGEData*)info->data;
if (xge_data->extensions)
{
XGEExtList current, next;
current = xge_data->extensions;
while(current)
{
next = current->next;
Xfree(current);
current = next;
}
}
XFree(xge_data->vers);
XFree(xge_data);
}
return XextRemoveDisplay(xge_info, dpy);
}
static Bool
_xgeWireToEvent(Display* dpy, XEvent* re, xEvent *event)
{
int extension;
XGEExtList it;
XExtDisplayInfo* info = _xgeFindDisplay(dpy);
if (!info)
return False;
extension = ((xGenericEvent*)event)->extension;
it = ((XGEData*)info->data)->extensions;
while(it)
{
if (it->extension == extension)
{
return (it->hooks->wire_to_event(dpy, re, event));
}
it = it->next;
}
fprintf(stderr,
"_xgeWireToEvent: Unknown extension %d, this should never happen.\n",
extension);
return False;
}
Status
_xgeEventToWire(Display* dpy, XEvent* re, xEvent* event)
{
int extension;
XGEExtList it;
XExtDisplayInfo* info = _xgeFindDisplay(dpy);
if (!info)
return 1;
extension = ((XGenericEvent*)re)->extension;
it = ((XGEData*)info->data)->extensions;
while(it)
{
if (it->extension == extension)
{
return (it->hooks->event_to_wire(dpy, re, event));
}
it = it->next;
}
fprintf(stderr,
"_xgeEventToWire: Unknown extension %d, this should never happen.\n",
extension);
return Success;
}
Bool
xgeExtRegister(Display* dpy, int offset, XExtensionHooks* callbacks)
{
XGEExtNode* newExt;
XGEData* xge_data;
XExtDisplayInfo* info = _xgeFindDisplay(dpy);
if (!info)
return False;
if (!_xgeCheckExtInit(dpy, info))
return False;
xge_data = (XGEData*)info->data;
newExt = (XGEExtNode*)Xmalloc(sizeof(XGEExtNode));
if (!newExt)
{
fprintf(stderr, "xgeExtRegister: Failed to alloc memory.\n");
return False;
}
newExt->extension = offset;
newExt->hooks = callbacks;
newExt->next = xge_data->extensions;
xge_data->extensions = newExt;
return True;
}
Bool
XGEQueryExtension(Display* dpy, int* event_base, int* error_base)
{
XExtDisplayInfo* info = _xgeFindDisplay(dpy);
if (!_xgeCheckExtInit(dpy, info))
return False;
*event_base = info->codes->first_event;
*error_base = info->codes->first_error;
return True;
}
Bool
XGEQueryVersion(Display* dpy,
int *major_version,
int *minor_version)
{
XExtDisplayInfo* info = _xgeFindDisplay(dpy);
if (!info)
return False;
if (!_xgeCheckExtInit(dpy, info))
return False;
*major_version = ((XGEData*)info->data)->vers->major_version;
*minor_version = ((XGEData*)info->data)->vers->minor_version;
return True;
}