xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xiproperty.c (37523B)


      1 /*
      2  * Copyright © 2006 Keith Packard
      3  * Copyright © 2008 Peter Hutterer
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WAXIANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  */
     25 
     26 /* This code is a modified version of randr/rrproperty.c */
     27 
     28 #ifdef HAVE_DIX_CONFIG_H
     29 #include <dix-config.h>
     30 #endif
     31 
     32 #include "dix.h"
     33 #include "inputstr.h"
     34 #include <X11/extensions/XI.h>
     35 #include <X11/Xatom.h>
     36 #include <X11/extensions/XIproto.h>
     37 #include <X11/extensions/XI2proto.h>
     38 #include "exglobals.h"
     39 #include "exevents.h"
     40 #include "swaprep.h"
     41 
     42 #include "xiproperty.h"
     43 #include "xserver-properties.h"
     44 
     45 /**
     46  * Properties used or alloced from inside the server.
     47  */
     48 static struct dev_properties {
     49     Atom type;
     50     const char *name;
     51 } dev_properties[] = {
     52     {0, XI_PROP_ENABLED},
     53     {0, XI_PROP_XTEST_DEVICE},
     54     {0, XATOM_FLOAT},
     55     {0, ACCEL_PROP_PROFILE_NUMBER},
     56     {0, ACCEL_PROP_CONSTANT_DECELERATION},
     57     {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
     58     {0, ACCEL_PROP_VELOCITY_SCALING},
     59     {0, AXIS_LABEL_PROP},
     60     {0, AXIS_LABEL_PROP_REL_X},
     61     {0, AXIS_LABEL_PROP_REL_Y},
     62     {0, AXIS_LABEL_PROP_REL_Z},
     63     {0, AXIS_LABEL_PROP_REL_RX},
     64     {0, AXIS_LABEL_PROP_REL_RY},
     65     {0, AXIS_LABEL_PROP_REL_RZ},
     66     {0, AXIS_LABEL_PROP_REL_HWHEEL},
     67     {0, AXIS_LABEL_PROP_REL_DIAL},
     68     {0, AXIS_LABEL_PROP_REL_WHEEL},
     69     {0, AXIS_LABEL_PROP_REL_MISC},
     70     {0, AXIS_LABEL_PROP_REL_VSCROLL},
     71     {0, AXIS_LABEL_PROP_REL_HSCROLL},
     72     {0, AXIS_LABEL_PROP_ABS_X},
     73     {0, AXIS_LABEL_PROP_ABS_Y},
     74     {0, AXIS_LABEL_PROP_ABS_Z},
     75     {0, AXIS_LABEL_PROP_ABS_RX},
     76     {0, AXIS_LABEL_PROP_ABS_RY},
     77     {0, AXIS_LABEL_PROP_ABS_RZ},
     78     {0, AXIS_LABEL_PROP_ABS_THROTTLE},
     79     {0, AXIS_LABEL_PROP_ABS_RUDDER},
     80     {0, AXIS_LABEL_PROP_ABS_WHEEL},
     81     {0, AXIS_LABEL_PROP_ABS_GAS},
     82     {0, AXIS_LABEL_PROP_ABS_BRAKE},
     83     {0, AXIS_LABEL_PROP_ABS_HAT0X},
     84     {0, AXIS_LABEL_PROP_ABS_HAT0Y},
     85     {0, AXIS_LABEL_PROP_ABS_HAT1X},
     86     {0, AXIS_LABEL_PROP_ABS_HAT1Y},
     87     {0, AXIS_LABEL_PROP_ABS_HAT2X},
     88     {0, AXIS_LABEL_PROP_ABS_HAT2Y},
     89     {0, AXIS_LABEL_PROP_ABS_HAT3X},
     90     {0, AXIS_LABEL_PROP_ABS_HAT3Y},
     91     {0, AXIS_LABEL_PROP_ABS_PRESSURE},
     92     {0, AXIS_LABEL_PROP_ABS_DISTANCE},
     93     {0, AXIS_LABEL_PROP_ABS_TILT_X},
     94     {0, AXIS_LABEL_PROP_ABS_TILT_Y},
     95     {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH},
     96     {0, AXIS_LABEL_PROP_ABS_VOLUME},
     97     {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR},
     98     {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR},
     99     {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR},
    100     {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR},
    101     {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION},
    102     {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X},
    103     {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y},
    104     {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE},
    105     {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID},
    106     {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID},
    107     {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE},
    108     {0, AXIS_LABEL_PROP_ABS_MT_DISTANCE},
    109     {0, AXIS_LABEL_PROP_ABS_MT_TOOL_X},
    110     {0, AXIS_LABEL_PROP_ABS_MT_TOOL_Y},
    111     {0, AXIS_LABEL_PROP_ABS_MISC},
    112     {0, BTN_LABEL_PROP},
    113     {0, BTN_LABEL_PROP_BTN_UNKNOWN},
    114     {0, BTN_LABEL_PROP_BTN_WHEEL_UP},
    115     {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN},
    116     {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT},
    117     {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT},
    118     {0, BTN_LABEL_PROP_BTN_0},
    119     {0, BTN_LABEL_PROP_BTN_1},
    120     {0, BTN_LABEL_PROP_BTN_2},
    121     {0, BTN_LABEL_PROP_BTN_3},
    122     {0, BTN_LABEL_PROP_BTN_4},
    123     {0, BTN_LABEL_PROP_BTN_5},
    124     {0, BTN_LABEL_PROP_BTN_6},
    125     {0, BTN_LABEL_PROP_BTN_7},
    126     {0, BTN_LABEL_PROP_BTN_8},
    127     {0, BTN_LABEL_PROP_BTN_9},
    128     {0, BTN_LABEL_PROP_BTN_LEFT},
    129     {0, BTN_LABEL_PROP_BTN_RIGHT},
    130     {0, BTN_LABEL_PROP_BTN_MIDDLE},
    131     {0, BTN_LABEL_PROP_BTN_SIDE},
    132     {0, BTN_LABEL_PROP_BTN_EXTRA},
    133     {0, BTN_LABEL_PROP_BTN_FORWARD},
    134     {0, BTN_LABEL_PROP_BTN_BACK},
    135     {0, BTN_LABEL_PROP_BTN_TASK},
    136     {0, BTN_LABEL_PROP_BTN_TRIGGER},
    137     {0, BTN_LABEL_PROP_BTN_THUMB},
    138     {0, BTN_LABEL_PROP_BTN_THUMB2},
    139     {0, BTN_LABEL_PROP_BTN_TOP},
    140     {0, BTN_LABEL_PROP_BTN_TOP2},
    141     {0, BTN_LABEL_PROP_BTN_PINKIE},
    142     {0, BTN_LABEL_PROP_BTN_BASE},
    143     {0, BTN_LABEL_PROP_BTN_BASE2},
    144     {0, BTN_LABEL_PROP_BTN_BASE3},
    145     {0, BTN_LABEL_PROP_BTN_BASE4},
    146     {0, BTN_LABEL_PROP_BTN_BASE5},
    147     {0, BTN_LABEL_PROP_BTN_BASE6},
    148     {0, BTN_LABEL_PROP_BTN_DEAD},
    149     {0, BTN_LABEL_PROP_BTN_A},
    150     {0, BTN_LABEL_PROP_BTN_B},
    151     {0, BTN_LABEL_PROP_BTN_C},
    152     {0, BTN_LABEL_PROP_BTN_X},
    153     {0, BTN_LABEL_PROP_BTN_Y},
    154     {0, BTN_LABEL_PROP_BTN_Z},
    155     {0, BTN_LABEL_PROP_BTN_TL},
    156     {0, BTN_LABEL_PROP_BTN_TR},
    157     {0, BTN_LABEL_PROP_BTN_TL2},
    158     {0, BTN_LABEL_PROP_BTN_TR2},
    159     {0, BTN_LABEL_PROP_BTN_SELECT},
    160     {0, BTN_LABEL_PROP_BTN_START},
    161     {0, BTN_LABEL_PROP_BTN_MODE},
    162     {0, BTN_LABEL_PROP_BTN_THUMBL},
    163     {0, BTN_LABEL_PROP_BTN_THUMBR},
    164     {0, BTN_LABEL_PROP_BTN_TOOL_PEN},
    165     {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
    166     {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
    167     {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
    168     {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
    169     {0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
    170     {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
    171     {0, BTN_LABEL_PROP_BTN_TOOL_LENS},
    172     {0, BTN_LABEL_PROP_BTN_TOUCH},
    173     {0, BTN_LABEL_PROP_BTN_STYLUS},
    174     {0, BTN_LABEL_PROP_BTN_STYLUS2},
    175     {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
    176     {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
    177     {0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
    178     {0, BTN_LABEL_PROP_BTN_GEAR_UP},
    179     {0, XI_PROP_TRANSFORM}
    180 };
    181 
    182 static long XIPropHandlerID = 1;
    183 
    184 static void
    185 send_property_event(DeviceIntPtr dev, Atom property, int what)
    186 {
    187     int state = (what == XIPropertyDeleted) ? PropertyDelete : PropertyNewValue;
    188     devicePropertyNotify event = {
    189         .type = DevicePropertyNotify,
    190         .deviceid = dev->id,
    191         .state = state,
    192         .atom = property,
    193         .time = currentTime.milliseconds
    194     };
    195     xXIPropertyEvent xi2 = {
    196         .type = GenericEvent,
    197         .extension = IReqCode,
    198         .length = 0,
    199         .evtype = XI_PropertyEvent,
    200         .deviceid = dev->id,
    201         .time = currentTime.milliseconds,
    202         .property = property,
    203         .what = what
    204     };
    205 
    206     SendEventToAllWindows(dev, DevicePropertyNotifyMask, (xEvent *) &event, 1);
    207 
    208     SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent *) &xi2),
    209                           (xEvent *) &xi2, 1);
    210 }
    211 
    212 static int
    213 list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
    214 {
    215     XIPropertyPtr prop;
    216     Atom *atoms = NULL;
    217     int nprops = 0;
    218 
    219     for (prop = dev->properties.properties; prop; prop = prop->next)
    220         nprops++;
    221     if (nprops) {
    222         Atom *a;
    223 
    224         atoms = xallocarray(nprops, sizeof(Atom));
    225         if (!atoms)
    226             return BadAlloc;
    227         a = atoms;
    228         for (prop = dev->properties.properties; prop; prop = prop->next, a++)
    229             *a = prop->propertyName;
    230     }
    231 
    232     *natoms = nprops;
    233     *atoms_return = atoms;
    234     return Success;
    235 }
    236 
    237 static int
    238 get_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
    239              BOOL delete, int offset, int length,
    240              int *bytes_after, Atom *type_return, int *format, int *nitems,
    241              int *length_return, char **data)
    242 {
    243     unsigned long n, len, ind;
    244     int rc;
    245     XIPropertyPtr prop;
    246     XIPropertyValuePtr prop_value;
    247 
    248     if (!ValidAtom(property)) {
    249         client->errorValue = property;
    250         return BadAtom;
    251     }
    252     if ((delete != xTrue) && (delete != xFalse)) {
    253         client->errorValue = delete;
    254         return BadValue;
    255     }
    256 
    257     if ((type != AnyPropertyType) && !ValidAtom(type)) {
    258         client->errorValue = type;
    259         return BadAtom;
    260     }
    261 
    262     for (prop = dev->properties.properties; prop; prop = prop->next)
    263         if (prop->propertyName == property)
    264             break;
    265 
    266     if (!prop) {
    267         *bytes_after = 0;
    268         *type_return = None;
    269         *format = 0;
    270         *nitems = 0;
    271         *length_return = 0;
    272         return Success;
    273     }
    274 
    275     rc = XIGetDeviceProperty(dev, property, &prop_value);
    276     if (rc != Success) {
    277         client->errorValue = property;
    278         return rc;
    279     }
    280 
    281     /* If the request type and actual type don't match. Return the
    282        property information, but not the data. */
    283 
    284     if (((type != prop_value->type) && (type != AnyPropertyType))) {
    285         *bytes_after = prop_value->size;
    286         *format = prop_value->format;
    287         *length_return = 0;
    288         *nitems = 0;
    289         *type_return = prop_value->type;
    290         return Success;
    291     }
    292 
    293     /* Return type, format, value to client */
    294     n = (prop_value->format / 8) * prop_value->size;    /* size (bytes) of prop */
    295     ind = offset << 2;
    296 
    297     /* If offset is invalid such that it causes "len" to
    298        be negative, it's a value error. */
    299 
    300     if (n < ind) {
    301         client->errorValue = offset;
    302         return BadValue;
    303     }
    304 
    305     len = min(n - ind, 4 * length);
    306 
    307     *bytes_after = n - (ind + len);
    308     *format = prop_value->format;
    309     *length_return = len;
    310     if (prop_value->format)
    311         *nitems = len / (prop_value->format / 8);
    312     else
    313         *nitems = 0;
    314     *type_return = prop_value->type;
    315 
    316     *data = (char *) prop_value->data + ind;
    317 
    318     return Success;
    319 }
    320 
    321 static int
    322 check_change_property(ClientPtr client, Atom property, Atom type, int format,
    323                       int mode, int nitems)
    324 {
    325     if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
    326         (mode != PropModePrepend)) {
    327         client->errorValue = mode;
    328         return BadValue;
    329     }
    330     if ((format != 8) && (format != 16) && (format != 32)) {
    331         client->errorValue = format;
    332         return BadValue;
    333     }
    334 
    335     if (!ValidAtom(property)) {
    336         client->errorValue = property;
    337         return BadAtom;
    338     }
    339     if (!ValidAtom(type)) {
    340         client->errorValue = type;
    341         return BadAtom;
    342     }
    343 
    344     return Success;
    345 }
    346 
    347 static int
    348 change_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
    349                 int format, int mode, int len, void *data)
    350 {
    351     int rc = Success;
    352 
    353     rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data,
    354                                 TRUE);
    355     if (rc != Success)
    356         client->errorValue = property;
    357 
    358     return rc;
    359 }
    360 
    361 /**
    362  * Return the atom assigned to the specified string or 0 if the atom isn't known
    363  * to the DIX.
    364  *
    365  * If name is NULL, None is returned.
    366  */
    367 Atom
    368 XIGetKnownProperty(const char *name)
    369 {
    370     int i;
    371 
    372     if (!name)
    373         return None;
    374 
    375     for (i = 0; i < ARRAY_SIZE(dev_properties); i++) {
    376         if (strcmp(name, dev_properties[i].name) == 0) {
    377             if (dev_properties[i].type == None) {
    378                 dev_properties[i].type =
    379                     MakeAtom(dev_properties[i].name,
    380                              strlen(dev_properties[i].name), TRUE);
    381             }
    382 
    383             return dev_properties[i].type;
    384         }
    385     }
    386 
    387     return 0;
    388 }
    389 
    390 void
    391 XIResetProperties(void)
    392 {
    393     int i;
    394 
    395     for (i = 0; i < ARRAY_SIZE(dev_properties); i++)
    396         dev_properties[i].type = None;
    397 }
    398 
    399 /**
    400  * Convert the given property's value(s) into @nelem_return integer values and
    401  * store them in @buf_return. If @nelem_return is larger than the number of
    402  * values in the property, @nelem_return is set to the number of values in the
    403  * property.
    404  *
    405  * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
    406  * automatically and must be freed by the caller.
    407  *
    408  * Possible return codes.
    409  * Success ... No error.
    410  * BadMatch ... Wrong atom type, atom is not XA_INTEGER
    411  * BadAlloc ... NULL passed as buffer and allocation failed.
    412  * BadLength ... @buff is NULL but @nelem_return is non-zero.
    413  *
    414  * @param val The property value
    415  * @param nelem_return The maximum number of elements to return.
    416  * @param buf_return Pointer to an array of at least @nelem_return values.
    417  * @return Success or the error code if an error occurred.
    418  */
    419 _X_EXPORT int
    420 XIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
    421 {
    422     int i;
    423     int *buf;
    424 
    425     if (val->type != XA_INTEGER)
    426         return BadMatch;
    427     if (!*buf_return && *nelem_return)
    428         return BadLength;
    429 
    430     switch (val->format) {
    431     case 8:
    432     case 16:
    433     case 32:
    434         break;
    435     default:
    436         return BadValue;
    437     }
    438 
    439     buf = *buf_return;
    440 
    441     if (!buf && !(*nelem_return)) {
    442         buf = calloc(val->size, sizeof(int));
    443         if (!buf)
    444             return BadAlloc;
    445         *buf_return = buf;
    446         *nelem_return = val->size;
    447     }
    448     else if (val->size < *nelem_return)
    449         *nelem_return = val->size;
    450 
    451     for (i = 0; i < val->size && i < *nelem_return; i++) {
    452         switch (val->format) {
    453         case 8:
    454             buf[i] = ((CARD8 *) val->data)[i];
    455             break;
    456         case 16:
    457             buf[i] = ((CARD16 *) val->data)[i];
    458             break;
    459         case 32:
    460             buf[i] = ((CARD32 *) val->data)[i];
    461             break;
    462         }
    463     }
    464 
    465     return Success;
    466 }
    467 
    468 /**
    469  * Convert the given property's value(s) into @nelem_return float values and
    470  * store them in @buf_return. If @nelem_return is larger than the number of
    471  * values in the property, @nelem_return is set to the number of values in the
    472  * property.
    473  *
    474  * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
    475  * automatically and must be freed by the caller.
    476  *
    477  * Possible errors returned:
    478  * Success
    479  * BadMatch ... Wrong atom type, atom is not XA_FLOAT
    480  * BadValue ... Wrong format, format is not 32
    481  * BadAlloc ... NULL passed as buffer and allocation failed.
    482  * BadLength ... @buff is NULL but @nelem_return is non-zero.
    483  *
    484  * @param val The property value
    485  * @param nelem_return The maximum number of elements to return.
    486  * @param buf_return Pointer to an array of at least @nelem_return values.
    487  * @return Success or the error code if an error occurred.
    488  */
    489 _X_EXPORT int
    490 XIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
    491 {
    492     int i;
    493     float *buf;
    494 
    495     if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
    496         return BadMatch;
    497 
    498     if (val->format != 32)
    499         return BadValue;
    500     if (!*buf_return && *nelem_return)
    501         return BadLength;
    502 
    503     buf = *buf_return;
    504 
    505     if (!buf && !(*nelem_return)) {
    506         buf = calloc(val->size, sizeof(float));
    507         if (!buf)
    508             return BadAlloc;
    509         *buf_return = buf;
    510         *nelem_return = val->size;
    511     }
    512     else if (val->size < *nelem_return)
    513         *nelem_return = val->size;
    514 
    515     for (i = 0; i < val->size && i < *nelem_return; i++)
    516         buf[i] = ((float *) val->data)[i];
    517 
    518     return Success;
    519 }
    520 
    521 /* Registers a new property handler on the given device and returns a unique
    522  * identifier for this handler. This identifier is required to unregister the
    523  * property handler again.
    524  * @return The handler's identifier or 0 if an error occurred.
    525  */
    526 long
    527 XIRegisterPropertyHandler(DeviceIntPtr dev,
    528                           int (*SetProperty) (DeviceIntPtr dev,
    529                                               Atom property,
    530                                               XIPropertyValuePtr prop,
    531                                               BOOL checkonly),
    532                           int (*GetProperty) (DeviceIntPtr dev,
    533                                               Atom property),
    534                           int (*DeleteProperty) (DeviceIntPtr dev,
    535                                                  Atom property))
    536 {
    537     XIPropertyHandlerPtr new_handler;
    538 
    539     new_handler = calloc(1, sizeof(XIPropertyHandler));
    540     if (!new_handler)
    541         return 0;
    542 
    543     new_handler->id = XIPropHandlerID++;
    544     new_handler->SetProperty = SetProperty;
    545     new_handler->GetProperty = GetProperty;
    546     new_handler->DeleteProperty = DeleteProperty;
    547     new_handler->next = dev->properties.handlers;
    548     dev->properties.handlers = new_handler;
    549 
    550     return new_handler->id;
    551 }
    552 
    553 void
    554 XIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
    555 {
    556     XIPropertyHandlerPtr curr, prev = NULL;
    557 
    558     curr = dev->properties.handlers;
    559     while (curr && curr->id != id) {
    560         prev = curr;
    561         curr = curr->next;
    562     }
    563 
    564     if (!curr)
    565         return;
    566 
    567     if (!prev)                  /* first one */
    568         dev->properties.handlers = curr->next;
    569     else
    570         prev->next = curr->next;
    571 
    572     free(curr);
    573 }
    574 
    575 static XIPropertyPtr
    576 XICreateDeviceProperty(Atom property)
    577 {
    578     XIPropertyPtr prop;
    579 
    580     prop = (XIPropertyPtr) malloc(sizeof(XIPropertyRec));
    581     if (!prop)
    582         return NULL;
    583 
    584     prop->next = NULL;
    585     prop->propertyName = property;
    586     prop->value.type = None;
    587     prop->value.format = 0;
    588     prop->value.size = 0;
    589     prop->value.data = NULL;
    590     prop->deletable = TRUE;
    591 
    592     return prop;
    593 }
    594 
    595 static XIPropertyPtr
    596 XIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
    597 {
    598     XIPropertyPtr prop;
    599 
    600     for (prop = dev->properties.properties; prop; prop = prop->next)
    601         if (prop->propertyName == property)
    602             return prop;
    603     return NULL;
    604 }
    605 
    606 static void
    607 XIDestroyDeviceProperty(XIPropertyPtr prop)
    608 {
    609     free(prop->value.data);
    610     free(prop);
    611 }
    612 
    613 /* This function destroys all of the device's property-related stuff,
    614  * including removing all device handlers.
    615  * DO NOT CALL FROM THE DRIVER.
    616  */
    617 void
    618 XIDeleteAllDeviceProperties(DeviceIntPtr device)
    619 {
    620     XIPropertyPtr prop, next;
    621     XIPropertyHandlerPtr curr_handler, next_handler;
    622 
    623     UpdateCurrentTimeIf();
    624     for (prop = device->properties.properties; prop; prop = next) {
    625         next = prop->next;
    626         send_property_event(device, prop->propertyName, XIPropertyDeleted);
    627         XIDestroyDeviceProperty(prop);
    628     }
    629 
    630     device->properties.properties = NULL;
    631 
    632     /* Now free all handlers */
    633     curr_handler = device->properties.handlers;
    634     while (curr_handler) {
    635         next_handler = curr_handler->next;
    636         free(curr_handler);
    637         curr_handler = next_handler;
    638     }
    639 
    640     device->properties.handlers = NULL;
    641 }
    642 
    643 int
    644 XIDeleteDeviceProperty(DeviceIntPtr device, Atom property, Bool fromClient)
    645 {
    646     XIPropertyPtr prop, *prev;
    647     int rc = Success;
    648 
    649     for (prev = &device->properties.properties; (prop = *prev);
    650          prev = &(prop->next))
    651         if (prop->propertyName == property)
    652             break;
    653 
    654     if (!prop)
    655         return Success;
    656 
    657     if (fromClient && !prop->deletable)
    658         return BadAccess;
    659 
    660     /* Ask handlers if we may delete the property */
    661     if (device->properties.handlers) {
    662         XIPropertyHandlerPtr handler = device->properties.handlers;
    663 
    664         while (handler) {
    665             if (handler->DeleteProperty)
    666                 rc = handler->DeleteProperty(device, prop->propertyName);
    667             if (rc != Success)
    668                 return rc;
    669             handler = handler->next;
    670         }
    671     }
    672 
    673     if (prop) {
    674         UpdateCurrentTimeIf();
    675         *prev = prop->next;
    676         send_property_event(device, prop->propertyName, XIPropertyDeleted);
    677         XIDestroyDeviceProperty(prop);
    678     }
    679 
    680     return Success;
    681 }
    682 
    683 int
    684 XIChangeDeviceProperty(DeviceIntPtr dev, Atom property, Atom type,
    685                        int format, int mode, unsigned long len,
    686                        const void *value, Bool sendevent)
    687 {
    688     XIPropertyPtr prop;
    689     int size_in_bytes;
    690     unsigned long total_len;
    691     XIPropertyValuePtr prop_value;
    692     XIPropertyValueRec new_value;
    693     Bool add = FALSE;
    694     int rc;
    695 
    696     size_in_bytes = format >> 3;
    697 
    698     /* first see if property already exists */
    699     prop = XIFetchDeviceProperty(dev, property);
    700     if (!prop) {                /* just add to list */
    701         prop = XICreateDeviceProperty(property);
    702         if (!prop)
    703             return BadAlloc;
    704         add = TRUE;
    705         mode = PropModeReplace;
    706     }
    707     prop_value = &prop->value;
    708 
    709     /* To append or prepend to a property the request format and type
    710        must match those of the already defined property.  The
    711        existing format and type are irrelevant when using the mode
    712        "PropModeReplace" since they will be written over. */
    713 
    714     if ((format != prop_value->format) && (mode != PropModeReplace))
    715         return BadMatch;
    716     if ((prop_value->type != type) && (mode != PropModeReplace))
    717         return BadMatch;
    718     new_value = *prop_value;
    719     if (mode == PropModeReplace)
    720         total_len = len;
    721     else
    722         total_len = prop_value->size + len;
    723 
    724     if (mode == PropModeReplace || len > 0) {
    725         void *new_data = NULL, *old_data = NULL;
    726 
    727         new_value.data = xallocarray(total_len, size_in_bytes);
    728         if (!new_value.data && total_len && size_in_bytes) {
    729             if (add)
    730                 XIDestroyDeviceProperty(prop);
    731             return BadAlloc;
    732         }
    733         new_value.size = len;
    734         new_value.type = type;
    735         new_value.format = format;
    736 
    737         switch (mode) {
    738         case PropModeReplace:
    739             new_data = new_value.data;
    740             old_data = NULL;
    741             break;
    742         case PropModeAppend:
    743             new_data = (void *) (((char *) new_value.data) +
    744                                   (prop_value->size * size_in_bytes));
    745             old_data = new_value.data;
    746             break;
    747         case PropModePrepend:
    748             new_data = new_value.data;
    749             old_data = (void *) (((char *) new_value.data) +
    750                                   (prop_value->size * size_in_bytes));
    751             break;
    752         }
    753         if (new_data)
    754             memcpy((char *) new_data, value, len * size_in_bytes);
    755         if (old_data)
    756             memcpy((char *) old_data, (char *) prop_value->data,
    757                    prop_value->size * size_in_bytes);
    758 
    759         if (dev->properties.handlers) {
    760             XIPropertyHandlerPtr handler;
    761             BOOL checkonly = TRUE;
    762 
    763             /* run through all handlers with checkonly TRUE, then again with
    764              * checkonly FALSE. Handlers MUST return error codes on the
    765              * checkonly run, errors on the second run are ignored */
    766             do {
    767                 handler = dev->properties.handlers;
    768                 while (handler) {
    769                     if (handler->SetProperty) {
    770                         input_lock();
    771                         rc = handler->SetProperty(dev, prop->propertyName,
    772                                                   &new_value, checkonly);
    773                         input_unlock();
    774                         if (checkonly && rc != Success) {
    775                             free(new_value.data);
    776                             if (add)
    777                                 XIDestroyDeviceProperty(prop);
    778                             return rc;
    779                         }
    780                     }
    781                     handler = handler->next;
    782                 }
    783                 checkonly = !checkonly;
    784             } while (!checkonly);
    785         }
    786         free(prop_value->data);
    787         *prop_value = new_value;
    788     }
    789     else if (len == 0) {
    790         /* do nothing */
    791     }
    792 
    793     if (add) {
    794         prop->next = dev->properties.properties;
    795         dev->properties.properties = prop;
    796     }
    797 
    798     if (sendevent) {
    799         UpdateCurrentTimeIf();
    800         send_property_event(dev, prop->propertyName,
    801                             (add) ? XIPropertyCreated : XIPropertyModified);
    802     }
    803 
    804     return Success;
    805 }
    806 
    807 int
    808 XIGetDeviceProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
    809 {
    810     XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
    811     int rc;
    812 
    813     if (!prop) {
    814         *value = NULL;
    815         return BadAtom;
    816     }
    817 
    818     /* If we can, try to update the property value first */
    819     if (dev->properties.handlers) {
    820         XIPropertyHandlerPtr handler = dev->properties.handlers;
    821 
    822         while (handler) {
    823             if (handler->GetProperty) {
    824                 rc = handler->GetProperty(dev, prop->propertyName);
    825                 if (rc != Success) {
    826                     *value = NULL;
    827                     return rc;
    828                 }
    829             }
    830             handler = handler->next;
    831         }
    832     }
    833 
    834     *value = &prop->value;
    835     return Success;
    836 }
    837 
    838 int
    839 XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
    840 {
    841     XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
    842 
    843     if (!prop)
    844         return BadAtom;
    845 
    846     prop->deletable = deletable;
    847     return Success;
    848 }
    849 
    850 int
    851 ProcXListDeviceProperties(ClientPtr client)
    852 {
    853     Atom *atoms;
    854     xListDevicePropertiesReply rep;
    855     int natoms;
    856     DeviceIntPtr dev;
    857     int rc = Success;
    858 
    859     REQUEST(xListDevicePropertiesReq);
    860     REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
    861 
    862     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess);
    863     if (rc != Success)
    864         return rc;
    865 
    866     rc = list_atoms(dev, &natoms, &atoms);
    867     if (rc != Success)
    868         return rc;
    869 
    870     rep = (xListDevicePropertiesReply) {
    871         .repType = X_Reply,
    872         .RepType = X_ListDeviceProperties,
    873         .sequenceNumber = client->sequence,
    874         .length = natoms,
    875         .nAtoms = natoms
    876     };
    877 
    878     WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
    879     if (natoms) {
    880         client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
    881         WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
    882         free(atoms);
    883     }
    884     return rc;
    885 }
    886 
    887 int
    888 ProcXChangeDeviceProperty(ClientPtr client)
    889 {
    890     REQUEST(xChangeDevicePropertyReq);
    891     DeviceIntPtr dev;
    892     unsigned long len;
    893     int totalSize;
    894     int rc;
    895 
    896     REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
    897     UpdateCurrentTime();
    898 
    899     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
    900     if (rc != Success)
    901         return rc;
    902 
    903     rc = check_change_property(client, stuff->property, stuff->type,
    904                                stuff->format, stuff->mode, stuff->nUnits);
    905 
    906     len = stuff->nUnits;
    907     if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
    908         return BadLength;
    909 
    910     totalSize = len * (stuff->format / 8);
    911     REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
    912 
    913     rc = change_property(client, dev, stuff->property, stuff->type,
    914                          stuff->format, stuff->mode, len, (void *) &stuff[1]);
    915     return rc;
    916 }
    917 
    918 int
    919 ProcXDeleteDeviceProperty(ClientPtr client)
    920 {
    921     REQUEST(xDeleteDevicePropertyReq);
    922     DeviceIntPtr dev;
    923     int rc;
    924 
    925     REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
    926     UpdateCurrentTime();
    927     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
    928     if (rc != Success)
    929         return rc;
    930 
    931     if (!ValidAtom(stuff->property)) {
    932         client->errorValue = stuff->property;
    933         return BadAtom;
    934     }
    935 
    936     rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
    937     return rc;
    938 }
    939 
    940 int
    941 ProcXGetDeviceProperty(ClientPtr client)
    942 {
    943     REQUEST(xGetDevicePropertyReq);
    944     DeviceIntPtr dev;
    945     int length;
    946     int rc, format, nitems, bytes_after;
    947     char *data;
    948     Atom type;
    949     xGetDevicePropertyReply reply;
    950 
    951     REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
    952     if (stuff->delete)
    953         UpdateCurrentTime();
    954     rc = dixLookupDevice(&dev, stuff->deviceid, client,
    955                          stuff->delete ? DixSetPropAccess : DixGetPropAccess);
    956     if (rc != Success)
    957         return rc;
    958 
    959     rc = get_property(client, dev, stuff->property, stuff->type,
    960                       stuff->delete, stuff->longOffset, stuff->longLength,
    961                       &bytes_after, &type, &format, &nitems, &length, &data);
    962 
    963     if (rc != Success)
    964         return rc;
    965 
    966     reply = (xGetDevicePropertyReply) {
    967         .repType = X_Reply,
    968         .RepType = X_GetDeviceProperty,
    969         .sequenceNumber = client->sequence,
    970         .length = bytes_to_int32(length),
    971         .propertyType = type,
    972         .bytesAfter = bytes_after,
    973         .nItems = nitems,
    974         .format = format,
    975         .deviceid = dev->id
    976     };
    977 
    978     if (stuff->delete && (reply.bytesAfter == 0))
    979         send_property_event(dev, stuff->property, XIPropertyDeleted);
    980 
    981     WriteReplyToClient(client, sizeof(xGenericReply), &reply);
    982 
    983     if (length) {
    984         switch (reply.format) {
    985         case 32:
    986             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
    987             break;
    988         case 16:
    989             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
    990             break;
    991         default:
    992             client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
    993             break;
    994         }
    995         WriteSwappedDataToClient(client, length, data);
    996     }
    997 
    998     /* delete the Property */
    999     if (stuff->delete && (reply.bytesAfter == 0)) {
   1000         XIPropertyPtr prop, *prev;
   1001 
   1002         for (prev = &dev->properties.properties; (prop = *prev);
   1003              prev = &prop->next) {
   1004             if (prop->propertyName == stuff->property) {
   1005                 *prev = prop->next;
   1006                 XIDestroyDeviceProperty(prop);
   1007                 break;
   1008             }
   1009         }
   1010     }
   1011     return Success;
   1012 }
   1013 
   1014 int _X_COLD
   1015 SProcXListDeviceProperties(ClientPtr client)
   1016 {
   1017     REQUEST(xListDevicePropertiesReq);
   1018     REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
   1019 
   1020     swaps(&stuff->length);
   1021     return (ProcXListDeviceProperties(client));
   1022 }
   1023 
   1024 int _X_COLD
   1025 SProcXChangeDeviceProperty(ClientPtr client)
   1026 {
   1027     REQUEST(xChangeDevicePropertyReq);
   1028 
   1029     REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
   1030     swaps(&stuff->length);
   1031     swapl(&stuff->property);
   1032     swapl(&stuff->type);
   1033     swapl(&stuff->nUnits);
   1034     return (ProcXChangeDeviceProperty(client));
   1035 }
   1036 
   1037 int _X_COLD
   1038 SProcXDeleteDeviceProperty(ClientPtr client)
   1039 {
   1040     REQUEST(xDeleteDevicePropertyReq);
   1041     REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
   1042 
   1043     swaps(&stuff->length);
   1044     swapl(&stuff->property);
   1045     return (ProcXDeleteDeviceProperty(client));
   1046 }
   1047 
   1048 int _X_COLD
   1049 SProcXGetDeviceProperty(ClientPtr client)
   1050 {
   1051     REQUEST(xGetDevicePropertyReq);
   1052     REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
   1053 
   1054     swaps(&stuff->length);
   1055     swapl(&stuff->property);
   1056     swapl(&stuff->type);
   1057     swapl(&stuff->longOffset);
   1058     swapl(&stuff->longLength);
   1059     return (ProcXGetDeviceProperty(client));
   1060 }
   1061 
   1062 /* Reply swapping */
   1063 
   1064 void _X_COLD
   1065 SRepXListDeviceProperties(ClientPtr client, int size,
   1066                           xListDevicePropertiesReply * rep)
   1067 {
   1068     swaps(&rep->sequenceNumber);
   1069     swapl(&rep->length);
   1070     swaps(&rep->nAtoms);
   1071     /* properties will be swapped later, see ProcXListDeviceProperties */
   1072     WriteToClient(client, size, rep);
   1073 }
   1074 
   1075 void _X_COLD
   1076 SRepXGetDeviceProperty(ClientPtr client, int size,
   1077                        xGetDevicePropertyReply * rep)
   1078 {
   1079     swaps(&rep->sequenceNumber);
   1080     swapl(&rep->length);
   1081     swapl(&rep->propertyType);
   1082     swapl(&rep->bytesAfter);
   1083     swapl(&rep->nItems);
   1084     /* data will be swapped, see ProcXGetDeviceProperty */
   1085     WriteToClient(client, size, rep);
   1086 }
   1087 
   1088 /* XI2 Request/reply handling */
   1089 int
   1090 ProcXIListProperties(ClientPtr client)
   1091 {
   1092     Atom *atoms;
   1093     xXIListPropertiesReply rep;
   1094     int natoms;
   1095     DeviceIntPtr dev;
   1096     int rc = Success;
   1097 
   1098     REQUEST(xXIListPropertiesReq);
   1099     REQUEST_SIZE_MATCH(xXIListPropertiesReq);
   1100 
   1101     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess);
   1102     if (rc != Success)
   1103         return rc;
   1104 
   1105     rc = list_atoms(dev, &natoms, &atoms);
   1106     if (rc != Success)
   1107         return rc;
   1108 
   1109     rep = (xXIListPropertiesReply) {
   1110         .repType = X_Reply,
   1111         .RepType = X_XIListProperties,
   1112         .sequenceNumber = client->sequence,
   1113         .length = natoms,
   1114         .num_properties = natoms
   1115     };
   1116 
   1117     WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep);
   1118     if (natoms) {
   1119         client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
   1120         WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
   1121         free(atoms);
   1122     }
   1123     return rc;
   1124 }
   1125 
   1126 int
   1127 ProcXIChangeProperty(ClientPtr client)
   1128 {
   1129     int rc;
   1130     DeviceIntPtr dev;
   1131     int totalSize;
   1132     unsigned long len;
   1133 
   1134     REQUEST(xXIChangePropertyReq);
   1135     REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
   1136     UpdateCurrentTime();
   1137 
   1138     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
   1139     if (rc != Success)
   1140         return rc;
   1141 
   1142     rc = check_change_property(client, stuff->property, stuff->type,
   1143                                stuff->format, stuff->mode, stuff->num_items);
   1144     len = stuff->num_items;
   1145     if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
   1146         return BadLength;
   1147 
   1148     totalSize = len * (stuff->format / 8);
   1149     REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize);
   1150 
   1151     rc = change_property(client, dev, stuff->property, stuff->type,
   1152                          stuff->format, stuff->mode, len, (void *) &stuff[1]);
   1153     return rc;
   1154 }
   1155 
   1156 int
   1157 ProcXIDeleteProperty(ClientPtr client)
   1158 {
   1159     DeviceIntPtr dev;
   1160     int rc;
   1161 
   1162     REQUEST(xXIDeletePropertyReq);
   1163 
   1164     REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
   1165     UpdateCurrentTime();
   1166     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
   1167     if (rc != Success)
   1168         return rc;
   1169 
   1170     if (!ValidAtom(stuff->property)) {
   1171         client->errorValue = stuff->property;
   1172         return BadAtom;
   1173     }
   1174 
   1175     rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
   1176     return rc;
   1177 }
   1178 
   1179 int
   1180 ProcXIGetProperty(ClientPtr client)
   1181 {
   1182     REQUEST(xXIGetPropertyReq);
   1183     DeviceIntPtr dev;
   1184     xXIGetPropertyReply reply;
   1185     int length;
   1186     int rc, format, nitems, bytes_after;
   1187     char *data;
   1188     Atom type;
   1189 
   1190     REQUEST_SIZE_MATCH(xXIGetPropertyReq);
   1191     if (stuff->delete)
   1192         UpdateCurrentTime();
   1193     rc = dixLookupDevice(&dev, stuff->deviceid, client,
   1194                          stuff->delete ? DixSetPropAccess : DixGetPropAccess);
   1195     if (rc != Success)
   1196         return rc;
   1197 
   1198     rc = get_property(client, dev, stuff->property, stuff->type,
   1199                       stuff->delete, stuff->offset, stuff->len,
   1200                       &bytes_after, &type, &format, &nitems, &length, &data);
   1201 
   1202     if (rc != Success)
   1203         return rc;
   1204 
   1205     reply = (xXIGetPropertyReply) {
   1206         .repType = X_Reply,
   1207         .RepType = X_XIGetProperty,
   1208         .sequenceNumber = client->sequence,
   1209         .length = bytes_to_int32(length),
   1210         .type = type,
   1211         .bytes_after = bytes_after,
   1212         .num_items = nitems,
   1213         .format = format
   1214     };
   1215 
   1216     if (length && stuff->delete && (reply.bytes_after == 0))
   1217         send_property_event(dev, stuff->property, XIPropertyDeleted);
   1218 
   1219     WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply);
   1220 
   1221     if (length) {
   1222         switch (reply.format) {
   1223         case 32:
   1224             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
   1225             break;
   1226         case 16:
   1227             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
   1228             break;
   1229         default:
   1230             client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
   1231             break;
   1232         }
   1233         WriteSwappedDataToClient(client, length, data);
   1234     }
   1235 
   1236     /* delete the Property */
   1237     if (stuff->delete && (reply.bytes_after == 0)) {
   1238         XIPropertyPtr prop, *prev;
   1239 
   1240         for (prev = &dev->properties.properties; (prop = *prev);
   1241              prev = &prop->next) {
   1242             if (prop->propertyName == stuff->property) {
   1243                 *prev = prop->next;
   1244                 XIDestroyDeviceProperty(prop);
   1245                 break;
   1246             }
   1247         }
   1248     }
   1249 
   1250     return Success;
   1251 }
   1252 
   1253 int _X_COLD
   1254 SProcXIListProperties(ClientPtr client)
   1255 {
   1256     REQUEST(xXIListPropertiesReq);
   1257     REQUEST_SIZE_MATCH(xXIListPropertiesReq);
   1258 
   1259     swaps(&stuff->length);
   1260     swaps(&stuff->deviceid);
   1261     return (ProcXIListProperties(client));
   1262 }
   1263 
   1264 int _X_COLD
   1265 SProcXIChangeProperty(ClientPtr client)
   1266 {
   1267     REQUEST(xXIChangePropertyReq);
   1268 
   1269     REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
   1270     swaps(&stuff->length);
   1271     swaps(&stuff->deviceid);
   1272     swapl(&stuff->property);
   1273     swapl(&stuff->type);
   1274     swapl(&stuff->num_items);
   1275     return (ProcXIChangeProperty(client));
   1276 }
   1277 
   1278 int _X_COLD
   1279 SProcXIDeleteProperty(ClientPtr client)
   1280 {
   1281     REQUEST(xXIDeletePropertyReq);
   1282     REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
   1283 
   1284     swaps(&stuff->length);
   1285     swaps(&stuff->deviceid);
   1286     swapl(&stuff->property);
   1287     return (ProcXIDeleteProperty(client));
   1288 }
   1289 
   1290 int _X_COLD
   1291 SProcXIGetProperty(ClientPtr client)
   1292 {
   1293     REQUEST(xXIGetPropertyReq);
   1294     REQUEST_SIZE_MATCH(xXIGetPropertyReq);
   1295 
   1296     swaps(&stuff->length);
   1297     swaps(&stuff->deviceid);
   1298     swapl(&stuff->property);
   1299     swapl(&stuff->type);
   1300     swapl(&stuff->offset);
   1301     swapl(&stuff->len);
   1302     return (ProcXIGetProperty(client));
   1303 }
   1304 
   1305 void _X_COLD
   1306 SRepXIListProperties(ClientPtr client, int size, xXIListPropertiesReply * rep)
   1307 {
   1308     swaps(&rep->sequenceNumber);
   1309     swapl(&rep->length);
   1310     swaps(&rep->num_properties);
   1311     /* properties will be swapped later, see ProcXIListProperties */
   1312     WriteToClient(client, size, rep);
   1313 }
   1314 
   1315 void _X_COLD
   1316 SRepXIGetProperty(ClientPtr client, int size, xXIGetPropertyReply * rep)
   1317 {
   1318     swaps(&rep->sequenceNumber);
   1319     swapl(&rep->length);
   1320     swapl(&rep->type);
   1321     swapl(&rep->bytes_after);
   1322     swapl(&rep->num_items);
   1323     /* data will be swapped, see ProcXIGetProperty */
   1324     WriteToClient(client, size, rep);
   1325 }