XExtInt.c revision 87404ef7
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);
2333e256790Smrg      if (dpyinfo->codes) /* NULL 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);
1431c27c18e8Smrg    len = sizeof(XIRawEvent) + in->valuators.mask_len;
1432c27c18e8Smrg    len += bits * sizeof(double) * 2;
1433c27c18e8Smrg
1434b789ec8aSmrg    ptr = cookie_out->data = malloc(len);
1435c27c18e8Smrg    if (!ptr)
1436c27c18e8Smrg        return False;
1437c27c18e8Smrg
1438c27c18e8Smrg    out = next_block(&ptr, sizeof(XIRawEvent));
1439c27c18e8Smrg    *out = *in;
1440c27c18e8Smrg    out->valuators.mask = next_block(&ptr, out->valuators.mask_len);
1441c27c18e8Smrg    memcpy(out->valuators.mask, in->valuators.mask, out->valuators.mask_len);
1442c27c18e8Smrg
1443c27c18e8Smrg    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1444c27c18e8Smrg    memcpy(out->valuators.values, in->valuators.values, bits * sizeof(double));
1445c27c18e8Smrg
1446c27c18e8Smrg    out->raw_values = next_block(&ptr, bits * sizeof(double));
1447c27c18e8Smrg    memcpy(out->raw_values, in->raw_values, bits * sizeof(double));
1448c27c18e8Smrg
1449c27c18e8Smrg    return True;
1450c27c18e8Smrg}
1451c27c18e8Smrg
1452f1ee322dSmrgstatic Bool
1453f1ee322dSmrgcopyBarrierEvent(XGenericEventCookie *in_cookie,
1454f1ee322dSmrg                 XGenericEventCookie *out_cookie)
1455f1ee322dSmrg{
1456f1ee322dSmrg    XIBarrierEvent *in, *out;
1457f1ee322dSmrg
1458f1ee322dSmrg    in = in_cookie->data;
1459f1ee322dSmrg
1460f1ee322dSmrg    out = out_cookie->data = calloc(1, sizeof(XIBarrierEvent));
1461f1ee322dSmrg    if (!out)
1462f1ee322dSmrg        return False;
1463f1ee322dSmrg    *out = *in;
1464c27c18e8Smrg
1465f1ee322dSmrg    return True;
1466f1ee322dSmrg}
1467c27c18e8Smrg
146887404ef7Smrg
146987404ef7Smrgstatic Bool
147087404ef7SmrgcopyGesturePinchEvent(XGenericEventCookie *cookie_in,
147187404ef7Smrg                      XGenericEventCookie *cookie_out)
147287404ef7Smrg{
147387404ef7Smrg    XIGesturePinchEvent *in, *out;
147487404ef7Smrg
147587404ef7Smrg    in = cookie_in->data;
147687404ef7Smrg
147787404ef7Smrg    out = cookie_out->data = malloc(sizeof(XIGesturePinchEvent));
147887404ef7Smrg    if (!out)
147987404ef7Smrg        return False;
148087404ef7Smrg
148187404ef7Smrg    *out = *in;
148287404ef7Smrg
148387404ef7Smrg    return True;
148487404ef7Smrg}
148587404ef7Smrg
148687404ef7Smrgstatic Bool
148787404ef7SmrgcopyGestureSwipeEvent(XGenericEventCookie *cookie_in,
148887404ef7Smrg                      XGenericEventCookie *cookie_out)
148987404ef7Smrg{
149087404ef7Smrg    XIGestureSwipeEvent *in, *out;
149187404ef7Smrg
149287404ef7Smrg    in = cookie_in->data;
149387404ef7Smrg
149487404ef7Smrg    out = cookie_out->data = malloc(sizeof(XIGestureSwipeEvent));
149587404ef7Smrg    if (!out)
149687404ef7Smrg        return False;
149787404ef7Smrg
149887404ef7Smrg    *out = *in;
149987404ef7Smrg
150087404ef7Smrg    return True;
150187404ef7Smrg}
150287404ef7Smrg
1503c27c18e8Smrgstatic Bool
1504c27c18e8SmrgXInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
1505c27c18e8Smrg{
1506c27c18e8Smrg    int ret = True;
1507c27c18e8Smrg
1508c27c18e8Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
1509c27c18e8Smrg
1510c27c18e8Smrg    if (in->extension != info->codes->major_opcode)
1511c43cc173Smrg    {
1512c27c18e8Smrg        printf("XInputCopyCookie: wrong extension opcode %d\n",
1513c27c18e8Smrg                in->extension);
1514c27c18e8Smrg        return False;
1515c27c18e8Smrg    }
1516c27c18e8Smrg
1517c27c18e8Smrg    *out = *in;
1518c27c18e8Smrg    out->data = NULL;
1519c27c18e8Smrg    out->cookie = 0;
1520c27c18e8Smrg
1521c27c18e8Smrg    switch(in->evtype) {
1522c27c18e8Smrg        case XI_Motion:
1523c27c18e8Smrg        case XI_ButtonPress:
1524c27c18e8Smrg        case XI_ButtonRelease:
1525c27c18e8Smrg        case XI_KeyPress:
1526c27c18e8Smrg        case XI_KeyRelease:
1527f1ee322dSmrg        case XI_TouchBegin:
1528f1ee322dSmrg        case XI_TouchUpdate:
1529f1ee322dSmrg        case XI_TouchEnd:
1530c27c18e8Smrg            ret = copyDeviceEvent(in, out);
1531c27c18e8Smrg            break;
1532c27c18e8Smrg        case XI_DeviceChanged:
1533c27c18e8Smrg            ret = copyDeviceChangedEvent(in, out);
1534c27c18e8Smrg            break;
1535c27c18e8Smrg        case XI_HierarchyChanged:
1536c27c18e8Smrg            ret = copyHierarchyEvent(in, out);
1537c27c18e8Smrg            break;
1538c27c18e8Smrg        case XI_Enter:
1539c27c18e8Smrg        case XI_Leave:
1540c27c18e8Smrg        case XI_FocusIn:
1541c27c18e8Smrg        case XI_FocusOut:
1542c27c18e8Smrg            ret = copyEnterEvent(in, out);
1543c27c18e8Smrg            break;
1544c27c18e8Smrg        case XI_PropertyEvent:
1545c27c18e8Smrg            ret = copyPropertyEvent(in, out);
1546c27c18e8Smrg            break;
1547f1ee322dSmrg        case XI_TouchOwnership:
1548f1ee322dSmrg            ret = copyTouchOwnershipEvent(in, out);
1549f1ee322dSmrg            break;
1550c27c18e8Smrg        case XI_RawKeyPress:
1551c27c18e8Smrg        case XI_RawKeyRelease:
1552c27c18e8Smrg        case XI_RawButtonPress:
1553c27c18e8Smrg        case XI_RawButtonRelease:
1554c27c18e8Smrg        case XI_RawMotion:
1555f1ee322dSmrg        case XI_RawTouchBegin:
1556f1ee322dSmrg        case XI_RawTouchUpdate:
1557f1ee322dSmrg        case XI_RawTouchEnd:
1558c27c18e8Smrg            ret = copyRawEvent(in, out);
1559c27c18e8Smrg            break;
1560f1ee322dSmrg        case XI_BarrierHit:
1561f1ee322dSmrg        case XI_BarrierLeave:
1562f1ee322dSmrg            ret = copyBarrierEvent(in, out);
1563f1ee322dSmrg            break;
156487404ef7Smrg        case XI_GesturePinchBegin:
156587404ef7Smrg        case XI_GesturePinchUpdate:
156687404ef7Smrg        case XI_GesturePinchEnd:
156787404ef7Smrg            ret = copyGesturePinchEvent(in, out);
156887404ef7Smrg            break;
156987404ef7Smrg        case XI_GestureSwipeBegin:
157087404ef7Smrg        case XI_GestureSwipeUpdate:
157187404ef7Smrg        case XI_GestureSwipeEnd:
157287404ef7Smrg            ret = copyGestureSwipeEvent(in, out);
157387404ef7Smrg            break;
1574c27c18e8Smrg        default:
1575c27c18e8Smrg            printf("XInputCopyCookie: unknown evtype %d\n", in->evtype);
1576c27c18e8Smrg            ret = False;
1577c43cc173Smrg    }
1578c27c18e8Smrg
1579c27c18e8Smrg    if (!ret)
1580c27c18e8Smrg        printf("XInputCopyCookie: Failed to copy evtype %d", in->evtype);
1581c27c18e8Smrg    return ret;
1582c27c18e8Smrg}
1583c27c18e8Smrg
1584c27c18e8Smrgstatic int
1585c27c18e8SmrgwireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* cookie)
1586c27c18e8Smrg{
1587c27c18e8Smrg    int len, i;
1588c27c18e8Smrg    unsigned char *ptr;
1589c27c18e8Smrg    void *ptr_lib;
1590c27c18e8Smrg    FP3232 *values;
1591c27c18e8Smrg    XIDeviceEvent *out;
1592c27c18e8Smrg
1593c27c18e8Smrg    ptr = (unsigned char*)&in[1] + in->buttons_len * 4;
1594c27c18e8Smrg
1595c27c18e8Smrg    len = sizeDeviceEvent(in->buttons_len * 4, in->valuators_len * 4, ptr);
1596c27c18e8Smrg
1597c27c18e8Smrg    cookie->data = ptr_lib = malloc(len);
1598c27c18e8Smrg
1599c27c18e8Smrg    out = next_block(&ptr_lib, sizeof(XIDeviceEvent));
160089069ce9Smrg    out->display = cookie->display;
1601c27c18e8Smrg    out->type = in->type;
160244584a44Smrg    out->serial = cookie->serial;
1603c27c18e8Smrg    out->extension = in->extension;
1604c27c18e8Smrg    out->evtype = in->evtype;
1605c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
1606c27c18e8Smrg    out->time = in->time;
1607c27c18e8Smrg    out->deviceid = in->deviceid;
1608c27c18e8Smrg    out->sourceid = in->sourceid;
1609c27c18e8Smrg    out->detail = in->detail;
1610c27c18e8Smrg    out->root = in->root;
1611c27c18e8Smrg    out->event = in->event;
1612c27c18e8Smrg    out->child = in->child;
1613c27c18e8Smrg    out->root_x = FP1616toDBL(in->root_x);
1614c27c18e8Smrg    out->root_y = FP1616toDBL(in->root_y);
1615c27c18e8Smrg    out->event_x = FP1616toDBL(in->event_x);
1616c27c18e8Smrg    out->event_y = FP1616toDBL(in->event_y);
1617c27c18e8Smrg    out->flags = in->flags;
1618c27c18e8Smrg    out->mods.base = in->mods.base_mods;
1619c27c18e8Smrg    out->mods.locked = in->mods.locked_mods;
1620c27c18e8Smrg    out->mods.latched = in->mods.latched_mods;
1621c27c18e8Smrg    out->mods.effective = in->mods.effective_mods;
1622c27c18e8Smrg    out->group.base = in->group.base_group;
1623c27c18e8Smrg    out->group.locked = in->group.locked_group;
1624c27c18e8Smrg    out->group.latched = in->group.latched_group;
1625c27c18e8Smrg    out->group.effective = in->group.effective_group;
1626c27c18e8Smrg    out->buttons.mask_len = in->buttons_len * 4;
1627c27c18e8Smrg    out->valuators.mask_len = in->valuators_len * 4;
1628c27c18e8Smrg
1629c27c18e8Smrg    out->buttons.mask = next_block(&ptr_lib, out->buttons.mask_len);
1630c27c18e8Smrg
1631c27c18e8Smrg    /* buttons */
1632c27c18e8Smrg    ptr = (unsigned char*)&in[1];
1633c27c18e8Smrg    memcpy(out->buttons.mask, ptr, out->buttons.mask_len);
1634c27c18e8Smrg    ptr += in->buttons_len * 4;
1635c27c18e8Smrg
1636c27c18e8Smrg    /* valuators */
1637c27c18e8Smrg    out->valuators.mask = next_block(&ptr_lib, out->valuators.mask_len);
1638c27c18e8Smrg    memcpy(out->valuators.mask, ptr, out->valuators.mask_len);
1639c27c18e8Smrg    ptr += in->valuators_len * 4;
1640c27c18e8Smrg
1641c27c18e8Smrg    len = count_bits(out->valuators.mask, out->valuators.mask_len);
1642c27c18e8Smrg    out->valuators.values = next_block(&ptr_lib, len * sizeof(double));
1643c27c18e8Smrg
1644c27c18e8Smrg    values = (FP3232*)ptr;
1645c27c18e8Smrg    for (i = 0; i < len; i++, values++)
1646c43cc173Smrg    {
1647c27c18e8Smrg        out->valuators.values[i] = values->integral;
1648c27c18e8Smrg        out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1649c43cc173Smrg    }
1650c27c18e8Smrg
1651c27c18e8Smrg
1652c27c18e8Smrg    return 1;
1653c27c18e8Smrg}
1654c27c18e8Smrg
1655c27c18e8Smrg_X_HIDDEN int
1656c27c18e8Smrgsize_classes(xXIAnyInfo* from, int nclasses)
1657c27c18e8Smrg{
1658c27c18e8Smrg    int len, i;
1659c27c18e8Smrg    xXIAnyInfo *any_wire;
1660c27c18e8Smrg    char *ptr_wire;
1661c27c18e8Smrg
1662f1ee322dSmrg    /* len for to->classes */
1663f1ee322dSmrg    len = pad_to_double(nclasses * sizeof(XIAnyClassInfo*));
1664c27c18e8Smrg    ptr_wire = (char*)from;
1665c27c18e8Smrg    for (i = 0; i < nclasses; i++)
1666c43cc173Smrg    {
1667c27c18e8Smrg        int l = 0;
1668c27c18e8Smrg        any_wire = (xXIAnyInfo*)ptr_wire;
1669c27c18e8Smrg        switch(any_wire->type)
1670c27c18e8Smrg        {
1671c27c18e8Smrg            case XIButtonClass:
1672c27c18e8Smrg                l = sizeDeviceClassType(XIButtonClass,
1673c27c18e8Smrg                        ((xXIButtonInfo*)any_wire)->num_buttons);
1674c27c18e8Smrg                break;
1675c27c18e8Smrg            case XIKeyClass:
1676c27c18e8Smrg                l = sizeDeviceClassType(XIKeyClass,
1677c27c18e8Smrg                        ((xXIKeyInfo*)any_wire)->num_keycodes);
1678c27c18e8Smrg                break;
1679c27c18e8Smrg            case XIValuatorClass:
1680c27c18e8Smrg                l = sizeDeviceClassType(XIValuatorClass, 0);
1681c27c18e8Smrg                break;
1682f1ee322dSmrg            case XIScrollClass:
1683f1ee322dSmrg                l = sizeDeviceClassType(XIScrollClass, 0);
1684f1ee322dSmrg                break;
1685f1ee322dSmrg            case XITouchClass:
1686f1ee322dSmrg                l = sizeDeviceClassType(XITouchClass, 0);
1687f1ee322dSmrg                break;
168887404ef7Smrg            case XIGestureClass:
168987404ef7Smrg                l = sizeDeviceClassType(XIGestureClass, 0);
169087404ef7Smrg                break;
1691c27c18e8Smrg        }
1692c27c18e8Smrg
1693c27c18e8Smrg        len += l;
1694c27c18e8Smrg        ptr_wire += any_wire->length * 4;
1695c43cc173Smrg    }
1696c27c18e8Smrg
1697c27c18e8Smrg    return len;
1698c27c18e8Smrg}
1699c27c18e8Smrg
17004940c694Smrg#define FP3232_TO_DOUBLE(x) ((double) (x).integral + (double) (x).frac / (1ULL << 32))
17014940c694Smrg
1702c27c18e8Smrg/* Copy classes from any into to->classes and return the number of bytes
1703c27c18e8Smrg * copied. Memory layout of to->classes is
1704c27c18e8Smrg * [clsptr][clsptr][clsptr][classinfo][classinfo]...
1705c27c18e8Smrg *    |________|___________^
1706c27c18e8Smrg *             |______________________^
1707c27c18e8Smrg */
1708c27c18e8Smrg_X_HIDDEN int
1709f1ee322dSmrgcopy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
1710c27c18e8Smrg{
1711c27c18e8Smrg    XIAnyClassInfo *any_lib;
1712c27c18e8Smrg    xXIAnyInfo *any_wire;
1713c27c18e8Smrg    void *ptr_lib;
1714c27c18e8Smrg    char *ptr_wire;
1715c27c18e8Smrg    int i, len;
1716f1ee322dSmrg    int cls_idx = 0;
1717c27c18e8Smrg
1718c27c18e8Smrg    if (!to->classes)
1719c27c18e8Smrg        return -1;
1720c27c18e8Smrg
1721c27c18e8Smrg    ptr_wire = (char*)from;
1722c27c18e8Smrg    ptr_lib = to->classes;
1723f1ee322dSmrg    to->classes = next_block(&ptr_lib,
1724f1ee322dSmrg                             pad_to_double((*nclasses) * sizeof(XIAnyClassInfo*)));
1725f1ee322dSmrg    memset(to->classes, 0, (*nclasses) * sizeof(XIAnyClassInfo*));
1726c27c18e8Smrg    len = 0; /* count wire length */
1727c27c18e8Smrg
1728f1ee322dSmrg    for (i = 0; i < *nclasses; i++)
1729c43cc173Smrg    {
1730c27c18e8Smrg        any_lib = (XIAnyClassInfo*)ptr_lib;
1731c27c18e8Smrg        any_wire = (xXIAnyInfo*)ptr_wire;
1732c27c18e8Smrg
1733c27c18e8Smrg        switch(any_wire->type)
1734c27c18e8Smrg        {
1735c27c18e8Smrg            case XIButtonClass:
1736c27c18e8Smrg                {
1737c27c18e8Smrg                    XIButtonClassInfo *cls_lib;
1738c27c18e8Smrg                    xXIButtonInfo *cls_wire;
1739c27c18e8Smrg                    uint32_t *atoms;
1740c27c18e8Smrg                    int j;
1741f1ee322dSmrg                    int struct_size;
1742f1ee322dSmrg                    int state_size;
1743f1ee322dSmrg                    int labels_size;
1744f1ee322dSmrg                    int wire_mask_size;
1745c27c18e8Smrg
1746c27c18e8Smrg                    cls_wire = (xXIButtonInfo*)any_wire;
1747f1ee322dSmrg                    sizeXIButtonClassType(cls_wire->num_buttons,
1748f1ee322dSmrg                                          &struct_size, &state_size,
1749f1ee322dSmrg                                          &labels_size);
1750f1ee322dSmrg                    cls_lib = next_block(&ptr_lib, struct_size);
1751f1ee322dSmrg                    wire_mask_size = ((cls_wire->num_buttons + 7)/8 + 3)/4 * 4;
1752f1ee322dSmrg
1753f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1754f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1755c27c18e8Smrg                    cls_lib->num_buttons = cls_wire->num_buttons;
1756f1ee322dSmrg                    cls_lib->state.mask_len = state_size;
1757f1ee322dSmrg                    cls_lib->state.mask = next_block(&ptr_lib, state_size);
1758c27c18e8Smrg                    memcpy(cls_lib->state.mask, &cls_wire[1],
1759f1ee322dSmrg                           wire_mask_size);
1760f1ee322dSmrg                    if (state_size != wire_mask_size)
1761f1ee322dSmrg                        memset(&cls_lib->state.mask[wire_mask_size], 0,
1762f1ee322dSmrg                               state_size - wire_mask_size);
1763c27c18e8Smrg
1764f1ee322dSmrg                    cls_lib->labels = next_block(&ptr_lib, labels_size);
1765f1ee322dSmrg
1766f1ee322dSmrg                    atoms =(uint32_t*)((char*)&cls_wire[1] + wire_mask_size);
1767c27c18e8Smrg                    for (j = 0; j < cls_lib->num_buttons; j++)
1768c27c18e8Smrg                        cls_lib->labels[j] = *atoms++;
1769c27c18e8Smrg
1770f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1771c27c18e8Smrg                    break;
1772c27c18e8Smrg                }
1773c27c18e8Smrg            case XIKeyClass:
1774c27c18e8Smrg                {
1775c27c18e8Smrg                    XIKeyClassInfo *cls_lib;
1776c27c18e8Smrg                    xXIKeyInfo *cls_wire;
1777f1ee322dSmrg                    int struct_size;
1778f1ee322dSmrg                    int keycodes_size;
1779c27c18e8Smrg
1780c27c18e8Smrg                    cls_wire = (xXIKeyInfo*)any_wire;
1781f1ee322dSmrg                    sizeXIKeyClassType(cls_wire->num_keycodes,
1782f1ee322dSmrg                                       &struct_size, &keycodes_size);
1783f1ee322dSmrg                    cls_lib = next_block(&ptr_lib, struct_size);
1784c27c18e8Smrg
1785f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1786f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1787c27c18e8Smrg                    cls_lib->num_keycodes = cls_wire->num_keycodes;
1788f1ee322dSmrg                    cls_lib->keycodes = next_block(&ptr_lib, keycodes_size);
1789c27c18e8Smrg                    memcpy(cls_lib->keycodes, &cls_wire[1],
1790c27c18e8Smrg                            cls_lib->num_keycodes);
1791c27c18e8Smrg
1792f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1793c27c18e8Smrg                    break;
1794c27c18e8Smrg                }
1795c27c18e8Smrg            case XIValuatorClass:
1796c27c18e8Smrg                {
1797c27c18e8Smrg                    XIValuatorClassInfo *cls_lib;
1798c27c18e8Smrg                    xXIValuatorInfo *cls_wire;
1799c27c18e8Smrg
1800f1ee322dSmrg                    cls_lib =
1801f1ee322dSmrg                      next_block(&ptr_lib,
1802f1ee322dSmrg                                 sizeDeviceClassType(XIValuatorClass, 0));
1803c27c18e8Smrg                    cls_wire = (xXIValuatorInfo*)any_wire;
1804c27c18e8Smrg
1805f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1806f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1807c27c18e8Smrg                    cls_lib->number = cls_wire->number;
1808c27c18e8Smrg                    cls_lib->label  = cls_wire->label;
1809c27c18e8Smrg                    cls_lib->resolution = cls_wire->resolution;
18104940c694Smrg                    cls_lib->min        = FP3232_TO_DOUBLE(cls_wire->min);
18114940c694Smrg                    cls_lib->max        = FP3232_TO_DOUBLE(cls_wire->max);
18124940c694Smrg                    cls_lib->value      = FP3232_TO_DOUBLE(cls_wire->value);
1813c27c18e8Smrg                    cls_lib->mode       = cls_wire->mode;
1814c27c18e8Smrg
1815f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1816f1ee322dSmrg                }
1817f1ee322dSmrg                break;
1818f1ee322dSmrg            case XIScrollClass:
1819f1ee322dSmrg                {
1820f1ee322dSmrg                    XIScrollClassInfo *cls_lib;
1821f1ee322dSmrg                    xXIScrollInfo *cls_wire;
1822f1ee322dSmrg
1823f1ee322dSmrg                    cls_lib =
1824f1ee322dSmrg                      next_block(&ptr_lib,
1825f1ee322dSmrg                                 sizeDeviceClassType(XIScrollClass, 0));
1826f1ee322dSmrg                    cls_wire = (xXIScrollInfo*)any_wire;
1827f1ee322dSmrg
1828f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1829f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1830f1ee322dSmrg                    cls_lib->number     = cls_wire->number;
1831f1ee322dSmrg                    cls_lib->scroll_type= cls_wire->scroll_type;
1832f1ee322dSmrg                    cls_lib->flags      = cls_wire->flags;
18334940c694Smrg                    cls_lib->increment  = FP3232_TO_DOUBLE(cls_wire->increment);
1834f1ee322dSmrg
1835f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1836f1ee322dSmrg                }
1837f1ee322dSmrg                break;
1838f1ee322dSmrg            case XITouchClass:
1839f1ee322dSmrg                {
1840f1ee322dSmrg                    XITouchClassInfo *cls_lib;
1841f1ee322dSmrg                    xXITouchInfo *cls_wire;
1842f1ee322dSmrg
1843f1ee322dSmrg                    cls_wire = (xXITouchInfo*)any_wire;
1844f1ee322dSmrg                    cls_lib = next_block(&ptr_lib, sizeof(XITouchClassInfo));
1845f1ee322dSmrg
1846f1ee322dSmrg                    cls_lib->type = cls_wire->type;
1847f1ee322dSmrg                    cls_lib->sourceid = cls_wire->sourceid;
1848f1ee322dSmrg                    cls_lib->mode = cls_wire->mode;
1849f1ee322dSmrg                    cls_lib->num_touches = cls_wire->num_touches;
1850f1ee322dSmrg
1851f1ee322dSmrg                    to->classes[cls_idx++] = any_lib;
1852c27c18e8Smrg                }
1853c27c18e8Smrg                break;
185487404ef7Smrg            case XIGestureClass:
185587404ef7Smrg                {
185687404ef7Smrg                    XIGestureClassInfo *cls_lib;
185787404ef7Smrg                    xXIGestureInfo *cls_wire;
185887404ef7Smrg
185987404ef7Smrg                    cls_wire = (xXIGestureInfo*)any_wire;
186087404ef7Smrg                    cls_lib = next_block(&ptr_lib, sizeof(XIGestureClassInfo));
186187404ef7Smrg
186287404ef7Smrg                    cls_lib->type = cls_wire->type;
186387404ef7Smrg                    cls_lib->sourceid = cls_wire->sourceid;
186487404ef7Smrg                    cls_lib->num_touches = cls_wire->num_touches;
186587404ef7Smrg
186687404ef7Smrg                    to->classes[cls_idx++] = any_lib;
186787404ef7Smrg                }
186887404ef7Smrg                break;
1869c27c18e8Smrg        }
1870c27c18e8Smrg        len += any_wire->length * 4;
1871c27c18e8Smrg        ptr_wire += any_wire->length * 4;
1872c43cc173Smrg    }
1873f1ee322dSmrg
1874f1ee322dSmrg    /* we may have skipped unknown classes, reset nclasses */
1875f1ee322dSmrg    *nclasses = cls_idx;
1876c27c18e8Smrg    return len;
1877c27c18e8Smrg}
1878c27c18e8Smrg
1879c27c18e8Smrg
1880c27c18e8Smrgstatic int
1881c27c18e8SmrgwireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie)
1882c27c18e8Smrg{
1883c27c18e8Smrg    XIDeviceChangedEvent *out;
1884c27c18e8Smrg    XIDeviceInfo info;
1885c27c18e8Smrg    int len;
1886f1ee322dSmrg    int nclasses = in->num_classes;
1887c27c18e8Smrg
1888c27c18e8Smrg    len = size_classes((xXIAnyInfo*)&in[1], in->num_classes);
1889c27c18e8Smrg
1890c27c18e8Smrg    cookie->data = out = malloc(sizeof(XIDeviceChangedEvent) + len);
1891c27c18e8Smrg
1892c27c18e8Smrg    out->type = in->type;
189344584a44Smrg    out->serial = cookie->serial;
189489069ce9Smrg    out->display = cookie->display;
1895c27c18e8Smrg    out->extension = in->extension;
1896c27c18e8Smrg    out->evtype = in->evtype;
1897c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
1898c27c18e8Smrg    out->time = in->time;
1899c27c18e8Smrg    out->deviceid = in->deviceid;
1900c27c18e8Smrg    out->sourceid = in->sourceid;
1901c27c18e8Smrg    out->reason = in->reason;
1902c27c18e8Smrg
1903c27c18e8Smrg    out->classes = (XIAnyClassInfo**)&out[1];
1904c27c18e8Smrg
1905c27c18e8Smrg    info.classes = out->classes;
1906c27c18e8Smrg
1907f1ee322dSmrg    copy_classes(&info, (xXIAnyInfo*)&in[1], &nclasses);
1908f1ee322dSmrg    out->num_classes = nclasses;
1909c27c18e8Smrg
1910c27c18e8Smrg    return 1;
1911c27c18e8Smrg}
1912c27c18e8Smrg
1913c27c18e8Smrgstatic int
1914c27c18e8SmrgwireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie)
1915c27c18e8Smrg{
1916c27c18e8Smrg    int i;
1917c27c18e8Smrg    XIHierarchyInfo *info_out;
1918c27c18e8Smrg    xXIHierarchyInfo *info_in;
1919c27c18e8Smrg    XIHierarchyEvent *out;
1920c27c18e8Smrg
1921c27c18e8Smrg    cookie->data = out = malloc(sizeof(XIHierarchyEvent) + in->num_info * sizeof(XIHierarchyInfo));;
1922c27c18e8Smrg
1923c27c18e8Smrg    out->info           = (XIHierarchyInfo*)&out[1];
192489069ce9Smrg    out->display        = cookie->display;
1925c27c18e8Smrg    out->type           = in->type;
192644584a44Smrg    out->serial         = cookie->serial;
1927c27c18e8Smrg    out->extension      = in->extension;
1928c27c18e8Smrg    out->evtype         = in->evtype;
1929c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
1930c27c18e8Smrg    out->time           = in->time;
1931c27c18e8Smrg    out->flags          = in->flags;
1932c27c18e8Smrg    out->num_info       = in->num_info;
1933c27c18e8Smrg
1934c27c18e8Smrg    info_out            = out->info;
1935c27c18e8Smrg    info_in             = (xXIHierarchyInfo*)&in[1];
1936c27c18e8Smrg
1937c27c18e8Smrg    for (i = 0; i < out->num_info; i++, info_out++, info_in++)
1938c43cc173Smrg    {
1939c27c18e8Smrg        info_out->deviceid      = info_in->deviceid;
1940c27c18e8Smrg        info_out->attachment    = info_in->attachment;
1941c27c18e8Smrg        info_out->use           = info_in->use;
1942c27c18e8Smrg        info_out->enabled       = info_in->enabled;
1943c27c18e8Smrg        info_out->flags         = info_in->flags;
1944c43cc173Smrg    }
1945c43cc173Smrg
1946c27c18e8Smrg    return 1;
1947c27c18e8Smrg}
1948c27c18e8Smrg
1949c27c18e8Smrgstatic int
1950f1ee322dSmrgwireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *cookie)
1951c27c18e8Smrg{
1952c27c18e8Smrg    int len, i, bits;
1953c27c18e8Smrg    FP3232 *values;
1954c27c18e8Smrg    XIRawEvent *out;
1955c27c18e8Smrg    void *ptr;
1956c27c18e8Smrg
1957c27c18e8Smrg    len = sizeof(XIRawEvent) + in->valuators_len * 4;
1958c27c18e8Smrg    bits = count_bits((unsigned char*)&in[1], in->valuators_len * 4);
1959c27c18e8Smrg    len += bits * sizeof(double) * 2; /* raw + normal */
1960c27c18e8Smrg
1961c27c18e8Smrg    cookie->data = ptr = calloc(1, len);
1962c27c18e8Smrg    if (!ptr)
1963c27c18e8Smrg        return 0;
1964c27c18e8Smrg
1965c27c18e8Smrg    out = next_block(&ptr, sizeof(XIRawEvent));
1966c27c18e8Smrg    out->type           = in->type;
196744584a44Smrg    out->serial         = cookie->serial;
196889069ce9Smrg    out->display        = cookie->display;
1969c27c18e8Smrg    out->extension      = in->extension;
1970c27c18e8Smrg    out->evtype         = in->evtype;
1971c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
1972c27c18e8Smrg    out->time           = in->time;
1973c27c18e8Smrg    out->detail         = in->detail;
1974c27c18e8Smrg    out->deviceid       = in->deviceid;
1975c27c18e8Smrg    out->flags          = in->flags;
1976c27c18e8Smrg
1977f1ee322dSmrg    /* https://bugs.freedesktop.org/show_bug.cgi?id=34240 */
1978f1ee322dSmrg    if (_XiCheckVersion(info, XInput_2_2) >= 0)
1979f1ee322dSmrg        out->sourceid       = in->sourceid;
1980f1ee322dSmrg    else
1981f1ee322dSmrg        out->sourceid       = 0;
1982f1ee322dSmrg
1983c27c18e8Smrg    out->valuators.mask_len = in->valuators_len * 4;
1984c27c18e8Smrg    out->valuators.mask = next_block(&ptr, out->valuators.mask_len);
1985c27c18e8Smrg    memcpy(out->valuators.mask, &in[1], out->valuators.mask_len);
1986c27c18e8Smrg
1987c27c18e8Smrg    out->valuators.values = next_block(&ptr, bits * sizeof(double));
1988c27c18e8Smrg    out->raw_values = next_block(&ptr, bits * sizeof(double));
1989c27c18e8Smrg
1990c27c18e8Smrg    values = (FP3232*)(((char*)&in[1]) + in->valuators_len * 4);
1991c27c18e8Smrg    for (i = 0; i < bits; i++)
1992c43cc173Smrg    {
1993c27c18e8Smrg        out->valuators.values[i] = values->integral;
1994c27c18e8Smrg        out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16));
1995c27c18e8Smrg        out->raw_values[i] = (values + bits)->integral;
199637eb1ca1Smrg        out->raw_values[i] += ((double)(values + bits)->frac / (1 << 16) / (1 << 16));
1997c27c18e8Smrg        values++;
1998c43cc173Smrg    }
1999c43cc173Smrg
2000c27c18e8Smrg    return 1;
2001c27c18e8Smrg}
200221e67964Smrg
2003c27c18e8Smrg/* Memory layout of XIEnterEvents:
2004c27c18e8Smrg   [event][modifiers][group][button]
2005c27c18e8Smrg */
2006c27c18e8Smrgstatic int
2007c27c18e8SmrgwireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie)
2008c27c18e8Smrg{
2009c27c18e8Smrg    int len;
2010c27c18e8Smrg    XIEnterEvent *out;
2011c27c18e8Smrg
2012c27c18e8Smrg    len = sizeof(XIEnterEvent) + in->buttons_len * 4;
2013c27c18e8Smrg
2014c27c18e8Smrg    cookie->data = out = malloc(len);
2015c27c18e8Smrg    out->buttons.mask = (unsigned char*)&out[1];
2016c27c18e8Smrg
2017c27c18e8Smrg    out->type           = in->type;
201844584a44Smrg    out->serial         = cookie->serial;
201989069ce9Smrg    out->display        = cookie->display;
2020c27c18e8Smrg    out->extension      = in->extension;
2021c27c18e8Smrg    out->evtype         = in->evtype;
2022c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
2023c27c18e8Smrg    out->time           = in->time;
2024c27c18e8Smrg    out->detail         = in->detail;
2025c27c18e8Smrg    out->deviceid       = in->deviceid;
2026c27c18e8Smrg    out->root           = in->root;
2027c27c18e8Smrg    out->event          = in->event;
2028c27c18e8Smrg    out->child          = in->child;
2029c27c18e8Smrg    out->sourceid       = in->sourceid;
2030c27c18e8Smrg    out->root_x         = FP1616toDBL(in->root_x);
2031c27c18e8Smrg    out->root_y         = FP1616toDBL(in->root_y);
2032c27c18e8Smrg    out->event_x        = FP1616toDBL(in->event_x);
2033c27c18e8Smrg    out->event_y        = FP1616toDBL(in->event_y);
2034c27c18e8Smrg    out->mode           = in->mode;
2035c27c18e8Smrg    out->focus          = in->focus;
2036c27c18e8Smrg    out->same_screen    = in->same_screen;
2037c27c18e8Smrg
2038c27c18e8Smrg    out->mods.base = in->mods.base_mods;
2039c27c18e8Smrg    out->mods.locked = in->mods.locked_mods;
2040c27c18e8Smrg    out->mods.latched = in->mods.latched_mods;
2041c27c18e8Smrg    out->mods.effective = in->mods.effective_mods;
2042c27c18e8Smrg    out->group.base = in->group.base_group;
2043c27c18e8Smrg    out->group.locked = in->group.locked_group;
2044c27c18e8Smrg    out->group.latched = in->group.latched_group;
2045c27c18e8Smrg    out->group.effective = in->group.effective_group;
2046c27c18e8Smrg
2047c27c18e8Smrg    out->buttons.mask_len = in->buttons_len * 4;
2048c27c18e8Smrg    memcpy(out->buttons.mask, &in[1], out->buttons.mask_len);
204921e67964Smrg
2050c27c18e8Smrg    return 1;
2051c27c18e8Smrg}
2052c43cc173Smrg
2053c27c18e8Smrgstatic int
2054c27c18e8SmrgwireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie)
2055c27c18e8Smrg{
2056c27c18e8Smrg    XIPropertyEvent *out = malloc(sizeof(XIPropertyEvent));
2057c27c18e8Smrg
2058c27c18e8Smrg    cookie->data = out;
2059c27c18e8Smrg
2060c27c18e8Smrg    out->type           = in->type;
206144584a44Smrg    out->serial         = cookie->serial;
2062c27c18e8Smrg    out->extension      = in->extension;
2063c27c18e8Smrg    out->evtype         = in->evtype;
2064c27c18e8Smrg    out->send_event = ((in->type & 0x80) != 0);
2065c27c18e8Smrg    out->time           = in->time;
2066c27c18e8Smrg    out->property       = in->property;
2067c27c18e8Smrg    out->what           = in->what;
2068c27c18e8Smrg    out->deviceid       = in->deviceid;
2069c27c18e8Smrg
2070c27c18e8Smrg    return 1;
2071c43cc173Smrg}
2072f1ee322dSmrg
2073f1ee322dSmrgstatic int
2074f1ee322dSmrgwireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
2075f1ee322dSmrg                          XGenericEventCookie *cookie)
2076f1ee322dSmrg{
2077f1ee322dSmrg    XITouchOwnershipEvent *out = malloc(sizeof(XITouchOwnershipEvent));
2078f1ee322dSmrg
2079f1ee322dSmrg    cookie->data = out;
2080f1ee322dSmrg
2081f1ee322dSmrg    out->type           = in->type;
208244584a44Smrg    out->serial         = cookie->serial;
2083f1ee322dSmrg    out->display        = cookie->display;
2084f1ee322dSmrg    out->extension      = in->extension;
2085f1ee322dSmrg    out->evtype         = in->evtype;
2086f1ee322dSmrg    out->send_event     = ((in->type & 0x80) != 0);
2087f1ee322dSmrg    out->time           = in->time;
2088f1ee322dSmrg    out->deviceid       = in->deviceid;
2089f1ee322dSmrg    out->sourceid       = in->sourceid;
2090f1ee322dSmrg    out->touchid        = in->touchid;
2091f1ee322dSmrg    out->root           = in->root;
2092f1ee322dSmrg    out->event          = in->event;
2093f1ee322dSmrg    out->child          = in->child;
2094f1ee322dSmrg    out->flags          = in->flags;
2095f1ee322dSmrg
2096f1ee322dSmrg    return 1;
2097f1ee322dSmrg}
2098f1ee322dSmrg
2099f1ee322dSmrgstatic int
2100f1ee322dSmrgwireToBarrierEvent(xXIBarrierEvent *in, XGenericEventCookie *cookie)
2101f1ee322dSmrg{
2102f1ee322dSmrg    XIBarrierEvent *out = malloc(sizeof(XIBarrierEvent));
2103f1ee322dSmrg
2104f1ee322dSmrg    cookie->data = out;
2105f1ee322dSmrg
2106f1ee322dSmrg    out->display    = cookie->display;
2107f1ee322dSmrg    out->type       = in->type;
210844584a44Smrg    out->serial     = cookie->serial;
2109f1ee322dSmrg    out->extension  = in->extension;
2110f1ee322dSmrg    out->evtype     = in->evtype;
2111f1ee322dSmrg    out->send_event = ((in->type & 0x80) != 0);
2112f1ee322dSmrg    out->time       = in->time;
2113f1ee322dSmrg    out->deviceid   = in->deviceid;
2114f1ee322dSmrg    out->sourceid   = in->sourceid;
2115f1ee322dSmrg    out->event      = in->event;
2116f1ee322dSmrg    out->root       = in->root;
2117f1ee322dSmrg    out->root_x     = FP1616toDBL(in->root_x);
2118f1ee322dSmrg    out->root_y     = FP1616toDBL(in->root_y);
2119f1ee322dSmrg    out->dx         = FP3232_TO_DOUBLE (in->dx);
2120f1ee322dSmrg    out->dy         = FP3232_TO_DOUBLE (in->dy);
2121f1ee322dSmrg    out->dtime      = in->dtime;
2122f1ee322dSmrg    out->flags      = in->flags;
2123f1ee322dSmrg    out->barrier    = in->barrier;
2124f1ee322dSmrg    out->eventid    = in->eventid;
2125f1ee322dSmrg
2126f1ee322dSmrg    return 1;
2127f1ee322dSmrg}
212887404ef7Smrg
212987404ef7Smrgstatic int
213087404ef7SmrgwireToPinchEvent(xXIGesturePinchEvent *in,
213187404ef7Smrg                 XGenericEventCookie *cookie)
213287404ef7Smrg{
213387404ef7Smrg    XIGesturePinchEvent *out;
213487404ef7Smrg
213587404ef7Smrg    cookie->data = out = malloc(sizeof(XIGesturePinchEvent));
213687404ef7Smrg
213787404ef7Smrg    out->display    = cookie->display;
213887404ef7Smrg    out->type       = in->type;
213987404ef7Smrg    out->serial     = cookie->serial;
214087404ef7Smrg    out->extension  = in->extension;
214187404ef7Smrg    out->evtype     = in->evtype;
214287404ef7Smrg    out->send_event = ((in->type & 0x80) != 0);
214387404ef7Smrg    out->time       = in->time;
214487404ef7Smrg    out->deviceid   = in->deviceid;
214587404ef7Smrg    out->sourceid   = in->sourceid;
214687404ef7Smrg    out->detail     = in->detail;
214787404ef7Smrg    out->root       = in->root;
214887404ef7Smrg    out->event      = in->event;
214987404ef7Smrg    out->child      = in->child;
215087404ef7Smrg    out->root_x     = FP1616toDBL(in->root_x);
215187404ef7Smrg    out->root_y     = FP1616toDBL(in->root_y);
215287404ef7Smrg    out->event_x    = FP1616toDBL(in->event_x);
215387404ef7Smrg    out->event_y    = FP1616toDBL(in->event_y);
215487404ef7Smrg    out->delta_x    = FP1616toDBL(in->delta_x);
215587404ef7Smrg    out->delta_y    = FP1616toDBL(in->delta_y);
215687404ef7Smrg    out->delta_unaccel_x = FP1616toDBL(in->delta_unaccel_x);
215787404ef7Smrg    out->delta_unaccel_y = FP1616toDBL(in->delta_unaccel_y);
215887404ef7Smrg    out->scale      = FP1616toDBL(in->scale);
215987404ef7Smrg    out->delta_angle = FP1616toDBL(in->delta_angle);
216087404ef7Smrg    out->flags      = in->flags;
216187404ef7Smrg
216287404ef7Smrg    out->mods.base = in->mods.base_mods;
216387404ef7Smrg    out->mods.locked = in->mods.locked_mods;
216487404ef7Smrg    out->mods.latched = in->mods.latched_mods;
216587404ef7Smrg    out->mods.effective = in->mods.effective_mods;
216687404ef7Smrg    out->group.base = in->group.base_group;
216787404ef7Smrg    out->group.locked = in->group.locked_group;
216887404ef7Smrg    out->group.latched = in->group.latched_group;
216987404ef7Smrg    out->group.effective = in->group.effective_group;
217087404ef7Smrg
217187404ef7Smrg    return 1;
217287404ef7Smrg}
217387404ef7Smrg
217487404ef7Smrgstatic int
217587404ef7SmrgwireToSwipeEvent(xXIGestureSwipeEvent *in,
217687404ef7Smrg                 XGenericEventCookie *cookie)
217787404ef7Smrg{
217887404ef7Smrg    XIGestureSwipeEvent *out;
217987404ef7Smrg
218087404ef7Smrg    cookie->data = out = malloc(sizeof(XIGestureSwipeEvent));
218187404ef7Smrg
218287404ef7Smrg    out->display    = cookie->display;
218387404ef7Smrg    out->type       = in->type;
218487404ef7Smrg    out->serial     = cookie->serial;
218587404ef7Smrg    out->extension  = in->extension;
218687404ef7Smrg    out->evtype     = in->evtype;
218787404ef7Smrg    out->send_event = ((in->type & 0x80) != 0);
218887404ef7Smrg    out->time       = in->time;
218987404ef7Smrg    out->deviceid   = in->deviceid;
219087404ef7Smrg    out->sourceid   = in->sourceid;
219187404ef7Smrg    out->detail     = in->detail;
219287404ef7Smrg    out->root       = in->root;
219387404ef7Smrg    out->event      = in->event;
219487404ef7Smrg    out->child      = in->child;
219587404ef7Smrg    out->root_x     = FP1616toDBL(in->root_x);
219687404ef7Smrg    out->root_y     = FP1616toDBL(in->root_y);
219787404ef7Smrg    out->event_x    = FP1616toDBL(in->event_x);
219887404ef7Smrg    out->event_y    = FP1616toDBL(in->event_y);
219987404ef7Smrg    out->delta_x    = FP1616toDBL(in->delta_x);
220087404ef7Smrg    out->delta_y    = FP1616toDBL(in->delta_y);
220187404ef7Smrg    out->delta_unaccel_x = FP1616toDBL(in->delta_unaccel_x);
220287404ef7Smrg    out->delta_unaccel_y = FP1616toDBL(in->delta_unaccel_y);
220387404ef7Smrg    out->flags      = in->flags;
220487404ef7Smrg
220587404ef7Smrg    out->mods.base = in->mods.base_mods;
220687404ef7Smrg    out->mods.locked = in->mods.locked_mods;
220787404ef7Smrg    out->mods.latched = in->mods.latched_mods;
220887404ef7Smrg    out->mods.effective = in->mods.effective_mods;
220987404ef7Smrg    out->group.base = in->group.base_group;
221087404ef7Smrg    out->group.locked = in->group.locked_group;
221187404ef7Smrg    out->group.latched = in->group.latched_group;
221287404ef7Smrg    out->group.effective = in->group.effective_group;
221387404ef7Smrg
221487404ef7Smrg    return 1;
221587404ef7Smrg}
2216