summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xi/Makefile.am6
-rw-r--r--Xi/extinit.c17
-rw-r--r--Xi/xiproperty.c755
-rw-r--r--Xi/xiproperty.h43
-rw-r--r--dix/devices.c9
-rw-r--r--include/exevents.h47
-rw-r--r--include/inputstr.h41
7 files changed, 912 insertions, 6 deletions
diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 2af1940eb..768f996cc 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -94,7 +94,9 @@ libXi_la_SOURCES = \
ungrdevk.h \
warpdevp.c \
warpdevp.h \
- xiselev.c \
- xiselev.h
+ xiproperty.c \
+ xiproperty.h \
+ xiselev.c \
+ xiselev.h
EXTRA_DIST = stubs.c
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 613472ab6..7460d71ee 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -122,6 +122,7 @@ SOFTWARE.
#include "ungrdevk.h"
#include "warpdevp.h"
#include "xiselev.h"
+#include "xiproperty.c"
static Mask lastExtEventMask = 1;
@@ -217,7 +218,13 @@ static int (*ProcIVector[])(ClientPtr) = {
ProcXSetClientPointer, /* 42 */
ProcXGetClientPointer, /* 43 */
ProcXiSelectEvent, /* 44 */
- ProcXExtendedGrabDevice /* 45 */
+ ProcXExtendedGrabDevice, /* 45 */
+ ProcXListDeviceProperties, /* 46 */
+ ProcXQueryDeviceProperty, /* 47 */
+ ProcXConfigureDeviceProperty, /* 48 */
+ ProcXChangeDeviceProperty, /* 49 */
+ ProcXDeleteDeviceProperty, /* 50 */
+ ProcXGetDeviceProperty /* 51 */
};
/* For swapped clients */
@@ -267,7 +274,13 @@ static int (*SProcIVector[])(ClientPtr) = {
SProcXSetClientPointer, /* 42 */
SProcXGetClientPointer, /* 43 */
SProcXiSelectEvent, /* 44 */
- SProcXExtendedGrabDevice /* 45 */
+ SProcXExtendedGrabDevice, /* 45 */
+ SProcXListDeviceProperties, /* 46 */
+ SProcXQueryDeviceProperty, /* 47 */
+ SProcXConfigureDeviceProperty, /* 48 */
+ SProcXChangeDeviceProperty, /* 49 */
+ SProcXDeleteDeviceProperty, /* 50 */
+ SProcXGetDeviceProperty /* 51 */
};
/*****************************************************************
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c
new file mode 100644
index 000000000..832a4582d
--- /dev/null
+++ b/Xi/xiproperty.c
@@ -0,0 +1,755 @@
+/*
+ * 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/extensions/XIproto.h>
+#include "exglobals.h"
+#include "exevents.h"
+#include "swaprep.h"
+
+#include "xiproperty.h"
+
+void
+XIDeleteAllDeviceProperties (DeviceIntPtr device)
+{
+ XIPropertyPtr prop, next;
+ devicePropertyNotifyEvent event;
+
+ for (prop = device->properties; prop; prop = next)
+ {
+ next = prop->next;
+
+ event.type = GenericEvent;
+ event.extension = IReqCode;
+ event.evtype = XI_DevicePropertyNotify;
+ event.length = 0;
+ event.deviceid = device->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(device, XI_DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+
+ if (prop->current.data)
+ xfree(prop->current.data);
+ if (prop->pending.data)
+ xfree(prop->pending.data);
+ xfree(prop);
+ }
+}
+
+static void
+XIInitDevicePropertyValue (XIPropertyValuePtr property_value)
+{
+ property_value->type = None;
+ property_value->format = 0;
+ property_value->size = 0;
+ property_value->data = NULL;
+}
+
+static XIPropertyPtr
+XICreateDeviceProperty (Atom property)
+{
+ XIPropertyPtr prop;
+
+ prop = (XIPropertyPtr)xalloc(sizeof(XIPropertyRec));
+ if (!prop)
+ return NULL;
+
+ prop->next = NULL;
+ prop->propertyName = property;
+ prop->is_pending = FALSE;
+ prop->range = FALSE;
+ prop->fromClient = FALSE;
+ prop->immutable = FALSE;
+ prop->num_valid = 0;
+ prop->valid_values = NULL;
+
+ XIInitDevicePropertyValue (&prop->current);
+ XIInitDevicePropertyValue (&prop->pending);
+ return prop;
+}
+
+static void
+XIDestroyDeviceProperty (XIPropertyPtr prop)
+{
+ if (prop->valid_values)
+ xfree (prop->valid_values);
+ if (prop->current.data)
+ xfree(prop->current.data);
+ if (prop->pending.data)
+ xfree(prop->pending.data);
+ xfree(prop);
+}
+
+int
+XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient)
+{
+ XIPropertyPtr prop, *prev;
+ devicePropertyNotifyEvent event;
+
+ for (prev = &device->properties; (prop = *prev); prev = &(prop->next))
+ if (prop->propertyName == property)
+ break;
+
+ if (!prop->fromClient && fromClient)
+ return BadAtom;
+
+ if (prop)
+ {
+ *prev = prop->next;
+ event.type = GenericEvent;
+ event.extension = IReqCode;
+ event.length = 0;
+ event.evtype = XI_DevicePropertyNotify;
+ event.deviceid = device->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(device, XI_DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+ XIDestroyDeviceProperty (prop);
+ }
+
+ return Success;
+}
+
+int
+XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type,
+ int format, int mode, unsigned long len,
+ pointer value, Bool sendevent, Bool pending,
+ Bool fromClient)
+{
+ XIPropertyPtr prop;
+ devicePropertyNotifyEvent event;
+ int size_in_bytes;
+ int total_size;
+ unsigned long total_len;
+ XIPropertyValuePtr prop_value;
+ XIPropertyValueRec new_value;
+ Bool add = FALSE;
+
+ size_in_bytes = format >> 3;
+
+ /* first see if property already exists */
+ prop = XIQueryDeviceProperty (dev, property);
+ if (!prop) /* just add to list */
+ {
+ prop = XICreateDeviceProperty (property);
+ if (!prop)
+ return(BadAlloc);
+ prop->fromClient = fromClient;
+ add = TRUE;
+ mode = PropModeReplace;
+ }
+ if (pending && prop->is_pending)
+ prop_value = &prop->pending;
+ else
+ prop_value = &prop->current;
+
+ /* 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);
+
+ /* We must set pendingProperties TRUE before we commit to the driver,
+ we're in a single thread after all
+ */
+ if (pending && prop->is_pending)
+ dev->pendingProperties = TRUE;
+ if (pending && dev->SetProperty &&
+ !dev->SetProperty(dev, prop->propertyName, &new_value))
+ {
+ if (new_value.data)
+ xfree (new_value.data);
+ return (BadValue);
+ }
+ if (prop_value->data)
+ xfree (prop_value->data);
+ *prop_value = new_value;
+ }
+
+ else if (len == 0)
+ {
+ /* do nothing */
+ }
+
+ if (add)
+ {
+ prop->next = dev->properties;
+ dev->properties = prop;
+ }
+
+
+ if (sendevent)
+ {
+ event.type = GenericEvent;
+ event.extension = IReqCode;
+ event.length = 0;
+ event.evtype = XI_DevicePropertyNotify;
+ event.deviceid = dev->id;
+ event.state = PropertyNewValue;
+ event.atom = prop->propertyName;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(dev, XI_DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+ }
+ return(Success);
+}
+
+XIPropertyPtr
+XIQueryDeviceProperty (DeviceIntPtr dev, Atom property)
+{
+ XIPropertyPtr prop;
+
+ for (prop = dev->properties; prop; prop = prop->next)
+ if (prop->propertyName == property)
+ return prop;
+ return NULL;
+}
+
+XIPropertyValuePtr
+XIGetDeviceProperty (DeviceIntPtr dev, Atom property, Bool pending)
+{
+ XIPropertyPtr prop = XIQueryDeviceProperty (dev, property);
+
+ if (!prop)
+ return NULL;
+ if (pending && prop->is_pending)
+ return &prop->pending;
+ else {
+ /* If we can, try to update the property value first */
+ if (dev->GetProperty)
+ dev->GetProperty(dev, prop->propertyName);
+ return &prop->current;
+ }
+}
+
+int
+XIConfigureDeviceProperty (DeviceIntPtr dev, Atom property,
+ Bool pending, Bool range, Bool immutable,
+ int num_values, INT32 *values)
+{
+ XIPropertyPtr prop = XIQueryDeviceProperty (dev, property);
+ Bool add = FALSE;
+ INT32 *new_values;
+
+ if (!prop)
+ {
+ prop = XICreateDeviceProperty (property);
+ if (!prop)
+ return(BadAlloc);
+ add = TRUE;
+ } else if (prop->immutable && !immutable)
+ return(BadAccess);
+
+ /*
+ * ranges must have even number of values
+ */
+ if (range && (num_values & 1))
+ return BadMatch;
+
+ new_values = xalloc (num_values * sizeof (INT32));
+ if (!new_values && num_values)
+ return BadAlloc;
+ if (num_values)
+ memcpy (new_values, values, num_values * sizeof (INT32));
+
+ /*
+ * Property moving from pending to non-pending
+ * loses any pending values
+ */
+ if (prop->is_pending && !pending)
+ {
+ if (prop->pending.data)
+ xfree (prop->pending.data);
+ XIInitDevicePropertyValue (&prop->pending);
+ }
+
+ prop->is_pending = pending;
+ prop->range = range;
+ prop->immutable = immutable;
+ prop->num_valid = num_values;
+ if (prop->valid_values)
+ xfree (prop->valid_values);
+ prop->valid_values = new_values;
+
+ if (add) {
+ prop->next = dev->properties;
+ dev->properties = prop;
+ }
+
+ return Success;
+}
+
+int
+ProcXListDeviceProperties (ClientPtr client)
+{
+ Atom *pAtoms = NULL, *temppAtoms;
+ xListDevicePropertiesReply rep;
+ int numProps = 0;
+ DeviceIntPtr dev;
+ XIPropertyPtr prop;
+ int rc = Success;
+
+ REQUEST(xListDevicePropertiesReq);
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ for (prop = dev->properties; prop; prop = prop->next)
+ numProps++;
+ if (numProps)
+ if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
+ return(BadAlloc);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_ListDeviceProperties;
+ rep.length = (numProps * sizeof(Atom)) >> 2;
+ rep.sequenceNumber = client->sequence;
+ rep.nAtoms = numProps;
+ if (client->swapped)
+ {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ }
+ temppAtoms = pAtoms;
+ for (prop = dev->properties; prop; prop = prop->next)
+ *temppAtoms++ = prop->propertyName;
+
+ WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
+ if (numProps)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
+ xfree(pAtoms);
+ }
+ return rc;
+}
+
+int
+ProcXQueryDeviceProperty (ClientPtr client)
+{
+ REQUEST(xQueryDevicePropertyReq);
+ xQueryDevicePropertyReply rep;
+ DeviceIntPtr dev;
+ XIPropertyPtr prop;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xQueryDevicePropertyReq);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixReadAccess);
+
+ if (rc != Success)
+ return rc;
+
+ prop = XIQueryDeviceProperty (dev, stuff->property);
+ if (!prop)
+ return BadName;
+
+ rep.repType = X_Reply;
+ rep.length = prop->num_valid;
+ rep.sequenceNumber = client->sequence;
+ rep.pending = prop->is_pending;
+ rep.range = prop->range;
+ rep.immutable = prop->immutable;
+ rep.fromClient = prop->fromClient;
+ if (client->swapped)
+ {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ }
+ WriteReplyToClient (client, sizeof (xQueryDevicePropertyReply), &rep);
+ if (prop->num_valid)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32),
+ prop->valid_values);
+ }
+ return(client->noClientException);
+}
+
+int
+ProcXConfigureDeviceProperty (ClientPtr client)
+{
+ REQUEST(xConfigureDevicePropertyReq);
+ DeviceIntPtr dev;
+ int num_valid;
+ int rc;
+
+ REQUEST_AT_LEAST_SIZE(xConfigureDevicePropertyReq);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixReadAccess);
+
+ if (rc != Success)
+ return rc;
+
+ num_valid = stuff->length - (sizeof (xConfigureDevicePropertyReq) >> 2);
+ return XIConfigureDeviceProperty (dev, stuff->property,
+ stuff->pending, stuff->range,
+ FALSE, num_valid,
+ (INT32 *) (stuff + 1));
+}
+
+int
+ProcXChangeDeviceProperty (ClientPtr client)
+{
+ REQUEST(xChangeDevicePropertyReq);
+ DeviceIntPtr dev;
+ char format, mode;
+ unsigned long len;
+ int sizeInBytes;
+ int totalSize;
+ int rc;
+
+ REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
+ UpdateCurrentTime();
+ format = stuff->format;
+ mode = stuff->mode;
+ if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
+ (mode != PropModePrepend))
+ {
+ client->errorValue = mode;
+ return BadValue;
+ }
+ if ((format != 8) && (format != 16) && (format != 32))
+ {
+ client->errorValue = format;
+ return BadValue;
+ }
+ len = stuff->nUnits;
+ if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2))
+ return BadLength;
+ sizeInBytes = format>>3;
+ totalSize = len * sizeInBytes;
+ REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return(BadAtom);
+ }
+ if (!ValidAtom(stuff->type))
+ {
+ client->errorValue = stuff->type;
+ return(BadAtom);
+ }
+
+ rc = XIChangeDeviceProperty(dev, stuff->property,
+ stuff->type, (int)format,
+ (int)mode, len, (pointer)&stuff[1], TRUE,
+ TRUE, TRUE);
+
+ return rc;
+}
+
+int
+ProcXDeleteDeviceProperty (ClientPtr client)
+{
+ REQUEST(xDeleteDevicePropertyReq);
+ DeviceIntPtr dev;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixWriteAccess);
+ 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);
+ XIPropertyPtr prop, *prev;
+ XIPropertyValuePtr prop_value;
+ unsigned long n, len, ind;
+ DeviceIntPtr dev;
+ xGetDevicePropertyReply reply;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ if (stuff->delete)
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client,
+ stuff->delete ? DixWriteAccess :
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return(BadAtom);
+ }
+ if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
+ {
+ client->errorValue = stuff->delete;
+ return(BadValue);
+ }
+ if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
+ {
+ client->errorValue = stuff->type;
+ return(BadAtom);
+ }
+
+ for (prev = &dev->properties; (prop = *prev); prev = &prop->next)
+ if (prop->propertyName == stuff->property)
+ break;
+
+ reply.repType = X_Reply;
+ reply.RepType = X_GetDeviceProperty;
+ reply.sequenceNumber = client->sequence;
+ if (!prop)
+ {
+ reply.nItems = 0;
+ reply.length = 0;
+ reply.bytesAfter = 0;
+ reply.propertyType = None;
+ reply.format = 0;
+ WriteReplyToClient(client, sizeof(xGetDevicePropertyReply), &reply);
+ return(client->noClientException);
+ }
+
+ if (prop->immutable && stuff->delete)
+ return BadAccess;
+
+ prop_value = XIGetDeviceProperty(dev, stuff->property, stuff->pending);
+ if (!prop_value)
+ return BadAtom;
+
+ /* If the request type and actual type don't match. Return the
+ property information, but not the data. */
+
+ if (((stuff->type != prop_value->type) &&
+ (stuff->type != AnyPropertyType))
+ )
+ {
+ reply.bytesAfter = prop_value->size;
+ reply.format = prop_value->format;
+ reply.length = 0;
+ reply.nItems = 0;
+ reply.propertyType = prop_value->type;
+ WriteReplyToClient(client, sizeof(xGetDevicePropertyReply), &reply);
+ return(client->noClientException);
+ }
+
+/*
+ * Return type, format, value to client
+ */
+ n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */
+ ind = stuff->longOffset << 2;
+
+ /* If longOffset is invalid such that it causes "len" to
+ be negative, it's a value error. */
+
+ if (n < ind)
+ {
+ client->errorValue = stuff->longOffset;
+ return BadValue;
+ }
+
+ len = min(n - ind, 4 * stuff->longLength);
+
+ reply.bytesAfter = n - (ind + len);
+ reply.format = prop_value->format;
+ reply.length = (len + 3) >> 2;
+ if (prop_value->format)
+ reply.nItems = len / (prop_value->format / 8);
+ else
+ reply.nItems = 0;
+ reply.propertyType = prop_value->type;
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ {
+ devicePropertyNotifyEvent event;
+
+ event.type = GenericEvent;
+ event.extension = IReqCode;
+ event.length = 0;
+ event.evtype = XI_DevicePropertyNotify;
+ event.deviceid = dev->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(dev, XI_DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+ }
+
+ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+ if (len)
+ {
+ 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, len,
+ (char *)prop_value->data + ind);
+ }
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ { /* delete the Property */
+ *prev = prop->next;
+ XIDestroyDeviceProperty (prop);
+ }
+ return(client->noClientException);
+}
+
+
+int
+SProcXListDeviceProperties (ClientPtr client)
+{
+ REQUEST(xListDevicePropertiesReq);
+
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+ (void) stuff;
+ return BadImplementation;
+}
+
+int
+SProcXQueryDeviceProperty (ClientPtr client)
+{
+ REQUEST(xQueryDevicePropertyReq);
+
+ REQUEST_SIZE_MATCH(xQueryDevicePropertyReq);
+ (void) stuff;
+ return BadImplementation;
+}
+
+int
+SProcXConfigureDeviceProperty (ClientPtr client)
+{
+ REQUEST(xConfigureDevicePropertyReq);
+
+ REQUEST_SIZE_MATCH(xConfigureDevicePropertyReq);
+ (void) stuff;
+ return BadImplementation;
+}
+
+int
+SProcXChangeDeviceProperty (ClientPtr client)
+{
+ REQUEST(xChangeDevicePropertyReq);
+
+ REQUEST_SIZE_MATCH(xChangeDevicePropertyReq);
+ (void) stuff;
+ return BadImplementation;
+}
+
+int
+SProcXDeleteDeviceProperty (ClientPtr client)
+{
+ REQUEST(xDeleteDevicePropertyReq);
+
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ (void) stuff;
+ return BadImplementation;
+}
+
+int
+SProcXGetDeviceProperty (ClientPtr client)
+{
+ REQUEST(xGetDevicePropertyReq);
+
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ (void) stuff;
+ return BadImplementation;
+}
+
diff --git a/Xi/xiproperty.h b/Xi/xiproperty.h
new file mode 100644
index 000000000..e31cdad0a
--- /dev/null
+++ b/Xi/xiproperty.h
@@ -0,0 +1,43 @@
+/*
+ * 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 WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 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.
+ *
+ * Author: Peter Hutterer
+ */
+
+#ifndef XIPROPERTY_C
+#define XIPROPERTY_C
+
+int ProcXListDeviceProperties (ClientPtr client);
+int ProcXQueryDeviceProperty (ClientPtr client);
+int ProcXConfigureDeviceProperty (ClientPtr client);
+int ProcXChangeDeviceProperty (ClientPtr client);
+int ProcXDeleteDeviceProperty (ClientPtr client);
+int ProcXGetDeviceProperty (ClientPtr client);
+
+int SProcXListDeviceProperties (ClientPtr client);
+int SProcXQueryDeviceProperty (ClientPtr client);
+int SProcXConfigureDeviceProperty (ClientPtr client);
+int SProcXChangeDeviceProperty (ClientPtr client);
+int SProcXDeleteDeviceProperty (ClientPtr client);
+int SProcXGetDeviceProperty (ClientPtr client);
+
+#endif /* XIPROPERTY_C */
diff --git a/dix/devices.c b/dix/devices.c
index 0a68c0e61..df53613c3 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -83,6 +83,7 @@ SOFTWARE.
#include "exglobals.h"
#include "exevents.h"
#include "listdev.h" /* for CopySwapXXXClass */
+#include "xiproperty.h"
/** @file
* This file handles input device-related stuff.
@@ -173,6 +174,12 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
memset(dev->last.valuators, 0, sizeof(dev->last.valuators));
dev->last.numValuators = 0;
+ /* device properties */
+ dev->properties = NULL;
+ dev->SetProperty = NULL;
+ dev->GetProperty = NULL;
+ dev->pendingProperties = FALSE;
+
/* security creation/labeling check
*/
if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) {
@@ -770,6 +777,8 @@ CloseDevice(DeviceIntPtr dev)
if (!dev)
return;
+ XIDeleteAllDeviceProperties(dev);
+
if (dev->inited)
(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
diff --git a/include/exevents.h b/include/exevents.h
index 664e236dc..48dfccf02 100644
--- a/include/exevents.h
+++ b/include/exevents.h
@@ -188,10 +188,55 @@ extern int DeviceEventSuppressForWindow(
Mask /* mask */,
int /* maskndx */);
-void SendEventToAllWindows(
+extern void SendEventToAllWindows(
DeviceIntPtr /* dev */,
Mask /* mask */,
xEvent * /* ev */,
int /* count */);
+/* Input device properties */
+extern void XIDeleteAllDeviceProperties(
+ DeviceIntPtr /* device */
+);
+
+extern int XIDeleteDeviceProperty(
+ DeviceIntPtr /* device */,
+ Atom /* property */,
+ Bool /* fromClient */
+);
+
+extern int XIChangeDeviceProperty(
+ DeviceIntPtr /* dev */,
+ Atom /* property */,
+ Atom /* type */,
+ int /* format*/,
+ int /* mode*/,
+ unsigned long /* len*/,
+ pointer /* value*/,
+ Bool /* sendevent*/,
+ Bool /* pending*/,
+ Bool /* fromClient */
+ );
+
+extern XIPropertyPtr XIQueryDeviceProperty(
+ DeviceIntPtr /* dev */,
+ Atom /* property */
+);
+
+extern XIPropertyValuePtr XIGetDeviceProperty(
+ DeviceIntPtr /* dev */,
+ Atom /* property */,
+ Bool /* pending */
+);
+
+extern int XIConfigureDeviceProperty(
+ DeviceIntPtr /* dev */,
+ Atom /* property */,
+ Bool /* pending */,
+ Bool /* range */,
+ Bool /* immutable */,
+ int /* num_values */,
+ INT32* /* values */
+);
+
#endif /* EXEVENTS_H */
diff --git a/include/inputstr.h b/include/inputstr.h
index e5de6fc31..280774e99 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -335,6 +335,38 @@ typedef struct {
} SpriteRec, *SpritePtr;
+/* Device properties */
+typedef struct _XIPropertyValue
+{
+ Atom type; /* ignored by server */
+ short format; /* format of data for swapping - 8,16,32 */
+ long size; /* size of data in (format/8) bytes */
+ pointer data; /* private to client */
+} XIPropertyValueRec;
+
+typedef struct _XIProperty
+{
+ struct _XIProperty *next;
+ Atom propertyName;
+ Bool is_pending;
+ Bool range;
+ Bool immutable;
+ Bool fromClient; /* created by client or driver/server */
+ int num_valid;
+ INT32 *valid_values;
+ XIPropertyValueRec current,
+ pending;
+} XIPropertyRec;
+
+typedef XIPropertyRec *XIPropertyPtr;
+typedef XIPropertyValueRec *XIPropertyValuePtr;
+
+typedef Bool (*XISetDevicePropertyProcPtr) (DeviceIntPtr dev,
+ Atom property,
+ XIPropertyValuePtr prop);
+typedef Bool (*XIGetDevicePropertyProcPtr) (DeviceIntPtr dev,
+ Atom property);
+
/* states for devices */
#define NOT_GRABBED 0
@@ -347,8 +379,9 @@ typedef struct {
#define FROZEN_WITH_EVENT 6
#define THAW_OTHERS 7
+
typedef struct _GrabInfoRec {
- TimeStamp grabTime;
+ TimeStamp grabTime;
Bool fromPassiveGrab; /* true if from passive grab */
Bool implicitGrab; /* implicit from ButtonPress */
GrabRec activeGrab;
@@ -431,6 +464,12 @@ typedef struct _DeviceIntRec {
int valuators[MAX_VALUATORS];
int numValuators;
} last;
+
+ /* Input device property handling */
+ XIPropertyPtr properties;
+ Bool pendingProperties;
+ XISetDevicePropertyProcPtr SetProperty;
+ XIGetDevicePropertyProcPtr GetProperty;
} DeviceIntRec;
typedef struct {