Xi: split some code out of the XI 1.5 property request processing.

This is in preparation for the XI2 property requests that can re-use much of
this code.
This commit is contained in:
Peter Hutterer 2009-05-07 09:43:56 +10:00
parent f6f1e41706
commit 9935bec6e8

View File

@ -169,6 +169,165 @@ static struct dev_properties
static long XIPropHandlerID = 1; static long XIPropHandlerID = 1;
static int list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
{
XIPropertyPtr prop;
Atom *atoms = NULL;
int nprops = 0;
for (prop = dev->properties.properties; prop; prop = prop->next)
nprops++;
if (nprops)
{
Atom *a;
atoms = xalloc(nprops * sizeof(Atom));
if(!atoms)
return BadAlloc;
a = atoms;
for (prop = dev->properties.properties; prop; prop = prop->next, a++)
*a = prop->propertyName;
}
*natoms = nprops;
*atoms_return = atoms;
return Success;
}
static int
get_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
BOOL delete, int offset, int length,
int *bytes_after, Atom *type_return, int *format, int *nitems,
int *length_return, char **data)
{
unsigned long n, len, ind;
int rc;
XIPropertyPtr prop;
XIPropertyValuePtr prop_value;
if (!ValidAtom(property))
{
client->errorValue = property;
return(BadAtom);
}
if ((delete != xTrue) && (delete != xFalse))
{
client->errorValue = delete;
return(BadValue);
}
if ((type != AnyPropertyType) && !ValidAtom(type))
{
client->errorValue = type;
return(BadAtom);
}
for (prop = dev->properties.properties; prop; prop = prop->next)
if (prop->propertyName == property)
break;
if (!prop)
{
*bytes_after = 0;
*type_return = None;
*format = 0;
*nitems = 0;
*length_return = 0;
return Success;
}
rc = XIGetDeviceProperty(dev, property, &prop_value);
if (rc != Success)
{
client->errorValue = property;
return rc;
}
/* If the request type and actual type don't match. Return the
property information, but not the data. */
if (((type != prop_value->type) && (type != AnyPropertyType)))
{
*bytes_after = prop_value->size;
*format = prop_value->format;
*length_return = 0;
*nitems = 0;
*type_return = prop_value->type;
return Success;
}
/* Return type, format, value to client */
n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */
ind = offset << 2;
/* If offset is invalid such that it causes "len" to
be negative, it's a value error. */
if (n < ind)
{
client->errorValue = offset;
return BadValue;
}
len = min(n - ind, 4 * length);
*bytes_after = n - (ind + len);
*format = prop_value->format;
*length_return = len;
if (prop_value->format)
*nitems = len / (prop_value->format / 8);
else
*nitems = 0;
*type_return = prop_value->type;
*data = (char*)prop_value->data + ind;
return Success;
}
static int
check_change_property(ClientPtr client, Atom property, Atom type, int format,
int mode, int nitems)
{
if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
(mode != PropModePrepend))
{
client->errorValue = mode;
return BadValue;
}
if ((format != 8) && (format != 16) && (format != 32))
{
client->errorValue = format;
return BadValue;
}
if (!ValidAtom(property))
{
client->errorValue = property;
return(BadAtom);
}
if (!ValidAtom(type))
{
client->errorValue = type;
return(BadAtom);
}
return Success;
}
static int
change_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
int format, int mode, int len, void *data)
{
int rc = Success;
rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data, TRUE);
if (rc != Success)
client->errorValue = property;
return rc;
}
/** /**
* Return the atom assigned to the specified string or 0 if the atom isn't known * Return the atom assigned to the specified string or 0 if the atom isn't known
* to the DIX. * to the DIX.
@ -681,11 +840,10 @@ XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
int int
ProcXListDeviceProperties (ClientPtr client) ProcXListDeviceProperties (ClientPtr client)
{ {
Atom *pAtoms = NULL, *temppAtoms; Atom *atoms;
xListDevicePropertiesReply rep; xListDevicePropertiesReply rep;
int numProps = 0; int natoms;
DeviceIntPtr dev; DeviceIntPtr dev;
XIPropertyPtr prop;
int rc = Success; int rc = Success;
REQUEST(xListDevicePropertiesReq); REQUEST(xListDevicePropertiesReq);
@ -695,27 +853,22 @@ ProcXListDeviceProperties (ClientPtr client)
if (rc != Success) if (rc != Success)
return rc; return rc;
for (prop = dev->properties.properties; prop; prop = prop->next) rc = list_atoms(dev, &natoms, &atoms);
numProps++; if (rc != Success)
if (numProps) return rc;
if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
return(BadAlloc);
rep.repType = X_Reply; rep.repType = X_Reply;
rep.RepType = X_ListDeviceProperties; rep.RepType = X_ListDeviceProperties;
rep.length = (numProps * sizeof(Atom)) >> 2; rep.length = natoms;
rep.sequenceNumber = client->sequence; rep.sequenceNumber = client->sequence;
rep.nAtoms = numProps; rep.nAtoms = natoms;
temppAtoms = pAtoms;
for (prop = dev->properties.properties; prop; prop = prop->next)
*temppAtoms++ = prop->propertyName;
WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep); WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
if (numProps) if (natoms)
{ {
client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
xfree(pAtoms); xfree(atoms);
} }
return rc; return rc;
} }
@ -725,55 +878,29 @@ ProcXChangeDeviceProperty (ClientPtr client)
{ {
REQUEST(xChangeDevicePropertyReq); REQUEST(xChangeDevicePropertyReq);
DeviceIntPtr dev; DeviceIntPtr dev;
char format, mode;
unsigned long len; unsigned long len;
int sizeInBytes;
int totalSize; int totalSize;
int rc; int rc;
REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq); REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
UpdateCurrentTime(); 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(xChangeDevicePropertyReq)) >> 2))
return BadLength;
sizeInBytes = format>>3;
totalSize = len * sizeInBytes;
REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
rc = dixLookupDevice (&dev, stuff->deviceid, client, DixWriteAccess); rc = dixLookupDevice (&dev, stuff->deviceid, client, DixWriteAccess);
if (rc != Success) if (rc != Success)
return rc; return rc;
if (!ValidAtom(stuff->property)) rc = check_change_property(client, stuff->property, stuff->type,
{ stuff->format, stuff->mode, stuff->nUnits);
client->errorValue = stuff->property;
return(BadAtom);
}
if (!ValidAtom(stuff->type))
{
client->errorValue = stuff->type;
return(BadAtom);
}
rc = XIChangeDeviceProperty(dev, stuff->property, len = stuff->nUnits;
stuff->type, (int)format, if (len > ((0xffffffff - sizeof(xChangeDevicePropertyReq)) >> 2))
(int)mode, len, (pointer)&stuff[1], TRUE); return BadLength;
if (rc != Success) totalSize = len * (stuff->format/8);
client->errorValue = stuff->property; REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
rc = change_property(client, dev, stuff->property, stuff->type,
stuff->format, stuff->mode, len, (void*)&stuff[1]);
return rc; return rc;
} }
@ -804,12 +931,12 @@ int
ProcXGetDeviceProperty (ClientPtr client) ProcXGetDeviceProperty (ClientPtr client)
{ {
REQUEST(xGetDevicePropertyReq); REQUEST(xGetDevicePropertyReq);
XIPropertyPtr prop, *prev;
XIPropertyValuePtr prop_value;
unsigned long n, len, ind;
DeviceIntPtr dev; DeviceIntPtr dev;
int length;
int rc, format, nitems, bytes_after;
char *data;
Atom type;
xGetDevicePropertyReply reply; xGetDevicePropertyReply reply;
int rc;
REQUEST_SIZE_MATCH(xGetDevicePropertyReq); REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
if (stuff->delete) if (stuff->delete)
@ -820,121 +947,74 @@ ProcXGetDeviceProperty (ClientPtr client)
if (rc != Success) if (rc != Success)
return rc; return rc;
if (!ValidAtom(stuff->property)) rc = get_property(client, dev, stuff->property, stuff->type,
{ stuff->delete, stuff->longOffset, stuff->longLength,
client->errorValue = stuff->property; &bytes_after, &type, &format, &nitems, &length, &data);
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.properties; (prop = *prev); prev = &prop->next) if (rc != Success)
if (prop->propertyName == stuff->property) return rc;
break;
reply.repType = X_Reply; reply.repType = X_Reply;
reply.RepType = X_GetDeviceProperty; reply.RepType = X_GetDeviceProperty;
reply.sequenceNumber = client->sequence; reply.sequenceNumber = client->sequence;
reply.deviceid = dev->id; reply.deviceid = dev->id;
if (!prop) reply.nItems = nitems;
{ reply.format = format;
reply.nItems = 0; reply.bytesAfter = bytes_after;
reply.length = 0; reply.propertyType = type;
reply.bytesAfter = 0; reply.length = (length + 3) >> 2;
reply.propertyType = None;
reply.format = 0;
WriteReplyToClient(client, sizeof(xGetDevicePropertyReply), &reply);
return(client->noClientException);
}
rc = XIGetDeviceProperty(dev, stuff->property, &prop_value);
if (rc != Success)
{
client->errorValue = stuff->property;
return rc;
}
/* 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)) if (stuff->delete && (reply.bytesAfter == 0))
{ {
devicePropertyNotify event; devicePropertyNotify event;
xXIPropertyEvent xi2;
event.type = DevicePropertyNotify; event.type = DevicePropertyNotify;
event.deviceid = dev->id; event.deviceid = dev->id;
event.state = PropertyDelete; event.state = PropertyDelete;
event.atom = prop->propertyName; event.atom = stuff->property;
event.time = currentTime.milliseconds; event.time = currentTime.milliseconds;
SendEventToAllWindows(dev, DevicePropertyNotifyMask, SendEventToAllWindows(dev, DevicePropertyNotifyMask,
(xEvent*)&event, 1); (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 = stuff->property;
xi2.what = XIPropertyDeleted;
SendEventToAllWindows(dev, XI_PropertyEventMask, (xEvent*)&xi2, 1);
} }
WriteReplyToClient(client, sizeof(xGenericReply), &reply); WriteReplyToClient(client, sizeof(xGenericReply), &reply);
if (len)
if (length)
{ {
switch (reply.format) { switch (reply.format) {
case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
} }
WriteSwappedDataToClient(client, len, WriteSwappedDataToClient(client, length, data);
(char *)prop_value->data + ind);
} }
/* delete the Property */
if (stuff->delete && (reply.bytesAfter == 0)) if (stuff->delete && (reply.bytesAfter == 0))
{ /* delete the Property */ {
*prev = prop->next; XIPropertyPtr prop, *prev;
XIDestroyDeviceProperty (prop); for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
{
if (prop->propertyName == stuff->property)
{
*prev = prop->next;
XIDestroyDeviceProperty(prop);
break;
}
}
} }
return(client->noClientException); return Success;
} }