d3c6b7c1988e9d58e52825072a8fbce0178d3698
[platform/upstream/libXi.git] / src / XExtInt.c
1 /************************************************************
2
3 Copyright 1989, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27                         All Rights Reserved
28
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Hewlett-Packard not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
36
37 HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 SOFTWARE.
44
45 ********************************************************/
46
47 /***********************************************************************
48  *
49  * Input Extension library internal functions.
50  *
51  */
52
53 #if HAVE_CONFIG_H
54 #include <config.h>
55 #endif
56
57 #include <stdio.h>
58 #include <stdint.h>
59 #include <X11/extensions/XI.h>
60 #include <X11/extensions/XI2.h>
61 #include <X11/extensions/XIproto.h>
62 #include <X11/extensions/XI2proto.h>
63 #include <X11/Xlibint.h>
64 #include <X11/extensions/XInput.h>
65 #include <X11/extensions/XInput2.h>
66 #include <X11/extensions/extutil.h>
67 #include <X11/extensions/geproto.h>
68 #include <X11/extensions/ge.h>
69 #include <X11/extensions/Xge.h>
70 #include "XIint.h"
71
72 #define ENQUEUE_EVENT   True
73 #define DONT_ENQUEUE    False
74 #define FP1616toDBL(x) ((x) * 1.0 / (1 << 16))
75
76 int copy_classes(XIDeviceInfo *to, xXIAnyInfo* from, int *nclasses);
77 int size_classes(xXIAnyInfo* from, int nclasses);
78
79 static XExtensionInfo *xinput_info;
80 static const char *xinput_extension_name = INAME;
81
82 static int XInputClose(
83     Display *           /* dpy */,
84     XExtCodes *         /* codes */
85 );
86
87 static char *XInputError(
88     Display *           /* dpy */,
89     int                 /* code */,
90     XExtCodes *         /* codes */,
91     char *              /* buf */,
92     int                 /* n */
93 );
94
95 static Bool XInputWireToEvent(
96     Display *           /* dpy */,
97     XEvent *            /* re */,
98     xEvent *            /* event */
99 );
100 static Bool XInputWireToCookie(
101     Display*            /* display */,
102     XGenericEventCookie*        /* re */,
103     xEvent*             /* event */
104 );
105
106 static Bool XInputCopyCookie(
107     Display*            /* display */,
108     XGenericEventCookie*        /* in */,
109     XGenericEventCookie*        /* out */
110 );
111
112 static int
113 wireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* out);
114 static int
115 wireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie);
116 static int
117 wireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie);
118 static int
119 wireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *cookie);
120 static int
121 wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie);
122 static int
123 wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie);
124 static int
125 wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
126                           XGenericEventCookie *cookie);
127 static int
128 wireToBarrierEvent(xXIBarrierEvent *in,
129                    XGenericEventCookie *cookie);
130
131 static /* const */ XEvent emptyevent;
132
133 typedef Status (*core_event_to_wire)(Display*, XEvent*, xEvent*);
134
135 static /* const */ XExtensionHooks xinput_extension_hooks = {
136     NULL,       /* create_gc */
137     NULL,       /* copy_gc */
138     NULL,       /* flush_gc */
139     NULL,       /* free_gc */
140     NULL,       /* create_font */
141     NULL,       /* free_font */
142     XInputClose,        /* close_display */
143     XInputWireToEvent,  /* wire_to_event */
144     (core_event_to_wire)_XiEventToWire, /* event_to_wire */
145     NULL,       /* error */
146     XInputError,        /* error_string */
147 };
148
149 static const char *XInputErrorList[] = {
150     "BadDevice, invalid or uninitialized input device", /* BadDevice */
151     "BadEvent, invalid event type",     /* BadEvent */
152     "BadMode, invalid mode parameter",  /* BadMode  */
153     "DeviceBusy, device is busy",       /* DeviceBusy */
154     "BadClass, invalid event class",    /* BadClass */
155 };
156
157 /* Get the version supported by the server to know which number of
158 * events are support. Otherwise, a wrong number of events may smash
159 * the Xlib-internal event processing vector.
160 *
161 * Since the extension hasn't been initialized yet, we need to
162 * manually get the opcode, then the version.
163 */
164 static int
165 _XiFindEventsSupported(Display *dpy)
166 {
167     XExtCodes codes;
168     XExtensionVersion *extversion = NULL;
169     int nevents = 0;
170
171     if (!XQueryExtension(dpy, INAME, &codes.major_opcode,
172                          &codes.first_event, &codes.first_error))
173         goto out;
174
175     LockDisplay(dpy);
176     extversion = _XiGetExtensionVersionRequest(dpy, INAME, codes.major_opcode);
177     UnlockDisplay(dpy);
178     SyncHandle();
179
180     if (!extversion || !extversion->present)
181         goto out;
182
183     if (extversion->major_version >= 2)
184         nevents = IEVENTS; /* number is fixed, XI2 adds GenericEvents only */
185     else if (extversion->major_version <= 0)
186     {
187         printf("XInput_find_display: invalid extension version %d.%d\n",
188                 extversion->major_version, extversion->minor_version);
189         goto out;
190     }
191     else
192     {
193         switch(extversion->minor_version)
194         {
195             case XI_Add_DeviceProperties_Minor:
196                 nevents = XI_DevicePropertyNotify + 1;
197                 break;
198             case  XI_Add_DevicePresenceNotify_Minor:
199                 nevents = XI_DevicePresenceNotify + 1;
200                 break;
201             default:
202                 nevents = XI_DeviceButtonstateNotify + 1;
203                 break;
204         }
205     }
206
207 out:
208     if (extversion)
209         XFree(extversion);
210     return nevents;
211 }
212
213
214 _X_HIDDEN
215 XExtDisplayInfo *XInput_find_display (Display *dpy)
216 {
217     XExtDisplayInfo *dpyinfo;
218     if (!xinput_info) { if (!(xinput_info = XextCreateExtension())) return NULL; }
219     if (!(dpyinfo = XextFindDisplay (xinput_info, dpy)))
220     {
221       int nevents = _XiFindEventsSupported(dpy);
222
223       dpyinfo = XextAddDisplay (xinput_info, dpy,
224                                 xinput_extension_name,
225                                 &xinput_extension_hooks,
226                                 nevents, NULL);
227       if (dpyinfo->codes) /* NULL if XI doesn't exist on the server */
228       {
229           XESetWireToEventCookie(dpy, dpyinfo->codes->major_opcode, XInputWireToCookie);
230           XESetCopyEventCookie(dpy, dpyinfo->codes->major_opcode, XInputCopyCookie);
231       }
232     }
233     return dpyinfo;
234 }
235
236 static XEXT_GENERATE_ERROR_STRING(XInputError, xinput_extension_name,
237                                   IERRORS, XInputErrorList)
238 /*******************************************************************
239 *
240 * Input extension versions.
241 *
242 */
243 static XExtensionVersion versions[] = { {XI_Absent, 0, 0},
244 {XI_Present, XI_Initial_Release_Major, XI_Initial_Release_Minor},
245 {XI_Present, XI_Add_XDeviceBell_Major, XI_Add_XDeviceBell_Minor},
246 {XI_Present, XI_Add_XSetDeviceValuators_Major,
247  XI_Add_XSetDeviceValuators_Minor},
248 {XI_Present, XI_Add_XChangeDeviceControl_Major,
249  XI_Add_XChangeDeviceControl_Minor},
250 {XI_Present, XI_Add_DevicePresenceNotify_Major,
251  XI_Add_DevicePresenceNotify_Minor},
252 {XI_Present, XI_Add_DeviceProperties_Major,
253  XI_Add_DeviceProperties_Minor},
254 {XI_Present, 2, 0},
255 {XI_Present, 2, 1},
256 {XI_Present, 2, 2}
257 };
258
259 /***********************************************************************
260  *
261  * Return errors reported by this extension.
262  *
263  */
264
265 void
266 _xibaddevice(
267     Display     *dpy,
268     int         *error)
269 {
270     XExtDisplayInfo *info = XInput_find_display(dpy);
271
272     *error = info->codes->first_error + XI_BadDevice;
273 }
274
275 void
276 _xibadclass(
277     Display     *dpy,
278     int         *error)
279 {
280     XExtDisplayInfo *info = XInput_find_display(dpy);
281
282     *error = info->codes->first_error + XI_BadClass;
283 }
284
285 void
286 _xibadevent(
287     Display     *dpy,
288     int         *error)
289 {
290     XExtDisplayInfo *info = XInput_find_display(dpy);
291
292     *error = info->codes->first_error + XI_BadEvent;
293 }
294
295 void
296 _xibadmode(
297     Display     *dpy,
298     int         *error)
299 {
300     XExtDisplayInfo *info = XInput_find_display(dpy);
301
302     *error = info->codes->first_error + XI_BadMode;
303 }
304
305 void
306 _xidevicebusy(
307     Display     *dpy,
308     int         *error)
309 {
310     XExtDisplayInfo *info = XInput_find_display(dpy);
311
312     *error = info->codes->first_error + XI_DeviceBusy;
313 }
314
315 static int XInputCheckExtension(Display *dpy, XExtDisplayInfo *info)
316 {
317     XextCheckExtension (dpy, info, xinput_extension_name, 0);
318     return 1;
319 }
320
321 /*****************************************************************
322  * Compare version numbers between info and the built-in version table.
323  * Returns
324  *   -1 if info's version is less than version_index's version,
325  *   0 if equal (or DontCheck),
326  *   1 if info's version is greater than version_index's version.
327  * Returns -2 on initialization errors which shouldn't happen if you call it
328  * correctly.
329  */
330 _X_HIDDEN int
331 _XiCheckVersion(XExtDisplayInfo *info,
332                 int version_index)
333 {
334     XExtensionVersion *ext;
335
336     if (versions[version_index].major_version == Dont_Check)
337         return 0;
338
339     if (!info->data)
340         return -2;
341
342     ext = ((XInputData *) info->data)->vers;
343     if (!ext)
344         return -2;
345
346     if (ext->major_version == versions[version_index].major_version &&
347         ext->minor_version == versions[version_index].minor_version)
348         return 0;
349
350     if (ext->major_version < versions[version_index].major_version ||
351         (ext->major_version == versions[version_index].major_version &&
352          ext->minor_version < versions[version_index].minor_version))
353         return -1;
354     else
355         return 1;
356 }
357
358 /***********************************************************************
359  *
360  * Check to see if the input extension is installed in the server.
361  * Also check to see if the version is >= the requested version.
362  *
363  */
364
365 _X_HIDDEN int
366 _XiCheckExtInit(
367     register Display    *dpy,
368     register int         version_index,
369     XExtDisplayInfo     *info)
370 {
371     if (!XInputCheckExtension(dpy, info)) {
372         UnlockDisplay(dpy);
373         return (-1);
374     }
375
376     if (info->data == NULL) {
377         info->data = (XPointer) Xmalloc(sizeof(XInputData));
378         if (!info->data) {
379             UnlockDisplay(dpy);
380             return (-1);
381         }
382         ((XInputData *) info->data)->vers =
383             _XiGetExtensionVersion(dpy, "XInputExtension", info);
384     }
385
386     if (_XiCheckVersion(info, version_index) < 0) {
387         UnlockDisplay(dpy);
388         return -1;
389     }
390
391     return (0);
392 }
393
394 /***********************************************************************
395  *
396  * Close display routine.
397  *
398  */
399
400 static int
401 XInputClose(
402     Display     *dpy,
403     XExtCodes   *codes)
404 {
405     XExtDisplayInfo *info = XInput_find_display(dpy);
406
407     if (info->data != NULL) {
408         XFree((char *)((XInputData *) info->data)->vers);
409         XFree((char *)info->data);
410     }
411
412     if (!XextRemoveDisplay(xinput_info, dpy))
413         return 0;
414
415     if (xinput_info->ndisplays == 0) {
416         XextDestroyExtension(xinput_info);
417         xinput_info = NULL;
418     }
419
420     return 1;
421 }
422
423 static int
424 Ones(Mask mask)
425 {
426     register Mask y;
427
428     y = (mask >> 1) & 033333333333;
429     y = mask - y - ((y >> 1) & 033333333333);
430     return (((y + (y >> 3)) & 030707070707) % 077);
431 }
432
433 static int count_bits(unsigned char* ptr, int len)
434 {
435     int bits = 0;
436     unsigned int i;
437     unsigned char x;
438
439     for (i = 0; i < len; i++)
440     {
441         x = ptr[i];
442         while(x > 0)
443         {
444             bits += (x & 0x1);
445             x >>= 1;
446         }
447     }
448     return bits;
449 }
450
451 int
452 _XiGetDevicePresenceNotifyEvent(Display * dpy)
453 {
454     XExtDisplayInfo *info = XInput_find_display(dpy);
455
456     return info->codes->first_event + XI_DevicePresenceNotify;
457 }
458
459 /***********************************************************************
460  *
461  * Handle Input extension events.
462  * Reformat a wire event into an XEvent structure of the right type.
463  *
464  */
465
466 static Bool
467 XInputWireToEvent(
468     Display     *dpy,
469     XEvent      *re,
470     xEvent      *event)
471 {
472     unsigned int type, reltype;
473     XExtDisplayInfo *info = XInput_find_display(dpy);
474     XEvent *save = (XEvent *) info->data;
475
476     type = event->u.u.type & 0x7f;
477     reltype = (type - info->codes->first_event);
478
479     if (type == GenericEvent || 
480         (reltype != XI_DeviceValuator &&
481         reltype != XI_DeviceKeystateNotify &&
482         reltype != XI_DeviceButtonstateNotify)) {
483         *save = emptyevent;
484         save->type = type;
485         ((XAnyEvent *) save)->serial = _XSetLastRequestRead(dpy,
486                                                             (xGenericReply *)
487                                                             event);
488         ((XAnyEvent *) save)->send_event = ((event->u.u.type & 0x80) != 0);
489         ((XAnyEvent *) save)->display = dpy;
490     }
491
492     /* Process traditional events */
493     if (type != GenericEvent)
494     {
495         switch (reltype) {
496             case XI_DeviceMotionNotify:
497                 {
498                     register XDeviceMotionEvent *ev = (XDeviceMotionEvent *) save;
499                     deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event;
500
501                     ev->root = ev2->root;
502                     ev->window = ev2->event;
503                     ev->subwindow = ev2->child;
504                     ev->time = ev2->time;
505                     ev->x_root = ev2->root_x;
506                     ev->y_root = ev2->root_y;
507                     ev->x = ev2->event_x;
508                     ev->y = ev2->event_y;
509                     ev->state = ev2->state;
510                     ev->same_screen = ev2->same_screen;
511                     ev->is_hint = ev2->detail;
512                     ev->deviceid = ev2->deviceid & DEVICE_BITS;
513                     return (DONT_ENQUEUE);
514                 }
515                 break;
516             case XI_DeviceKeyPress:
517             case XI_DeviceKeyRelease:
518                 {
519                     register XDeviceKeyEvent *ev = (XDeviceKeyEvent *) save;
520                     deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event;
521
522                     ev->root = ev2->root;
523                     ev->window = ev2->event;
524                     ev->subwindow = ev2->child;
525                     ev->time = ev2->time;
526                     ev->x_root = ev2->root_x;
527                     ev->y_root = ev2->root_y;
528                     ev->x = ev2->event_x;
529                     ev->y = ev2->event_y;
530                     ev->state = ev2->state;
531                     ev->same_screen = ev2->same_screen;
532                     ev->keycode = ev2->detail;
533                     ev->deviceid = ev2->deviceid & DEVICE_BITS;
534                     if (ev2->deviceid & MORE_EVENTS)
535                         return (DONT_ENQUEUE);
536                     else {
537                         *re = *save;
538                         return (ENQUEUE_EVENT);
539                     }
540                 }
541                 break;
542             case XI_DeviceButtonPress:
543             case XI_DeviceButtonRelease:
544                 {
545                     register XDeviceButtonEvent *ev = (XDeviceButtonEvent *) save;
546                     deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event;
547
548                     ev->root = ev2->root;
549                     ev->window = ev2->event;
550                     ev->subwindow = ev2->child;
551                     ev->time = ev2->time;
552                     ev->x_root = ev2->root_x;
553                     ev->y_root = ev2->root_y;
554                     ev->x = ev2->event_x;
555                     ev->y = ev2->event_y;
556                     ev->state = ev2->state;
557                     ev->same_screen = ev2->same_screen;
558                     ev->button = ev2->detail;
559                     ev->deviceid = ev2->deviceid & DEVICE_BITS;
560                     if (ev2->deviceid & MORE_EVENTS)
561                         return (DONT_ENQUEUE);
562                     else {
563                         *re = *save;
564                         return (ENQUEUE_EVENT);
565                     }
566                 }
567                 break;
568             case XI_ProximityIn:
569             case XI_ProximityOut:
570                 {
571                     register XProximityNotifyEvent *ev = (XProximityNotifyEvent *) save;
572                     deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event;
573
574                     ev->root = ev2->root;
575                     ev->window = ev2->event;
576                     ev->subwindow = ev2->child;
577                     ev->time = ev2->time;
578                     ev->x_root = ev2->root_x;
579                     ev->y_root = ev2->root_y;
580                     ev->x = ev2->event_x;
581                     ev->y = ev2->event_y;
582                     ev->state = ev2->state;
583                     ev->same_screen = ev2->same_screen;
584                     ev->deviceid = ev2->deviceid & DEVICE_BITS;
585                     if (ev2->deviceid & MORE_EVENTS)
586                         return (DONT_ENQUEUE);
587                     else {
588                         *re = *save;
589                         return (ENQUEUE_EVENT);
590                     }
591                 }
592                 break;
593             case XI_DeviceValuator:
594                 {
595                     deviceValuator *xev = (deviceValuator *) event;
596                     int save_type = save->type - info->codes->first_event;
597                     int i;
598
599                     if (save_type == XI_DeviceKeyPress || save_type == XI_DeviceKeyRelease) {
600                         XDeviceKeyEvent *kev = (XDeviceKeyEvent *) save;
601
602                         kev->device_state = xev->device_state;
603                         kev->axes_count = xev->num_valuators;
604                         kev->first_axis = xev->first_valuator;
605                         i = xev->num_valuators;
606                         if (i > 6)
607                             i = 6;
608                         switch (i) {
609                             case 6:
610                                 kev->axis_data[5] = xev->valuator5;
611                             case 5:
612                                 kev->axis_data[4] = xev->valuator4;
613                             case 4:
614                                 kev->axis_data[3] = xev->valuator3;
615                             case 3:
616                                 kev->axis_data[2] = xev->valuator2;
617                             case 2:
618                                 kev->axis_data[1] = xev->valuator1;
619                             case 1:
620                                 kev->axis_data[0] = xev->valuator0;
621                         }
622                     } else if (save_type == XI_DeviceButtonPress ||
623                             save_type == XI_DeviceButtonRelease) {
624                         XDeviceButtonEvent *bev = (XDeviceButtonEvent *) save;
625
626                         bev->device_state = xev->device_state;
627                         bev->axes_count = xev->num_valuators;
628                         bev->first_axis = xev->first_valuator;
629                         i = xev->num_valuators;
630                         if (i > 6)
631                             i = 6;
632                         switch (i) {
633                             case 6:
634                                 bev->axis_data[5] = xev->valuator5;
635                             case 5:
636                                 bev->axis_data[4] = xev->valuator4;
637                             case 4:
638                                 bev->axis_data[3] = xev->valuator3;
639                             case 3:
640                                 bev->axis_data[2] = xev->valuator2;
641                             case 2:
642                                 bev->axis_data[1] = xev->valuator1;
643                             case 1:
644                                 bev->axis_data[0] = xev->valuator0;
645                         }
646                     } else if (save_type == XI_DeviceMotionNotify) {
647                         XDeviceMotionEvent *mev = (XDeviceMotionEvent *) save;
648
649                         mev->device_state = xev->device_state;
650                         mev->axes_count = xev->num_valuators;
651                         mev->first_axis = xev->first_valuator;
652                         i = xev->num_valuators;
653                         if (i > 6)
654                             i = 6;
655                         switch (i) {
656                             case 6:
657                                 mev->axis_data[5] = xev->valuator5;
658                             case 5:
659                                 mev->axis_data[4] = xev->valuator4;
660                             case 4:
661                                 mev->axis_data[3] = xev->valuator3;
662                             case 3:
663                                 mev->axis_data[2] = xev->valuator2;
664                             case 2:
665                                 mev->axis_data[1] = xev->valuator1;
666                             case 1:
667                                 mev->axis_data[0] = xev->valuator0;
668                         }
669                     } else if (save_type == XI_ProximityIn || save_type == XI_ProximityOut) {
670                         XProximityNotifyEvent *pev = (XProximityNotifyEvent *) save;
671
672                         pev->device_state = xev->device_state;
673                         pev->axes_count = xev->num_valuators;
674                         pev->first_axis = xev->first_valuator;
675                         i = xev->num_valuators;
676                         if (i > 6)
677                             i = 6;
678                         switch (i) {
679                             case 6:
680                                 pev->axis_data[5] = xev->valuator5;
681                             case 5:
682                                 pev->axis_data[4] = xev->valuator4;
683                             case 4:
684                                 pev->axis_data[3] = xev->valuator3;
685                             case 3:
686                                 pev->axis_data[2] = xev->valuator2;
687                             case 2:
688                                 pev->axis_data[1] = xev->valuator1;
689                             case 1:
690                                 pev->axis_data[0] = xev->valuator0;
691                         }
692                     } else if (save_type == XI_DeviceStateNotify) {
693                         int j;
694                         XDeviceStateNotifyEvent *sev = (XDeviceStateNotifyEvent *) save;
695                         XInputClass *any = (XInputClass *) & sev->data[0];
696                         XValuatorStatus *v;
697
698                         for (i = 0; i < sev->num_classes; i++)
699                             if (any->class != ValuatorClass)
700                                 any = (XInputClass *) ((char *)any + any->length);
701                         v = (XValuatorStatus *) any;
702                         i = v->num_valuators;
703                         j = xev->num_valuators;
704                         if (j > 3)
705                             j = 3;
706                         switch (j) {
707                             case 3:
708                                 v->valuators[i + 2] = xev->valuator2;
709                             case 2:
710                                 v->valuators[i + 1] = xev->valuator1;
711                             case 1:
712                                 v->valuators[i + 0] = xev->valuator0;
713                         }
714                         v->num_valuators += j;
715
716                     }
717                     *re = *save;
718                     return (ENQUEUE_EVENT);
719                 }
720                 break;
721             case XI_DeviceFocusIn:
722             case XI_DeviceFocusOut:
723                 {
724                     register XDeviceFocusChangeEvent *ev = (XDeviceFocusChangeEvent *) re;
725                     deviceFocus *fev = (deviceFocus *) event;
726
727                     *ev = *((XDeviceFocusChangeEvent *) save);
728                     ev->window = fev->window;
729                     ev->time = fev->time;
730                     ev->mode = fev->mode;
731                     ev->detail = fev->detail;
732                     ev->deviceid = fev->deviceid & DEVICE_BITS;
733                     return (ENQUEUE_EVENT);
734                 }
735                 break;
736             case XI_DeviceStateNotify:
737                 {
738                     int j;
739                     XDeviceStateNotifyEvent *stev = (XDeviceStateNotifyEvent *) save;
740                     deviceStateNotify *sev = (deviceStateNotify *) event;
741                     char *data;
742
743                     stev->window = None;
744                     stev->deviceid = sev->deviceid & DEVICE_BITS;
745                     stev->time = sev->time;
746                     stev->num_classes = Ones((Mask) sev->classes_reported & InputClassBits);
747                     data = (char *)&stev->data[0];
748                     if (sev->classes_reported & (1 << KeyClass)) {
749                         register XKeyStatus *kstev = (XKeyStatus *) data;
750
751                         kstev->class = KeyClass;
752                         kstev->length = sizeof(XKeyStatus);
753                         kstev->num_keys = sev->num_keys;
754                         memcpy((char *)&kstev->keys[0], (char *)&sev->keys[0], 4);
755                         data += sizeof(XKeyStatus);
756                     }
757                     if (sev->classes_reported & (1 << ButtonClass)) {
758                         register XButtonStatus *bev = (XButtonStatus *) data;
759
760                         bev->class = ButtonClass;
761                         bev->length = sizeof(XButtonStatus);
762                         bev->num_buttons = sev->num_buttons;
763                         memcpy((char *)bev->buttons, (char *)sev->buttons, 4);
764                         data += sizeof(XButtonStatus);
765                     }
766                     if (sev->classes_reported & (1 << ValuatorClass)) {
767                         register XValuatorStatus *vev = (XValuatorStatus *) data;
768
769                         vev->class = ValuatorClass;
770                         vev->length = sizeof(XValuatorStatus);
771                         vev->num_valuators = sev->num_valuators;
772                         vev->mode = sev->classes_reported >> ModeBitsShift;
773                         j = sev->num_valuators;
774                         if (j > 3)
775                             j = 3;
776                         switch (j) {
777                             case 3:
778                                 vev->valuators[2] = sev->valuator2;
779                             case 2:
780                                 vev->valuators[1] = sev->valuator1;
781                             case 1:
782                                 vev->valuators[0] = sev->valuator0;
783                         }
784                         data += sizeof(XValuatorStatus);
785                     }
786                     if (sev->deviceid & MORE_EVENTS)
787                         return (DONT_ENQUEUE);
788                     else {
789                         *re = *save;
790                         return (ENQUEUE_EVENT);
791                     }
792                 }
793                 break;
794             case XI_DeviceKeystateNotify:
795                 {
796                     int i;
797                     XInputClass *anyclass;
798                     register XKeyStatus *kv;
799                     deviceKeyStateNotify *ksev = (deviceKeyStateNotify *) event;
800                     XDeviceStateNotifyEvent *kstev = (XDeviceStateNotifyEvent *) save;
801
802                     anyclass = (XInputClass *) & kstev->data[0];
803                     for (i = 0; i < kstev->num_classes; i++)
804                         if (anyclass->class == KeyClass)
805                             break;
806                         else
807                             anyclass = (XInputClass *) ((char *)anyclass +
808                                     anyclass->length);
809
810                     kv = (XKeyStatus *) anyclass;
811                     kv->num_keys = 256;
812                     memcpy((char *)&kv->keys[4], (char *)ksev->keys, 28);
813                     if (ksev->deviceid & MORE_EVENTS)
814                         return (DONT_ENQUEUE);
815                     else {
816                         *re = *save;
817                         return (ENQUEUE_EVENT);
818                     }
819                 }
820                 break;
821             case XI_DeviceButtonstateNotify:
822                 {
823                     int i;
824                     XInputClass *anyclass;
825                     register XButtonStatus *bv;
826                     deviceButtonStateNotify *bsev = (deviceButtonStateNotify *) event;
827                     XDeviceStateNotifyEvent *bstev = (XDeviceStateNotifyEvent *) save;
828
829                     anyclass = (XInputClass *) & bstev->data[0];
830                     for (i = 0; i < bstev->num_classes; i++)
831                         if (anyclass->class == ButtonClass)
832                             break;
833                         else
834                             anyclass = (XInputClass *) ((char *)anyclass +
835                                     anyclass->length);
836
837                     bv = (XButtonStatus *) anyclass;
838                     bv->num_buttons = 256;
839                     memcpy((char *)&bv->buttons[4], (char *)bsev->buttons, 28);
840                     if (bsev->deviceid & MORE_EVENTS)
841                         return (DONT_ENQUEUE);
842                     else {
843                         *re = *save;
844                         return (ENQUEUE_EVENT);
845                     }
846                 }
847                 break;
848             case XI_DeviceMappingNotify:
849                 {
850                     register XDeviceMappingEvent *ev = (XDeviceMappingEvent *) re;
851                     deviceMappingNotify *ev2 = (deviceMappingNotify *) event;
852
853                     *ev = *((XDeviceMappingEvent *) save);
854                     ev->window = 0;
855                     ev->first_keycode = ev2->firstKeyCode;
856                     ev->request = ev2->request;
857                     ev->count = ev2->count;
858                     ev->time = ev2->time;
859                     ev->deviceid = ev2->deviceid & DEVICE_BITS;
860                     return (ENQUEUE_EVENT);
861                 }
862                 break;
863             case XI_ChangeDeviceNotify:
864                 {
865                     register XChangeDeviceNotifyEvent *ev = (XChangeDeviceNotifyEvent *) re;
866                     changeDeviceNotify *ev2 = (changeDeviceNotify *) event;
867
868                     *ev = *((XChangeDeviceNotifyEvent *) save);
869                     ev->window = 0;
870                     ev->request = ev2->request;
871                     ev->time = ev2->time;
872                     ev->deviceid = ev2->deviceid & DEVICE_BITS;
873                     return (ENQUEUE_EVENT);
874                 }
875                 break;
876
877             case XI_DevicePresenceNotify:
878                 {
879                     XDevicePresenceNotifyEvent *ev = (XDevicePresenceNotifyEvent *) re;
880                     devicePresenceNotify *ev2 = (devicePresenceNotify *) event;
881
882                     *ev = *(XDevicePresenceNotifyEvent *) save;
883                     ev->window = 0;
884                     ev->time = ev2->time;
885                     ev->devchange = ev2->devchange;
886                     ev->deviceid = ev2->deviceid;
887                     ev->control = ev2->control;
888                     return (ENQUEUE_EVENT);
889                 }
890                 break;
891             case XI_DevicePropertyNotify:
892                 {
893                     XDevicePropertyNotifyEvent* ev = (XDevicePropertyNotifyEvent*)re;
894                     devicePropertyNotify *ev2 = (devicePropertyNotify*)event;
895
896                     *ev = *(XDevicePropertyNotifyEvent*)save;
897                     ev->time = ev2->time;
898                     ev->deviceid = ev2->deviceid;
899                     ev->atom = ev2->atom;
900                     ev->state = ev2->state;
901                     return ENQUEUE_EVENT;
902                 }
903                 break;
904             default:
905                 printf("XInputWireToEvent: UNKNOWN WIRE EVENT! type=%d\n", type);
906                 break;
907         }
908     }
909     return (DONT_ENQUEUE);
910 }
911
912 static void xge_copy_to_cookie(xGenericEvent* ev,
913                                XGenericEventCookie *cookie)
914 {
915     cookie->type = ev->type;
916     cookie->evtype = ev->evtype;
917     cookie->extension = ev->extension;
918 }
919
920 static Bool
921 XInputWireToCookie(
922     Display     *dpy,
923     XGenericEventCookie *cookie,
924     xEvent      *event)
925 {
926     XExtDisplayInfo *info = XInput_find_display(dpy);
927     XEvent *save = (XEvent *) info->data;
928     xGenericEvent* ge = (xGenericEvent*)event;
929
930     if (ge->extension != info->codes->major_opcode)
931     {
932         printf("XInputWireToCookie: wrong extension opcode %d\n",
933                 ge->extension);
934         return DONT_ENQUEUE;
935     }
936
937     *save = emptyevent;
938     save->type = event->u.u.type;
939     ((XAnyEvent*)save)->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
940     ((XAnyEvent*)save)->send_event = ((event->u.u.type & 0x80) != 0);
941     ((XAnyEvent*)save)->display = dpy;
942
943     xge_copy_to_cookie((xGenericEvent*)event, (XGenericEventCookie*)save);
944     switch(ge->evtype)
945     {
946         case XI_Motion:
947         case XI_ButtonPress:
948         case XI_ButtonRelease:
949         case XI_KeyPress:
950         case XI_KeyRelease:
951         case XI_TouchBegin:
952         case XI_TouchUpdate:
953         case XI_TouchEnd:
954             *cookie = *(XGenericEventCookie*)save;
955             if (!wireToDeviceEvent((xXIDeviceEvent*)event, cookie))
956             {
957                 printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
958                         ge->evtype);
959                 break;
960             }
961             return ENQUEUE_EVENT;
962         case XI_DeviceChanged:
963             *cookie = *(XGenericEventCookie*)save;
964             if (!wireToDeviceChangedEvent((xXIDeviceChangedEvent*)event, cookie))
965             {
966                 printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
967                         ge->evtype);
968                 break;
969             }
970             return ENQUEUE_EVENT;
971         case XI_HierarchyChanged:
972             *cookie = *(XGenericEventCookie*)save;
973             if (!wireToHierarchyChangedEvent((xXIHierarchyEvent*)event, cookie))
974             {
975                 printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
976                         ge->evtype);
977                 break;
978             }
979             return ENQUEUE_EVENT;
980         case XI_TouchOwnership:
981             *cookie = *(XGenericEventCookie*)save;
982             if (!wireToTouchOwnershipEvent((xXITouchOwnershipEvent*)event,
983                                            cookie))
984             {
985                 printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
986                         ge->evtype);
987                 break;
988             }
989             return ENQUEUE_EVENT;
990
991         case XI_RawKeyPress:
992         case XI_RawKeyRelease:
993         case XI_RawButtonPress:
994         case XI_RawButtonRelease:
995         case XI_RawMotion:
996         case XI_RawTouchBegin:
997         case XI_RawTouchUpdate:
998         case XI_RawTouchEnd:
999             *cookie = *(XGenericEventCookie*)save;
1000             if (!wireToRawEvent(info, (xXIRawEvent*)event, cookie))
1001             {
1002                 printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
1003                         ge->evtype);
1004                 break;
1005             }
1006             return ENQUEUE_EVENT;
1007         case XI_Enter:
1008         case XI_Leave:
1009         case XI_FocusIn:
1010         case XI_FocusOut:
1011             *cookie = *(XGenericEventCookie*)save;
1012             if (!wireToEnterLeave((xXIEnterEvent*)event, cookie))
1013             {
1014                 printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
1015                         ge->evtype);
1016                 break;
1017             }
1018             return ENQUEUE_EVENT;
1019         case XI_PropertyEvent:
1020             *cookie = *(XGenericEventCookie*)save;
1021             if (!wireToPropertyEvent((xXIPropertyEvent*)event, cookie))
1022             {
1023                 printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
1024                         ge->evtype);
1025                 break;
1026             }
1027             return ENQUEUE_EVENT;
1028         case XI_BarrierHit:
1029         case XI_BarrierLeave:
1030             *cookie = *(XGenericEventCookie*)save;
1031             if (!wireToBarrierEvent((xXIBarrierEvent*)event, cookie))
1032             {
1033                 printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
1034                         ge->evtype);
1035                 break;
1036             }
1037             return ENQUEUE_EVENT;
1038         default:
1039             printf("XInputWireToCookie: Unknown generic event. type %d\n", ge->evtype);
1040
1041     }
1042     return DONT_ENQUEUE;
1043 }
1044
1045 /**
1046  * Calculate length in bytes needed for the device event with the given
1047  * button mask length, valuator mask length + valuator mask. All parameters
1048  * in bytes.
1049  */
1050 static inline int
1051 sizeDeviceEvent(int buttons_len, int valuators_len,
1052                 unsigned char *valuators_mask)
1053 {
1054     int len;
1055
1056     len = sizeof(XIDeviceEvent);
1057     len += sizeof(XIButtonState) + buttons_len;
1058     len += sizeof(XIValuatorState) + valuators_len;
1059     len += count_bits(valuators_mask, valuators_len) * sizeof(double);
1060     len += sizeof(XIModifierState) + sizeof(XIGroupState);
1061
1062     return len;
1063 }
1064
1065 /* Return the size with added padding so next element would be
1066    double-aligned unless the architecture is known to allow unaligned
1067    data accesses.  Not doing this can cause a bus error on
1068    MIPS N32. */
1069 static int
1070 pad_to_double(int size)
1071 {
1072 #if !defined(__i386__) && !defined(__sh__)
1073     if (size % sizeof(double) != 0)
1074         size += sizeof(double) - size % sizeof(double);
1075 #endif
1076     return size;
1077 }
1078
1079 /**
1080  * Set structure and atoms to size in bytes of XIButtonClassInfo, its
1081  * button state mask and labels array.
1082  */
1083 static void
1084 sizeXIButtonClassType(int num_buttons, int* structure, int* state, int* atoms)
1085 {
1086     int size;
1087     int labels;
1088
1089     *structure = pad_to_double(sizeof(XIButtonClassInfo));
1090     size = ((((num_buttons + 7)/8) + 3)/4);
1091
1092     /* Force mask alignment with longs to avoid unaligned
1093      * access when accessing the atoms. */
1094     *state = pad_to_double(size * 4);
1095     labels = num_buttons * sizeof(Atom);
1096
1097     /* Force mask alignment with longs to avoid
1098      * unaligned access when accessing the atoms. */
1099     labels += ((((num_buttons + 7)/8) + 3)/4) * sizeof(Atom);
1100     *atoms = pad_to_double(labels);
1101 }
1102
1103 /**
1104  * Set structure and keycodes to size in bytes of XIKeyClassInfo and
1105  * its keycodes array.
1106  */
1107 static void
1108 sizeXIKeyClassType(int num_keycodes, int* structure, int* keycodes)
1109 {
1110     *structure = pad_to_double(sizeof(XIKeyClassInfo));
1111     *keycodes = pad_to_double(num_keycodes * sizeof(int));
1112 }
1113
1114 /**
1115  * Return the size in bytes required to store the matching class type
1116  * num_elements is num_buttons for XIButtonClass or num_keycodes for
1117  * XIKeyClass.
1118  *
1119  * Also used from copy_classes in XIQueryDevice.c
1120  */
1121 static int
1122 sizeDeviceClassType(int type, int num_elements)
1123 {
1124     int l = 0;
1125     int extra1 = 0;
1126     int extra2 = 0;
1127     switch(type)
1128     {
1129         case XIButtonClass:
1130             sizeXIButtonClassType(num_elements, &l, &extra1, &extra2);
1131             l += extra1 + extra2;
1132             break;
1133         case XIKeyClass:
1134             sizeXIKeyClassType(num_elements, &l, &extra1);
1135             l += extra1;
1136             break;
1137         case XIValuatorClass:
1138             l = pad_to_double(sizeof(XIValuatorClassInfo));
1139             break;
1140         case XIScrollClass:
1141             l = pad_to_double(sizeof(XIScrollClassInfo));
1142             break;
1143         case XITouchClass:
1144             l = pad_to_double(sizeof(XITouchClassInfo));
1145             break;
1146         default:
1147             printf("sizeDeviceClassType: unknown type %d\n", type);
1148             break;
1149     }
1150     return l;
1151 }
1152
1153 static Bool
1154 copyHierarchyEvent(XGenericEventCookie *cookie_in,
1155                    XGenericEventCookie *cookie_out)
1156 {
1157     XIHierarchyEvent *in, *out;
1158     void *ptr;
1159
1160     in = cookie_in->data;
1161
1162     ptr = cookie_out->data = malloc(sizeof(XIHierarchyEvent) +
1163                                     in->num_info * sizeof(XIHierarchyInfo));
1164     if (!ptr)
1165         return False;
1166
1167     out = next_block(&ptr, sizeof(XIHierarchyEvent));
1168     *out = *in;
1169     out->info = next_block(&ptr, in->num_info * sizeof(XIHierarchyInfo));
1170     memcpy(out->info, in->info, in->num_info * sizeof(XIHierarchyInfo));
1171
1172     return True;
1173 }
1174
1175 static Bool
1176 copyDeviceChangedEvent(XGenericEventCookie *in_cookie,
1177                        XGenericEventCookie *out_cookie)
1178 {
1179     int len, i;
1180     XIDeviceChangedEvent *in, *out;
1181     XIAnyClassInfo *any;
1182     void *ptr;
1183
1184     in = in_cookie->data;
1185
1186     len = sizeof(XIDeviceChangedEvent);
1187     len += in->num_classes * sizeof(XIAnyClassInfo*);
1188
1189     for (i = 0; i < in->num_classes; i++)
1190     {
1191         any = in->classes[i];
1192         switch(any->type)
1193         {
1194             case XIButtonClass:
1195                 len += sizeDeviceClassType(XIButtonClass,
1196                         ((XIButtonClassInfo*)any)->num_buttons);
1197                 break;
1198             case XIKeyClass:
1199                 len += sizeDeviceClassType(XIKeyClass,
1200                         ((XIKeyClassInfo*)any)->num_keycodes);
1201                 break;
1202             case XIValuatorClass:
1203                 len += sizeDeviceClassType(XIValuatorClass, 0);
1204                 break;
1205             case XIScrollClass:
1206                 len += sizeDeviceClassType(XIScrollClass, 0);
1207                 break;
1208             default:
1209                 printf("copyDeviceChangedEvent: unknown type %d\n",
1210                         any->type);
1211                 break;
1212         }
1213
1214     }
1215
1216     ptr = out_cookie->data = malloc(len);
1217     if (!ptr)
1218         return False;
1219     out = next_block(&ptr, sizeof(XIDeviceChangedEvent));
1220     *out = *in;
1221
1222     out->classes = next_block(&ptr,
1223                               out->num_classes * sizeof(XIAnyClassInfo*));
1224
1225     for (i = 0; i < in->num_classes; i++)
1226     {
1227         any = in->classes[i];
1228
1229         switch(any->type)
1230         {
1231             case XIButtonClass:
1232                 {
1233                     int struct_size;
1234                     int state_size;
1235                     int labels_size;
1236                     XIButtonClassInfo *bin, *bout;
1237                     bin = (XIButtonClassInfo*)any;
1238                     sizeXIButtonClassType(bin->num_buttons, &struct_size,
1239                                           &state_size, &labels_size);
1240                     bout = next_block(&ptr, struct_size);
1241
1242                     *bout = *bin;
1243                     bout->state.mask = next_block(&ptr, state_size);
1244                     memcpy(bout->state.mask, bin->state.mask,
1245                             bout->state.mask_len);
1246
1247                     bout->labels = next_block(&ptr, labels_size);
1248                     memcpy(bout->labels, bin->labels, bout->num_buttons * sizeof(Atom));
1249                     out->classes[i] = (XIAnyClassInfo*)bout;
1250                     break;
1251                 }
1252             case XIKeyClass:
1253                 {
1254                     XIKeyClassInfo *kin, *kout;
1255                     int struct_size;
1256                     int keycodes_size;
1257                     kin = (XIKeyClassInfo*)any;
1258                     sizeXIKeyClassType(kin->num_keycodes, &struct_size,
1259                                        &keycodes_size);
1260
1261                     kout = next_block(&ptr, struct_size);
1262                     *kout = *kin;
1263                     kout->keycodes = next_block(&ptr, keycodes_size);
1264                     memcpy(kout->keycodes, kin->keycodes, kout->num_keycodes * sizeof(int));
1265                     out->classes[i] = (XIAnyClassInfo*)kout;
1266                     break;
1267                 }
1268             case XIValuatorClass:
1269                 {
1270                     XIValuatorClassInfo *vin, *vout;
1271                     vin = (XIValuatorClassInfo*)any;
1272                     vout = next_block(&ptr,
1273                                       sizeDeviceClassType(XIValuatorClass, 0));
1274                     *vout = *vin;
1275                     out->classes[i] = (XIAnyClassInfo*)vout;
1276                     break;
1277                 }
1278             case XIScrollClass:
1279                 {
1280                     XIScrollClassInfo *sin, *sout;
1281                     sin = (XIScrollClassInfo*)any;
1282                     sout = next_block(&ptr,
1283                                       sizeDeviceClassType(XIScrollClass, 0));
1284                     *sout = *sin;
1285                     out->classes[i] = (XIAnyClassInfo*)sout;
1286                     break;
1287                 }
1288         }
1289     }
1290
1291     return True;
1292 }
1293
1294 static Bool
1295 copyDeviceEvent(XGenericEventCookie *cookie_in,
1296                 XGenericEventCookie *cookie_out)
1297 {
1298     int len;
1299     XIDeviceEvent *in, *out;
1300     int bits; /* valuator bits */
1301     void *ptr;
1302
1303     in = cookie_in->data;
1304     bits = count_bits(in->valuators.mask, in->valuators.mask_len);
1305
1306     len = sizeDeviceEvent(in->buttons.mask_len, in->valuators.mask_len,
1307                           in->valuators.mask);
1308
1309     ptr = cookie_out->data = malloc(len);
1310     if (!ptr)
1311         return False;
1312
1313     out = next_block(&ptr, sizeof(XIDeviceEvent));
1314     *out = *in;
1315
1316     out->buttons.mask = next_block(&ptr, in->buttons.mask_len);
1317     memcpy(out->buttons.mask, in->buttons.mask,
1318            out->buttons.mask_len);
1319     out->valuators.mask = next_block(&ptr, in->valuators.mask_len);
1320     memcpy(out->valuators.mask, in->valuators.mask,
1321            out->valuators.mask_len);
1322     out->valuators.values = next_block(&ptr, bits * sizeof(double));
1323     memcpy(out->valuators.values, in->valuators.values,
1324            bits * sizeof(double));
1325
1326     return True;
1327 }
1328
1329 static Bool
1330 copyEnterEvent(XGenericEventCookie *cookie_in,
1331                XGenericEventCookie *cookie_out)
1332 {
1333     int len;
1334     XIEnterEvent *in, *out;
1335     void *ptr;
1336
1337     in = cookie_in->data;
1338
1339     len = sizeof(XIEnterEvent) + in->buttons.mask_len;
1340
1341     ptr = cookie_out->data = malloc(len);
1342     if (!ptr)
1343         return False;
1344
1345     out = next_block(&ptr, sizeof(XIEnterEvent));
1346     *out = *in;
1347
1348     out->buttons.mask = next_block(&ptr, in->buttons.mask_len);
1349     memcpy(out->buttons.mask, in->buttons.mask, out->buttons.mask_len);
1350
1351     return True;
1352 }
1353
1354 static Bool
1355 copyPropertyEvent(XGenericEventCookie *cookie_in,
1356                   XGenericEventCookie *cookie_out)
1357 {
1358     XIPropertyEvent *in, *out;
1359
1360     in = cookie_in->data;
1361
1362     out = cookie_out->data = malloc(sizeof(XIPropertyEvent));
1363     if (!out)
1364         return False;
1365
1366     *out = *in;
1367     return True;
1368 }
1369
1370 static Bool
1371 copyTouchOwnershipEvent(XGenericEventCookie *cookie_in,
1372                         XGenericEventCookie *cookie_out)
1373 {
1374     XITouchOwnershipEvent *in, *out;
1375
1376     in = cookie_in->data;
1377
1378     out = cookie_out->data = malloc(sizeof(XITouchOwnershipEvent));
1379     if (!out)
1380         return False;
1381
1382     *out = *in;
1383     return True;
1384 }
1385
1386 static Bool
1387 copyRawEvent(XGenericEventCookie *cookie_in,
1388              XGenericEventCookie *cookie_out)
1389 {
1390     XIRawEvent *in, *out;
1391     void *ptr;
1392     int len;
1393     int bits;
1394
1395     in = cookie_in->data;
1396
1397     bits = count_bits(in->valuators.mask, in->valuators.mask_len);
1398     len = sizeof(XIRawEvent) + in->valuators.mask_len;
1399     len += bits * sizeof(double) * 2;
1400
1401     ptr = cookie_out->data = malloc(len);
1402     if (!ptr)
1403         return False;
1404
1405     out = next_block(&ptr, sizeof(XIRawEvent));
1406     *out = *in;
1407     out->valuators.mask = next_block(&ptr, out->valuators.mask_len);
1408     memcpy(out->valuators.mask, in->valuators.mask, out->valuators.mask_len);
1409
1410     out->valuators.values = next_block(&ptr, bits * sizeof(double));
1411     memcpy(out->valuators.values, in->valuators.values, bits * sizeof(double));
1412
1413     out->raw_values = next_block(&ptr, bits * sizeof(double));
1414     memcpy(out->raw_values, in->raw_values, bits * sizeof(double));
1415
1416     return True;
1417 }
1418
1419 static Bool
1420 copyBarrierEvent(XGenericEventCookie *in_cookie,
1421                  XGenericEventCookie *out_cookie)
1422 {
1423     XIBarrierEvent *in, *out;
1424
1425     in = in_cookie->data;
1426
1427     out = out_cookie->data = calloc(1, sizeof(XIBarrierEvent));
1428     if (!out)
1429         return False;
1430     *out = *in;
1431
1432     return True;
1433 }
1434
1435 static Bool
1436 XInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
1437 {
1438     int ret = True;
1439
1440     XExtDisplayInfo *info = XInput_find_display(dpy);
1441
1442     if (in->extension != info->codes->major_opcode)
1443     {
1444         printf("XInputCopyCookie: wrong extension opcode %d\n",
1445                 in->extension);
1446         return False;
1447     }
1448
1449     *out = *in;
1450     out->data = NULL;
1451     out->cookie = 0;
1452
1453     switch(in->evtype) {
1454         case XI_Motion:
1455         case XI_ButtonPress:
1456         case XI_ButtonRelease:
1457         case XI_KeyPress:
1458         case XI_KeyRelease:
1459         case XI_TouchBegin:
1460         case XI_TouchUpdate:
1461         case XI_TouchEnd:
1462             ret = copyDeviceEvent(in, out);
1463             break;
1464         case XI_DeviceChanged:
1465             ret = copyDeviceChangedEvent(in, out);
1466             break;
1467         case XI_HierarchyChanged:
1468             ret = copyHierarchyEvent(in, out);
1469             break;
1470         case XI_Enter:
1471         case XI_Leave:
1472         case XI_FocusIn:
1473         case XI_FocusOut:
1474             ret = copyEnterEvent(in, out);
1475             break;
1476         case XI_PropertyEvent:
1477             ret = copyPropertyEvent(in, out);
1478             break;
1479         case XI_TouchOwnership:
1480             ret = copyTouchOwnershipEvent(in, out);
1481             break;
1482         case XI_RawKeyPress:
1483         case XI_RawKeyRelease:
1484         case XI_RawButtonPress:
1485         case XI_RawButtonRelease:
1486         case XI_RawMotion:
1487         case XI_RawTouchBegin:
1488         case XI_RawTouchUpdate:
1489         case XI_RawTouchEnd:
1490             ret = copyRawEvent(in, out);
1491             break;
1492         case XI_BarrierHit:
1493         case XI_BarrierLeave:
1494             ret = copyBarrierEvent(in, out);
1495             break;
1496         default:
1497             printf("XInputCopyCookie: unknown evtype %d\n", in->evtype);
1498             ret = False;
1499     }
1500
1501     if (!ret)
1502         printf("XInputCopyCookie: Failed to copy evtype %d", in->evtype);
1503     return ret;
1504 }
1505
1506 static int
1507 wireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* cookie)
1508 {
1509     int len, i;
1510     unsigned char *ptr;
1511     void *ptr_lib;
1512     FP3232 *values;
1513     XIDeviceEvent *out;
1514
1515     ptr = (unsigned char*)&in[1] + in->buttons_len * 4;
1516
1517     len = sizeDeviceEvent(in->buttons_len * 4, in->valuators_len * 4, ptr);
1518
1519     cookie->data = ptr_lib = malloc(len);
1520
1521     out = next_block(&ptr_lib, sizeof(XIDeviceEvent));
1522     out->display = cookie->display;
1523     out->type = in->type;
1524     out->serial = in->sequenceNumber;
1525     out->extension = in->extension;
1526     out->evtype = in->evtype;
1527     out->send_event = ((in->type & 0x80) != 0);
1528     out->time = in->time;
1529     out->deviceid = in->deviceid;
1530     out->sourceid = in->sourceid;
1531     out->detail = in->detail;
1532     out->root = in->root;
1533     out->event = in->event;
1534     out->child = in->child;
1535     out->root_x = FP1616toDBL(in->root_x);
1536     out->root_y = FP1616toDBL(in->root_y);
1537     out->event_x = FP1616toDBL(in->event_x);
1538     out->event_y = FP1616toDBL(in->event_y);
1539     out->flags = in->flags;
1540     out->mods.base = in->mods.base_mods;
1541     out->mods.locked = in->mods.locked_mods;
1542     out->mods.latched = in->mods.latched_mods;
1543     out->mods.effective = in->mods.effective_mods;
1544     out->group.base = in->group.base_group;
1545     out->group.locked = in->group.locked_group;
1546     out->group.latched = in->group.latched_group;
1547     out->group.effective = in->group.effective_group;
1548     out->buttons.mask_len = in->buttons_len * 4;
1549     out->valuators.mask_len = in->valuators_len * 4;
1550
1551     out->buttons.mask = next_block(&ptr_lib, out->buttons.mask_len);
1552
1553     /* buttons */
1554     ptr = (unsigned char*)&in[1];
1555     memcpy(out->buttons.mask, ptr, out->buttons.mask_len);
1556     ptr += in->buttons_len * 4;
1557
1558     /* valuators */
1559     out->valuators.mask = next_block(&ptr_lib, out->valuators.mask_len);
1560     memcpy(out->valuators.mask, ptr, out->valuators.mask_len);
1561     ptr += in->valuators_len * 4;
1562
1563     len = count_bits(out->valuators.mask, out->valuators.mask_len);
1564     out->valuators.values = next_block(&ptr_lib, len * sizeof(double));
1565
1566     values = (FP3232*)ptr;
1567     for (i = 0; i < len; i++, values++)
1568     {
1569         out->valuators.values[i] = values->integral;
1570         out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1571     }
1572
1573
1574     return 1;
1575 }
1576
1577 _X_HIDDEN int
1578 size_classes(xXIAnyInfo* from, int nclasses)
1579 {
1580     int len, i;
1581     xXIAnyInfo *any_wire;
1582     char *ptr_wire;
1583
1584     /* len for to->classes */
1585     len = pad_to_double(nclasses * sizeof(XIAnyClassInfo*));
1586     ptr_wire = (char*)from;
1587     for (i = 0; i < nclasses; i++)
1588     {
1589         int l = 0;
1590         any_wire = (xXIAnyInfo*)ptr_wire;
1591         switch(any_wire->type)
1592         {
1593             case XIButtonClass:
1594                 l = sizeDeviceClassType(XIButtonClass,
1595                         ((xXIButtonInfo*)any_wire)->num_buttons);
1596                 break;
1597             case XIKeyClass:
1598                 l = sizeDeviceClassType(XIKeyClass,
1599                         ((xXIKeyInfo*)any_wire)->num_keycodes);
1600                 break;
1601             case XIValuatorClass:
1602                 l = sizeDeviceClassType(XIValuatorClass, 0);
1603                 break;
1604             case XIScrollClass:
1605                 l = sizeDeviceClassType(XIScrollClass, 0);
1606                 break;
1607             case XITouchClass:
1608                 l = sizeDeviceClassType(XITouchClass, 0);
1609                 break;
1610         }
1611
1612         len += l;
1613         ptr_wire += any_wire->length * 4;
1614     }
1615
1616     return len;
1617 }
1618
1619 /* Copy classes from any into to->classes and return the number of bytes
1620  * copied. Memory layout of to->classes is
1621  * [clsptr][clsptr][clsptr][classinfo][classinfo]...
1622  *    |________|___________^
1623  *             |______________________^
1624  */
1625 _X_HIDDEN int
1626 copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
1627 {
1628     XIAnyClassInfo *any_lib;
1629     xXIAnyInfo *any_wire;
1630     void *ptr_lib;
1631     char *ptr_wire;
1632     int i, len;
1633     int cls_idx = 0;
1634
1635     if (!to->classes)
1636         return -1;
1637
1638     ptr_wire = (char*)from;
1639     ptr_lib = to->classes;
1640     to->classes = next_block(&ptr_lib,
1641                              pad_to_double((*nclasses) * sizeof(XIAnyClassInfo*)));
1642     memset(to->classes, 0, (*nclasses) * sizeof(XIAnyClassInfo*));
1643     len = 0; /* count wire length */
1644
1645     for (i = 0; i < *nclasses; i++)
1646     {
1647         any_lib = (XIAnyClassInfo*)ptr_lib;
1648         any_wire = (xXIAnyInfo*)ptr_wire;
1649
1650         switch(any_wire->type)
1651         {
1652             case XIButtonClass:
1653                 {
1654                     XIButtonClassInfo *cls_lib;
1655                     xXIButtonInfo *cls_wire;
1656                     uint32_t *atoms;
1657                     int j;
1658                     int struct_size;
1659                     int state_size;
1660                     int labels_size;
1661                     int wire_mask_size;
1662
1663                     cls_wire = (xXIButtonInfo*)any_wire;
1664                     sizeXIButtonClassType(cls_wire->num_buttons,
1665                                           &struct_size, &state_size,
1666                                           &labels_size);
1667                     cls_lib = next_block(&ptr_lib, struct_size);
1668                     wire_mask_size = ((cls_wire->num_buttons + 7)/8 + 3)/4 * 4;
1669
1670                     cls_lib->type = cls_wire->type;
1671                     cls_lib->sourceid = cls_wire->sourceid;
1672                     cls_lib->num_buttons = cls_wire->num_buttons;
1673                     cls_lib->state.mask_len = state_size;
1674                     cls_lib->state.mask = next_block(&ptr_lib, state_size);
1675                     memcpy(cls_lib->state.mask, &cls_wire[1],
1676                            wire_mask_size);
1677                     if (state_size != wire_mask_size)
1678                         memset(&cls_lib->state.mask[wire_mask_size], 0,
1679                                state_size - wire_mask_size);
1680
1681                     cls_lib->labels = next_block(&ptr_lib, labels_size);
1682
1683                     atoms =(uint32_t*)((char*)&cls_wire[1] + wire_mask_size);
1684                     for (j = 0; j < cls_lib->num_buttons; j++)
1685                         cls_lib->labels[j] = *atoms++;
1686
1687                     to->classes[cls_idx++] = any_lib;
1688                     break;
1689                 }
1690             case XIKeyClass:
1691                 {
1692                     XIKeyClassInfo *cls_lib;
1693                     xXIKeyInfo *cls_wire;
1694                     int struct_size;
1695                     int keycodes_size;
1696
1697                     cls_wire = (xXIKeyInfo*)any_wire;
1698                     sizeXIKeyClassType(cls_wire->num_keycodes,
1699                                        &struct_size, &keycodes_size);
1700                     cls_lib = next_block(&ptr_lib, struct_size);
1701
1702                     cls_lib->type = cls_wire->type;
1703                     cls_lib->sourceid = cls_wire->sourceid;
1704                     cls_lib->num_keycodes = cls_wire->num_keycodes;
1705                     cls_lib->keycodes = next_block(&ptr_lib, keycodes_size);
1706                     memcpy(cls_lib->keycodes, &cls_wire[1],
1707                             cls_lib->num_keycodes);
1708
1709                     to->classes[cls_idx++] = any_lib;
1710                     break;
1711                 }
1712             case XIValuatorClass:
1713                 {
1714                     XIValuatorClassInfo *cls_lib;
1715                     xXIValuatorInfo *cls_wire;
1716
1717                     cls_lib =
1718                       next_block(&ptr_lib,
1719                                  sizeDeviceClassType(XIValuatorClass, 0));
1720                     cls_wire = (xXIValuatorInfo*)any_wire;
1721
1722                     cls_lib->type = cls_wire->type;
1723                     cls_lib->sourceid = cls_wire->sourceid;
1724                     cls_lib->number = cls_wire->number;
1725                     cls_lib->label  = cls_wire->label;
1726                     cls_lib->resolution = cls_wire->resolution;
1727                     cls_lib->min        = cls_wire->min.integral;
1728                     cls_lib->max        = cls_wire->max.integral;
1729                     cls_lib->value      = cls_wire->value.integral;
1730                     /* FIXME: fractional parts */
1731                     cls_lib->mode       = cls_wire->mode;
1732
1733                     to->classes[cls_idx++] = any_lib;
1734                 }
1735                 break;
1736             case XIScrollClass:
1737                 {
1738                     XIScrollClassInfo *cls_lib;
1739                     xXIScrollInfo *cls_wire;
1740
1741                     cls_lib =
1742                       next_block(&ptr_lib,
1743                                  sizeDeviceClassType(XIScrollClass, 0));
1744                     cls_wire = (xXIScrollInfo*)any_wire;
1745
1746                     cls_lib->type = cls_wire->type;
1747                     cls_lib->sourceid = cls_wire->sourceid;
1748                     cls_lib->number     = cls_wire->number;
1749                     cls_lib->scroll_type= cls_wire->scroll_type;
1750                     cls_lib->flags      = cls_wire->flags;
1751                     cls_lib->increment  = cls_wire->increment.integral;
1752                     cls_lib->increment += (unsigned int)cls_wire->increment.frac/(double)(1ULL << 32);
1753
1754                     to->classes[cls_idx++] = any_lib;
1755                 }
1756                 break;
1757             case XITouchClass:
1758                 {
1759                     XITouchClassInfo *cls_lib;
1760                     xXITouchInfo *cls_wire;
1761
1762                     cls_wire = (xXITouchInfo*)any_wire;
1763                     cls_lib = next_block(&ptr_lib, sizeof(XITouchClassInfo));
1764
1765                     cls_lib->type = cls_wire->type;
1766                     cls_lib->sourceid = cls_wire->sourceid;
1767                     cls_lib->mode = cls_wire->mode;
1768                     cls_lib->num_touches = cls_wire->num_touches;
1769
1770                     to->classes[cls_idx++] = any_lib;
1771                 }
1772                 break;
1773         }
1774         len += any_wire->length * 4;
1775         ptr_wire += any_wire->length * 4;
1776     }
1777
1778     /* we may have skipped unknown classes, reset nclasses */
1779     *nclasses = cls_idx;
1780     return len;
1781 }
1782
1783
1784 static int
1785 wireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie)
1786 {
1787     XIDeviceChangedEvent *out;
1788     XIDeviceInfo info;
1789     int len;
1790     int nclasses = in->num_classes;
1791
1792     len = size_classes((xXIAnyInfo*)&in[1], in->num_classes);
1793
1794     cookie->data = out = malloc(sizeof(XIDeviceChangedEvent) + len);
1795
1796     out->type = in->type;
1797     out->serial = in->sequenceNumber;
1798     out->display = cookie->display;
1799     out->extension = in->extension;
1800     out->evtype = in->evtype;
1801     out->send_event = ((in->type & 0x80) != 0);
1802     out->time = in->time;
1803     out->deviceid = in->deviceid;
1804     out->sourceid = in->sourceid;
1805     out->reason = in->reason;
1806
1807     out->classes = (XIAnyClassInfo**)&out[1];
1808
1809     info.classes = out->classes;
1810
1811     copy_classes(&info, (xXIAnyInfo*)&in[1], &nclasses);
1812     out->num_classes = nclasses;
1813
1814     return 1;
1815 }
1816
1817 static int
1818 wireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie)
1819 {
1820     int i;
1821     XIHierarchyInfo *info_out;
1822     xXIHierarchyInfo *info_in;
1823     XIHierarchyEvent *out;
1824
1825     cookie->data = out = malloc(sizeof(XIHierarchyEvent) + in->num_info * sizeof(XIHierarchyInfo));;
1826
1827     out->info           = (XIHierarchyInfo*)&out[1];
1828     out->display        = cookie->display;
1829     out->type           = in->type;
1830     out->serial         = in->sequenceNumber;
1831     out->extension      = in->extension;
1832     out->evtype         = in->evtype;
1833     out->send_event = ((in->type & 0x80) != 0);
1834     out->time           = in->time;
1835     out->flags          = in->flags;
1836     out->num_info       = in->num_info;
1837
1838     info_out            = out->info;
1839     info_in             = (xXIHierarchyInfo*)&in[1];
1840
1841     for (i = 0; i < out->num_info; i++, info_out++, info_in++)
1842     {
1843         info_out->deviceid      = info_in->deviceid;
1844         info_out->attachment    = info_in->attachment;
1845         info_out->use           = info_in->use;
1846         info_out->enabled       = info_in->enabled;
1847         info_out->flags         = info_in->flags;
1848     }
1849
1850     return 1;
1851 }
1852
1853 static int
1854 wireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *cookie)
1855 {
1856     int len, i, bits;
1857     FP3232 *values;
1858     XIRawEvent *out;
1859     void *ptr;
1860
1861     len = sizeof(XIRawEvent) + in->valuators_len * 4;
1862     bits = count_bits((unsigned char*)&in[1], in->valuators_len * 4);
1863     len += bits * sizeof(double) * 2; /* raw + normal */
1864
1865     cookie->data = ptr = calloc(1, len);
1866     if (!ptr)
1867         return 0;
1868
1869     out = next_block(&ptr, sizeof(XIRawEvent));
1870     out->type           = in->type;
1871     out->serial         = in->sequenceNumber;
1872     out->display        = cookie->display;
1873     out->extension      = in->extension;
1874     out->evtype         = in->evtype;
1875     out->send_event = ((in->type & 0x80) != 0);
1876     out->time           = in->time;
1877     out->detail         = in->detail;
1878     out->deviceid       = in->deviceid;
1879     out->flags          = in->flags;
1880
1881     /* https://bugs.freedesktop.org/show_bug.cgi?id=34240 */
1882     if (_XiCheckVersion(info, XInput_2_2) >= 0)
1883         out->sourceid       = in->sourceid;
1884     else
1885         out->sourceid       = 0;
1886
1887     out->valuators.mask_len = in->valuators_len * 4;
1888     out->valuators.mask = next_block(&ptr, out->valuators.mask_len);
1889     memcpy(out->valuators.mask, &in[1], out->valuators.mask_len);
1890
1891     out->valuators.values = next_block(&ptr, bits * sizeof(double));
1892     out->raw_values = next_block(&ptr, bits * sizeof(double));
1893
1894     values = (FP3232*)(((char*)&in[1]) + in->valuators_len * 4);
1895     for (i = 0; i < bits; i++)
1896     {
1897         out->valuators.values[i] = values->integral;
1898         out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1899         out->raw_values[i] = (values + bits)->integral;
1900         out->raw_values[i] += ((double)(values + bits)->frac / (1 << 16) / (1 << 16));
1901         values++;
1902     }
1903
1904     return 1;
1905 }
1906
1907 /* Memory layout of XIEnterEvents:
1908    [event][modifiers][group][button]
1909  */
1910 static int
1911 wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie)
1912 {
1913     int len;
1914     XIEnterEvent *out;
1915
1916     len = sizeof(XIEnterEvent) + in->buttons_len * 4;
1917
1918     cookie->data = out = malloc(len);
1919     out->buttons.mask = (unsigned char*)&out[1];
1920
1921     out->type           = in->type;
1922     out->serial         = in->sequenceNumber;
1923     out->display        = cookie->display;
1924     out->extension      = in->extension;
1925     out->evtype         = in->evtype;
1926     out->send_event = ((in->type & 0x80) != 0);
1927     out->time           = in->time;
1928     out->detail         = in->detail;
1929     out->deviceid       = in->deviceid;
1930     out->root           = in->root;
1931     out->event          = in->event;
1932     out->child          = in->child;
1933     out->sourceid       = in->sourceid;
1934     out->root_x         = FP1616toDBL(in->root_x);
1935     out->root_y         = FP1616toDBL(in->root_y);
1936     out->event_x        = FP1616toDBL(in->event_x);
1937     out->event_y        = FP1616toDBL(in->event_y);
1938     out->mode           = in->mode;
1939     out->focus          = in->focus;
1940     out->same_screen    = in->same_screen;
1941
1942     out->mods.base = in->mods.base_mods;
1943     out->mods.locked = in->mods.locked_mods;
1944     out->mods.latched = in->mods.latched_mods;
1945     out->mods.effective = in->mods.effective_mods;
1946     out->group.base = in->group.base_group;
1947     out->group.locked = in->group.locked_group;
1948     out->group.latched = in->group.latched_group;
1949     out->group.effective = in->group.effective_group;
1950
1951     out->buttons.mask_len = in->buttons_len * 4;
1952     memcpy(out->buttons.mask, &in[1], out->buttons.mask_len);
1953
1954     return 1;
1955 }
1956
1957 static int
1958 wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie)
1959 {
1960     XIPropertyEvent *out = malloc(sizeof(XIPropertyEvent));
1961
1962     cookie->data = out;
1963
1964     out->type           = in->type;
1965     out->serial         = in->sequenceNumber;
1966     out->extension      = in->extension;
1967     out->evtype         = in->evtype;
1968     out->send_event = ((in->type & 0x80) != 0);
1969     out->time           = in->time;
1970     out->property       = in->property;
1971     out->what           = in->what;
1972     out->deviceid       = in->deviceid;
1973
1974     return 1;
1975 }
1976
1977 static int
1978 wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
1979                           XGenericEventCookie *cookie)
1980 {
1981     XITouchOwnershipEvent *out = malloc(sizeof(XITouchOwnershipEvent));
1982
1983     cookie->data = out;
1984
1985     out->type           = in->type;
1986     out->serial         = in->sequenceNumber;
1987     out->display        = cookie->display;
1988     out->extension      = in->extension;
1989     out->evtype         = in->evtype;
1990     out->send_event     = ((in->type & 0x80) != 0);
1991     out->time           = in->time;
1992     out->deviceid       = in->deviceid;
1993     out->sourceid       = in->sourceid;
1994     out->touchid        = in->touchid;
1995     out->root           = in->root;
1996     out->event          = in->event;
1997     out->child          = in->child;
1998     out->flags          = in->flags;
1999
2000     return 1;
2001 }
2002
2003 #define FP3232_TO_DOUBLE(x) ((double) (x).integral + (x).frac / (1ULL << 32))
2004
2005 static int
2006 wireToBarrierEvent(xXIBarrierEvent *in, XGenericEventCookie *cookie)
2007 {
2008     XIBarrierEvent *out = malloc(sizeof(XIBarrierEvent));
2009
2010     cookie->data = out;
2011
2012     out->display    = cookie->display;
2013     out->type       = in->type;
2014     out->serial     = in->sequenceNumber;
2015     out->extension  = in->extension;
2016     out->evtype     = in->evtype;
2017     out->send_event = ((in->type & 0x80) != 0);
2018     out->time       = in->time;
2019     out->deviceid   = in->deviceid;
2020     out->sourceid   = in->sourceid;
2021     out->event      = in->event;
2022     out->root       = in->root;
2023     out->root_x     = FP1616toDBL(in->root_x);
2024     out->root_y     = FP1616toDBL(in->root_y);
2025     out->dx         = FP3232_TO_DOUBLE (in->dx);
2026     out->dy         = FP3232_TO_DOUBLE (in->dy);
2027     out->dtime      = in->dtime;
2028     out->flags      = in->flags;
2029     out->barrier    = in->barrier;
2030     out->eventid    = in->eventid;
2031
2032     return 1;
2033 }