diff options
author | marha <marha@users.sourceforge.net> | 2010-02-14 21:53:27 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2010-02-14 21:53:27 +0000 |
commit | bdebed13fbe3b1064f9bca04b34643b2587b5304 (patch) | |
tree | a0ea44088ab60dfeddc70ecdb0c8811f3dc170b0 /xorg-server/randr/rrproperty.c | |
parent | 8d38172d866775594af3185ae3fbd8d750677650 (diff) | |
download | vcxsrv-bdebed13fbe3b1064f9bca04b34643b2587b5304.tar.gz vcxsrv-bdebed13fbe3b1064f9bca04b34643b2587b5304.tar.bz2 vcxsrv-bdebed13fbe3b1064f9bca04b34643b2587b5304.zip |
git update 14-2-2010
Diffstat (limited to 'xorg-server/randr/rrproperty.c')
-rw-r--r-- | xorg-server/randr/rrproperty.c | 1521 |
1 files changed, 758 insertions, 763 deletions
diff --git a/xorg-server/randr/rrproperty.c b/xorg-server/randr/rrproperty.c index 146facbe1..96e27a9dc 100644 --- a/xorg-server/randr/rrproperty.c +++ b/xorg-server/randr/rrproperty.c @@ -1,763 +1,758 @@ -/* - * Copyright © 2006 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "randrstr.h" -#include "propertyst.h" -#include "swaprep.h" - -static int -DeliverPropertyEvent(WindowPtr pWin, void *value) -{ - xRROutputPropertyNotifyEvent *event = value; - RREventPtr *pHead, pRREvent; - ClientPtr client; - - dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - RREventType, serverClient, DixReadAccess); - if (!pHead) - return WT_WALKCHILDREN; - - for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) - { - client = pRREvent->client; - if (client == serverClient || client->clientGone) - continue; - - if (!(pRREvent->mask & RROutputPropertyNotifyMask)) - continue; - - event->sequenceNumber = client->sequence; - event->window = pRREvent->window->drawable.id; - if (client->swapped) { - int n; - swaps(&event->sequenceNumber, n); - swapl(&event->window, n); - } - WriteEventsToClient(pRREvent->client, 1, (xEvent *)event); - } - - return WT_WALKCHILDREN; -} - -static void RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event) -{ - if (!(dispatchException & (DE_RESET | DE_TERMINATE))) - WalkTree(pScreen, DeliverPropertyEvent, event); -} - -void -RRDeleteAllOutputProperties (RROutputPtr output) -{ - RRPropertyPtr prop, next; - xRROutputPropertyNotifyEvent event; - - for (prop = output->properties; prop; prop = next) - { - next = prop->next; - event.type = RREventBase + RRNotify; - event.subCode = RRNotify_OutputProperty; - event.output = output->id; - event.state = PropertyDelete; - event.atom = prop->propertyName; - event.timestamp = currentTime.milliseconds; - RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event); - if (prop->current.data) - xfree(prop->current.data); - if (prop->pending.data) - xfree(prop->pending.data); - xfree(prop); - } -} - -static void -RRInitOutputPropertyValue (RRPropertyValuePtr property_value) -{ - property_value->type = None; - property_value->format = 0; - property_value->size = 0; - property_value->data = NULL; -} - -static RRPropertyPtr -RRCreateOutputProperty (Atom property) -{ - RRPropertyPtr prop; - - prop = (RRPropertyPtr)xalloc(sizeof(RRPropertyRec)); - if (!prop) - return NULL; - prop->next = NULL; - prop->propertyName = property; - prop->is_pending = FALSE; - prop->range = FALSE; - prop->immutable = FALSE; - prop->num_valid = 0; - prop->valid_values = NULL; - RRInitOutputPropertyValue (&prop->current); - RRInitOutputPropertyValue (&prop->pending); - return prop; -} - -static void -RRDestroyOutputProperty (RRPropertyPtr prop) -{ - if (prop->valid_values) - xfree (prop->valid_values); - if (prop->current.data) - xfree(prop->current.data); - if (prop->pending.data) - xfree(prop->pending.data); - if (prop->valid_values) - xfree(prop->valid_values); - xfree(prop); -} - -void -RRDeleteOutputProperty (RROutputPtr output, Atom property) -{ - RRPropertyPtr prop, *prev; - xRROutputPropertyNotifyEvent event; - - for (prev = &output->properties; (prop = *prev); prev = &(prop->next)) - if (prop->propertyName == property) - break; - if (prop) - { - *prev = prop->next; - event.type = RREventBase + RRNotify; - event.subCode = RRNotify_OutputProperty; - event.output = output->id; - event.state = PropertyDelete; - event.atom = prop->propertyName; - event.timestamp = currentTime.milliseconds; - RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event); - RRDestroyOutputProperty (prop); - } -} - -int -RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, - int format, int mode, unsigned long len, - pointer value, Bool sendevent, Bool pending) -{ - RRPropertyPtr prop; - xRROutputPropertyNotifyEvent event; - rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen); - int size_in_bytes; - int total_size; - unsigned long total_len; - RRPropertyValuePtr prop_value; - RRPropertyValueRec new_value; - Bool add = FALSE; - - size_in_bytes = format >> 3; - - /* first see if property already exists */ - prop = RRQueryOutputProperty (output, property); - if (!prop) /* just add to list */ - { - prop = RRCreateOutputProperty (property); - if (!prop) - return(BadAlloc); - add = TRUE; - mode = PropModeReplace; - } - if (pending && prop->is_pending) - prop_value = &prop->pending; - else - prop_value = &prop->current; - - /* To append or prepend to a property the request format and type - must match those of the already defined property. The - existing format and type are irrelevant when using the mode - "PropModeReplace" since they will be written over. */ - - if ((format != prop_value->format) && (mode != PropModeReplace)) - return(BadMatch); - if ((prop_value->type != type) && (mode != PropModeReplace)) - return(BadMatch); - new_value = *prop_value; - if (mode == PropModeReplace) - total_len = len; - else - total_len = prop_value->size + len; - - if (mode == PropModeReplace || len > 0) - { - pointer new_data = NULL, old_data = NULL; - - total_size = total_len * size_in_bytes; - new_value.data = (pointer)xalloc (total_size); - if (!new_value.data && total_size) - { - if (add) - RRDestroyOutputProperty (prop); - return BadAlloc; - } - new_value.size = len; - new_value.type = type; - new_value.format = format; - - switch (mode) { - case PropModeReplace: - new_data = new_value.data; - old_data = NULL; - break; - case PropModeAppend: - new_data = (pointer) (((char *) new_value.data) + - (prop_value->size * size_in_bytes)); - old_data = new_value.data; - break; - case PropModePrepend: - new_data = new_value.data; - old_data = (pointer) (((char *) new_value.data) + - (prop_value->size * size_in_bytes)); - break; - } - if (new_data) - memcpy ((char *) new_data, (char *) value, len * size_in_bytes); - if (old_data) - memcpy ((char *) old_data, (char *) prop_value->data, - prop_value->size * size_in_bytes); - - if (pending && pScrPriv->rrOutputSetProperty && - !pScrPriv->rrOutputSetProperty(output->pScreen, output, - prop->propertyName, &new_value)) - { - if (new_value.data) - xfree (new_value.data); - return (BadValue); - } - if (prop_value->data) - xfree (prop_value->data); - *prop_value = new_value; - } - - else if (len == 0) - { - /* do nothing */ - } - - if (add) - { - prop->next = output->properties; - output->properties = prop; - } - - if (pending && prop->is_pending) - output->pendingProperties = TRUE; - - if (sendevent) - { - event.type = RREventBase + RRNotify; - event.subCode = RRNotify_OutputProperty; - event.output = output->id; - event.state = PropertyNewValue; - event.atom = prop->propertyName; - event.timestamp = currentTime.milliseconds; - RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event); - } - return(Success); -} - -Bool -RRPostPendingProperties (RROutputPtr output) -{ - RRPropertyValuePtr pending_value; - RRPropertyValuePtr current_value; - RRPropertyPtr property; - Bool ret = TRUE; - - if (!output->pendingProperties) - return TRUE; - - output->pendingProperties = FALSE; - for (property = output->properties; property; property = property->next) - { - /* Skip non-pending properties */ - if (!property->is_pending) - continue; - - pending_value = &property->pending; - current_value = &property->current; - - /* - * If the pending and current values are equal, don't mark it - * as changed (which would deliver an event) - */ - if (pending_value->type == current_value->type && - pending_value->format == current_value->format && - pending_value->size == current_value->size && - !memcmp (pending_value->data, current_value->data, - pending_value->size)) - continue; - - if (RRChangeOutputProperty (output, property->propertyName, - pending_value->type, pending_value->format, - PropModeReplace, pending_value->size, - pending_value->data, TRUE, - FALSE) != Success) - ret = FALSE; - } - return ret; -} - -RRPropertyPtr -RRQueryOutputProperty (RROutputPtr output, Atom property) -{ - RRPropertyPtr prop; - - for (prop = output->properties; prop; prop = prop->next) - if (prop->propertyName == property) - return prop; - return NULL; -} - -RRPropertyValuePtr -RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending) -{ - RRPropertyPtr prop = RRQueryOutputProperty (output, property); - rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen); - - if (!prop) - return NULL; - if (pending && prop->is_pending) - return &prop->pending; - else { -#if RANDR_13_INTERFACE - /* If we can, try to update the property value first */ - if (pScrPriv->rrOutputGetProperty) - pScrPriv->rrOutputGetProperty(output->pScreen, output, - prop->propertyName); -#endif - return &prop->current; - } -} - -int -RRConfigureOutputProperty (RROutputPtr output, Atom property, - Bool pending, Bool range, Bool immutable, - int num_values, INT32 *values) -{ - RRPropertyPtr prop = RRQueryOutputProperty (output, property); - Bool add = FALSE; - INT32 *new_values; - - if (!prop) - { - prop = RRCreateOutputProperty (property); - if (!prop) - return(BadAlloc); - add = TRUE; - } else if (prop->immutable && !immutable) - return(BadAccess); - - /* - * ranges must have even number of values - */ - if (range && (num_values & 1)) - return BadMatch; - - new_values = xalloc (num_values * sizeof (INT32)); - if (!new_values && num_values) - return BadAlloc; - if (num_values) - memcpy (new_values, values, num_values * sizeof (INT32)); - - /* - * Property moving from pending to non-pending - * loses any pending values - */ - if (prop->is_pending && !pending) - { - if (prop->pending.data) - xfree (prop->pending.data); - RRInitOutputPropertyValue (&prop->pending); - } - - prop->is_pending = pending; - prop->range = range; - prop->immutable = immutable; - prop->num_valid = num_values; - if (prop->valid_values) - xfree (prop->valid_values); - prop->valid_values = new_values; - - if (add) { - prop->next = output->properties; - output->properties = prop; - } - - return Success; -} - -int -ProcRRListOutputProperties (ClientPtr client) -{ - REQUEST(xRRListOutputPropertiesReq); - Atom *pAtoms = NULL, *temppAtoms; - xRRListOutputPropertiesReply rep; - int numProps = 0; - RROutputPtr output; - RRPropertyPtr prop; - - REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq); - - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - - for (prop = output->properties; prop; prop = prop->next) - numProps++; - if (numProps) - if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom)))) - return(BadAlloc); - - rep.type = X_Reply; - rep.length = bytes_to_int32(numProps * sizeof(Atom)); - rep.sequenceNumber = client->sequence; - rep.nAtoms = numProps; - if (client->swapped) - { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swaps (&rep.nAtoms, n); - } - temppAtoms = pAtoms; - for (prop = output->properties; prop; prop = prop->next) - *temppAtoms++ = prop->propertyName; - - WriteToClient(client, sizeof(xRRListOutputPropertiesReply), (char*)&rep); - if (numProps) - { - client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; - WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); - xfree(pAtoms); - } - return(client->noClientException); -} - -int -ProcRRQueryOutputProperty (ClientPtr client) -{ - REQUEST(xRRQueryOutputPropertyReq); - xRRQueryOutputPropertyReply rep; - RROutputPtr output; - RRPropertyPtr prop; - char *extra = NULL; - - REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq); - - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - - prop = RRQueryOutputProperty (output, stuff->property); - if (!prop) - return BadName; - - if (prop->num_valid) { - extra = xalloc(prop->num_valid * sizeof(INT32)); - if (!extra) - return BadAlloc; - } - rep.type = X_Reply; - rep.length = prop->num_valid; - rep.sequenceNumber = client->sequence; - rep.pending = prop->is_pending; - rep.range = prop->range; - rep.immutable = prop->immutable; - if (client->swapped) - { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - } - WriteToClient (client, sizeof (xRRQueryOutputPropertyReply), (char*)&rep); - if (prop->num_valid) - { - memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32)); - client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; - WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32), - extra); - xfree(extra); - } - return(client->noClientException); -} - -int -ProcRRConfigureOutputProperty (ClientPtr client) -{ - REQUEST(xRRConfigureOutputPropertyReq); - RROutputPtr output; - int num_valid; - - REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq); - - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - - num_valid = stuff->length - bytes_to_int32(sizeof (xRRConfigureOutputPropertyReq)); - return RRConfigureOutputProperty (output, stuff->property, - stuff->pending, stuff->range, - FALSE, num_valid, - (INT32 *) (stuff + 1)); -} - -int -ProcRRChangeOutputProperty (ClientPtr client) -{ - REQUEST(xRRChangeOutputPropertyReq); - RROutputPtr output; - char format, mode; - unsigned long len; - int sizeInBytes; - int totalSize; - int err; - - REQUEST_AT_LEAST_SIZE(xRRChangeOutputPropertyReq); - 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 > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq)))) - return BadLength; - sizeInBytes = format>>3; - totalSize = len * sizeInBytes; - REQUEST_FIXED_SIZE(xRRChangeOutputPropertyReq, totalSize); - - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - - if (!ValidAtom(stuff->property)) - { - client->errorValue = stuff->property; - return(BadAtom); - } - if (!ValidAtom(stuff->type)) - { - client->errorValue = stuff->type; - return(BadAtom); - } - - err = RRChangeOutputProperty(output, stuff->property, - stuff->type, (int)format, - (int)mode, len, (pointer)&stuff[1], TRUE, TRUE); - if (err != Success) - return err; - else - return client->noClientException; -} - -int -ProcRRDeleteOutputProperty (ClientPtr client) -{ - REQUEST(xRRDeleteOutputPropertyReq); - RROutputPtr output; - - REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq); - UpdateCurrentTime(); - VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); - - if (!ValidAtom(stuff->property)) - { - client->errorValue = stuff->property; - return (BadAtom); - } - - - RRDeleteOutputProperty(output, stuff->property); - return client->noClientException; -} - -int -ProcRRGetOutputProperty (ClientPtr client) -{ - REQUEST(xRRGetOutputPropertyReq); - RRPropertyPtr prop, *prev; - RRPropertyValuePtr prop_value; - unsigned long n, len, ind; - RROutputPtr output; - xRRGetOutputPropertyReply reply; - char *extra = NULL; - - REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq); - if (stuff->delete) - UpdateCurrentTime(); - VERIFY_RR_OUTPUT(stuff->output, output, - stuff->delete ? DixWriteAccess : DixReadAccess); - - 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); - } - - for (prev = &output->properties; (prop = *prev); prev = &prop->next) - if (prop->propertyName == stuff->property) - break; - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - if (!prop) - { - reply.nItems = 0; - reply.length = 0; - reply.bytesAfter = 0; - reply.propertyType = None; - reply.format = 0; - if (client->swapped) { - int n; - - swaps(&reply.sequenceNumber, n); - swapl(&reply.length, n); - swapl(&reply.propertyType, n); - swapl(&reply.bytesAfter, n); - swapl(&reply.nItems, n); - } - WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &reply); - return(client->noClientException); - } - - if (prop->immutable && stuff->delete) - return BadAccess; - - prop_value = RRGetOutputProperty(output, stuff->property, stuff->pending); - if (!prop_value) - return BadAtom; - - /* 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; - if (client->swapped) { - int n; - - swaps(&reply.sequenceNumber, n); - swapl(&reply.length, n); - swapl(&reply.propertyType, n); - swapl(&reply.bytesAfter, n); - swapl(&reply.nItems, n); - } - WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &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); - - if (len) { - extra = xalloc(len); - if (!extra) - return BadAlloc; - } - reply.bytesAfter = n - (ind + len); - reply.format = prop_value->format; - reply.length = bytes_to_int32(len); - 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)) - { - xRROutputPropertyNotifyEvent event; - - event.type = RREventBase + RRNotify; - event.subCode = RRNotify_OutputProperty; - event.output = output->id; - event.state = PropertyDelete; - event.atom = prop->propertyName; - event.timestamp = currentTime.milliseconds; - RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event); - } - - if (client->swapped) { - int n; - - swaps(&reply.sequenceNumber, n); - swapl(&reply.length, n); - swapl(&reply.propertyType, n); - swapl(&reply.bytesAfter, n); - swapl(&reply.nItems, n); - } - WriteToClient(client, sizeof(xGenericReply), &reply); - if (len) - { - memcpy(extra, (char *)prop_value->data + ind, len); - switch (reply.format) { - case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; - case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; - default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; - } - WriteSwappedDataToClient(client, len, - extra); - xfree(extra); - } - - if (stuff->delete && (reply.bytesAfter == 0)) - { /* delete the Property */ - *prev = prop->next; - RRDestroyOutputProperty (prop); - } - return(client->noClientException); -} - +/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+#include "propertyst.h"
+#include "swaprep.h"
+
+static int
+DeliverPropertyEvent(WindowPtr pWin, void *value)
+{
+ xRROutputPropertyNotifyEvent *event = value;
+ RREventPtr *pHead, pRREvent;
+ ClientPtr client;
+
+ dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
+ RREventType, serverClient, DixReadAccess);
+ if (!pHead)
+ return WT_WALKCHILDREN;
+
+ for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
+ {
+ client = pRREvent->client;
+ if (client == serverClient || client->clientGone)
+ continue;
+
+ if (!(pRREvent->mask & RROutputPropertyNotifyMask))
+ continue;
+
+ event->sequenceNumber = client->sequence;
+ event->window = pRREvent->window->drawable.id;
+ WriteEventsToClient(pRREvent->client, 1, (xEvent *)event);
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+static void RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event)
+{
+ if (!(dispatchException & (DE_RESET | DE_TERMINATE)))
+ WalkTree(pScreen, DeliverPropertyEvent, event);
+}
+
+void
+RRDeleteAllOutputProperties (RROutputPtr output)
+{
+ RRPropertyPtr prop, next;
+ xRROutputPropertyNotifyEvent event;
+
+ for (prop = output->properties; prop; prop = next)
+ {
+ next = prop->next;
+ event.type = RREventBase + RRNotify;
+ event.subCode = RRNotify_OutputProperty;
+ event.output = output->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.timestamp = currentTime.milliseconds;
+ RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event);
+ if (prop->current.data)
+ xfree(prop->current.data);
+ if (prop->pending.data)
+ xfree(prop->pending.data);
+ xfree(prop);
+ }
+}
+
+static void
+RRInitOutputPropertyValue (RRPropertyValuePtr property_value)
+{
+ property_value->type = None;
+ property_value->format = 0;
+ property_value->size = 0;
+ property_value->data = NULL;
+}
+
+static RRPropertyPtr
+RRCreateOutputProperty (Atom property)
+{
+ RRPropertyPtr prop;
+
+ prop = (RRPropertyPtr)xalloc(sizeof(RRPropertyRec));
+ if (!prop)
+ return NULL;
+ prop->next = NULL;
+ prop->propertyName = property;
+ prop->is_pending = FALSE;
+ prop->range = FALSE;
+ prop->immutable = FALSE;
+ prop->num_valid = 0;
+ prop->valid_values = NULL;
+ RRInitOutputPropertyValue (&prop->current);
+ RRInitOutputPropertyValue (&prop->pending);
+ return prop;
+}
+
+static void
+RRDestroyOutputProperty (RRPropertyPtr prop)
+{
+ if (prop->valid_values)
+ xfree (prop->valid_values);
+ if (prop->current.data)
+ xfree(prop->current.data);
+ if (prop->pending.data)
+ xfree(prop->pending.data);
+ if (prop->valid_values)
+ xfree(prop->valid_values);
+ xfree(prop);
+}
+
+void
+RRDeleteOutputProperty (RROutputPtr output, Atom property)
+{
+ RRPropertyPtr prop, *prev;
+ xRROutputPropertyNotifyEvent event;
+
+ for (prev = &output->properties; (prop = *prev); prev = &(prop->next))
+ if (prop->propertyName == property)
+ break;
+ if (prop)
+ {
+ *prev = prop->next;
+ event.type = RREventBase + RRNotify;
+ event.subCode = RRNotify_OutputProperty;
+ event.output = output->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.timestamp = currentTime.milliseconds;
+ RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event);
+ RRDestroyOutputProperty (prop);
+ }
+}
+
+int
+RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
+ int format, int mode, unsigned long len,
+ pointer value, Bool sendevent, Bool pending)
+{
+ RRPropertyPtr prop;
+ xRROutputPropertyNotifyEvent event;
+ rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
+ int size_in_bytes;
+ int total_size;
+ unsigned long total_len;
+ RRPropertyValuePtr prop_value;
+ RRPropertyValueRec new_value;
+ Bool add = FALSE;
+
+ size_in_bytes = format >> 3;
+
+ /* first see if property already exists */
+ prop = RRQueryOutputProperty (output, property);
+ if (!prop) /* just add to list */
+ {
+ prop = RRCreateOutputProperty (property);
+ if (!prop)
+ return(BadAlloc);
+ add = TRUE;
+ mode = PropModeReplace;
+ }
+ if (pending && prop->is_pending)
+ prop_value = &prop->pending;
+ else
+ prop_value = &prop->current;
+
+ /* To append or prepend to a property the request format and type
+ must match those of the already defined property. The
+ existing format and type are irrelevant when using the mode
+ "PropModeReplace" since they will be written over. */
+
+ if ((format != prop_value->format) && (mode != PropModeReplace))
+ return(BadMatch);
+ if ((prop_value->type != type) && (mode != PropModeReplace))
+ return(BadMatch);
+ new_value = *prop_value;
+ if (mode == PropModeReplace)
+ total_len = len;
+ else
+ total_len = prop_value->size + len;
+
+ if (mode == PropModeReplace || len > 0)
+ {
+ pointer new_data = NULL, old_data = NULL;
+
+ total_size = total_len * size_in_bytes;
+ new_value.data = (pointer)xalloc (total_size);
+ if (!new_value.data && total_size)
+ {
+ if (add)
+ RRDestroyOutputProperty (prop);
+ return BadAlloc;
+ }
+ new_value.size = len;
+ new_value.type = type;
+ new_value.format = format;
+
+ switch (mode) {
+ case PropModeReplace:
+ new_data = new_value.data;
+ old_data = NULL;
+ break;
+ case PropModeAppend:
+ new_data = (pointer) (((char *) new_value.data) +
+ (prop_value->size * size_in_bytes));
+ old_data = new_value.data;
+ break;
+ case PropModePrepend:
+ new_data = new_value.data;
+ old_data = (pointer) (((char *) new_value.data) +
+ (prop_value->size * size_in_bytes));
+ break;
+ }
+ if (new_data)
+ memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
+ if (old_data)
+ memcpy ((char *) old_data, (char *) prop_value->data,
+ prop_value->size * size_in_bytes);
+
+ if (pending && pScrPriv->rrOutputSetProperty &&
+ !pScrPriv->rrOutputSetProperty(output->pScreen, output,
+ prop->propertyName, &new_value))
+ {
+ if (new_value.data)
+ xfree (new_value.data);
+ return (BadValue);
+ }
+ if (prop_value->data)
+ xfree (prop_value->data);
+ *prop_value = new_value;
+ }
+
+ else if (len == 0)
+ {
+ /* do nothing */
+ }
+
+ if (add)
+ {
+ prop->next = output->properties;
+ output->properties = prop;
+ }
+
+ if (pending && prop->is_pending)
+ output->pendingProperties = TRUE;
+
+ if (sendevent)
+ {
+ event.type = RREventBase + RRNotify;
+ event.subCode = RRNotify_OutputProperty;
+ event.output = output->id;
+ event.state = PropertyNewValue;
+ event.atom = prop->propertyName;
+ event.timestamp = currentTime.milliseconds;
+ RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event);
+ }
+ return(Success);
+}
+
+Bool
+RRPostPendingProperties (RROutputPtr output)
+{
+ RRPropertyValuePtr pending_value;
+ RRPropertyValuePtr current_value;
+ RRPropertyPtr property;
+ Bool ret = TRUE;
+
+ if (!output->pendingProperties)
+ return TRUE;
+
+ output->pendingProperties = FALSE;
+ for (property = output->properties; property; property = property->next)
+ {
+ /* Skip non-pending properties */
+ if (!property->is_pending)
+ continue;
+
+ pending_value = &property->pending;
+ current_value = &property->current;
+
+ /*
+ * If the pending and current values are equal, don't mark it
+ * as changed (which would deliver an event)
+ */
+ if (pending_value->type == current_value->type &&
+ pending_value->format == current_value->format &&
+ pending_value->size == current_value->size &&
+ !memcmp (pending_value->data, current_value->data,
+ pending_value->size))
+ continue;
+
+ if (RRChangeOutputProperty (output, property->propertyName,
+ pending_value->type, pending_value->format,
+ PropModeReplace, pending_value->size,
+ pending_value->data, TRUE,
+ FALSE) != Success)
+ ret = FALSE;
+ }
+ return ret;
+}
+
+RRPropertyPtr
+RRQueryOutputProperty (RROutputPtr output, Atom property)
+{
+ RRPropertyPtr prop;
+
+ for (prop = output->properties; prop; prop = prop->next)
+ if (prop->propertyName == property)
+ return prop;
+ return NULL;
+}
+
+RRPropertyValuePtr
+RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending)
+{
+ RRPropertyPtr prop = RRQueryOutputProperty (output, property);
+ rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
+
+ if (!prop)
+ return NULL;
+ if (pending && prop->is_pending)
+ return &prop->pending;
+ else {
+#if RANDR_13_INTERFACE
+ /* If we can, try to update the property value first */
+ if (pScrPriv->rrOutputGetProperty)
+ pScrPriv->rrOutputGetProperty(output->pScreen, output,
+ prop->propertyName);
+#endif
+ return &prop->current;
+ }
+}
+
+int
+RRConfigureOutputProperty (RROutputPtr output, Atom property,
+ Bool pending, Bool range, Bool immutable,
+ int num_values, INT32 *values)
+{
+ RRPropertyPtr prop = RRQueryOutputProperty (output, property);
+ Bool add = FALSE;
+ INT32 *new_values;
+
+ if (!prop)
+ {
+ prop = RRCreateOutputProperty (property);
+ if (!prop)
+ return(BadAlloc);
+ add = TRUE;
+ } else if (prop->immutable && !immutable)
+ return(BadAccess);
+
+ /*
+ * ranges must have even number of values
+ */
+ if (range && (num_values & 1))
+ return BadMatch;
+
+ new_values = xalloc (num_values * sizeof (INT32));
+ if (!new_values && num_values)
+ return BadAlloc;
+ if (num_values)
+ memcpy (new_values, values, num_values * sizeof (INT32));
+
+ /*
+ * Property moving from pending to non-pending
+ * loses any pending values
+ */
+ if (prop->is_pending && !pending)
+ {
+ if (prop->pending.data)
+ xfree (prop->pending.data);
+ RRInitOutputPropertyValue (&prop->pending);
+ }
+
+ prop->is_pending = pending;
+ prop->range = range;
+ prop->immutable = immutable;
+ prop->num_valid = num_values;
+ if (prop->valid_values)
+ xfree (prop->valid_values);
+ prop->valid_values = new_values;
+
+ if (add) {
+ prop->next = output->properties;
+ output->properties = prop;
+ }
+
+ return Success;
+}
+
+int
+ProcRRListOutputProperties (ClientPtr client)
+{
+ REQUEST(xRRListOutputPropertiesReq);
+ Atom *pAtoms = NULL, *temppAtoms;
+ xRRListOutputPropertiesReply rep;
+ int numProps = 0;
+ RROutputPtr output;
+ RRPropertyPtr prop;
+
+ REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
+
+ VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+
+ for (prop = output->properties; prop; prop = prop->next)
+ numProps++;
+ if (numProps)
+ if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
+ return(BadAlloc);
+
+ rep.type = X_Reply;
+ rep.length = bytes_to_int32(numProps * sizeof(Atom));
+ rep.sequenceNumber = client->sequence;
+ rep.nAtoms = numProps;
+ if (client->swapped)
+ {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.nAtoms, n);
+ }
+ temppAtoms = pAtoms;
+ for (prop = output->properties; prop; prop = prop->next)
+ *temppAtoms++ = prop->propertyName;
+
+ WriteToClient(client, sizeof(xRRListOutputPropertiesReply), (char*)&rep);
+ if (numProps)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
+ xfree(pAtoms);
+ }
+ return(client->noClientException);
+}
+
+int
+ProcRRQueryOutputProperty (ClientPtr client)
+{
+ REQUEST(xRRQueryOutputPropertyReq);
+ xRRQueryOutputPropertyReply rep;
+ RROutputPtr output;
+ RRPropertyPtr prop;
+ char *extra = NULL;
+
+ REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq);
+
+ VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+
+ prop = RRQueryOutputProperty (output, stuff->property);
+ if (!prop)
+ return BadName;
+
+ if (prop->num_valid) {
+ extra = xalloc(prop->num_valid * sizeof(INT32));
+ if (!extra)
+ return BadAlloc;
+ }
+ rep.type = X_Reply;
+ rep.length = prop->num_valid;
+ rep.sequenceNumber = client->sequence;
+ rep.pending = prop->is_pending;
+ rep.range = prop->range;
+ rep.immutable = prop->immutable;
+ if (client->swapped)
+ {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ }
+ WriteToClient (client, sizeof (xRRQueryOutputPropertyReply), (char*)&rep);
+ if (prop->num_valid)
+ {
+ memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32));
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32),
+ extra);
+ xfree(extra);
+ }
+ return(client->noClientException);
+}
+
+int
+ProcRRConfigureOutputProperty (ClientPtr client)
+{
+ REQUEST(xRRConfigureOutputPropertyReq);
+ RROutputPtr output;
+ int num_valid;
+
+ REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq);
+
+ VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+
+ num_valid = stuff->length - bytes_to_int32(sizeof (xRRConfigureOutputPropertyReq));
+ return RRConfigureOutputProperty (output, stuff->property,
+ stuff->pending, stuff->range,
+ FALSE, num_valid,
+ (INT32 *) (stuff + 1));
+}
+
+int
+ProcRRChangeOutputProperty (ClientPtr client)
+{
+ REQUEST(xRRChangeOutputPropertyReq);
+ RROutputPtr output;
+ char format, mode;
+ unsigned long len;
+ int sizeInBytes;
+ int totalSize;
+ int err;
+
+ REQUEST_AT_LEAST_SIZE(xRRChangeOutputPropertyReq);
+ 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 > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq))))
+ return BadLength;
+ sizeInBytes = format>>3;
+ totalSize = len * sizeInBytes;
+ REQUEST_FIXED_SIZE(xRRChangeOutputPropertyReq, totalSize);
+
+ VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return(BadAtom);
+ }
+ if (!ValidAtom(stuff->type))
+ {
+ client->errorValue = stuff->type;
+ return(BadAtom);
+ }
+
+ err = RRChangeOutputProperty(output, stuff->property,
+ stuff->type, (int)format,
+ (int)mode, len, (pointer)&stuff[1], TRUE, TRUE);
+ if (err != Success)
+ return err;
+ else
+ return client->noClientException;
+}
+
+int
+ProcRRDeleteOutputProperty (ClientPtr client)
+{
+ REQUEST(xRRDeleteOutputPropertyReq);
+ RROutputPtr output;
+
+ REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
+ UpdateCurrentTime();
+ VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return (BadAtom);
+ }
+
+
+ RRDeleteOutputProperty(output, stuff->property);
+ return client->noClientException;
+}
+
+int
+ProcRRGetOutputProperty (ClientPtr client)
+{
+ REQUEST(xRRGetOutputPropertyReq);
+ RRPropertyPtr prop, *prev;
+ RRPropertyValuePtr prop_value;
+ unsigned long n, len, ind;
+ RROutputPtr output;
+ xRRGetOutputPropertyReply reply;
+ char *extra = NULL;
+
+ REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
+ if (stuff->delete)
+ UpdateCurrentTime();
+ VERIFY_RR_OUTPUT(stuff->output, output,
+ stuff->delete ? DixWriteAccess : DixReadAccess);
+
+ 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);
+ }
+
+ for (prev = &output->properties; (prop = *prev); prev = &prop->next)
+ if (prop->propertyName == stuff->property)
+ break;
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ if (!prop)
+ {
+ reply.nItems = 0;
+ reply.length = 0;
+ reply.bytesAfter = 0;
+ reply.propertyType = None;
+ reply.format = 0;
+ if (client->swapped) {
+ int n;
+
+ swaps(&reply.sequenceNumber, n);
+ swapl(&reply.length, n);
+ swapl(&reply.propertyType, n);
+ swapl(&reply.bytesAfter, n);
+ swapl(&reply.nItems, n);
+ }
+ WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
+ return(client->noClientException);
+ }
+
+ if (prop->immutable && stuff->delete)
+ return BadAccess;
+
+ prop_value = RRGetOutputProperty(output, stuff->property, stuff->pending);
+ if (!prop_value)
+ return BadAtom;
+
+ /* 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;
+ if (client->swapped) {
+ int n;
+
+ swaps(&reply.sequenceNumber, n);
+ swapl(&reply.length, n);
+ swapl(&reply.propertyType, n);
+ swapl(&reply.bytesAfter, n);
+ swapl(&reply.nItems, n);
+ }
+ WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &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);
+
+ if (len) {
+ extra = xalloc(len);
+ if (!extra)
+ return BadAlloc;
+ }
+ reply.bytesAfter = n - (ind + len);
+ reply.format = prop_value->format;
+ reply.length = bytes_to_int32(len);
+ 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))
+ {
+ xRROutputPropertyNotifyEvent event;
+
+ event.type = RREventBase + RRNotify;
+ event.subCode = RRNotify_OutputProperty;
+ event.output = output->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.timestamp = currentTime.milliseconds;
+ RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event);
+ }
+
+ if (client->swapped) {
+ int n;
+
+ swaps(&reply.sequenceNumber, n);
+ swapl(&reply.length, n);
+ swapl(&reply.propertyType, n);
+ swapl(&reply.bytesAfter, n);
+ swapl(&reply.nItems, n);
+ }
+ WriteToClient(client, sizeof(xGenericReply), &reply);
+ if (len)
+ {
+ memcpy(extra, (char *)prop_value->data + ind, len);
+ switch (reply.format) {
+ case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
+ case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
+ default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
+ }
+ WriteSwappedDataToClient(client, len,
+ extra);
+ xfree(extra);
+ }
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ { /* delete the Property */
+ *prev = prop->next;
+ RRDestroyOutputProperty (prop);
+ }
+ return(client->noClientException);
+}
+
|