XExtInt.c revision b789ec8a
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            /* Force mask alignment with longs to avoid
1032             * unaligned access when accessing the atoms. */
1033            l += ((((num_elements + 7)/8) + 3)/4) * sizeof(Atom);
1034            break;
1035        case XIKeyClass:
1036            l = sizeof(XIKeyClassInfo);
1037            l += num_elements * sizeof(int);
1038            break;
1039        case XIValuatorClass:
1040            l = sizeof(XIValuatorClassInfo);
1041            break;
1042        default:
1043            printf("sizeDeviceClassType: unknown type %d\n", type);
1044            break;
1045    }
1046    return l;
1047}
1048
1049static Bool
1050copyHierarchyEvent(XGenericEventCookie *cookie_in,
1051                   XGenericEventCookie *cookie_out)
1052{
1053    XIHierarchyEvent *in, *out;
1054    void *ptr;
1055
1056    in = cookie_in->data;
1057
1058    ptr = cookie_out->data = malloc(sizeof(XIHierarchyEvent) +
1059                                    in->num_info * sizeof(XIHierarchyInfo));
1060    if (!ptr)
1061        return False;
1062
1063    out = next_block(&ptr, sizeof(XIHierarchyEvent));
1064    *out = *in;
1065    out->info = next_block(&ptr, in->num_info * sizeof(XIHierarchyInfo));
1066    memcpy(out->info, in->info, in->num_info * sizeof(XIHierarchyInfo));
1067
1068    return True;
1069}
1070
1071static Bool
1072copyDeviceChangedEvent(XGenericEventCookie *in_cookie,
1073                       XGenericEventCookie *out_cookie)
1074{
1075    int len, i;
1076    XIDeviceChangedEvent *in, *out;
1077    XIAnyClassInfo *any;
1078    void *ptr;
1079
1080    in = in_cookie->data;
1081
1082    len = sizeof(XIDeviceChangedEvent);
1083    len += in->num_classes * sizeof(XIAnyClassInfo*);
1084
1085    for (i = 0; i < in->num_classes; i++)
1086    {
1087        any = in->classes[i];
1088        switch(any->type)
1089        {
1090            case XIButtonClass:
1091                len += sizeDeviceClassType(XIButtonClass,
1092                        ((XIButtonClassInfo*)any)->num_buttons);
1093                break;
1094            case XIKeyClass:
1095                len += sizeDeviceClassType(XIKeyClass,
1096                        ((XIKeyClassInfo*)any)->num_keycodes);
1097                break;
1098            case XIValuatorClass:
1099                len += sizeDeviceClassType(XIValuatorClass, 0);
1100                break;
1101            default:
1102                printf("copyDeviceChangedEvent: unknown type %d\n",
1103                        any->type);
1104                break;
1105        }
1106
1107    }
1108
1109    ptr = out_cookie->data = malloc(len);
1110    if (!ptr)
1111        return False;
1112    out = next_block(&ptr, sizeof(XIDeviceChangedEvent));
1113    *out = *in;
1114
1115    out->classes = next_block(&ptr,
1116                              out->num_classes * sizeof(XIAnyClassInfo*));
1117
1118    for (i = 0; i < in->num_classes; i++)
1119    {
1120        any = in->classes[i];
1121
1122        switch(any->type)
1123        {
1124            case XIButtonClass:
1125                {
1126                    int size;
1127                    XIButtonClassInfo *bin, *bout;
1128                    bin = (XIButtonClassInfo*)any;
1129                    bout = next_block(&ptr, sizeof(XIButtonClass));
1130
1131                    *bout = *bin;
1132                    /* Force mask alignment with longs to avoid unaligned
1133                     * access when accessing the atoms. */
1134                    size = bout->state.mask_len/4 * sizeof(Atom);
1135                    bout->state.mask = next_block(&ptr, size);
1136                    memcpy(bout->state.mask, bin->state.mask,
1137                            bout->state.mask_len);
1138
1139                    bout->labels = next_block(&ptr, bout->num_buttons * sizeof(Atom));
1140                    memcpy(bout->labels, bin->labels, bout->num_buttons * sizeof(Atom));
1141                    out->classes[i] = (XIAnyClassInfo*)bout;
1142                    break;
1143                }
1144            case XIKeyClass:
1145                {
1146                    XIKeyClassInfo *kin, *kout;
1147                    kin = (XIKeyClassInfo*)any;
1148
1149                    kout = next_block(&ptr, sizeof(XIKeyClass));
1150                    *kout = *kin;
1151                    kout->keycodes = next_block(&ptr, kout->num_keycodes * sizeof(int));
1152                    memcpy(kout->keycodes, kin->keycodes, kout->num_keycodes * sizeof(int));
1153                    out->classes[i] = (XIAnyClassInfo*)kout;
1154                    break;
1155                }
1156            case XIValuatorClass:
1157                {
1158                    XIValuatorClassInfo *vin, *vout;
1159                    vin = (XIValuatorClassInfo*)any;
1160                    vout = next_block(&ptr, sizeof(XIValuatorClass));
1161                    *vout = *vin;
1162                    out->classes[i] = (XIAnyClassInfo*)vout;
1163                    break;
1164                }
1165        }
1166    }
1167
1168    return True;
1169}
1170
1171static Bool
1172copyDeviceEvent(XGenericEventCookie *cookie_in,
1173                XGenericEventCookie *cookie_out)
1174{
1175    int len;
1176    XIDeviceEvent *in, *out;
1177    int bits; /* valuator bits */
1178    void *ptr;
1179
1180    in = cookie_in->data;
1181    bits = count_bits(in->valuators.mask, in->valuators.mask_len);
1182
1183    len = sizeDeviceEvent(in->buttons.mask_len, in->valuators.mask_len,
1184                          in->valuators.mask);
1185
1186    ptr = cookie_out->data = malloc(len);
1187    if (!ptr)
1188        return False;
1189
1190    out = next_block(&ptr, sizeof(XIDeviceEvent));
1191    *out = *in;
1192
1193    out->buttons.mask = next_block(&ptr, in->buttons.mask_len);
1194    memcpy(out->buttons.mask, in->buttons.mask,
1195           out->buttons.mask_len);
1196    out->valuators.mask = next_block(&ptr, in->valuators.mask_len);
1197    memcpy(out->valuators.mask, in->valuators.mask,
1198           out->valuators.mask_len);
1199    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1200    memcpy(out->valuators.values, in->valuators.values,
1201           bits * sizeof(double));
1202
1203    return True;
1204}
1205
1206static Bool
1207copyEnterEvent(XGenericEventCookie *cookie_in,
1208               XGenericEventCookie *cookie_out)
1209{
1210    int len;
1211    XIEnterEvent *in, *out;
1212    void *ptr;
1213
1214    in = cookie_in->data;
1215
1216    len = sizeof(XIEnterEvent) + in->buttons.mask_len;
1217
1218    ptr = cookie_out->data = malloc(len);
1219    if (!ptr)
1220        return False;
1221
1222    out = next_block(&ptr, sizeof(XIEnterEvent));
1223    *out = *in;
1224
1225    out->buttons.mask = next_block(&ptr, in->buttons.mask_len);
1226    memcpy(out->buttons.mask, in->buttons.mask, out->buttons.mask_len);
1227
1228    return True;
1229}
1230
1231static Bool
1232copyPropertyEvent(XGenericEventCookie *cookie_in,
1233                  XGenericEventCookie *cookie_out)
1234{
1235    XIPropertyEvent *in, *out;
1236
1237    in = cookie_in->data;
1238
1239    out = cookie_out->data = malloc(sizeof(XIPropertyEvent));
1240    if (!out)
1241        return False;
1242
1243    *out = *in;
1244    return True;
1245}
1246
1247static Bool
1248copyRawEvent(XGenericEventCookie *cookie_in,
1249             XGenericEventCookie *cookie_out)
1250{
1251    XIRawEvent *in, *out;
1252    void *ptr;
1253    int len;
1254    int bits;
1255
1256    in = cookie_in->data;
1257
1258    bits = count_bits(in->valuators.mask, in->valuators.mask_len);
1259    len = sizeof(XIRawEvent) + in->valuators.mask_len;
1260    len += bits * sizeof(double) * 2;
1261
1262    ptr = cookie_out->data = malloc(len);
1263    if (!ptr)
1264        return False;
1265
1266    out = next_block(&ptr, sizeof(XIRawEvent));
1267    *out = *in;
1268    out->valuators.mask = next_block(&ptr, out->valuators.mask_len);
1269    memcpy(out->valuators.mask, in->valuators.mask, out->valuators.mask_len);
1270
1271    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1272    memcpy(out->valuators.values, in->valuators.values, bits * sizeof(double));
1273
1274    out->raw_values = next_block(&ptr, bits * sizeof(double));
1275    memcpy(out->raw_values, in->raw_values, bits * sizeof(double));
1276
1277    return True;
1278}
1279
1280
1281
1282static Bool
1283XInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
1284{
1285    int ret = True;
1286
1287    XExtDisplayInfo *info = XInput_find_display(dpy);
1288
1289    if (in->extension != info->codes->major_opcode)
1290    {
1291        printf("XInputCopyCookie: wrong extension opcode %d\n",
1292                in->extension);
1293        return False;
1294    }
1295
1296    *out = *in;
1297    out->data = NULL;
1298    out->cookie = 0;
1299
1300    switch(in->evtype) {
1301        case XI_Motion:
1302        case XI_ButtonPress:
1303        case XI_ButtonRelease:
1304        case XI_KeyPress:
1305        case XI_KeyRelease:
1306            ret = copyDeviceEvent(in, out);
1307            break;
1308        case XI_DeviceChanged:
1309            ret = copyDeviceChangedEvent(in, out);
1310            break;
1311        case XI_HierarchyChanged:
1312            ret = copyHierarchyEvent(in, out);
1313            break;
1314        case XI_Enter:
1315        case XI_Leave:
1316        case XI_FocusIn:
1317        case XI_FocusOut:
1318            ret = copyEnterEvent(in, out);
1319            break;
1320        case XI_PropertyEvent:
1321            ret = copyPropertyEvent(in, out);
1322            break;
1323        case XI_RawKeyPress:
1324        case XI_RawKeyRelease:
1325        case XI_RawButtonPress:
1326        case XI_RawButtonRelease:
1327        case XI_RawMotion:
1328            ret = copyRawEvent(in, out);
1329            break;
1330        default:
1331            printf("XInputCopyCookie: unknown evtype %d\n", in->evtype);
1332            ret = False;
1333    }
1334
1335    if (!ret)
1336        printf("XInputCopyCookie: Failed to copy evtype %d", in->evtype);
1337    return ret;
1338}
1339
1340static int
1341wireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* cookie)
1342{
1343    int len, i;
1344    unsigned char *ptr;
1345    void *ptr_lib;
1346    FP3232 *values;
1347    XIDeviceEvent *out;
1348
1349    ptr = (unsigned char*)&in[1] + in->buttons_len * 4;
1350
1351    len = sizeDeviceEvent(in->buttons_len * 4, in->valuators_len * 4, ptr);
1352
1353    cookie->data = ptr_lib = malloc(len);
1354
1355    out = next_block(&ptr_lib, sizeof(XIDeviceEvent));
1356    out->display = cookie->display;
1357    out->type = in->type;
1358    out->extension = in->extension;
1359    out->evtype = in->evtype;
1360    out->send_event = ((in->type & 0x80) != 0);
1361    out->time = in->time;
1362    out->deviceid = in->deviceid;
1363    out->sourceid = in->sourceid;
1364    out->detail = in->detail;
1365    out->root = in->root;
1366    out->event = in->event;
1367    out->child = in->child;
1368    out->root_x = FP1616toDBL(in->root_x);
1369    out->root_y = FP1616toDBL(in->root_y);
1370    out->event_x = FP1616toDBL(in->event_x);
1371    out->event_y = FP1616toDBL(in->event_y);
1372    out->flags = in->flags;
1373    out->mods.base = in->mods.base_mods;
1374    out->mods.locked = in->mods.locked_mods;
1375    out->mods.latched = in->mods.latched_mods;
1376    out->mods.effective = in->mods.effective_mods;
1377    out->group.base = in->group.base_group;
1378    out->group.locked = in->group.locked_group;
1379    out->group.latched = in->group.latched_group;
1380    out->group.effective = in->group.effective_group;
1381    out->buttons.mask_len = in->buttons_len * 4;
1382    out->valuators.mask_len = in->valuators_len * 4;
1383
1384    out->buttons.mask = next_block(&ptr_lib, out->buttons.mask_len);
1385
1386    /* buttons */
1387    ptr = (unsigned char*)&in[1];
1388    memcpy(out->buttons.mask, ptr, out->buttons.mask_len);
1389    ptr += in->buttons_len * 4;
1390
1391    /* valuators */
1392    out->valuators.mask = next_block(&ptr_lib, out->valuators.mask_len);
1393    memcpy(out->valuators.mask, ptr, out->valuators.mask_len);
1394    ptr += in->valuators_len * 4;
1395
1396    len = count_bits(out->valuators.mask, out->valuators.mask_len);
1397    out->valuators.values = next_block(&ptr_lib, len * sizeof(double));
1398
1399    values = (FP3232*)ptr;
1400    for (i = 0; i < len; i++, values++)
1401    {
1402        out->valuators.values[i] = values->integral;
1403        out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1404    }
1405
1406
1407    return 1;
1408}
1409
1410_X_HIDDEN int
1411size_classes(xXIAnyInfo* from, int nclasses)
1412{
1413    int len, i;
1414    xXIAnyInfo *any_wire;
1415    char *ptr_wire;
1416
1417    len = nclasses * sizeof(XIAnyClassInfo*); /* len for to->classes */
1418    ptr_wire = (char*)from;
1419    for (i = 0; i < nclasses; i++)
1420    {
1421        int l = 0;
1422        any_wire = (xXIAnyInfo*)ptr_wire;
1423        switch(any_wire->type)
1424        {
1425            case XIButtonClass:
1426                l = sizeDeviceClassType(XIButtonClass,
1427                        ((xXIButtonInfo*)any_wire)->num_buttons);
1428                break;
1429            case XIKeyClass:
1430                l = sizeDeviceClassType(XIKeyClass,
1431                        ((xXIKeyInfo*)any_wire)->num_keycodes);
1432                break;
1433            case XIValuatorClass:
1434                l = sizeDeviceClassType(XIValuatorClass, 0);
1435                break;
1436        }
1437
1438        len += l;
1439        ptr_wire += any_wire->length * 4;
1440    }
1441
1442    return len;
1443}
1444
1445/* Copy classes from any into to->classes and return the number of bytes
1446 * copied. Memory layout of to->classes is
1447 * [clsptr][clsptr][clsptr][classinfo][classinfo]...
1448 *    |________|___________^
1449 *             |______________________^
1450 */
1451_X_HIDDEN int
1452copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int nclasses)
1453{
1454    XIAnyClassInfo *any_lib;
1455    xXIAnyInfo *any_wire;
1456    void *ptr_lib;
1457    char *ptr_wire;
1458    int i, len;
1459
1460    if (!to->classes)
1461        return -1;
1462
1463    ptr_wire = (char*)from;
1464    ptr_lib = to->classes;
1465    to->classes = next_block(&ptr_lib, nclasses * sizeof(XIAnyClassInfo*));
1466    len = 0; /* count wire length */
1467
1468    for (i = 0; i < nclasses; i++)
1469    {
1470        any_lib = (XIAnyClassInfo*)ptr_lib;
1471        any_wire = (xXIAnyInfo*)ptr_wire;
1472
1473        to->classes[i] = any_lib;
1474        any_lib->type = any_wire->type;
1475        any_lib->sourceid = any_wire->sourceid;
1476        switch(any_wire->type)
1477        {
1478            case XIButtonClass:
1479                {
1480                    XIButtonClassInfo *cls_lib;
1481                    xXIButtonInfo *cls_wire;
1482                    uint32_t *atoms;
1483                    int size;
1484                    int j;
1485
1486                    cls_lib = next_block(&ptr_lib, sizeof(XIButtonClassInfo));
1487                    cls_wire = (xXIButtonInfo*)any_wire;
1488
1489                    cls_lib->num_buttons = cls_wire->num_buttons;
1490                    size = ((((cls_wire->num_buttons + 7)/8) + 3)/4);
1491                    cls_lib->state.mask_len = size * 4;
1492                    /* Force mask alignment with longs to avoid unaligned
1493                     * access when accessing the atoms. */
1494                    cls_lib->state.mask = next_block(&ptr_lib, size * sizeof(Atom));
1495                    memcpy(cls_lib->state.mask, &cls_wire[1],
1496                           cls_lib->state.mask_len);
1497
1498                    cls_lib->labels = next_block(&ptr_lib, cls_lib->num_buttons * sizeof(Atom));
1499                    atoms =(uint32_t*)((char*)&cls_wire[1] + cls_lib->state.mask_len);
1500                    for (j = 0; j < cls_lib->num_buttons; j++)
1501                        cls_lib->labels[j] = *atoms++;
1502
1503                    break;
1504                }
1505            case XIKeyClass:
1506                {
1507                    XIKeyClassInfo *cls_lib;
1508                    xXIKeyInfo *cls_wire;
1509
1510                    cls_lib = next_block(&ptr_lib, sizeof(XIKeyClassInfo));
1511                    cls_wire = (xXIKeyInfo*)any_wire;
1512
1513                    cls_lib->num_keycodes = cls_wire->num_keycodes;
1514                    cls_lib->keycodes = next_block(&ptr_lib,
1515                            cls_lib->num_keycodes * sizeof(int));
1516                    memcpy(cls_lib->keycodes, &cls_wire[1],
1517                            cls_lib->num_keycodes);
1518
1519                    break;
1520                }
1521            case XIValuatorClass:
1522                {
1523                    XIValuatorClassInfo *cls_lib;
1524                    xXIValuatorInfo *cls_wire;
1525
1526                    cls_lib = next_block(&ptr_lib, sizeof(XIValuatorClassInfo));
1527                    cls_wire = (xXIValuatorInfo*)any_wire;
1528
1529                    cls_lib->number = cls_wire->number;
1530                    cls_lib->label  = cls_wire->label;
1531                    cls_lib->resolution = cls_wire->resolution;
1532                    cls_lib->min        = cls_wire->min.integral;
1533                    cls_lib->max        = cls_wire->max.integral;
1534                    cls_lib->value      = cls_wire->value.integral;
1535                    /* FIXME: fractional parts */
1536                    cls_lib->mode       = cls_wire->mode;
1537
1538                }
1539                break;
1540        }
1541        len += any_wire->length * 4;
1542        ptr_wire += any_wire->length * 4;
1543    }
1544    return len;
1545}
1546
1547
1548static int
1549wireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie)
1550{
1551    XIDeviceChangedEvent *out;
1552    XIDeviceInfo info;
1553    int len;
1554
1555    len = size_classes((xXIAnyInfo*)&in[1], in->num_classes);
1556
1557    cookie->data = out = malloc(sizeof(XIDeviceChangedEvent) + len);
1558
1559    out->type = in->type;
1560    out->display = cookie->display;
1561    out->extension = in->extension;
1562    out->evtype = in->evtype;
1563    out->send_event = ((in->type & 0x80) != 0);
1564    out->time = in->time;
1565    out->deviceid = in->deviceid;
1566    out->sourceid = in->sourceid;
1567    out->reason = in->reason;
1568    out->num_classes = in->num_classes;
1569
1570    out->classes = (XIAnyClassInfo**)&out[1];
1571
1572    info.classes = out->classes;
1573
1574    copy_classes(&info, (xXIAnyInfo*)&in[1], in->num_classes);
1575
1576    return 1;
1577}
1578
1579static int
1580wireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie)
1581{
1582    int i;
1583    XIHierarchyInfo *info_out;
1584    xXIHierarchyInfo *info_in;
1585    XIHierarchyEvent *out;
1586
1587    cookie->data = out = malloc(sizeof(XIHierarchyEvent) + in->num_info * sizeof(XIHierarchyInfo));;
1588
1589    out->info           = (XIHierarchyInfo*)&out[1];
1590    out->display        = cookie->display;
1591    out->type           = in->type;
1592    out->extension      = in->extension;
1593    out->evtype         = in->evtype;
1594    out->send_event = ((in->type & 0x80) != 0);
1595    out->time           = in->time;
1596    out->flags          = in->flags;
1597    out->num_info       = in->num_info;
1598
1599    info_out            = out->info;
1600    info_in             = (xXIHierarchyInfo*)&in[1];
1601
1602    for (i = 0; i < out->num_info; i++, info_out++, info_in++)
1603    {
1604        info_out->deviceid      = info_in->deviceid;
1605        info_out->attachment    = info_in->attachment;
1606        info_out->use           = info_in->use;
1607        info_out->enabled       = info_in->enabled;
1608        info_out->flags         = info_in->flags;
1609    }
1610
1611    return 1;
1612}
1613
1614static int
1615wireToRawEvent(xXIRawEvent *in, XGenericEventCookie *cookie)
1616{
1617    int len, i, bits;
1618    FP3232 *values;
1619    XIRawEvent *out;
1620    void *ptr;
1621
1622
1623    len = sizeof(XIRawEvent) + in->valuators_len * 4;
1624    bits = count_bits((unsigned char*)&in[1], in->valuators_len * 4);
1625    len += bits * sizeof(double) * 2; /* raw + normal */
1626
1627    cookie->data = ptr = calloc(1, len);
1628    if (!ptr)
1629        return 0;
1630
1631    out = next_block(&ptr, sizeof(XIRawEvent));
1632    out->type           = in->type;
1633    out->display        = cookie->display;
1634    out->extension      = in->extension;
1635    out->evtype         = in->evtype;
1636    out->send_event = ((in->type & 0x80) != 0);
1637    out->time           = in->time;
1638    out->detail         = in->detail;
1639    out->deviceid       = in->deviceid;
1640    out->sourceid       = 0; /* https://bugs.freedesktop.org/show_bug.cgi?id=34240 */
1641    out->flags          = in->flags;
1642
1643    out->valuators.mask_len = in->valuators_len * 4;
1644    out->valuators.mask = next_block(&ptr, out->valuators.mask_len);
1645    memcpy(out->valuators.mask, &in[1], out->valuators.mask_len);
1646
1647    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1648    out->raw_values = next_block(&ptr, bits * sizeof(double));
1649
1650    values = (FP3232*)(((char*)&in[1]) + in->valuators_len * 4);
1651    for (i = 0; i < bits; i++)
1652    {
1653        out->valuators.values[i] = values->integral;
1654        out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1655        out->raw_values[i] = (values + bits)->integral;
1656        out->raw_values[i] += ((double)(values + bits)->frac / (1 << 16) / (1 << 16));
1657        values++;
1658    }
1659
1660    return 1;
1661}
1662
1663/* Memory layout of XIEnterEvents:
1664   [event][modifiers][group][button]
1665 */
1666static int
1667wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie)
1668{
1669    int len;
1670    XIEnterEvent *out;
1671
1672    len = sizeof(XIEnterEvent) + in->buttons_len * 4;
1673
1674    cookie->data = out = malloc(len);
1675    out->buttons.mask = (unsigned char*)&out[1];
1676
1677    out->type           = in->type;
1678    out->display        = cookie->display;
1679    out->extension      = in->extension;
1680    out->evtype         = in->evtype;
1681    out->send_event = ((in->type & 0x80) != 0);
1682    out->time           = in->time;
1683    out->detail         = in->detail;
1684    out->deviceid       = in->deviceid;
1685    out->root           = in->root;
1686    out->event          = in->event;
1687    out->child          = in->child;
1688    out->sourceid       = in->sourceid;
1689    out->root_x         = FP1616toDBL(in->root_x);
1690    out->root_y         = FP1616toDBL(in->root_y);
1691    out->event_x        = FP1616toDBL(in->event_x);
1692    out->event_y        = FP1616toDBL(in->event_y);
1693    out->mode           = in->mode;
1694    out->focus          = in->focus;
1695    out->same_screen    = in->same_screen;
1696
1697    out->mods.base = in->mods.base_mods;
1698    out->mods.locked = in->mods.locked_mods;
1699    out->mods.latched = in->mods.latched_mods;
1700    out->mods.effective = in->mods.effective_mods;
1701    out->group.base = in->group.base_group;
1702    out->group.locked = in->group.locked_group;
1703    out->group.latched = in->group.latched_group;
1704    out->group.effective = in->group.effective_group;
1705
1706    out->buttons.mask_len = in->buttons_len * 4;
1707    memcpy(out->buttons.mask, &in[1], out->buttons.mask_len);
1708
1709    return 1;
1710}
1711
1712static int
1713wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie)
1714{
1715    XIPropertyEvent *out = malloc(sizeof(XIPropertyEvent));
1716
1717    cookie->data = out;
1718
1719    out->type           = in->type;
1720    out->extension      = in->extension;
1721    out->evtype         = in->evtype;
1722    out->send_event = ((in->type & 0x80) != 0);
1723    out->time           = in->time;
1724    out->property       = in->property;
1725    out->what           = in->what;
1726    out->deviceid       = in->deviceid;
1727
1728    return 1;
1729}
1730