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