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