XExtInt.c revision 89069ce9
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->display = cookie->display;
1351    out->type = in->type;
1352    out->extension = in->extension;
1353    out->evtype = in->evtype;
1354    out->send_event = ((in->type & 0x80) != 0);
1355    out->time = in->time;
1356    out->deviceid = in->deviceid;
1357    out->sourceid = in->sourceid;
1358    out->detail = in->detail;
1359    out->root = in->root;
1360    out->event = in->event;
1361    out->child = in->child;
1362    out->root_x = FP1616toDBL(in->root_x);
1363    out->root_y = FP1616toDBL(in->root_y);
1364    out->event_x = FP1616toDBL(in->event_x);
1365    out->event_y = FP1616toDBL(in->event_y);
1366    out->flags = in->flags;
1367    out->mods.base = in->mods.base_mods;
1368    out->mods.locked = in->mods.locked_mods;
1369    out->mods.latched = in->mods.latched_mods;
1370    out->mods.effective = in->mods.effective_mods;
1371    out->group.base = in->group.base_group;
1372    out->group.locked = in->group.locked_group;
1373    out->group.latched = in->group.latched_group;
1374    out->group.effective = in->group.effective_group;
1375    out->buttons.mask_len = in->buttons_len * 4;
1376    out->valuators.mask_len = in->valuators_len * 4;
1377
1378    out->buttons.mask = next_block(&ptr_lib, out->buttons.mask_len);
1379
1380    /* buttons */
1381    ptr = (unsigned char*)&in[1];
1382    memcpy(out->buttons.mask, ptr, out->buttons.mask_len);
1383    ptr += in->buttons_len * 4;
1384
1385    /* valuators */
1386    out->valuators.mask = next_block(&ptr_lib, out->valuators.mask_len);
1387    memcpy(out->valuators.mask, ptr, out->valuators.mask_len);
1388    ptr += in->valuators_len * 4;
1389
1390    len = count_bits(out->valuators.mask, out->valuators.mask_len);
1391    out->valuators.values = next_block(&ptr_lib, len * sizeof(double));
1392
1393    values = (FP3232*)ptr;
1394    for (i = 0; i < len; i++, values++)
1395    {
1396        out->valuators.values[i] = values->integral;
1397        out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1398    }
1399
1400
1401    return 1;
1402}
1403
1404_X_HIDDEN int
1405size_classes(xXIAnyInfo* from, int nclasses)
1406{
1407    int len, i;
1408    xXIAnyInfo *any_wire;
1409    char *ptr_wire;
1410
1411    len = nclasses * sizeof(XIAnyClassInfo*); /* len for to->classes */
1412    ptr_wire = (char*)from;
1413    for (i = 0; i < nclasses; i++)
1414    {
1415        int l = 0;
1416        any_wire = (xXIAnyInfo*)ptr_wire;
1417        switch(any_wire->type)
1418        {
1419            case XIButtonClass:
1420                l = sizeDeviceClassType(XIButtonClass,
1421                        ((xXIButtonInfo*)any_wire)->num_buttons);
1422                break;
1423            case XIKeyClass:
1424                l = sizeDeviceClassType(XIKeyClass,
1425                        ((xXIKeyInfo*)any_wire)->num_keycodes);
1426                break;
1427            case XIValuatorClass:
1428                l = sizeDeviceClassType(XIValuatorClass, 0);
1429                break;
1430        }
1431
1432        len += l;
1433        ptr_wire += any_wire->length * 4;
1434    }
1435
1436    return len;
1437}
1438
1439/* Copy classes from any into to->classes and return the number of bytes
1440 * copied. Memory layout of to->classes is
1441 * [clsptr][clsptr][clsptr][classinfo][classinfo]...
1442 *    |________|___________^
1443 *             |______________________^
1444 */
1445_X_HIDDEN int
1446copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int nclasses)
1447{
1448    XIAnyClassInfo *any_lib;
1449    xXIAnyInfo *any_wire;
1450    void *ptr_lib;
1451    char *ptr_wire;
1452    int i, len;
1453
1454    if (!to->classes)
1455        return -1;
1456
1457    ptr_wire = (char*)from;
1458    ptr_lib = to->classes;
1459    to->classes = next_block(&ptr_lib, nclasses * sizeof(XIAnyClassInfo*));
1460    len = 0; /* count wire length */
1461
1462    for (i = 0; i < nclasses; i++)
1463    {
1464        any_lib = (XIAnyClassInfo*)ptr_lib;
1465        any_wire = (xXIAnyInfo*)ptr_wire;
1466
1467        to->classes[i] = any_lib;
1468        any_lib->type = any_wire->type;
1469        any_lib->sourceid = any_wire->sourceid;
1470        switch(any_wire->type)
1471        {
1472            case XIButtonClass:
1473                {
1474                    XIButtonClassInfo *cls_lib;
1475                    xXIButtonInfo *cls_wire;
1476                    uint32_t *atoms;
1477                    int j;
1478
1479                    cls_lib = next_block(&ptr_lib, sizeof(XIButtonClassInfo));
1480                    cls_wire = (xXIButtonInfo*)any_wire;
1481
1482                    cls_lib->num_buttons = cls_wire->num_buttons;
1483                    cls_lib->state.mask_len = ((((cls_wire->num_buttons + 7)/8) + 3)/4) * 4;
1484                    cls_lib->state.mask = next_block(&ptr_lib, cls_lib->state.mask_len);
1485                    memcpy(cls_lib->state.mask, &cls_wire[1],
1486                           cls_lib->state.mask_len);
1487
1488                    cls_lib->labels = next_block(&ptr_lib, cls_lib->num_buttons * sizeof(Atom));
1489                    atoms =(uint32_t*)((char*)&cls_wire[1] + cls_lib->state.mask_len);
1490                    for (j = 0; j < cls_lib->num_buttons; j++)
1491                        cls_lib->labels[j] = *atoms++;
1492
1493                    break;
1494                }
1495            case XIKeyClass:
1496                {
1497                    XIKeyClassInfo *cls_lib;
1498                    xXIKeyInfo *cls_wire;
1499
1500                    cls_lib = next_block(&ptr_lib, sizeof(XIKeyClassInfo));
1501                    cls_wire = (xXIKeyInfo*)any_wire;
1502
1503                    cls_lib->num_keycodes = cls_wire->num_keycodes;
1504                    cls_lib->keycodes = next_block(&ptr_lib,
1505                            cls_lib->num_keycodes * sizeof(int));
1506                    memcpy(cls_lib->keycodes, &cls_wire[1],
1507                            cls_lib->num_keycodes);
1508
1509                    break;
1510                }
1511            case XIValuatorClass:
1512                {
1513                    XIValuatorClassInfo *cls_lib;
1514                    xXIValuatorInfo *cls_wire;
1515
1516                    cls_lib = next_block(&ptr_lib, sizeof(XIValuatorClassInfo));
1517                    cls_wire = (xXIValuatorInfo*)any_wire;
1518
1519                    cls_lib->number = cls_wire->number;
1520                    cls_lib->label  = cls_wire->label;
1521                    cls_lib->resolution = cls_wire->resolution;
1522                    cls_lib->min        = cls_wire->min.integral;
1523                    cls_lib->max        = cls_wire->max.integral;
1524                    cls_lib->value      = cls_wire->value.integral;
1525                    /* FIXME: fractional parts */
1526                    cls_lib->mode       = cls_wire->mode;
1527
1528                }
1529                break;
1530        }
1531        len += any_wire->length * 4;
1532        ptr_wire += any_wire->length * 4;
1533    }
1534    return len;
1535}
1536
1537
1538static int
1539wireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie)
1540{
1541    XIDeviceChangedEvent *out;
1542    XIDeviceInfo info;
1543    int len;
1544
1545    len = size_classes((xXIAnyInfo*)&in[1], in->num_classes);
1546
1547    cookie->data = out = malloc(sizeof(XIDeviceChangedEvent) + len);
1548
1549    out->type = in->type;
1550    out->display = cookie->display;
1551    out->extension = in->extension;
1552    out->evtype = in->evtype;
1553    out->send_event = ((in->type & 0x80) != 0);
1554    out->time = in->time;
1555    out->deviceid = in->deviceid;
1556    out->sourceid = in->sourceid;
1557    out->reason = in->reason;
1558    out->num_classes = in->num_classes;
1559
1560    out->classes = (XIAnyClassInfo**)&out[1];
1561
1562    info.classes = out->classes;
1563
1564    copy_classes(&info, (xXIAnyInfo*)&in[1], in->num_classes);
1565
1566    return 1;
1567}
1568
1569static int
1570wireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie)
1571{
1572    int i;
1573    XIHierarchyInfo *info_out;
1574    xXIHierarchyInfo *info_in;
1575    XIHierarchyEvent *out;
1576
1577    cookie->data = out = malloc(sizeof(XIHierarchyEvent) + in->num_info * sizeof(XIHierarchyInfo));;
1578
1579    out->info           = (XIHierarchyInfo*)&out[1];
1580    out->display        = cookie->display;
1581    out->type           = in->type;
1582    out->extension      = in->extension;
1583    out->evtype         = in->evtype;
1584    out->send_event = ((in->type & 0x80) != 0);
1585    out->time           = in->time;
1586    out->flags          = in->flags;
1587    out->num_info       = in->num_info;
1588
1589    info_out            = out->info;
1590    info_in             = (xXIHierarchyInfo*)&in[1];
1591
1592    for (i = 0; i < out->num_info; i++, info_out++, info_in++)
1593    {
1594        info_out->deviceid      = info_in->deviceid;
1595        info_out->attachment    = info_in->attachment;
1596        info_out->use           = info_in->use;
1597        info_out->enabled       = info_in->enabled;
1598        info_out->flags         = info_in->flags;
1599    }
1600
1601    return 1;
1602}
1603
1604static int
1605wireToRawEvent(xXIRawEvent *in, XGenericEventCookie *cookie)
1606{
1607    int len, i, bits;
1608    FP3232 *values;
1609    XIRawEvent *out;
1610    void *ptr;
1611
1612
1613    len = sizeof(XIRawEvent) + in->valuators_len * 4;
1614    bits = count_bits((unsigned char*)&in[1], in->valuators_len * 4);
1615    len += bits * sizeof(double) * 2; /* raw + normal */
1616
1617    cookie->data = ptr = calloc(1, len);
1618    if (!ptr)
1619        return 0;
1620
1621    out = next_block(&ptr, sizeof(XIRawEvent));
1622    out->type           = in->type;
1623    out->display        = cookie->display;
1624    out->extension      = in->extension;
1625    out->evtype         = in->evtype;
1626    out->send_event = ((in->type & 0x80) != 0);
1627    out->time           = in->time;
1628    out->detail         = in->detail;
1629    out->deviceid       = in->deviceid;
1630    out->flags          = in->flags;
1631
1632    out->valuators.mask_len = in->valuators_len * 4;
1633    out->valuators.mask = next_block(&ptr, out->valuators.mask_len);
1634    memcpy(out->valuators.mask, &in[1], out->valuators.mask_len);
1635
1636    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1637    out->raw_values = next_block(&ptr, bits * sizeof(double));
1638
1639    values = (FP3232*)(((char*)&in[1]) + in->valuators_len * 4);
1640    for (i = 0; i < bits; i++)
1641    {
1642        out->valuators.values[i] = values->integral;
1643        out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1644        out->raw_values[i] = (values + bits)->integral;
1645        out->raw_values[i] += ((double)(values + bits)->frac / (1 << 16) / (1 << 16));
1646        values++;
1647    }
1648
1649    return 1;
1650}
1651
1652/* Memory layout of XIEnterEvents:
1653   [event][modifiers][group][button]
1654 */
1655static int
1656wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie)
1657{
1658    int len;
1659    XIEnterEvent *out;
1660
1661    len = sizeof(XIEnterEvent) + in->buttons_len * 4;
1662
1663    cookie->data = out = malloc(len);
1664    out->buttons.mask = (unsigned char*)&out[1];
1665
1666    out->type           = in->type;
1667    out->display        = cookie->display;
1668    out->extension      = in->extension;
1669    out->evtype         = in->evtype;
1670    out->send_event = ((in->type & 0x80) != 0);
1671    out->time           = in->time;
1672    out->detail         = in->detail;
1673    out->deviceid       = in->deviceid;
1674    out->root           = in->root;
1675    out->event          = in->event;
1676    out->child          = in->child;
1677    out->sourceid       = in->sourceid;
1678    out->root_x         = FP1616toDBL(in->root_x);
1679    out->root_y         = FP1616toDBL(in->root_y);
1680    out->event_x        = FP1616toDBL(in->event_x);
1681    out->event_y        = FP1616toDBL(in->event_y);
1682    out->mode           = in->mode;
1683    out->focus          = in->focus;
1684    out->same_screen    = in->same_screen;
1685
1686    out->mods.base = in->mods.base_mods;
1687    out->mods.locked = in->mods.locked_mods;
1688    out->mods.latched = in->mods.latched_mods;
1689    out->mods.effective = in->mods.effective_mods;
1690    out->group.base = in->group.base_group;
1691    out->group.locked = in->group.locked_group;
1692    out->group.latched = in->group.latched_group;
1693    out->group.effective = in->group.effective_group;
1694
1695    out->buttons.mask_len = in->buttons_len * 4;
1696    memcpy(out->buttons.mask, &in[1], out->buttons.mask_len);
1697
1698    return 1;
1699}
1700
1701static int
1702wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie)
1703{
1704    XIPropertyEvent *out = malloc(sizeof(XIPropertyEvent));
1705
1706    cookie->data = out;
1707
1708    out->type           = in->type;
1709    out->extension      = in->extension;
1710    out->evtype         = in->evtype;
1711    out->send_event = ((in->type & 0x80) != 0);
1712    out->time           = in->time;
1713    out->property       = in->property;
1714    out->what           = in->what;
1715    out->deviceid       = in->deviceid;
1716
1717    return 1;
1718}
1719