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