dix: Refactoring of property code to allow for polyinstantiation.

Introduces dixLookupProperty() API.
This commit is contained in:
Eamon Walsh 2008-02-29 16:16:12 -05:00 committed by Eamon Walsh
parent c0e1959f28
commit d5715f7bea
3 changed files with 112 additions and 117 deletions

View File

@ -63,11 +63,10 @@ SOFTWARE.
/***************************************************************** /*****************************************************************
* Property Stuff * Property Stuff
* *
* ChangeProperty, DeleteProperty, GetProperties, * dixLookupProperty, dixChangeProperty, DeleteProperty
* ListProperties
* *
* Properties below to windows. A allocate slots each time * Properties belong to windows. The list of properties should not be
* a property is added. No fancy searching done. * traversed directly. Instead, use the three functions listed above.
* *
*****************************************************************/ *****************************************************************/
@ -91,17 +90,22 @@ PrintPropertys(WindowPtr pWin)
} }
#endif #endif
static _X_INLINE PropertyPtr _X_EXPORT int
FindProperty(WindowPtr pWin, Atom propertyName) dixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName,
ClientPtr client, Mask access_mode)
{ {
PropertyPtr pProp = wUserProps(pWin); PropertyPtr pProp;
while (pProp) int rc = BadMatch;
{ client->errorValue = propertyName;
for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
if (pProp->propertyName == propertyName) if (pProp->propertyName == propertyName)
break; break;
pProp = pProp->next;
} if (pProp)
return pProp; rc = XaceHookPropertyAccess(client, pWin, pProp, access_mode);
*result = pProp;
return rc;
} }
static void static void
@ -125,65 +129,69 @@ ProcRotateProperties(ClientPtr client)
WindowPtr pWin; WindowPtr pWin;
Atom * atoms; Atom * atoms;
PropertyPtr * props; /* array of pointer */ PropertyPtr * props; /* array of pointer */
PropertyPtr pProp; PropertyPtr pProp, saved;
REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
UpdateCurrentTime(); UpdateCurrentTime();
rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
if (rc != Success) if (rc != Success || stuff->nAtoms <= 0)
return rc; return rc;
if (!stuff->nAtoms)
return(Success);
atoms = (Atom *) & stuff[1]; atoms = (Atom *) & stuff[1];
props = (PropertyPtr *)xalloc(stuff->nAtoms * sizeof(PropertyPtr)); props = (PropertyPtr *)xalloc(stuff->nAtoms * sizeof(PropertyPtr));
if (!props) saved = (PropertyPtr)xalloc(stuff->nAtoms * sizeof(PropertyRec));
return(BadAlloc); if (!props || !saved) {
rc = BadAlloc;
goto out;
}
for (i = 0; i < stuff->nAtoms; i++) for (i = 0; i < stuff->nAtoms; i++)
{ {
if (!ValidAtom(atoms[i])) { if (!ValidAtom(atoms[i])) {
xfree(props); rc = BadAtom;
client->errorValue = atoms[i]; client->errorValue = atoms[i];
return BadAtom; goto out;
} }
for (j = i + 1; j < stuff->nAtoms; j++) for (j = i + 1; j < stuff->nAtoms; j++)
if (atoms[j] == atoms[i]) if (atoms[j] == atoms[i])
{ {
xfree(props); rc = BadMatch;
return BadMatch; goto out;
} }
pProp = FindProperty(pWin, atoms[i]);
if (!pProp) { rc = dixLookupProperty(&pProp, pWin, atoms[i], client,
xfree(props);
return BadMatch;
}
rc = XaceHookPropertyAccess(client, pWin, pProp,
DixReadAccess|DixWriteAccess); DixReadAccess|DixWriteAccess);
if (rc != Success) { if (rc != Success)
xfree(props); goto out;
client->errorValue = atoms[i];
return rc;
}
props[i] = pProp; props[i] = pProp;
saved[i] = *pProp;
} }
delta = stuff->nPositions; delta = stuff->nPositions;
/* If the rotation is a complete 360 degrees, then moving the properties /* If the rotation is a complete 360 degrees, then moving the properties
around and generating PropertyNotify events should be skipped. */ around and generating PropertyNotify events should be skipped. */
if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) if (abs(delta) % stuff->nAtoms)
{ {
while (delta < 0) /* faster if abs value is small */ while (delta < 0) /* faster if abs value is small */
delta += stuff->nAtoms; delta += stuff->nAtoms;
for (i = 0; i < stuff->nAtoms; i++) for (i = 0; i < stuff->nAtoms; i++)
{ {
deliverPropertyNotifyEvent(pWin, PropertyNewValue, j = (i + delta) % stuff->nAtoms;
props[i]->propertyName); deliverPropertyNotifyEvent(pWin, PropertyNewValue, atoms[i]);
props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; /* Preserve name and devPrivates */
props[j]->type = saved[i].type;
props[j]->format = saved[i].format;
props[j]->size = saved[i].size;
props[j]->data = saved[i].data;
} }
} }
out:
xfree(saved);
xfree(props); xfree(props);
return Success; return rc;
} }
int int
@ -253,9 +261,9 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
totalSize = len * sizeInBytes; totalSize = len * sizeInBytes;
/* first see if property already exists */ /* first see if property already exists */
pProp = FindProperty(pWin, property); rc = dixLookupProperty(&pProp, pWin, property, pClient, DixWriteAccess);
if (!pProp) /* just add to list */ if (rc == BadMatch) /* just add to list */
{ {
if (!pWin->optional && !MakeWindowOptional (pWin)) if (!pWin->optional && !MakeWindowOptional (pWin))
return(BadAlloc); return(BadAlloc);
@ -287,13 +295,8 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
pProp->next = pWin->optional->userProps; pProp->next = pWin->optional->userProps;
pWin->optional->userProps = pProp; pWin->optional->userProps = pProp;
} }
else else if (rc == Success)
{ {
rc = XaceHookPropertyAccess(pClient, pWin, pProp, DixWriteAccess);
if (rc != Success) {
pClient->errorValue = property;
return rc;
}
/* To append or prepend to a property the request format and type /* To append or prepend to a property the request format and type
must match those of the already defined property. The must match those of the already defined property. The
existing format and type are irrelevant when using the mode existing format and type are irrelevant when using the mode
@ -347,6 +350,8 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
pProp->size += len; pProp->size += len;
} }
} }
else
return rc;
if (sendevent) if (sendevent)
deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName); deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName);
@ -369,37 +374,29 @@ DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
PropertyPtr pProp, prevProp; PropertyPtr pProp, prevProp;
int rc; int rc;
if (!(pProp = wUserProps (pWin))) rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
return(Success); if (rc == BadMatch)
prevProp = (PropertyPtr)NULL; return Success; /* Succeed if property does not exist */
while (pProp)
{
if (pProp->propertyName == propName)
break;
prevProp = pProp;
pProp = pProp->next;
}
if (pProp)
{
rc = XaceHookPropertyAccess(client, pWin, pProp, DixDestroyAccess);
if (rc != Success)
return rc;
if (prevProp == (PropertyPtr)NULL) /* takes care of head */ if (rc == Success) {
{ if (pWin->optional->userProps == pProp) {
/* Takes care of head */
if (!(pWin->optional->userProps = pProp->next)) if (!(pWin->optional->userProps = pProp->next))
CheckWindowOptionalNeed (pWin); CheckWindowOptionalNeed (pWin);
} } else {
else /* Need to traverse to find the previous element */
{ prevProp = pWin->optional->userProps;
while (prevProp->next != pProp)
prevProp = prevProp->next;
prevProp->next = pProp->next; prevProp->next = pProp->next;
} }
deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName); deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
dixFreePrivates(pProp->devPrivates); dixFreePrivates(pProp->devPrivates);
xfree(pProp->data); xfree(pProp->data);
xfree(pProp); xfree(pProp);
} }
return(Success); return rc;
} }
void void
@ -453,15 +450,16 @@ ProcGetProperty(ClientPtr client)
int rc; int rc;
WindowPtr pWin; WindowPtr pWin;
xGetPropertyReply reply; xGetPropertyReply reply;
Mask access_mode = DixGetPropAccess; Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
REQUEST(xGetPropertyReq); REQUEST(xGetPropertyReq);
REQUEST_SIZE_MATCH(xGetPropertyReq); REQUEST_SIZE_MATCH(xGetPropertyReq);
if (stuff->delete) { if (stuff->delete) {
UpdateCurrentTime(); UpdateCurrentTime();
access_mode |= DixSetPropAccess; win_mode |= DixSetPropAccess;
prop_mode |= DixDestroyAccess;
} }
rc = dixLookupWindow(&pWin, stuff->window, client, access_mode); rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
if (rc != Success) if (rc != Success)
return rc; return rc;
@ -481,30 +479,14 @@ ProcGetProperty(ClientPtr client)
return(BadAtom); return(BadAtom);
} }
pProp = wUserProps (pWin);
prevProp = (PropertyPtr)NULL;
while (pProp)
{
if (pProp->propertyName == stuff->property)
break;
prevProp = pProp;
pProp = pProp->next;
}
reply.type = X_Reply; reply.type = X_Reply;
reply.sequenceNumber = client->sequence; reply.sequenceNumber = client->sequence;
if (!pProp)
rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
if (rc == BadMatch)
return NullPropertyReply(client, None, 0, &reply); return NullPropertyReply(client, None, 0, &reply);
else if (rc != Success)
access_mode = DixReadAccess;
if (stuff->delete)
access_mode |= DixDestroyAccess;
rc = XaceHookPropertyAccess(client, pWin, pProp, access_mode);
if (rc != Success) {
client->errorValue = stuff->property;
return rc; return rc;
}
/* If the request type and actual type don't match. Return the /* If the request type and actual type don't match. Return the
property information, but not the data. */ property information, but not the data. */
@ -560,15 +542,20 @@ ProcGetProperty(ClientPtr client)
(char *)pProp->data + ind); (char *)pProp->data + ind);
} }
if (stuff->delete && (reply.bytesAfter == 0)) if (stuff->delete && (reply.bytesAfter == 0)) {
{ /* delete the Property */ /* Delete the Property */
if (prevProp == (PropertyPtr)NULL) /* takes care of head */ if (pWin->optional->userProps == pProp) {
{ /* Takes care of head */
if (!(pWin->optional->userProps = pProp->next)) if (!(pWin->optional->userProps = pProp->next))
CheckWindowOptionalNeed (pWin); CheckWindowOptionalNeed (pWin);
} } else {
else /* Need to traverse to find the previous element */
prevProp = pWin->optional->userProps;
while (prevProp->next != pProp)
prevProp = prevProp->next;
prevProp->next = pProp->next; prevProp->next = pProp->next;
}
dixFreePrivates(pProp->devPrivates); dixFreePrivates(pProp->devPrivates);
xfree(pProp->data); xfree(pProp->data);
xfree(pProp); xfree(pProp);
@ -583,7 +570,7 @@ ProcListProperties(ClientPtr client)
xListPropertiesReply xlpr; xListPropertiesReply xlpr;
int rc, numProps = 0; int rc, numProps = 0;
WindowPtr pWin; WindowPtr pWin;
PropertyPtr pProp; PropertyPtr pProp, realProp;
REQUEST(xResourceReq); REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq); REQUEST_SIZE_MATCH(xResourceReq);
@ -591,34 +578,34 @@ ProcListProperties(ClientPtr client)
if (rc != Success) if (rc != Success)
return rc; return rc;
pProp = wUserProps (pWin); for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
while (pProp) numProps++;
{
pProp = pProp->next; if (numProps && !(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
return BadAlloc;
numProps = 0;
temppAtoms = pAtoms;
for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
realProp = pProp;
rc = XaceHookPropertyAccess(client, pWin, pProp, DixGetAttrAccess);
if (rc == Success && realProp == pProp) {
*temppAtoms++ = pProp->propertyName;
numProps++; numProps++;
} }
if (numProps) }
if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
return(BadAlloc);
xlpr.type = X_Reply; xlpr.type = X_Reply;
xlpr.nProperties = numProps; xlpr.nProperties = numProps;
xlpr.length = (numProps * sizeof(Atom)) >> 2; xlpr.length = (numProps * sizeof(Atom)) >> 2;
xlpr.sequenceNumber = client->sequence; xlpr.sequenceNumber = client->sequence;
pProp = wUserProps (pWin);
temppAtoms = pAtoms;
while (pProp)
{
*temppAtoms++ = pProp->propertyName;
pProp = pProp->next;
}
WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
if (numProps) if (numProps)
{ {
client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
xfree(pAtoms);
} }
xfree(pAtoms);
return(client->noClientException); return(client->noClientException);
} }

View File

@ -193,6 +193,7 @@ _X_HIDDEN void *dixLookupTab[] = {
SYMFUNC(XineramaGetCursorScreen) SYMFUNC(XineramaGetCursorScreen)
#endif #endif
/* property.c */ /* property.c */
SYMFUNC(dixLookupProperty)
SYMFUNC(ChangeWindowProperty) SYMFUNC(ChangeWindowProperty)
SYMFUNC(dixChangeWindowProperty) SYMFUNC(dixChangeWindowProperty)
/* extension.c */ /* extension.c */

View File

@ -52,6 +52,13 @@ SOFTWARE.
typedef struct _Property *PropertyPtr; typedef struct _Property *PropertyPtr;
extern int dixLookupProperty(
PropertyPtr * /*result*/,
WindowPtr /*pWin*/,
Atom /*proprty*/,
ClientPtr /*pClient*/,
Mask /*access_mode*/);
extern int dixChangeWindowProperty( extern int dixChangeWindowProperty(
ClientPtr /*pClient*/, ClientPtr /*pClient*/,
WindowPtr /*pWin*/, WindowPtr /*pWin*/,