aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xi/xiproperty.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2011-09-22 15:42:49 +0200
committermarha <marha@users.sourceforge.net>2011-09-22 15:42:49 +0200
commit46d4f558531910ca1f3297da85b99334d6de2921 (patch)
tree60c37077eb160948fe317a17ec4c19bef679aa35 /xorg-server/Xi/xiproperty.c
parent0bf6df93b9fdbb7902bf1014d605c6876a3ad035 (diff)
parentc1e6c7428a8d2c1b60ffac7df7a3f56c300fa983 (diff)
downloadvcxsrv-46d4f558531910ca1f3297da85b99334d6de2921.tar.gz
vcxsrv-46d4f558531910ca1f3297da85b99334d6de2921.tar.bz2
vcxsrv-46d4f558531910ca1f3297da85b99334d6de2921.zip
Merge remote-tracking branch 'origin/released'
Conflicts: xorg-server/Xext/dpms.c xorg-server/Xext/saver.c xorg-server/Xext/security.c xorg-server/Xext/shape.c xorg-server/Xext/sync.c xorg-server/Xi/opendev.c xorg-server/fb/wfbrename.h xorg-server/glx/glxserver.h xorg-server/hw/xwin/winwindowswm.c xorg-server/mi/miarc.c xorg-server/mi/miwideline.c xorg-server/os/io.c xorg-server/render/mipict.c
Diffstat (limited to 'xorg-server/Xi/xiproperty.c')
-rw-r--r--xorg-server/Xi/xiproperty.c2710
1 files changed, 1348 insertions, 1362 deletions
diff --git a/xorg-server/Xi/xiproperty.c b/xorg-server/Xi/xiproperty.c
index b10891d1c..fa0d81188 100644
--- a/xorg-server/Xi/xiproperty.c
+++ b/xorg-server/Xi/xiproperty.c
@@ -1,1362 +1,1348 @@
-/*
- * 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},
-
- {0, XI_PROP_TRANSFORM}
-};
-
-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 = malloc(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 = calloc(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 = calloc(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 = calloc(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;
-
- free(curr);
-}
-
-static XIPropertyPtr
-XICreateDeviceProperty (Atom property)
-{
- XIPropertyPtr prop;
-
- prop = (XIPropertyPtr)malloc(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)
-{
- free(prop->value.data);
- free(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;
- free(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,
- const 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)malloc(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)
- {
- free(new_value.data);
- return rc;
- }
- }
- handler = handler->next;
- }
- checkonly = !checkonly;
- } while (!checkonly);
- }
- free(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);
- free(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);
-
- REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
- swaps(&stuff->length, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->nUnits, n);
- 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);
- free(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);
-
- REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->num_items, n);
- 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},
+
+ {0, XI_PROP_TRANSFORM}
+};
+
+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 = malloc(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 = calloc(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 = calloc(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 = calloc(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;
+
+ free(curr);
+}
+
+static XIPropertyPtr
+XICreateDeviceProperty (Atom property)
+{
+ XIPropertyPtr prop;
+
+ prop = (XIPropertyPtr)malloc(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)
+{
+ free(prop->value.data);
+ free(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;
+ free(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,
+ const 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)malloc(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)
+ {
+ free(new_value.data);
+ return rc;
+ }
+ }
+ handler = handler->next;
+ }
+ checkonly = !checkonly;
+ } while (!checkonly);
+ }
+ free(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);
+ free(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)
+{
+ REQUEST(xListDevicePropertiesReq);
+
+ swaps(&stuff->length);
+
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+ return (ProcXListDeviceProperties(client));
+}
+
+int
+SProcXChangeDeviceProperty (ClientPtr client)
+{
+ REQUEST(xChangeDevicePropertyReq);
+
+ REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
+ swaps(&stuff->length);
+ swapl(&stuff->property);
+ swapl(&stuff->type);
+ swapl(&stuff->nUnits);
+ return (ProcXChangeDeviceProperty(client));
+}
+
+int
+SProcXDeleteDeviceProperty (ClientPtr client)
+{
+ REQUEST(xDeleteDevicePropertyReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->property);
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ return (ProcXDeleteDeviceProperty(client));
+}
+
+int
+SProcXGetDeviceProperty (ClientPtr client)
+{
+ REQUEST(xGetDevicePropertyReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->property);
+ swapl(&stuff->type);
+ swapl(&stuff->longOffset);
+ swapl(&stuff->longLength);
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ return (ProcXGetDeviceProperty(client));
+}
+
+
+/* Reply swapping */
+
+void
+SRepXListDeviceProperties(ClientPtr client, int size,
+ xListDevicePropertiesReply *rep)
+{
+ swaps(&rep->sequenceNumber);
+ swapl(&rep->length);
+ swaps(&rep->nAtoms);
+ /* properties will be swapped later, see ProcXListDeviceProperties */
+ WriteToClient(client, size, (char*)rep);
+}
+
+void
+SRepXGetDeviceProperty(ClientPtr client, int size,
+ xGetDevicePropertyReply *rep)
+{
+ swaps(&rep->sequenceNumber);
+ swapl(&rep->length);
+ swapl(&rep->propertyType);
+ swapl(&rep->bytesAfter);
+ swapl(&rep->nItems);
+ /* 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);
+ free(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)
+{
+ REQUEST(xXIListPropertiesReq);
+
+ swaps(&stuff->length);
+ swaps(&stuff->deviceid);
+
+ REQUEST_SIZE_MATCH(xXIListPropertiesReq);
+ return (ProcXIListProperties(client));
+}
+
+int
+SProcXIChangeProperty(ClientPtr client)
+{
+ REQUEST(xXIChangePropertyReq);
+
+ REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
+ swaps(&stuff->length);
+ swaps(&stuff->deviceid);
+ swapl(&stuff->property);
+ swapl(&stuff->type);
+ swapl(&stuff->num_items);
+ return (ProcXIChangeProperty(client));
+}
+
+int
+SProcXIDeleteProperty(ClientPtr client)
+{
+ REQUEST(xXIDeletePropertyReq);
+
+ swaps(&stuff->length);
+ swaps(&stuff->deviceid);
+ swapl(&stuff->property);
+ REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
+ return (ProcXIDeleteProperty(client));
+}
+
+int
+SProcXIGetProperty(ClientPtr client)
+{
+ REQUEST(xXIGetPropertyReq);
+
+ swaps(&stuff->length);
+ swaps(&stuff->deviceid);
+ swapl(&stuff->property);
+ swapl(&stuff->type);
+ swapl(&stuff->offset);
+ swapl(&stuff->len);
+ REQUEST_SIZE_MATCH(xXIGetPropertyReq);
+ return (ProcXIGetProperty(client));
+}
+
+
+void
+SRepXIListProperties(ClientPtr client, int size,
+ xXIListPropertiesReply *rep)
+{
+ swaps(&rep->sequenceNumber);
+ swapl(&rep->length);
+ swaps(&rep->num_properties);
+ /* properties will be swapped later, see ProcXIListProperties */
+ WriteToClient(client, size, (char*)rep);
+}
+
+void
+SRepXIGetProperty(ClientPtr client, int size,
+ xXIGetPropertyReply *rep)
+{
+ swaps(&rep->sequenceNumber);
+ swapl(&rep->length);
+ swapl(&rep->type);
+ swapl(&rep->bytes_after);
+ swapl(&rep->num_items);
+ /* data will be swapped, see ProcXIGetProperty */
+ WriteToClient(client, size, (char*)rep);
+}