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:
parent
f6f1e41706
commit
9935bec6e8
368
Xi/xiproperty.c
368
Xi/xiproperty.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue