| 1 | /* |
| 2 | * Copyright © 2003 Keith Packard |
| 3 | * |
| 4 | * Permission to use, copy, modify, distribute, and sell this software and its |
| 5 | * documentation for any purpose is hereby granted without fee, provided that |
| 6 | * the above copyright notice appear in all copies and that both that |
| 7 | * copyright notice and this permission notice appear in supporting |
| 8 | * documentation, and that the name of Keith Packard not be used in |
| 9 | * advertising or publicity pertaining to distribution of the software without |
| 10 | * specific, written prior permission. Keith Packard makes no |
| 11 | * representations about the suitability of this software for any purpose. It |
| 12 | * is provided "as is" without express or implied warranty. |
| 13 | * |
| 14 | * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
| 16 | * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
| 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 20 | * PERFORMANCE OF THIS SOFTWARE. |
| 21 | */ |
| 22 | |
| 23 | #ifdef HAVE_DIX_CONFIG_H |
| 24 | #include <dix-config.h> |
| 25 | #endif |
| 26 | |
| 27 | #include "xfixesint.h" |
| 28 | #include "scrnintstr.h" |
| 29 | #include <picturestr.h> |
| 30 | |
| 31 | #include <regionstr.h> |
| 32 | #include <gcstruct.h> |
| 33 | #include <window.h> |
| 34 | |
| 35 | RESTYPE RegionResType; |
| 36 | |
| 37 | static int |
| 38 | RegionResFree(pointer data, XID id) |
| 39 | { |
| 40 | RegionPtr pRegion = (RegionPtr) data; |
| 41 | |
| 42 | RegionDestroy(pRegion); |
| 43 | return Success; |
| 44 | } |
| 45 | |
| 46 | RegionPtr |
| 47 | XFixesRegionCopy(RegionPtr pRegion) |
| 48 | { |
| 49 | RegionPtr pNew = RegionCreate(RegionExtents(pRegion), |
| 50 | RegionNumRects(pRegion)); |
| 51 | |
| 52 | if (!pNew) |
| 53 | return 0; |
| 54 | if (!RegionCopy(pNew, pRegion)) { |
| 55 | RegionDestroy(pNew); |
| 56 | return 0; |
| 57 | } |
| 58 | return pNew; |
| 59 | } |
| 60 | |
| 61 | Bool |
| 62 | XFixesRegionInit(void) |
| 63 | { |
| 64 | RegionResType = CreateNewResourceType(RegionResFree, "XFixesRegion"); |
| 65 | |
| 66 | return RegionResType != 0; |
| 67 | } |
| 68 | |
| 69 | int |
| 70 | ProcXFixesCreateRegion(ClientPtr client) |
| 71 | { |
| 72 | int things; |
| 73 | RegionPtr pRegion; |
| 74 | |
| 75 | REQUEST(xXFixesCreateRegionReq); |
| 76 | |
| 77 | REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq); |
| 78 | LEGAL_NEW_RESOURCE(stuff->region, client); |
| 79 | |
| 80 | things = (client->req_len << 2) - sizeof(xXFixesCreateRegionReq); |
| 81 | if (things & 4) |
| 82 | return BadLength; |
| 83 | things >>= 3; |
| 84 | |
| 85 | pRegion = RegionFromRects(things, (xRectangle *) (stuff + 1), CT_UNSORTED); |
| 86 | if (!pRegion) |
| 87 | return BadAlloc; |
| 88 | if (!AddResource(stuff->region, RegionResType, (pointer) pRegion)) |
| 89 | return BadAlloc; |
| 90 | |
| 91 | return Success; |
| 92 | } |
| 93 | |
| 94 | int |
| 95 | SProcXFixesCreateRegion(ClientPtr client) |
| 96 | { |
| 97 | REQUEST(xXFixesCreateRegionReq); |
| 98 | |
| 99 | swaps(&stuff->length); |
| 100 | REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq); |
| 101 | swapl(&stuff->region); |
| 102 | SwapRestS(stuff); |
| 103 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 104 | } |
| 105 | |
| 106 | int |
| 107 | ProcXFixesCreateRegionFromBitmap(ClientPtr client) |
| 108 | { |
| 109 | RegionPtr pRegion; |
| 110 | PixmapPtr pPixmap; |
| 111 | int rc; |
| 112 | |
| 113 | REQUEST(xXFixesCreateRegionFromBitmapReq); |
| 114 | |
| 115 | REQUEST_SIZE_MATCH(xXFixesCreateRegionFromBitmapReq); |
| 116 | LEGAL_NEW_RESOURCE(stuff->region, client); |
| 117 | |
| 118 | rc = dixLookupResourceByType((pointer *) &pPixmap, stuff->bitmap, RT_PIXMAP, |
| 119 | client, DixReadAccess); |
| 120 | if (rc != Success) { |
| 121 | client->errorValue = stuff->bitmap; |
| 122 | return rc; |
| 123 | } |
| 124 | if (pPixmap->drawable.depth != 1) |
| 125 | return BadMatch; |
| 126 | |
| 127 | pRegion = BitmapToRegion(pPixmap->drawable.pScreen, pPixmap); |
| 128 | |
| 129 | if (!pRegion) |
| 130 | return BadAlloc; |
| 131 | |
| 132 | if (!AddResource(stuff->region, RegionResType, (pointer) pRegion)) |
| 133 | return BadAlloc; |
| 134 | |
| 135 | return Success; |
| 136 | } |
| 137 | |
| 138 | int |
| 139 | SProcXFixesCreateRegionFromBitmap(ClientPtr client) |
| 140 | { |
| 141 | REQUEST(xXFixesCreateRegionFromBitmapReq); |
| 142 | |
| 143 | swaps(&stuff->length); |
| 144 | REQUEST_SIZE_MATCH(xXFixesCreateRegionFromBitmapReq); |
| 145 | swapl(&stuff->region); |
| 146 | swapl(&stuff->bitmap); |
| 147 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 148 | } |
| 149 | |
| 150 | int |
| 151 | ProcXFixesCreateRegionFromWindow(ClientPtr client) |
| 152 | { |
| 153 | RegionPtr pRegion; |
| 154 | Bool copy = TRUE; |
| 155 | WindowPtr pWin; |
| 156 | int rc; |
| 157 | |
| 158 | REQUEST(xXFixesCreateRegionFromWindowReq); |
| 159 | |
| 160 | REQUEST_SIZE_MATCH(xXFixesCreateRegionFromWindowReq); |
| 161 | LEGAL_NEW_RESOURCE(stuff->region, client); |
| 162 | rc = dixLookupResourceByType((pointer *) &pWin, stuff->window, RT_WINDOW, |
| 163 | client, DixGetAttrAccess); |
| 164 | if (rc != Success) { |
| 165 | client->errorValue = stuff->window; |
| 166 | return rc; |
| 167 | } |
| 168 | switch (stuff->kind) { |
| 169 | case WindowRegionBounding: |
| 170 | pRegion = wBoundingShape(pWin); |
| 171 | if (!pRegion) { |
| 172 | pRegion = CreateBoundingShape(pWin); |
| 173 | copy = FALSE; |
| 174 | } |
| 175 | break; |
| 176 | case WindowRegionClip: |
| 177 | pRegion = wClipShape(pWin); |
| 178 | if (!pRegion) { |
| 179 | pRegion = CreateClipShape(pWin); |
| 180 | copy = FALSE; |
| 181 | } |
| 182 | break; |
| 183 | default: |
| 184 | client->errorValue = stuff->kind; |
| 185 | return BadValue; |
| 186 | } |
| 187 | if (copy && pRegion) |
| 188 | pRegion = XFixesRegionCopy(pRegion); |
| 189 | if (!pRegion) |
| 190 | return BadAlloc; |
| 191 | if (!AddResource(stuff->region, RegionResType, (pointer) pRegion)) |
| 192 | return BadAlloc; |
| 193 | |
| 194 | return Success; |
| 195 | } |
| 196 | |
| 197 | int |
| 198 | SProcXFixesCreateRegionFromWindow(ClientPtr client) |
| 199 | { |
| 200 | REQUEST(xXFixesCreateRegionFromWindowReq); |
| 201 | |
| 202 | swaps(&stuff->length); |
| 203 | REQUEST_SIZE_MATCH(xXFixesCreateRegionFromWindowReq); |
| 204 | swapl(&stuff->region); |
| 205 | swapl(&stuff->window); |
| 206 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 207 | } |
| 208 | |
| 209 | int |
| 210 | ProcXFixesCreateRegionFromGC(ClientPtr client) |
| 211 | { |
| 212 | RegionPtr pRegion, pClip; |
| 213 | GCPtr pGC; |
| 214 | int rc; |
| 215 | |
| 216 | REQUEST(xXFixesCreateRegionFromGCReq); |
| 217 | |
| 218 | REQUEST_SIZE_MATCH(xXFixesCreateRegionFromGCReq); |
| 219 | LEGAL_NEW_RESOURCE(stuff->region, client); |
| 220 | |
| 221 | rc = dixLookupGC(&pGC, stuff->gc, client, DixGetAttrAccess); |
| 222 | if (rc != Success) |
| 223 | return rc; |
| 224 | |
| 225 | switch (pGC->clientClipType) { |
| 226 | case CT_PIXMAP: |
| 227 | pRegion = BitmapToRegion(pGC->pScreen, (PixmapPtr) pGC->clientClip); |
| 228 | if (!pRegion) |
| 229 | return BadAlloc; |
| 230 | break; |
| 231 | case CT_REGION: |
| 232 | pClip = (RegionPtr) pGC->clientClip; |
| 233 | pRegion = XFixesRegionCopy(pClip); |
| 234 | if (!pRegion) |
| 235 | return BadAlloc; |
| 236 | break; |
| 237 | default: |
| 238 | return BadImplementation; /* assume sane server bits */ |
| 239 | } |
| 240 | |
| 241 | if (!AddResource(stuff->region, RegionResType, (pointer) pRegion)) |
| 242 | return BadAlloc; |
| 243 | |
| 244 | return Success; |
| 245 | } |
| 246 | |
| 247 | int |
| 248 | SProcXFixesCreateRegionFromGC(ClientPtr client) |
| 249 | { |
| 250 | REQUEST(xXFixesCreateRegionFromGCReq); |
| 251 | |
| 252 | swaps(&stuff->length); |
| 253 | REQUEST_SIZE_MATCH(xXFixesCreateRegionFromGCReq); |
| 254 | swapl(&stuff->region); |
| 255 | swapl(&stuff->gc); |
| 256 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 257 | } |
| 258 | |
| 259 | int |
| 260 | ProcXFixesCreateRegionFromPicture(ClientPtr client) |
| 261 | { |
| 262 | RegionPtr pRegion; |
| 263 | PicturePtr pPicture; |
| 264 | |
| 265 | REQUEST(xXFixesCreateRegionFromPictureReq); |
| 266 | |
| 267 | REQUEST_SIZE_MATCH(xXFixesCreateRegionFromPictureReq); |
| 268 | LEGAL_NEW_RESOURCE(stuff->region, client); |
| 269 | |
| 270 | VERIFY_PICTURE(pPicture, stuff->picture, client, DixGetAttrAccess); |
| 271 | |
| 272 | switch (pPicture->clientClipType) { |
| 273 | case CT_PIXMAP: |
| 274 | pRegion = BitmapToRegion(pPicture->pDrawable->pScreen, |
| 275 | (PixmapPtr) pPicture->clientClip); |
| 276 | if (!pRegion) |
| 277 | return BadAlloc; |
| 278 | break; |
| 279 | case CT_REGION: |
| 280 | pRegion = XFixesRegionCopy((RegionPtr) pPicture->clientClip); |
| 281 | if (!pRegion) |
| 282 | return BadAlloc; |
| 283 | break; |
| 284 | default: |
| 285 | return BadImplementation; /* assume sane server bits */ |
| 286 | } |
| 287 | |
| 288 | if (!AddResource(stuff->region, RegionResType, (pointer) pRegion)) |
| 289 | return BadAlloc; |
| 290 | |
| 291 | return Success; |
| 292 | } |
| 293 | |
| 294 | int |
| 295 | SProcXFixesCreateRegionFromPicture(ClientPtr client) |
| 296 | { |
| 297 | REQUEST(xXFixesCreateRegionFromPictureReq); |
| 298 | |
| 299 | swaps(&stuff->length); |
| 300 | REQUEST_SIZE_MATCH(xXFixesCreateRegionFromPictureReq); |
| 301 | swapl(&stuff->region); |
| 302 | swapl(&stuff->picture); |
| 303 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 304 | } |
| 305 | |
| 306 | int |
| 307 | ProcXFixesDestroyRegion(ClientPtr client) |
| 308 | { |
| 309 | REQUEST(xXFixesDestroyRegionReq); |
| 310 | RegionPtr pRegion; |
| 311 | |
| 312 | REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq); |
| 313 | VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess); |
| 314 | FreeResource(stuff->region, RT_NONE); |
| 315 | return Success; |
| 316 | } |
| 317 | |
| 318 | int |
| 319 | SProcXFixesDestroyRegion(ClientPtr client) |
| 320 | { |
| 321 | REQUEST(xXFixesDestroyRegionReq); |
| 322 | |
| 323 | swaps(&stuff->length); |
| 324 | REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq); |
| 325 | swapl(&stuff->region); |
| 326 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 327 | } |
| 328 | |
| 329 | int |
| 330 | ProcXFixesSetRegion(ClientPtr client) |
| 331 | { |
| 332 | int things; |
| 333 | RegionPtr pRegion, pNew; |
| 334 | |
| 335 | REQUEST(xXFixesSetRegionReq); |
| 336 | |
| 337 | REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq); |
| 338 | VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess); |
| 339 | |
| 340 | things = (client->req_len << 2) - sizeof(xXFixesCreateRegionReq); |
| 341 | if (things & 4) |
| 342 | return BadLength; |
| 343 | things >>= 3; |
| 344 | |
| 345 | pNew = RegionFromRects(things, (xRectangle *) (stuff + 1), CT_UNSORTED); |
| 346 | if (!pNew) |
| 347 | return BadAlloc; |
| 348 | if (!RegionCopy(pRegion, pNew)) { |
| 349 | RegionDestroy(pNew); |
| 350 | return BadAlloc; |
| 351 | } |
| 352 | RegionDestroy(pNew); |
| 353 | return Success; |
| 354 | } |
| 355 | |
| 356 | int |
| 357 | SProcXFixesSetRegion(ClientPtr client) |
| 358 | { |
| 359 | REQUEST(xXFixesSetRegionReq); |
| 360 | |
| 361 | swaps(&stuff->length); |
| 362 | REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq); |
| 363 | swapl(&stuff->region); |
| 364 | SwapRestS(stuff); |
| 365 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 366 | } |
| 367 | |
| 368 | int |
| 369 | ProcXFixesCopyRegion(ClientPtr client) |
| 370 | { |
| 371 | RegionPtr pSource, pDestination; |
| 372 | |
| 373 | REQUEST(xXFixesCopyRegionReq); |
| 374 | |
| 375 | VERIFY_REGION(pSource, stuff->source, client, DixReadAccess); |
| 376 | VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess); |
| 377 | |
| 378 | if (!RegionCopy(pDestination, pSource)) |
| 379 | return BadAlloc; |
| 380 | |
| 381 | return Success; |
| 382 | } |
| 383 | |
| 384 | int |
| 385 | SProcXFixesCopyRegion(ClientPtr client) |
| 386 | { |
| 387 | REQUEST(xXFixesCopyRegionReq); |
| 388 | |
| 389 | swaps(&stuff->length); |
| 390 | REQUEST_AT_LEAST_SIZE(xXFixesCopyRegionReq); |
| 391 | swapl(&stuff->source); |
| 392 | swapl(&stuff->destination); |
| 393 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 394 | } |
| 395 | |
| 396 | int |
| 397 | ProcXFixesCombineRegion(ClientPtr client) |
| 398 | { |
| 399 | RegionPtr pSource1, pSource2, pDestination; |
| 400 | |
| 401 | REQUEST(xXFixesCombineRegionReq); |
| 402 | |
| 403 | REQUEST_SIZE_MATCH(xXFixesCombineRegionReq); |
| 404 | VERIFY_REGION(pSource1, stuff->source1, client, DixReadAccess); |
| 405 | VERIFY_REGION(pSource2, stuff->source2, client, DixReadAccess); |
| 406 | VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess); |
| 407 | |
| 408 | switch (stuff->xfixesReqType) { |
| 409 | case X_XFixesUnionRegion: |
| 410 | if (!RegionUnion(pDestination, pSource1, pSource2)) |
| 411 | return BadAlloc; |
| 412 | break; |
| 413 | case X_XFixesIntersectRegion: |
| 414 | if (!RegionIntersect(pDestination, pSource1, pSource2)) |
| 415 | return BadAlloc; |
| 416 | break; |
| 417 | case X_XFixesSubtractRegion: |
| 418 | if (!RegionSubtract(pDestination, pSource1, pSource2)) |
| 419 | return BadAlloc; |
| 420 | break; |
| 421 | } |
| 422 | |
| 423 | return Success; |
| 424 | } |
| 425 | |
| 426 | int |
| 427 | SProcXFixesCombineRegion(ClientPtr client) |
| 428 | { |
| 429 | REQUEST(xXFixesCombineRegionReq); |
| 430 | |
| 431 | swaps(&stuff->length); |
| 432 | REQUEST_SIZE_MATCH(xXFixesCombineRegionReq); |
| 433 | swapl(&stuff->source1); |
| 434 | swapl(&stuff->source2); |
| 435 | swapl(&stuff->destination); |
| 436 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 437 | } |
| 438 | |
| 439 | int |
| 440 | ProcXFixesInvertRegion(ClientPtr client) |
| 441 | { |
| 442 | RegionPtr pSource, pDestination; |
| 443 | BoxRec bounds; |
| 444 | |
| 445 | REQUEST(xXFixesInvertRegionReq); |
| 446 | |
| 447 | REQUEST_SIZE_MATCH(xXFixesInvertRegionReq); |
| 448 | VERIFY_REGION(pSource, stuff->source, client, DixReadAccess); |
| 449 | VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess); |
| 450 | |
| 451 | /* Compute bounds, limit to 16 bits */ |
| 452 | bounds.x1 = stuff->x; |
| 453 | bounds.y1 = stuff->y; |
| 454 | if ((int) stuff->x + (int) stuff->width > MAXSHORT) |
| 455 | bounds.x2 = MAXSHORT; |
| 456 | else |
| 457 | bounds.x2 = stuff->x + stuff->width; |
| 458 | |
| 459 | if ((int) stuff->y + (int) stuff->height > MAXSHORT) |
| 460 | bounds.y2 = MAXSHORT; |
| 461 | else |
| 462 | bounds.y2 = stuff->y + stuff->height; |
| 463 | |
| 464 | if (!RegionInverse(pDestination, pSource, &bounds)) |
| 465 | return BadAlloc; |
| 466 | |
| 467 | return Success; |
| 468 | } |
| 469 | |
| 470 | int |
| 471 | SProcXFixesInvertRegion(ClientPtr client) |
| 472 | { |
| 473 | REQUEST(xXFixesInvertRegionReq); |
| 474 | |
| 475 | swaps(&stuff->length); |
| 476 | REQUEST_SIZE_MATCH(xXFixesInvertRegionReq); |
| 477 | swapl(&stuff->source); |
| 478 | swaps(&stuff->x); |
| 479 | swaps(&stuff->y); |
| 480 | swaps(&stuff->width); |
| 481 | swaps(&stuff->height); |
| 482 | swapl(&stuff->destination); |
| 483 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 484 | } |
| 485 | |
| 486 | int |
| 487 | ProcXFixesTranslateRegion(ClientPtr client) |
| 488 | { |
| 489 | RegionPtr pRegion; |
| 490 | |
| 491 | REQUEST(xXFixesTranslateRegionReq); |
| 492 | |
| 493 | REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq); |
| 494 | VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess); |
| 495 | |
| 496 | RegionTranslate(pRegion, stuff->dx, stuff->dy); |
| 497 | return Success; |
| 498 | } |
| 499 | |
| 500 | int |
| 501 | SProcXFixesTranslateRegion(ClientPtr client) |
| 502 | { |
| 503 | REQUEST(xXFixesTranslateRegionReq); |
| 504 | |
| 505 | swaps(&stuff->length); |
| 506 | REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq); |
| 507 | swapl(&stuff->region); |
| 508 | swaps(&stuff->dx); |
| 509 | swaps(&stuff->dy); |
| 510 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 511 | } |
| 512 | |
| 513 | int |
| 514 | ProcXFixesRegionExtents(ClientPtr client) |
| 515 | { |
| 516 | RegionPtr pSource, pDestination; |
| 517 | |
| 518 | REQUEST(xXFixesRegionExtentsReq); |
| 519 | |
| 520 | REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq); |
| 521 | VERIFY_REGION(pSource, stuff->source, client, DixReadAccess); |
| 522 | VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess); |
| 523 | |
| 524 | RegionReset(pDestination, RegionExtents(pSource)); |
| 525 | |
| 526 | return Success; |
| 527 | } |
| 528 | |
| 529 | int |
| 530 | SProcXFixesRegionExtents(ClientPtr client) |
| 531 | { |
| 532 | REQUEST(xXFixesRegionExtentsReq); |
| 533 | |
| 534 | swaps(&stuff->length); |
| 535 | REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq); |
| 536 | swapl(&stuff->source); |
| 537 | swapl(&stuff->destination); |
| 538 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 539 | } |
| 540 | |
| 541 | int |
| 542 | ProcXFixesFetchRegion(ClientPtr client) |
| 543 | { |
| 544 | RegionPtr pRegion; |
| 545 | xXFixesFetchRegionReply *reply; |
| 546 | xRectangle *pRect; |
| 547 | BoxPtr pExtent; |
| 548 | BoxPtr pBox; |
| 549 | int i, nBox; |
| 550 | |
| 551 | REQUEST(xXFixesFetchRegionReq); |
| 552 | |
| 553 | REQUEST_SIZE_MATCH(xXFixesFetchRegionReq); |
| 554 | VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess); |
| 555 | |
| 556 | pExtent = RegionExtents(pRegion); |
| 557 | pBox = RegionRects(pRegion); |
| 558 | nBox = RegionNumRects(pRegion); |
| 559 | |
| 560 | reply = calloc(sizeof(xXFixesFetchRegionReply) + nBox * sizeof(xRectangle), |
| 561 | 1); |
| 562 | if (!reply) |
| 563 | return BadAlloc; |
| 564 | reply->type = X_Reply; |
| 565 | reply->sequenceNumber = client->sequence; |
| 566 | reply->length = nBox << 1; |
| 567 | reply->x = pExtent->x1; |
| 568 | reply->y = pExtent->y1; |
| 569 | reply->width = pExtent->x2 - pExtent->x1; |
| 570 | reply->height = pExtent->y2 - pExtent->y1; |
| 571 | |
| 572 | pRect = (xRectangle *) (reply + 1); |
| 573 | for (i = 0; i < nBox; i++) { |
| 574 | pRect[i].x = pBox[i].x1; |
| 575 | pRect[i].y = pBox[i].y1; |
| 576 | pRect[i].width = pBox[i].x2 - pBox[i].x1; |
| 577 | pRect[i].height = pBox[i].y2 - pBox[i].y1; |
| 578 | } |
| 579 | if (client->swapped) { |
| 580 | swaps(&reply->sequenceNumber); |
| 581 | swapl(&reply->length); |
| 582 | swaps(&reply->x); |
| 583 | swaps(&reply->y); |
| 584 | swaps(&reply->width); |
| 585 | swaps(&reply->height); |
| 586 | SwapShorts((INT16 *) pRect, nBox * 4); |
| 587 | } |
| 588 | WriteToClient(client, sizeof(xXFixesFetchRegionReply) + |
| 589 | nBox * sizeof(xRectangle), (char *) reply); |
| 590 | free(reply); |
| 591 | return Success; |
| 592 | } |
| 593 | |
| 594 | int |
| 595 | SProcXFixesFetchRegion(ClientPtr client) |
| 596 | { |
| 597 | REQUEST(xXFixesFetchRegionReq); |
| 598 | |
| 599 | swaps(&stuff->length); |
| 600 | REQUEST_SIZE_MATCH(xXFixesFetchRegionReq); |
| 601 | swapl(&stuff->region); |
| 602 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 603 | } |
| 604 | |
| 605 | int |
| 606 | ProcXFixesSetGCClipRegion(ClientPtr client) |
| 607 | { |
| 608 | GCPtr pGC; |
| 609 | RegionPtr pRegion; |
| 610 | ChangeGCVal vals[2]; |
| 611 | int rc; |
| 612 | |
| 613 | REQUEST(xXFixesSetGCClipRegionReq); |
| 614 | REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq); |
| 615 | |
| 616 | rc = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); |
| 617 | if (rc != Success) |
| 618 | return rc; |
| 619 | |
| 620 | VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess); |
| 621 | |
| 622 | if (pRegion) { |
| 623 | pRegion = XFixesRegionCopy(pRegion); |
| 624 | if (!pRegion) |
| 625 | return BadAlloc; |
| 626 | } |
| 627 | |
| 628 | vals[0].val = stuff->xOrigin; |
| 629 | vals[1].val = stuff->yOrigin; |
| 630 | ChangeGC(NullClient, pGC, GCClipXOrigin | GCClipYOrigin, vals); |
| 631 | (*pGC->funcs->ChangeClip) (pGC, pRegion ? CT_REGION : CT_NONE, |
| 632 | (pointer) pRegion, 0); |
| 633 | |
| 634 | return Success; |
| 635 | } |
| 636 | |
| 637 | int |
| 638 | SProcXFixesSetGCClipRegion(ClientPtr client) |
| 639 | { |
| 640 | REQUEST(xXFixesSetGCClipRegionReq); |
| 641 | |
| 642 | swaps(&stuff->length); |
| 643 | REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq); |
| 644 | swapl(&stuff->gc); |
| 645 | swapl(&stuff->region); |
| 646 | swaps(&stuff->xOrigin); |
| 647 | swaps(&stuff->yOrigin); |
| 648 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 649 | } |
| 650 | |
| 651 | typedef RegionPtr (*CreateDftPtr) (WindowPtr pWin); |
| 652 | |
| 653 | int |
| 654 | ProcXFixesSetWindowShapeRegion(ClientPtr client) |
| 655 | { |
| 656 | WindowPtr pWin; |
| 657 | RegionPtr pRegion; |
| 658 | RegionPtr *pDestRegion; |
| 659 | int rc; |
| 660 | |
| 661 | REQUEST(xXFixesSetWindowShapeRegionReq); |
| 662 | |
| 663 | REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq); |
| 664 | rc = dixLookupResourceByType((pointer *) &pWin, stuff->dest, RT_WINDOW, |
| 665 | client, DixSetAttrAccess); |
| 666 | if (rc != Success) { |
| 667 | client->errorValue = stuff->dest; |
| 668 | return rc; |
| 669 | } |
| 670 | VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixWriteAccess); |
| 671 | switch (stuff->destKind) { |
| 672 | case ShapeBounding: |
| 673 | case ShapeClip: |
| 674 | case ShapeInput: |
| 675 | break; |
| 676 | default: |
| 677 | client->errorValue = stuff->destKind; |
| 678 | return BadValue; |
| 679 | } |
| 680 | if (pRegion) { |
| 681 | pRegion = XFixesRegionCopy(pRegion); |
| 682 | if (!pRegion) |
| 683 | return BadAlloc; |
| 684 | if (!pWin->optional) |
| 685 | MakeWindowOptional(pWin); |
| 686 | switch (stuff->destKind) { |
| 687 | default: |
| 688 | case ShapeBounding: |
| 689 | pDestRegion = &pWin->optional->boundingShape; |
| 690 | break; |
| 691 | case ShapeClip: |
| 692 | pDestRegion = &pWin->optional->clipShape; |
| 693 | break; |
| 694 | case ShapeInput: |
| 695 | pDestRegion = &pWin->optional->inputShape; |
| 696 | break; |
| 697 | } |
| 698 | if (stuff->xOff || stuff->yOff) |
| 699 | RegionTranslate(pRegion, stuff->xOff, stuff->yOff); |
| 700 | } |
| 701 | else { |
| 702 | if (pWin->optional) { |
| 703 | switch (stuff->destKind) { |
| 704 | default: |
| 705 | case ShapeBounding: |
| 706 | pDestRegion = &pWin->optional->boundingShape; |
| 707 | break; |
| 708 | case ShapeClip: |
| 709 | pDestRegion = &pWin->optional->clipShape; |
| 710 | break; |
| 711 | case ShapeInput: |
| 712 | pDestRegion = &pWin->optional->inputShape; |
| 713 | break; |
| 714 | } |
| 715 | } |
| 716 | else |
| 717 | pDestRegion = &pRegion; /* a NULL region pointer */ |
| 718 | } |
| 719 | if (*pDestRegion) |
| 720 | RegionDestroy(*pDestRegion); |
| 721 | *pDestRegion = pRegion; |
| 722 | (*pWin->drawable.pScreen->SetShape) (pWin, stuff->destKind); |
| 723 | SendShapeNotify(pWin, stuff->destKind); |
| 724 | return Success; |
| 725 | } |
| 726 | |
| 727 | int |
| 728 | SProcXFixesSetWindowShapeRegion(ClientPtr client) |
| 729 | { |
| 730 | REQUEST(xXFixesSetWindowShapeRegionReq); |
| 731 | |
| 732 | swaps(&stuff->length); |
| 733 | REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq); |
| 734 | swapl(&stuff->dest); |
| 735 | swaps(&stuff->xOff); |
| 736 | swaps(&stuff->yOff); |
| 737 | swapl(&stuff->region); |
| 738 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 739 | } |
| 740 | |
| 741 | int |
| 742 | ProcXFixesSetPictureClipRegion(ClientPtr client) |
| 743 | { |
| 744 | PicturePtr pPicture; |
| 745 | RegionPtr pRegion; |
| 746 | |
| 747 | REQUEST(xXFixesSetPictureClipRegionReq); |
| 748 | |
| 749 | REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq); |
| 750 | VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess); |
| 751 | VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess); |
| 752 | |
| 753 | return SetPictureClipRegion(pPicture, stuff->xOrigin, stuff->yOrigin, |
| 754 | pRegion); |
| 755 | } |
| 756 | |
| 757 | int |
| 758 | SProcXFixesSetPictureClipRegion(ClientPtr client) |
| 759 | { |
| 760 | REQUEST(xXFixesSetPictureClipRegionReq); |
| 761 | |
| 762 | swaps(&stuff->length); |
| 763 | REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq); |
| 764 | swapl(&stuff->picture); |
| 765 | swapl(&stuff->region); |
| 766 | swaps(&stuff->xOrigin); |
| 767 | swaps(&stuff->yOrigin); |
| 768 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 769 | } |
| 770 | |
| 771 | int |
| 772 | ProcXFixesExpandRegion(ClientPtr client) |
| 773 | { |
| 774 | RegionPtr pSource, pDestination; |
| 775 | |
| 776 | REQUEST(xXFixesExpandRegionReq); |
| 777 | BoxPtr pTmp; |
| 778 | BoxPtr pSrc; |
| 779 | int nBoxes; |
| 780 | int i; |
| 781 | |
| 782 | REQUEST_SIZE_MATCH(xXFixesExpandRegionReq); |
| 783 | VERIFY_REGION(pSource, stuff->source, client, DixReadAccess); |
| 784 | VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess); |
| 785 | |
| 786 | nBoxes = RegionNumRects(pSource); |
| 787 | pSrc = RegionRects(pSource); |
| 788 | if (nBoxes) { |
| 789 | pTmp = malloc(nBoxes * sizeof(BoxRec)); |
| 790 | if (!pTmp) |
| 791 | return BadAlloc; |
| 792 | for (i = 0; i < nBoxes; i++) { |
| 793 | pTmp[i].x1 = pSrc[i].x1 - stuff->left; |
| 794 | pTmp[i].x2 = pSrc[i].x2 + stuff->right; |
| 795 | pTmp[i].y1 = pSrc[i].y1 - stuff->top; |
| 796 | pTmp[i].y2 = pSrc[i].y2 + stuff->bottom; |
| 797 | } |
| 798 | RegionEmpty(pDestination); |
| 799 | for (i = 0; i < nBoxes; i++) { |
| 800 | RegionRec r; |
| 801 | |
| 802 | RegionInit(&r, &pTmp[i], 0); |
| 803 | RegionUnion(pDestination, pDestination, &r); |
| 804 | } |
| 805 | free(pTmp); |
| 806 | } |
| 807 | return Success; |
| 808 | } |
| 809 | |
| 810 | int |
| 811 | SProcXFixesExpandRegion(ClientPtr client) |
| 812 | { |
| 813 | REQUEST(xXFixesExpandRegionReq); |
| 814 | |
| 815 | swaps(&stuff->length); |
| 816 | REQUEST_SIZE_MATCH(xXFixesExpandRegionReq); |
| 817 | swapl(&stuff->source); |
| 818 | swapl(&stuff->destination); |
| 819 | swaps(&stuff->left); |
| 820 | swaps(&stuff->right); |
| 821 | swaps(&stuff->top); |
| 822 | swaps(&stuff->bottom); |
| 823 | return (*ProcXFixesVector[stuff->xfixesReqType]) (client); |
| 824 | } |
| 825 | |
| 826 | #ifdef PANORAMIX |
| 827 | #include "panoramiX.h" |
| 828 | #include "panoramiXsrv.h" |
| 829 | |
| 830 | int |
| 831 | PanoramiXFixesSetGCClipRegion(ClientPtr client) |
| 832 | { |
| 833 | REQUEST(xXFixesSetGCClipRegionReq); |
| 834 | int result = Success, j; |
| 835 | PanoramiXRes *gc; |
| 836 | |
| 837 | REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq); |
| 838 | |
| 839 | if ((result = dixLookupResourceByType((void **) &gc, stuff->gc, XRT_GC, |
| 840 | client, DixWriteAccess))) { |
| 841 | client->errorValue = stuff->gc; |
| 842 | return result; |
| 843 | } |
| 844 | |
| 845 | FOR_NSCREENS_BACKWARD(j) { |
| 846 | stuff->gc = gc->info[j].id; |
| 847 | result = (*PanoramiXSaveXFixesVector[X_XFixesSetGCClipRegion]) (client); |
| 848 | if (result != Success) |
| 849 | break; |
| 850 | } |
| 851 | |
| 852 | return result; |
| 853 | } |
| 854 | |
| 855 | int |
| 856 | PanoramiXFixesSetWindowShapeRegion(ClientPtr client) |
| 857 | { |
| 858 | int result = Success, j; |
| 859 | PanoramiXRes *win; |
| 860 | RegionPtr reg = NULL; |
| 861 | |
| 862 | REQUEST(xXFixesSetWindowShapeRegionReq); |
| 863 | |
| 864 | REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq); |
| 865 | |
| 866 | if ((result = dixLookupResourceByType((void **) &win, stuff->dest, |
| 867 | XRT_WINDOW, client, |
| 868 | DixWriteAccess))) { |
| 869 | client->errorValue = stuff->dest; |
| 870 | return result; |
| 871 | } |
| 872 | |
| 873 | if (win->u.win.root) |
| 874 | VERIFY_REGION_OR_NONE(reg, stuff->region, client, DixReadAccess); |
| 875 | |
| 876 | FOR_NSCREENS_FORWARD(j) { |
| 877 | ScreenPtr screen = screenInfo.screens[j]; |
| 878 | stuff->dest = win->info[j].id; |
| 879 | |
| 880 | if (reg) |
| 881 | RegionTranslate(reg, -screen->x, -screen->y); |
| 882 | |
| 883 | result = |
| 884 | (*PanoramiXSaveXFixesVector[X_XFixesSetWindowShapeRegion]) (client); |
| 885 | |
| 886 | if (reg) |
| 887 | RegionTranslate(reg, screen->x, screen->y); |
| 888 | |
| 889 | if (result != Success) |
| 890 | break; |
| 891 | } |
| 892 | |
| 893 | return result; |
| 894 | } |
| 895 | |
| 896 | int |
| 897 | PanoramiXFixesSetPictureClipRegion(ClientPtr client) |
| 898 | { |
| 899 | REQUEST(xXFixesSetPictureClipRegionReq); |
| 900 | int result = Success, j; |
| 901 | PanoramiXRes *pict; |
| 902 | RegionPtr reg = NULL; |
| 903 | |
| 904 | REQUEST_SIZE_MATCH(xXFixesSetPictureClipRegionReq); |
| 905 | |
| 906 | if ((result = dixLookupResourceByType((void **) &pict, stuff->picture, |
| 907 | XRT_PICTURE, client, |
| 908 | DixWriteAccess))) { |
| 909 | client->errorValue = stuff->picture; |
| 910 | return result; |
| 911 | } |
| 912 | |
| 913 | if (pict->u.pict.root) |
| 914 | VERIFY_REGION_OR_NONE(reg, stuff->region, client, DixReadAccess); |
| 915 | |
| 916 | FOR_NSCREENS_BACKWARD(j) { |
| 917 | ScreenPtr screen = screenInfo.screens[j]; |
| 918 | stuff->picture = pict->info[j].id; |
| 919 | |
| 920 | if (reg) |
| 921 | RegionTranslate(reg, -screen->x, -screen->y); |
| 922 | |
| 923 | result = |
| 924 | (*PanoramiXSaveXFixesVector[X_XFixesSetPictureClipRegion]) (client); |
| 925 | |
| 926 | if (reg) |
| 927 | RegionTranslate(reg, screen->x, screen->y); |
| 928 | |
| 929 | if (result != Success) |
| 930 | break; |
| 931 | } |
| 932 | |
| 933 | return result; |
| 934 | } |
| 935 | |
| 936 | #endif |