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) {
|
if (data_len != 0) {
|
||||||
RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
|
RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
|
||||||
PropModeReplace, data_len, data, FALSE);
|
PropModeReplace, data_len, data, FALSE, TRUE);
|
||||||
} else {
|
} else {
|
||||||
RRDeleteOutputProperty(output->randr_output, edid_atom);
|
RRDeleteOutputProperty(output->randr_output, edid_atom);
|
||||||
}
|
}
|
||||||
|
|
|
@ -761,10 +761,13 @@ RRQueryOutputProperty (RROutputPtr output, Atom property);
|
||||||
void
|
void
|
||||||
RRDeleteOutputProperty (RROutputPtr output, Atom property);
|
RRDeleteOutputProperty (RROutputPtr output, Atom property);
|
||||||
|
|
||||||
|
Bool
|
||||||
|
RRPostPendingProperty (RROutputPtr output, Atom property);
|
||||||
|
|
||||||
int
|
int
|
||||||
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
||||||
int format, int mode, unsigned long len,
|
int format, int mode, unsigned long len,
|
||||||
pointer value, Bool sendevent);
|
pointer value, Bool sendevent, Bool pending);
|
||||||
|
|
||||||
int
|
int
|
||||||
RRConfigureOutputProperty (RROutputPtr output, Atom property,
|
RRConfigureOutputProperty (RROutputPtr output, Atom property,
|
||||||
|
|
|
@ -121,19 +121,19 @@ RRDeleteOutputProperty (RROutputPtr output, Atom property)
|
||||||
int
|
int
|
||||||
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
||||||
int format, int mode, unsigned long len,
|
int format, int mode, unsigned long len,
|
||||||
pointer value, Bool sendevent)
|
pointer value, Bool sendevent, Bool pending)
|
||||||
{
|
{
|
||||||
RRPropertyPtr prop;
|
RRPropertyPtr prop;
|
||||||
xRROutputPropertyNotifyEvent event;
|
xRROutputPropertyNotifyEvent event;
|
||||||
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
|
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
|
||||||
int sizeInBytes;
|
int size_in_bytes;
|
||||||
int totalSize;
|
int total_size;
|
||||||
pointer data;
|
unsigned long total_len;
|
||||||
RRPropertyValuePtr prop_value;
|
RRPropertyValuePtr prop_value;
|
||||||
|
RRPropertyValueRec new_value;
|
||||||
Bool add = FALSE;
|
Bool add = FALSE;
|
||||||
|
|
||||||
sizeInBytes = format >> 3;
|
size_in_bytes = format >> 3;
|
||||||
totalSize = len * sizeInBytes;
|
|
||||||
|
|
||||||
/* first see if property already exists */
|
/* first see if property already exists */
|
||||||
prop = RRQueryOutputProperty (output, property);
|
prop = RRQueryOutputProperty (output, property);
|
||||||
|
@ -145,7 +145,7 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
||||||
add = TRUE;
|
add = TRUE;
|
||||||
mode = PropModeReplace;
|
mode = PropModeReplace;
|
||||||
}
|
}
|
||||||
if (prop->is_pending)
|
if (pending && prop->is_pending)
|
||||||
prop_value = &prop->pending;
|
prop_value = &prop->pending;
|
||||||
else
|
else
|
||||||
prop_value = &prop->current;
|
prop_value = &prop->current;
|
||||||
|
@ -159,68 +159,75 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
||||||
return(BadMatch);
|
return(BadMatch);
|
||||||
if ((prop_value->type != type) && (mode != PropModeReplace))
|
if ((prop_value->type != type) && (mode != PropModeReplace))
|
||||||
return(BadMatch);
|
return(BadMatch);
|
||||||
|
new_value = *prop_value;
|
||||||
if (mode == PropModeReplace)
|
if (mode == PropModeReplace)
|
||||||
{
|
total_len = len;
|
||||||
if (totalSize != prop_value->size * (prop_value->format >> 3))
|
|
||||||
{
|
|
||||||
if (prop_value->data)
|
|
||||||
data = (pointer)xrealloc(prop_value->data, totalSize);
|
|
||||||
else
|
else
|
||||||
data = (pointer)xalloc (totalSize);
|
total_len = prop_value->size + len;
|
||||||
if (!data && 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)
|
if (add)
|
||||||
RRDestroyOutputProperty (prop);
|
RRDestroyOutputProperty (prop);
|
||||||
return(BadAlloc);
|
return BadAlloc;
|
||||||
}
|
|
||||||
prop_value->data = data;
|
|
||||||
}
|
}
|
||||||
if (len)
|
if (len)
|
||||||
memmove((char *)prop_value->data, (char *)value, totalSize);
|
memmove((char *)new_value.data, (char *)value, total_size);
|
||||||
prop_value->size = len;
|
new_value.size = len;
|
||||||
prop_value->type = type;
|
new_value.type = type;
|
||||||
prop_value->format = format;
|
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)
|
else if (len == 0)
|
||||||
{
|
{
|
||||||
/* do nothing */
|
/* 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)
|
if (add)
|
||||||
{
|
{
|
||||||
prop->next = output->properties;
|
prop->next = output->properties;
|
||||||
output->properties = prop;
|
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)
|
if (sendevent)
|
||||||
{
|
{
|
||||||
event.type = RREventBase + RRNotify;
|
event.type = RREventBase + RRNotify;
|
||||||
|
@ -234,6 +241,33 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
||||||
return(Success);
|
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
|
RRPropertyPtr
|
||||||
RRQueryOutputProperty (RROutputPtr output, Atom property)
|
RRQueryOutputProperty (RROutputPtr output, Atom property)
|
||||||
{
|
{
|
||||||
|
@ -474,7 +508,7 @@ ProcRRChangeOutputProperty (ClientPtr client)
|
||||||
|
|
||||||
err = RRChangeOutputProperty(output, stuff->property,
|
err = RRChangeOutputProperty(output, stuff->property,
|
||||||
stuff->type, (int)format,
|
stuff->type, (int)format,
|
||||||
(int)mode, len, (pointer)&stuff[1], TRUE);
|
(int)mode, len, (pointer)&stuff[1], TRUE, TRUE);
|
||||||
if (err != Success)
|
if (err != Success)
|
||||||
return err;
|
return err;
|
||||||
else
|
else
|
||||||
|
@ -600,7 +634,10 @@ ProcRRGetOutputProperty (ClientPtr client)
|
||||||
reply.bytesAfter = n - (ind + len);
|
reply.bytesAfter = n - (ind + len);
|
||||||
reply.format = prop_value->format;
|
reply.format = prop_value->format;
|
||||||
reply.length = (len + 3) >> 2;
|
reply.length = (len + 3) >> 2;
|
||||||
|
if (prop_value->format)
|
||||||
reply.nItems = len / (prop_value->format / 8);
|
reply.nItems = len / (prop_value->format / 8);
|
||||||
|
else
|
||||||
|
reply.nItems = 0;
|
||||||
reply.propertyType = prop_value->type;
|
reply.propertyType = prop_value->type;
|
||||||
|
|
||||||
if (stuff->delete && (reply.bytesAfter == 0))
|
if (stuff->delete && (reply.bytesAfter == 0))
|
||||||
|
|
Loading…
Reference in New Issue