upload tizen2.0 source
[framework/uifw/xorg/lib/libxext.git] / src / Xge.c
1 /*
2  * Copyright © 2007-2008 Peter Hutterer
3  *
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:
10  *
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
13  * Software.
14  *
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.
22  *
23  * Authors: Peter Hutterer, University of South Australia, NICTA
24  */
25
26 /*
27  * XGE is an extension to re-use a single opcode for multiple events,
28  * depending on the extension. XGE allows events >32 bytes.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <stdio.h>
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>
41
42 /***********************************************************************/
43 /*                    internal data structures                         */
44 /***********************************************************************/
45
46 typedef struct {
47         int     present;
48         short   major_version;
49         short   minor_version;
50 } XGEVersionRec;
51
52 /* NULL terminated list of registered extensions. */
53 typedef struct _XGEExtNode {
54     int extension;
55     XExtensionHooks* hooks;
56     struct _XGEExtNode* next;
57 } XGEExtNode, *XGEExtList;
58
59 /* Internal data for GE extension */
60 typedef struct _XGEData {
61     XEvent data;
62     XGEVersionRec *vers;
63     XGEExtList extensions;
64 } XGEData;
65
66
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*,
73                                               _Xconst char*,
74                                               XExtDisplayInfo*);
75 static Bool _xgeCheckExtension(Display* dpy, XExtDisplayInfo* info);
76
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 = {
81     NULL,               /* create_gc */
82     NULL,               /* copy_gc */
83     NULL,               /* flush_gc */
84     NULL,               /* free_gc */
85     NULL,               /* create_font */
86     NULL,               /* free_font */
87     _xgeDpyClose,       /* close_display */
88     _xgeWireToEvent,    /* wire_to_event */
89     _xgeEventToWire,    /* event_to_wire */
90     NULL,               /* error */
91     NULL,               /* error_string */
92 };
93
94
95 static XExtDisplayInfo *_xgeFindDisplay(Display *dpy)
96 {
97     XExtDisplayInfo *dpyinfo;
98     if (!xge_info)
99     {
100         if (!(xge_info = XextCreateExtension()))
101             return NULL;
102     }
103     if (!(dpyinfo = XextFindDisplay (xge_info, dpy)))
104     {
105         dpyinfo = XextAddDisplay (xge_info,
106                                   dpy,
107                                   xge_extension_name,
108                                   &xge_extension_hooks,
109                                   0 /* no events, see below */,
110                                   NULL);
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
113          * XExtAddDisplay  */
114         XESetWireToEvent (dpy,
115                           GenericEvent,
116                           xge_extension_hooks.wire_to_event);
117         XESetEventToWire (dpy,
118                           GenericEvent,
119                           xge_extension_hooks.event_to_wire);
120     }
121     return dpyinfo;
122 }
123
124 /*
125  * Check extension is set up and internal data fields are filled.
126  */
127 static Bool
128 _xgeCheckExtInit(Display* dpy, XExtDisplayInfo* info)
129 {
130     LockDisplay(dpy);
131     if(!_xgeCheckExtension(dpy, info))
132     {
133         goto cleanup;
134     }
135
136     if (!info->data)
137     {
138         XGEData* data = (XGEData*)Xmalloc(sizeof(XGEData));
139         if (!data) {
140             goto cleanup;
141         }
142         /* get version from server */
143         data->vers =
144             _xgeGetExtensionVersion(dpy, "Generic Event Extension", info);
145         data->extensions = NULL;
146         info->data = (XPointer)data;
147     }
148
149     UnlockDisplay(dpy);
150     return True;
151
152 cleanup:
153     UnlockDisplay(dpy);
154     return False;
155 }
156
157 /* Return 1 if XGE extension exists, 0 otherwise. */
158 static Bool
159 _xgeCheckExtension(Display* dpy, XExtDisplayInfo* info)
160 {
161     return XextHasExtension(info);
162 }
163
164
165 /* Retrieve XGE version number from server. */
166 static XGEVersionRec*
167 _xgeGetExtensionVersion(Display* dpy,
168                             _Xconst char* name,
169                             XExtDisplayInfo*info)
170 {
171     xGEQueryVersionReply rep;
172     xGEQueryVersionReq *req;
173     XGEVersionRec *vers;
174
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;
180
181     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue))
182     {
183         Xfree(info);
184         return NULL;
185     }
186
187     vers = (XGEVersionRec*)Xmalloc(sizeof(XGEVersionRec));
188     vers->major_version = rep.majorVersion;
189     vers->minor_version = rep.minorVersion;
190     return vers;
191 }
192
193 /*
194  * Display closing routine.
195  */
196
197 static int
198 _xgeDpyClose(Display* dpy, XExtCodes* codes)
199 {
200     XExtDisplayInfo *info = _xgeFindDisplay(dpy);
201
202     if (info->data != NULL) {
203         XGEData* xge_data = (XGEData*)info->data;
204
205         if (xge_data->extensions)
206         {
207             XGEExtList current, next;
208             current = xge_data->extensions;
209             while(current)
210             {
211                 next = current->next;
212                 Xfree(current);
213                 current = next;
214             }
215         }
216
217         XFree(xge_data->vers);
218         XFree(xge_data);
219     }
220
221     return XextRemoveDisplay(xge_info, dpy);
222 }
223
224 /*
225  * protocol to Xlib event conversion routine.
226  */
227 static Bool
228 _xgeWireToEvent(Display* dpy, XEvent* re, xEvent *event)
229 {
230     int extension;
231     XGEExtList it;
232     XExtDisplayInfo* info = _xgeFindDisplay(dpy);
233     if (!info)
234         return False;
235     /*
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))
239                 return False;
240      */
241
242     extension = ((xGenericEvent*)event)->extension;
243
244     it = ((XGEData*)info->data)->extensions;
245     while(it)
246     {
247         if (it->extension == extension)
248         {
249             return (it->hooks->wire_to_event(dpy, re, event));
250         }
251         it = it->next;
252     }
253
254     fprintf(stderr,
255         "_xgeWireToEvent: Unknown extension %d, this should never happen.\n",
256             extension);
257     return False;
258 }
259
260 /*
261  * xlib event to protocol conversion routine.
262  */
263 static Status
264 _xgeEventToWire(Display* dpy, XEvent* re, xEvent* event)
265 {
266     int extension;
267     XGEExtList it;
268     XExtDisplayInfo* info = _xgeFindDisplay(dpy);
269     if (!info)
270         return 1; /* error! */
271
272     extension = ((XGenericEvent*)re)->extension;
273
274     it = ((XGEData*)info->data)->extensions;
275     while(it)
276     {
277         if (it->extension == extension)
278         {
279             return (it->hooks->event_to_wire(dpy, re, event));
280         }
281         it = it->next;
282     }
283
284     fprintf(stderr,
285         "_xgeEventToWire: Unknown extension %d, this should never happen.\n",
286         extension);
287
288     return Success;
289 }
290
291 /*
292  * Extensions need to register callbacks for their events.
293  */
294 Bool
295 _X_HIDDEN xgeExtRegister(Display* dpy, int offset, XExtensionHooks* callbacks)
296 {
297     XGEExtNode* newExt;
298     XGEData* xge_data;
299
300     XExtDisplayInfo* info = _xgeFindDisplay(dpy);
301     if (!info)
302         return False; /* error! */
303
304     if (!_xgeCheckExtInit(dpy, info))
305         return False;
306
307     xge_data = (XGEData*)info->data;
308
309     newExt = (XGEExtNode*)Xmalloc(sizeof(XGEExtNode));
310     if (!newExt)
311     {
312         fprintf(stderr, "xgeExtRegister: Failed to alloc memory.\n");
313         return False;
314     }
315
316     newExt->extension = offset;
317     newExt->hooks = callbacks;
318     newExt->next = xge_data->extensions;
319     xge_data->extensions = newExt;
320
321     return True;
322 }
323
324 /***********************************************************************/
325 /*                    Client interfaces                                */
326 /***********************************************************************/
327
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.
331  */
332 Bool
333 XGEQueryExtension(Display* dpy, int* event_base, int* error_base)
334 {
335     XExtDisplayInfo* info = _xgeFindDisplay(dpy);
336     if (!_xgeCheckExtInit(dpy, info))
337         return False;
338
339     *event_base = info->codes->first_event;
340     *error_base = info->codes->first_error;
341     return True;
342 }
343
344 /* Get XGE version number.
345  * Doesn't actually get it from server, that should have been done beforehand
346  * already
347  */
348 Bool
349 XGEQueryVersion(Display* dpy,
350                 int *major_version,
351                 int *minor_version)
352 {
353     XExtDisplayInfo* info = _xgeFindDisplay(dpy);
354     if (!info)
355         return False;
356
357     if (!_xgeCheckExtInit(dpy, info))
358         return False;
359
360     *major_version = ((XGEData*)info->data)->vers->major_version;
361     *minor_version = ((XGEData*)info->data)->vers->minor_version;
362
363     return True;
364 }
365