1706f2543Smrg/* 2706f2543Smrg * Copyright © 2006 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that copyright 7706f2543Smrg * notice and this permission notice appear in supporting documentation, and 8706f2543Smrg * that the name of the copyright holders not be used in advertising or 9706f2543Smrg * publicity pertaining to distribution of the software without specific, 10706f2543Smrg * written prior permission. The copyright holders make no representations 11706f2543Smrg * about the suitability of this software for any purpose. It is provided "as 12706f2543Smrg * is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20706f2543Smrg * OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#include "randrstr.h" 24706f2543Smrg#include "propertyst.h" 25706f2543Smrg#include "swaprep.h" 26706f2543Smrg 27706f2543Smrgstatic int 28706f2543SmrgDeliverPropertyEvent(WindowPtr pWin, void *value) 29706f2543Smrg{ 30706f2543Smrg xRROutputPropertyNotifyEvent *event = value; 31706f2543Smrg RREventPtr *pHead, pRREvent; 32706f2543Smrg 33706f2543Smrg dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, 34706f2543Smrg RREventType, serverClient, DixReadAccess); 35706f2543Smrg if (!pHead) 36706f2543Smrg return WT_WALKCHILDREN; 37706f2543Smrg 38706f2543Smrg for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) 39706f2543Smrg { 40706f2543Smrg if (!(pRREvent->mask & RROutputPropertyNotifyMask)) 41706f2543Smrg continue; 42706f2543Smrg 43706f2543Smrg event->window = pRREvent->window->drawable.id; 44706f2543Smrg WriteEventsToClient(pRREvent->client, 1, (xEvent *)event); 45706f2543Smrg } 46706f2543Smrg 47706f2543Smrg return WT_WALKCHILDREN; 48706f2543Smrg} 49706f2543Smrg 50706f2543Smrgstatic void RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event) 51706f2543Smrg{ 52706f2543Smrg if (!(dispatchException & (DE_RESET | DE_TERMINATE))) 53706f2543Smrg WalkTree(pScreen, DeliverPropertyEvent, event); 54706f2543Smrg} 55706f2543Smrg 56706f2543Smrgstatic void 57706f2543SmrgRRDestroyOutputProperty (RRPropertyPtr prop) 58706f2543Smrg{ 59706f2543Smrg free(prop->valid_values); 60706f2543Smrg free(prop->current.data); 61706f2543Smrg free(prop->pending.data); 62706f2543Smrg free(prop); 63706f2543Smrg} 64706f2543Smrg 65706f2543Smrgstatic void 66706f2543SmrgRRDeleteProperty(RROutputRec *output, RRPropertyRec *prop) 67706f2543Smrg{ 68706f2543Smrg xRROutputPropertyNotifyEvent event; 69706f2543Smrg event.type = RREventBase + RRNotify; 70706f2543Smrg event.subCode = RRNotify_OutputProperty; 71706f2543Smrg event.output = output->id; 72706f2543Smrg event.state = PropertyDelete; 73706f2543Smrg event.atom = prop->propertyName; 74706f2543Smrg event.timestamp = currentTime.milliseconds; 75706f2543Smrg 76706f2543Smrg RRDeliverPropertyEvent(output->pScreen, (xEvent *)&event); 77706f2543Smrg 78706f2543Smrg RRDestroyOutputProperty(prop); 79706f2543Smrg} 80706f2543Smrg 81706f2543Smrgvoid 82706f2543SmrgRRDeleteAllOutputProperties(RROutputPtr output) 83706f2543Smrg{ 84706f2543Smrg RRPropertyPtr prop, next; 85706f2543Smrg 86706f2543Smrg for (prop = output->properties; prop; prop = next) { 87706f2543Smrg next = prop->next; 88706f2543Smrg RRDeleteProperty(output, prop); 89706f2543Smrg } 90706f2543Smrg} 91706f2543Smrg 92706f2543Smrgstatic void 93706f2543SmrgRRInitOutputPropertyValue (RRPropertyValuePtr property_value) 94706f2543Smrg{ 95706f2543Smrg property_value->type = None; 96706f2543Smrg property_value->format = 0; 97706f2543Smrg property_value->size = 0; 98706f2543Smrg property_value->data = NULL; 99706f2543Smrg} 100706f2543Smrg 101706f2543Smrgstatic RRPropertyPtr 102706f2543SmrgRRCreateOutputProperty (Atom property) 103706f2543Smrg{ 104706f2543Smrg RRPropertyPtr prop; 105706f2543Smrg 106706f2543Smrg prop = (RRPropertyPtr)malloc(sizeof(RRPropertyRec)); 107706f2543Smrg if (!prop) 108706f2543Smrg return NULL; 109706f2543Smrg prop->next = NULL; 110706f2543Smrg prop->propertyName = property; 111706f2543Smrg prop->is_pending = FALSE; 112706f2543Smrg prop->range = FALSE; 113706f2543Smrg prop->immutable = FALSE; 114706f2543Smrg prop->num_valid = 0; 115706f2543Smrg prop->valid_values = NULL; 116706f2543Smrg RRInitOutputPropertyValue (&prop->current); 117706f2543Smrg RRInitOutputPropertyValue (&prop->pending); 118706f2543Smrg return prop; 119706f2543Smrg} 120706f2543Smrg 121706f2543Smrgvoid 122706f2543SmrgRRDeleteOutputProperty(RROutputPtr output, Atom property) 123706f2543Smrg{ 124706f2543Smrg RRPropertyRec *prop, **prev; 125706f2543Smrg 126706f2543Smrg for (prev = &output->properties; (prop = *prev); prev = &(prop->next)) 127706f2543Smrg if (prop->propertyName == property) { 128706f2543Smrg *prev = prop->next; 129706f2543Smrg RRDeleteProperty(output, prop); 130706f2543Smrg return; 131706f2543Smrg } 132706f2543Smrg} 133706f2543Smrg 134706f2543Smrgint 135706f2543SmrgRRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, 136706f2543Smrg int format, int mode, unsigned long len, 137706f2543Smrg pointer value, Bool sendevent, Bool pending) 138706f2543Smrg{ 139706f2543Smrg RRPropertyPtr prop; 140706f2543Smrg xRROutputPropertyNotifyEvent event; 141706f2543Smrg rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen); 142706f2543Smrg int size_in_bytes; 143706f2543Smrg int total_size; 144706f2543Smrg unsigned long total_len; 145706f2543Smrg RRPropertyValuePtr prop_value; 146706f2543Smrg RRPropertyValueRec new_value; 147706f2543Smrg Bool add = FALSE; 148706f2543Smrg 149706f2543Smrg size_in_bytes = format >> 3; 150706f2543Smrg 151706f2543Smrg /* first see if property already exists */ 152706f2543Smrg prop = RRQueryOutputProperty (output, property); 153706f2543Smrg if (!prop) /* just add to list */ 154706f2543Smrg { 155706f2543Smrg prop = RRCreateOutputProperty (property); 156706f2543Smrg if (!prop) 157706f2543Smrg return BadAlloc; 158706f2543Smrg add = TRUE; 159706f2543Smrg mode = PropModeReplace; 160706f2543Smrg } 161706f2543Smrg if (pending && prop->is_pending) 162706f2543Smrg prop_value = &prop->pending; 163706f2543Smrg else 164706f2543Smrg prop_value = &prop->current; 165706f2543Smrg 166706f2543Smrg /* To append or prepend to a property the request format and type 167706f2543Smrg must match those of the already defined property. The 168706f2543Smrg existing format and type are irrelevant when using the mode 169706f2543Smrg "PropModeReplace" since they will be written over. */ 170706f2543Smrg 171706f2543Smrg if ((format != prop_value->format) && (mode != PropModeReplace)) 172706f2543Smrg return BadMatch; 173706f2543Smrg if ((prop_value->type != type) && (mode != PropModeReplace)) 174706f2543Smrg return BadMatch; 175706f2543Smrg new_value = *prop_value; 176706f2543Smrg if (mode == PropModeReplace) 177706f2543Smrg total_len = len; 178706f2543Smrg else 179706f2543Smrg total_len = prop_value->size + len; 180706f2543Smrg 181706f2543Smrg if (mode == PropModeReplace || len > 0) 182706f2543Smrg { 183706f2543Smrg pointer new_data = NULL, old_data = NULL; 184706f2543Smrg 185706f2543Smrg total_size = total_len * size_in_bytes; 186706f2543Smrg new_value.data = (pointer)malloc(total_size); 187706f2543Smrg if (!new_value.data && total_size) 188706f2543Smrg { 189706f2543Smrg if (add) 190706f2543Smrg RRDestroyOutputProperty (prop); 191706f2543Smrg return BadAlloc; 192706f2543Smrg } 193bc1411c9Smrg new_value.size = total_len; 194706f2543Smrg new_value.type = type; 195706f2543Smrg new_value.format = format; 196706f2543Smrg 197706f2543Smrg switch (mode) { 198706f2543Smrg case PropModeReplace: 199706f2543Smrg new_data = new_value.data; 200706f2543Smrg old_data = NULL; 201706f2543Smrg break; 202706f2543Smrg case PropModeAppend: 203706f2543Smrg new_data = (pointer) (((char *) new_value.data) + 204706f2543Smrg (prop_value->size * size_in_bytes)); 205706f2543Smrg old_data = new_value.data; 206706f2543Smrg break; 207706f2543Smrg case PropModePrepend: 208706f2543Smrg new_data = new_value.data; 209706f2543Smrg old_data = (pointer) (((char *) new_value.data) + 210bc1411c9Smrg (len * size_in_bytes)); 211706f2543Smrg break; 212706f2543Smrg } 213706f2543Smrg if (new_data) 214706f2543Smrg memcpy ((char *) new_data, (char *) value, len * size_in_bytes); 215706f2543Smrg if (old_data) 216706f2543Smrg memcpy ((char *) old_data, (char *) prop_value->data, 217706f2543Smrg prop_value->size * size_in_bytes); 218706f2543Smrg 219706f2543Smrg if (pending && pScrPriv->rrOutputSetProperty && 220706f2543Smrg !pScrPriv->rrOutputSetProperty(output->pScreen, output, 221706f2543Smrg prop->propertyName, &new_value)) 222706f2543Smrg { 223706f2543Smrg free(new_value.data); 224706f2543Smrg return BadValue; 225706f2543Smrg } 226706f2543Smrg free(prop_value->data); 227706f2543Smrg *prop_value = new_value; 228706f2543Smrg } 229706f2543Smrg 230706f2543Smrg else if (len == 0) 231706f2543Smrg { 232706f2543Smrg /* do nothing */ 233706f2543Smrg } 234706f2543Smrg 235706f2543Smrg if (add) 236706f2543Smrg { 237706f2543Smrg prop->next = output->properties; 238706f2543Smrg output->properties = prop; 239706f2543Smrg } 240706f2543Smrg 241706f2543Smrg if (pending && prop->is_pending) 242706f2543Smrg output->pendingProperties = TRUE; 243706f2543Smrg 244706f2543Smrg if (sendevent) 245706f2543Smrg { 246706f2543Smrg event.type = RREventBase + RRNotify; 247706f2543Smrg event.subCode = RRNotify_OutputProperty; 248706f2543Smrg event.output = output->id; 249706f2543Smrg event.state = PropertyNewValue; 250706f2543Smrg event.atom = prop->propertyName; 251706f2543Smrg event.timestamp = currentTime.milliseconds; 252706f2543Smrg RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event); 253706f2543Smrg } 254706f2543Smrg return Success; 255706f2543Smrg} 256706f2543Smrg 257706f2543SmrgBool 258706f2543SmrgRRPostPendingProperties (RROutputPtr output) 259706f2543Smrg{ 260706f2543Smrg RRPropertyValuePtr pending_value; 261706f2543Smrg RRPropertyValuePtr current_value; 262706f2543Smrg RRPropertyPtr property; 263706f2543Smrg Bool ret = TRUE; 264706f2543Smrg 265706f2543Smrg if (!output->pendingProperties) 266706f2543Smrg return TRUE; 267706f2543Smrg 268706f2543Smrg output->pendingProperties = FALSE; 269706f2543Smrg for (property = output->properties; property; property = property->next) 270706f2543Smrg { 271706f2543Smrg /* Skip non-pending properties */ 272706f2543Smrg if (!property->is_pending) 273706f2543Smrg continue; 274706f2543Smrg 275706f2543Smrg pending_value = &property->pending; 276706f2543Smrg current_value = &property->current; 277706f2543Smrg 278706f2543Smrg /* 279706f2543Smrg * If the pending and current values are equal, don't mark it 280706f2543Smrg * as changed (which would deliver an event) 281706f2543Smrg */ 282706f2543Smrg if (pending_value->type == current_value->type && 283706f2543Smrg pending_value->format == current_value->format && 284706f2543Smrg pending_value->size == current_value->size && 285706f2543Smrg !memcmp (pending_value->data, current_value->data, 286706f2543Smrg pending_value->size * (pending_value->format / 8))) 287706f2543Smrg continue; 288706f2543Smrg 289706f2543Smrg if (RRChangeOutputProperty (output, property->propertyName, 290706f2543Smrg pending_value->type, pending_value->format, 291706f2543Smrg PropModeReplace, pending_value->size, 292706f2543Smrg pending_value->data, TRUE, 293706f2543Smrg FALSE) != Success) 294706f2543Smrg ret = FALSE; 295706f2543Smrg } 296706f2543Smrg return ret; 297706f2543Smrg} 298706f2543Smrg 299706f2543SmrgRRPropertyPtr 300706f2543SmrgRRQueryOutputProperty (RROutputPtr output, Atom property) 301706f2543Smrg{ 302706f2543Smrg RRPropertyPtr prop; 303706f2543Smrg 304706f2543Smrg for (prop = output->properties; prop; prop = prop->next) 305706f2543Smrg if (prop->propertyName == property) 306706f2543Smrg return prop; 307706f2543Smrg return NULL; 308706f2543Smrg} 309706f2543Smrg 310706f2543SmrgRRPropertyValuePtr 311706f2543SmrgRRGetOutputProperty (RROutputPtr output, Atom property, Bool pending) 312706f2543Smrg{ 313706f2543Smrg RRPropertyPtr prop = RRQueryOutputProperty (output, property); 314706f2543Smrg rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen); 315706f2543Smrg 316706f2543Smrg if (!prop) 317706f2543Smrg return NULL; 318706f2543Smrg if (pending && prop->is_pending) 319706f2543Smrg return &prop->pending; 320706f2543Smrg else { 321706f2543Smrg#if RANDR_13_INTERFACE 322706f2543Smrg /* If we can, try to update the property value first */ 323706f2543Smrg if (pScrPriv->rrOutputGetProperty) 324706f2543Smrg pScrPriv->rrOutputGetProperty(output->pScreen, output, 325706f2543Smrg prop->propertyName); 326706f2543Smrg#endif 327706f2543Smrg return &prop->current; 328706f2543Smrg } 329706f2543Smrg} 330706f2543Smrg 331706f2543Smrgint 332706f2543SmrgRRConfigureOutputProperty (RROutputPtr output, Atom property, 333706f2543Smrg Bool pending, Bool range, Bool immutable, 334706f2543Smrg int num_values, INT32 *values) 335706f2543Smrg{ 336706f2543Smrg RRPropertyPtr prop = RRQueryOutputProperty (output, property); 337706f2543Smrg Bool add = FALSE; 338706f2543Smrg INT32 *new_values; 339706f2543Smrg 340706f2543Smrg if (!prop) 341706f2543Smrg { 342706f2543Smrg prop = RRCreateOutputProperty (property); 343706f2543Smrg if (!prop) 344706f2543Smrg return BadAlloc; 345706f2543Smrg add = TRUE; 346706f2543Smrg } else if (prop->immutable && !immutable) 347706f2543Smrg return BadAccess; 348706f2543Smrg 349706f2543Smrg /* 350706f2543Smrg * ranges must have even number of values 351706f2543Smrg */ 352706f2543Smrg if (range && (num_values & 1)) 353706f2543Smrg return BadMatch; 354706f2543Smrg 355706f2543Smrg new_values = malloc(num_values * sizeof (INT32)); 356706f2543Smrg if (!new_values && num_values) 357706f2543Smrg return BadAlloc; 358706f2543Smrg if (num_values) 359706f2543Smrg memcpy (new_values, values, num_values * sizeof (INT32)); 360706f2543Smrg 361706f2543Smrg /* 362706f2543Smrg * Property moving from pending to non-pending 363706f2543Smrg * loses any pending values 364706f2543Smrg */ 365706f2543Smrg if (prop->is_pending && !pending) 366706f2543Smrg { 367706f2543Smrg free(prop->pending.data); 368706f2543Smrg RRInitOutputPropertyValue (&prop->pending); 369706f2543Smrg } 370706f2543Smrg 371706f2543Smrg prop->is_pending = pending; 372706f2543Smrg prop->range = range; 373706f2543Smrg prop->immutable = immutable; 374706f2543Smrg prop->num_valid = num_values; 375706f2543Smrg free(prop->valid_values); 376706f2543Smrg prop->valid_values = new_values; 377706f2543Smrg 378706f2543Smrg if (add) { 379706f2543Smrg prop->next = output->properties; 380706f2543Smrg output->properties = prop; 381706f2543Smrg } 382706f2543Smrg 383706f2543Smrg return Success; 384706f2543Smrg} 385706f2543Smrg 386706f2543Smrgint 387706f2543SmrgProcRRListOutputProperties (ClientPtr client) 388706f2543Smrg{ 389706f2543Smrg REQUEST(xRRListOutputPropertiesReq); 390706f2543Smrg Atom *pAtoms = NULL, *temppAtoms; 391706f2543Smrg xRRListOutputPropertiesReply rep; 392706f2543Smrg int numProps = 0; 393706f2543Smrg RROutputPtr output; 394706f2543Smrg RRPropertyPtr prop; 395706f2543Smrg 396706f2543Smrg REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq); 397706f2543Smrg 398706f2543Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 399706f2543Smrg 400706f2543Smrg for (prop = output->properties; prop; prop = prop->next) 401706f2543Smrg numProps++; 402706f2543Smrg if (numProps) 403706f2543Smrg if(!(pAtoms = (Atom *)malloc(numProps * sizeof(Atom)))) 404706f2543Smrg return BadAlloc; 405706f2543Smrg 406706f2543Smrg rep.type = X_Reply; 407706f2543Smrg rep.length = bytes_to_int32(numProps * sizeof(Atom)); 408706f2543Smrg rep.sequenceNumber = client->sequence; 409706f2543Smrg rep.nAtoms = numProps; 410706f2543Smrg if (client->swapped) 411706f2543Smrg { 412706f2543Smrg int n; 413706f2543Smrg swaps (&rep.sequenceNumber, n); 414706f2543Smrg swapl (&rep.length, n); 415706f2543Smrg swaps (&rep.nAtoms, n); 416706f2543Smrg } 417706f2543Smrg temppAtoms = pAtoms; 418706f2543Smrg for (prop = output->properties; prop; prop = prop->next) 419706f2543Smrg *temppAtoms++ = prop->propertyName; 420706f2543Smrg 421706f2543Smrg WriteToClient(client, sizeof(xRRListOutputPropertiesReply), (char*)&rep); 422706f2543Smrg if (numProps) 423706f2543Smrg { 424706f2543Smrg client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; 425706f2543Smrg WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); 426706f2543Smrg free(pAtoms); 427706f2543Smrg } 428706f2543Smrg return Success; 429706f2543Smrg} 430706f2543Smrg 431706f2543Smrgint 432706f2543SmrgProcRRQueryOutputProperty (ClientPtr client) 433706f2543Smrg{ 434706f2543Smrg REQUEST(xRRQueryOutputPropertyReq); 435706f2543Smrg xRRQueryOutputPropertyReply rep; 436706f2543Smrg RROutputPtr output; 437706f2543Smrg RRPropertyPtr prop; 438706f2543Smrg char *extra = NULL; 439706f2543Smrg 440706f2543Smrg REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq); 441706f2543Smrg 442706f2543Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 443706f2543Smrg 444706f2543Smrg prop = RRQueryOutputProperty (output, stuff->property); 445706f2543Smrg if (!prop) 446706f2543Smrg return BadName; 447706f2543Smrg 448706f2543Smrg if (prop->num_valid) { 449706f2543Smrg extra = malloc(prop->num_valid * sizeof(INT32)); 450706f2543Smrg if (!extra) 451706f2543Smrg return BadAlloc; 452706f2543Smrg } 453706f2543Smrg rep.type = X_Reply; 454706f2543Smrg rep.length = prop->num_valid; 455706f2543Smrg rep.sequenceNumber = client->sequence; 456706f2543Smrg rep.pending = prop->is_pending; 457706f2543Smrg rep.range = prop->range; 458706f2543Smrg rep.immutable = prop->immutable; 459706f2543Smrg if (client->swapped) 460706f2543Smrg { 461706f2543Smrg int n; 462706f2543Smrg swaps (&rep.sequenceNumber, n); 463706f2543Smrg swapl (&rep.length, n); 464706f2543Smrg } 465706f2543Smrg WriteToClient (client, sizeof (xRRQueryOutputPropertyReply), (char*)&rep); 466706f2543Smrg if (prop->num_valid) 467706f2543Smrg { 468706f2543Smrg memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32)); 469706f2543Smrg client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; 470706f2543Smrg WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32), 471706f2543Smrg extra); 472706f2543Smrg free(extra); 473706f2543Smrg } 474706f2543Smrg return Success; 475706f2543Smrg} 476706f2543Smrg 477706f2543Smrgint 478706f2543SmrgProcRRConfigureOutputProperty (ClientPtr client) 479706f2543Smrg{ 480706f2543Smrg REQUEST(xRRConfigureOutputPropertyReq); 481706f2543Smrg RROutputPtr output; 482706f2543Smrg int num_valid; 483706f2543Smrg 484706f2543Smrg REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq); 485706f2543Smrg 486706f2543Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 487706f2543Smrg 488706f2543Smrg num_valid = stuff->length - bytes_to_int32(sizeof (xRRConfigureOutputPropertyReq)); 489706f2543Smrg return RRConfigureOutputProperty (output, stuff->property, 490706f2543Smrg stuff->pending, stuff->range, 491706f2543Smrg FALSE, num_valid, 492706f2543Smrg (INT32 *) (stuff + 1)); 493706f2543Smrg} 494706f2543Smrg 495706f2543Smrgint 496706f2543SmrgProcRRChangeOutputProperty (ClientPtr client) 497706f2543Smrg{ 498706f2543Smrg REQUEST(xRRChangeOutputPropertyReq); 499706f2543Smrg RROutputPtr output; 500706f2543Smrg char format, mode; 501706f2543Smrg unsigned long len; 502706f2543Smrg int sizeInBytes; 50364af8facSmrg uint64_t totalSize; 504706f2543Smrg int err; 505706f2543Smrg 506706f2543Smrg REQUEST_AT_LEAST_SIZE(xRRChangeOutputPropertyReq); 507706f2543Smrg UpdateCurrentTime(); 508706f2543Smrg format = stuff->format; 509706f2543Smrg mode = stuff->mode; 510706f2543Smrg if ((mode != PropModeReplace) && (mode != PropModeAppend) && 511706f2543Smrg (mode != PropModePrepend)) 512706f2543Smrg { 513706f2543Smrg client->errorValue = mode; 514706f2543Smrg return BadValue; 515706f2543Smrg } 516706f2543Smrg if ((format != 8) && (format != 16) && (format != 32)) 517706f2543Smrg { 518706f2543Smrg client->errorValue = format; 519706f2543Smrg return BadValue; 520706f2543Smrg } 521706f2543Smrg len = stuff->nUnits; 522706f2543Smrg if (len > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq)))) 523706f2543Smrg return BadLength; 524706f2543Smrg sizeInBytes = format>>3; 525706f2543Smrg totalSize = len * sizeInBytes; 526706f2543Smrg REQUEST_FIXED_SIZE(xRRChangeOutputPropertyReq, totalSize); 527706f2543Smrg 528706f2543Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 529706f2543Smrg 530706f2543Smrg if (!ValidAtom(stuff->property)) 531706f2543Smrg { 532706f2543Smrg client->errorValue = stuff->property; 533706f2543Smrg return BadAtom; 534706f2543Smrg } 535706f2543Smrg if (!ValidAtom(stuff->type)) 536706f2543Smrg { 537706f2543Smrg client->errorValue = stuff->type; 538706f2543Smrg return BadAtom; 539706f2543Smrg } 540706f2543Smrg 541706f2543Smrg err = RRChangeOutputProperty(output, stuff->property, 542706f2543Smrg stuff->type, (int)format, 543706f2543Smrg (int)mode, len, (pointer)&stuff[1], TRUE, TRUE); 544706f2543Smrg if (err != Success) 545706f2543Smrg return err; 546706f2543Smrg else 547706f2543Smrg return Success; 548706f2543Smrg} 549706f2543Smrg 550706f2543Smrgint 551706f2543SmrgProcRRDeleteOutputProperty (ClientPtr client) 552706f2543Smrg{ 553706f2543Smrg REQUEST(xRRDeleteOutputPropertyReq); 554706f2543Smrg RROutputPtr output; 555706f2543Smrg 556706f2543Smrg REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq); 557706f2543Smrg UpdateCurrentTime(); 558706f2543Smrg VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); 559706f2543Smrg 560706f2543Smrg if (!ValidAtom(stuff->property)) 561706f2543Smrg { 562706f2543Smrg client->errorValue = stuff->property; 563706f2543Smrg return BadAtom; 564706f2543Smrg } 565706f2543Smrg 566706f2543Smrg 567706f2543Smrg RRDeleteOutputProperty(output, stuff->property); 568706f2543Smrg return Success; 569706f2543Smrg} 570706f2543Smrg 571706f2543Smrgint 572706f2543SmrgProcRRGetOutputProperty (ClientPtr client) 573706f2543Smrg{ 574706f2543Smrg REQUEST(xRRGetOutputPropertyReq); 575706f2543Smrg RRPropertyPtr prop, *prev; 576706f2543Smrg RRPropertyValuePtr prop_value; 577706f2543Smrg unsigned long n, len, ind; 578706f2543Smrg RROutputPtr output; 579706f2543Smrg xRRGetOutputPropertyReply reply; 580706f2543Smrg char *extra = NULL; 581706f2543Smrg 582706f2543Smrg REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq); 583706f2543Smrg if (stuff->delete) 584706f2543Smrg UpdateCurrentTime(); 585706f2543Smrg VERIFY_RR_OUTPUT(stuff->output, output, 586706f2543Smrg stuff->delete ? DixWriteAccess : DixReadAccess); 587706f2543Smrg 588706f2543Smrg if (!ValidAtom(stuff->property)) 589706f2543Smrg { 590706f2543Smrg client->errorValue = stuff->property; 591706f2543Smrg return BadAtom; 592706f2543Smrg } 593706f2543Smrg if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) 594706f2543Smrg { 595706f2543Smrg client->errorValue = stuff->delete; 596706f2543Smrg return BadValue; 597706f2543Smrg } 598706f2543Smrg if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) 599706f2543Smrg { 600706f2543Smrg client->errorValue = stuff->type; 601706f2543Smrg return BadAtom; 602706f2543Smrg } 603706f2543Smrg 604706f2543Smrg for (prev = &output->properties; (prop = *prev); prev = &prop->next) 605706f2543Smrg if (prop->propertyName == stuff->property) 606706f2543Smrg break; 607706f2543Smrg 608706f2543Smrg reply.type = X_Reply; 609706f2543Smrg reply.sequenceNumber = client->sequence; 610706f2543Smrg if (!prop) 611706f2543Smrg { 612706f2543Smrg reply.nItems = 0; 613706f2543Smrg reply.length = 0; 614706f2543Smrg reply.bytesAfter = 0; 615706f2543Smrg reply.propertyType = None; 616706f2543Smrg reply.format = 0; 617706f2543Smrg if (client->swapped) { 618706f2543Smrg int n; 619706f2543Smrg 620706f2543Smrg swaps(&reply.sequenceNumber, n); 621706f2543Smrg swapl(&reply.length, n); 622706f2543Smrg swapl(&reply.propertyType, n); 623706f2543Smrg swapl(&reply.bytesAfter, n); 624706f2543Smrg swapl(&reply.nItems, n); 625706f2543Smrg } 626706f2543Smrg WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &reply); 627706f2543Smrg return Success; 628706f2543Smrg } 629706f2543Smrg 630706f2543Smrg if (prop->immutable && stuff->delete) 631706f2543Smrg return BadAccess; 632706f2543Smrg 633706f2543Smrg prop_value = RRGetOutputProperty(output, stuff->property, stuff->pending); 634706f2543Smrg if (!prop_value) 635706f2543Smrg return BadAtom; 636706f2543Smrg 637706f2543Smrg /* If the request type and actual type don't match. Return the 638706f2543Smrg property information, but not the data. */ 639706f2543Smrg 640706f2543Smrg if (((stuff->type != prop_value->type) && 641706f2543Smrg (stuff->type != AnyPropertyType)) 642706f2543Smrg ) 643706f2543Smrg { 644706f2543Smrg reply.bytesAfter = prop_value->size; 645706f2543Smrg reply.format = prop_value->format; 646706f2543Smrg reply.length = 0; 647706f2543Smrg reply.nItems = 0; 648706f2543Smrg reply.propertyType = prop_value->type; 649706f2543Smrg if (client->swapped) { 650706f2543Smrg int n; 651706f2543Smrg 652706f2543Smrg swaps(&reply.sequenceNumber, n); 653706f2543Smrg swapl(&reply.length, n); 654706f2543Smrg swapl(&reply.propertyType, n); 655706f2543Smrg swapl(&reply.bytesAfter, n); 656706f2543Smrg swapl(&reply.nItems, n); 657706f2543Smrg } 658706f2543Smrg WriteToClient(client, sizeof(xRRGetOutputPropertyReply), &reply); 659706f2543Smrg return Success; 660706f2543Smrg } 661706f2543Smrg 662706f2543Smrg/* 663706f2543Smrg * Return type, format, value to client 664706f2543Smrg */ 665706f2543Smrg n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */ 666706f2543Smrg ind = stuff->longOffset << 2; 667706f2543Smrg 668706f2543Smrg /* If longOffset is invalid such that it causes "len" to 669706f2543Smrg be negative, it's a value error. */ 670706f2543Smrg 671706f2543Smrg if (n < ind) 672706f2543Smrg { 673706f2543Smrg client->errorValue = stuff->longOffset; 674706f2543Smrg return BadValue; 675706f2543Smrg } 676706f2543Smrg 677706f2543Smrg len = min(n - ind, 4 * stuff->longLength); 678706f2543Smrg 679706f2543Smrg if (len) { 680706f2543Smrg extra = malloc(len); 681706f2543Smrg if (!extra) 682706f2543Smrg return BadAlloc; 683706f2543Smrg } 684706f2543Smrg reply.bytesAfter = n - (ind + len); 685706f2543Smrg reply.format = prop_value->format; 686706f2543Smrg reply.length = bytes_to_int32(len); 687706f2543Smrg if (prop_value->format) 688706f2543Smrg reply.nItems = len / (prop_value->format / 8); 689706f2543Smrg else 690706f2543Smrg reply.nItems = 0; 691706f2543Smrg reply.propertyType = prop_value->type; 692706f2543Smrg 693706f2543Smrg if (stuff->delete && (reply.bytesAfter == 0)) 694706f2543Smrg { 695706f2543Smrg xRROutputPropertyNotifyEvent event; 696706f2543Smrg 697706f2543Smrg event.type = RREventBase + RRNotify; 698706f2543Smrg event.subCode = RRNotify_OutputProperty; 699706f2543Smrg event.output = output->id; 700706f2543Smrg event.state = PropertyDelete; 701706f2543Smrg event.atom = prop->propertyName; 702706f2543Smrg event.timestamp = currentTime.milliseconds; 703706f2543Smrg RRDeliverPropertyEvent (output->pScreen, (xEvent *)&event); 704706f2543Smrg } 705706f2543Smrg 706706f2543Smrg if (client->swapped) { 707706f2543Smrg int n; 708706f2543Smrg 709706f2543Smrg swaps(&reply.sequenceNumber, n); 710706f2543Smrg swapl(&reply.length, n); 711706f2543Smrg swapl(&reply.propertyType, n); 712706f2543Smrg swapl(&reply.bytesAfter, n); 713706f2543Smrg swapl(&reply.nItems, n); 714706f2543Smrg } 715706f2543Smrg WriteToClient(client, sizeof(xGenericReply), &reply); 716706f2543Smrg if (len) 717706f2543Smrg { 718706f2543Smrg memcpy(extra, (char *)prop_value->data + ind, len); 719706f2543Smrg switch (reply.format) { 720706f2543Smrg case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; 721706f2543Smrg case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; 722706f2543Smrg default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; 723706f2543Smrg } 724706f2543Smrg WriteSwappedDataToClient(client, len, 725706f2543Smrg extra); 726706f2543Smrg free(extra); 727706f2543Smrg } 728706f2543Smrg 729706f2543Smrg if (stuff->delete && (reply.bytesAfter == 0)) 730706f2543Smrg { /* delete the Property */ 731706f2543Smrg *prev = prop->next; 732706f2543Smrg RRDestroyOutputProperty (prop); 733706f2543Smrg } 734706f2543Smrg return Success; 735706f2543Smrg} 736706f2543Smrg 737