2 * Copyright © 2007-2008 Peter Hutterer
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:
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
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.
23 * Authors: Peter Hutterer, University of South Australia, NICTA
27 * XGE is an extension to re-use a single opcode for multiple events,
28 * depending on the extension. XGE allows events >32 bytes.
36 #include <X11/extensions/geproto.h>
37 #include <X11/extensions/ge.h>
38 #include <X11/Xlibint.h>
39 #include <X11/extensions/extutil.h>
40 #include <X11/extensions/Xge.h>
42 /***********************************************************************/
43 /* internal data structures */
44 /***********************************************************************/
52 /* NULL terminated list of registered extensions. */
53 typedef struct _XGEExtNode {
55 XExtensionHooks* hooks;
56 struct _XGEExtNode* next;
57 } XGEExtNode, *XGEExtList;
59 /* Internal data for GE extension */
60 typedef struct _XGEData {
63 XGEExtList extensions;
67 /* forward declarations */
68 static XExtDisplayInfo* _xgeFindDisplay(Display*);
69 static Bool _xgeWireToEvent(Display*, XEvent*, xEvent*);
70 static Status _xgeEventToWire(Display*, XEvent*, xEvent*);
71 static int _xgeDpyClose(Display*, XExtCodes*);
72 static XGEVersionRec* _xgeGetExtensionVersion(Display*,
75 static Bool _xgeCheckExtension(Display* dpy, XExtDisplayInfo* info);
77 /* main extension information data */
78 static XExtensionInfo *xge_info;
79 static const char xge_extension_name[] = GE_NAME;
80 static XExtensionHooks xge_extension_hooks = {
85 NULL, /* create_font */
87 _xgeDpyClose, /* close_display */
88 _xgeWireToEvent, /* wire_to_event */
89 _xgeEventToWire, /* event_to_wire */
91 NULL, /* error_string */
95 static XExtDisplayInfo *_xgeFindDisplay(Display *dpy)
97 XExtDisplayInfo *dpyinfo;
100 if (!(xge_info = XextCreateExtension()))
103 if (!(dpyinfo = XextFindDisplay (xge_info, dpy)))
105 dpyinfo = XextAddDisplay (xge_info,
108 &xge_extension_hooks,
109 0 /* no events, see below */,
111 /* We don't use an extension opcode, so we have to set the handlers
112 * directly. If GenericEvent would be > 64, the job would be done by
114 XESetWireToEvent (dpy,
116 xge_extension_hooks.wire_to_event);
117 XESetEventToWire (dpy,
119 xge_extension_hooks.event_to_wire);
125 * Check extension is set up and internal data fields are filled.
128 _xgeCheckExtInit(Display* dpy, XExtDisplayInfo* info)
131 if(!_xgeCheckExtension(dpy, info))
138 XGEData* data = (XGEData*)Xmalloc(sizeof(XGEData));
142 /* get version from server */
144 _xgeGetExtensionVersion(dpy, "Generic Event Extension", info);
145 data->extensions = NULL;
146 info->data = (XPointer)data;
157 /* Return 1 if XGE extension exists, 0 otherwise. */
159 _xgeCheckExtension(Display* dpy, XExtDisplayInfo* info)
161 return XextHasExtension(info);
165 /* Retrieve XGE version number from server. */
166 static XGEVersionRec*
167 _xgeGetExtensionVersion(Display* dpy,
169 XExtDisplayInfo*info)
171 xGEQueryVersionReply rep;
172 xGEQueryVersionReq *req;
175 GetReq(GEQueryVersion, req);
176 req->reqType = info->codes->major_opcode;
177 req->ReqType = X_GEQueryVersion;
178 req->majorVersion = GE_MAJOR;
179 req->minorVersion = GE_MINOR;
181 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue))
187 vers = (XGEVersionRec*)Xmalloc(sizeof(XGEVersionRec));
188 vers->major_version = rep.majorVersion;
189 vers->minor_version = rep.minorVersion;
194 * Display closing routine.
198 _xgeDpyClose(Display* dpy, XExtCodes* codes)
200 XExtDisplayInfo *info = _xgeFindDisplay(dpy);
202 if (info->data != NULL) {
203 XGEData* xge_data = (XGEData*)info->data;
205 if (xge_data->extensions)
207 XGEExtList current, next;
208 current = xge_data->extensions;
211 next = current->next;
217 XFree(xge_data->vers);
221 return XextRemoveDisplay(xge_info, dpy);
225 * protocol to Xlib event conversion routine.
228 _xgeWireToEvent(Display* dpy, XEvent* re, xEvent *event)
232 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
236 _xgeCheckExtInit() calls LockDisplay, leading to a SIGABRT.
237 Well, I guess we don't need the data we get in CheckExtInit anyway
238 if (!_xgeCheckExtInit(dpy, info))
242 extension = ((xGenericEvent*)event)->extension;
244 it = ((XGEData*)info->data)->extensions;
247 if (it->extension == extension)
249 return (it->hooks->wire_to_event(dpy, re, event));
255 "_xgeWireToEvent: Unknown extension %d, this should never happen.\n",
261 * xlib event to protocol conversion routine.
264 _xgeEventToWire(Display* dpy, XEvent* re, xEvent* event)
268 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
270 return 1; /* error! */
272 extension = ((XGenericEvent*)re)->extension;
274 it = ((XGEData*)info->data)->extensions;
277 if (it->extension == extension)
279 return (it->hooks->event_to_wire(dpy, re, event));
285 "_xgeEventToWire: Unknown extension %d, this should never happen.\n",
292 * Extensions need to register callbacks for their events.
295 _X_HIDDEN xgeExtRegister(Display* dpy, int offset, XExtensionHooks* callbacks)
300 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
302 return False; /* error! */
304 if (!_xgeCheckExtInit(dpy, info))
307 xge_data = (XGEData*)info->data;
309 newExt = (XGEExtNode*)Xmalloc(sizeof(XGEExtNode));
312 fprintf(stderr, "xgeExtRegister: Failed to alloc memory.\n");
316 newExt->extension = offset;
317 newExt->hooks = callbacks;
318 newExt->next = xge_data->extensions;
319 xge_data->extensions = newExt;
324 /***********************************************************************/
325 /* Client interfaces */
326 /***********************************************************************/
328 /* Set event_base and error_base to the matching values for XGE.
329 * Note that since XGE doesn't use any errors and events, the actual return
330 * value is of limited use.
333 XGEQueryExtension(Display* dpy, int* event_base, int* error_base)
335 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
336 if (!_xgeCheckExtInit(dpy, info))
339 *event_base = info->codes->first_event;
340 *error_base = info->codes->first_error;
344 /* Get XGE version number.
345 * Doesn't actually get it from server, that should have been done beforehand
349 XGEQueryVersion(Display* dpy,
353 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
357 if (!_xgeCheckExtInit(dpy, info))
360 *major_version = ((XGEData*)info->data)->vers->major_version;
361 *minor_version = ((XGEData*)info->data)->vers->minor_version;