diff options
author | marha <marha@users.sourceforge.net> | 2010-05-09 21:09:18 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2010-05-09 21:09:18 +0000 |
commit | 49c7992dfc9c6b8a60baf1afbede4616e0265e7f (patch) | |
tree | da1d8cc09eab39cbb53ed5d5b8339b85e5a6510c /xorg-server/Xi/xiproperty.c | |
parent | 31c8a87d28f60894541bd54a6ad466328ccf5936 (diff) | |
download | vcxsrv-49c7992dfc9c6b8a60baf1afbede4616e0265e7f.tar.gz vcxsrv-49c7992dfc9c6b8a60baf1afbede4616e0265e7f.tar.bz2 vcxsrv-49c7992dfc9c6b8a60baf1afbede4616e0265e7f.zip |
xserver git update 9/5/2010
Diffstat (limited to 'xorg-server/Xi/xiproperty.c')
-rw-r--r-- | xorg-server/Xi/xiproperty.c | 2717 |
1 files changed, 1363 insertions, 1354 deletions
diff --git a/xorg-server/Xi/xiproperty.c b/xorg-server/Xi/xiproperty.c index be0783107..6e298b7d1 100644 --- a/xorg-server/Xi/xiproperty.c +++ b/xorg-server/Xi/xiproperty.c @@ -1,1354 +1,1363 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2008 Peter Hutterer - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WAXIANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -/* This code is a modified version of randr/rrproperty.c */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "dix.h" -#include "inputstr.h" -#include <X11/extensions/XI.h> -#include <X11/Xatom.h> -#include <X11/extensions/XIproto.h> -#include <X11/extensions/XI2proto.h> -#include "exglobals.h" -#include "exevents.h" -#include "swaprep.h" - -#include "xiproperty.h" -#include "xserver-properties.h" - -/** - * Properties used or alloced from inside the server. - */ -static struct dev_properties -{ - Atom type; - char *name; -} dev_properties[] = { - {0, XI_PROP_ENABLED}, - {0, XI_PROP_XTEST_DEVICE}, - {0, XATOM_FLOAT}, - {0, ACCEL_PROP_PROFILE_NUMBER}, - {0, ACCEL_PROP_CONSTANT_DECELERATION}, - {0, ACCEL_PROP_ADAPTIVE_DECELERATION}, - {0, ACCEL_PROP_VELOCITY_SCALING}, - {0, AXIS_LABEL_PROP}, - {0, AXIS_LABEL_PROP_REL_X}, - {0, AXIS_LABEL_PROP_REL_Y}, - {0, AXIS_LABEL_PROP_REL_Z}, - {0, AXIS_LABEL_PROP_REL_RX}, - {0, AXIS_LABEL_PROP_REL_RY}, - {0, AXIS_LABEL_PROP_REL_RZ}, - {0, AXIS_LABEL_PROP_REL_HWHEEL}, - {0, AXIS_LABEL_PROP_REL_DIAL}, - {0, AXIS_LABEL_PROP_REL_WHEEL}, - {0, AXIS_LABEL_PROP_REL_MISC}, - {0, AXIS_LABEL_PROP_ABS_X}, - {0, AXIS_LABEL_PROP_ABS_Y}, - {0, AXIS_LABEL_PROP_ABS_Z}, - {0, AXIS_LABEL_PROP_ABS_RX}, - {0, AXIS_LABEL_PROP_ABS_RY}, - {0, AXIS_LABEL_PROP_ABS_RZ}, - {0, AXIS_LABEL_PROP_ABS_THROTTLE}, - {0, AXIS_LABEL_PROP_ABS_RUDDER}, - {0, AXIS_LABEL_PROP_ABS_WHEEL}, - {0, AXIS_LABEL_PROP_ABS_GAS}, - {0, AXIS_LABEL_PROP_ABS_BRAKE}, - {0, AXIS_LABEL_PROP_ABS_HAT0X}, - {0, AXIS_LABEL_PROP_ABS_HAT0Y}, - {0, AXIS_LABEL_PROP_ABS_HAT1X}, - {0, AXIS_LABEL_PROP_ABS_HAT1Y}, - {0, AXIS_LABEL_PROP_ABS_HAT2X}, - {0, AXIS_LABEL_PROP_ABS_HAT2Y}, - {0, AXIS_LABEL_PROP_ABS_HAT3X}, - {0, AXIS_LABEL_PROP_ABS_HAT3Y}, - {0, AXIS_LABEL_PROP_ABS_PRESSURE}, - {0, AXIS_LABEL_PROP_ABS_DISTANCE}, - {0, AXIS_LABEL_PROP_ABS_TILT_X}, - {0, AXIS_LABEL_PROP_ABS_TILT_Y}, - {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH}, - {0, AXIS_LABEL_PROP_ABS_VOLUME}, - {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR}, - {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR}, - {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR}, - {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR}, - {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION}, - {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X}, - {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y}, - {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE}, - {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID}, - {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID}, - {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE}, - {0, AXIS_LABEL_PROP_ABS_MISC}, - - {0, BTN_LABEL_PROP}, - {0, BTN_LABEL_PROP_BTN_UNKNOWN}, - {0, BTN_LABEL_PROP_BTN_WHEEL_UP}, - {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN}, - {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT}, - {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT}, - {0, BTN_LABEL_PROP_BTN_0}, - {0, BTN_LABEL_PROP_BTN_1}, - {0, BTN_LABEL_PROP_BTN_2}, - {0, BTN_LABEL_PROP_BTN_3}, - {0, BTN_LABEL_PROP_BTN_4}, - {0, BTN_LABEL_PROP_BTN_5}, - {0, BTN_LABEL_PROP_BTN_6}, - {0, BTN_LABEL_PROP_BTN_7}, - {0, BTN_LABEL_PROP_BTN_8}, - {0, BTN_LABEL_PROP_BTN_9}, - - {0, BTN_LABEL_PROP_BTN_LEFT}, - {0, BTN_LABEL_PROP_BTN_RIGHT}, - {0, BTN_LABEL_PROP_BTN_MIDDLE}, - {0, BTN_LABEL_PROP_BTN_SIDE}, - {0, BTN_LABEL_PROP_BTN_EXTRA}, - {0, BTN_LABEL_PROP_BTN_FORWARD}, - {0, BTN_LABEL_PROP_BTN_BACK}, - {0, BTN_LABEL_PROP_BTN_TASK}, - - {0, BTN_LABEL_PROP_BTN_TRIGGER}, - {0, BTN_LABEL_PROP_BTN_THUMB}, - {0, BTN_LABEL_PROP_BTN_THUMB2}, - {0, BTN_LABEL_PROP_BTN_TOP}, - {0, BTN_LABEL_PROP_BTN_TOP2}, - {0, BTN_LABEL_PROP_BTN_PINKIE}, - {0, BTN_LABEL_PROP_BTN_BASE}, - {0, BTN_LABEL_PROP_BTN_BASE2}, - {0, BTN_LABEL_PROP_BTN_BASE3}, - {0, BTN_LABEL_PROP_BTN_BASE4}, - {0, BTN_LABEL_PROP_BTN_BASE5}, - {0, BTN_LABEL_PROP_BTN_BASE6}, - {0, BTN_LABEL_PROP_BTN_DEAD}, - - {0, BTN_LABEL_PROP_BTN_A}, - {0, BTN_LABEL_PROP_BTN_B}, - {0, BTN_LABEL_PROP_BTN_C}, - {0, BTN_LABEL_PROP_BTN_X}, - {0, BTN_LABEL_PROP_BTN_Y}, - {0, BTN_LABEL_PROP_BTN_Z}, - {0, BTN_LABEL_PROP_BTN_TL}, - {0, BTN_LABEL_PROP_BTN_TR}, - {0, BTN_LABEL_PROP_BTN_TL2}, - {0, BTN_LABEL_PROP_BTN_TR2}, - {0, BTN_LABEL_PROP_BTN_SELECT}, - {0, BTN_LABEL_PROP_BTN_START}, - {0, BTN_LABEL_PROP_BTN_MODE}, - {0, BTN_LABEL_PROP_BTN_THUMBL}, - {0, BTN_LABEL_PROP_BTN_THUMBR}, - - {0, BTN_LABEL_PROP_BTN_TOOL_PEN}, - {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER}, - {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH}, - {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL}, - {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH}, - {0, BTN_LABEL_PROP_BTN_TOOL_FINGER}, - {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE}, - {0, BTN_LABEL_PROP_BTN_TOOL_LENS}, - {0, BTN_LABEL_PROP_BTN_TOUCH}, - {0, BTN_LABEL_PROP_BTN_STYLUS}, - {0, BTN_LABEL_PROP_BTN_STYLUS2}, - {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP}, - {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP}, - - {0, BTN_LABEL_PROP_BTN_GEAR_DOWN}, - {0, BTN_LABEL_PROP_BTN_GEAR_UP} -}; - -static long XIPropHandlerID = 1; - -static void send_property_event(DeviceIntPtr dev, Atom property, int what) -{ - devicePropertyNotify event; - xXIPropertyEvent xi2; - int state; - - if (what == XIPropertyDeleted) - state = PropertyDelete; - else - state = PropertyNewValue; - - event.type = DevicePropertyNotify; - event.deviceid = dev->id; - event.state = state; - event.atom = property; - event.time = currentTime.milliseconds; - SendEventToAllWindows(dev, DevicePropertyNotifyMask, - (xEvent*)&event, 1); - - xi2.type = GenericEvent; - xi2.extension = IReqCode; - xi2.length = 0; - xi2.evtype = XI_PropertyEvent; - xi2.deviceid = dev->id; - xi2.time = currentTime.milliseconds; - xi2.property = property; - xi2.what = what; - SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent*)&xi2), - (xEvent*)&xi2, 1); -} - -static int list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return) -{ - XIPropertyPtr prop; - Atom *atoms = NULL; - int nprops = 0; - - for (prop = dev->properties.properties; prop; prop = prop->next) - nprops++; - if (nprops) - { - Atom *a; - - atoms = xalloc(nprops * sizeof(Atom)); - if(!atoms) - return BadAlloc; - a = atoms; - for (prop = dev->properties.properties; prop; prop = prop->next, a++) - *a = prop->propertyName; - } - - *natoms = nprops; - *atoms_return = atoms; - return Success; -} - -static int -get_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type, - BOOL delete, int offset, int length, - int *bytes_after, Atom *type_return, int *format, int *nitems, - int *length_return, char **data) -{ - unsigned long n, len, ind; - int rc; - XIPropertyPtr prop; - XIPropertyValuePtr prop_value; - - if (!ValidAtom(property)) - { - client->errorValue = property; - return(BadAtom); - } - if ((delete != xTrue) && (delete != xFalse)) - { - client->errorValue = delete; - return(BadValue); - } - - if ((type != AnyPropertyType) && !ValidAtom(type)) - { - client->errorValue = type; - return(BadAtom); - } - - for (prop = dev->properties.properties; prop; prop = prop->next) - if (prop->propertyName == property) - break; - - if (!prop) - { - *bytes_after = 0; - *type_return = None; - *format = 0; - *nitems = 0; - *length_return = 0; - return Success; - } - - rc = XIGetDeviceProperty(dev, property, &prop_value); - if (rc != Success) - { - client->errorValue = property; - return rc; - } - - /* If the request type and actual type don't match. Return the - property information, but not the data. */ - - if (((type != prop_value->type) && (type != AnyPropertyType))) - { - *bytes_after = prop_value->size; - *format = prop_value->format; - *length_return = 0; - *nitems = 0; - *type_return = prop_value->type; - return Success; - } - - /* Return type, format, value to client */ - n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */ - ind = offset << 2; - - /* If offset is invalid such that it causes "len" to - be negative, it's a value error. */ - - if (n < ind) - { - client->errorValue = offset; - return BadValue; - } - - len = min(n - ind, 4 * length); - - *bytes_after = n - (ind + len); - *format = prop_value->format; - *length_return = len; - if (prop_value->format) - *nitems = len / (prop_value->format / 8); - else - *nitems = 0; - *type_return = prop_value->type; - - *data = (char*)prop_value->data + ind; - - return Success; -} - -static int -check_change_property(ClientPtr client, Atom property, Atom type, int format, - int mode, int nitems) -{ - if ((mode != PropModeReplace) && (mode != PropModeAppend) && - (mode != PropModePrepend)) - { - client->errorValue = mode; - return BadValue; - } - if ((format != 8) && (format != 16) && (format != 32)) - { - client->errorValue = format; - return BadValue; - } - - if (!ValidAtom(property)) - { - client->errorValue = property; - return(BadAtom); - } - if (!ValidAtom(type)) - { - client->errorValue = type; - return(BadAtom); - } - - return Success; -} - -static int -change_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type, - int format, int mode, int len, void *data) -{ - int rc = Success; - - rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data, TRUE); - if (rc != Success) - client->errorValue = property; - - return rc; -} - -/** - * Return the atom assigned to the specified string or 0 if the atom isn't known - * to the DIX. - * - * If name is NULL, None is returned. - */ -Atom -XIGetKnownProperty(char *name) -{ - int i; - - if (!name) - return None; - - for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++) - { - if (strcmp(name, dev_properties[i].name) == 0){ - if (dev_properties[i].type == None){ - dev_properties[i].type = - MakeAtom(dev_properties[i].name, - strlen(dev_properties[i].name), - TRUE); - } - - return dev_properties[i].type; - } - } - - return 0; -} - -/** - * Convert the given property's value(s) into @nelem_return integer values and - * store them in @buf_return. If @nelem_return is larger than the number of - * values in the property, @nelem_return is set to the number of values in the - * property. - * - * If *@buf_return is NULL and @nelem_return is 0, memory is allocated - * automatically and must be freed by the caller. - * - * Possible return codes. - * Success ... No error. - * BadMatch ... Wrong atom type, atom is not XA_INTEGER - * BadAlloc ... NULL passed as buffer and allocation failed. - * BadLength ... @buff is NULL but @nelem_return is non-zero. - * - * @param val The property value - * @param nelem_return The maximum number of elements to return. - * @param buf_return Pointer to an array of at least @nelem_return values. - * @return Success or the error code if an error occured. - */ -_X_EXPORT int -XIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return) -{ - int i; - int *buf; - - if (val->type != XA_INTEGER) - return BadMatch; - if (!*buf_return && *nelem_return) - return BadLength; - - switch(val->format) - { - case 8: - case 16: - case 32: - break; - default: - return BadValue; - } - - buf = *buf_return; - - if (!buf && !(*nelem_return)) - { - buf = xcalloc(val->size, sizeof(int)); - if (!buf) - return BadAlloc; - *buf_return = buf; - *nelem_return = val->size; - } else if (val->size < *nelem_return) - *nelem_return = val->size; - - for (i = 0; i < val->size && i < *nelem_return; i++) - { - switch(val->format) - { - case 8: buf[i] = ((CARD8*)val->data)[i]; break; - case 16: buf[i] = ((CARD16*)val->data)[i]; break; - case 32: buf[i] = ((CARD32*)val->data)[i]; break; - } - } - - return Success; -} - -/** - * Convert the given property's value(s) into @nelem_return float values and - * store them in @buf_return. If @nelem_return is larger than the number of - * values in the property, @nelem_return is set to the number of values in the - * property. - * - * If *@buf_return is NULL and @nelem_return is 0, memory is allocated - * automatically and must be freed by the caller. - * - * Possible errors returned: - * Success - * BadMatch ... Wrong atom type, atom is not XA_FLOAT - * BadValue ... Wrong format, format is not 32 - * BadAlloc ... NULL passed as buffer and allocation failed. - * BadLength ... @buff is NULL but @nelem_return is non-zero. - * - * @param val The property value - * @param nelem_return The maximum number of elements to return. - * @param buf_return Pointer to an array of at least @nelem_return values. - * @return Success or the error code if an error occured. - */ -_X_EXPORT int -XIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return) -{ - int i; - float *buf; - - if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT)) - return BadMatch; - - if (val->format != 32) - return BadValue; - if (!*buf_return && *nelem_return) - return BadLength; - - buf = *buf_return; - - if (!buf && !(*nelem_return)) - { - buf = xcalloc(val->size, sizeof(float)); - if (!buf) - return BadAlloc; - *buf_return = buf; - *nelem_return = val->size; - } else if (val->size < *nelem_return) - *nelem_return = val->size; - - for (i = 0; i < val->size && i < *nelem_return; i++) - buf[i] = ((float*)val->data)[i]; - - return Success; -} - -/* Registers a new property handler on the given device and returns a unique - * identifier for this handler. This identifier is required to unregister the - * property handler again. - * @return The handler's identifier or 0 if an error occured. - */ -long -XIRegisterPropertyHandler(DeviceIntPtr dev, - int (*SetProperty) (DeviceIntPtr dev, - Atom property, - XIPropertyValuePtr prop, - BOOL checkonly), - int (*GetProperty) (DeviceIntPtr dev, - Atom property), - int (*DeleteProperty) (DeviceIntPtr dev, - Atom property)) -{ - XIPropertyHandlerPtr new_handler; - - new_handler = xcalloc(1, sizeof(XIPropertyHandler)); - if (!new_handler) - return 0; - - new_handler->id = XIPropHandlerID++; - new_handler->SetProperty = SetProperty; - new_handler->GetProperty = GetProperty; - new_handler->DeleteProperty = DeleteProperty; - new_handler->next = dev->properties.handlers; - dev->properties.handlers = new_handler; - - return new_handler->id; -} - -void -XIUnregisterPropertyHandler(DeviceIntPtr dev, long id) -{ - XIPropertyHandlerPtr curr, prev = NULL; - - curr = dev->properties.handlers; - while(curr && curr->id != id) - { - prev = curr; - curr = curr->next; - } - - if (!curr) - return; - - if (!prev) /* first one */ - dev->properties.handlers = curr->next; - else - prev->next = curr->next; - - xfree(curr); -} - -static XIPropertyPtr -XICreateDeviceProperty (Atom property) -{ - XIPropertyPtr prop; - - prop = (XIPropertyPtr)xalloc(sizeof(XIPropertyRec)); - if (!prop) - return NULL; - - prop->next = NULL; - prop->propertyName = property; - prop->value.type = None; - prop->value.format = 0; - prop->value.size = 0; - prop->value.data = NULL; - prop->deletable = TRUE; - - return prop; -} - -static XIPropertyPtr -XIFetchDeviceProperty(DeviceIntPtr dev, Atom property) -{ - XIPropertyPtr prop; - - for (prop = dev->properties.properties; prop; prop = prop->next) - if (prop->propertyName == property) - return prop; - return NULL; -} - -static void -XIDestroyDeviceProperty (XIPropertyPtr prop) -{ - if (prop->value.data) - xfree(prop->value.data); - xfree(prop); -} - -/* This function destroys all of the device's property-related stuff, - * including removing all device handlers. - * DO NOT CALL FROM THE DRIVER. - */ -void -XIDeleteAllDeviceProperties (DeviceIntPtr device) -{ - XIPropertyPtr prop, next; - XIPropertyHandlerPtr curr_handler, next_handler; - - for (prop = device->properties.properties; prop; prop = next) - { - next = prop->next; - send_property_event(device, prop->propertyName, XIPropertyDeleted); - XIDestroyDeviceProperty(prop); - } - - device->properties.properties = NULL; - - /* Now free all handlers */ - curr_handler = device->properties.handlers; - while(curr_handler) - { - next_handler = curr_handler->next; - xfree(curr_handler); - curr_handler = next_handler; - } - - device->properties.handlers = NULL; -} - - -int -XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient) -{ - XIPropertyPtr prop, *prev; - int rc = Success; - - for (prev = &device->properties.properties; (prop = *prev); prev = &(prop->next)) - if (prop->propertyName == property) - break; - - if (!prop) - return Success; - - if (fromClient && !prop->deletable) - return BadAccess; - - /* Ask handlers if we may delete the property */ - if (device->properties.handlers) - { - XIPropertyHandlerPtr handler = device->properties.handlers; - while(handler) - { - if (handler->DeleteProperty) - rc = handler->DeleteProperty(device, prop->propertyName); - if (rc != Success) - return (rc); - handler = handler->next; - } - } - - if (prop) - { - *prev = prop->next; - send_property_event(device, prop->propertyName, XIPropertyDeleted); - XIDestroyDeviceProperty (prop); - } - - return Success; -} - -int -XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type, - int format, int mode, unsigned long len, - pointer value, Bool sendevent) -{ - XIPropertyPtr prop; - int size_in_bytes; - int total_size; - unsigned long total_len; - XIPropertyValuePtr prop_value; - XIPropertyValueRec new_value; - Bool add = FALSE; - int rc; - - size_in_bytes = format >> 3; - - /* first see if property already exists */ - prop = XIFetchDeviceProperty (dev, property); - if (!prop) /* just add to list */ - { - prop = XICreateDeviceProperty (property); - if (!prop) - return(BadAlloc); - add = TRUE; - mode = PropModeReplace; - } - prop_value = &prop->value; - - /* To append or prepend to a property the request format and type - must match those of the already defined property. The - existing format and type are irrelevant when using the mode - "PropModeReplace" since they will be written over. */ - - if ((format != prop_value->format) && (mode != PropModeReplace)) - return(BadMatch); - if ((prop_value->type != type) && (mode != PropModeReplace)) - return(BadMatch); - new_value = *prop_value; - if (mode == PropModeReplace) - total_len = len; - else - total_len = prop_value->size + len; - - if (mode == PropModeReplace || len > 0) - { - pointer new_data = NULL, old_data = NULL; - - total_size = total_len * size_in_bytes; - new_value.data = (pointer)xalloc (total_size); - if (!new_value.data && total_size) - { - if (add) - XIDestroyDeviceProperty (prop); - return BadAlloc; - } - new_value.size = len; - new_value.type = type; - new_value.format = format; - - switch (mode) { - case PropModeReplace: - new_data = new_value.data; - old_data = NULL; - break; - case PropModeAppend: - new_data = (pointer) (((char *) new_value.data) + - (prop_value->size * size_in_bytes)); - old_data = new_value.data; - break; - case PropModePrepend: - new_data = new_value.data; - old_data = (pointer) (((char *) new_value.data) + - (prop_value->size * size_in_bytes)); - break; - } - if (new_data) - memcpy ((char *) new_data, (char *) value, len * size_in_bytes); - if (old_data) - memcpy ((char *) old_data, (char *) prop_value->data, - prop_value->size * size_in_bytes); - - if (dev->properties.handlers) - { - XIPropertyHandlerPtr handler; - BOOL checkonly = TRUE; - /* run through all handlers with checkonly TRUE, then again with - * checkonly FALSE. Handlers MUST return error codes on the - * checkonly run, errors on the second run are ignored */ - do - { - handler = dev->properties.handlers; - while(handler) - { - if (handler->SetProperty) - { - rc = handler->SetProperty(dev, prop->propertyName, - &new_value, checkonly); - if (checkonly && rc != Success) - { - if (new_value.data) - xfree (new_value.data); - return (rc); - } - } - handler = handler->next; - } - checkonly = !checkonly; - } while (!checkonly); - } - if (prop_value->data) - xfree (prop_value->data); - *prop_value = new_value; - } else if (len == 0) - { - /* do nothing */ - } - - if (add) - { - prop->next = dev->properties.properties; - dev->properties.properties = prop; - } - - if (sendevent) - send_property_event(dev, prop->propertyName, - (add) ? XIPropertyCreated : XIPropertyModified); - - return(Success); -} - -int -XIGetDeviceProperty (DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value) -{ - XIPropertyPtr prop = XIFetchDeviceProperty (dev, property); - int rc; - - if (!prop) - { - *value = NULL; - return BadAtom; - } - - /* If we can, try to update the property value first */ - if (dev->properties.handlers) - { - XIPropertyHandlerPtr handler = dev->properties.handlers; - while(handler) - { - if (handler->GetProperty) - { - rc = handler->GetProperty(dev, prop->propertyName); - if (rc != Success) - { - *value = NULL; - return rc; - } - } - handler = handler->next; - } - } - - *value = &prop->value; - return Success; -} - -int -XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable) -{ - XIPropertyPtr prop = XIFetchDeviceProperty(dev, property); - - if (!prop) - return BadAtom; - - prop->deletable = deletable; - return Success; -} - -int -ProcXListDeviceProperties (ClientPtr client) -{ - Atom *atoms; - xListDevicePropertiesReply rep; - int natoms; - DeviceIntPtr dev; - int rc = Success; - - REQUEST(xListDevicePropertiesReq); - REQUEST_SIZE_MATCH(xListDevicePropertiesReq); - - rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess); - if (rc != Success) - return rc; - - rc = list_atoms(dev, &natoms, &atoms); - if (rc != Success) - return rc; - - rep.repType = X_Reply; - rep.RepType = X_ListDeviceProperties; - rep.length = natoms; - rep.sequenceNumber = client->sequence; - rep.nAtoms = natoms; - - WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep); - if (natoms) - { - client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; - WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms); - xfree(atoms); - } - return rc; -} - -int -ProcXChangeDeviceProperty (ClientPtr client) -{ - REQUEST(xChangeDevicePropertyReq); - DeviceIntPtr dev; - unsigned long len; - int totalSize; - int rc; - - REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq); - UpdateCurrentTime(); - - rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess); - if (rc != Success) - return rc; - - rc = check_change_property(client, stuff->property, stuff->type, - stuff->format, stuff->mode, stuff->nUnits); - - len = stuff->nUnits; - if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq)))) - return BadLength; - - totalSize = len * (stuff->format/8); - REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize); - - rc = change_property(client, dev, stuff->property, stuff->type, - stuff->format, stuff->mode, len, (void*)&stuff[1]); - return rc; -} - -int -ProcXDeleteDeviceProperty (ClientPtr client) -{ - REQUEST(xDeleteDevicePropertyReq); - DeviceIntPtr dev; - int rc; - - REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); - UpdateCurrentTime(); - rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess); - if (rc != Success) - return rc; - - if (!ValidAtom(stuff->property)) - { - client->errorValue = stuff->property; - return (BadAtom); - } - - rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE); - return rc; -} - -int -ProcXGetDeviceProperty (ClientPtr client) -{ - REQUEST(xGetDevicePropertyReq); - DeviceIntPtr dev; - int length; - int rc, format, nitems, bytes_after; - char *data; - Atom type; - xGetDevicePropertyReply reply; - - REQUEST_SIZE_MATCH(xGetDevicePropertyReq); - if (stuff->delete) - UpdateCurrentTime(); - rc = dixLookupDevice (&dev, stuff->deviceid, client, - stuff->delete ? DixSetPropAccess : - DixGetPropAccess); - if (rc != Success) - return rc; - - rc = get_property(client, dev, stuff->property, stuff->type, - stuff->delete, stuff->longOffset, stuff->longLength, - &bytes_after, &type, &format, &nitems, &length, &data); - - if (rc != Success) - return rc; - - reply.repType = X_Reply; - reply.RepType = X_GetDeviceProperty; - reply.sequenceNumber = client->sequence; - reply.deviceid = dev->id; - reply.nItems = nitems; - reply.format = format; - reply.bytesAfter = bytes_after; - reply.propertyType = type; - reply.length = bytes_to_int32(length); - - if (stuff->delete && (reply.bytesAfter == 0)) - send_property_event(dev, stuff->property, XIPropertyDeleted); - - WriteReplyToClient(client, sizeof(xGenericReply), &reply); - - if (length) - { - switch (reply.format) { - case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; - case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; - default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; - } - WriteSwappedDataToClient(client, length, data); - } - - /* delete the Property */ - if (stuff->delete && (reply.bytesAfter == 0)) - { - XIPropertyPtr prop, *prev; - for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next) - { - if (prop->propertyName == stuff->property) - { - *prev = prop->next; - XIDestroyDeviceProperty(prop); - break; - } - } - } - return Success; -} - - -int -SProcXListDeviceProperties (ClientPtr client) -{ - char n; - REQUEST(xListDevicePropertiesReq); - - swaps(&stuff->length, n); - - REQUEST_SIZE_MATCH(xListDevicePropertiesReq); - return (ProcXListDeviceProperties(client)); -} - -int -SProcXChangeDeviceProperty (ClientPtr client) -{ - char n; - REQUEST(xChangeDevicePropertyReq); - - swaps(&stuff->length, n); - swapl(&stuff->property, n); - swapl(&stuff->type, n); - swapl(&stuff->nUnits, n); - REQUEST_SIZE_MATCH(xChangeDevicePropertyReq); - return (ProcXChangeDeviceProperty(client)); -} - -int -SProcXDeleteDeviceProperty (ClientPtr client) -{ - char n; - REQUEST(xDeleteDevicePropertyReq); - - swaps(&stuff->length, n); - swapl(&stuff->property, n); - REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); - return (ProcXDeleteDeviceProperty(client)); -} - -int -SProcXGetDeviceProperty (ClientPtr client) -{ - char n; - REQUEST(xGetDevicePropertyReq); - - swaps(&stuff->length, n); - swapl(&stuff->property, n); - swapl(&stuff->type, n); - swapl(&stuff->longOffset, n); - swapl(&stuff->longLength, n); - REQUEST_SIZE_MATCH(xGetDevicePropertyReq); - return (ProcXGetDeviceProperty(client)); -} - - -/* Reply swapping */ - -void -SRepXListDeviceProperties(ClientPtr client, int size, - xListDevicePropertiesReply *rep) -{ - char n; - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swaps(&rep->nAtoms, n); - /* properties will be swapped later, see ProcXListDeviceProperties */ - WriteToClient(client, size, (char*)rep); -} - -void -SRepXGetDeviceProperty(ClientPtr client, int size, - xGetDevicePropertyReply *rep) -{ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swapl(&rep->propertyType, n); - swapl(&rep->bytesAfter, n); - swapl(&rep->nItems, n); - /* data will be swapped, see ProcXGetDeviceProperty */ - WriteToClient(client, size, (char*)rep); -} - -/* XI2 Request/reply handling */ -int -ProcXIListProperties(ClientPtr client) -{ - Atom *atoms; - xXIListPropertiesReply rep; - int natoms; - DeviceIntPtr dev; - int rc = Success; - - REQUEST(xXIListPropertiesReq); - REQUEST_SIZE_MATCH(xXIListPropertiesReq); - - rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess); - if (rc != Success) - return rc; - - rc = list_atoms(dev, &natoms, &atoms); - if (rc != Success) - return rc; - - rep.repType = X_Reply; - rep.RepType = X_XIListProperties; - rep.length = natoms; - rep.sequenceNumber = client->sequence; - rep.num_properties = natoms; - - WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep); - if (natoms) - { - client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; - WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms); - xfree(atoms); - } - return rc; -} - -int -ProcXIChangeProperty(ClientPtr client) -{ - int rc; - DeviceIntPtr dev; - int totalSize; - unsigned long len; - - REQUEST(xXIChangePropertyReq); - REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq); - UpdateCurrentTime(); - - rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess); - if (rc != Success) - return rc; - - rc = check_change_property(client, stuff->property, stuff->type, - stuff->format, stuff->mode, stuff->num_items); - len = stuff->num_items; - if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq))) - return BadLength; - - totalSize = len * (stuff->format/8); - REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize); - - rc = change_property(client, dev, stuff->property, stuff->type, - stuff->format, stuff->mode, len, (void*)&stuff[1]); - return rc; -} - -int -ProcXIDeleteProperty(ClientPtr client) -{ - DeviceIntPtr dev; - int rc; - REQUEST(xXIDeletePropertyReq); - - REQUEST_SIZE_MATCH(xXIDeletePropertyReq); - UpdateCurrentTime(); - rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess); - if (rc != Success) - return rc; - - if (!ValidAtom(stuff->property)) - { - client->errorValue = stuff->property; - return (BadAtom); - } - - rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE); - return rc; -} - - -int -ProcXIGetProperty(ClientPtr client) -{ - REQUEST(xXIGetPropertyReq); - DeviceIntPtr dev; - xXIGetPropertyReply reply; - int length; - int rc, format, nitems, bytes_after; - char *data; - Atom type; - - REQUEST_SIZE_MATCH(xXIGetPropertyReq); - if (stuff->delete) - UpdateCurrentTime(); - rc = dixLookupDevice (&dev, stuff->deviceid, client, - stuff->delete ? DixSetPropAccess : - DixGetPropAccess); - if (rc != Success) - return rc; - - rc = get_property(client, dev, stuff->property, stuff->type, - stuff->delete, stuff->offset, stuff->len, - &bytes_after, &type, &format, &nitems, &length, &data); - - if (rc != Success) - return rc; - - reply.repType = X_Reply; - reply.RepType = X_XIGetProperty; - reply.sequenceNumber = client->sequence; - reply.num_items = nitems; - reply.format = format; - reply.bytes_after = bytes_after; - reply.type = type; - reply.length = bytes_to_int32(length); - - if (length && stuff->delete && (reply.bytes_after == 0)) - send_property_event(dev, stuff->property, XIPropertyDeleted); - - WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply); - - if (length) - { - switch (reply.format) { - case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; - case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; - default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; - } - WriteSwappedDataToClient(client, length, data); - } - - /* delete the Property */ - if (stuff->delete && (reply.bytes_after == 0)) - { - XIPropertyPtr prop, *prev; - for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next) - { - if (prop->propertyName == stuff->property) - { - *prev = prop->next; - XIDestroyDeviceProperty(prop); - break; - } - } - } - - return Success; -} - -int -SProcXIListProperties(ClientPtr client) -{ - char n; - REQUEST(xXIListPropertiesReq); - - swaps(&stuff->length, n); - swaps(&stuff->deviceid, n); - - REQUEST_SIZE_MATCH(xXIListPropertiesReq); - return (ProcXIListProperties(client)); -} - -int -SProcXIChangeProperty(ClientPtr client) -{ - char n; - REQUEST(xXIChangePropertyReq); - - swaps(&stuff->length, n); - swaps(&stuff->deviceid, n); - swapl(&stuff->property, n); - swapl(&stuff->type, n); - swapl(&stuff->num_items, n); - REQUEST_SIZE_MATCH(xXIChangePropertyReq); - return (ProcXIChangeProperty(client)); -} - -int -SProcXIDeleteProperty(ClientPtr client) -{ - char n; - REQUEST(xXIDeletePropertyReq); - - swaps(&stuff->length, n); - swaps(&stuff->deviceid, n); - swapl(&stuff->property, n); - REQUEST_SIZE_MATCH(xXIDeletePropertyReq); - return (ProcXIDeleteProperty(client)); -} - -int -SProcXIGetProperty(ClientPtr client) -{ - char n; - REQUEST(xXIGetPropertyReq); - - swaps(&stuff->length, n); - swaps(&stuff->deviceid, n); - swapl(&stuff->property, n); - swapl(&stuff->type, n); - swapl(&stuff->offset, n); - swapl(&stuff->len, n); - REQUEST_SIZE_MATCH(xXIGetPropertyReq); - return (ProcXIGetProperty(client)); -} - - -void -SRepXIListProperties(ClientPtr client, int size, - xXIListPropertiesReply *rep) -{ - char n; - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swaps(&rep->num_properties, n); - /* properties will be swapped later, see ProcXIListProperties */ - WriteToClient(client, size, (char*)rep); -} - -void -SRepXIGetProperty(ClientPtr client, int size, - xXIGetPropertyReply *rep) -{ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swapl(&rep->type, n); - swapl(&rep->bytes_after, n); - swapl(&rep->num_items, n); - /* data will be swapped, see ProcXIGetProperty */ - WriteToClient(client, size, (char*)rep); -} +/*
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WAXIANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/* This code is a modified version of randr/rrproperty.c */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "dix.h"
+#include "inputstr.h"
+#include <X11/extensions/XI.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI2proto.h>
+#include "exglobals.h"
+#include "exevents.h"
+#include "swaprep.h"
+
+#include "xiproperty.h"
+#include "xserver-properties.h"
+
+/**
+ * Properties used or alloced from inside the server.
+ */
+static struct dev_properties
+{
+ Atom type;
+ char *name;
+} dev_properties[] = {
+ {0, XI_PROP_ENABLED},
+ {0, XI_PROP_XTEST_DEVICE},
+ {0, XATOM_FLOAT},
+ {0, ACCEL_PROP_PROFILE_NUMBER},
+ {0, ACCEL_PROP_CONSTANT_DECELERATION},
+ {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
+ {0, ACCEL_PROP_VELOCITY_SCALING},
+ {0, AXIS_LABEL_PROP},
+ {0, AXIS_LABEL_PROP_REL_X},
+ {0, AXIS_LABEL_PROP_REL_Y},
+ {0, AXIS_LABEL_PROP_REL_Z},
+ {0, AXIS_LABEL_PROP_REL_RX},
+ {0, AXIS_LABEL_PROP_REL_RY},
+ {0, AXIS_LABEL_PROP_REL_RZ},
+ {0, AXIS_LABEL_PROP_REL_HWHEEL},
+ {0, AXIS_LABEL_PROP_REL_DIAL},
+ {0, AXIS_LABEL_PROP_REL_WHEEL},
+ {0, AXIS_LABEL_PROP_REL_MISC},
+ {0, AXIS_LABEL_PROP_ABS_X},
+ {0, AXIS_LABEL_PROP_ABS_Y},
+ {0, AXIS_LABEL_PROP_ABS_Z},
+ {0, AXIS_LABEL_PROP_ABS_RX},
+ {0, AXIS_LABEL_PROP_ABS_RY},
+ {0, AXIS_LABEL_PROP_ABS_RZ},
+ {0, AXIS_LABEL_PROP_ABS_THROTTLE},
+ {0, AXIS_LABEL_PROP_ABS_RUDDER},
+ {0, AXIS_LABEL_PROP_ABS_WHEEL},
+ {0, AXIS_LABEL_PROP_ABS_GAS},
+ {0, AXIS_LABEL_PROP_ABS_BRAKE},
+ {0, AXIS_LABEL_PROP_ABS_HAT0X},
+ {0, AXIS_LABEL_PROP_ABS_HAT0Y},
+ {0, AXIS_LABEL_PROP_ABS_HAT1X},
+ {0, AXIS_LABEL_PROP_ABS_HAT1Y},
+ {0, AXIS_LABEL_PROP_ABS_HAT2X},
+ {0, AXIS_LABEL_PROP_ABS_HAT2Y},
+ {0, AXIS_LABEL_PROP_ABS_HAT3X},
+ {0, AXIS_LABEL_PROP_ABS_HAT3Y},
+ {0, AXIS_LABEL_PROP_ABS_PRESSURE},
+ {0, AXIS_LABEL_PROP_ABS_DISTANCE},
+ {0, AXIS_LABEL_PROP_ABS_TILT_X},
+ {0, AXIS_LABEL_PROP_ABS_TILT_Y},
+ {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH},
+ {0, AXIS_LABEL_PROP_ABS_VOLUME},
+ {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR},
+ {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR},
+ {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR},
+ {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR},
+ {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION},
+ {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X},
+ {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y},
+ {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE},
+ {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID},
+ {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID},
+ {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE},
+ {0, AXIS_LABEL_PROP_ABS_MISC},
+
+ {0, BTN_LABEL_PROP},
+ {0, BTN_LABEL_PROP_BTN_UNKNOWN},
+ {0, BTN_LABEL_PROP_BTN_WHEEL_UP},
+ {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN},
+ {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT},
+ {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT},
+ {0, BTN_LABEL_PROP_BTN_0},
+ {0, BTN_LABEL_PROP_BTN_1},
+ {0, BTN_LABEL_PROP_BTN_2},
+ {0, BTN_LABEL_PROP_BTN_3},
+ {0, BTN_LABEL_PROP_BTN_4},
+ {0, BTN_LABEL_PROP_BTN_5},
+ {0, BTN_LABEL_PROP_BTN_6},
+ {0, BTN_LABEL_PROP_BTN_7},
+ {0, BTN_LABEL_PROP_BTN_8},
+ {0, BTN_LABEL_PROP_BTN_9},
+
+ {0, BTN_LABEL_PROP_BTN_LEFT},
+ {0, BTN_LABEL_PROP_BTN_RIGHT},
+ {0, BTN_LABEL_PROP_BTN_MIDDLE},
+ {0, BTN_LABEL_PROP_BTN_SIDE},
+ {0, BTN_LABEL_PROP_BTN_EXTRA},
+ {0, BTN_LABEL_PROP_BTN_FORWARD},
+ {0, BTN_LABEL_PROP_BTN_BACK},
+ {0, BTN_LABEL_PROP_BTN_TASK},
+
+ {0, BTN_LABEL_PROP_BTN_TRIGGER},
+ {0, BTN_LABEL_PROP_BTN_THUMB},
+ {0, BTN_LABEL_PROP_BTN_THUMB2},
+ {0, BTN_LABEL_PROP_BTN_TOP},
+ {0, BTN_LABEL_PROP_BTN_TOP2},
+ {0, BTN_LABEL_PROP_BTN_PINKIE},
+ {0, BTN_LABEL_PROP_BTN_BASE},
+ {0, BTN_LABEL_PROP_BTN_BASE2},
+ {0, BTN_LABEL_PROP_BTN_BASE3},
+ {0, BTN_LABEL_PROP_BTN_BASE4},
+ {0, BTN_LABEL_PROP_BTN_BASE5},
+ {0, BTN_LABEL_PROP_BTN_BASE6},
+ {0, BTN_LABEL_PROP_BTN_DEAD},
+
+ {0, BTN_LABEL_PROP_BTN_A},
+ {0, BTN_LABEL_PROP_BTN_B},
+ {0, BTN_LABEL_PROP_BTN_C},
+ {0, BTN_LABEL_PROP_BTN_X},
+ {0, BTN_LABEL_PROP_BTN_Y},
+ {0, BTN_LABEL_PROP_BTN_Z},
+ {0, BTN_LABEL_PROP_BTN_TL},
+ {0, BTN_LABEL_PROP_BTN_TR},
+ {0, BTN_LABEL_PROP_BTN_TL2},
+ {0, BTN_LABEL_PROP_BTN_TR2},
+ {0, BTN_LABEL_PROP_BTN_SELECT},
+ {0, BTN_LABEL_PROP_BTN_START},
+ {0, BTN_LABEL_PROP_BTN_MODE},
+ {0, BTN_LABEL_PROP_BTN_THUMBL},
+ {0, BTN_LABEL_PROP_BTN_THUMBR},
+
+ {0, BTN_LABEL_PROP_BTN_TOOL_PEN},
+ {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
+ {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
+ {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
+ {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
+ {0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
+ {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
+ {0, BTN_LABEL_PROP_BTN_TOOL_LENS},
+ {0, BTN_LABEL_PROP_BTN_TOUCH},
+ {0, BTN_LABEL_PROP_BTN_STYLUS},
+ {0, BTN_LABEL_PROP_BTN_STYLUS2},
+ {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
+ {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
+
+ {0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
+ {0, BTN_LABEL_PROP_BTN_GEAR_UP}
+};
+
+static long XIPropHandlerID = 1;
+
+static void send_property_event(DeviceIntPtr dev, Atom property, int what)
+{
+ devicePropertyNotify event;
+ xXIPropertyEvent xi2;
+ int state;
+
+ if (what == XIPropertyDeleted)
+ state = PropertyDelete;
+ else
+ state = PropertyNewValue;
+
+ event.type = DevicePropertyNotify;
+ event.deviceid = dev->id;
+ event.state = state;
+ event.atom = property;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(dev, DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+
+ xi2.type = GenericEvent;
+ xi2.extension = IReqCode;
+ xi2.length = 0;
+ xi2.evtype = XI_PropertyEvent;
+ xi2.deviceid = dev->id;
+ xi2.time = currentTime.milliseconds;
+ xi2.property = property;
+ xi2.what = what;
+ SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent*)&xi2),
+ (xEvent*)&xi2, 1);
+}
+
+static int list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
+{
+ XIPropertyPtr prop;
+ Atom *atoms = NULL;
+ int nprops = 0;
+
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ nprops++;
+ if (nprops)
+ {
+ Atom *a;
+
+ atoms = xalloc(nprops * sizeof(Atom));
+ if(!atoms)
+ return BadAlloc;
+ a = atoms;
+ for (prop = dev->properties.properties; prop; prop = prop->next, a++)
+ *a = prop->propertyName;
+ }
+
+ *natoms = nprops;
+ *atoms_return = atoms;
+ return Success;
+}
+
+static int
+get_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
+ BOOL delete, int offset, int length,
+ int *bytes_after, Atom *type_return, int *format, int *nitems,
+ int *length_return, char **data)
+{
+ unsigned long n, len, ind;
+ int rc;
+ XIPropertyPtr prop;
+ XIPropertyValuePtr prop_value;
+
+ if (!ValidAtom(property))
+ {
+ client->errorValue = property;
+ return(BadAtom);
+ }
+ if ((delete != xTrue) && (delete != xFalse))
+ {
+ client->errorValue = delete;
+ return(BadValue);
+ }
+
+ if ((type != AnyPropertyType) && !ValidAtom(type))
+ {
+ client->errorValue = type;
+ return(BadAtom);
+ }
+
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ if (prop->propertyName == property)
+ break;
+
+ if (!prop)
+ {
+ *bytes_after = 0;
+ *type_return = None;
+ *format = 0;
+ *nitems = 0;
+ *length_return = 0;
+ return Success;
+ }
+
+ rc = XIGetDeviceProperty(dev, property, &prop_value);
+ if (rc != Success)
+ {
+ client->errorValue = property;
+ return rc;
+ }
+
+ /* If the request type and actual type don't match. Return the
+ property information, but not the data. */
+
+ if (((type != prop_value->type) && (type != AnyPropertyType)))
+ {
+ *bytes_after = prop_value->size;
+ *format = prop_value->format;
+ *length_return = 0;
+ *nitems = 0;
+ *type_return = prop_value->type;
+ return Success;
+ }
+
+ /* Return type, format, value to client */
+ n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */
+ ind = offset << 2;
+
+ /* If offset is invalid such that it causes "len" to
+ be negative, it's a value error. */
+
+ if (n < ind)
+ {
+ client->errorValue = offset;
+ return BadValue;
+ }
+
+ len = min(n - ind, 4 * length);
+
+ *bytes_after = n - (ind + len);
+ *format = prop_value->format;
+ *length_return = len;
+ if (prop_value->format)
+ *nitems = len / (prop_value->format / 8);
+ else
+ *nitems = 0;
+ *type_return = prop_value->type;
+
+ *data = (char*)prop_value->data + ind;
+
+ return Success;
+}
+
+static int
+check_change_property(ClientPtr client, Atom property, Atom type, int format,
+ int mode, int nitems)
+{
+ if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
+ (mode != PropModePrepend))
+ {
+ client->errorValue = mode;
+ return BadValue;
+ }
+ if ((format != 8) && (format != 16) && (format != 32))
+ {
+ client->errorValue = format;
+ return BadValue;
+ }
+
+ if (!ValidAtom(property))
+ {
+ client->errorValue = property;
+ return(BadAtom);
+ }
+ if (!ValidAtom(type))
+ {
+ client->errorValue = type;
+ return(BadAtom);
+ }
+
+ return Success;
+}
+
+static int
+change_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
+ int format, int mode, int len, void *data)
+{
+ int rc = Success;
+
+ rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data, TRUE);
+ if (rc != Success)
+ client->errorValue = property;
+
+ return rc;
+}
+
+/**
+ * Return the atom assigned to the specified string or 0 if the atom isn't known
+ * to the DIX.
+ *
+ * If name is NULL, None is returned.
+ */
+Atom
+XIGetKnownProperty(char *name)
+{
+ int i;
+
+ if (!name)
+ return None;
+
+ for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
+ {
+ if (strcmp(name, dev_properties[i].name) == 0){
+ if (dev_properties[i].type == None){
+ dev_properties[i].type =
+ MakeAtom(dev_properties[i].name,
+ strlen(dev_properties[i].name),
+ TRUE);
+ }
+
+ return dev_properties[i].type;
+ }
+ }
+
+ return 0;
+}
+
+void
+XIResetProperties(void)
+{
+ int i;
+
+ for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
+ dev_properties[i].type = None;
+}
+
+/**
+ * Convert the given property's value(s) into @nelem_return integer values and
+ * store them in @buf_return. If @nelem_return is larger than the number of
+ * values in the property, @nelem_return is set to the number of values in the
+ * property.
+ *
+ * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
+ * automatically and must be freed by the caller.
+ *
+ * Possible return codes.
+ * Success ... No error.
+ * BadMatch ... Wrong atom type, atom is not XA_INTEGER
+ * BadAlloc ... NULL passed as buffer and allocation failed.
+ * BadLength ... @buff is NULL but @nelem_return is non-zero.
+ *
+ * @param val The property value
+ * @param nelem_return The maximum number of elements to return.
+ * @param buf_return Pointer to an array of at least @nelem_return values.
+ * @return Success or the error code if an error occured.
+ */
+_X_EXPORT int
+XIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
+{
+ int i;
+ int *buf;
+
+ if (val->type != XA_INTEGER)
+ return BadMatch;
+ if (!*buf_return && *nelem_return)
+ return BadLength;
+
+ switch(val->format)
+ {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return BadValue;
+ }
+
+ buf = *buf_return;
+
+ if (!buf && !(*nelem_return))
+ {
+ buf = xcalloc(val->size, sizeof(int));
+ if (!buf)
+ return BadAlloc;
+ *buf_return = buf;
+ *nelem_return = val->size;
+ } else if (val->size < *nelem_return)
+ *nelem_return = val->size;
+
+ for (i = 0; i < val->size && i < *nelem_return; i++)
+ {
+ switch(val->format)
+ {
+ case 8: buf[i] = ((CARD8*)val->data)[i]; break;
+ case 16: buf[i] = ((CARD16*)val->data)[i]; break;
+ case 32: buf[i] = ((CARD32*)val->data)[i]; break;
+ }
+ }
+
+ return Success;
+}
+
+/**
+ * Convert the given property's value(s) into @nelem_return float values and
+ * store them in @buf_return. If @nelem_return is larger than the number of
+ * values in the property, @nelem_return is set to the number of values in the
+ * property.
+ *
+ * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
+ * automatically and must be freed by the caller.
+ *
+ * Possible errors returned:
+ * Success
+ * BadMatch ... Wrong atom type, atom is not XA_FLOAT
+ * BadValue ... Wrong format, format is not 32
+ * BadAlloc ... NULL passed as buffer and allocation failed.
+ * BadLength ... @buff is NULL but @nelem_return is non-zero.
+ *
+ * @param val The property value
+ * @param nelem_return The maximum number of elements to return.
+ * @param buf_return Pointer to an array of at least @nelem_return values.
+ * @return Success or the error code if an error occured.
+ */
+_X_EXPORT int
+XIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
+{
+ int i;
+ float *buf;
+
+ if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
+ return BadMatch;
+
+ if (val->format != 32)
+ return BadValue;
+ if (!*buf_return && *nelem_return)
+ return BadLength;
+
+ buf = *buf_return;
+
+ if (!buf && !(*nelem_return))
+ {
+ buf = xcalloc(val->size, sizeof(float));
+ if (!buf)
+ return BadAlloc;
+ *buf_return = buf;
+ *nelem_return = val->size;
+ } else if (val->size < *nelem_return)
+ *nelem_return = val->size;
+
+ for (i = 0; i < val->size && i < *nelem_return; i++)
+ buf[i] = ((float*)val->data)[i];
+
+ return Success;
+}
+
+/* Registers a new property handler on the given device and returns a unique
+ * identifier for this handler. This identifier is required to unregister the
+ * property handler again.
+ * @return The handler's identifier or 0 if an error occured.
+ */
+long
+XIRegisterPropertyHandler(DeviceIntPtr dev,
+ int (*SetProperty) (DeviceIntPtr dev,
+ Atom property,
+ XIPropertyValuePtr prop,
+ BOOL checkonly),
+ int (*GetProperty) (DeviceIntPtr dev,
+ Atom property),
+ int (*DeleteProperty) (DeviceIntPtr dev,
+ Atom property))
+{
+ XIPropertyHandlerPtr new_handler;
+
+ new_handler = xcalloc(1, sizeof(XIPropertyHandler));
+ if (!new_handler)
+ return 0;
+
+ new_handler->id = XIPropHandlerID++;
+ new_handler->SetProperty = SetProperty;
+ new_handler->GetProperty = GetProperty;
+ new_handler->DeleteProperty = DeleteProperty;
+ new_handler->next = dev->properties.handlers;
+ dev->properties.handlers = new_handler;
+
+ return new_handler->id;
+}
+
+void
+XIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
+{
+ XIPropertyHandlerPtr curr, prev = NULL;
+
+ curr = dev->properties.handlers;
+ while(curr && curr->id != id)
+ {
+ prev = curr;
+ curr = curr->next;
+ }
+
+ if (!curr)
+ return;
+
+ if (!prev) /* first one */
+ dev->properties.handlers = curr->next;
+ else
+ prev->next = curr->next;
+
+ xfree(curr);
+}
+
+static XIPropertyPtr
+XICreateDeviceProperty (Atom property)
+{
+ XIPropertyPtr prop;
+
+ prop = (XIPropertyPtr)xalloc(sizeof(XIPropertyRec));
+ if (!prop)
+ return NULL;
+
+ prop->next = NULL;
+ prop->propertyName = property;
+ prop->value.type = None;
+ prop->value.format = 0;
+ prop->value.size = 0;
+ prop->value.data = NULL;
+ prop->deletable = TRUE;
+
+ return prop;
+}
+
+static XIPropertyPtr
+XIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
+{
+ XIPropertyPtr prop;
+
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ if (prop->propertyName == property)
+ return prop;
+ return NULL;
+}
+
+static void
+XIDestroyDeviceProperty (XIPropertyPtr prop)
+{
+ if (prop->value.data)
+ xfree(prop->value.data);
+ xfree(prop);
+}
+
+/* This function destroys all of the device's property-related stuff,
+ * including removing all device handlers.
+ * DO NOT CALL FROM THE DRIVER.
+ */
+void
+XIDeleteAllDeviceProperties (DeviceIntPtr device)
+{
+ XIPropertyPtr prop, next;
+ XIPropertyHandlerPtr curr_handler, next_handler;
+
+ for (prop = device->properties.properties; prop; prop = next)
+ {
+ next = prop->next;
+ send_property_event(device, prop->propertyName, XIPropertyDeleted);
+ XIDestroyDeviceProperty(prop);
+ }
+
+ device->properties.properties = NULL;
+
+ /* Now free all handlers */
+ curr_handler = device->properties.handlers;
+ while(curr_handler)
+ {
+ next_handler = curr_handler->next;
+ xfree(curr_handler);
+ curr_handler = next_handler;
+ }
+
+ device->properties.handlers = NULL;
+}
+
+
+int
+XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient)
+{
+ XIPropertyPtr prop, *prev;
+ int rc = Success;
+
+ for (prev = &device->properties.properties; (prop = *prev); prev = &(prop->next))
+ if (prop->propertyName == property)
+ break;
+
+ if (!prop)
+ return Success;
+
+ if (fromClient && !prop->deletable)
+ return BadAccess;
+
+ /* Ask handlers if we may delete the property */
+ if (device->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler = device->properties.handlers;
+ while(handler)
+ {
+ if (handler->DeleteProperty)
+ rc = handler->DeleteProperty(device, prop->propertyName);
+ if (rc != Success)
+ return (rc);
+ handler = handler->next;
+ }
+ }
+
+ if (prop)
+ {
+ *prev = prop->next;
+ send_property_event(device, prop->propertyName, XIPropertyDeleted);
+ XIDestroyDeviceProperty (prop);
+ }
+
+ return Success;
+}
+
+int
+XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type,
+ int format, int mode, unsigned long len,
+ pointer value, Bool sendevent)
+{
+ XIPropertyPtr prop;
+ int size_in_bytes;
+ int total_size;
+ unsigned long total_len;
+ XIPropertyValuePtr prop_value;
+ XIPropertyValueRec new_value;
+ Bool add = FALSE;
+ int rc;
+
+ size_in_bytes = format >> 3;
+
+ /* first see if property already exists */
+ prop = XIFetchDeviceProperty (dev, property);
+ if (!prop) /* just add to list */
+ {
+ prop = XICreateDeviceProperty (property);
+ if (!prop)
+ return(BadAlloc);
+ add = TRUE;
+ mode = PropModeReplace;
+ }
+ prop_value = &prop->value;
+
+ /* To append or prepend to a property the request format and type
+ must match those of the already defined property. The
+ existing format and type are irrelevant when using the mode
+ "PropModeReplace" since they will be written over. */
+
+ if ((format != prop_value->format) && (mode != PropModeReplace))
+ return(BadMatch);
+ if ((prop_value->type != type) && (mode != PropModeReplace))
+ return(BadMatch);
+ new_value = *prop_value;
+ if (mode == PropModeReplace)
+ total_len = len;
+ else
+ total_len = prop_value->size + len;
+
+ if (mode == PropModeReplace || len > 0)
+ {
+ pointer new_data = NULL, old_data = NULL;
+
+ total_size = total_len * size_in_bytes;
+ new_value.data = (pointer)xalloc (total_size);
+ if (!new_value.data && total_size)
+ {
+ if (add)
+ XIDestroyDeviceProperty (prop);
+ return BadAlloc;
+ }
+ new_value.size = len;
+ new_value.type = type;
+ new_value.format = format;
+
+ switch (mode) {
+ case PropModeReplace:
+ new_data = new_value.data;
+ old_data = NULL;
+ break;
+ case PropModeAppend:
+ new_data = (pointer) (((char *) new_value.data) +
+ (prop_value->size * size_in_bytes));
+ old_data = new_value.data;
+ break;
+ case PropModePrepend:
+ new_data = new_value.data;
+ old_data = (pointer) (((char *) new_value.data) +
+ (prop_value->size * size_in_bytes));
+ break;
+ }
+ if (new_data)
+ memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
+ if (old_data)
+ memcpy ((char *) old_data, (char *) prop_value->data,
+ prop_value->size * size_in_bytes);
+
+ if (dev->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler;
+ BOOL checkonly = TRUE;
+ /* run through all handlers with checkonly TRUE, then again with
+ * checkonly FALSE. Handlers MUST return error codes on the
+ * checkonly run, errors on the second run are ignored */
+ do
+ {
+ handler = dev->properties.handlers;
+ while(handler)
+ {
+ if (handler->SetProperty)
+ {
+ rc = handler->SetProperty(dev, prop->propertyName,
+ &new_value, checkonly);
+ if (checkonly && rc != Success)
+ {
+ if (new_value.data)
+ xfree (new_value.data);
+ return (rc);
+ }
+ }
+ handler = handler->next;
+ }
+ checkonly = !checkonly;
+ } while (!checkonly);
+ }
+ if (prop_value->data)
+ xfree (prop_value->data);
+ *prop_value = new_value;
+ } else if (len == 0)
+ {
+ /* do nothing */
+ }
+
+ if (add)
+ {
+ prop->next = dev->properties.properties;
+ dev->properties.properties = prop;
+ }
+
+ if (sendevent)
+ send_property_event(dev, prop->propertyName,
+ (add) ? XIPropertyCreated : XIPropertyModified);
+
+ return(Success);
+}
+
+int
+XIGetDeviceProperty (DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
+{
+ XIPropertyPtr prop = XIFetchDeviceProperty (dev, property);
+ int rc;
+
+ if (!prop)
+ {
+ *value = NULL;
+ return BadAtom;
+ }
+
+ /* If we can, try to update the property value first */
+ if (dev->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler = dev->properties.handlers;
+ while(handler)
+ {
+ if (handler->GetProperty)
+ {
+ rc = handler->GetProperty(dev, prop->propertyName);
+ if (rc != Success)
+ {
+ *value = NULL;
+ return rc;
+ }
+ }
+ handler = handler->next;
+ }
+ }
+
+ *value = &prop->value;
+ return Success;
+}
+
+int
+XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
+{
+ XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
+
+ if (!prop)
+ return BadAtom;
+
+ prop->deletable = deletable;
+ return Success;
+}
+
+int
+ProcXListDeviceProperties (ClientPtr client)
+{
+ Atom *atoms;
+ xListDevicePropertiesReply rep;
+ int natoms;
+ DeviceIntPtr dev;
+ int rc = Success;
+
+ REQUEST(xListDevicePropertiesReq);
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = list_atoms(dev, &natoms, &atoms);
+ if (rc != Success)
+ return rc;
+
+ rep.repType = X_Reply;
+ rep.RepType = X_ListDeviceProperties;
+ rep.length = natoms;
+ rep.sequenceNumber = client->sequence;
+ rep.nAtoms = natoms;
+
+ WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
+ if (natoms)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
+ xfree(atoms);
+ }
+ return rc;
+}
+
+int
+ProcXChangeDeviceProperty (ClientPtr client)
+{
+ REQUEST(xChangeDevicePropertyReq);
+ DeviceIntPtr dev;
+ unsigned long len;
+ int totalSize;
+ int rc;
+
+ REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
+ UpdateCurrentTime();
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = check_change_property(client, stuff->property, stuff->type,
+ stuff->format, stuff->mode, stuff->nUnits);
+
+ len = stuff->nUnits;
+ if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
+ return BadLength;
+
+ totalSize = len * (stuff->format/8);
+ REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
+
+ rc = change_property(client, dev, stuff->property, stuff->type,
+ stuff->format, stuff->mode, len, (void*)&stuff[1]);
+ return rc;
+}
+
+int
+ProcXDeleteDeviceProperty (ClientPtr client)
+{
+ REQUEST(xDeleteDevicePropertyReq);
+ DeviceIntPtr dev;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return (BadAtom);
+ }
+
+ rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
+ return rc;
+}
+
+int
+ProcXGetDeviceProperty (ClientPtr client)
+{
+ REQUEST(xGetDevicePropertyReq);
+ DeviceIntPtr dev;
+ int length;
+ int rc, format, nitems, bytes_after;
+ char *data;
+ Atom type;
+ xGetDevicePropertyReply reply;
+
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ if (stuff->delete)
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client,
+ stuff->delete ? DixSetPropAccess :
+ DixGetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = get_property(client, dev, stuff->property, stuff->type,
+ stuff->delete, stuff->longOffset, stuff->longLength,
+ &bytes_after, &type, &format, &nitems, &length, &data);
+
+ if (rc != Success)
+ return rc;
+
+ reply.repType = X_Reply;
+ reply.RepType = X_GetDeviceProperty;
+ reply.sequenceNumber = client->sequence;
+ reply.deviceid = dev->id;
+ reply.nItems = nitems;
+ reply.format = format;
+ reply.bytesAfter = bytes_after;
+ reply.propertyType = type;
+ reply.length = bytes_to_int32(length);
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ send_property_event(dev, stuff->property, XIPropertyDeleted);
+
+ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+
+ if (length)
+ {
+ switch (reply.format) {
+ case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
+ case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
+ default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
+ }
+ WriteSwappedDataToClient(client, length, data);
+ }
+
+ /* delete the Property */
+ if (stuff->delete && (reply.bytesAfter == 0))
+ {
+ XIPropertyPtr prop, *prev;
+ for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
+ {
+ if (prop->propertyName == stuff->property)
+ {
+ *prev = prop->next;
+ XIDestroyDeviceProperty(prop);
+ break;
+ }
+ }
+ }
+ return Success;
+}
+
+
+int
+SProcXListDeviceProperties (ClientPtr client)
+{
+ char n;
+ REQUEST(xListDevicePropertiesReq);
+
+ swaps(&stuff->length, n);
+
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+ return (ProcXListDeviceProperties(client));
+}
+
+int
+SProcXChangeDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xChangeDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->nUnits, n);
+ REQUEST_SIZE_MATCH(xChangeDevicePropertyReq);
+ return (ProcXChangeDeviceProperty(client));
+}
+
+int
+SProcXDeleteDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xDeleteDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ return (ProcXDeleteDeviceProperty(client));
+}
+
+int
+SProcXGetDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xGetDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->longOffset, n);
+ swapl(&stuff->longLength, n);
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ return (ProcXGetDeviceProperty(client));
+}
+
+
+/* Reply swapping */
+
+void
+SRepXListDeviceProperties(ClientPtr client, int size,
+ xListDevicePropertiesReply *rep)
+{
+ char n;
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->nAtoms, n);
+ /* properties will be swapped later, see ProcXListDeviceProperties */
+ WriteToClient(client, size, (char*)rep);
+}
+
+void
+SRepXGetDeviceProperty(ClientPtr client, int size,
+ xGetDevicePropertyReply *rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->propertyType, n);
+ swapl(&rep->bytesAfter, n);
+ swapl(&rep->nItems, n);
+ /* data will be swapped, see ProcXGetDeviceProperty */
+ WriteToClient(client, size, (char*)rep);
+}
+
+/* XI2 Request/reply handling */
+int
+ProcXIListProperties(ClientPtr client)
+{
+ Atom *atoms;
+ xXIListPropertiesReply rep;
+ int natoms;
+ DeviceIntPtr dev;
+ int rc = Success;
+
+ REQUEST(xXIListPropertiesReq);
+ REQUEST_SIZE_MATCH(xXIListPropertiesReq);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = list_atoms(dev, &natoms, &atoms);
+ if (rc != Success)
+ return rc;
+
+ rep.repType = X_Reply;
+ rep.RepType = X_XIListProperties;
+ rep.length = natoms;
+ rep.sequenceNumber = client->sequence;
+ rep.num_properties = natoms;
+
+ WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep);
+ if (natoms)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
+ xfree(atoms);
+ }
+ return rc;
+}
+
+int
+ProcXIChangeProperty(ClientPtr client)
+{
+ int rc;
+ DeviceIntPtr dev;
+ int totalSize;
+ unsigned long len;
+
+ REQUEST(xXIChangePropertyReq);
+ REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
+ UpdateCurrentTime();
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = check_change_property(client, stuff->property, stuff->type,
+ stuff->format, stuff->mode, stuff->num_items);
+ len = stuff->num_items;
+ if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
+ return BadLength;
+
+ totalSize = len * (stuff->format/8);
+ REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize);
+
+ rc = change_property(client, dev, stuff->property, stuff->type,
+ stuff->format, stuff->mode, len, (void*)&stuff[1]);
+ return rc;
+}
+
+int
+ProcXIDeleteProperty(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ int rc;
+ REQUEST(xXIDeletePropertyReq);
+
+ REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return (BadAtom);
+ }
+
+ rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
+ return rc;
+}
+
+
+int
+ProcXIGetProperty(ClientPtr client)
+{
+ REQUEST(xXIGetPropertyReq);
+ DeviceIntPtr dev;
+ xXIGetPropertyReply reply;
+ int length;
+ int rc, format, nitems, bytes_after;
+ char *data;
+ Atom type;
+
+ REQUEST_SIZE_MATCH(xXIGetPropertyReq);
+ if (stuff->delete)
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client,
+ stuff->delete ? DixSetPropAccess :
+ DixGetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = get_property(client, dev, stuff->property, stuff->type,
+ stuff->delete, stuff->offset, stuff->len,
+ &bytes_after, &type, &format, &nitems, &length, &data);
+
+ if (rc != Success)
+ return rc;
+
+ reply.repType = X_Reply;
+ reply.RepType = X_XIGetProperty;
+ reply.sequenceNumber = client->sequence;
+ reply.num_items = nitems;
+ reply.format = format;
+ reply.bytes_after = bytes_after;
+ reply.type = type;
+ reply.length = bytes_to_int32(length);
+
+ if (length && stuff->delete && (reply.bytes_after == 0))
+ send_property_event(dev, stuff->property, XIPropertyDeleted);
+
+ WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply);
+
+ if (length)
+ {
+ switch (reply.format) {
+ case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
+ case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
+ default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
+ }
+ WriteSwappedDataToClient(client, length, data);
+ }
+
+ /* delete the Property */
+ if (stuff->delete && (reply.bytes_after == 0))
+ {
+ XIPropertyPtr prop, *prev;
+ for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
+ {
+ if (prop->propertyName == stuff->property)
+ {
+ *prev = prop->next;
+ XIDestroyDeviceProperty(prop);
+ break;
+ }
+ }
+ }
+
+ return Success;
+}
+
+int
+SProcXIListProperties(ClientPtr client)
+{
+ char n;
+ REQUEST(xXIListPropertiesReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+
+ REQUEST_SIZE_MATCH(xXIListPropertiesReq);
+ return (ProcXIListProperties(client));
+}
+
+int
+SProcXIChangeProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xXIChangePropertyReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->num_items, n);
+ REQUEST_SIZE_MATCH(xXIChangePropertyReq);
+ return (ProcXIChangeProperty(client));
+}
+
+int
+SProcXIDeleteProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xXIDeletePropertyReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->property, n);
+ REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
+ return (ProcXIDeleteProperty(client));
+}
+
+int
+SProcXIGetProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xXIGetPropertyReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->offset, n);
+ swapl(&stuff->len, n);
+ REQUEST_SIZE_MATCH(xXIGetPropertyReq);
+ return (ProcXIGetProperty(client));
+}
+
+
+void
+SRepXIListProperties(ClientPtr client, int size,
+ xXIListPropertiesReply *rep)
+{
+ char n;
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->num_properties, n);
+ /* properties will be swapped later, see ProcXIListProperties */
+ WriteToClient(client, size, (char*)rep);
+}
+
+void
+SRepXIGetProperty(ClientPtr client, int size,
+ xXIGetPropertyReply *rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->type, n);
+ swapl(&rep->bytes_after, n);
+ swapl(&rep->num_items, n);
+ /* data will be swapped, see ProcXIGetProperty */
+ WriteToClient(client, size, (char*)rep);
+}
|