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);
13087404ef7Smrgstatic int
13187404ef7SmrgwireToPinchEvent(xXIGesturePinchEvent *in,
13287404ef7Smrg                 XGenericEventCookie *cookie);
13387404ef7Smrgstatic int
13487404ef7SmrgwireToSwipeEvent(xXIGestureSwipeEvent *in,
13587404ef7Smrg                 XGenericEventCookie *cookie);
136c27c18e8Smrg
137c27c18e8Smrgstatic /* const */ XEvent emptyevent;
138c43cc173Smrg
139f1ee322dSmrgtypedef Status (*core_event_to_wire)(Display*, XEvent*, xEvent*);
140f1ee322dSmrg
141c43cc173Smrgstatic /* const */ XExtensionHooks xinput_extension_hooks = {
142c43cc173Smrg    NULL,	/* create_gc */
143c43cc173Smrg    NULL,	/* copy_gc */
144c43cc173Smrg    NULL,	/* flush_gc */
145c43cc173Smrg    NULL,	/* free_gc */
146c43cc173Smrg    NULL,	/* create_font */
147c43cc173Smrg    NULL,	/* free_font */
148c43cc173Smrg    XInputClose,	/* close_display */
149c43cc173Smrg    XInputWireToEvent,	/* wire_to_event */
150f1ee322dSmrg    (core_event_to_wire)_XiEventToWire, /* event_to_wire */
151c43cc173Smrg    NULL,	/* error */
152c43cc173Smrg    XInputError,	/* error_string */
153c43cc173Smrg};
154c43cc173Smrg
155f1ee322dSmrgstatic const char *XInputErrorList[] = {
156c43cc173Smrg    "BadDevice, invalid or uninitialized input device",	/* BadDevice */
157c43cc173Smrg    "BadEvent, invalid event type",	/* BadEvent */
158c43cc173Smrg    "BadMode, invalid mode parameter",	/* BadMode  */
159c43cc173Smrg    "DeviceBusy, device is busy",	/* DeviceBusy */
160c43cc173Smrg    "BadClass, invalid event class",	/* BadClass */
161c43cc173Smrg};
162c43cc173Smrg
1633e256790Smrg/* Get the version supported by the server to know which number of
1643e256790Smrg* events are support. Otherwise, a wrong number of events may smash
1653e256790Smrg* the Xlib-internal event processing vector.
1663e256790Smrg*
1673e256790Smrg* Since the extension hasn't been initialized yet, we need to
1683e256790Smrg* manually get the opcode, then the version.
1693e256790Smrg*/
1703e256790Smrgstatic int
1713e256790Smrg_XiFindEventsSupported(Display *dpy)
1723e256790Smrg{
1733e256790Smrg    XExtCodes codes;
1743e256790Smrg    XExtensionVersion *extversion = NULL;
1753e256790Smrg    int nevents = 0;
1763e256790Smrg
1773e256790Smrg    if (!XQueryExtension(dpy, INAME, &codes.major_opcode,
1783e256790Smrg                         &codes.first_event, &codes.first_error))
1793e256790Smrg        goto out;
1803e256790Smrg
1813e256790Smrg    LockDisplay(dpy);
1823e256790Smrg    extversion = _XiGetExtensionVersionRequest(dpy, INAME, codes.major_opcode);
1833e256790Smrg    UnlockDisplay(dpy);
1843e256790Smrg    SyncHandle();
1853e256790Smrg
1863e256790Smrg    if (!extversion || !extversion->present)
1873e256790Smrg        goto out;
1883e256790Smrg
1893e256790Smrg    if (extversion->major_version >= 2)
1903e256790Smrg        nevents = IEVENTS; /* number is fixed, XI2 adds GenericEvents only */
1913e256790Smrg    else if (extversion->major_version <= 0)
1923e256790Smrg    {
1933e256790Smrg        printf("XInput_find_display: invalid extension version %d.%d\n",
1943e256790Smrg                extversion->major_version, extversion->minor_version);
1953e256790Smrg        goto out;
1963e256790Smrg    }
1973e256790Smrg    else
1983e256790Smrg    {
1993e256790Smrg        switch(extversion->minor_version)
2003e256790Smrg        {
2013e256790Smrg            case XI_Add_DeviceProperties_Minor:
2023e256790Smrg                nevents = XI_DevicePropertyNotify + 1;
2033e256790Smrg                break;
2043e256790Smrg            case  XI_Add_DevicePresenceNotify_Minor:
2053e256790Smrg                nevents = XI_DevicePresenceNotify + 1;
2063e256790Smrg                break;
2073e256790Smrg            default:
2083e256790Smrg                nevents = XI_DeviceButtonstateNotify + 1;
2093e256790Smrg                break;
2103e256790Smrg        }
2113e256790Smrg    }
2123e256790Smrg
2133e256790Smrgout:
2143e256790Smrg    if (extversion)
2153e256790Smrg        XFree(extversion);
2163e256790Smrg    return nevents;
2173e256790Smrg}
2183e256790Smrg
2193e256790Smrg
220c27c18e8Smrg_X_HIDDEN
221c27c18e8SmrgXExtDisplayInfo *XInput_find_display (Display *dpy)
222c27c18e8Smrg{
223c27c18e8Smrg    XExtDisplayInfo *dpyinfo;
224c27c18e8Smrg    if (!xinput_info) { if (!(xinput_info = XextCreateExtension())) return NULL; }
225c27c18e8Smrg    if (!(dpyinfo = XextFindDisplay (xinput_info, dpy)))
226c27c18e8Smrg    {
2273e256790Smrg      int nevents = _XiFindEventsSupported(dpy);
2283e256790Smrg
229c27c18e8Smrg      dpyinfo = XextAddDisplay (xinput_info, dpy,
230c27c18e8Smrg                                xinput_extension_name,
231c27c18e8Smrg                                &xinput_extension_hooks,
2323e256790Smrg                                nevents, NULL);
2334e8f48c7Smrg      if (XextHasExtension(dpyinfo)) /* skip if XI doesn't exist on the server */
2343e256790Smrg      {
2353e256790Smrg          XESetWireToEventCookie(dpy, dpyinfo->codes->major_opcode, XInputWireToCookie);
2363e256790Smrg          XESetCopyEventCookie(dpy, dpyinfo->codes->major_opcode, XInputCopyCookie);
2373e256790Smrg      }
238c27c18e8Smrg    }
239c27c18e8Smrg    return dpyinfo;
240c27c18e8Smrg}
241c43cc173Smrg
242c27c18e8Smrgstatic XEXT_GENERATE_ERROR_STRING(XInputError, xinput_extension_name,
243c27c18e8Smrg                                  IERRORS, XInputErrorList)
244c43cc173Smrg/*******************************************************************
245c27c18e8Smrg*
246c27c18e8Smrg* Input extension versions.
247c27c18e8Smrg*
248c27c18e8Smrg*/
249c27c18e8Smrgstatic XExtensionVersion versions[] = { {XI_Absent, 0, 0},
250c27c18e8Smrg{XI_Present, XI_Initial_Release_Major, XI_Initial_Release_Minor},
251c27c18e8Smrg{XI_Present, XI_Add_XDeviceBell_Major, XI_Add_XDeviceBell_Minor},
252c27c18e8Smrg{XI_Present, XI_Add_XSetDeviceValuators_Major,
253c27c18e8Smrg XI_Add_XSetDeviceValuators_Minor},
254c27c18e8Smrg{XI_Present, XI_Add_XChangeDeviceControl_Major,
255c27c18e8Smrg XI_Add_XChangeDeviceControl_Minor},
256c27c18e8Smrg{XI_Present, XI_Add_DevicePresenceNotify_Major,
257c27c18e8Smrg XI_Add_DevicePresenceNotify_Minor},
258c27c18e8Smrg{XI_Present, XI_Add_DeviceProperties_Major,
259c27c18e8Smrg XI_Add_DeviceProperties_Minor},
260f1ee322dSmrg{XI_Present, 2, 0},
261f1ee322dSmrg{XI_Present, 2, 1},
26287404ef7Smrg{XI_Present, 2, 2},
26387404ef7Smrg{XI_Present, 2, 3},
26487404ef7Smrg{XI_Present, 2, 4},
265c27c18e8Smrg};
266c43cc173Smrg
267c43cc173Smrg/***********************************************************************
268c43cc173Smrg *
269c43cc173Smrg * Return errors reported by this extension.
270c43cc173Smrg *
271c43cc173Smrg */
272c43cc173Smrg
273c43cc173Smrgvoid
274c27c18e8Smrg_xibaddevice(
275c27c18e8Smrg    Display	*dpy,
276c27c18e8Smrg    int		*error)
277c43cc173Smrg{
278c43cc173Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
279c43cc173Smrg
280c43cc173Smrg    *error = info->codes->first_error + XI_BadDevice;
281c43cc173Smrg}
282c43cc173Smrg
283c43cc173Smrgvoid
284c27c18e8Smrg_xibadclass(
285c27c18e8Smrg    Display	*dpy,
286c27c18e8Smrg    int		*error)
287c43cc173Smrg{
288c43cc173Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
289c43cc173Smrg
290c43cc173Smrg    *error = info->codes->first_error + XI_BadClass;
291c43cc173Smrg}
292c43cc173Smrg
293c43cc173Smrgvoid
294c27c18e8Smrg_xibadevent(
295c27c18e8Smrg    Display	*dpy,
296c27c18e8Smrg    int		*error)
297c43cc173Smrg{
298c43cc173Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
299c43cc173Smrg
300c43cc173Smrg    *error = info->codes->first_error + XI_BadEvent;
301c43cc173Smrg}
302c43cc173Smrg
303c43cc173Smrgvoid
304c27c18e8Smrg_xibadmode(
305c27c18e8Smrg    Display	*dpy,
306c27c18e8Smrg    int		*error)
307c43cc173Smrg{
308c43cc173Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
309c43cc173Smrg
310c43cc173Smrg    *error = info->codes->first_error + XI_BadMode;
311c43cc173Smrg}
312c43cc173Smrg
313c43cc173Smrgvoid
314c27c18e8Smrg_xidevicebusy(
315c27c18e8Smrg    Display	*dpy,
316c27c18e8Smrg    int		*error)
317c43cc173Smrg{
318c43cc173Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
319c43cc173Smrg
320c43cc173Smrg    *error = info->codes->first_error + XI_DeviceBusy;
321c43cc173Smrg}
322c43cc173Smrg
323c43cc173Smrgstatic int XInputCheckExtension(Display *dpy, XExtDisplayInfo *info)
324c43cc173Smrg{
325c43cc173Smrg    XextCheckExtension (dpy, info, xinput_extension_name, 0);
326c43cc173Smrg    return 1;
327c43cc173Smrg}
328c43cc173Smrg
329f1ee322dSmrg/*****************************************************************
330f1ee322dSmrg * Compare version numbers between info and the built-in version table.
331f1ee322dSmrg * Returns
332f1ee322dSmrg *   -1 if info's version is less than version_index's version,
333f1ee322dSmrg *   0 if equal (or DontCheck),
334f1ee322dSmrg *   1 if info's version is greater than version_index's version.
335f1ee322dSmrg * Returns -2 on initialization errors which shouldn't happen if you call it
336f1ee322dSmrg * correctly.
337f1ee322dSmrg */
338f1ee322dSmrg_X_HIDDEN int
339f1ee322dSmrg_XiCheckVersion(XExtDisplayInfo *info,
340f1ee322dSmrg                int version_index)
341f1ee322dSmrg{
342f1ee322dSmrg    XExtensionVersion *ext;
343f1ee322dSmrg
344f1ee322dSmrg    if (versions[version_index].major_version == Dont_Check)
345f1ee322dSmrg        return 0;
346f1ee322dSmrg
347f1ee322dSmrg    if (!info->data)
348f1ee322dSmrg        return -2;
349f1ee322dSmrg
350f1ee322dSmrg    ext = ((XInputData *) info->data)->vers;
351f1ee322dSmrg    if (!ext)
352f1ee322dSmrg        return -2;
353f1ee322dSmrg
354f1ee322dSmrg    if (ext->major_version == versions[version_index].major_version &&
355f1ee322dSmrg        ext->minor_version == versions[version_index].minor_version)
356f1ee322dSmrg        return 0;
357f1ee322dSmrg
358f1ee322dSmrg    if (ext->major_version < versions[version_index].major_version ||
359f1ee322dSmrg        (ext->major_version == versions[version_index].major_version &&
360f1ee322dSmrg         ext->minor_version < versions[version_index].minor_version))
361f1ee322dSmrg        return -1;
362f1ee322dSmrg    else
363f1ee322dSmrg        return 1;
364f1ee322dSmrg}
365f1ee322dSmrg
366c43cc173Smrg/***********************************************************************
367c43cc173Smrg *
368c43cc173Smrg * Check to see if the input extension is installed in the server.
369c43cc173Smrg * Also check to see if the version is >= the requested version.
370c43cc173Smrg *
371c43cc173Smrg */
372c43cc173Smrg
373c27c18e8Smrg_X_HIDDEN int
374c27c18e8Smrg_XiCheckExtInit(
375c27c18e8Smrg    register Display	*dpy,
376c27c18e8Smrg    register int	 version_index,
377c27c18e8Smrg    XExtDisplayInfo	*info)
378c43cc173Smrg{
379c43cc173Smrg    if (!XInputCheckExtension(dpy, info)) {
380c43cc173Smrg	UnlockDisplay(dpy);
381c43cc173Smrg	return (-1);
382c43cc173Smrg    }
383c43cc173Smrg
384c43cc173Smrg    if (info->data == NULL) {
385c43cc173Smrg	info->data = (XPointer) Xmalloc(sizeof(XInputData));
386c43cc173Smrg	if (!info->data) {
387c43cc173Smrg	    UnlockDisplay(dpy);
388c43cc173Smrg	    return (-1);
389c43cc173Smrg	}
390c43cc173Smrg	((XInputData *) info->data)->vers =
39144584a44Smrg	    _XiGetExtensionVersionRequest(dpy, "XInputExtension", info->codes->major_opcode);
392c43cc173Smrg    }
393c43cc173Smrg
394f1ee322dSmrg    if (_XiCheckVersion(info, version_index) < 0) {
395f1ee322dSmrg	UnlockDisplay(dpy);
396f1ee322dSmrg	return -1;
397c43cc173Smrg    }
398f1ee322dSmrg
399c43cc173Smrg    return (0);
400c43cc173Smrg}
401c43cc173Smrg
402c43cc173Smrg/***********************************************************************
403c43cc173Smrg *
404c43cc173Smrg * Close display routine.
405c43cc173Smrg *
406c43cc173Smrg */
407c43cc173Smrg
408c43cc173Smrgstatic int
409c27c18e8SmrgXInputClose(
410c27c18e8Smrg    Display	*dpy,
411c27c18e8Smrg    XExtCodes	*codes)
412c43cc173Smrg{
413c43cc173Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
414c43cc173Smrg
415c43cc173Smrg    if (info->data != NULL) {
416c43cc173Smrg	XFree((char *)((XInputData *) info->data)->vers);
417c43cc173Smrg	XFree((char *)info->data);
418c43cc173Smrg    }
419f1ee322dSmrg
420f1ee322dSmrg    if (!XextRemoveDisplay(xinput_info, dpy))
421f1ee322dSmrg        return 0;
422f1ee322dSmrg
423f1ee322dSmrg    if (xinput_info->ndisplays == 0) {
424f1ee322dSmrg        XextDestroyExtension(xinput_info);
425f1ee322dSmrg        xinput_info = NULL;
426f1ee322dSmrg    }
427f1ee322dSmrg
428f1ee322dSmrg    return 1;
429c43cc173Smrg}
430c43cc173Smrg
431c43cc173Smrgstatic int
432c27c18e8SmrgOnes(Mask mask)
433c43cc173Smrg{
434c43cc173Smrg    register Mask y;
435c43cc173Smrg
436c43cc173Smrg    y = (mask >> 1) & 033333333333;
437c43cc173Smrg    y = mask - y - ((y >> 1) & 033333333333);
438c43cc173Smrg    return (((y + (y >> 3)) & 030707070707) % 077);
439c43cc173Smrg}
440c43cc173Smrg
441c27c18e8Smrgstatic int count_bits(unsigned char* ptr, int len)
442c27c18e8Smrg{
443c27c18e8Smrg    int bits = 0;
444c27c18e8Smrg    unsigned int i;
445c27c18e8Smrg    unsigned char x;
446c27c18e8Smrg
447c27c18e8Smrg    for (i = 0; i < len; i++)
448c27c18e8Smrg    {
449c27c18e8Smrg        x = ptr[i];
450c27c18e8Smrg        while(x > 0)
451c27c18e8Smrg        {
452c27c18e8Smrg            bits += (x & 0x1);
453c27c18e8Smrg            x >>= 1;
454c27c18e8Smrg        }
455c27c18e8Smrg    }
456c27c18e8Smrg    return bits;
457c27c18e8Smrg}
458c27c18e8Smrg
459c43cc173Smrgint
460c43cc173Smrg_XiGetDevicePresenceNotifyEvent(Display * dpy)
461c43cc173Smrg{
462c43cc173Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
463c43cc173Smrg
464c43cc173Smrg    return info->codes->first_event + XI_DevicePresenceNotify;
465c43cc173Smrg}
466c43cc173Smrg
467c43cc173Smrg/***********************************************************************
468c43cc173Smrg *
469c43cc173Smrg * Handle Input extension events.
470c43cc173Smrg * Reformat a wire event into an XEvent structure of the right type.
471c43cc173Smrg *
472c43cc173Smrg */
473c43cc173Smrg
474c43cc173Smrgstatic Bool
475c27c18e8SmrgXInputWireToEvent(
476c27c18e8Smrg    Display	*dpy,
477c27c18e8Smrg    XEvent	*re,
478c27c18e8Smrg    xEvent	*event)
479c43cc173Smrg{
480c43cc173Smrg    unsigned int type, reltype;
481c43cc173Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
482c43cc173Smrg    XEvent *save = (XEvent *) info->data;
483c43cc173Smrg
484c43cc173Smrg    type = event->u.u.type & 0x7f;
485c43cc173Smrg    reltype = (type - info->codes->first_event);
486c43cc173Smrg
487c27c18e8Smrg    if (type == GenericEvent ||
488c27c18e8Smrg        (reltype != XI_DeviceValuator &&
489c43cc173Smrg	reltype != XI_DeviceKeystateNotify &&
490c27c18e8Smrg	reltype != XI_DeviceButtonstateNotify)) {
491c43cc173Smrg	*save = emptyevent;
492c43cc173Smrg	save->type = type;
493c43cc173Smrg	((XAnyEvent *) save)->serial = _XSetLastRequestRead(dpy,
494c43cc173Smrg							    (xGenericReply *)
495c43cc173Smrg							    event);
496c43cc173Smrg	((XAnyEvent *) save)->send_event = ((event->u.u.type & 0x80) != 0);
497c43cc173Smrg	((XAnyEvent *) save)->display = dpy;
498c43cc173Smrg    }
499c43cc173Smrg
500c27c18e8Smrg    /* Process traditional events */
501c27c18e8Smrg    if (type != GenericEvent)
502c43cc173Smrg    {
503c27c18e8Smrg        switch (reltype) {
504c27c18e8Smrg            case XI_DeviceMotionNotify:
505c27c18e8Smrg                {
506c27c18e8Smrg                    register XDeviceMotionEvent *ev = (XDeviceMotionEvent *) save;
507c27c18e8Smrg                    deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event;
508c27c18e8Smrg
509c27c18e8Smrg                    ev->root = ev2->root;
510c27c18e8Smrg                    ev->window = ev2->event;
511c27c18e8Smrg                    ev->subwindow = ev2->child;
512c27c18e8Smrg                    ev->time = ev2->time;
513c27c18e8Smrg                    ev->x_root = ev2->root_x;
514c27c18e8Smrg                    ev->y_root = ev2->root_y;
515c27c18e8Smrg                    ev->x = ev2->event_x;
516c27c18e8Smrg                    ev->y = ev2->event_y;
517c27c18e8Smrg                    ev->state = ev2->state;
518c27c18e8Smrg                    ev->same_screen = ev2->same_screen;
519c27c18e8Smrg                    ev->is_hint = ev2->detail;
520c27c18e8Smrg                    ev->deviceid = ev2->deviceid & DEVICE_BITS;
521c27c18e8Smrg                    return (DONT_ENQUEUE);
522c27c18e8Smrg                }
523c27c18e8Smrg                break;
524c27c18e8Smrg            case XI_DeviceKeyPress:
525c27c18e8Smrg            case XI_DeviceKeyRelease:
526c27c18e8Smrg                {
527c27c18e8Smrg                    register XDeviceKeyEvent *ev = (XDeviceKeyEvent *) save;
528c27c18e8Smrg                    deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event;
529c27c18e8Smrg
530c27c18e8Smrg                    ev->root = ev2->root;
531c27c18e8Smrg                    ev->window = ev2->event;
532c27c18e8Smrg                    ev->subwindow = ev2->child;
533c27c18e8Smrg                    ev->time = ev2->time;
534c27c18e8Smrg                    ev->x_root = ev2->root_x;
535c27c18e8Smrg                    ev->y_root = ev2->root_y;
536c27c18e8Smrg                    ev->x = ev2->event_x;
537c27c18e8Smrg                    ev->y = ev2->event_y;
538c27c18e8Smrg                    ev->state = ev2->state;
539c27c18e8Smrg                    ev->same_screen = ev2->same_screen;
540c27c18e8Smrg                    ev->keycode = ev2->detail;
541c27c18e8Smrg                    ev->deviceid = ev2->deviceid & DEVICE_BITS;
542c27c18e8Smrg                    if (ev2->deviceid & MORE_EVENTS)
543c27c18e8Smrg                        return (DONT_ENQUEUE);
544c27c18e8Smrg                    else {
545c27c18e8Smrg                        *re = *save;
546c27c18e8Smrg                        return (ENQUEUE_EVENT);
547c27c18e8Smrg                    }
548c27c18e8Smrg                }
549c27c18e8Smrg                break;
550c27c18e8Smrg            case XI_DeviceButtonPress:
551c27c18e8Smrg            case XI_DeviceButtonRelease:
552c27c18e8Smrg                {
553c27c18e8Smrg                    register XDeviceButtonEvent *ev = (XDeviceButtonEvent *) save;
554c27c18e8Smrg                    deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event;
555c27c18e8Smrg
556c27c18e8Smrg                    ev->root = ev2->root;
557c27c18e8Smrg                    ev->window = ev2->event;
558c27c18e8Smrg                    ev->subwindow = ev2->child;
559c27c18e8Smrg                    ev->time = ev2->time;
560c27c18e8Smrg                    ev->x_root = ev2->root_x;
561c27c18e8Smrg                    ev->y_root = ev2->root_y;
562c27c18e8Smrg                    ev->x = ev2->event_x;
563c27c18e8Smrg                    ev->y = ev2->event_y;
564c27c18e8Smrg                    ev->state = ev2->state;
565c27c18e8Smrg                    ev->same_screen = ev2->same_screen;
566c27c18e8Smrg                    ev->button = ev2->detail;
567c27c18e8Smrg                    ev->deviceid = ev2->deviceid & DEVICE_BITS;
568c27c18e8Smrg                    if (ev2->deviceid & MORE_EVENTS)
569c27c18e8Smrg                        return (DONT_ENQUEUE);
570c27c18e8Smrg                    else {
571c27c18e8Smrg                        *re = *save;
572c27c18e8Smrg                        return (ENQUEUE_EVENT);
573c27c18e8Smrg                    }
574c27c18e8Smrg                }
575c27c18e8Smrg                break;
576c27c18e8Smrg            case XI_ProximityIn:
577c27c18e8Smrg            case XI_ProximityOut:
578c27c18e8Smrg                {
579c27c18e8Smrg                    register XProximityNotifyEvent *ev = (XProximityNotifyEvent *) save;
580c27c18e8Smrg                    deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event;
581c27c18e8Smrg
582c27c18e8Smrg                    ev->root = ev2->root;
583c27c18e8Smrg                    ev->window = ev2->event;
584c27c18e8Smrg                    ev->subwindow = ev2->child;
585c27c18e8Smrg                    ev->time = ev2->time;
586c27c18e8Smrg                    ev->x_root = ev2->root_x;
587c27c18e8Smrg                    ev->y_root = ev2->root_y;
588c27c18e8Smrg                    ev->x = ev2->event_x;
589c27c18e8Smrg                    ev->y = ev2->event_y;
590c27c18e8Smrg                    ev->state = ev2->state;
591c27c18e8Smrg                    ev->same_screen = ev2->same_screen;
592c27c18e8Smrg                    ev->deviceid = ev2->deviceid & DEVICE_BITS;
593c27c18e8Smrg                    if (ev2->deviceid & MORE_EVENTS)
594c27c18e8Smrg                        return (DONT_ENQUEUE);
595c27c18e8Smrg                    else {
596c27c18e8Smrg                        *re = *save;
597c27c18e8Smrg                        return (ENQUEUE_EVENT);
598c27c18e8Smrg                    }
599c27c18e8Smrg                }
600c27c18e8Smrg                break;
601c27c18e8Smrg            case XI_DeviceValuator:
602c27c18e8Smrg                {
603c27c18e8Smrg                    deviceValuator *xev = (deviceValuator *) event;
604c27c18e8Smrg                    int save_type = save->type - info->codes->first_event;
605f1ee322dSmrg                    int i;
606c27c18e8Smrg
607c27c18e8Smrg                    if (save_type == XI_DeviceKeyPress || save_type == XI_DeviceKeyRelease) {
608c27c18e8Smrg                        XDeviceKeyEvent *kev = (XDeviceKeyEvent *) save;
609c27c18e8Smrg
610c27c18e8Smrg                        kev->device_state = xev->device_state;
611c27c18e8Smrg                        kev->axes_count = xev->num_valuators;
612c27c18e8Smrg                        kev->first_axis = xev->first_valuator;
613c27c18e8Smrg                        i = xev->num_valuators;
614c27c18e8Smrg                        if (i > 6)
615c27c18e8Smrg                            i = 6;
616c27c18e8Smrg                        switch (i) {
617c27c18e8Smrg                            case 6:
618c27c18e8Smrg                                kev->axis_data[5] = xev->valuator5;
619c27c18e8Smrg                            case 5:
620c27c18e8Smrg                                kev->axis_data[4] = xev->valuator4;
621c27c18e8Smrg                            case 4:
622c27c18e8Smrg                                kev->axis_data[3] = xev->valuator3;
623c27c18e8Smrg                            case 3:
624c27c18e8Smrg                                kev->axis_data[2] = xev->valuator2;
625c27c18e8Smrg                            case 2:
626c27c18e8Smrg                                kev->axis_data[1] = xev->valuator1;
627c27c18e8Smrg                            case 1:
628c27c18e8Smrg                                kev->axis_data[0] = xev->valuator0;
629c27c18e8Smrg                        }
630c27c18e8Smrg                    } else if (save_type == XI_DeviceButtonPress ||
631c27c18e8Smrg                            save_type == XI_DeviceButtonRelease) {
632c27c18e8Smrg                        XDeviceButtonEvent *bev = (XDeviceButtonEvent *) save;
633c27c18e8Smrg
634c27c18e8Smrg                        bev->device_state = xev->device_state;
635c27c18e8Smrg                        bev->axes_count = xev->num_valuators;
636c27c18e8Smrg                        bev->first_axis = xev->first_valuator;
637c27c18e8Smrg                        i = xev->num_valuators;
638c27c18e8Smrg                        if (i > 6)
639c27c18e8Smrg                            i = 6;
640c27c18e8Smrg                        switch (i) {
641c27c18e8Smrg                            case 6:
642c27c18e8Smrg                                bev->axis_data[5] = xev->valuator5;
643c27c18e8Smrg                            case 5:
644c27c18e8Smrg                                bev->axis_data[4] = xev->valuator4;
645c27c18e8Smrg                            case 4:
646c27c18e8Smrg                                bev->axis_data[3] = xev->valuator3;
647c27c18e8Smrg                            case 3:
648c27c18e8Smrg                                bev->axis_data[2] = xev->valuator2;
649c27c18e8Smrg                            case 2:
650c27c18e8Smrg                                bev->axis_data[1] = xev->valuator1;
651c27c18e8Smrg                            case 1:
652c27c18e8Smrg                                bev->axis_data[0] = xev->valuator0;
653c27c18e8Smrg                        }
654c27c18e8Smrg                    } else if (save_type == XI_DeviceMotionNotify) {
655c27c18e8Smrg                        XDeviceMotionEvent *mev = (XDeviceMotionEvent *) save;
656c27c18e8Smrg
657c27c18e8Smrg                        mev->device_state = xev->device_state;
658c27c18e8Smrg                        mev->axes_count = xev->num_valuators;
659c27c18e8Smrg                        mev->first_axis = xev->first_valuator;
660c27c18e8Smrg                        i = xev->num_valuators;
661c27c18e8Smrg                        if (i > 6)
662c27c18e8Smrg                            i = 6;
663c27c18e8Smrg                        switch (i) {
664c27c18e8Smrg                            case 6:
665c27c18e8Smrg                                mev->axis_data[5] = xev->valuator5;
666c27c18e8Smrg                            case 5:
667c27c18e8Smrg                                mev->axis_data[4] = xev->valuator4;
668c27c18e8Smrg                            case 4:
669c27c18e8Smrg                                mev->axis_data[3] = xev->valuator3;
670c27c18e8Smrg                            case 3:
671c27c18e8Smrg                                mev->axis_data[2] = xev->valuator2;
672c27c18e8Smrg                            case 2:
673c27c18e8Smrg                                mev->axis_data[1] = xev->valuator1;
674c27c18e8Smrg                            case 1:
675c27c18e8Smrg                                mev->axis_data[0] = xev->valuator0;
676c27c18e8Smrg                        }
677c27c18e8Smrg                    } else if (save_type == XI_ProximityIn || save_type == XI_ProximityOut) {
678c27c18e8Smrg                        XProximityNotifyEvent *pev = (XProximityNotifyEvent *) save;
679c27c18e8Smrg
680c27c18e8Smrg                        pev->device_state = xev->device_state;
681c27c18e8Smrg                        pev->axes_count = xev->num_valuators;
682c27c18e8Smrg                        pev->first_axis = xev->first_valuator;
683c27c18e8Smrg                        i = xev->num_valuators;
684c27c18e8Smrg                        if (i > 6)
685c27c18e8Smrg                            i = 6;
686c27c18e8Smrg                        switch (i) {
687c27c18e8Smrg                            case 6:
688c27c18e8Smrg                                pev->axis_data[5] = xev->valuator5;
689c27c18e8Smrg                            case 5:
690c27c18e8Smrg                                pev->axis_data[4] = xev->valuator4;
691c27c18e8Smrg                            case 4:
692c27c18e8Smrg                                pev->axis_data[3] = xev->valuator3;
693c27c18e8Smrg                            case 3:
694c27c18e8Smrg                                pev->axis_data[2] = xev->valuator2;
695c27c18e8Smrg                            case 2:
696c27c18e8Smrg                                pev->axis_data[1] = xev->valuator1;
697c27c18e8Smrg                            case 1:
698c27c18e8Smrg                                pev->axis_data[0] = xev->valuator0;
699c27c18e8Smrg                        }
700c27c18e8Smrg                    } else if (save_type == XI_DeviceStateNotify) {
701f1ee322dSmrg                        int j;
702c27c18e8Smrg                        XDeviceStateNotifyEvent *sev = (XDeviceStateNotifyEvent *) save;
703c27c18e8Smrg                        XInputClass *any = (XInputClass *) & sev->data[0];
704c27c18e8Smrg                        XValuatorStatus *v;
705c27c18e8Smrg
706c27c18e8Smrg                        for (i = 0; i < sev->num_classes; i++)
707c27c18e8Smrg                            if (any->class != ValuatorClass)
708c27c18e8Smrg                                any = (XInputClass *) ((char *)any + any->length);
709c27c18e8Smrg                        v = (XValuatorStatus *) any;
710c27c18e8Smrg                        i = v->num_valuators;
711c27c18e8Smrg                        j = xev->num_valuators;
712c27c18e8Smrg                        if (j > 3)
713c27c18e8Smrg                            j = 3;
714c27c18e8Smrg                        switch (j) {
715c27c18e8Smrg                            case 3:
716c27c18e8Smrg                                v->valuators[i + 2] = xev->valuator2;
717c27c18e8Smrg                            case 2:
718c27c18e8Smrg                                v->valuators[i + 1] = xev->valuator1;
719c27c18e8Smrg                            case 1:
720c27c18e8Smrg                                v->valuators[i + 0] = xev->valuator0;
721c27c18e8Smrg                        }
722c27c18e8Smrg                        v->num_valuators += j;
723c27c18e8Smrg
724c27c18e8Smrg                    }
725c27c18e8Smrg                    *re = *save;
726c27c18e8Smrg                    return (ENQUEUE_EVENT);
727c27c18e8Smrg                }
728c27c18e8Smrg                break;
729c27c18e8Smrg            case XI_DeviceFocusIn:
730c27c18e8Smrg            case XI_DeviceFocusOut:
731c27c18e8Smrg                {
732c27c18e8Smrg                    register XDeviceFocusChangeEvent *ev = (XDeviceFocusChangeEvent *) re;
733c27c18e8Smrg                    deviceFocus *fev = (deviceFocus *) event;
734c27c18e8Smrg
735c27c18e8Smrg                    *ev = *((XDeviceFocusChangeEvent *) save);
736c27c18e8Smrg                    ev->window = fev->window;
737c27c18e8Smrg                    ev->time = fev->time;
738c27c18e8Smrg                    ev->mode = fev->mode;
739c27c18e8Smrg                    ev->detail = fev->detail;
740c27c18e8Smrg                    ev->deviceid = fev->deviceid & DEVICE_BITS;
741c27c18e8Smrg                    return (ENQUEUE_EVENT);
742c27c18e8Smrg                }
743c27c18e8Smrg                break;
744c27c18e8Smrg            case XI_DeviceStateNotify:
745c27c18e8Smrg                {
746f1ee322dSmrg                    int j;
747c27c18e8Smrg                    XDeviceStateNotifyEvent *stev = (XDeviceStateNotifyEvent *) save;
748c27c18e8Smrg                    deviceStateNotify *sev = (deviceStateNotify *) event;
749c27c18e8Smrg                    char *data;
750c27c18e8Smrg
751c27c18e8Smrg                    stev->window = None;
752c27c18e8Smrg                    stev->deviceid = sev->deviceid & DEVICE_BITS;
753c27c18e8Smrg                    stev->time = sev->time;
754c27c18e8Smrg                    stev->num_classes = Ones((Mask) sev->classes_reported & InputClassBits);
755c27c18e8Smrg                    data = (char *)&stev->data[0];
756c27c18e8Smrg                    if (sev->classes_reported & (1 << KeyClass)) {
757c27c18e8Smrg                        register XKeyStatus *kstev = (XKeyStatus *) data;
758c27c18e8Smrg
759c27c18e8Smrg                        kstev->class = KeyClass;
760c27c18e8Smrg                        kstev->length = sizeof(XKeyStatus);
761c27c18e8Smrg                        kstev->num_keys = sev->num_keys;
762c27c18e8Smrg                        memcpy((char *)&kstev->keys[0], (char *)&sev->keys[0], 4);
763c27c18e8Smrg                        data += sizeof(XKeyStatus);
764c27c18e8Smrg                    }
765c27c18e8Smrg                    if (sev->classes_reported & (1 << ButtonClass)) {
766c27c18e8Smrg                        register XButtonStatus *bev = (XButtonStatus *) data;
767c27c18e8Smrg
768c27c18e8Smrg                        bev->class = ButtonClass;
769c27c18e8Smrg                        bev->length = sizeof(XButtonStatus);
770c27c18e8Smrg                        bev->num_buttons = sev->num_buttons;
771c27c18e8Smrg                        memcpy((char *)bev->buttons, (char *)sev->buttons, 4);
772c27c18e8Smrg                        data += sizeof(XButtonStatus);
773c27c18e8Smrg                    }
774c27c18e8Smrg                    if (sev->classes_reported & (1 << ValuatorClass)) {
775c27c18e8Smrg                        register XValuatorStatus *vev = (XValuatorStatus *) data;
776c27c18e8Smrg
777c27c18e8Smrg                        vev->class = ValuatorClass;
778c27c18e8Smrg                        vev->length = sizeof(XValuatorStatus);
779c27c18e8Smrg                        vev->num_valuators = sev->num_valuators;
780c27c18e8Smrg                        vev->mode = sev->classes_reported >> ModeBitsShift;
781c27c18e8Smrg                        j = sev->num_valuators;
782c27c18e8Smrg                        if (j > 3)
783c27c18e8Smrg                            j = 3;
784c27c18e8Smrg                        switch (j) {
785c27c18e8Smrg                            case 3:
786c27c18e8Smrg                                vev->valuators[2] = sev->valuator2;
787c27c18e8Smrg                            case 2:
788c27c18e8Smrg                                vev->valuators[1] = sev->valuator1;
789c27c18e8Smrg                            case 1:
790c27c18e8Smrg                                vev->valuators[0] = sev->valuator0;
791c27c18e8Smrg                        }
792c27c18e8Smrg                        data += sizeof(XValuatorStatus);
793c27c18e8Smrg                    }
794c27c18e8Smrg                    if (sev->deviceid & MORE_EVENTS)
795c27c18e8Smrg                        return (DONT_ENQUEUE);
796c27c18e8Smrg                    else {
797c27c18e8Smrg                        *re = *save;
798c27c18e8Smrg                        return (ENQUEUE_EVENT);
799c27c18e8Smrg                    }
800c27c18e8Smrg                }
801c27c18e8Smrg                break;
802c27c18e8Smrg            case XI_DeviceKeystateNotify:
803c27c18e8Smrg                {
804c27c18e8Smrg                    int i;
805c27c18e8Smrg                    XInputClass *anyclass;
806c27c18e8Smrg                    register XKeyStatus *kv;
807c27c18e8Smrg                    deviceKeyStateNotify *ksev = (deviceKeyStateNotify *) event;
808c27c18e8Smrg                    XDeviceStateNotifyEvent *kstev = (XDeviceStateNotifyEvent *) save;
809c27c18e8Smrg
810c27c18e8Smrg                    anyclass = (XInputClass *) & kstev->data[0];
811c27c18e8Smrg                    for (i = 0; i < kstev->num_classes; i++)
812c27c18e8Smrg                        if (anyclass->class == KeyClass)
813c27c18e8Smrg                            break;
814c27c18e8Smrg                        else
815c27c18e8Smrg                            anyclass = (XInputClass *) ((char *)anyclass +
816c27c18e8Smrg                                    anyclass->length);
817c27c18e8Smrg
818c27c18e8Smrg                    kv = (XKeyStatus *) anyclass;
819c27c18e8Smrg                    kv->num_keys = 256;
820c27c18e8Smrg                    memcpy((char *)&kv->keys[4], (char *)ksev->keys, 28);
821c27c18e8Smrg                    if (ksev->deviceid & MORE_EVENTS)
822c27c18e8Smrg                        return (DONT_ENQUEUE);
823c27c18e8Smrg                    else {
824c27c18e8Smrg                        *re = *save;
825c27c18e8Smrg                        return (ENQUEUE_EVENT);
826c27c18e8Smrg                    }
827c27c18e8Smrg                }
828c27c18e8Smrg                break;
829c27c18e8Smrg            case XI_DeviceButtonstateNotify:
830c27c18e8Smrg                {
831c27c18e8Smrg                    int i;
832c27c18e8Smrg                    XInputClass *anyclass;
833c27c18e8Smrg                    register XButtonStatus *bv;
834c27c18e8Smrg                    deviceButtonStateNotify *bsev = (deviceButtonStateNotify *) event;
835c27c18e8Smrg                    XDeviceStateNotifyEvent *bstev = (XDeviceStateNotifyEvent *) save;
836c27c18e8Smrg
837c27c18e8Smrg                    anyclass = (XInputClass *) & bstev->data[0];
838c27c18e8Smrg                    for (i = 0; i < bstev->num_classes; i++)
839c27c18e8Smrg                        if (anyclass->class == ButtonClass)
840c27c18e8Smrg                            break;
841c27c18e8Smrg                        else
842c27c18e8Smrg                            anyclass = (XInputClass *) ((char *)anyclass +
843c27c18e8Smrg                                    anyclass->length);
844c27c18e8Smrg
845c27c18e8Smrg                    bv = (XButtonStatus *) anyclass;
846c27c18e8Smrg                    bv->num_buttons = 256;
847c27c18e8Smrg                    memcpy((char *)&bv->buttons[4], (char *)bsev->buttons, 28);
848c27c18e8Smrg                    if (bsev->deviceid & MORE_EVENTS)
849c27c18e8Smrg                        return (DONT_ENQUEUE);
850c27c18e8Smrg                    else {
851c27c18e8Smrg                        *re = *save;
852c27c18e8Smrg                        return (ENQUEUE_EVENT);
853c27c18e8Smrg                    }
854c27c18e8Smrg                }
855c27c18e8Smrg                break;
856c27c18e8Smrg            case XI_DeviceMappingNotify:
857c27c18e8Smrg                {
858c27c18e8Smrg                    register XDeviceMappingEvent *ev = (XDeviceMappingEvent *) re;
859c27c18e8Smrg                    deviceMappingNotify *ev2 = (deviceMappingNotify *) event;
860c27c18e8Smrg
861c27c18e8Smrg                    *ev = *((XDeviceMappingEvent *) save);
862c27c18e8Smrg                    ev->window = 0;
863c27c18e8Smrg                    ev->first_keycode = ev2->firstKeyCode;
864c27c18e8Smrg                    ev->request = ev2->request;
865c27c18e8Smrg                    ev->count = ev2->count;
866c27c18e8Smrg                    ev->time = ev2->time;
867c27c18e8Smrg                    ev->deviceid = ev2->deviceid & DEVICE_BITS;
868c27c18e8Smrg                    return (ENQUEUE_EVENT);
869c27c18e8Smrg                }
870c27c18e8Smrg                break;
871c27c18e8Smrg            case XI_ChangeDeviceNotify:
872c27c18e8Smrg                {
873c27c18e8Smrg                    register XChangeDeviceNotifyEvent *ev = (XChangeDeviceNotifyEvent *) re;
874c27c18e8Smrg                    changeDeviceNotify *ev2 = (changeDeviceNotify *) event;
875c27c18e8Smrg
876c27c18e8Smrg                    *ev = *((XChangeDeviceNotifyEvent *) save);
877c27c18e8Smrg                    ev->window = 0;
878c27c18e8Smrg                    ev->request = ev2->request;
879c27c18e8Smrg                    ev->time = ev2->time;
880c27c18e8Smrg                    ev->deviceid = ev2->deviceid & DEVICE_BITS;
881c27c18e8Smrg                    return (ENQUEUE_EVENT);
882c27c18e8Smrg                }
883c27c18e8Smrg                break;
884c27c18e8Smrg
885c27c18e8Smrg            case XI_DevicePresenceNotify:
886c27c18e8Smrg                {
887c27c18e8Smrg                    XDevicePresenceNotifyEvent *ev = (XDevicePresenceNotifyEvent *) re;
888c27c18e8Smrg                    devicePresenceNotify *ev2 = (devicePresenceNotify *) event;
889c27c18e8Smrg
890c27c18e8Smrg                    *ev = *(XDevicePresenceNotifyEvent *) save;
891c27c18e8Smrg                    ev->window = 0;
892c27c18e8Smrg                    ev->time = ev2->time;
893c27c18e8Smrg                    ev->devchange = ev2->devchange;
894c27c18e8Smrg                    ev->deviceid = ev2->deviceid;
895c27c18e8Smrg                    ev->control = ev2->control;
896c27c18e8Smrg                    return (ENQUEUE_EVENT);
897c27c18e8Smrg                }
898c27c18e8Smrg                break;
899c27c18e8Smrg            case XI_DevicePropertyNotify:
900c27c18e8Smrg                {
901c27c18e8Smrg                    XDevicePropertyNotifyEvent* ev = (XDevicePropertyNotifyEvent*)re;
902c27c18e8Smrg                    devicePropertyNotify *ev2 = (devicePropertyNotify*)event;
903c27c18e8Smrg
904c27c18e8Smrg                    *ev = *(XDevicePropertyNotifyEvent*)save;
905c27c18e8Smrg                    ev->time = ev2->time;
906c27c18e8Smrg                    ev->deviceid = ev2->deviceid;
907c27c18e8Smrg                    ev->atom = ev2->atom;
908c27c18e8Smrg                    ev->state = ev2->state;
909c27c18e8Smrg                    return ENQUEUE_EVENT;
910c27c18e8Smrg                }
911c27c18e8Smrg                break;
912c27c18e8Smrg            default:
913c27c18e8Smrg                printf("XInputWireToEvent: UNKNOWN WIRE EVENT! type=%d\n", type);
914c27c18e8Smrg                break;
915c27c18e8Smrg        }
916c43cc173Smrg    }
917c27c18e8Smrg    return (DONT_ENQUEUE);
918c27c18e8Smrg}
919c27c18e8Smrg
920c27c18e8Smrgstatic void xge_copy_to_cookie(xGenericEvent* ev,
921c27c18e8Smrg                               XGenericEventCookie *cookie)
922c27c18e8Smrg{
923c27c18e8Smrg    cookie->type = ev->type;
924c27c18e8Smrg    cookie->evtype = ev->evtype;
925c27c18e8Smrg    cookie->extension = ev->extension;
926c27c18e8Smrg}
927c27c18e8Smrg
928c27c18e8Smrgstatic Bool
929c27c18e8SmrgXInputWireToCookie(
930c27c18e8Smrg    Display	*dpy,
931c27c18e8Smrg    XGenericEventCookie *cookie,
932c27c18e8Smrg    xEvent	*event)
933c27c18e8Smrg{
934c27c18e8Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
935c27c18e8Smrg    XEvent *save = (XEvent *) info->data;
936c27c18e8Smrg    xGenericEvent* ge = (xGenericEvent*)event;
937c27c18e8Smrg
938c27c18e8Smrg    if (ge->extension != info->codes->major_opcode)
939c43cc173Smrg    {
940c27c18e8Smrg        printf("XInputWireToCookie: wrong extension opcode %d\n",
941c27c18e8Smrg                ge->extension);
942c27c18e8Smrg        return DONT_ENQUEUE;
943c43cc173Smrg    }
944c27c18e8Smrg
945c27c18e8Smrg    *save = emptyevent;
946c27c18e8Smrg    save->type = event->u.u.type;
947c27c18e8Smrg    ((XAnyEvent*)save)->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
948c27c18e8Smrg    ((XAnyEvent*)save)->send_event = ((event->u.u.type & 0x80) != 0);
949c27c18e8Smrg    ((XAnyEvent*)save)->display = dpy;
950c27c18e8Smrg
951c27c18e8Smrg    xge_copy_to_cookie((xGenericEvent*)event, (XGenericEventCookie*)save);
952c27c18e8Smrg    switch(ge->evtype)
953c43cc173Smrg    {
954c27c18e8Smrg        case XI_Motion:
955c27c18e8Smrg        case XI_ButtonPress:
956c27c18e8Smrg        case XI_ButtonRelease:
957c27c18e8Smrg        case XI_KeyPress:
958c27c18e8Smrg        case XI_KeyRelease:
959f1ee322dSmrg        case XI_TouchBegin:
960f1ee322dSmrg        case XI_TouchUpdate:
961f1ee322dSmrg        case XI_TouchEnd:
962c27c18e8Smrg            *cookie = *(XGenericEventCookie*)save;
963c27c18e8Smrg            if (!wireToDeviceEvent((xXIDeviceEvent*)event, cookie))
964c27c18e8Smrg            {
965c27c18e8Smrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
966c27c18e8Smrg                        ge->evtype);
967c27c18e8Smrg                break;
968c27c18e8Smrg            }
969c27c18e8Smrg            return ENQUEUE_EVENT;
970c27c18e8Smrg        case XI_DeviceChanged:
971c27c18e8Smrg            *cookie = *(XGenericEventCookie*)save;
972c27c18e8Smrg            if (!wireToDeviceChangedEvent((xXIDeviceChangedEvent*)event, cookie))
973c27c18e8Smrg            {
974c27c18e8Smrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
975c27c18e8Smrg                        ge->evtype);
976c27c18e8Smrg                break;
977c27c18e8Smrg            }
978c27c18e8Smrg            return ENQUEUE_EVENT;
979c27c18e8Smrg        case XI_HierarchyChanged:
980c27c18e8Smrg            *cookie = *(XGenericEventCookie*)save;
981c27c18e8Smrg            if (!wireToHierarchyChangedEvent((xXIHierarchyEvent*)event, cookie))
982c27c18e8Smrg            {
983c27c18e8Smrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
984c27c18e8Smrg                        ge->evtype);
985c27c18e8Smrg                break;
986c27c18e8Smrg            }
987c27c18e8Smrg            return ENQUEUE_EVENT;
988f1ee322dSmrg        case XI_TouchOwnership:
989f1ee322dSmrg            *cookie = *(XGenericEventCookie*)save;
990f1ee322dSmrg            if (!wireToTouchOwnershipEvent((xXITouchOwnershipEvent*)event,
991f1ee322dSmrg                                           cookie))
992f1ee322dSmrg            {
993f1ee322dSmrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
994f1ee322dSmrg                        ge->evtype);
995f1ee322dSmrg                break;
996f1ee322dSmrg            }
997f1ee322dSmrg            return ENQUEUE_EVENT;
998c27c18e8Smrg
999c27c18e8Smrg        case XI_RawKeyPress:
1000c27c18e8Smrg        case XI_RawKeyRelease:
1001c27c18e8Smrg        case XI_RawButtonPress:
1002c27c18e8Smrg        case XI_RawButtonRelease:
1003c27c18e8Smrg        case XI_RawMotion:
1004f1ee322dSmrg        case XI_RawTouchBegin:
1005f1ee322dSmrg        case XI_RawTouchUpdate:
1006f1ee322dSmrg        case XI_RawTouchEnd:
1007c27c18e8Smrg            *cookie = *(XGenericEventCookie*)save;
1008f1ee322dSmrg            if (!wireToRawEvent(info, (xXIRawEvent*)event, cookie))
1009c27c18e8Smrg            {
1010c27c18e8Smrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
1011c27c18e8Smrg                        ge->evtype);
1012c27c18e8Smrg                break;
1013c27c18e8Smrg            }
1014c27c18e8Smrg            return ENQUEUE_EVENT;
1015c27c18e8Smrg        case XI_Enter:
1016c27c18e8Smrg        case XI_Leave:
1017c27c18e8Smrg        case XI_FocusIn:
1018c27c18e8Smrg        case XI_FocusOut:
1019c27c18e8Smrg            *cookie = *(XGenericEventCookie*)save;
1020c27c18e8Smrg            if (!wireToEnterLeave((xXIEnterEvent*)event, cookie))
1021c27c18e8Smrg            {
1022c27c18e8Smrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
1023c27c18e8Smrg                        ge->evtype);
1024c27c18e8Smrg                break;
1025c27c18e8Smrg            }
1026c27c18e8Smrg            return ENQUEUE_EVENT;
1027c27c18e8Smrg        case XI_PropertyEvent:
1028c27c18e8Smrg            *cookie = *(XGenericEventCookie*)save;
1029c27c18e8Smrg            if (!wireToPropertyEvent((xXIPropertyEvent*)event, cookie))
1030c27c18e8Smrg            {
1031c27c18e8Smrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
1032c27c18e8Smrg                        ge->evtype);
1033c27c18e8Smrg                break;
1034c27c18e8Smrg            }
1035c27c18e8Smrg            return ENQUEUE_EVENT;
1036f1ee322dSmrg        case XI_BarrierHit:
1037f1ee322dSmrg        case XI_BarrierLeave:
1038f1ee322dSmrg            *cookie = *(XGenericEventCookie*)save;
1039f1ee322dSmrg            if (!wireToBarrierEvent((xXIBarrierEvent*)event, cookie))
1040f1ee322dSmrg            {
1041f1ee322dSmrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
1042f1ee322dSmrg                        ge->evtype);
1043f1ee322dSmrg                break;
1044f1ee322dSmrg            }
1045f1ee322dSmrg            return ENQUEUE_EVENT;
104687404ef7Smrg        case XI_GesturePinchBegin:
104787404ef7Smrg        case XI_GesturePinchUpdate:
104887404ef7Smrg        case XI_GesturePinchEnd:
104987404ef7Smrg            *cookie = *(XGenericEventCookie*)save;
105087404ef7Smrg            if (!wireToPinchEvent((xXIGesturePinchEvent*)event, cookie))
105187404ef7Smrg            {
105287404ef7Smrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
105387404ef7Smrg                        ge->evtype);
105487404ef7Smrg                break;
105587404ef7Smrg            }
105687404ef7Smrg            return ENQUEUE_EVENT;
105787404ef7Smrg        case XI_GestureSwipeBegin:
105887404ef7Smrg        case XI_GestureSwipeUpdate:
105987404ef7Smrg        case XI_GestureSwipeEnd:
106087404ef7Smrg            *cookie = *(XGenericEventCookie*)save;
106187404ef7Smrg            if (!wireToSwipeEvent((xXIGestureSwipeEvent*)event, cookie))
106287404ef7Smrg            {
106387404ef7Smrg                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
106487404ef7Smrg                        ge->evtype);
106587404ef7Smrg                break;
106687404ef7Smrg            }
106787404ef7Smrg            return ENQUEUE_EVENT;
1068c27c18e8Smrg        default:
1069c27c18e8Smrg            printf("XInputWireToCookie: Unknown generic event. type %d\n", ge->evtype);
1070c27c18e8Smrg
1071c43cc173Smrg    }
1072c27c18e8Smrg    return DONT_ENQUEUE;
1073c27c18e8Smrg}
1074c27c18e8Smrg
1075c27c18e8Smrg/**
1076c27c18e8Smrg * Calculate length in bytes needed for the device event with the given
1077c27c18e8Smrg * button mask length, valuator mask length + valuator mask. All parameters
1078c27c18e8Smrg * in bytes.
1079c27c18e8Smrg */
1080c27c18e8Smrgstatic inline int
1081c27c18e8SmrgsizeDeviceEvent(int buttons_len, int valuators_len,
1082c27c18e8Smrg                unsigned char *valuators_mask)
1083c27c18e8Smrg{
1084c27c18e8Smrg    int len;
1085c27c18e8Smrg
1086c27c18e8Smrg    len = sizeof(XIDeviceEvent);
1087c27c18e8Smrg    len += sizeof(XIButtonState) + buttons_len;
1088c27c18e8Smrg    len += sizeof(XIValuatorState) + valuators_len;
1089c27c18e8Smrg    len += count_bits(valuators_mask, valuators_len) * sizeof(double);
1090c27c18e8Smrg    len += sizeof(XIModifierState) + sizeof(XIGroupState);
1091c27c18e8Smrg
1092c27c18e8Smrg    return len;
1093c27c18e8Smrg}
1094c27c18e8Smrg
1095f1ee322dSmrg/* Return the size with added padding so next element would be
1096f1ee322dSmrg   double-aligned unless the architecture is known to allow unaligned
1097f1ee322dSmrg   data accesses.  Not doing this can cause a bus error on
109887404ef7Smrg   MIPS N32. */
1099f1ee322dSmrgstatic int
1100f1ee322dSmrgpad_to_double(int size)
1101f1ee322dSmrg{
1102f1ee322dSmrg#if !defined(__i386__) && !defined(__sh__)
1103f1ee322dSmrg    if (size % sizeof(double) != 0)
1104f1ee322dSmrg        size += sizeof(double) - size % sizeof(double);
1105f1ee322dSmrg#endif
1106f1ee322dSmrg    return size;
1107f1ee322dSmrg}
1108f1ee322dSmrg
1109f1ee322dSmrg/**
1110f1ee322dSmrg * Set structure and atoms to size in bytes of XIButtonClassInfo, its
1111f1ee322dSmrg * button state mask and labels array.
1112f1ee322dSmrg */
1113f1ee322dSmrgstatic void
1114f1ee322dSmrgsizeXIButtonClassType(int num_buttons, int* structure, int* state, int* atoms)
1115f1ee322dSmrg{
1116f1ee322dSmrg    int size;
1117f1ee322dSmrg    int labels;
1118f1ee322dSmrg
1119f1ee322dSmrg    *structure = pad_to_double(sizeof(XIButtonClassInfo));
1120f1ee322dSmrg    size = ((((num_buttons + 7)/8) + 3)/4);
1121f1ee322dSmrg
1122f1ee322dSmrg    /* Force mask alignment with longs to avoid unaligned
1123f1ee322dSmrg     * access when accessing the atoms. */
1124f1ee322dSmrg    *state = pad_to_double(size * 4);
1125f1ee322dSmrg    labels = num_buttons * sizeof(Atom);
1126f1ee322dSmrg
1127f1ee322dSmrg    /* Force mask alignment with longs to avoid
1128f1ee322dSmrg     * unaligned access when accessing the atoms. */
1129f1ee322dSmrg    labels += ((((num_buttons + 7)/8) + 3)/4) * sizeof(Atom);
1130f1ee322dSmrg    *atoms = pad_to_double(labels);
1131f1ee322dSmrg}
1132f1ee322dSmrg
1133f1ee322dSmrg/**
1134f1ee322dSmrg * Set structure and keycodes to size in bytes of XIKeyClassInfo and
1135f1ee322dSmrg * its keycodes array.
1136f1ee322dSmrg */
1137f1ee322dSmrgstatic void
1138f1ee322dSmrgsizeXIKeyClassType(int num_keycodes, int* structure, int* keycodes)
1139f1ee322dSmrg{
1140f1ee322dSmrg    *structure = pad_to_double(sizeof(XIKeyClassInfo));
1141f1ee322dSmrg    *keycodes = pad_to_double(num_keycodes * sizeof(int));
1142f1ee322dSmrg}
1143f1ee322dSmrg
1144c27c18e8Smrg/**
1145c27c18e8Smrg * Return the size in bytes required to store the matching class type
1146c27c18e8Smrg * num_elements is num_buttons for XIButtonClass or num_keycodes for
1147c27c18e8Smrg * XIKeyClass.
1148c27c18e8Smrg *
1149c27c18e8Smrg * Also used from copy_classes in XIQueryDevice.c
1150c27c18e8Smrg */
1151c27c18e8Smrgstatic int
1152c27c18e8SmrgsizeDeviceClassType(int type, int num_elements)
1153c27c18e8Smrg{
1154c27c18e8Smrg    int l = 0;
1155f1ee322dSmrg    int extra1 = 0;
1156f1ee322dSmrg    int extra2 = 0;
1157c27c18e8Smrg    switch(type)
1158c43cc173Smrg    {
1159c27c18e8Smrg        case XIButtonClass:
1160f1ee322dSmrg            sizeXIButtonClassType(num_elements, &l, &extra1, &extra2);
1161f1ee322dSmrg            l += extra1 + extra2;
1162c27c18e8Smrg            break;
1163c27c18e8Smrg        case XIKeyClass:
1164f1ee322dSmrg            sizeXIKeyClassType(num_elements, &l, &extra1);
1165f1ee322dSmrg            l += extra1;
1166c27c18e8Smrg            break;
1167c27c18e8Smrg        case XIValuatorClass:
1168f1ee322dSmrg            l = pad_to_double(sizeof(XIValuatorClassInfo));
1169f1ee322dSmrg            break;
1170f1ee322dSmrg        case XIScrollClass:
1171f1ee322dSmrg            l = pad_to_double(sizeof(XIScrollClassInfo));
1172f1ee322dSmrg            break;
1173f1ee322dSmrg        case XITouchClass:
1174f1ee322dSmrg            l = pad_to_double(sizeof(XITouchClassInfo));
1175c27c18e8Smrg            break;
117687404ef7Smrg        case XIGestureClass:
117787404ef7Smrg            l = pad_to_double(sizeof(XIGestureClassInfo));
117887404ef7Smrg            break;
1179c27c18e8Smrg        default:
1180c27c18e8Smrg            printf("sizeDeviceClassType: unknown type %d\n", type);
1181c27c18e8Smrg            break;
1182c43cc173Smrg    }
1183c27c18e8Smrg    return l;
1184c27c18e8Smrg}
1185c27c18e8Smrg
1186c27c18e8Smrgstatic Bool
1187c27c18e8SmrgcopyHierarchyEvent(XGenericEventCookie *cookie_in,
1188c27c18e8Smrg                   XGenericEventCookie *cookie_out)
1189c27c18e8Smrg{
1190c27c18e8Smrg    XIHierarchyEvent *in, *out;
1191c27c18e8Smrg    void *ptr;
1192c27c18e8Smrg
1193c27c18e8Smrg    in = cookie_in->data;
1194c27c18e8Smrg
1195c27c18e8Smrg    ptr = cookie_out->data = malloc(sizeof(XIHierarchyEvent) +
1196c27c18e8Smrg                                    in->num_info * sizeof(XIHierarchyInfo));
1197c27c18e8Smrg    if (!ptr)
1198c27c18e8Smrg        return False;
1199c27c18e8Smrg
1200c27c18e8Smrg    out = next_block(&ptr, sizeof(XIHierarchyEvent));
1201c27c18e8Smrg    *out = *in;
1202c27c18e8Smrg    out->info = next_block(&ptr, in->num_info * sizeof(XIHierarchyInfo));
1203c27c18e8Smrg    memcpy(out->info, in->info, in->num_info * sizeof(XIHierarchyInfo));
1204c27c18e8Smrg
1205c27c18e8Smrg    return True;
1206c27c18e8Smrg}
1207c27c18e8Smrg
1208c27c18e8Smrgstatic Bool
1209c27c18e8SmrgcopyDeviceChangedEvent(XGenericEventCookie *in_cookie,
1210c27c18e8Smrg                       XGenericEventCookie *out_cookie)
1211c27c18e8Smrg{
1212c27c18e8Smrg    int len, i;
1213c27c18e8Smrg    XIDeviceChangedEvent *in, *out;
1214c27c18e8Smrg    XIAnyClassInfo *any;
1215c27c18e8Smrg    void *ptr;
1216c27c18e8Smrg
1217c27c18e8Smrg    in = in_cookie->data;
1218c27c18e8Smrg
1219c27c18e8Smrg    len = sizeof(XIDeviceChangedEvent);
1220c27c18e8Smrg    len += in->num_classes * sizeof(XIAnyClassInfo*);
1221c27c18e8Smrg
1222c27c18e8Smrg    for (i = 0; i < in->num_classes; i++)
1223c43cc173Smrg    {
1224c27c18e8Smrg        any = in->classes[i];
1225c27c18e8Smrg        switch(any->type)
1226c27c18e8Smrg        {
1227c27c18e8Smrg            case XIButtonClass:
1228c27c18e8Smrg                len += sizeDeviceClassType(XIButtonClass,
1229c27c18e8Smrg                        ((XIButtonClassInfo*)any)->num_buttons);
1230c27c18e8Smrg                break;
1231c27c18e8Smrg            case XIKeyClass:
1232c27c18e8Smrg                len += sizeDeviceClassType(XIKeyClass,
1233c27c18e8Smrg                        ((XIKeyClassInfo*)any)->num_keycodes);
1234c27c18e8Smrg                break;
1235c27c18e8Smrg            case XIValuatorClass:
1236c27c18e8Smrg                len += sizeDeviceClassType(XIValuatorClass, 0);
1237c27c18e8Smrg                break;
1238f1ee322dSmrg            case XIScrollClass:
1239f1ee322dSmrg                len += sizeDeviceClassType(XIScrollClass, 0);
1240f1ee322dSmrg                break;
1241c27c18e8Smrg            default:
1242c27c18e8Smrg                printf("copyDeviceChangedEvent: unknown type %d\n",
1243c27c18e8Smrg                        any->type);
1244c27c18e8Smrg                break;
1245c27c18e8Smrg        }
1246c43cc173Smrg
1247c43cc173Smrg    }
1248c27c18e8Smrg
1249c27c18e8Smrg    ptr = out_cookie->data = malloc(len);
1250c27c18e8Smrg    if (!ptr)
1251c27c18e8Smrg        return False;
1252c27c18e8Smrg    out = next_block(&ptr, sizeof(XIDeviceChangedEvent));
1253c27c18e8Smrg    *out = *in;
1254c27c18e8Smrg
1255c27c18e8Smrg    out->classes = next_block(&ptr,
1256c27c18e8Smrg                              out->num_classes * sizeof(XIAnyClassInfo*));
1257c27c18e8Smrg
1258c27c18e8Smrg    for (i = 0; i < in->num_classes; i++)
1259c43cc173Smrg    {
1260c27c18e8Smrg        any = in->classes[i];
1261c27c18e8Smrg
1262c27c18e8Smrg        switch(any->type)
1263c27c18e8Smrg        {
1264c27c18e8Smrg            case XIButtonClass:
1265c27c18e8Smrg                {
1266f1ee322dSmrg                    int struct_size;
1267f1ee322dSmrg                    int state_size;
1268f1ee322dSmrg                    int labels_size;
1269c27c18e8Smrg                    XIButtonClassInfo *bin, *bout;
1270c27c18e8Smrg                    bin = (XIButtonClassInfo*)any;
1271f1ee322dSmrg                    sizeXIButtonClassType(bin->num_buttons, &struct_size,
1272f1ee322dSmrg                                          &state_size, &labels_size);
1273f1ee322dSmrg                    bout = next_block(&ptr, struct_size);
1274c27c18e8Smrg
1275c27c18e8Smrg                    *bout = *bin;
1276f1ee322dSmrg                    bout->state.mask = next_block(&ptr, state_size);
1277c27c18e8Smrg                    memcpy(bout->state.mask, bin->state.mask,
1278c27c18e8Smrg                            bout->state.mask_len);
1279c27c18e8Smrg
1280f1ee322dSmrg                    bout->labels = next_block(&ptr, labels_size);
1281c27c18e8Smrg                    memcpy(bout->labels, bin->labels, bout->num_buttons * sizeof(Atom));
1282c27c18e8Smrg                    out->classes[i] = (XIAnyClassInfo*)bout;
1283c27c18e8Smrg                    break;
1284c27c18e8Smrg                }
1285c27c18e8Smrg            case XIKeyClass:
1286c27c18e8Smrg                {
1287c27c18e8Smrg                    XIKeyClassInfo *kin, *kout;
1288f1ee322dSmrg                    int struct_size;
1289f1ee322dSmrg                    int keycodes_size;
1290c27c18e8Smrg                    kin = (XIKeyClassInfo*)any;
1291f1ee322dSmrg                    sizeXIKeyClassType(kin->num_keycodes, &struct_size,
1292f1ee322dSmrg                                       &keycodes_size);
1293c27c18e8Smrg
1294f1ee322dSmrg                    kout = next_block(&ptr, struct_size);
1295c27c18e8Smrg                    *kout = *kin;
1296f1ee322dSmrg                    kout->keycodes = next_block(&ptr, keycodes_size);
1297c27c18e8Smrg                    memcpy(kout->keycodes, kin->keycodes, kout->num_keycodes * sizeof(int));
1298c27c18e8Smrg                    out->classes[i] = (XIAnyClassInfo*)kout;
1299c27c18e8Smrg                    break;
1300c27c18e8Smrg                }
1301c27c18e8Smrg            case XIValuatorClass:
1302c27c18e8Smrg                {
1303c27c18e8Smrg                    XIValuatorClassInfo *vin, *vout;
1304c27c18e8Smrg                    vin = (XIValuatorClassInfo*)any;
1305f1ee322dSmrg                    vout = next_block(&ptr,
1306f1ee322dSmrg                                      sizeDeviceClassType(XIValuatorClass, 0));
1307c27c18e8Smrg                    *vout = *vin;
1308c27c18e8Smrg                    out->classes[i] = (XIAnyClassInfo*)vout;
1309c27c18e8Smrg                    break;
1310c27c18e8Smrg                }
1311f1ee322dSmrg            case XIScrollClass:
1312f1ee322dSmrg                {
1313f1ee322dSmrg                    XIScrollClassInfo *sin, *sout;
1314f1ee322dSmrg                    sin = (XIScrollClassInfo*)any;
1315f1ee322dSmrg                    sout = next_block(&ptr,
1316f1ee322dSmrg                                      sizeDeviceClassType(XIScrollClass, 0));
1317f1ee322dSmrg                    *sout = *sin;
1318f1ee322dSmrg                    out->classes[i] = (XIAnyClassInfo*)sout;
1319f1ee322dSmrg                    break;
1320f1ee322dSmrg                }
1321c27c18e8Smrg        }
1322c43cc173Smrg    }
1323c27c18e8Smrg
1324c27c18e8Smrg    return True;
1325c27c18e8Smrg}
1326c27c18e8Smrg
1327c27c18e8Smrgstatic Bool
1328c27c18e8SmrgcopyDeviceEvent(XGenericEventCookie *cookie_in,
1329c27c18e8Smrg                XGenericEventCookie *cookie_out)
1330c27c18e8Smrg{
1331c27c18e8Smrg    int len;
1332c27c18e8Smrg    XIDeviceEvent *in, *out;
1333c27c18e8Smrg    int bits; /* valuator bits */
1334c27c18e8Smrg    void *ptr;
1335c27c18e8Smrg
1336c27c18e8Smrg    in = cookie_in->data;
1337c27c18e8Smrg    bits = count_bits(in->valuators.mask, in->valuators.mask_len);
1338c27c18e8Smrg
1339c27c18e8Smrg    len = sizeDeviceEvent(in->buttons.mask_len, in->valuators.mask_len,
1340c27c18e8Smrg                          in->valuators.mask);
1341c27c18e8Smrg
1342c27c18e8Smrg    ptr = cookie_out->data = malloc(len);
1343c27c18e8Smrg    if (!ptr)
1344c27c18e8Smrg        return False;
1345c27c18e8Smrg
1346c27c18e8Smrg    out = next_block(&ptr, sizeof(XIDeviceEvent));
1347c27c18e8Smrg    *out = *in;
1348c27c18e8Smrg
1349c27c18e8Smrg    out->buttons.mask = next_block(&ptr, in->buttons.mask_len);
1350c27c18e8Smrg    memcpy(out->buttons.mask, in->buttons.mask,
1351c27c18e8Smrg           out->buttons.mask_len);
1352c27c18e8Smrg    out->valuators.mask = next_block(&ptr, in->valuators.mask_len);
1353c27c18e8Smrg    memcpy(out->valuators.mask, in->valuators.mask,
1354c27c18e8Smrg           out->valuators.mask_len);
1355c27c18e8Smrg    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1356c27c18e8Smrg    memcpy(out->valuators.values, in->valuators.values,
1357c27c18e8Smrg           bits * sizeof(double));
1358c27c18e8Smrg
1359c27c18e8Smrg    return True;
1360c27c18e8Smrg}
1361c27c18e8Smrg
1362c27c18e8Smrgstatic Bool
1363c27c18e8SmrgcopyEnterEvent(XGenericEventCookie *cookie_in,
1364c27c18e8Smrg               XGenericEventCookie *cookie_out)
1365c27c18e8Smrg{
1366c27c18e8Smrg    int len;
1367c27c18e8Smrg    XIEnterEvent *in, *out;
1368c27c18e8Smrg    void *ptr;
1369c27c18e8Smrg
1370c27c18e8Smrg    in = cookie_in->data;
1371c27c18e8Smrg
1372c27c18e8Smrg    len = sizeof(XIEnterEvent) + in->buttons.mask_len;
1373c27c18e8Smrg
1374c27c18e8Smrg    ptr = cookie_out->data = malloc(len);
1375c27c18e8Smrg    if (!ptr)
1376c27c18e8Smrg        return False;
1377c27c18e8Smrg
1378c27c18e8Smrg    out = next_block(&ptr, sizeof(XIEnterEvent));
1379c27c18e8Smrg    *out = *in;
1380c27c18e8Smrg
1381c27c18e8Smrg    out->buttons.mask = next_block(&ptr, in->buttons.mask_len);
1382c27c18e8Smrg    memcpy(out->buttons.mask, in->buttons.mask, out->buttons.mask_len);
1383c27c18e8Smrg
1384c27c18e8Smrg    return True;
1385c27c18e8Smrg}
1386c27c18e8Smrg
1387c27c18e8Smrgstatic Bool
1388c27c18e8SmrgcopyPropertyEvent(XGenericEventCookie *cookie_in,
1389c27c18e8Smrg                  XGenericEventCookie *cookie_out)
1390c27c18e8Smrg{
1391c27c18e8Smrg    XIPropertyEvent *in, *out;
1392c27c18e8Smrg
1393c27c18e8Smrg    in = cookie_in->data;
1394c27c18e8Smrg
1395c27c18e8Smrg    out = cookie_out->data = malloc(sizeof(XIPropertyEvent));
1396c27c18e8Smrg    if (!out)
1397c27c18e8Smrg        return False;
1398c27c18e8Smrg
1399c27c18e8Smrg    *out = *in;
1400c27c18e8Smrg    return True;
1401c27c18e8Smrg}
1402c27c18e8Smrg
1403f1ee322dSmrgstatic Bool
1404f1ee322dSmrgcopyTouchOwnershipEvent(XGenericEventCookie *cookie_in,
1405f1ee322dSmrg                        XGenericEventCookie *cookie_out)
1406f1ee322dSmrg{
1407f1ee322dSmrg    XITouchOwnershipEvent *in, *out;
1408f1ee322dSmrg
1409f1ee322dSmrg    in = cookie_in->data;
1410f1ee322dSmrg
1411f1ee322dSmrg    out = cookie_out->data = malloc(sizeof(XITouchOwnershipEvent));
1412f1ee322dSmrg    if (!out)
1413f1ee322dSmrg        return False;
1414f1ee322dSmrg
1415f1ee322dSmrg    *out = *in;
1416f1ee322dSmrg    return True;
1417f1ee322dSmrg}
1418f1ee322dSmrg
1419c27c18e8Smrgstatic Bool
1420c27c18e8SmrgcopyRawEvent(XGenericEventCookie *cookie_in,
1421c27c18e8Smrg             XGenericEventCookie *cookie_out)
1422c27c18e8Smrg{
1423c27c18e8Smrg    XIRawEvent *in, *out;
1424c27c18e8Smrg    void *ptr;
1425c27c18e8Smrg    int len;
1426c27c18e8Smrg    int bits;
1427c27c18e8Smrg
1428c27c18e8Smrg    in = cookie_in->data;
1429c27c18e8Smrg
1430c27c18e8Smrg    bits = count_bits(in->valuators.mask, in->valuators.mask_len);
1431c6b4a769Smrg    len = pad_to_double(sizeof(XIRawEvent))
1432c6b4a769Smrg        + pad_to_double(in->valuators.mask_len);
1433c27c18e8Smrg    len += bits * sizeof(double) * 2;
1434c27c18e8Smrg
1435b789ec8aSmrg    ptr = cookie_out->data = malloc(len);
1436c27c18e8Smrg    if (!ptr)
1437c27c18e8Smrg        return False;
1438c27c18e8Smrg
1439c6b4a769Smrg    out = next_block(&ptr, pad_to_double(sizeof(XIRawEvent)));
1440c27c18e8Smrg    *out = *in;
1441c6b4a769Smrg    out->valuators.mask
1442c6b4a769Smrg        = next_block(&ptr, pad_to_double(out->valuators.mask_len));
1443c27c18e8Smrg    memcpy(out->valuators.mask, in->valuators.mask, out->valuators.mask_len);
1444c27c18e8Smrg
1445c27c18e8Smrg    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1446c27c18e8Smrg    memcpy(out->valuators.values, in->valuators.values, bits * sizeof(double));
1447c27c18e8Smrg
1448c27c18e8Smrg    out->raw_values = next_block(&ptr, bits * sizeof(double));
1449c27c18e8Smrg    memcpy(out->raw_values, in->raw_values, bits * sizeof(double));
1450c27c18e8Smrg
1451c27c18e8Smrg    return True;
1452c27c18e8Smrg}
1453c27c18e8Smrg
1454f1ee322dSmrgstatic Bool
1455f1ee322dSmrgcopyBarrierEvent(XGenericEventCookie *in_cookie,
1456f1ee322dSmrg                 XGenericEventCookie *out_cookie)
1457f1ee322dSmrg{
1458f1ee322dSmrg    XIBarrierEvent *in, *out;
1459f1ee322dSmrg
1460f1ee322dSmrg    in = in_cookie->data;
1461f1ee322dSmrg
1462f1ee322dSmrg    out = out_cookie->data = calloc(1, sizeof(XIBarrierEvent));
1463f1ee322dSmrg    if (!out)
1464f1ee322dSmrg        return False;
1465f1ee322dSmrg    *out = *in;
1466c27c18e8Smrg
1467f1ee322dSmrg    return True;
1468f1ee322dSmrg}
1469c27c18e8Smrg
147087404ef7Smrg
147187404ef7Smrgstatic Bool
147287404ef7SmrgcopyGesturePinchEvent(XGenericEventCookie *cookie_in,
147387404ef7Smrg                      XGenericEventCookie *cookie_out)
147487404ef7Smrg{
147587404ef7Smrg    XIGesturePinchEvent *in, *out;
147687404ef7Smrg
147787404ef7Smrg    in = cookie_in->data;
147887404ef7Smrg
147987404ef7Smrg    out = cookie_out->data = malloc(sizeof(XIGesturePinchEvent));
148087404ef7Smrg    if (!out)
148187404ef7Smrg        return False;
148287404ef7Smrg
148387404ef7Smrg    *out = *in;
148487404ef7Smrg
148587404ef7Smrg    return True;
148687404ef7Smrg}
148787404ef7Smrg
148887404ef7Smrgstatic Bool
148987404ef7SmrgcopyGestureSwipeEvent(XGenericEventCookie *cookie_in,
149087404ef7Smrg                      XGenericEventCookie *cookie_out)
149187404ef7Smrg{
149287404ef7Smrg    XIGestureSwipeEvent *in, *out;
149387404ef7Smrg
149487404ef7Smrg    in = cookie_in->data;
149587404ef7Smrg
149687404ef7Smrg    out = cookie_out->data = malloc(sizeof(XIGestureSwipeEvent));
149787404ef7Smrg    if (!out)
149887404ef7Smrg        return False;
149987404ef7Smrg
150087404ef7Smrg    *out = *in;
150187404ef7Smrg
150287404ef7Smrg    return True;
150387404ef7Smrg}
150487404ef7Smrg
1505c27c18e8Smrgstatic Bool
1506c27c18e8SmrgXInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
1507c27c18e8Smrg{
1508c27c18e8Smrg    int ret = True;
1509c27c18e8Smrg
1510c27c18e8Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
1511c27c18e8Smrg
1512c27c18e8Smrg    if (in->extension != info->codes->major_opcode)
1513c43cc173Smrg    {
1514c27c18e8Smrg        printf("XInputCopyCookie: wrong extension opcode %d\n",
1515c27c18e8Smrg                in->extension);
1516c27c18e8Smrg        return False;
1517c27c18e8Smrg    }
1518c27c18e8Smrg
1519c27c18e8Smrg    *out = *in;
1520c27c18e8Smrg    out->data = NULL;
1521c27c18e8Smrg    out->cookie = 0;
1522c27c18e8Smrg
1523c27c18e8Smrg    switch(in->evtype) {
1524c27c18e8Smrg        case XI_Motion:
1525c27c18e8Smrg        case XI_ButtonPress:
1526c27c18e8Smrg        case XI_ButtonRelease:
1527c27c18e8Smrg        case XI_KeyPress:
1528c27c18e8Smrg        case XI_KeyRelease:
1529f1ee322dSmrg        case XI_TouchBegin:
1530f1ee322dSmrg        case XI_TouchUpdate:
1531f1ee322dSmrg        case XI_TouchEnd:
1532c27c18e8Smrg            ret = copyDeviceEvent(in, out);
1533c27c18e8Smrg            break;
1534c27c18e8Smrg        case XI_DeviceChanged:
1535c27c18e8Smrg            ret = copyDeviceChangedEvent(in, out);
1536c27c18e8Smrg            break;
1537c27c18e8Smrg        case XI_HierarchyChanged:
1538c27c18e8Smrg            ret = copyHierarchyEvent(in, out);
1539c27c18e8Smrg            break;
1540c27c18e8Smrg        case XI_Enter:
1541c27c18e8Smrg        case XI_Leave:
1542c27c18e8Smrg        case XI_FocusIn:
1543c27c18e8Smrg        case XI_FocusOut:
1544c27c18e8Smrg            ret = copyEnterEvent(in, out);
1545c27c18e8Smrg            break;
1546c27c18e8Smrg        case XI_PropertyEvent:
1547c27c18e8Smrg            ret = copyPropertyEvent(in, out);
1548c27c18e8Smrg            break;
1549f1ee322dSmrg        case XI_TouchOwnership:
1550f1ee322dSmrg            ret = copyTouchOwnershipEvent(in, out);
1551f1ee322dSmrg            break;
1552c27c18e8Smrg        case XI_RawKeyPress:
1553c27c18e8Smrg        case XI_RawKeyRelease:
1554c27c18e8Smrg        case XI_RawButtonPress:
1555c27c18e8Smrg        case XI_RawButtonRelease:
1556c27c18e8Smrg        case XI_RawMotion:
1557f1ee322dSmrg        case XI_RawTouchBegin:
1558f1ee322dSmrg        case XI_RawTouchUpdate:
1559f1ee322dSmrg        case XI_RawTouchEnd:
1560c27c18e8Smrg            ret = copyRawEvent(in, out);
1561c27c18e8Smrg            break;
1562f1ee322dSmrg        case XI_BarrierHit:
1563f1ee322dSmrg        case XI_BarrierLeave:
1564f1ee322dSmrg            ret = copyBarrierEvent(in, out);
1565f1ee322dSmrg            break;
156687404ef7Smrg        case XI_GesturePinchBegin:
156787404ef7Smrg        case XI_GesturePinchUpdate:
156887404ef7Smrg        case XI_GesturePinchEnd:
156987404ef7Smrg            ret = copyGesturePinchEvent(in, out);
157087404ef7Smrg            break;
157187404ef7Smrg        case XI_GestureSwipeBegin:
157287404ef7Smrg        case XI_GestureSwipeUpdate:
157387404ef7Smrg        case XI_GestureSwipeEnd:
157487404ef7Smrg            ret = copyGestureSwipeEvent(in, out);
157587404ef7Smrg            break;
1576c27c18e8Smrg        default:
1577c27c18e8Smrg            printf("XInputCopyCookie: unknown evtype %d\n", in->evtype);
1578c27c18e8Smrg            ret = False;
1579c43cc173Smrg    }
1580c27c18e8Smrg
1581c27c18e8Smrg    if (!ret)
1582c27c18e8Smrg        printf("XInputCopyCookie: Failed to copy evtype %d", in->evtype);
1583c27c18e8Smrg    return ret;
1584c27c18e8Smrg}
1585c27c18e8Smrg
1586c27c18e8Smrgstatic int
1587c27c18e8SmrgwireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* cookie)
1588c27c18e8Smrg{
1589c27c18e8Smrg    int len, i;
1590c27c18e8Smrg    unsigned char *ptr;
1591c27c18e8Smrg    void *ptr_lib;
1592c27c18e8Smrg    FP3232 *values;
1593c27c18e8Smrg    XIDeviceEvent *out;
1594c27c18e8Smrg
1595c27c18e8Smrg    ptr = (unsigned char*)&in[1] + in->buttons_len * 4;
1596c27c18e8Smrg
1597c27c18e8Smrg    len = sizeDeviceEvent(in->buttons_len * 4, in->valuators_len * 4, ptr);
1598c27c18e8Smrg
1599c27c18e8Smrg    cookie->data = ptr_lib = malloc(len);
1600c6b4a769Smrg    if (!ptr_lib)
1601c6b4a769Smrg        return 0;
1602c27c18e8Smrg
1603c27c18e8Smrg    out = next_block(&ptr_lib, sizeof(XIDeviceEvent));
160489069ce9Smrg    out->display = cookie->display;
1605c27c18e8Smrg    out->type = in->type;
160644584a44Smrg    out->serial = cookie->serial;
1607c27c18e8Smrg    out->extension = in->extension;
1608c27c18e8Smrg    out->evtype = in->evtype;
1609c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
1610c27c18e8Smrg    out->time = in->time;
1611c27c18e8Smrg    out->deviceid = in->deviceid;
1612c27c18e8Smrg    out->sourceid = in->sourceid;
1613c27c18e8Smrg    out->detail = in->detail;
1614c27c18e8Smrg    out->root = in->root;
1615c27c18e8Smrg    out->event = in->event;
1616c27c18e8Smrg    out->child = in->child;
1617c27c18e8Smrg    out->root_x = FP1616toDBL(in->root_x);
1618c27c18e8Smrg    out->root_y = FP1616toDBL(in->root_y);
1619c27c18e8Smrg    out->event_x = FP1616toDBL(in->event_x);
1620c27c18e8Smrg    out->event_y = FP1616toDBL(in->event_y);
1621c27c18e8Smrg    out->flags = in->flags;
1622c27c18e8Smrg    out->mods.base = in->mods.base_mods;
1623c27c18e8Smrg    out->mods.locked = in->mods.locked_mods;
1624c27c18e8Smrg    out->mods.latched = in->mods.latched_mods;
1625c27c18e8Smrg    out->mods.effective = in->mods.effective_mods;
1626c27c18e8Smrg    out->group.base = in->group.base_group;
1627c27c18e8Smrg    out->group.locked = in->group.locked_group;
1628c27c18e8Smrg    out->group.latched = in->group.latched_group;
1629c27c18e8Smrg    out->group.effective = in->group.effective_group;
1630c27c18e8Smrg    out->buttons.mask_len = in->buttons_len * 4;
1631c27c18e8Smrg    out->valuators.mask_len = in->valuators_len * 4;
1632c27c18e8Smrg
1633c27c18e8Smrg    out->buttons.mask = next_block(&ptr_lib, out->buttons.mask_len);
1634c27c18e8Smrg
1635c27c18e8Smrg    /* buttons */
1636c27c18e8Smrg    ptr = (unsigned char*)&in[1];
1637c27c18e8Smrg    memcpy(out->buttons.mask, ptr, out->buttons.mask_len);
1638c27c18e8Smrg    ptr += in->buttons_len * 4;
1639c27c18e8Smrg
1640c27c18e8Smrg    /* valuators */
1641c27c18e8Smrg    out->valuators.mask = next_block(&ptr_lib, out->valuators.mask_len);
1642c27c18e8Smrg    memcpy(out->valuators.mask, ptr, out->valuators.mask_len);
1643c27c18e8Smrg    ptr += in->valuators_len * 4;
1644c27c18e8Smrg
1645c27c18e8Smrg    len = count_bits(out->valuators.mask, out->valuators.mask_len);
1646c27c18e8Smrg    out->valuators.values = next_block(&ptr_lib, len * sizeof(double));
1647c27c18e8Smrg
1648c27c18e8Smrg    values = (FP3232*)ptr;
1649c27c18e8Smrg    for (i = 0; i < len; i++, values++)
1650c43cc173Smrg    {
1651c27c18e8Smrg        out->valuators.values[i] = values->integral;
1652c27c18e8Smrg        out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1653c43cc173Smrg    }
1654c27c18e8Smrg
1655c27c18e8Smrg
1656c27c18e8Smrg    return 1;
1657c27c18e8Smrg}
1658c27c18e8Smrg
1659c27c18e8Smrg_X_HIDDEN int
1660c27c18e8Smrgsize_classes(xXIAnyInfo* from, int nclasses)
1661c27c18e8Smrg{
1662c27c18e8Smrg    int len, i;
1663c27c18e8Smrg    xXIAnyInfo *any_wire;
1664c27c18e8Smrg    char *ptr_wire;
1665c27c18e8Smrg
1666f1ee322dSmrg    /* len for to->classes */
1667f1ee322dSmrg    len = pad_to_double(nclasses * sizeof(XIAnyClassInfo*));
1668c27c18e8Smrg    ptr_wire = (char*)from;
1669c27c18e8Smrg    for (i = 0; i < nclasses; i++)
1670c43cc173Smrg    {
1671c27c18e8Smrg        int l = 0;
1672c27c18e8Smrg        any_wire = (xXIAnyInfo*)ptr_wire;
1673c27c18e8Smrg        switch(any_wire->type)
1674c27c18e8Smrg        {
1675c27c18e8Smrg            case XIButtonClass:
1676c27c18e8Smrg                l = sizeDeviceClassType(XIButtonClass,
1677c27c18e8Smrg                        ((xXIButtonInfo*)any_wire)->num_buttons);
1678c27c18e8Smrg                break;
1679c27c18e8Smrg            case XIKeyClass:
1680c27c18e8Smrg                l = sizeDeviceClassType(XIKeyClass,
1681c27c18e8Smrg                        ((xXIKeyInfo*)any_wire)->num_keycodes);
1682c27c18e8Smrg                break;
1683c27c18e8Smrg            case XIValuatorClass:
1684c27c18e8Smrg                l = sizeDeviceClassType(XIValuatorClass, 0);
1685c27c18e8Smrg                break;
1686f1ee322dSmrg            case XIScrollClass:
1687f1ee322dSmrg                l = sizeDeviceClassType(XIScrollClass, 0);
1688f1ee322dSmrg                break;
1689f1ee322dSmrg            case XITouchClass:
1690f1ee322dSmrg                l = sizeDeviceClassType(XITouchClass, 0);
1691f1ee322dSmrg                break;
169287404ef7Smrg            case XIGestureClass:
169387404ef7Smrg                l = sizeDeviceClassType(XIGestureClass, 0);
169487404ef7Smrg                break;
1695c27c18e8Smrg        }
1696c27c18e8Smrg
1697c27c18e8Smrg        len += l;
1698c27c18e8Smrg        ptr_wire += any_wire->length * 4;
1699c43cc173Smrg    }
1700c27c18e8Smrg
1701c27c18e8Smrg    return len;
1702c27c18e8Smrg}
1703c27c18e8Smrg
17044940c694Smrg#define FP3232_TO_DOUBLE(x) ((double) (x).integral + (double) (x).frac / (1ULL << 32))
17054940c694Smrg
1706c27c18e8Smrg/* Copy classes from any into to->classes and return the number of bytes
1707c27c18e8Smrg * copied. Memory layout of to->classes is
1708c27c18e8Smrg * [clsptr][clsptr][clsptr][classinfo][classinfo]...
1709c27c18e8Smrg *    |________|___________^
1710c27c18e8Smrg *             |______________________^
1711c27c18e8Smrg */
1712c27c18e8Smrg_X_HIDDEN int
1713f1ee322dSmrgcopy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
1714c27c18e8Smrg{
1715c27c18e8Smrg    XIAnyClassInfo *any_lib;
1716c27c18e8Smrg    xXIAnyInfo *any_wire;
1717c27c18e8Smrg    void *ptr_lib;
1718c27c18e8Smrg    char *ptr_wire;
1719c27c18e8Smrg    int i, len;
1720f1ee322dSmrg    int cls_idx = 0;
1721c27c18e8Smrg
1722c27c18e8Smrg    if (!to->classes)
1723c27c18e8Smrg        return -1;
1724c27c18e8Smrg
1725c27c18e8Smrg    ptr_wire = (char*)from;
1726c27c18e8Smrg    ptr_lib = to->classes;
1727f1ee322dSmrg    to->classes = next_block(&ptr_lib,
1728f1ee322dSmrg                             pad_to_double((*nclasses) * sizeof(XIAnyClassInfo*)));
1729f1ee322dSmrg    memset(to->classes, 0, (*nclasses) * sizeof(XIAnyClassInfo*));
1730c27c18e8Smrg    len = 0; /* count wire length */
1731c27c18e8Smrg
1732f1ee322dSmrg    for (i = 0; i < *nclasses; i++)
1733c43cc173Smrg    {
1734c27c18e8Smrg        any_lib = (XIAnyClassInfo*)ptr_lib;
1735c27c18e8Smrg        any_wire = (xXIAnyInfo*)ptr_wire;
1736c27c18e8Smrg
1737c27c18e8Smrg        switch(any_wire->type)
1738c27c18e8Smrg        {
1739c27c18e8Smrg            case XIButtonClass:
1740c27c18e8Smrg                {
1741c27c18e8Smrg                    XIButtonClassInfo *cls_lib;
1742c27c18e8Smrg                    xXIButtonInfo *cls_wire;
1743c27c18e8Smrg                    uint32_t *atoms;
1744c27c18e8Smrg                    int j;
1745f1ee322dSmrg                    int struct_size;
1746f1ee322dSmrg                    int state_size;
1747f1ee322dSmrg                    int labels_size;
1748f1ee322dSmrg                    int wire_mask_size;
1749c27c18e8Smrg
1750c27c18e8Smrg                    cls_wire = (xXIButtonInfo*)any_wire;
1751f1ee322dSmrg                    sizeXIButtonClassType(cls_wire->num_buttons,
1752f1ee322dSmrg                                          &struct_size, &state_size,
1753f1ee322dSmrg                                          &labels_size);
1754f1ee322dSmrg                    cls_lib = next_block(&ptr_lib, struct_size);
1755f1ee322dSmrg                    wire_mask_size = ((cls_wire->num_buttons + 7)/8 + 3)/4 * 4;
1756f1ee322dSmrg
1757f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1758f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1759c27c18e8Smrg                    cls_lib->num_buttons = cls_wire->num_buttons;
1760f1ee322dSmrg                    cls_lib->state.mask_len = state_size;
1761f1ee322dSmrg                    cls_lib->state.mask = next_block(&ptr_lib, state_size);
1762c27c18e8Smrg                    memcpy(cls_lib->state.mask, &cls_wire[1],
1763f1ee322dSmrg                           wire_mask_size);
1764f1ee322dSmrg                    if (state_size != wire_mask_size)
1765f1ee322dSmrg                        memset(&cls_lib->state.mask[wire_mask_size], 0,
1766f1ee322dSmrg                               state_size - wire_mask_size);
1767c27c18e8Smrg
1768f1ee322dSmrg                    cls_lib->labels = next_block(&ptr_lib, labels_size);
1769f1ee322dSmrg
1770f1ee322dSmrg                    atoms =(uint32_t*)((char*)&cls_wire[1] + wire_mask_size);
1771c27c18e8Smrg                    for (j = 0; j < cls_lib->num_buttons; j++)
1772c27c18e8Smrg                        cls_lib->labels[j] = *atoms++;
1773c27c18e8Smrg
1774f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1775c27c18e8Smrg                    break;
1776c27c18e8Smrg                }
1777c27c18e8Smrg            case XIKeyClass:
1778c27c18e8Smrg                {
1779c27c18e8Smrg                    XIKeyClassInfo *cls_lib;
1780c27c18e8Smrg                    xXIKeyInfo *cls_wire;
1781f1ee322dSmrg                    int struct_size;
1782f1ee322dSmrg                    int keycodes_size;
1783c27c18e8Smrg
1784c27c18e8Smrg                    cls_wire = (xXIKeyInfo*)any_wire;
1785f1ee322dSmrg                    sizeXIKeyClassType(cls_wire->num_keycodes,
1786f1ee322dSmrg                                       &struct_size, &keycodes_size);
1787f1ee322dSmrg                    cls_lib = next_block(&ptr_lib, struct_size);
1788c27c18e8Smrg
1789f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1790f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1791c27c18e8Smrg                    cls_lib->num_keycodes = cls_wire->num_keycodes;
1792f1ee322dSmrg                    cls_lib->keycodes = next_block(&ptr_lib, keycodes_size);
1793c27c18e8Smrg                    memcpy(cls_lib->keycodes, &cls_wire[1],
1794c27c18e8Smrg                            cls_lib->num_keycodes);
1795c27c18e8Smrg
1796f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1797c27c18e8Smrg                    break;
1798c27c18e8Smrg                }
1799c27c18e8Smrg            case XIValuatorClass:
1800c27c18e8Smrg                {
1801c27c18e8Smrg                    XIValuatorClassInfo *cls_lib;
1802c27c18e8Smrg                    xXIValuatorInfo *cls_wire;
1803c27c18e8Smrg
1804f1ee322dSmrg                    cls_lib =
1805f1ee322dSmrg                      next_block(&ptr_lib,
1806f1ee322dSmrg                                 sizeDeviceClassType(XIValuatorClass, 0));
1807c27c18e8Smrg                    cls_wire = (xXIValuatorInfo*)any_wire;
1808c27c18e8Smrg
1809f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1810f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1811c27c18e8Smrg                    cls_lib->number = cls_wire->number;
1812c27c18e8Smrg                    cls_lib->label  = cls_wire->label;
1813c27c18e8Smrg                    cls_lib->resolution = cls_wire->resolution;
18144940c694Smrg                    cls_lib->min        = FP3232_TO_DOUBLE(cls_wire->min);
18154940c694Smrg                    cls_lib->max        = FP3232_TO_DOUBLE(cls_wire->max);
18164940c694Smrg                    cls_lib->value      = FP3232_TO_DOUBLE(cls_wire->value);
1817c27c18e8Smrg                    cls_lib->mode       = cls_wire->mode;
1818c27c18e8Smrg
1819f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1820f1ee322dSmrg                }
1821f1ee322dSmrg                break;
1822f1ee322dSmrg            case XIScrollClass:
1823f1ee322dSmrg                {
1824f1ee322dSmrg                    XIScrollClassInfo *cls_lib;
1825f1ee322dSmrg                    xXIScrollInfo *cls_wire;
1826f1ee322dSmrg
1827f1ee322dSmrg                    cls_lib =
1828f1ee322dSmrg                      next_block(&ptr_lib,
1829f1ee322dSmrg                                 sizeDeviceClassType(XIScrollClass, 0));
1830f1ee322dSmrg                    cls_wire = (xXIScrollInfo*)any_wire;
1831f1ee322dSmrg
1832f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1833f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1834f1ee322dSmrg                    cls_lib->number     = cls_wire->number;
1835f1ee322dSmrg                    cls_lib->scroll_type= cls_wire->scroll_type;
1836f1ee322dSmrg                    cls_lib->flags      = cls_wire->flags;
18374940c694Smrg                    cls_lib->increment  = FP3232_TO_DOUBLE(cls_wire->increment);
1838f1ee322dSmrg
1839f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1840f1ee322dSmrg                }
1841f1ee322dSmrg                break;
1842f1ee322dSmrg            case XITouchClass:
1843f1ee322dSmrg                {
1844f1ee322dSmrg                    XITouchClassInfo *cls_lib;
1845f1ee322dSmrg                    xXITouchInfo *cls_wire;
1846f1ee322dSmrg
1847f1ee322dSmrg                    cls_wire = (xXITouchInfo*)any_wire;
1848f1ee322dSmrg                    cls_lib = next_block(&ptr_lib, sizeof(XITouchClassInfo));
1849f1ee322dSmrg
1850f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1851f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1852f1ee322dSmrg                    cls_lib->mode = cls_wire->mode;
1853f1ee322dSmrg                    cls_lib->num_touches = cls_wire->num_touches;
1854f1ee322dSmrg
1855f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1856c27c18e8Smrg                }
1857c27c18e8Smrg                break;
185887404ef7Smrg            case XIGestureClass:
185987404ef7Smrg                {
186087404ef7Smrg                    XIGestureClassInfo *cls_lib;
186187404ef7Smrg                    xXIGestureInfo *cls_wire;
186287404ef7Smrg
186387404ef7Smrg                    cls_wire = (xXIGestureInfo*)any_wire;
186487404ef7Smrg                    cls_lib = next_block(&ptr_lib, sizeof(XIGestureClassInfo));
186587404ef7Smrg
186687404ef7Smrg                    cls_lib->type = cls_wire->type;
186787404ef7Smrg                    cls_lib->sourceid = cls_wire->sourceid;
186887404ef7Smrg                    cls_lib->num_touches = cls_wire->num_touches;
186987404ef7Smrg
187087404ef7Smrg                    to->classes[cls_idx++] = any_lib;
187187404ef7Smrg                }
187287404ef7Smrg                break;
1873c27c18e8Smrg        }
1874c27c18e8Smrg        len += any_wire->length * 4;
1875c27c18e8Smrg        ptr_wire += any_wire->length * 4;
1876c43cc173Smrg    }
1877f1ee322dSmrg
1878f1ee322dSmrg    /* we may have skipped unknown classes, reset nclasses */
1879f1ee322dSmrg    *nclasses = cls_idx;
1880c27c18e8Smrg    return len;
1881c27c18e8Smrg}
1882c27c18e8Smrg
1883c27c18e8Smrg
1884c27c18e8Smrgstatic int
1885c27c18e8SmrgwireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie)
1886c27c18e8Smrg{
1887c27c18e8Smrg    XIDeviceChangedEvent *out;
1888c27c18e8Smrg    XIDeviceInfo info;
1889c27c18e8Smrg    int len;
1890f1ee322dSmrg    int nclasses = in->num_classes;
1891c27c18e8Smrg
1892c27c18e8Smrg    len = size_classes((xXIAnyInfo*)&in[1], in->num_classes);
1893c27c18e8Smrg
1894c27c18e8Smrg    cookie->data = out = malloc(sizeof(XIDeviceChangedEvent) + len);
1895c6b4a769Smrg    if (!out)
1896c6b4a769Smrg        return 0;
1897c27c18e8Smrg
1898c27c18e8Smrg    out->type = in->type;
189944584a44Smrg    out->serial = cookie->serial;
190089069ce9Smrg    out->display = cookie->display;
1901c27c18e8Smrg    out->extension = in->extension;
1902c27c18e8Smrg    out->evtype = in->evtype;
1903c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
1904c27c18e8Smrg    out->time = in->time;
1905c27c18e8Smrg    out->deviceid = in->deviceid;
1906c27c18e8Smrg    out->sourceid = in->sourceid;
1907c27c18e8Smrg    out->reason = in->reason;
1908c27c18e8Smrg
1909c27c18e8Smrg    out->classes = (XIAnyClassInfo**)&out[1];
1910c27c18e8Smrg
1911c27c18e8Smrg    info.classes = out->classes;
1912c27c18e8Smrg
1913f1ee322dSmrg    copy_classes(&info, (xXIAnyInfo*)&in[1], &nclasses);
1914f1ee322dSmrg    out->num_classes = nclasses;
1915c27c18e8Smrg
1916c27c18e8Smrg    return 1;
1917c27c18e8Smrg}
1918c27c18e8Smrg
1919c27c18e8Smrgstatic int
1920c27c18e8SmrgwireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie)
1921c27c18e8Smrg{
1922c27c18e8Smrg    int i;
1923c27c18e8Smrg    XIHierarchyInfo *info_out;
1924c27c18e8Smrg    xXIHierarchyInfo *info_in;
1925c27c18e8Smrg    XIHierarchyEvent *out;
1926c27c18e8Smrg
1927c6b4a769Smrg    cookie->data = out = malloc(sizeof(XIHierarchyEvent) + in->num_info * sizeof(XIHierarchyInfo));
1928c6b4a769Smrg    if (!out)
1929c6b4a769Smrg        return 0;
1930c27c18e8Smrg
1931c27c18e8Smrg    out->info           = (XIHierarchyInfo*)&out[1];
193289069ce9Smrg    out->display        = cookie->display;
1933c27c18e8Smrg    out->type           = in->type;
193444584a44Smrg    out->serial         = cookie->serial;
1935c27c18e8Smrg    out->extension      = in->extension;
1936c27c18e8Smrg    out->evtype         = in->evtype;
1937c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
1938c27c18e8Smrg    out->time           = in->time;
1939c27c18e8Smrg    out->flags          = in->flags;
1940c27c18e8Smrg    out->num_info       = in->num_info;
1941c27c18e8Smrg
1942c27c18e8Smrg    info_out            = out->info;
1943c27c18e8Smrg    info_in             = (xXIHierarchyInfo*)&in[1];
1944c27c18e8Smrg
1945c27c18e8Smrg    for (i = 0; i < out->num_info; i++, info_out++, info_in++)
1946c43cc173Smrg    {
1947c27c18e8Smrg        info_out->deviceid      = info_in->deviceid;
1948c27c18e8Smrg        info_out->attachment    = info_in->attachment;
1949c27c18e8Smrg        info_out->use           = info_in->use;
1950c27c18e8Smrg        info_out->enabled       = info_in->enabled;
1951c27c18e8Smrg        info_out->flags         = info_in->flags;
1952c43cc173Smrg    }
1953c43cc173Smrg
1954c27c18e8Smrg    return 1;
1955c27c18e8Smrg}
1956c27c18e8Smrg
1957c27c18e8Smrgstatic int
1958f1ee322dSmrgwireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *cookie)
1959c27c18e8Smrg{
1960c27c18e8Smrg    int len, i, bits;
1961c27c18e8Smrg    FP3232 *values;
1962c27c18e8Smrg    XIRawEvent *out;
1963c27c18e8Smrg    void *ptr;
1964c27c18e8Smrg
1965c6b4a769Smrg    len = pad_to_double(sizeof(XIRawEvent))
1966c6b4a769Smrg        + pad_to_double(in->valuators_len * 4);
1967c27c18e8Smrg    bits = count_bits((unsigned char*)&in[1], in->valuators_len * 4);
1968c27c18e8Smrg    len += bits * sizeof(double) * 2; /* raw + normal */
1969c27c18e8Smrg
1970c27c18e8Smrg    cookie->data = ptr = calloc(1, len);
1971c27c18e8Smrg    if (!ptr)
1972c27c18e8Smrg        return 0;
1973c27c18e8Smrg
1974c6b4a769Smrg    out = next_block(&ptr, pad_to_double(sizeof(XIRawEvent)));
1975c27c18e8Smrg    out->type           = in->type;
197644584a44Smrg    out->serial         = cookie->serial;
197789069ce9Smrg    out->display        = cookie->display;
1978c27c18e8Smrg    out->extension      = in->extension;
1979c27c18e8Smrg    out->evtype         = in->evtype;
1980c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
1981c27c18e8Smrg    out->time           = in->time;
1982c27c18e8Smrg    out->detail         = in->detail;
1983c27c18e8Smrg    out->deviceid       = in->deviceid;
1984c27c18e8Smrg    out->flags          = in->flags;
1985c27c18e8Smrg
1986f1ee322dSmrg    /* https://bugs.freedesktop.org/show_bug.cgi?id=34240 */
1987f1ee322dSmrg    if (_XiCheckVersion(info, XInput_2_2) >= 0)
1988f1ee322dSmrg        out->sourceid       = in->sourceid;
1989f1ee322dSmrg    else
1990f1ee322dSmrg        out->sourceid       = 0;
1991f1ee322dSmrg
1992c27c18e8Smrg    out->valuators.mask_len = in->valuators_len * 4;
1993c6b4a769Smrg    out->valuators.mask
1994c6b4a769Smrg        = next_block(&ptr, pad_to_double(out->valuators.mask_len));
1995c27c18e8Smrg    memcpy(out->valuators.mask, &in[1], out->valuators.mask_len);
1996c27c18e8Smrg
1997c27c18e8Smrg    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1998c27c18e8Smrg    out->raw_values = next_block(&ptr, bits * sizeof(double));
1999c27c18e8Smrg
2000c27c18e8Smrg    values = (FP3232*)(((char*)&in[1]) + in->valuators_len * 4);
2001c27c18e8Smrg    for (i = 0; i < bits; i++)
2002c43cc173Smrg    {
2003c27c18e8Smrg        out->valuators.values[i] = values->integral;
2004c27c18e8Smrg        out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
2005c27c18e8Smrg        out->raw_values[i] = (values + bits)->integral;
200637eb1ca1Smrg        out->raw_values[i] += ((double)(values + bits)->frac / (1 << 16) / (1 << 16));
2007c27c18e8Smrg        values++;
2008c43cc173Smrg    }
2009c43cc173Smrg
2010c27c18e8Smrg    return 1;
2011c27c18e8Smrg}
201221e67964Smrg
2013c27c18e8Smrg/* Memory layout of XIEnterEvents:
2014c27c18e8Smrg   [event][modifiers][group][button]
2015c27c18e8Smrg */
2016c27c18e8Smrgstatic int
2017c27c18e8SmrgwireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie)
2018c27c18e8Smrg{
2019c27c18e8Smrg    int len;
2020c27c18e8Smrg    XIEnterEvent *out;
2021c27c18e8Smrg
2022c27c18e8Smrg    len = sizeof(XIEnterEvent) + in->buttons_len * 4;
2023c27c18e8Smrg
2024c27c18e8Smrg    cookie->data = out = malloc(len);
2025c6b4a769Smrg    if (!out)
2026c6b4a769Smrg        return 0;
2027c6b4a769Smrg
2028c27c18e8Smrg    out->buttons.mask = (unsigned char*)&out[1];
2029c27c18e8Smrg
2030c27c18e8Smrg    out->type           = in->type;
203144584a44Smrg    out->serial         = cookie->serial;
203289069ce9Smrg    out->display        = cookie->display;
2033c27c18e8Smrg    out->extension      = in->extension;
2034c27c18e8Smrg    out->evtype         = in->evtype;
2035c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
2036c27c18e8Smrg    out->time           = in->time;
2037c27c18e8Smrg    out->detail         = in->detail;
2038c27c18e8Smrg    out->deviceid       = in->deviceid;
2039c27c18e8Smrg    out->root           = in->root;
2040c27c18e8Smrg    out->event          = in->event;
2041c27c18e8Smrg    out->child          = in->child;
2042c27c18e8Smrg    out->sourceid       = in->sourceid;
2043c27c18e8Smrg    out->root_x         = FP1616toDBL(in->root_x);
2044c27c18e8Smrg    out->root_y         = FP1616toDBL(in->root_y);
2045c27c18e8Smrg    out->event_x        = FP1616toDBL(in->event_x);
2046c27c18e8Smrg    out->event_y        = FP1616toDBL(in->event_y);
2047c27c18e8Smrg    out->mode           = in->mode;
2048c27c18e8Smrg    out->focus          = in->focus;
2049c27c18e8Smrg    out->same_screen    = in->same_screen;
2050c27c18e8Smrg
2051c27c18e8Smrg    out->mods.base = in->mods.base_mods;
2052c27c18e8Smrg    out->mods.locked = in->mods.locked_mods;
2053c27c18e8Smrg    out->mods.latched = in->mods.latched_mods;
2054c27c18e8Smrg    out->mods.effective = in->mods.effective_mods;
2055c27c18e8Smrg    out->group.base = in->group.base_group;
2056c27c18e8Smrg    out->group.locked = in->group.locked_group;
2057c27c18e8Smrg    out->group.latched = in->group.latched_group;
2058c27c18e8Smrg    out->group.effective = in->group.effective_group;
2059c27c18e8Smrg
2060c27c18e8Smrg    out->buttons.mask_len = in->buttons_len * 4;
2061c27c18e8Smrg    memcpy(out->buttons.mask, &in[1], out->buttons.mask_len);
206221e67964Smrg
2063c27c18e8Smrg    return 1;
2064c27c18e8Smrg}
2065c43cc173Smrg
2066c27c18e8Smrgstatic int
2067c27c18e8SmrgwireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie)
2068c27c18e8Smrg{
2069c27c18e8Smrg    XIPropertyEvent *out = malloc(sizeof(XIPropertyEvent));
2070c27c18e8Smrg
2071c27c18e8Smrg    cookie->data = out;
2072c6b4a769Smrg    if (!out)
2073c6b4a769Smrg        return 0;
2074c27c18e8Smrg
2075c27c18e8Smrg    out->type           = in->type;
207644584a44Smrg    out->serial         = cookie->serial;
2077c27c18e8Smrg    out->extension      = in->extension;
2078c27c18e8Smrg    out->evtype         = in->evtype;
2079c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
2080c27c18e8Smrg    out->time           = in->time;
2081c27c18e8Smrg    out->property       = in->property;
2082c27c18e8Smrg    out->what           = in->what;
2083c27c18e8Smrg    out->deviceid       = in->deviceid;
2084c27c18e8Smrg
2085c27c18e8Smrg    return 1;
2086c43cc173Smrg}
2087f1ee322dSmrg
2088f1ee322dSmrgstatic int
2089f1ee322dSmrgwireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
2090f1ee322dSmrg                          XGenericEventCookie *cookie)
2091f1ee322dSmrg{
2092f1ee322dSmrg    XITouchOwnershipEvent *out = malloc(sizeof(XITouchOwnershipEvent));
2093f1ee322dSmrg
2094f1ee322dSmrg    cookie->data = out;
2095c6b4a769Smrg    if (!out)
2096c6b4a769Smrg        return 0;
2097f1ee322dSmrg
2098f1ee322dSmrg    out->type           = in->type;
209944584a44Smrg    out->serial         = cookie->serial;
2100f1ee322dSmrg    out->display        = cookie->display;
2101f1ee322dSmrg    out->extension      = in->extension;
2102f1ee322dSmrg    out->evtype         = in->evtype;
2103f1ee322dSmrg    out->send_event     = ((in->type & 0x80) != 0);
2104f1ee322dSmrg    out->time           = in->time;
2105f1ee322dSmrg    out->deviceid       = in->deviceid;
2106f1ee322dSmrg    out->sourceid       = in->sourceid;
2107f1ee322dSmrg    out->touchid        = in->touchid;
2108f1ee322dSmrg    out->root           = in->root;
2109f1ee322dSmrg    out->event          = in->event;
2110f1ee322dSmrg    out->child          = in->child;
2111f1ee322dSmrg    out->flags          = in->flags;
2112f1ee322dSmrg
2113f1ee322dSmrg    return 1;
2114f1ee322dSmrg}
2115f1ee322dSmrg
2116f1ee322dSmrgstatic int
2117f1ee322dSmrgwireToBarrierEvent(xXIBarrierEvent *in, XGenericEventCookie *cookie)
2118f1ee322dSmrg{
2119f1ee322dSmrg    XIBarrierEvent *out = malloc(sizeof(XIBarrierEvent));
2120f1ee322dSmrg
2121f1ee322dSmrg    cookie->data = out;
2122c6b4a769Smrg    if (!out)
2123c6b4a769Smrg        return 0;
2124f1ee322dSmrg
2125f1ee322dSmrg    out->display    = cookie->display;
2126f1ee322dSmrg    out->type       = in->type;
212744584a44Smrg    out->serial     = cookie->serial;
2128f1ee322dSmrg    out->extension  = in->extension;
2129f1ee322dSmrg    out->evtype     = in->evtype;
2130f1ee322dSmrg    out->send_event = ((in->type & 0x80) != 0);
2131f1ee322dSmrg    out->time       = in->time;
2132f1ee322dSmrg    out->deviceid   = in->deviceid;
2133f1ee322dSmrg    out->sourceid   = in->sourceid;
2134f1ee322dSmrg    out->event      = in->event;
2135f1ee322dSmrg    out->root       = in->root;
2136f1ee322dSmrg    out->root_x     = FP1616toDBL(in->root_x);
2137f1ee322dSmrg    out->root_y     = FP1616toDBL(in->root_y);
2138f1ee322dSmrg    out->dx         = FP3232_TO_DOUBLE (in->dx);
2139f1ee322dSmrg    out->dy         = FP3232_TO_DOUBLE (in->dy);
2140f1ee322dSmrg    out->dtime      = in->dtime;
2141f1ee322dSmrg    out->flags      = in->flags;
2142f1ee322dSmrg    out->barrier    = in->barrier;
2143f1ee322dSmrg    out->eventid    = in->eventid;
2144f1ee322dSmrg
2145f1ee322dSmrg    return 1;
2146f1ee322dSmrg}
214787404ef7Smrg
214887404ef7Smrgstatic int
214987404ef7SmrgwireToPinchEvent(xXIGesturePinchEvent *in,
215087404ef7Smrg                 XGenericEventCookie *cookie)
215187404ef7Smrg{
215287404ef7Smrg    XIGesturePinchEvent *out;
215387404ef7Smrg
215487404ef7Smrg    cookie->data = out = malloc(sizeof(XIGesturePinchEvent));
2155c6b4a769Smrg    if (!out)
2156c6b4a769Smrg        return 0;
215787404ef7Smrg
215887404ef7Smrg    out->display    = cookie->display;
215987404ef7Smrg    out->type       = in->type;
216087404ef7Smrg    out->serial     = cookie->serial;
216187404ef7Smrg    out->extension  = in->extension;
216287404ef7Smrg    out->evtype     = in->evtype;
216387404ef7Smrg    out->send_event = ((in->type & 0x80) != 0);
216487404ef7Smrg    out->time       = in->time;
216587404ef7Smrg    out->deviceid   = in->deviceid;
216687404ef7Smrg    out->sourceid   = in->sourceid;
216787404ef7Smrg    out->detail     = in->detail;
216887404ef7Smrg    out->root       = in->root;
216987404ef7Smrg    out->event      = in->event;
217087404ef7Smrg    out->child      = in->child;
217187404ef7Smrg    out->root_x     = FP1616toDBL(in->root_x);
217287404ef7Smrg    out->root_y     = FP1616toDBL(in->root_y);
217387404ef7Smrg    out->event_x    = FP1616toDBL(in->event_x);
217487404ef7Smrg    out->event_y    = FP1616toDBL(in->event_y);
217587404ef7Smrg    out->delta_x    = FP1616toDBL(in->delta_x);
217687404ef7Smrg    out->delta_y    = FP1616toDBL(in->delta_y);
217787404ef7Smrg    out->delta_unaccel_x = FP1616toDBL(in->delta_unaccel_x);
217887404ef7Smrg    out->delta_unaccel_y = FP1616toDBL(in->delta_unaccel_y);
217987404ef7Smrg    out->scale      = FP1616toDBL(in->scale);
218087404ef7Smrg    out->delta_angle = FP1616toDBL(in->delta_angle);
218187404ef7Smrg    out->flags      = in->flags;
218287404ef7Smrg
218387404ef7Smrg    out->mods.base = in->mods.base_mods;
218487404ef7Smrg    out->mods.locked = in->mods.locked_mods;
218587404ef7Smrg    out->mods.latched = in->mods.latched_mods;
218687404ef7Smrg    out->mods.effective = in->mods.effective_mods;
218787404ef7Smrg    out->group.base = in->group.base_group;
218887404ef7Smrg    out->group.locked = in->group.locked_group;
218987404ef7Smrg    out->group.latched = in->group.latched_group;
219087404ef7Smrg    out->group.effective = in->group.effective_group;
219187404ef7Smrg
219287404ef7Smrg    return 1;
219387404ef7Smrg}
219487404ef7Smrg
219587404ef7Smrgstatic int
219687404ef7SmrgwireToSwipeEvent(xXIGestureSwipeEvent *in,
219787404ef7Smrg                 XGenericEventCookie *cookie)
219887404ef7Smrg{
219987404ef7Smrg    XIGestureSwipeEvent *out;
220087404ef7Smrg
220187404ef7Smrg    cookie->data = out = malloc(sizeof(XIGestureSwipeEvent));
2202c6b4a769Smrg    if (!out)
2203c6b4a769Smrg        return 0;
220487404ef7Smrg
220587404ef7Smrg    out->display    = cookie->display;
220687404ef7Smrg    out->type       = in->type;
220787404ef7Smrg    out->serial     = cookie->serial;
220887404ef7Smrg    out->extension  = in->extension;
220987404ef7Smrg    out->evtype     = in->evtype;
221087404ef7Smrg    out->send_event = ((in->type & 0x80) != 0);
221187404ef7Smrg    out->time       = in->time;
221287404ef7Smrg    out->deviceid   = in->deviceid;
221387404ef7Smrg    out->sourceid   = in->sourceid;
221487404ef7Smrg    out->detail     = in->detail;
221587404ef7Smrg    out->root       = in->root;
221687404ef7Smrg    out->event      = in->event;
221787404ef7Smrg    out->child      = in->child;
221887404ef7Smrg    out->root_x     = FP1616toDBL(in->root_x);
221987404ef7Smrg    out->root_y     = FP1616toDBL(in->root_y);
222087404ef7Smrg    out->event_x    = FP1616toDBL(in->event_x);
222187404ef7Smrg    out->event_y    = FP1616toDBL(in->event_y);
222287404ef7Smrg    out->delta_x    = FP1616toDBL(in->delta_x);
222387404ef7Smrg    out->delta_y    = FP1616toDBL(in->delta_y);
222487404ef7Smrg    out->delta_unaccel_x = FP1616toDBL(in->delta_unaccel_x);
222587404ef7Smrg    out->delta_unaccel_y = FP1616toDBL(in->delta_unaccel_y);
222687404ef7Smrg    out->flags      = in->flags;
222787404ef7Smrg
222887404ef7Smrg    out->mods.base = in->mods.base_mods;
222987404ef7Smrg    out->mods.locked = in->mods.locked_mods;
223087404ef7Smrg    out->mods.latched = in->mods.latched_mods;
223187404ef7Smrg    out->mods.effective = in->mods.effective_mods;
223287404ef7Smrg    out->group.base = in->group.base_group;
223387404ef7Smrg    out->group.locked = in->group.locked_group;
223487404ef7Smrg    out->group.latched = in->group.latched_group;
223587404ef7Smrg    out->group.effective = in->group.effective_group;
223687404ef7Smrg
223787404ef7Smrg    return 1;
223887404ef7Smrg}
2239