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