diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2009-05-07 09:43:56 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2009-05-08 14:33:23 +1000 |
commit | 9935bec6e860cba9a3cc5baadd372ddb89d72ef0 (patch) | |
tree | 81561a73ab9acd3db05db5af0eeda8d3f6c3732a /Xi/xiproperty.c | |
parent | f6f1e417063d2d61d65731a7e3ebca3ec2bdaacc (diff) |
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.
Diffstat (limited to 'Xi/xiproperty.c')
-rw-r--r-- | Xi/xiproperty.c | 368 |
1 files changed, 224 insertions, 144 deletions
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index 7e20e0320..772571504 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -169,6 +169,165 @@ static struct dev_properties 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 * to the DIX. @@ -681,11 +840,10 @@ XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable) int ProcXListDeviceProperties (ClientPtr client) { - Atom *pAtoms = NULL, *temppAtoms; + Atom *atoms; xListDevicePropertiesReply rep; - int numProps = 0; + int natoms; DeviceIntPtr dev; - XIPropertyPtr prop; int rc = Success; REQUEST(xListDevicePropertiesReq); @@ -695,27 +853,22 @@ ProcXListDeviceProperties (ClientPtr client) if (rc != Success) return rc; - for (prop = dev->properties.properties; prop; prop = prop->next) - numProps++; - if (numProps) - if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom)))) - return(BadAlloc); + rc = list_atoms(dev, &natoms, &atoms); + if (rc != Success) + return rc; rep.repType = X_Reply; rep.RepType = X_ListDeviceProperties; - rep.length = (numProps * sizeof(Atom)) >> 2; + rep.length = natoms; rep.sequenceNumber = client->sequence; - rep.nAtoms = numProps; - temppAtoms = pAtoms; - for (prop = dev->properties.properties; prop; prop = prop->next) - *temppAtoms++ = prop->propertyName; + rep.nAtoms = natoms; WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep); - if (numProps) + if (natoms) { client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; - WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); - xfree(pAtoms); + WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms); + xfree(atoms); } return rc; } @@ -725,55 +878,29 @@ 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(xChangeDevicePropertyReq)) >> 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 = check_change_property(client, stuff->property, stuff->type, + stuff->format, stuff->mode, stuff->nUnits); + + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangeDevicePropertyReq)) >> 2)) + return BadLength; - rc = XIChangeDeviceProperty(dev, stuff->property, - stuff->type, (int)format, - (int)mode, len, (pointer)&stuff[1], TRUE); + totalSize = len * (stuff->format/8); + REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize); - if (rc != Success) - client->errorValue = stuff->property; + rc = change_property(client, dev, stuff->property, stuff->type, + stuff->format, stuff->mode, len, (void*)&stuff[1]); return rc; } @@ -804,12 +931,12 @@ int ProcXGetDeviceProperty (ClientPtr client) { REQUEST(xGetDevicePropertyReq); - XIPropertyPtr prop, *prev; - XIPropertyValuePtr prop_value; - unsigned long n, len, ind; DeviceIntPtr dev; + int length; + int rc, format, nitems, bytes_after; + char *data; + Atom type; xGetDevicePropertyReply reply; - int rc; REQUEST_SIZE_MATCH(xGetDevicePropertyReq); if (stuff->delete) @@ -820,121 +947,74 @@ ProcXGetDeviceProperty (ClientPtr client) 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); - } + rc = get_property(client, dev, stuff->property, stuff->type, + stuff->delete, stuff->longOffset, stuff->longLength, + &bytes_after, &type, &format, &nitems, &length, &data); - for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next) - if (prop->propertyName == stuff->property) - break; + if (rc != Success) + return rc; reply.repType = X_Reply; reply.RepType = X_GetDeviceProperty; reply.sequenceNumber = client->sequence; reply.deviceid = dev->id; - 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); - } - - 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; + reply.nItems = nitems; + reply.format = format; + reply.bytesAfter = bytes_after; + reply.propertyType = type; + reply.length = (length + 3) >> 2; if (stuff->delete && (reply.bytesAfter == 0)) { devicePropertyNotify event; + xXIPropertyEvent xi2; event.type = DevicePropertyNotify; event.deviceid = dev->id; event.state = PropertyDelete; - event.atom = prop->propertyName; + event.atom = stuff->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 = stuff->property; + xi2.what = XIPropertyDeleted; + SendEventToAllWindows(dev, XI_PropertyEventMask, (xEvent*)&xi2, 1); } WriteReplyToClient(client, sizeof(xGenericReply), &reply); - if (len) + + 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; + 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); + WriteSwappedDataToClient(client, length, data); } + /* delete the Property */ if (stuff->delete && (reply.bytesAfter == 0)) - { /* delete the Property */ - *prev = prop->next; - XIDestroyDeviceProperty (prop); + { + 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(client->noClientException); + return Success; } |