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