Fix Pending property API, adding RRPostPendingProperty.
Pending Properties take effect when the driver says they do, so provide an API to tell DIX when a property effect is made. Also, allow driver to reject property values in RRChangeOutputProperty. (cherry picked from commit 8eb288fbd69e2ffd02521d2c6a964c8180d08ec8)
This commit is contained in:
parent
86d76390eb
commit
7093367c39
|
@ -1923,7 +1923,7 @@ xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
|
|||
|
||||
if (data_len != 0) {
|
||||
RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
|
||||
PropModeReplace, data_len, data, FALSE);
|
||||
PropModeReplace, data_len, data, FALSE, TRUE);
|
||||
} else {
|
||||
RRDeleteOutputProperty(output->randr_output, edid_atom);
|
||||
}
|
||||
|
|
|
@ -761,10 +761,13 @@ RRQueryOutputProperty (RROutputPtr output, Atom property);
|
|||
void
|
||||
RRDeleteOutputProperty (RROutputPtr output, Atom property);
|
||||
|
||||
Bool
|
||||
RRPostPendingProperty (RROutputPtr output, Atom property);
|
||||
|
||||
int
|
||||
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
||||
int format, int mode, unsigned long len,
|
||||
pointer value, Bool sendevent);
|
||||
pointer value, Bool sendevent, Bool pending);
|
||||
|
||||
int
|
||||
RRConfigureOutputProperty (RROutputPtr output, Atom property,
|
||||
|
|
|
@ -121,19 +121,19 @@ RRDeleteOutputProperty (RROutputPtr output, Atom property)
|
|||
int
|
||||
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
||||
int format, int mode, unsigned long len,
|
||||
pointer value, Bool sendevent)
|
||||
pointer value, Bool sendevent, Bool pending)
|
||||
{
|
||||
RRPropertyPtr prop;
|
||||
xRROutputPropertyNotifyEvent event;
|
||||
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
|
||||
int sizeInBytes;
|
||||
int totalSize;
|
||||
pointer data;
|
||||
int size_in_bytes;
|
||||
int total_size;
|
||||
unsigned long total_len;
|
||||
RRPropertyValuePtr prop_value;
|
||||
RRPropertyValueRec new_value;
|
||||
Bool add = FALSE;
|
||||
|
||||
sizeInBytes = format >> 3;
|
||||
totalSize = len * sizeInBytes;
|
||||
size_in_bytes = format >> 3;
|
||||
|
||||
/* first see if property already exists */
|
||||
prop = RRQueryOutputProperty (output, property);
|
||||
|
@ -145,7 +145,7 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
|||
add = TRUE;
|
||||
mode = PropModeReplace;
|
||||
}
|
||||
if (prop->is_pending)
|
||||
if (pending && prop->is_pending)
|
||||
prop_value = &prop->pending;
|
||||
else
|
||||
prop_value = &prop->current;
|
||||
|
@ -159,68 +159,75 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
|||
return(BadMatch);
|
||||
if ((prop_value->type != type) && (mode != PropModeReplace))
|
||||
return(BadMatch);
|
||||
new_value = *prop_value;
|
||||
if (mode == PropModeReplace)
|
||||
{
|
||||
if (totalSize != prop_value->size * (prop_value->format >> 3))
|
||||
{
|
||||
if (prop_value->data)
|
||||
data = (pointer)xrealloc(prop_value->data, totalSize);
|
||||
total_len = len;
|
||||
else
|
||||
data = (pointer)xalloc (totalSize);
|
||||
if (!data && len)
|
||||
total_len = prop_value->size + len;
|
||||
|
||||
if (mode == PropModeReplace || len > 0)
|
||||
{
|
||||
pointer new_data, old_data;
|
||||
|
||||
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);
|
||||
}
|
||||
prop_value->data = data;
|
||||
return BadAlloc;
|
||||
}
|
||||
if (len)
|
||||
memmove((char *)prop_value->data, (char *)value, totalSize);
|
||||
prop_value->size = len;
|
||||
prop_value->type = type;
|
||||
prop_value->format = format;
|
||||
memmove((char *)new_value.data, (char *)value, total_size);
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
}
|
||||
else if (mode == PropModeAppend)
|
||||
{
|
||||
data = (pointer)xrealloc(prop_value->data,
|
||||
sizeInBytes * (len + prop_value->size));
|
||||
if (!data)
|
||||
return(BadAlloc);
|
||||
prop_value->data = data;
|
||||
memmove(&((char *)data)[prop_value->size * sizeInBytes],
|
||||
(char *)value,
|
||||
totalSize);
|
||||
prop_value->size += len;
|
||||
}
|
||||
else if (mode == PropModePrepend)
|
||||
{
|
||||
data = (pointer)xalloc(sizeInBytes * (len + prop_value->size));
|
||||
if (!data)
|
||||
return(BadAlloc);
|
||||
memmove(&((char *)data)[totalSize], (char *)prop_value->data,
|
||||
(int)(prop_value->size * sizeInBytes));
|
||||
memmove((char *)data, (char *)value, totalSize);
|
||||
xfree(prop_value->data);
|
||||
prop_value->data = data;
|
||||
prop_value->size += len;
|
||||
}
|
||||
|
||||
if (add)
|
||||
{
|
||||
prop->next = output->properties;
|
||||
output->properties = prop;
|
||||
}
|
||||
|
||||
if (!prop->is_pending) {
|
||||
/* What should we do in case of failure? */
|
||||
pScrPriv->rrOutputSetProperty(output->pScreen, output,
|
||||
prop->propertyName, prop_value);
|
||||
}
|
||||
|
||||
if (sendevent)
|
||||
{
|
||||
event.type = RREventBase + RRNotify;
|
||||
|
@ -234,6 +241,33 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
|||
return(Success);
|
||||
}
|
||||
|
||||
Bool
|
||||
RRPostPendingProperty (RROutputPtr output, Atom property)
|
||||
{
|
||||
RRPropertyPtr prop = RRQueryOutputProperty (output, property);
|
||||
RRPropertyValuePtr pending_value;
|
||||
RRPropertyValuePtr current_value;
|
||||
|
||||
if (!prop)
|
||||
return FALSE;
|
||||
if (!prop->is_pending)
|
||||
return FALSE;
|
||||
pending_value = &prop->pending;
|
||||
current_value = &prop->current;
|
||||
|
||||
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))
|
||||
return TRUE;
|
||||
|
||||
if (RRChangeOutputProperty (output, property,
|
||||
pending_value->type, pending_value->format, PropModeReplace,
|
||||
pending_value->size, pending_value->data, TRUE, FALSE) != Success)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
RRPropertyPtr
|
||||
RRQueryOutputProperty (RROutputPtr output, Atom property)
|
||||
{
|
||||
|
@ -474,7 +508,7 @@ ProcRRChangeOutputProperty (ClientPtr client)
|
|||
|
||||
err = RRChangeOutputProperty(output, stuff->property,
|
||||
stuff->type, (int)format,
|
||||
(int)mode, len, (pointer)&stuff[1], TRUE);
|
||||
(int)mode, len, (pointer)&stuff[1], TRUE, TRUE);
|
||||
if (err != Success)
|
||||
return err;
|
||||
else
|
||||
|
@ -600,7 +634,10 @@ ProcRRGetOutputProperty (ClientPtr client)
|
|||
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))
|
||||
|
|
Loading…
Reference in New Issue