XExtInt.c revision f1ee322d
1c43cc173Smrg/************************************************************ 2c43cc173Smrg 3c43cc173SmrgCopyright 1989, 1998 The Open Group 4c43cc173Smrg 5c43cc173SmrgPermission to use, copy, modify, distribute, and sell this software and its 6c43cc173Smrgdocumentation for any purpose is hereby granted without fee, provided that 7c43cc173Smrgthe above copyright notice appear in all copies and that both that 8c43cc173Smrgcopyright notice and this permission notice appear in supporting 9c43cc173Smrgdocumentation. 10c43cc173Smrg 11c43cc173SmrgThe above copyright notice and this permission notice shall be included in 12c43cc173Smrgall copies or substantial portions of the Software. 13c43cc173Smrg 14c43cc173SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15c43cc173SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16c43cc173SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17c43cc173SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18c43cc173SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19c43cc173SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20c43cc173Smrg 21c43cc173SmrgExcept as contained in this notice, the name of The Open Group shall not be 22c43cc173Smrgused in advertising or otherwise to promote the sale, use or other dealings 23c43cc173Smrgin this Software without prior written authorization from The Open Group. 24c43cc173Smrg 25c43cc173SmrgCopyright 1989 by Hewlett-Packard Company, Palo Alto, California. 26c43cc173Smrg 27c43cc173Smrg All Rights Reserved 28c43cc173Smrg 29c43cc173SmrgPermission to use, copy, modify, and distribute this software and its 30c43cc173Smrgdocumentation for any purpose and without fee is hereby granted, 31c43cc173Smrgprovided that the above copyright notice appear in all copies and that 32c43cc173Smrgboth that copyright notice and this permission notice appear in 33c43cc173Smrgsupporting documentation, and that the name of Hewlett-Packard not be 34c43cc173Smrgused in advertising or publicity pertaining to distribution of the 35c43cc173Smrgsoftware without specific, written prior permission. 36c43cc173Smrg 37c43cc173SmrgHEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38c43cc173SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39c43cc173SmrgHEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40c43cc173SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41c43cc173SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42c43cc173SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43c43cc173SmrgSOFTWARE. 44c43cc173Smrg 45c43cc173Smrg********************************************************/ 46c43cc173Smrg 47c43cc173Smrg/*********************************************************************** 48c43cc173Smrg * 49c43cc173Smrg * Input Extension library internal functions. 50c43cc173Smrg * 51c43cc173Smrg */ 52c43cc173Smrg 53f1ee322dSmrg#if HAVE_CONFIG_H 54f1ee322dSmrg#include <config.h> 55f1ee322dSmrg#endif 56f1ee322dSmrg 57c43cc173Smrg#include <stdio.h> 58c27c18e8Smrg#include <stdint.h> 59c43cc173Smrg#include <X11/extensions/XI.h> 60c27c18e8Smrg#include <X11/extensions/XI2.h> 61c43cc173Smrg#include <X11/extensions/XIproto.h> 62c27c18e8Smrg#include <X11/extensions/XI2proto.h> 63c43cc173Smrg#include <X11/Xlibint.h> 64c43cc173Smrg#include <X11/extensions/XInput.h> 65c27c18e8Smrg#include <X11/extensions/XInput2.h> 66c43cc173Smrg#include <X11/extensions/extutil.h> 67c27c18e8Smrg#include <X11/extensions/geproto.h> 68c27c18e8Smrg#include <X11/extensions/ge.h> 69c27c18e8Smrg#include <X11/extensions/Xge.h> 70c43cc173Smrg#include "XIint.h" 71c43cc173Smrg 72c43cc173Smrg#define ENQUEUE_EVENT True 73c43cc173Smrg#define DONT_ENQUEUE False 74c27c18e8Smrg#define FP1616toDBL(x) ((x) * 1.0 / (1 << 16)) 75c27c18e8Smrg 76f1ee322dSmrgint copy_classes(XIDeviceInfo *to, xXIAnyInfo* from, int *nclasses); 77c27c18e8Smrgint size_classes(xXIAnyInfo* from, int nclasses); 78c43cc173Smrg 79c43cc173Smrgstatic XExtensionInfo *xinput_info; 80f1ee322dSmrgstatic const char *xinput_extension_name = INAME; 81c43cc173Smrg 82c27c18e8Smrgstatic int XInputClose( 83c27c18e8Smrg Display * /* dpy */, 84c27c18e8Smrg XExtCodes * /* codes */ 85c27c18e8Smrg); 86c27c18e8Smrg 87c27c18e8Smrgstatic char *XInputError( 88c27c18e8Smrg Display * /* dpy */, 89c27c18e8Smrg int /* code */, 90c27c18e8Smrg XExtCodes * /* codes */, 91c27c18e8Smrg char * /* buf */, 92c27c18e8Smrg int /* n */ 93c27c18e8Smrg); 94c27c18e8Smrg 95c27c18e8Smrgstatic Bool XInputWireToEvent( 96c27c18e8Smrg Display * /* dpy */, 97c27c18e8Smrg XEvent * /* re */, 98c27c18e8Smrg xEvent * /* event */ 99c27c18e8Smrg); 100c27c18e8Smrgstatic Bool XInputWireToCookie( 101c27c18e8Smrg Display* /* display */, 102c27c18e8Smrg XGenericEventCookie* /* re */, 103c27c18e8Smrg xEvent* /* event */ 104c27c18e8Smrg); 105c27c18e8Smrg 106c27c18e8Smrgstatic Bool XInputCopyCookie( 107c27c18e8Smrg Display* /* display */, 108c27c18e8Smrg XGenericEventCookie* /* in */, 109c27c18e8Smrg XGenericEventCookie* /* out */ 110c27c18e8Smrg); 111c27c18e8Smrg 112c27c18e8Smrgstatic int 113c27c18e8SmrgwireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* out); 114c27c18e8Smrgstatic int 115c27c18e8SmrgwireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie); 116c27c18e8Smrgstatic int 117c27c18e8SmrgwireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie); 118c27c18e8Smrgstatic int 119f1ee322dSmrgwireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *cookie); 120c27c18e8Smrgstatic int 121c27c18e8SmrgwireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie); 122c27c18e8Smrgstatic int 123c27c18e8SmrgwireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie); 124f1ee322dSmrgstatic int 125f1ee322dSmrgwireToTouchOwnershipEvent(xXITouchOwnershipEvent *in, 126f1ee322dSmrg XGenericEventCookie *cookie); 127f1ee322dSmrgstatic int 128f1ee322dSmrgwireToBarrierEvent(xXIBarrierEvent *in, 129f1ee322dSmrg XGenericEventCookie *cookie); 130c27c18e8Smrg 131c27c18e8Smrgstatic /* const */ XEvent emptyevent; 132c43cc173Smrg 133f1ee322dSmrgtypedef Status (*core_event_to_wire)(Display*, XEvent*, xEvent*); 134f1ee322dSmrg 135c43cc173Smrgstatic /* const */ XExtensionHooks xinput_extension_hooks = { 136c43cc173Smrg NULL, /* create_gc */ 137c43cc173Smrg NULL, /* copy_gc */ 138c43cc173Smrg NULL, /* flush_gc */ 139c43cc173Smrg NULL, /* free_gc */ 140c43cc173Smrg NULL, /* create_font */ 141c43cc173Smrg NULL, /* free_font */ 142c43cc173Smrg XInputClose, /* close_display */ 143c43cc173Smrg XInputWireToEvent, /* wire_to_event */ 144f1ee322dSmrg (core_event_to_wire)_XiEventToWire, /* event_to_wire */ 145c43cc173Smrg NULL, /* error */ 146c43cc173Smrg XInputError, /* error_string */ 147c43cc173Smrg}; 148c43cc173Smrg 149f1ee322dSmrgstatic const char *XInputErrorList[] = { 150c43cc173Smrg "BadDevice, invalid or uninitialized input device", /* BadDevice */ 151c43cc173Smrg "BadEvent, invalid event type", /* BadEvent */ 152c43cc173Smrg "BadMode, invalid mode parameter", /* BadMode */ 153c43cc173Smrg "DeviceBusy, device is busy", /* DeviceBusy */ 154c43cc173Smrg "BadClass, invalid event class", /* BadClass */ 155c43cc173Smrg}; 156c43cc173Smrg 1573e256790Smrg/* Get the version supported by the server to know which number of 1583e256790Smrg* events are support. Otherwise, a wrong number of events may smash 1593e256790Smrg* the Xlib-internal event processing vector. 1603e256790Smrg* 1613e256790Smrg* Since the extension hasn't been initialized yet, we need to 1623e256790Smrg* manually get the opcode, then the version. 1633e256790Smrg*/ 1643e256790Smrgstatic int 1653e256790Smrg_XiFindEventsSupported(Display *dpy) 1663e256790Smrg{ 1673e256790Smrg XExtCodes codes; 1683e256790Smrg XExtensionVersion *extversion = NULL; 1693e256790Smrg int nevents = 0; 1703e256790Smrg 1713e256790Smrg if (!XQueryExtension(dpy, INAME, &codes.major_opcode, 1723e256790Smrg &codes.first_event, &codes.first_error)) 1733e256790Smrg goto out; 1743e256790Smrg 1753e256790Smrg LockDisplay(dpy); 1763e256790Smrg extversion = _XiGetExtensionVersionRequest(dpy, INAME, codes.major_opcode); 1773e256790Smrg UnlockDisplay(dpy); 1783e256790Smrg SyncHandle(); 1793e256790Smrg 1803e256790Smrg if (!extversion || !extversion->present) 1813e256790Smrg goto out; 1823e256790Smrg 1833e256790Smrg if (extversion->major_version >= 2) 1843e256790Smrg nevents = IEVENTS; /* number is fixed, XI2 adds GenericEvents only */ 1853e256790Smrg else if (extversion->major_version <= 0) 1863e256790Smrg { 1873e256790Smrg printf("XInput_find_display: invalid extension version %d.%d\n", 1883e256790Smrg extversion->major_version, extversion->minor_version); 1893e256790Smrg goto out; 1903e256790Smrg } 1913e256790Smrg else 1923e256790Smrg { 1933e256790Smrg switch(extversion->minor_version) 1943e256790Smrg { 1953e256790Smrg case XI_Add_DeviceProperties_Minor: 1963e256790Smrg nevents = XI_DevicePropertyNotify + 1; 1973e256790Smrg break; 1983e256790Smrg case XI_Add_DevicePresenceNotify_Minor: 1993e256790Smrg nevents = XI_DevicePresenceNotify + 1; 2003e256790Smrg break; 2013e256790Smrg default: 2023e256790Smrg nevents = XI_DeviceButtonstateNotify + 1; 2033e256790Smrg break; 2043e256790Smrg } 2053e256790Smrg } 2063e256790Smrg 2073e256790Smrgout: 2083e256790Smrg if (extversion) 2093e256790Smrg XFree(extversion); 2103e256790Smrg return nevents; 2113e256790Smrg} 2123e256790Smrg 2133e256790Smrg 214c27c18e8Smrg_X_HIDDEN 215c27c18e8SmrgXExtDisplayInfo *XInput_find_display (Display *dpy) 216c27c18e8Smrg{ 217c27c18e8Smrg XExtDisplayInfo *dpyinfo; 218c27c18e8Smrg if (!xinput_info) { if (!(xinput_info = XextCreateExtension())) return NULL; } 219c27c18e8Smrg if (!(dpyinfo = XextFindDisplay (xinput_info, dpy))) 220c27c18e8Smrg { 2213e256790Smrg int nevents = _XiFindEventsSupported(dpy); 2223e256790Smrg 223c27c18e8Smrg dpyinfo = XextAddDisplay (xinput_info, dpy, 224c27c18e8Smrg xinput_extension_name, 225c27c18e8Smrg &xinput_extension_hooks, 2263e256790Smrg nevents, NULL); 2273e256790Smrg if (dpyinfo->codes) /* NULL if XI doesn't exist on the server */ 2283e256790Smrg { 2293e256790Smrg XESetWireToEventCookie(dpy, dpyinfo->codes->major_opcode, XInputWireToCookie); 2303e256790Smrg XESetCopyEventCookie(dpy, dpyinfo->codes->major_opcode, XInputCopyCookie); 2313e256790Smrg } 232c27c18e8Smrg } 233c27c18e8Smrg return dpyinfo; 234c27c18e8Smrg} 235c43cc173Smrg 236c27c18e8Smrgstatic XEXT_GENERATE_ERROR_STRING(XInputError, xinput_extension_name, 237c27c18e8Smrg IERRORS, XInputErrorList) 238c43cc173Smrg/******************************************************************* 239c27c18e8Smrg* 240c27c18e8Smrg* Input extension versions. 241c27c18e8Smrg* 242c27c18e8Smrg*/ 243c27c18e8Smrgstatic XExtensionVersion versions[] = { {XI_Absent, 0, 0}, 244c27c18e8Smrg{XI_Present, XI_Initial_Release_Major, XI_Initial_Release_Minor}, 245c27c18e8Smrg{XI_Present, XI_Add_XDeviceBell_Major, XI_Add_XDeviceBell_Minor}, 246c27c18e8Smrg{XI_Present, XI_Add_XSetDeviceValuators_Major, 247c27c18e8Smrg XI_Add_XSetDeviceValuators_Minor}, 248c27c18e8Smrg{XI_Present, XI_Add_XChangeDeviceControl_Major, 249c27c18e8Smrg XI_Add_XChangeDeviceControl_Minor}, 250c27c18e8Smrg{XI_Present, XI_Add_DevicePresenceNotify_Major, 251c27c18e8Smrg XI_Add_DevicePresenceNotify_Minor}, 252c27c18e8Smrg{XI_Present, XI_Add_DeviceProperties_Major, 253c27c18e8Smrg XI_Add_DeviceProperties_Minor}, 254f1ee322dSmrg{XI_Present, 2, 0}, 255f1ee322dSmrg{XI_Present, 2, 1}, 256f1ee322dSmrg{XI_Present, 2, 2} 257c27c18e8Smrg}; 258c43cc173Smrg 259c43cc173Smrg/*********************************************************************** 260c43cc173Smrg * 261c43cc173Smrg * Return errors reported by this extension. 262c43cc173Smrg * 263c43cc173Smrg */ 264c43cc173Smrg 265c43cc173Smrgvoid 266c27c18e8Smrg_xibaddevice( 267c27c18e8Smrg Display *dpy, 268c27c18e8Smrg int *error) 269c43cc173Smrg{ 270c43cc173Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 271c43cc173Smrg 272c43cc173Smrg *error = info->codes->first_error + XI_BadDevice; 273c43cc173Smrg} 274c43cc173Smrg 275c43cc173Smrgvoid 276c27c18e8Smrg_xibadclass( 277c27c18e8Smrg Display *dpy, 278c27c18e8Smrg int *error) 279c43cc173Smrg{ 280c43cc173Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 281c43cc173Smrg 282c43cc173Smrg *error = info->codes->first_error + XI_BadClass; 283c43cc173Smrg} 284c43cc173Smrg 285c43cc173Smrgvoid 286c27c18e8Smrg_xibadevent( 287c27c18e8Smrg Display *dpy, 288c27c18e8Smrg int *error) 289c43cc173Smrg{ 290c43cc173Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 291c43cc173Smrg 292c43cc173Smrg *error = info->codes->first_error + XI_BadEvent; 293c43cc173Smrg} 294c43cc173Smrg 295c43cc173Smrgvoid 296c27c18e8Smrg_xibadmode( 297c27c18e8Smrg Display *dpy, 298c27c18e8Smrg int *error) 299c43cc173Smrg{ 300c43cc173Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 301c43cc173Smrg 302c43cc173Smrg *error = info->codes->first_error + XI_BadMode; 303c43cc173Smrg} 304c43cc173Smrg 305c43cc173Smrgvoid 306c27c18e8Smrg_xidevicebusy( 307c27c18e8Smrg Display *dpy, 308c27c18e8Smrg int *error) 309c43cc173Smrg{ 310c43cc173Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 311c43cc173Smrg 312c43cc173Smrg *error = info->codes->first_error + XI_DeviceBusy; 313c43cc173Smrg} 314c43cc173Smrg 315c43cc173Smrgstatic int XInputCheckExtension(Display *dpy, XExtDisplayInfo *info) 316c43cc173Smrg{ 317c43cc173Smrg XextCheckExtension (dpy, info, xinput_extension_name, 0); 318c43cc173Smrg return 1; 319c43cc173Smrg} 320c43cc173Smrg 321f1ee322dSmrg/***************************************************************** 322f1ee322dSmrg * Compare version numbers between info and the built-in version table. 323f1ee322dSmrg * Returns 324f1ee322dSmrg * -1 if info's version is less than version_index's version, 325f1ee322dSmrg * 0 if equal (or DontCheck), 326f1ee322dSmrg * 1 if info's version is greater than version_index's version. 327f1ee322dSmrg * Returns -2 on initialization errors which shouldn't happen if you call it 328f1ee322dSmrg * correctly. 329f1ee322dSmrg */ 330f1ee322dSmrg_X_HIDDEN int 331f1ee322dSmrg_XiCheckVersion(XExtDisplayInfo *info, 332f1ee322dSmrg int version_index) 333f1ee322dSmrg{ 334f1ee322dSmrg XExtensionVersion *ext; 335f1ee322dSmrg 336f1ee322dSmrg if (versions[version_index].major_version == Dont_Check) 337f1ee322dSmrg return 0; 338f1ee322dSmrg 339f1ee322dSmrg if (!info->data) 340f1ee322dSmrg return -2; 341f1ee322dSmrg 342f1ee322dSmrg ext = ((XInputData *) info->data)->vers; 343f1ee322dSmrg if (!ext) 344f1ee322dSmrg return -2; 345f1ee322dSmrg 346f1ee322dSmrg if (ext->major_version == versions[version_index].major_version && 347f1ee322dSmrg ext->minor_version == versions[version_index].minor_version) 348f1ee322dSmrg return 0; 349f1ee322dSmrg 350f1ee322dSmrg if (ext->major_version < versions[version_index].major_version || 351f1ee322dSmrg (ext->major_version == versions[version_index].major_version && 352f1ee322dSmrg ext->minor_version < versions[version_index].minor_version)) 353f1ee322dSmrg return -1; 354f1ee322dSmrg else 355f1ee322dSmrg return 1; 356f1ee322dSmrg} 357f1ee322dSmrg 358c43cc173Smrg/*********************************************************************** 359c43cc173Smrg * 360c43cc173Smrg * Check to see if the input extension is installed in the server. 361c43cc173Smrg * Also check to see if the version is >= the requested version. 362c43cc173Smrg * 363c43cc173Smrg */ 364c43cc173Smrg 365c27c18e8Smrg_X_HIDDEN int 366c27c18e8Smrg_XiCheckExtInit( 367c27c18e8Smrg register Display *dpy, 368c27c18e8Smrg register int version_index, 369c27c18e8Smrg XExtDisplayInfo *info) 370c43cc173Smrg{ 371c43cc173Smrg if (!XInputCheckExtension(dpy, info)) { 372c43cc173Smrg UnlockDisplay(dpy); 373c43cc173Smrg return (-1); 374c43cc173Smrg } 375c43cc173Smrg 376c43cc173Smrg if (info->data == NULL) { 377c43cc173Smrg info->data = (XPointer) Xmalloc(sizeof(XInputData)); 378c43cc173Smrg if (!info->data) { 379c43cc173Smrg UnlockDisplay(dpy); 380c43cc173Smrg return (-1); 381c43cc173Smrg } 382c43cc173Smrg ((XInputData *) info->data)->vers = 383c43cc173Smrg _XiGetExtensionVersion(dpy, "XInputExtension", info); 384c43cc173Smrg } 385c43cc173Smrg 386f1ee322dSmrg if (_XiCheckVersion(info, version_index) < 0) { 387f1ee322dSmrg UnlockDisplay(dpy); 388f1ee322dSmrg return -1; 389c43cc173Smrg } 390f1ee322dSmrg 391c43cc173Smrg return (0); 392c43cc173Smrg} 393c43cc173Smrg 394c43cc173Smrg/*********************************************************************** 395c43cc173Smrg * 396c43cc173Smrg * Close display routine. 397c43cc173Smrg * 398c43cc173Smrg */ 399c43cc173Smrg 400c43cc173Smrgstatic int 401c27c18e8SmrgXInputClose( 402c27c18e8Smrg Display *dpy, 403c27c18e8Smrg XExtCodes *codes) 404c43cc173Smrg{ 405c43cc173Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 406c43cc173Smrg 407c43cc173Smrg if (info->data != NULL) { 408c43cc173Smrg XFree((char *)((XInputData *) info->data)->vers); 409c43cc173Smrg XFree((char *)info->data); 410c43cc173Smrg } 411f1ee322dSmrg 412f1ee322dSmrg if (!XextRemoveDisplay(xinput_info, dpy)) 413f1ee322dSmrg return 0; 414f1ee322dSmrg 415f1ee322dSmrg if (xinput_info->ndisplays == 0) { 416f1ee322dSmrg XextDestroyExtension(xinput_info); 417f1ee322dSmrg xinput_info = NULL; 418f1ee322dSmrg } 419f1ee322dSmrg 420f1ee322dSmrg return 1; 421c43cc173Smrg} 422c43cc173Smrg 423c43cc173Smrgstatic int 424c27c18e8SmrgOnes(Mask mask) 425c43cc173Smrg{ 426c43cc173Smrg register Mask y; 427c43cc173Smrg 428c43cc173Smrg y = (mask >> 1) & 033333333333; 429c43cc173Smrg y = mask - y - ((y >> 1) & 033333333333); 430c43cc173Smrg return (((y + (y >> 3)) & 030707070707) % 077); 431c43cc173Smrg} 432c43cc173Smrg 433c27c18e8Smrgstatic int count_bits(unsigned char* ptr, int len) 434c27c18e8Smrg{ 435c27c18e8Smrg int bits = 0; 436c27c18e8Smrg unsigned int i; 437c27c18e8Smrg unsigned char x; 438c27c18e8Smrg 439c27c18e8Smrg for (i = 0; i < len; i++) 440c27c18e8Smrg { 441c27c18e8Smrg x = ptr[i]; 442c27c18e8Smrg while(x > 0) 443c27c18e8Smrg { 444c27c18e8Smrg bits += (x & 0x1); 445c27c18e8Smrg x >>= 1; 446c27c18e8Smrg } 447c27c18e8Smrg } 448c27c18e8Smrg return bits; 449c27c18e8Smrg} 450c27c18e8Smrg 451c43cc173Smrgint 452c43cc173Smrg_XiGetDevicePresenceNotifyEvent(Display * dpy) 453c43cc173Smrg{ 454c43cc173Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 455c43cc173Smrg 456c43cc173Smrg return info->codes->first_event + XI_DevicePresenceNotify; 457c43cc173Smrg} 458c43cc173Smrg 459c43cc173Smrg/*********************************************************************** 460c43cc173Smrg * 461c43cc173Smrg * Handle Input extension events. 462c43cc173Smrg * Reformat a wire event into an XEvent structure of the right type. 463c43cc173Smrg * 464c43cc173Smrg */ 465c43cc173Smrg 466c43cc173Smrgstatic Bool 467c27c18e8SmrgXInputWireToEvent( 468c27c18e8Smrg Display *dpy, 469c27c18e8Smrg XEvent *re, 470c27c18e8Smrg xEvent *event) 471c43cc173Smrg{ 472c43cc173Smrg unsigned int type, reltype; 473c43cc173Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 474c43cc173Smrg XEvent *save = (XEvent *) info->data; 475c43cc173Smrg 476c43cc173Smrg type = event->u.u.type & 0x7f; 477c43cc173Smrg reltype = (type - info->codes->first_event); 478c43cc173Smrg 479c27c18e8Smrg if (type == GenericEvent || 480c27c18e8Smrg (reltype != XI_DeviceValuator && 481c43cc173Smrg reltype != XI_DeviceKeystateNotify && 482c27c18e8Smrg reltype != XI_DeviceButtonstateNotify)) { 483c43cc173Smrg *save = emptyevent; 484c43cc173Smrg save->type = type; 485c43cc173Smrg ((XAnyEvent *) save)->serial = _XSetLastRequestRead(dpy, 486c43cc173Smrg (xGenericReply *) 487c43cc173Smrg event); 488c43cc173Smrg ((XAnyEvent *) save)->send_event = ((event->u.u.type & 0x80) != 0); 489c43cc173Smrg ((XAnyEvent *) save)->display = dpy; 490c43cc173Smrg } 491c43cc173Smrg 492c27c18e8Smrg /* Process traditional events */ 493c27c18e8Smrg if (type != GenericEvent) 494c43cc173Smrg { 495c27c18e8Smrg switch (reltype) { 496c27c18e8Smrg case XI_DeviceMotionNotify: 497c27c18e8Smrg { 498c27c18e8Smrg register XDeviceMotionEvent *ev = (XDeviceMotionEvent *) save; 499c27c18e8Smrg deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event; 500c27c18e8Smrg 501c27c18e8Smrg ev->root = ev2->root; 502c27c18e8Smrg ev->window = ev2->event; 503c27c18e8Smrg ev->subwindow = ev2->child; 504c27c18e8Smrg ev->time = ev2->time; 505c27c18e8Smrg ev->x_root = ev2->root_x; 506c27c18e8Smrg ev->y_root = ev2->root_y; 507c27c18e8Smrg ev->x = ev2->event_x; 508c27c18e8Smrg ev->y = ev2->event_y; 509c27c18e8Smrg ev->state = ev2->state; 510c27c18e8Smrg ev->same_screen = ev2->same_screen; 511c27c18e8Smrg ev->is_hint = ev2->detail; 512c27c18e8Smrg ev->deviceid = ev2->deviceid & DEVICE_BITS; 513c27c18e8Smrg return (DONT_ENQUEUE); 514c27c18e8Smrg } 515c27c18e8Smrg break; 516c27c18e8Smrg case XI_DeviceKeyPress: 517c27c18e8Smrg case XI_DeviceKeyRelease: 518c27c18e8Smrg { 519c27c18e8Smrg register XDeviceKeyEvent *ev = (XDeviceKeyEvent *) save; 520c27c18e8Smrg deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event; 521c27c18e8Smrg 522c27c18e8Smrg ev->root = ev2->root; 523c27c18e8Smrg ev->window = ev2->event; 524c27c18e8Smrg ev->subwindow = ev2->child; 525c27c18e8Smrg ev->time = ev2->time; 526c27c18e8Smrg ev->x_root = ev2->root_x; 527c27c18e8Smrg ev->y_root = ev2->root_y; 528c27c18e8Smrg ev->x = ev2->event_x; 529c27c18e8Smrg ev->y = ev2->event_y; 530c27c18e8Smrg ev->state = ev2->state; 531c27c18e8Smrg ev->same_screen = ev2->same_screen; 532c27c18e8Smrg ev->keycode = ev2->detail; 533c27c18e8Smrg ev->deviceid = ev2->deviceid & DEVICE_BITS; 534c27c18e8Smrg if (ev2->deviceid & MORE_EVENTS) 535c27c18e8Smrg return (DONT_ENQUEUE); 536c27c18e8Smrg else { 537c27c18e8Smrg *re = *save; 538c27c18e8Smrg return (ENQUEUE_EVENT); 539c27c18e8Smrg } 540c27c18e8Smrg } 541c27c18e8Smrg break; 542c27c18e8Smrg case XI_DeviceButtonPress: 543c27c18e8Smrg case XI_DeviceButtonRelease: 544c27c18e8Smrg { 545c27c18e8Smrg register XDeviceButtonEvent *ev = (XDeviceButtonEvent *) save; 546c27c18e8Smrg deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event; 547c27c18e8Smrg 548c27c18e8Smrg ev->root = ev2->root; 549c27c18e8Smrg ev->window = ev2->event; 550c27c18e8Smrg ev->subwindow = ev2->child; 551c27c18e8Smrg ev->time = ev2->time; 552c27c18e8Smrg ev->x_root = ev2->root_x; 553c27c18e8Smrg ev->y_root = ev2->root_y; 554c27c18e8Smrg ev->x = ev2->event_x; 555c27c18e8Smrg ev->y = ev2->event_y; 556c27c18e8Smrg ev->state = ev2->state; 557c27c18e8Smrg ev->same_screen = ev2->same_screen; 558c27c18e8Smrg ev->button = ev2->detail; 559c27c18e8Smrg ev->deviceid = ev2->deviceid & DEVICE_BITS; 560c27c18e8Smrg if (ev2->deviceid & MORE_EVENTS) 561c27c18e8Smrg return (DONT_ENQUEUE); 562c27c18e8Smrg else { 563c27c18e8Smrg *re = *save; 564c27c18e8Smrg return (ENQUEUE_EVENT); 565c27c18e8Smrg } 566c27c18e8Smrg } 567c27c18e8Smrg break; 568c27c18e8Smrg case XI_ProximityIn: 569c27c18e8Smrg case XI_ProximityOut: 570c27c18e8Smrg { 571c27c18e8Smrg register XProximityNotifyEvent *ev = (XProximityNotifyEvent *) save; 572c27c18e8Smrg deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event; 573c27c18e8Smrg 574c27c18e8Smrg ev->root = ev2->root; 575c27c18e8Smrg ev->window = ev2->event; 576c27c18e8Smrg ev->subwindow = ev2->child; 577c27c18e8Smrg ev->time = ev2->time; 578c27c18e8Smrg ev->x_root = ev2->root_x; 579c27c18e8Smrg ev->y_root = ev2->root_y; 580c27c18e8Smrg ev->x = ev2->event_x; 581c27c18e8Smrg ev->y = ev2->event_y; 582c27c18e8Smrg ev->state = ev2->state; 583c27c18e8Smrg ev->same_screen = ev2->same_screen; 584c27c18e8Smrg ev->deviceid = ev2->deviceid & DEVICE_BITS; 585c27c18e8Smrg if (ev2->deviceid & MORE_EVENTS) 586c27c18e8Smrg return (DONT_ENQUEUE); 587c27c18e8Smrg else { 588c27c18e8Smrg *re = *save; 589c27c18e8Smrg return (ENQUEUE_EVENT); 590c27c18e8Smrg } 591c27c18e8Smrg } 592c27c18e8Smrg break; 593c27c18e8Smrg case XI_DeviceValuator: 594c27c18e8Smrg { 595c27c18e8Smrg deviceValuator *xev = (deviceValuator *) event; 596c27c18e8Smrg int save_type = save->type - info->codes->first_event; 597f1ee322dSmrg int i; 598c27c18e8Smrg 599c27c18e8Smrg if (save_type == XI_DeviceKeyPress || save_type == XI_DeviceKeyRelease) { 600c27c18e8Smrg XDeviceKeyEvent *kev = (XDeviceKeyEvent *) save; 601c27c18e8Smrg 602c27c18e8Smrg kev->device_state = xev->device_state; 603c27c18e8Smrg kev->axes_count = xev->num_valuators; 604c27c18e8Smrg kev->first_axis = xev->first_valuator; 605c27c18e8Smrg i = xev->num_valuators; 606c27c18e8Smrg if (i > 6) 607c27c18e8Smrg i = 6; 608c27c18e8Smrg switch (i) { 609c27c18e8Smrg case 6: 610c27c18e8Smrg kev->axis_data[5] = xev->valuator5; 611c27c18e8Smrg case 5: 612c27c18e8Smrg kev->axis_data[4] = xev->valuator4; 613c27c18e8Smrg case 4: 614c27c18e8Smrg kev->axis_data[3] = xev->valuator3; 615c27c18e8Smrg case 3: 616c27c18e8Smrg kev->axis_data[2] = xev->valuator2; 617c27c18e8Smrg case 2: 618c27c18e8Smrg kev->axis_data[1] = xev->valuator1; 619c27c18e8Smrg case 1: 620c27c18e8Smrg kev->axis_data[0] = xev->valuator0; 621c27c18e8Smrg } 622c27c18e8Smrg } else if (save_type == XI_DeviceButtonPress || 623c27c18e8Smrg save_type == XI_DeviceButtonRelease) { 624c27c18e8Smrg XDeviceButtonEvent *bev = (XDeviceButtonEvent *) save; 625c27c18e8Smrg 626c27c18e8Smrg bev->device_state = xev->device_state; 627c27c18e8Smrg bev->axes_count = xev->num_valuators; 628c27c18e8Smrg bev->first_axis = xev->first_valuator; 629c27c18e8Smrg i = xev->num_valuators; 630c27c18e8Smrg if (i > 6) 631c27c18e8Smrg i = 6; 632c27c18e8Smrg switch (i) { 633c27c18e8Smrg case 6: 634c27c18e8Smrg bev->axis_data[5] = xev->valuator5; 635c27c18e8Smrg case 5: 636c27c18e8Smrg bev->axis_data[4] = xev->valuator4; 637c27c18e8Smrg case 4: 638c27c18e8Smrg bev->axis_data[3] = xev->valuator3; 639c27c18e8Smrg case 3: 640c27c18e8Smrg bev->axis_data[2] = xev->valuator2; 641c27c18e8Smrg case 2: 642c27c18e8Smrg bev->axis_data[1] = xev->valuator1; 643c27c18e8Smrg case 1: 644c27c18e8Smrg bev->axis_data[0] = xev->valuator0; 645c27c18e8Smrg } 646c27c18e8Smrg } else if (save_type == XI_DeviceMotionNotify) { 647c27c18e8Smrg XDeviceMotionEvent *mev = (XDeviceMotionEvent *) save; 648c27c18e8Smrg 649c27c18e8Smrg mev->device_state = xev->device_state; 650c27c18e8Smrg mev->axes_count = xev->num_valuators; 651c27c18e8Smrg mev->first_axis = xev->first_valuator; 652c27c18e8Smrg i = xev->num_valuators; 653c27c18e8Smrg if (i > 6) 654c27c18e8Smrg i = 6; 655c27c18e8Smrg switch (i) { 656c27c18e8Smrg case 6: 657c27c18e8Smrg mev->axis_data[5] = xev->valuator5; 658c27c18e8Smrg case 5: 659c27c18e8Smrg mev->axis_data[4] = xev->valuator4; 660c27c18e8Smrg case 4: 661c27c18e8Smrg mev->axis_data[3] = xev->valuator3; 662c27c18e8Smrg case 3: 663c27c18e8Smrg mev->axis_data[2] = xev->valuator2; 664c27c18e8Smrg case 2: 665c27c18e8Smrg mev->axis_data[1] = xev->valuator1; 666c27c18e8Smrg case 1: 667c27c18e8Smrg mev->axis_data[0] = xev->valuator0; 668c27c18e8Smrg } 669c27c18e8Smrg } else if (save_type == XI_ProximityIn || save_type == XI_ProximityOut) { 670c27c18e8Smrg XProximityNotifyEvent *pev = (XProximityNotifyEvent *) save; 671c27c18e8Smrg 672c27c18e8Smrg pev->device_state = xev->device_state; 673c27c18e8Smrg pev->axes_count = xev->num_valuators; 674c27c18e8Smrg pev->first_axis = xev->first_valuator; 675c27c18e8Smrg i = xev->num_valuators; 676c27c18e8Smrg if (i > 6) 677c27c18e8Smrg i = 6; 678c27c18e8Smrg switch (i) { 679c27c18e8Smrg case 6: 680c27c18e8Smrg pev->axis_data[5] = xev->valuator5; 681c27c18e8Smrg case 5: 682c27c18e8Smrg pev->axis_data[4] = xev->valuator4; 683c27c18e8Smrg case 4: 684c27c18e8Smrg pev->axis_data[3] = xev->valuator3; 685c27c18e8Smrg case 3: 686c27c18e8Smrg pev->axis_data[2] = xev->valuator2; 687c27c18e8Smrg case 2: 688c27c18e8Smrg pev->axis_data[1] = xev->valuator1; 689c27c18e8Smrg case 1: 690c27c18e8Smrg pev->axis_data[0] = xev->valuator0; 691c27c18e8Smrg } 692c27c18e8Smrg } else if (save_type == XI_DeviceStateNotify) { 693f1ee322dSmrg int j; 694c27c18e8Smrg XDeviceStateNotifyEvent *sev = (XDeviceStateNotifyEvent *) save; 695c27c18e8Smrg XInputClass *any = (XInputClass *) & sev->data[0]; 696c27c18e8Smrg XValuatorStatus *v; 697c27c18e8Smrg 698c27c18e8Smrg for (i = 0; i < sev->num_classes; i++) 699c27c18e8Smrg if (any->class != ValuatorClass) 700c27c18e8Smrg any = (XInputClass *) ((char *)any + any->length); 701c27c18e8Smrg v = (XValuatorStatus *) any; 702c27c18e8Smrg i = v->num_valuators; 703c27c18e8Smrg j = xev->num_valuators; 704c27c18e8Smrg if (j > 3) 705c27c18e8Smrg j = 3; 706c27c18e8Smrg switch (j) { 707c27c18e8Smrg case 3: 708c27c18e8Smrg v->valuators[i + 2] = xev->valuator2; 709c27c18e8Smrg case 2: 710c27c18e8Smrg v->valuators[i + 1] = xev->valuator1; 711c27c18e8Smrg case 1: 712c27c18e8Smrg v->valuators[i + 0] = xev->valuator0; 713c27c18e8Smrg } 714c27c18e8Smrg v->num_valuators += j; 715c27c18e8Smrg 716c27c18e8Smrg } 717c27c18e8Smrg *re = *save; 718c27c18e8Smrg return (ENQUEUE_EVENT); 719c27c18e8Smrg } 720c27c18e8Smrg break; 721c27c18e8Smrg case XI_DeviceFocusIn: 722c27c18e8Smrg case XI_DeviceFocusOut: 723c27c18e8Smrg { 724c27c18e8Smrg register XDeviceFocusChangeEvent *ev = (XDeviceFocusChangeEvent *) re; 725c27c18e8Smrg deviceFocus *fev = (deviceFocus *) event; 726c27c18e8Smrg 727c27c18e8Smrg *ev = *((XDeviceFocusChangeEvent *) save); 728c27c18e8Smrg ev->window = fev->window; 729c27c18e8Smrg ev->time = fev->time; 730c27c18e8Smrg ev->mode = fev->mode; 731c27c18e8Smrg ev->detail = fev->detail; 732c27c18e8Smrg ev->deviceid = fev->deviceid & DEVICE_BITS; 733c27c18e8Smrg return (ENQUEUE_EVENT); 734c27c18e8Smrg } 735c27c18e8Smrg break; 736c27c18e8Smrg case XI_DeviceStateNotify: 737c27c18e8Smrg { 738f1ee322dSmrg int j; 739c27c18e8Smrg XDeviceStateNotifyEvent *stev = (XDeviceStateNotifyEvent *) save; 740c27c18e8Smrg deviceStateNotify *sev = (deviceStateNotify *) event; 741c27c18e8Smrg char *data; 742c27c18e8Smrg 743c27c18e8Smrg stev->window = None; 744c27c18e8Smrg stev->deviceid = sev->deviceid & DEVICE_BITS; 745c27c18e8Smrg stev->time = sev->time; 746c27c18e8Smrg stev->num_classes = Ones((Mask) sev->classes_reported & InputClassBits); 747c27c18e8Smrg data = (char *)&stev->data[0]; 748c27c18e8Smrg if (sev->classes_reported & (1 << KeyClass)) { 749c27c18e8Smrg register XKeyStatus *kstev = (XKeyStatus *) data; 750c27c18e8Smrg 751c27c18e8Smrg kstev->class = KeyClass; 752c27c18e8Smrg kstev->length = sizeof(XKeyStatus); 753c27c18e8Smrg kstev->num_keys = sev->num_keys; 754c27c18e8Smrg memcpy((char *)&kstev->keys[0], (char *)&sev->keys[0], 4); 755c27c18e8Smrg data += sizeof(XKeyStatus); 756c27c18e8Smrg } 757c27c18e8Smrg if (sev->classes_reported & (1 << ButtonClass)) { 758c27c18e8Smrg register XButtonStatus *bev = (XButtonStatus *) data; 759c27c18e8Smrg 760c27c18e8Smrg bev->class = ButtonClass; 761c27c18e8Smrg bev->length = sizeof(XButtonStatus); 762c27c18e8Smrg bev->num_buttons = sev->num_buttons; 763c27c18e8Smrg memcpy((char *)bev->buttons, (char *)sev->buttons, 4); 764c27c18e8Smrg data += sizeof(XButtonStatus); 765c27c18e8Smrg } 766c27c18e8Smrg if (sev->classes_reported & (1 << ValuatorClass)) { 767c27c18e8Smrg register XValuatorStatus *vev = (XValuatorStatus *) data; 768c27c18e8Smrg 769c27c18e8Smrg vev->class = ValuatorClass; 770c27c18e8Smrg vev->length = sizeof(XValuatorStatus); 771c27c18e8Smrg vev->num_valuators = sev->num_valuators; 772c27c18e8Smrg vev->mode = sev->classes_reported >> ModeBitsShift; 773c27c18e8Smrg j = sev->num_valuators; 774c27c18e8Smrg if (j > 3) 775c27c18e8Smrg j = 3; 776c27c18e8Smrg switch (j) { 777c27c18e8Smrg case 3: 778c27c18e8Smrg vev->valuators[2] = sev->valuator2; 779c27c18e8Smrg case 2: 780c27c18e8Smrg vev->valuators[1] = sev->valuator1; 781c27c18e8Smrg case 1: 782c27c18e8Smrg vev->valuators[0] = sev->valuator0; 783c27c18e8Smrg } 784c27c18e8Smrg data += sizeof(XValuatorStatus); 785c27c18e8Smrg } 786c27c18e8Smrg if (sev->deviceid & MORE_EVENTS) 787c27c18e8Smrg return (DONT_ENQUEUE); 788c27c18e8Smrg else { 789c27c18e8Smrg *re = *save; 790c27c18e8Smrg return (ENQUEUE_EVENT); 791c27c18e8Smrg } 792c27c18e8Smrg } 793c27c18e8Smrg break; 794c27c18e8Smrg case XI_DeviceKeystateNotify: 795c27c18e8Smrg { 796c27c18e8Smrg int i; 797c27c18e8Smrg XInputClass *anyclass; 798c27c18e8Smrg register XKeyStatus *kv; 799c27c18e8Smrg deviceKeyStateNotify *ksev = (deviceKeyStateNotify *) event; 800c27c18e8Smrg XDeviceStateNotifyEvent *kstev = (XDeviceStateNotifyEvent *) save; 801c27c18e8Smrg 802c27c18e8Smrg anyclass = (XInputClass *) & kstev->data[0]; 803c27c18e8Smrg for (i = 0; i < kstev->num_classes; i++) 804c27c18e8Smrg if (anyclass->class == KeyClass) 805c27c18e8Smrg break; 806c27c18e8Smrg else 807c27c18e8Smrg anyclass = (XInputClass *) ((char *)anyclass + 808c27c18e8Smrg anyclass->length); 809c27c18e8Smrg 810c27c18e8Smrg kv = (XKeyStatus *) anyclass; 811c27c18e8Smrg kv->num_keys = 256; 812c27c18e8Smrg memcpy((char *)&kv->keys[4], (char *)ksev->keys, 28); 813c27c18e8Smrg if (ksev->deviceid & MORE_EVENTS) 814c27c18e8Smrg return (DONT_ENQUEUE); 815c27c18e8Smrg else { 816c27c18e8Smrg *re = *save; 817c27c18e8Smrg return (ENQUEUE_EVENT); 818c27c18e8Smrg } 819c27c18e8Smrg } 820c27c18e8Smrg break; 821c27c18e8Smrg case XI_DeviceButtonstateNotify: 822c27c18e8Smrg { 823c27c18e8Smrg int i; 824c27c18e8Smrg XInputClass *anyclass; 825c27c18e8Smrg register XButtonStatus *bv; 826c27c18e8Smrg deviceButtonStateNotify *bsev = (deviceButtonStateNotify *) event; 827c27c18e8Smrg XDeviceStateNotifyEvent *bstev = (XDeviceStateNotifyEvent *) save; 828c27c18e8Smrg 829c27c18e8Smrg anyclass = (XInputClass *) & bstev->data[0]; 830c27c18e8Smrg for (i = 0; i < bstev->num_classes; i++) 831c27c18e8Smrg if (anyclass->class == ButtonClass) 832c27c18e8Smrg break; 833c27c18e8Smrg else 834c27c18e8Smrg anyclass = (XInputClass *) ((char *)anyclass + 835c27c18e8Smrg anyclass->length); 836c27c18e8Smrg 837c27c18e8Smrg bv = (XButtonStatus *) anyclass; 838c27c18e8Smrg bv->num_buttons = 256; 839c27c18e8Smrg memcpy((char *)&bv->buttons[4], (char *)bsev->buttons, 28); 840c27c18e8Smrg if (bsev->deviceid & MORE_EVENTS) 841c27c18e8Smrg return (DONT_ENQUEUE); 842c27c18e8Smrg else { 843c27c18e8Smrg *re = *save; 844c27c18e8Smrg return (ENQUEUE_EVENT); 845c27c18e8Smrg } 846c27c18e8Smrg } 847c27c18e8Smrg break; 848c27c18e8Smrg case XI_DeviceMappingNotify: 849c27c18e8Smrg { 850c27c18e8Smrg register XDeviceMappingEvent *ev = (XDeviceMappingEvent *) re; 851c27c18e8Smrg deviceMappingNotify *ev2 = (deviceMappingNotify *) event; 852c27c18e8Smrg 853c27c18e8Smrg *ev = *((XDeviceMappingEvent *) save); 854c27c18e8Smrg ev->window = 0; 855c27c18e8Smrg ev->first_keycode = ev2->firstKeyCode; 856c27c18e8Smrg ev->request = ev2->request; 857c27c18e8Smrg ev->count = ev2->count; 858c27c18e8Smrg ev->time = ev2->time; 859c27c18e8Smrg ev->deviceid = ev2->deviceid & DEVICE_BITS; 860c27c18e8Smrg return (ENQUEUE_EVENT); 861c27c18e8Smrg } 862c27c18e8Smrg break; 863c27c18e8Smrg case XI_ChangeDeviceNotify: 864c27c18e8Smrg { 865c27c18e8Smrg register XChangeDeviceNotifyEvent *ev = (XChangeDeviceNotifyEvent *) re; 866c27c18e8Smrg changeDeviceNotify *ev2 = (changeDeviceNotify *) event; 867c27c18e8Smrg 868c27c18e8Smrg *ev = *((XChangeDeviceNotifyEvent *) save); 869c27c18e8Smrg ev->window = 0; 870c27c18e8Smrg ev->request = ev2->request; 871c27c18e8Smrg ev->time = ev2->time; 872c27c18e8Smrg ev->deviceid = ev2->deviceid & DEVICE_BITS; 873c27c18e8Smrg return (ENQUEUE_EVENT); 874c27c18e8Smrg } 875c27c18e8Smrg break; 876c27c18e8Smrg 877c27c18e8Smrg case XI_DevicePresenceNotify: 878c27c18e8Smrg { 879c27c18e8Smrg XDevicePresenceNotifyEvent *ev = (XDevicePresenceNotifyEvent *) re; 880c27c18e8Smrg devicePresenceNotify *ev2 = (devicePresenceNotify *) event; 881c27c18e8Smrg 882c27c18e8Smrg *ev = *(XDevicePresenceNotifyEvent *) save; 883c27c18e8Smrg ev->window = 0; 884c27c18e8Smrg ev->time = ev2->time; 885c27c18e8Smrg ev->devchange = ev2->devchange; 886c27c18e8Smrg ev->deviceid = ev2->deviceid; 887c27c18e8Smrg ev->control = ev2->control; 888c27c18e8Smrg return (ENQUEUE_EVENT); 889c27c18e8Smrg } 890c27c18e8Smrg break; 891c27c18e8Smrg case XI_DevicePropertyNotify: 892c27c18e8Smrg { 893c27c18e8Smrg XDevicePropertyNotifyEvent* ev = (XDevicePropertyNotifyEvent*)re; 894c27c18e8Smrg devicePropertyNotify *ev2 = (devicePropertyNotify*)event; 895c27c18e8Smrg 896c27c18e8Smrg *ev = *(XDevicePropertyNotifyEvent*)save; 897c27c18e8Smrg ev->time = ev2->time; 898c27c18e8Smrg ev->deviceid = ev2->deviceid; 899c27c18e8Smrg ev->atom = ev2->atom; 900c27c18e8Smrg ev->state = ev2->state; 901c27c18e8Smrg return ENQUEUE_EVENT; 902c27c18e8Smrg } 903c27c18e8Smrg break; 904c27c18e8Smrg default: 905c27c18e8Smrg printf("XInputWireToEvent: UNKNOWN WIRE EVENT! type=%d\n", type); 906c27c18e8Smrg break; 907c27c18e8Smrg } 908c43cc173Smrg } 909c27c18e8Smrg return (DONT_ENQUEUE); 910c27c18e8Smrg} 911c27c18e8Smrg 912c27c18e8Smrgstatic void xge_copy_to_cookie(xGenericEvent* ev, 913c27c18e8Smrg XGenericEventCookie *cookie) 914c27c18e8Smrg{ 915c27c18e8Smrg cookie->type = ev->type; 916c27c18e8Smrg cookie->evtype = ev->evtype; 917c27c18e8Smrg cookie->extension = ev->extension; 918c27c18e8Smrg} 919c27c18e8Smrg 920c27c18e8Smrgstatic Bool 921c27c18e8SmrgXInputWireToCookie( 922c27c18e8Smrg Display *dpy, 923c27c18e8Smrg XGenericEventCookie *cookie, 924c27c18e8Smrg xEvent *event) 925c27c18e8Smrg{ 926c27c18e8Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 927c27c18e8Smrg XEvent *save = (XEvent *) info->data; 928c27c18e8Smrg xGenericEvent* ge = (xGenericEvent*)event; 929c27c18e8Smrg 930c27c18e8Smrg if (ge->extension != info->codes->major_opcode) 931c43cc173Smrg { 932c27c18e8Smrg printf("XInputWireToCookie: wrong extension opcode %d\n", 933c27c18e8Smrg ge->extension); 934c27c18e8Smrg return DONT_ENQUEUE; 935c43cc173Smrg } 936c27c18e8Smrg 937c27c18e8Smrg *save = emptyevent; 938c27c18e8Smrg save->type = event->u.u.type; 939c27c18e8Smrg ((XAnyEvent*)save)->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 940c27c18e8Smrg ((XAnyEvent*)save)->send_event = ((event->u.u.type & 0x80) != 0); 941c27c18e8Smrg ((XAnyEvent*)save)->display = dpy; 942c27c18e8Smrg 943c27c18e8Smrg xge_copy_to_cookie((xGenericEvent*)event, (XGenericEventCookie*)save); 944c27c18e8Smrg switch(ge->evtype) 945c43cc173Smrg { 946c27c18e8Smrg case XI_Motion: 947c27c18e8Smrg case XI_ButtonPress: 948c27c18e8Smrg case XI_ButtonRelease: 949c27c18e8Smrg case XI_KeyPress: 950c27c18e8Smrg case XI_KeyRelease: 951f1ee322dSmrg case XI_TouchBegin: 952f1ee322dSmrg case XI_TouchUpdate: 953f1ee322dSmrg case XI_TouchEnd: 954c27c18e8Smrg *cookie = *(XGenericEventCookie*)save; 955c27c18e8Smrg if (!wireToDeviceEvent((xXIDeviceEvent*)event, cookie)) 956c27c18e8Smrg { 957c27c18e8Smrg printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 958c27c18e8Smrg ge->evtype); 959c27c18e8Smrg break; 960c27c18e8Smrg } 961c27c18e8Smrg return ENQUEUE_EVENT; 962c27c18e8Smrg case XI_DeviceChanged: 963c27c18e8Smrg *cookie = *(XGenericEventCookie*)save; 964c27c18e8Smrg if (!wireToDeviceChangedEvent((xXIDeviceChangedEvent*)event, cookie)) 965c27c18e8Smrg { 966c27c18e8Smrg printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 967c27c18e8Smrg ge->evtype); 968c27c18e8Smrg break; 969c27c18e8Smrg } 970c27c18e8Smrg return ENQUEUE_EVENT; 971c27c18e8Smrg case XI_HierarchyChanged: 972c27c18e8Smrg *cookie = *(XGenericEventCookie*)save; 973c27c18e8Smrg if (!wireToHierarchyChangedEvent((xXIHierarchyEvent*)event, cookie)) 974c27c18e8Smrg { 975c27c18e8Smrg printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 976c27c18e8Smrg ge->evtype); 977c27c18e8Smrg break; 978c27c18e8Smrg } 979c27c18e8Smrg return ENQUEUE_EVENT; 980f1ee322dSmrg case XI_TouchOwnership: 981f1ee322dSmrg *cookie = *(XGenericEventCookie*)save; 982f1ee322dSmrg if (!wireToTouchOwnershipEvent((xXITouchOwnershipEvent*)event, 983f1ee322dSmrg cookie)) 984f1ee322dSmrg { 985f1ee322dSmrg printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 986f1ee322dSmrg ge->evtype); 987f1ee322dSmrg break; 988f1ee322dSmrg } 989f1ee322dSmrg return ENQUEUE_EVENT; 990c27c18e8Smrg 991c27c18e8Smrg case XI_RawKeyPress: 992c27c18e8Smrg case XI_RawKeyRelease: 993c27c18e8Smrg case XI_RawButtonPress: 994c27c18e8Smrg case XI_RawButtonRelease: 995c27c18e8Smrg case XI_RawMotion: 996f1ee322dSmrg case XI_RawTouchBegin: 997f1ee322dSmrg case XI_RawTouchUpdate: 998f1ee322dSmrg case XI_RawTouchEnd: 999c27c18e8Smrg *cookie = *(XGenericEventCookie*)save; 1000f1ee322dSmrg if (!wireToRawEvent(info, (xXIRawEvent*)event, cookie)) 1001c27c18e8Smrg { 1002c27c18e8Smrg printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 1003c27c18e8Smrg ge->evtype); 1004c27c18e8Smrg break; 1005c27c18e8Smrg } 1006c27c18e8Smrg return ENQUEUE_EVENT; 1007c27c18e8Smrg case XI_Enter: 1008c27c18e8Smrg case XI_Leave: 1009c27c18e8Smrg case XI_FocusIn: 1010c27c18e8Smrg case XI_FocusOut: 1011c27c18e8Smrg *cookie = *(XGenericEventCookie*)save; 1012c27c18e8Smrg if (!wireToEnterLeave((xXIEnterEvent*)event, cookie)) 1013c27c18e8Smrg { 1014c27c18e8Smrg printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 1015c27c18e8Smrg ge->evtype); 1016c27c18e8Smrg break; 1017c27c18e8Smrg } 1018c27c18e8Smrg return ENQUEUE_EVENT; 1019c27c18e8Smrg case XI_PropertyEvent: 1020c27c18e8Smrg *cookie = *(XGenericEventCookie*)save; 1021c27c18e8Smrg if (!wireToPropertyEvent((xXIPropertyEvent*)event, cookie)) 1022c27c18e8Smrg { 1023c27c18e8Smrg printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 1024c27c18e8Smrg ge->evtype); 1025c27c18e8Smrg break; 1026c27c18e8Smrg } 1027c27c18e8Smrg return ENQUEUE_EVENT; 1028f1ee322dSmrg case XI_BarrierHit: 1029f1ee322dSmrg case XI_BarrierLeave: 1030f1ee322dSmrg *cookie = *(XGenericEventCookie*)save; 1031f1ee322dSmrg if (!wireToBarrierEvent((xXIBarrierEvent*)event, cookie)) 1032f1ee322dSmrg { 1033f1ee322dSmrg printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 1034f1ee322dSmrg ge->evtype); 1035f1ee322dSmrg break; 1036f1ee322dSmrg } 1037f1ee322dSmrg return ENQUEUE_EVENT; 1038c27c18e8Smrg default: 1039c27c18e8Smrg printf("XInputWireToCookie: Unknown generic event. type %d\n", ge->evtype); 1040c27c18e8Smrg 1041c43cc173Smrg } 1042c27c18e8Smrg return DONT_ENQUEUE; 1043c27c18e8Smrg} 1044c27c18e8Smrg 1045c27c18e8Smrg/** 1046c27c18e8Smrg * Calculate length in bytes needed for the device event with the given 1047c27c18e8Smrg * button mask length, valuator mask length + valuator mask. All parameters 1048c27c18e8Smrg * in bytes. 1049c27c18e8Smrg */ 1050c27c18e8Smrgstatic inline int 1051c27c18e8SmrgsizeDeviceEvent(int buttons_len, int valuators_len, 1052c27c18e8Smrg unsigned char *valuators_mask) 1053c27c18e8Smrg{ 1054c27c18e8Smrg int len; 1055c27c18e8Smrg 1056c27c18e8Smrg len = sizeof(XIDeviceEvent); 1057c27c18e8Smrg len += sizeof(XIButtonState) + buttons_len; 1058c27c18e8Smrg len += sizeof(XIValuatorState) + valuators_len; 1059c27c18e8Smrg len += count_bits(valuators_mask, valuators_len) * sizeof(double); 1060c27c18e8Smrg len += sizeof(XIModifierState) + sizeof(XIGroupState); 1061c27c18e8Smrg 1062c27c18e8Smrg return len; 1063c27c18e8Smrg} 1064c27c18e8Smrg 1065f1ee322dSmrg/* Return the size with added padding so next element would be 1066f1ee322dSmrg double-aligned unless the architecture is known to allow unaligned 1067f1ee322dSmrg data accesses. Not doing this can cause a bus error on 1068f1ee322dSmrg MIPS N32. */ 1069f1ee322dSmrgstatic int 1070f1ee322dSmrgpad_to_double(int size) 1071f1ee322dSmrg{ 1072f1ee322dSmrg#if !defined(__i386__) && !defined(__sh__) 1073f1ee322dSmrg if (size % sizeof(double) != 0) 1074f1ee322dSmrg size += sizeof(double) - size % sizeof(double); 1075f1ee322dSmrg#endif 1076f1ee322dSmrg return size; 1077f1ee322dSmrg} 1078f1ee322dSmrg 1079f1ee322dSmrg/** 1080f1ee322dSmrg * Set structure and atoms to size in bytes of XIButtonClassInfo, its 1081f1ee322dSmrg * button state mask and labels array. 1082f1ee322dSmrg */ 1083f1ee322dSmrgstatic void 1084f1ee322dSmrgsizeXIButtonClassType(int num_buttons, int* structure, int* state, int* atoms) 1085f1ee322dSmrg{ 1086f1ee322dSmrg int size; 1087f1ee322dSmrg int labels; 1088f1ee322dSmrg 1089f1ee322dSmrg *structure = pad_to_double(sizeof(XIButtonClassInfo)); 1090f1ee322dSmrg size = ((((num_buttons + 7)/8) + 3)/4); 1091f1ee322dSmrg 1092f1ee322dSmrg /* Force mask alignment with longs to avoid unaligned 1093f1ee322dSmrg * access when accessing the atoms. */ 1094f1ee322dSmrg *state = pad_to_double(size * 4); 1095f1ee322dSmrg labels = num_buttons * sizeof(Atom); 1096f1ee322dSmrg 1097f1ee322dSmrg /* Force mask alignment with longs to avoid 1098f1ee322dSmrg * unaligned access when accessing the atoms. */ 1099f1ee322dSmrg labels += ((((num_buttons + 7)/8) + 3)/4) * sizeof(Atom); 1100f1ee322dSmrg *atoms = pad_to_double(labels); 1101f1ee322dSmrg} 1102f1ee322dSmrg 1103f1ee322dSmrg/** 1104f1ee322dSmrg * Set structure and keycodes to size in bytes of XIKeyClassInfo and 1105f1ee322dSmrg * its keycodes array. 1106f1ee322dSmrg */ 1107f1ee322dSmrgstatic void 1108f1ee322dSmrgsizeXIKeyClassType(int num_keycodes, int* structure, int* keycodes) 1109f1ee322dSmrg{ 1110f1ee322dSmrg *structure = pad_to_double(sizeof(XIKeyClassInfo)); 1111f1ee322dSmrg *keycodes = pad_to_double(num_keycodes * sizeof(int)); 1112f1ee322dSmrg} 1113f1ee322dSmrg 1114c27c18e8Smrg/** 1115c27c18e8Smrg * Return the size in bytes required to store the matching class type 1116c27c18e8Smrg * num_elements is num_buttons for XIButtonClass or num_keycodes for 1117c27c18e8Smrg * XIKeyClass. 1118c27c18e8Smrg * 1119c27c18e8Smrg * Also used from copy_classes in XIQueryDevice.c 1120c27c18e8Smrg */ 1121c27c18e8Smrgstatic int 1122c27c18e8SmrgsizeDeviceClassType(int type, int num_elements) 1123c27c18e8Smrg{ 1124c27c18e8Smrg int l = 0; 1125f1ee322dSmrg int extra1 = 0; 1126f1ee322dSmrg int extra2 = 0; 1127c27c18e8Smrg switch(type) 1128c43cc173Smrg { 1129c27c18e8Smrg case XIButtonClass: 1130f1ee322dSmrg sizeXIButtonClassType(num_elements, &l, &extra1, &extra2); 1131f1ee322dSmrg l += extra1 + extra2; 1132c27c18e8Smrg break; 1133c27c18e8Smrg case XIKeyClass: 1134f1ee322dSmrg sizeXIKeyClassType(num_elements, &l, &extra1); 1135f1ee322dSmrg l += extra1; 1136c27c18e8Smrg break; 1137c27c18e8Smrg case XIValuatorClass: 1138f1ee322dSmrg l = pad_to_double(sizeof(XIValuatorClassInfo)); 1139f1ee322dSmrg break; 1140f1ee322dSmrg case XIScrollClass: 1141f1ee322dSmrg l = pad_to_double(sizeof(XIScrollClassInfo)); 1142f1ee322dSmrg break; 1143f1ee322dSmrg case XITouchClass: 1144f1ee322dSmrg l = pad_to_double(sizeof(XITouchClassInfo)); 1145c27c18e8Smrg break; 1146c27c18e8Smrg default: 1147c27c18e8Smrg printf("sizeDeviceClassType: unknown type %d\n", type); 1148c27c18e8Smrg break; 1149c43cc173Smrg } 1150c27c18e8Smrg return l; 1151c27c18e8Smrg} 1152c27c18e8Smrg 1153c27c18e8Smrgstatic Bool 1154c27c18e8SmrgcopyHierarchyEvent(XGenericEventCookie *cookie_in, 1155c27c18e8Smrg XGenericEventCookie *cookie_out) 1156c27c18e8Smrg{ 1157c27c18e8Smrg XIHierarchyEvent *in, *out; 1158c27c18e8Smrg void *ptr; 1159c27c18e8Smrg 1160c27c18e8Smrg in = cookie_in->data; 1161c27c18e8Smrg 1162c27c18e8Smrg ptr = cookie_out->data = malloc(sizeof(XIHierarchyEvent) + 1163c27c18e8Smrg in->num_info * sizeof(XIHierarchyInfo)); 1164c27c18e8Smrg if (!ptr) 1165c27c18e8Smrg return False; 1166c27c18e8Smrg 1167c27c18e8Smrg out = next_block(&ptr, sizeof(XIHierarchyEvent)); 1168c27c18e8Smrg *out = *in; 1169c27c18e8Smrg out->info = next_block(&ptr, in->num_info * sizeof(XIHierarchyInfo)); 1170c27c18e8Smrg memcpy(out->info, in->info, in->num_info * sizeof(XIHierarchyInfo)); 1171c27c18e8Smrg 1172c27c18e8Smrg return True; 1173c27c18e8Smrg} 1174c27c18e8Smrg 1175c27c18e8Smrgstatic Bool 1176c27c18e8SmrgcopyDeviceChangedEvent(XGenericEventCookie *in_cookie, 1177c27c18e8Smrg XGenericEventCookie *out_cookie) 1178c27c18e8Smrg{ 1179c27c18e8Smrg int len, i; 1180c27c18e8Smrg XIDeviceChangedEvent *in, *out; 1181c27c18e8Smrg XIAnyClassInfo *any; 1182c27c18e8Smrg void *ptr; 1183c27c18e8Smrg 1184c27c18e8Smrg in = in_cookie->data; 1185c27c18e8Smrg 1186c27c18e8Smrg len = sizeof(XIDeviceChangedEvent); 1187c27c18e8Smrg len += in->num_classes * sizeof(XIAnyClassInfo*); 1188c27c18e8Smrg 1189c27c18e8Smrg for (i = 0; i < in->num_classes; i++) 1190c43cc173Smrg { 1191c27c18e8Smrg any = in->classes[i]; 1192c27c18e8Smrg switch(any->type) 1193c27c18e8Smrg { 1194c27c18e8Smrg case XIButtonClass: 1195c27c18e8Smrg len += sizeDeviceClassType(XIButtonClass, 1196c27c18e8Smrg ((XIButtonClassInfo*)any)->num_buttons); 1197c27c18e8Smrg break; 1198c27c18e8Smrg case XIKeyClass: 1199c27c18e8Smrg len += sizeDeviceClassType(XIKeyClass, 1200c27c18e8Smrg ((XIKeyClassInfo*)any)->num_keycodes); 1201c27c18e8Smrg break; 1202c27c18e8Smrg case XIValuatorClass: 1203c27c18e8Smrg len += sizeDeviceClassType(XIValuatorClass, 0); 1204c27c18e8Smrg break; 1205f1ee322dSmrg case XIScrollClass: 1206f1ee322dSmrg len += sizeDeviceClassType(XIScrollClass, 0); 1207f1ee322dSmrg break; 1208c27c18e8Smrg default: 1209c27c18e8Smrg printf("copyDeviceChangedEvent: unknown type %d\n", 1210c27c18e8Smrg any->type); 1211c27c18e8Smrg break; 1212c27c18e8Smrg } 1213c43cc173Smrg 1214c43cc173Smrg } 1215c27c18e8Smrg 1216c27c18e8Smrg ptr = out_cookie->data = malloc(len); 1217c27c18e8Smrg if (!ptr) 1218c27c18e8Smrg return False; 1219c27c18e8Smrg out = next_block(&ptr, sizeof(XIDeviceChangedEvent)); 1220c27c18e8Smrg *out = *in; 1221c27c18e8Smrg 1222c27c18e8Smrg out->classes = next_block(&ptr, 1223c27c18e8Smrg out->num_classes * sizeof(XIAnyClassInfo*)); 1224c27c18e8Smrg 1225c27c18e8Smrg for (i = 0; i < in->num_classes; i++) 1226c43cc173Smrg { 1227c27c18e8Smrg any = in->classes[i]; 1228c27c18e8Smrg 1229c27c18e8Smrg switch(any->type) 1230c27c18e8Smrg { 1231c27c18e8Smrg case XIButtonClass: 1232c27c18e8Smrg { 1233f1ee322dSmrg int struct_size; 1234f1ee322dSmrg int state_size; 1235f1ee322dSmrg int labels_size; 1236c27c18e8Smrg XIButtonClassInfo *bin, *bout; 1237c27c18e8Smrg bin = (XIButtonClassInfo*)any; 1238f1ee322dSmrg sizeXIButtonClassType(bin->num_buttons, &struct_size, 1239f1ee322dSmrg &state_size, &labels_size); 1240f1ee322dSmrg bout = next_block(&ptr, struct_size); 1241c27c18e8Smrg 1242c27c18e8Smrg *bout = *bin; 1243f1ee322dSmrg bout->state.mask = next_block(&ptr, state_size); 1244c27c18e8Smrg memcpy(bout->state.mask, bin->state.mask, 1245c27c18e8Smrg bout->state.mask_len); 1246c27c18e8Smrg 1247f1ee322dSmrg bout->labels = next_block(&ptr, labels_size); 1248c27c18e8Smrg memcpy(bout->labels, bin->labels, bout->num_buttons * sizeof(Atom)); 1249c27c18e8Smrg out->classes[i] = (XIAnyClassInfo*)bout; 1250c27c18e8Smrg break; 1251c27c18e8Smrg } 1252c27c18e8Smrg case XIKeyClass: 1253c27c18e8Smrg { 1254c27c18e8Smrg XIKeyClassInfo *kin, *kout; 1255f1ee322dSmrg int struct_size; 1256f1ee322dSmrg int keycodes_size; 1257c27c18e8Smrg kin = (XIKeyClassInfo*)any; 1258f1ee322dSmrg sizeXIKeyClassType(kin->num_keycodes, &struct_size, 1259f1ee322dSmrg &keycodes_size); 1260c27c18e8Smrg 1261f1ee322dSmrg kout = next_block(&ptr, struct_size); 1262c27c18e8Smrg *kout = *kin; 1263f1ee322dSmrg kout->keycodes = next_block(&ptr, keycodes_size); 1264c27c18e8Smrg memcpy(kout->keycodes, kin->keycodes, kout->num_keycodes * sizeof(int)); 1265c27c18e8Smrg out->classes[i] = (XIAnyClassInfo*)kout; 1266c27c18e8Smrg break; 1267c27c18e8Smrg } 1268c27c18e8Smrg case XIValuatorClass: 1269c27c18e8Smrg { 1270c27c18e8Smrg XIValuatorClassInfo *vin, *vout; 1271c27c18e8Smrg vin = (XIValuatorClassInfo*)any; 1272f1ee322dSmrg vout = next_block(&ptr, 1273f1ee322dSmrg sizeDeviceClassType(XIValuatorClass, 0)); 1274c27c18e8Smrg *vout = *vin; 1275c27c18e8Smrg out->classes[i] = (XIAnyClassInfo*)vout; 1276c27c18e8Smrg break; 1277c27c18e8Smrg } 1278f1ee322dSmrg case XIScrollClass: 1279f1ee322dSmrg { 1280f1ee322dSmrg XIScrollClassInfo *sin, *sout; 1281f1ee322dSmrg sin = (XIScrollClassInfo*)any; 1282f1ee322dSmrg sout = next_block(&ptr, 1283f1ee322dSmrg sizeDeviceClassType(XIScrollClass, 0)); 1284f1ee322dSmrg *sout = *sin; 1285f1ee322dSmrg out->classes[i] = (XIAnyClassInfo*)sout; 1286f1ee322dSmrg break; 1287f1ee322dSmrg } 1288c27c18e8Smrg } 1289c43cc173Smrg } 1290c27c18e8Smrg 1291c27c18e8Smrg return True; 1292c27c18e8Smrg} 1293c27c18e8Smrg 1294c27c18e8Smrgstatic Bool 1295c27c18e8SmrgcopyDeviceEvent(XGenericEventCookie *cookie_in, 1296c27c18e8Smrg XGenericEventCookie *cookie_out) 1297c27c18e8Smrg{ 1298c27c18e8Smrg int len; 1299c27c18e8Smrg XIDeviceEvent *in, *out; 1300c27c18e8Smrg int bits; /* valuator bits */ 1301c27c18e8Smrg void *ptr; 1302c27c18e8Smrg 1303c27c18e8Smrg in = cookie_in->data; 1304c27c18e8Smrg bits = count_bits(in->valuators.mask, in->valuators.mask_len); 1305c27c18e8Smrg 1306c27c18e8Smrg len = sizeDeviceEvent(in->buttons.mask_len, in->valuators.mask_len, 1307c27c18e8Smrg in->valuators.mask); 1308c27c18e8Smrg 1309c27c18e8Smrg ptr = cookie_out->data = malloc(len); 1310c27c18e8Smrg if (!ptr) 1311c27c18e8Smrg return False; 1312c27c18e8Smrg 1313c27c18e8Smrg out = next_block(&ptr, sizeof(XIDeviceEvent)); 1314c27c18e8Smrg *out = *in; 1315c27c18e8Smrg 1316c27c18e8Smrg out->buttons.mask = next_block(&ptr, in->buttons.mask_len); 1317c27c18e8Smrg memcpy(out->buttons.mask, in->buttons.mask, 1318c27c18e8Smrg out->buttons.mask_len); 1319c27c18e8Smrg out->valuators.mask = next_block(&ptr, in->valuators.mask_len); 1320c27c18e8Smrg memcpy(out->valuators.mask, in->valuators.mask, 1321c27c18e8Smrg out->valuators.mask_len); 1322c27c18e8Smrg out->valuators.values = next_block(&ptr, bits * sizeof(double)); 1323c27c18e8Smrg memcpy(out->valuators.values, in->valuators.values, 1324c27c18e8Smrg bits * sizeof(double)); 1325c27c18e8Smrg 1326c27c18e8Smrg return True; 1327c27c18e8Smrg} 1328c27c18e8Smrg 1329c27c18e8Smrgstatic Bool 1330c27c18e8SmrgcopyEnterEvent(XGenericEventCookie *cookie_in, 1331c27c18e8Smrg XGenericEventCookie *cookie_out) 1332c27c18e8Smrg{ 1333c27c18e8Smrg int len; 1334c27c18e8Smrg XIEnterEvent *in, *out; 1335c27c18e8Smrg void *ptr; 1336c27c18e8Smrg 1337c27c18e8Smrg in = cookie_in->data; 1338c27c18e8Smrg 1339c27c18e8Smrg len = sizeof(XIEnterEvent) + in->buttons.mask_len; 1340c27c18e8Smrg 1341c27c18e8Smrg ptr = cookie_out->data = malloc(len); 1342c27c18e8Smrg if (!ptr) 1343c27c18e8Smrg return False; 1344c27c18e8Smrg 1345c27c18e8Smrg out = next_block(&ptr, sizeof(XIEnterEvent)); 1346c27c18e8Smrg *out = *in; 1347c27c18e8Smrg 1348c27c18e8Smrg out->buttons.mask = next_block(&ptr, in->buttons.mask_len); 1349c27c18e8Smrg memcpy(out->buttons.mask, in->buttons.mask, out->buttons.mask_len); 1350c27c18e8Smrg 1351c27c18e8Smrg return True; 1352c27c18e8Smrg} 1353c27c18e8Smrg 1354c27c18e8Smrgstatic Bool 1355c27c18e8SmrgcopyPropertyEvent(XGenericEventCookie *cookie_in, 1356c27c18e8Smrg XGenericEventCookie *cookie_out) 1357c27c18e8Smrg{ 1358c27c18e8Smrg XIPropertyEvent *in, *out; 1359c27c18e8Smrg 1360c27c18e8Smrg in = cookie_in->data; 1361c27c18e8Smrg 1362c27c18e8Smrg out = cookie_out->data = malloc(sizeof(XIPropertyEvent)); 1363c27c18e8Smrg if (!out) 1364c27c18e8Smrg return False; 1365c27c18e8Smrg 1366c27c18e8Smrg *out = *in; 1367c27c18e8Smrg return True; 1368c27c18e8Smrg} 1369c27c18e8Smrg 1370f1ee322dSmrgstatic Bool 1371f1ee322dSmrgcopyTouchOwnershipEvent(XGenericEventCookie *cookie_in, 1372f1ee322dSmrg XGenericEventCookie *cookie_out) 1373f1ee322dSmrg{ 1374f1ee322dSmrg XITouchOwnershipEvent *in, *out; 1375f1ee322dSmrg 1376f1ee322dSmrg in = cookie_in->data; 1377f1ee322dSmrg 1378f1ee322dSmrg out = cookie_out->data = malloc(sizeof(XITouchOwnershipEvent)); 1379f1ee322dSmrg if (!out) 1380f1ee322dSmrg return False; 1381f1ee322dSmrg 1382f1ee322dSmrg *out = *in; 1383f1ee322dSmrg return True; 1384f1ee322dSmrg} 1385f1ee322dSmrg 1386c27c18e8Smrgstatic Bool 1387c27c18e8SmrgcopyRawEvent(XGenericEventCookie *cookie_in, 1388c27c18e8Smrg XGenericEventCookie *cookie_out) 1389c27c18e8Smrg{ 1390c27c18e8Smrg XIRawEvent *in, *out; 1391c27c18e8Smrg void *ptr; 1392c27c18e8Smrg int len; 1393c27c18e8Smrg int bits; 1394c27c18e8Smrg 1395c27c18e8Smrg in = cookie_in->data; 1396c27c18e8Smrg 1397c27c18e8Smrg bits = count_bits(in->valuators.mask, in->valuators.mask_len); 1398c27c18e8Smrg len = sizeof(XIRawEvent) + in->valuators.mask_len; 1399c27c18e8Smrg len += bits * sizeof(double) * 2; 1400c27c18e8Smrg 1401b789ec8aSmrg ptr = cookie_out->data = malloc(len); 1402c27c18e8Smrg if (!ptr) 1403c27c18e8Smrg return False; 1404c27c18e8Smrg 1405c27c18e8Smrg out = next_block(&ptr, sizeof(XIRawEvent)); 1406c27c18e8Smrg *out = *in; 1407c27c18e8Smrg out->valuators.mask = next_block(&ptr, out->valuators.mask_len); 1408c27c18e8Smrg memcpy(out->valuators.mask, in->valuators.mask, out->valuators.mask_len); 1409c27c18e8Smrg 1410c27c18e8Smrg out->valuators.values = next_block(&ptr, bits * sizeof(double)); 1411c27c18e8Smrg memcpy(out->valuators.values, in->valuators.values, bits * sizeof(double)); 1412c27c18e8Smrg 1413c27c18e8Smrg out->raw_values = next_block(&ptr, bits * sizeof(double)); 1414c27c18e8Smrg memcpy(out->raw_values, in->raw_values, bits * sizeof(double)); 1415c27c18e8Smrg 1416c27c18e8Smrg return True; 1417c27c18e8Smrg} 1418c27c18e8Smrg 1419f1ee322dSmrgstatic Bool 1420f1ee322dSmrgcopyBarrierEvent(XGenericEventCookie *in_cookie, 1421f1ee322dSmrg XGenericEventCookie *out_cookie) 1422f1ee322dSmrg{ 1423f1ee322dSmrg XIBarrierEvent *in, *out; 1424f1ee322dSmrg 1425f1ee322dSmrg in = in_cookie->data; 1426f1ee322dSmrg 1427f1ee322dSmrg out = out_cookie->data = calloc(1, sizeof(XIBarrierEvent)); 1428f1ee322dSmrg if (!out) 1429f1ee322dSmrg return False; 1430f1ee322dSmrg *out = *in; 1431c27c18e8Smrg 1432f1ee322dSmrg return True; 1433f1ee322dSmrg} 1434c27c18e8Smrg 1435c27c18e8Smrgstatic Bool 1436c27c18e8SmrgXInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) 1437c27c18e8Smrg{ 1438c27c18e8Smrg int ret = True; 1439c27c18e8Smrg 1440c27c18e8Smrg XExtDisplayInfo *info = XInput_find_display(dpy); 1441c27c18e8Smrg 1442c27c18e8Smrg if (in->extension != info->codes->major_opcode) 1443c43cc173Smrg { 1444c27c18e8Smrg printf("XInputCopyCookie: wrong extension opcode %d\n", 1445c27c18e8Smrg in->extension); 1446c27c18e8Smrg return False; 1447c27c18e8Smrg } 1448c27c18e8Smrg 1449c27c18e8Smrg *out = *in; 1450c27c18e8Smrg out->data = NULL; 1451c27c18e8Smrg out->cookie = 0; 1452c27c18e8Smrg 1453c27c18e8Smrg switch(in->evtype) { 1454c27c18e8Smrg case XI_Motion: 1455c27c18e8Smrg case XI_ButtonPress: 1456c27c18e8Smrg case XI_ButtonRelease: 1457c27c18e8Smrg case XI_KeyPress: 1458c27c18e8Smrg case XI_KeyRelease: 1459f1ee322dSmrg case XI_TouchBegin: 1460f1ee322dSmrg case XI_TouchUpdate: 1461f1ee322dSmrg case XI_TouchEnd: 1462c27c18e8Smrg ret = copyDeviceEvent(in, out); 1463c27c18e8Smrg break; 1464c27c18e8Smrg case XI_DeviceChanged: 1465c27c18e8Smrg ret = copyDeviceChangedEvent(in, out); 1466c27c18e8Smrg break; 1467c27c18e8Smrg case XI_HierarchyChanged: 1468c27c18e8Smrg ret = copyHierarchyEvent(in, out); 1469c27c18e8Smrg break; 1470c27c18e8Smrg case XI_Enter: 1471c27c18e8Smrg case XI_Leave: 1472c27c18e8Smrg case XI_FocusIn: 1473c27c18e8Smrg case XI_FocusOut: 1474c27c18e8Smrg ret = copyEnterEvent(in, out); 1475c27c18e8Smrg break; 1476c27c18e8Smrg case XI_PropertyEvent: 1477c27c18e8Smrg ret = copyPropertyEvent(in, out); 1478c27c18e8Smrg break; 1479f1ee322dSmrg case XI_TouchOwnership: 1480f1ee322dSmrg ret = copyTouchOwnershipEvent(in, out); 1481f1ee322dSmrg break; 1482c27c18e8Smrg case XI_RawKeyPress: 1483c27c18e8Smrg case XI_RawKeyRelease: 1484c27c18e8Smrg case XI_RawButtonPress: 1485c27c18e8Smrg case XI_RawButtonRelease: 1486c27c18e8Smrg case XI_RawMotion: 1487f1ee322dSmrg case XI_RawTouchBegin: 1488f1ee322dSmrg case XI_RawTouchUpdate: 1489f1ee322dSmrg case XI_RawTouchEnd: 1490c27c18e8Smrg ret = copyRawEvent(in, out); 1491c27c18e8Smrg break; 1492f1ee322dSmrg case XI_BarrierHit: 1493f1ee322dSmrg case XI_BarrierLeave: 1494f1ee322dSmrg ret = copyBarrierEvent(in, out); 1495f1ee322dSmrg break; 1496c27c18e8Smrg default: 1497c27c18e8Smrg printf("XInputCopyCookie: unknown evtype %d\n", in->evtype); 1498c27c18e8Smrg ret = False; 1499c43cc173Smrg } 1500c27c18e8Smrg 1501c27c18e8Smrg if (!ret) 1502c27c18e8Smrg printf("XInputCopyCookie: Failed to copy evtype %d", in->evtype); 1503c27c18e8Smrg return ret; 1504c27c18e8Smrg} 1505c27c18e8Smrg 1506c27c18e8Smrgstatic int 1507c27c18e8SmrgwireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* cookie) 1508c27c18e8Smrg{ 1509c27c18e8Smrg int len, i; 1510c27c18e8Smrg unsigned char *ptr; 1511c27c18e8Smrg void *ptr_lib; 1512c27c18e8Smrg FP3232 *values; 1513c27c18e8Smrg XIDeviceEvent *out; 1514c27c18e8Smrg 1515c27c18e8Smrg ptr = (unsigned char*)&in[1] + in->buttons_len * 4; 1516c27c18e8Smrg 1517c27c18e8Smrg len = sizeDeviceEvent(in->buttons_len * 4, in->valuators_len * 4, ptr); 1518c27c18e8Smrg 1519c27c18e8Smrg cookie->data = ptr_lib = malloc(len); 1520c27c18e8Smrg 1521c27c18e8Smrg out = next_block(&ptr_lib, sizeof(XIDeviceEvent)); 152289069ce9Smrg out->display = cookie->display; 1523c27c18e8Smrg out->type = in->type; 1524c27c18e8Smrg out->extension = in->extension; 1525c27c18e8Smrg out->evtype = in->evtype; 1526c27c18e8Smrg out->send_event = ((in->type & 0x80) != 0); 1527c27c18e8Smrg out->time = in->time; 1528c27c18e8Smrg out->deviceid = in->deviceid; 1529c27c18e8Smrg out->sourceid = in->sourceid; 1530c27c18e8Smrg out->detail = in->detail; 1531c27c18e8Smrg out->root = in->root; 1532c27c18e8Smrg out->event = in->event; 1533c27c18e8Smrg out->child = in->child; 1534c27c18e8Smrg out->root_x = FP1616toDBL(in->root_x); 1535c27c18e8Smrg out->root_y = FP1616toDBL(in->root_y); 1536c27c18e8Smrg out->event_x = FP1616toDBL(in->event_x); 1537c27c18e8Smrg out->event_y = FP1616toDBL(in->event_y); 1538c27c18e8Smrg out->flags = in->flags; 1539c27c18e8Smrg out->mods.base = in->mods.base_mods; 1540c27c18e8Smrg out->mods.locked = in->mods.locked_mods; 1541c27c18e8Smrg out->mods.latched = in->mods.latched_mods; 1542c27c18e8Smrg out->mods.effective = in->mods.effective_mods; 1543c27c18e8Smrg out->group.base = in->group.base_group; 1544c27c18e8Smrg out->group.locked = in->group.locked_group; 1545c27c18e8Smrg out->group.latched = in->group.latched_group; 1546c27c18e8Smrg out->group.effective = in->group.effective_group; 1547c27c18e8Smrg out->buttons.mask_len = in->buttons_len * 4; 1548c27c18e8Smrg out->valuators.mask_len = in->valuators_len * 4; 1549c27c18e8Smrg 1550c27c18e8Smrg out->buttons.mask = next_block(&ptr_lib, out->buttons.mask_len); 1551c27c18e8Smrg 1552c27c18e8Smrg /* buttons */ 1553c27c18e8Smrg ptr = (unsigned char*)&in[1]; 1554c27c18e8Smrg memcpy(out->buttons.mask, ptr, out->buttons.mask_len); 1555c27c18e8Smrg ptr += in->buttons_len * 4; 1556c27c18e8Smrg 1557c27c18e8Smrg /* valuators */ 1558c27c18e8Smrg out->valuators.mask = next_block(&ptr_lib, out->valuators.mask_len); 1559c27c18e8Smrg memcpy(out->valuators.mask, ptr, out->valuators.mask_len); 1560c27c18e8Smrg ptr += in->valuators_len * 4; 1561c27c18e8Smrg 1562c27c18e8Smrg len = count_bits(out->valuators.mask, out->valuators.mask_len); 1563c27c18e8Smrg out->valuators.values = next_block(&ptr_lib, len * sizeof(double)); 1564c27c18e8Smrg 1565c27c18e8Smrg values = (FP3232*)ptr; 1566c27c18e8Smrg for (i = 0; i < len; i++, values++) 1567c43cc173Smrg { 1568c27c18e8Smrg out->valuators.values[i] = values->integral; 1569c27c18e8Smrg out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16)); 1570c43cc173Smrg } 1571c27c18e8Smrg 1572c27c18e8Smrg 1573c27c18e8Smrg return 1; 1574c27c18e8Smrg} 1575c27c18e8Smrg 1576c27c18e8Smrg_X_HIDDEN int 1577c27c18e8Smrgsize_classes(xXIAnyInfo* from, int nclasses) 1578c27c18e8Smrg{ 1579c27c18e8Smrg int len, i; 1580c27c18e8Smrg xXIAnyInfo *any_wire; 1581c27c18e8Smrg char *ptr_wire; 1582c27c18e8Smrg 1583f1ee322dSmrg /* len for to->classes */ 1584f1ee322dSmrg len = pad_to_double(nclasses * sizeof(XIAnyClassInfo*)); 1585c27c18e8Smrg ptr_wire = (char*)from; 1586c27c18e8Smrg for (i = 0; i < nclasses; i++) 1587c43cc173Smrg { 1588c27c18e8Smrg int l = 0; 1589c27c18e8Smrg any_wire = (xXIAnyInfo*)ptr_wire; 1590c27c18e8Smrg switch(any_wire->type) 1591c27c18e8Smrg { 1592c27c18e8Smrg case XIButtonClass: 1593c27c18e8Smrg l = sizeDeviceClassType(XIButtonClass, 1594c27c18e8Smrg ((xXIButtonInfo*)any_wire)->num_buttons); 1595c27c18e8Smrg break; 1596c27c18e8Smrg case XIKeyClass: 1597c27c18e8Smrg l = sizeDeviceClassType(XIKeyClass, 1598c27c18e8Smrg ((xXIKeyInfo*)any_wire)->num_keycodes); 1599c27c18e8Smrg break; 1600c27c18e8Smrg case XIValuatorClass: 1601c27c18e8Smrg l = sizeDeviceClassType(XIValuatorClass, 0); 1602c27c18e8Smrg break; 1603f1ee322dSmrg case XIScrollClass: 1604f1ee322dSmrg l = sizeDeviceClassType(XIScrollClass, 0); 1605f1ee322dSmrg break; 1606f1ee322dSmrg case XITouchClass: 1607f1ee322dSmrg l = sizeDeviceClassType(XITouchClass, 0); 1608f1ee322dSmrg break; 1609c27c18e8Smrg } 1610c27c18e8Smrg 1611c27c18e8Smrg len += l; 1612c27c18e8Smrg ptr_wire += any_wire->length * 4; 1613c43cc173Smrg } 1614c27c18e8Smrg 1615c27c18e8Smrg return len; 1616c27c18e8Smrg} 1617c27c18e8Smrg 1618c27c18e8Smrg/* Copy classes from any into to->classes and return the number of bytes 1619c27c18e8Smrg * copied. Memory layout of to->classes is 1620c27c18e8Smrg * [clsptr][clsptr][clsptr][classinfo][classinfo]... 1621c27c18e8Smrg * |________|___________^ 1622c27c18e8Smrg * |______________________^ 1623c27c18e8Smrg */ 1624c27c18e8Smrg_X_HIDDEN int 1625f1ee322dSmrgcopy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses) 1626c27c18e8Smrg{ 1627c27c18e8Smrg XIAnyClassInfo *any_lib; 1628c27c18e8Smrg xXIAnyInfo *any_wire; 1629c27c18e8Smrg void *ptr_lib; 1630c27c18e8Smrg char *ptr_wire; 1631c27c18e8Smrg int i, len; 1632f1ee322dSmrg int cls_idx = 0; 1633c27c18e8Smrg 1634c27c18e8Smrg if (!to->classes) 1635c27c18e8Smrg return -1; 1636c27c18e8Smrg 1637c27c18e8Smrg ptr_wire = (char*)from; 1638c27c18e8Smrg ptr_lib = to->classes; 1639f1ee322dSmrg to->classes = next_block(&ptr_lib, 1640f1ee322dSmrg pad_to_double((*nclasses) * sizeof(XIAnyClassInfo*))); 1641f1ee322dSmrg memset(to->classes, 0, (*nclasses) * sizeof(XIAnyClassInfo*)); 1642c27c18e8Smrg len = 0; /* count wire length */ 1643c27c18e8Smrg 1644f1ee322dSmrg for (i = 0; i < *nclasses; i++) 1645c43cc173Smrg { 1646c27c18e8Smrg any_lib = (XIAnyClassInfo*)ptr_lib; 1647c27c18e8Smrg any_wire = (xXIAnyInfo*)ptr_wire; 1648c27c18e8Smrg 1649c27c18e8Smrg switch(any_wire->type) 1650c27c18e8Smrg { 1651c27c18e8Smrg case XIButtonClass: 1652c27c18e8Smrg { 1653c27c18e8Smrg XIButtonClassInfo *cls_lib; 1654c27c18e8Smrg xXIButtonInfo *cls_wire; 1655c27c18e8Smrg uint32_t *atoms; 1656c27c18e8Smrg int j; 1657f1ee322dSmrg int struct_size; 1658f1ee322dSmrg int state_size; 1659f1ee322dSmrg int labels_size; 1660f1ee322dSmrg int wire_mask_size; 1661c27c18e8Smrg 1662c27c18e8Smrg cls_wire = (xXIButtonInfo*)any_wire; 1663f1ee322dSmrg sizeXIButtonClassType(cls_wire->num_buttons, 1664f1ee322dSmrg &struct_size, &state_size, 1665f1ee322dSmrg &labels_size); 1666f1ee322dSmrg cls_lib = next_block(&ptr_lib, struct_size); 1667f1ee322dSmrg wire_mask_size = ((cls_wire->num_buttons + 7)/8 + 3)/4 * 4; 1668f1ee322dSmrg 1669f1ee322dSmrg cls_lib->type = cls_wire->type; 1670f1ee322dSmrg cls_lib->sourceid = cls_wire->sourceid; 1671c27c18e8Smrg cls_lib->num_buttons = cls_wire->num_buttons; 1672f1ee322dSmrg cls_lib->state.mask_len = state_size; 1673f1ee322dSmrg cls_lib->state.mask = next_block(&ptr_lib, state_size); 1674c27c18e8Smrg memcpy(cls_lib->state.mask, &cls_wire[1], 1675f1ee322dSmrg wire_mask_size); 1676f1ee322dSmrg if (state_size != wire_mask_size) 1677f1ee322dSmrg memset(&cls_lib->state.mask[wire_mask_size], 0, 1678f1ee322dSmrg state_size - wire_mask_size); 1679c27c18e8Smrg 1680f1ee322dSmrg cls_lib->labels = next_block(&ptr_lib, labels_size); 1681f1ee322dSmrg 1682f1ee322dSmrg atoms =(uint32_t*)((char*)&cls_wire[1] + wire_mask_size); 1683c27c18e8Smrg for (j = 0; j < cls_lib->num_buttons; j++) 1684c27c18e8Smrg cls_lib->labels[j] = *atoms++; 1685c27c18e8Smrg 1686f1ee322dSmrg to->classes[cls_idx++] = any_lib; 1687c27c18e8Smrg break; 1688c27c18e8Smrg } 1689c27c18e8Smrg case XIKeyClass: 1690c27c18e8Smrg { 1691c27c18e8Smrg XIKeyClassInfo *cls_lib; 1692c27c18e8Smrg xXIKeyInfo *cls_wire; 1693f1ee322dSmrg int struct_size; 1694f1ee322dSmrg int keycodes_size; 1695c27c18e8Smrg 1696c27c18e8Smrg cls_wire = (xXIKeyInfo*)any_wire; 1697f1ee322dSmrg sizeXIKeyClassType(cls_wire->num_keycodes, 1698f1ee322dSmrg &struct_size, &keycodes_size); 1699f1ee322dSmrg cls_lib = next_block(&ptr_lib, struct_size); 1700c27c18e8Smrg 1701f1ee322dSmrg cls_lib->type = cls_wire->type; 1702f1ee322dSmrg cls_lib->sourceid = cls_wire->sourceid; 1703c27c18e8Smrg cls_lib->num_keycodes = cls_wire->num_keycodes; 1704f1ee322dSmrg cls_lib->keycodes = next_block(&ptr_lib, keycodes_size); 1705c27c18e8Smrg memcpy(cls_lib->keycodes, &cls_wire[1], 1706c27c18e8Smrg cls_lib->num_keycodes); 1707c27c18e8Smrg 1708f1ee322dSmrg to->classes[cls_idx++] = any_lib; 1709c27c18e8Smrg break; 1710c27c18e8Smrg } 1711c27c18e8Smrg case XIValuatorClass: 1712c27c18e8Smrg { 1713c27c18e8Smrg XIValuatorClassInfo *cls_lib; 1714c27c18e8Smrg xXIValuatorInfo *cls_wire; 1715c27c18e8Smrg 1716f1ee322dSmrg cls_lib = 1717f1ee322dSmrg next_block(&ptr_lib, 1718f1ee322dSmrg sizeDeviceClassType(XIValuatorClass, 0)); 1719c27c18e8Smrg cls_wire = (xXIValuatorInfo*)any_wire; 1720c27c18e8Smrg 1721f1ee322dSmrg cls_lib->type = cls_wire->type; 1722f1ee322dSmrg cls_lib->sourceid = cls_wire->sourceid; 1723c27c18e8Smrg cls_lib->number = cls_wire->number; 1724c27c18e8Smrg cls_lib->label = cls_wire->label; 1725c27c18e8Smrg cls_lib->resolution = cls_wire->resolution; 1726c27c18e8Smrg cls_lib->min = cls_wire->min.integral; 1727c27c18e8Smrg cls_lib->max = cls_wire->max.integral; 1728c27c18e8Smrg cls_lib->value = cls_wire->value.integral; 1729c27c18e8Smrg /* FIXME: fractional parts */ 1730c27c18e8Smrg cls_lib->mode = cls_wire->mode; 1731c27c18e8Smrg 1732f1ee322dSmrg to->classes[cls_idx++] = any_lib; 1733f1ee322dSmrg } 1734f1ee322dSmrg break; 1735f1ee322dSmrg case XIScrollClass: 1736f1ee322dSmrg { 1737f1ee322dSmrg XIScrollClassInfo *cls_lib; 1738f1ee322dSmrg xXIScrollInfo *cls_wire; 1739f1ee322dSmrg 1740f1ee322dSmrg cls_lib = 1741f1ee322dSmrg next_block(&ptr_lib, 1742f1ee322dSmrg sizeDeviceClassType(XIScrollClass, 0)); 1743f1ee322dSmrg cls_wire = (xXIScrollInfo*)any_wire; 1744f1ee322dSmrg 1745f1ee322dSmrg cls_lib->type = cls_wire->type; 1746f1ee322dSmrg cls_lib->sourceid = cls_wire->sourceid; 1747f1ee322dSmrg cls_lib->number = cls_wire->number; 1748f1ee322dSmrg cls_lib->scroll_type= cls_wire->scroll_type; 1749f1ee322dSmrg cls_lib->flags = cls_wire->flags; 1750f1ee322dSmrg cls_lib->increment = cls_wire->increment.integral; 1751f1ee322dSmrg cls_lib->increment += (unsigned int)cls_wire->increment.frac/(double)(1ULL << 32); 1752f1ee322dSmrg 1753f1ee322dSmrg to->classes[cls_idx++] = any_lib; 1754f1ee322dSmrg } 1755f1ee322dSmrg break; 1756f1ee322dSmrg case XITouchClass: 1757f1ee322dSmrg { 1758f1ee322dSmrg XITouchClassInfo *cls_lib; 1759f1ee322dSmrg xXITouchInfo *cls_wire; 1760f1ee322dSmrg 1761f1ee322dSmrg cls_wire = (xXITouchInfo*)any_wire; 1762f1ee322dSmrg cls_lib = next_block(&ptr_lib, sizeof(XITouchClassInfo)); 1763f1ee322dSmrg 1764f1ee322dSmrg cls_lib->type = cls_wire->type; 1765f1ee322dSmrg cls_lib->sourceid = cls_wire->sourceid; 1766f1ee322dSmrg cls_lib->mode = cls_wire->mode; 1767f1ee322dSmrg cls_lib->num_touches = cls_wire->num_touches; 1768f1ee322dSmrg 1769f1ee322dSmrg to->classes[cls_idx++] = any_lib; 1770c27c18e8Smrg } 1771c27c18e8Smrg break; 1772c27c18e8Smrg } 1773c27c18e8Smrg len += any_wire->length * 4; 1774c27c18e8Smrg ptr_wire += any_wire->length * 4; 1775c43cc173Smrg } 1776f1ee322dSmrg 1777f1ee322dSmrg /* we may have skipped unknown classes, reset nclasses */ 1778f1ee322dSmrg *nclasses = cls_idx; 1779c27c18e8Smrg return len; 1780c27c18e8Smrg} 1781c27c18e8Smrg 1782c27c18e8Smrg 1783c27c18e8Smrgstatic int 1784c27c18e8SmrgwireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie) 1785c27c18e8Smrg{ 1786c27c18e8Smrg XIDeviceChangedEvent *out; 1787c27c18e8Smrg XIDeviceInfo info; 1788c27c18e8Smrg int len; 1789f1ee322dSmrg int nclasses = in->num_classes; 1790c27c18e8Smrg 1791c27c18e8Smrg len = size_classes((xXIAnyInfo*)&in[1], in->num_classes); 1792c27c18e8Smrg 1793c27c18e8Smrg cookie->data = out = malloc(sizeof(XIDeviceChangedEvent) + len); 1794c27c18e8Smrg 1795c27c18e8Smrg out->type = in->type; 179689069ce9Smrg out->display = cookie->display; 1797c27c18e8Smrg out->extension = in->extension; 1798c27c18e8Smrg out->evtype = in->evtype; 1799c27c18e8Smrg out->send_event = ((in->type & 0x80) != 0); 1800c27c18e8Smrg out->time = in->time; 1801c27c18e8Smrg out->deviceid = in->deviceid; 1802c27c18e8Smrg out->sourceid = in->sourceid; 1803c27c18e8Smrg out->reason = in->reason; 1804c27c18e8Smrg 1805c27c18e8Smrg out->classes = (XIAnyClassInfo**)&out[1]; 1806c27c18e8Smrg 1807c27c18e8Smrg info.classes = out->classes; 1808c27c18e8Smrg 1809f1ee322dSmrg copy_classes(&info, (xXIAnyInfo*)&in[1], &nclasses); 1810f1ee322dSmrg out->num_classes = nclasses; 1811c27c18e8Smrg 1812c27c18e8Smrg return 1; 1813c27c18e8Smrg} 1814c27c18e8Smrg 1815c27c18e8Smrgstatic int 1816c27c18e8SmrgwireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie) 1817c27c18e8Smrg{ 1818c27c18e8Smrg int i; 1819c27c18e8Smrg XIHierarchyInfo *info_out; 1820c27c18e8Smrg xXIHierarchyInfo *info_in; 1821c27c18e8Smrg XIHierarchyEvent *out; 1822c27c18e8Smrg 1823c27c18e8Smrg cookie->data = out = malloc(sizeof(XIHierarchyEvent) + in->num_info * sizeof(XIHierarchyInfo));; 1824c27c18e8Smrg 1825c27c18e8Smrg out->info = (XIHierarchyInfo*)&out[1]; 182689069ce9Smrg out->display = cookie->display; 1827c27c18e8Smrg out->type = in->type; 1828c27c18e8Smrg out->extension = in->extension; 1829c27c18e8Smrg out->evtype = in->evtype; 1830c27c18e8Smrg out->send_event = ((in->type & 0x80) != 0); 1831c27c18e8Smrg out->time = in->time; 1832c27c18e8Smrg out->flags = in->flags; 1833c27c18e8Smrg out->num_info = in->num_info; 1834c27c18e8Smrg 1835c27c18e8Smrg info_out = out->info; 1836c27c18e8Smrg info_in = (xXIHierarchyInfo*)&in[1]; 1837c27c18e8Smrg 1838c27c18e8Smrg for (i = 0; i < out->num_info; i++, info_out++, info_in++) 1839c43cc173Smrg { 1840c27c18e8Smrg info_out->deviceid = info_in->deviceid; 1841c27c18e8Smrg info_out->attachment = info_in->attachment; 1842c27c18e8Smrg info_out->use = info_in->use; 1843c27c18e8Smrg info_out->enabled = info_in->enabled; 1844c27c18e8Smrg info_out->flags = info_in->flags; 1845c43cc173Smrg } 1846c43cc173Smrg 1847c27c18e8Smrg return 1; 1848c27c18e8Smrg} 1849c27c18e8Smrg 1850c27c18e8Smrgstatic int 1851f1ee322dSmrgwireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *cookie) 1852c27c18e8Smrg{ 1853c27c18e8Smrg int len, i, bits; 1854c27c18e8Smrg FP3232 *values; 1855c27c18e8Smrg XIRawEvent *out; 1856c27c18e8Smrg void *ptr; 1857c27c18e8Smrg 1858c27c18e8Smrg len = sizeof(XIRawEvent) + in->valuators_len * 4; 1859c27c18e8Smrg bits = count_bits((unsigned char*)&in[1], in->valuators_len * 4); 1860c27c18e8Smrg len += bits * sizeof(double) * 2; /* raw + normal */ 1861c27c18e8Smrg 1862c27c18e8Smrg cookie->data = ptr = calloc(1, len); 1863c27c18e8Smrg if (!ptr) 1864c27c18e8Smrg return 0; 1865c27c18e8Smrg 1866c27c18e8Smrg out = next_block(&ptr, sizeof(XIRawEvent)); 1867c27c18e8Smrg out->type = in->type; 186889069ce9Smrg out->display = cookie->display; 1869c27c18e8Smrg out->extension = in->extension; 1870c27c18e8Smrg out->evtype = in->evtype; 1871c27c18e8Smrg out->send_event = ((in->type & 0x80) != 0); 1872c27c18e8Smrg out->time = in->time; 1873c27c18e8Smrg out->detail = in->detail; 1874c27c18e8Smrg out->deviceid = in->deviceid; 1875c27c18e8Smrg out->flags = in->flags; 1876c27c18e8Smrg 1877f1ee322dSmrg /* https://bugs.freedesktop.org/show_bug.cgi?id=34240 */ 1878f1ee322dSmrg if (_XiCheckVersion(info, XInput_2_2) >= 0) 1879f1ee322dSmrg out->sourceid = in->sourceid; 1880f1ee322dSmrg else 1881f1ee322dSmrg out->sourceid = 0; 1882f1ee322dSmrg 1883c27c18e8Smrg out->valuators.mask_len = in->valuators_len * 4; 1884c27c18e8Smrg out->valuators.mask = next_block(&ptr, out->valuators.mask_len); 1885c27c18e8Smrg memcpy(out->valuators.mask, &in[1], out->valuators.mask_len); 1886c27c18e8Smrg 1887c27c18e8Smrg out->valuators.values = next_block(&ptr, bits * sizeof(double)); 1888c27c18e8Smrg out->raw_values = next_block(&ptr, bits * sizeof(double)); 1889c27c18e8Smrg 1890c27c18e8Smrg values = (FP3232*)(((char*)&in[1]) + in->valuators_len * 4); 1891c27c18e8Smrg for (i = 0; i < bits; i++) 1892c43cc173Smrg { 1893c27c18e8Smrg out->valuators.values[i] = values->integral; 1894c27c18e8Smrg out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16)); 1895c27c18e8Smrg out->raw_values[i] = (values + bits)->integral; 189637eb1ca1Smrg out->raw_values[i] += ((double)(values + bits)->frac / (1 << 16) / (1 << 16)); 1897c27c18e8Smrg values++; 1898c43cc173Smrg } 1899c43cc173Smrg 1900c27c18e8Smrg return 1; 1901c27c18e8Smrg} 190221e67964Smrg 1903c27c18e8Smrg/* Memory layout of XIEnterEvents: 1904c27c18e8Smrg [event][modifiers][group][button] 1905c27c18e8Smrg */ 1906c27c18e8Smrgstatic int 1907c27c18e8SmrgwireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie) 1908c27c18e8Smrg{ 1909c27c18e8Smrg int len; 1910c27c18e8Smrg XIEnterEvent *out; 1911c27c18e8Smrg 1912c27c18e8Smrg len = sizeof(XIEnterEvent) + in->buttons_len * 4; 1913c27c18e8Smrg 1914c27c18e8Smrg cookie->data = out = malloc(len); 1915c27c18e8Smrg out->buttons.mask = (unsigned char*)&out[1]; 1916c27c18e8Smrg 1917c27c18e8Smrg out->type = in->type; 191889069ce9Smrg out->display = cookie->display; 1919c27c18e8Smrg out->extension = in->extension; 1920c27c18e8Smrg out->evtype = in->evtype; 1921c27c18e8Smrg out->send_event = ((in->type & 0x80) != 0); 1922c27c18e8Smrg out->time = in->time; 1923c27c18e8Smrg out->detail = in->detail; 1924c27c18e8Smrg out->deviceid = in->deviceid; 1925c27c18e8Smrg out->root = in->root; 1926c27c18e8Smrg out->event = in->event; 1927c27c18e8Smrg out->child = in->child; 1928c27c18e8Smrg out->sourceid = in->sourceid; 1929c27c18e8Smrg out->root_x = FP1616toDBL(in->root_x); 1930c27c18e8Smrg out->root_y = FP1616toDBL(in->root_y); 1931c27c18e8Smrg out->event_x = FP1616toDBL(in->event_x); 1932c27c18e8Smrg out->event_y = FP1616toDBL(in->event_y); 1933c27c18e8Smrg out->mode = in->mode; 1934c27c18e8Smrg out->focus = in->focus; 1935c27c18e8Smrg out->same_screen = in->same_screen; 1936c27c18e8Smrg 1937c27c18e8Smrg out->mods.base = in->mods.base_mods; 1938c27c18e8Smrg out->mods.locked = in->mods.locked_mods; 1939c27c18e8Smrg out->mods.latched = in->mods.latched_mods; 1940c27c18e8Smrg out->mods.effective = in->mods.effective_mods; 1941c27c18e8Smrg out->group.base = in->group.base_group; 1942c27c18e8Smrg out->group.locked = in->group.locked_group; 1943c27c18e8Smrg out->group.latched = in->group.latched_group; 1944c27c18e8Smrg out->group.effective = in->group.effective_group; 1945c27c18e8Smrg 1946c27c18e8Smrg out->buttons.mask_len = in->buttons_len * 4; 1947c27c18e8Smrg memcpy(out->buttons.mask, &in[1], out->buttons.mask_len); 194821e67964Smrg 1949c27c18e8Smrg return 1; 1950c27c18e8Smrg} 1951c43cc173Smrg 1952c27c18e8Smrgstatic int 1953c27c18e8SmrgwireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie) 1954c27c18e8Smrg{ 1955c27c18e8Smrg XIPropertyEvent *out = malloc(sizeof(XIPropertyEvent)); 1956c27c18e8Smrg 1957c27c18e8Smrg cookie->data = out; 1958c27c18e8Smrg 1959c27c18e8Smrg out->type = in->type; 1960c27c18e8Smrg out->extension = in->extension; 1961c27c18e8Smrg out->evtype = in->evtype; 1962c27c18e8Smrg out->send_event = ((in->type & 0x80) != 0); 1963c27c18e8Smrg out->time = in->time; 1964c27c18e8Smrg out->property = in->property; 1965c27c18e8Smrg out->what = in->what; 1966c27c18e8Smrg out->deviceid = in->deviceid; 1967c27c18e8Smrg 1968c27c18e8Smrg return 1; 1969c43cc173Smrg} 1970f1ee322dSmrg 1971f1ee322dSmrgstatic int 1972f1ee322dSmrgwireToTouchOwnershipEvent(xXITouchOwnershipEvent *in, 1973f1ee322dSmrg XGenericEventCookie *cookie) 1974f1ee322dSmrg{ 1975f1ee322dSmrg XITouchOwnershipEvent *out = malloc(sizeof(XITouchOwnershipEvent)); 1976f1ee322dSmrg 1977f1ee322dSmrg cookie->data = out; 1978f1ee322dSmrg 1979f1ee322dSmrg out->type = in->type; 1980f1ee322dSmrg out->display = cookie->display; 1981f1ee322dSmrg out->extension = in->extension; 1982f1ee322dSmrg out->evtype = in->evtype; 1983f1ee322dSmrg out->send_event = ((in->type & 0x80) != 0); 1984f1ee322dSmrg out->time = in->time; 1985f1ee322dSmrg out->deviceid = in->deviceid; 1986f1ee322dSmrg out->sourceid = in->sourceid; 1987f1ee322dSmrg out->touchid = in->touchid; 1988f1ee322dSmrg out->root = in->root; 1989f1ee322dSmrg out->event = in->event; 1990f1ee322dSmrg out->child = in->child; 1991f1ee322dSmrg out->flags = in->flags; 1992f1ee322dSmrg 1993f1ee322dSmrg return 1; 1994f1ee322dSmrg} 1995f1ee322dSmrg 1996f1ee322dSmrg#define FP3232_TO_DOUBLE(x) ((double) (x).integral + (x).frac / (1ULL << 32)) 1997f1ee322dSmrg 1998f1ee322dSmrgstatic int 1999f1ee322dSmrgwireToBarrierEvent(xXIBarrierEvent *in, XGenericEventCookie *cookie) 2000f1ee322dSmrg{ 2001f1ee322dSmrg XIBarrierEvent *out = malloc(sizeof(XIBarrierEvent)); 2002f1ee322dSmrg 2003f1ee322dSmrg cookie->data = out; 2004f1ee322dSmrg 2005f1ee322dSmrg out->display = cookie->display; 2006f1ee322dSmrg out->type = in->type; 2007f1ee322dSmrg out->extension = in->extension; 2008f1ee322dSmrg out->evtype = in->evtype; 2009f1ee322dSmrg out->send_event = ((in->type & 0x80) != 0); 2010f1ee322dSmrg out->time = in->time; 2011f1ee322dSmrg out->deviceid = in->deviceid; 2012f1ee322dSmrg out->sourceid = in->sourceid; 2013f1ee322dSmrg out->event = in->event; 2014f1ee322dSmrg out->root = in->root; 2015f1ee322dSmrg out->root_x = FP1616toDBL(in->root_x); 2016f1ee322dSmrg out->root_y = FP1616toDBL(in->root_y); 2017f1ee322dSmrg out->dx = FP3232_TO_DOUBLE (in->dx); 2018f1ee322dSmrg out->dy = FP3232_TO_DOUBLE (in->dy); 2019f1ee322dSmrg out->dtime = in->dtime; 2020f1ee322dSmrg out->flags = in->flags; 2021f1ee322dSmrg out->barrier = in->barrier; 2022f1ee322dSmrg out->eventid = in->eventid; 2023f1ee322dSmrg 2024f1ee322dSmrg return 1; 2025f1ee322dSmrg} 2026