diff --git a/dix/property.c b/dix/property.c index d0bd18f35..872658b5e 100644 --- a/dix/property.c +++ b/dix/property.c @@ -430,7 +430,7 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property, int DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName) { - PropertyPtr pProp, prevProp; + PropertyPtr pProp; int rc; rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess); @@ -438,18 +438,9 @@ DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName) return Success; /* Succeed if property does not exist */ if (rc == Success) { - if (pWin->properties == pProp) { - /* Takes care of head */ - if (!(pWin->properties = pProp->next)) - CheckWindowOptionalNeed(pWin); - } - else { - /* Need to traverse to find the previous element */ - prevProp = pWin->properties; - while (prevProp->next != pProp) - prevProp = prevProp->next; - prevProp->next = pProp->next; - } + dixPropertyUnlinkPtr(&pWin->properties, pProp); + if (!pWin->properties) + CheckWindowOptionalNeed(pWin); deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp); notifyVRRMode(client, pWin, PropertyDelete, pProp); @@ -461,16 +452,13 @@ DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName) void DeleteAllWindowProperties(WindowPtr pWin) { - PropertyPtr pProp = pWin->properties; + PropertyPtr pProp; - while (pProp) { + while ((pProp = pWin->properties)) { deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp); - PropertyPtr pNextProp = pProp->next; + dixPropertyUnlinkPtr(&pWin->properties, pProp); dixPropertyFree(pProp); - pProp = pNextProp; } - - pWin->properties = NULL; } /***************** diff --git a/dix/property_list.c b/dix/property_list.c index 9a7a2fc8b..b46a30a15 100644 --- a/dix/property_list.c +++ b/dix/property_list.c @@ -7,6 +7,7 @@ #include "dix/property_priv.h" #include "include/privates.h" #include "include/propertyst.h" +#include "os/bug_priv.h" void dixPropertyFree(PropertyPtr pr) { @@ -41,3 +42,35 @@ PropertyPtr dixPropertyCreate(Atom type, Atom name, int format, size_t len, return pProp; } + +PropertyPtr dixPropertyUnlinkPtr(PropertyPtr *list, PropertyPtr prop) +{ + BUG_RETURN_VAL(!list, NULL); + + if ((!prop) || (!(*list))) // nothing to do + return NULL; + + PropertyPtr walk = *list; + + // remove from head + if (walk == prop) { + *list = prop->next; + walk->next = NULL; + return prop; + } + + // walk the list to find it + while (walk->next && walk->next != prop) { + walk = walk->next; + } + + // didn't find it + if (!walk->next) + return NULL; + + // unlink the element + walk->next = walk->next->next; + prop->next = NULL; + + return prop; +} diff --git a/dix/property_priv.h b/dix/property_priv.h index dad4a07a7..a5833a5d2 100644 --- a/dix/property_priv.h +++ b/dix/property_priv.h @@ -123,4 +123,14 @@ void dixPropertyFree(PropertyPtr pProp); PropertyPtr dixPropertyCreate(Atom type, Atom name, int format, size_t len, const void *value); +/* + * Unlink a property structure from a property list. The given property's next + * pointer is also cleared. The property structure itself is NOT destroyed. + * + * @param list pointer to the property list head (NULL on empty list) + * @param prop pointer to the property to unlink. + * @return on success, pointer to the property, NULL if not found in list + */ +PropertyPtr dixPropertyUnlinkPtr(PropertyPtr *list, PropertyPtr prop); + #endif /* _XSERVER_PROPERTY_PRIV_H */