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