1 /************************************************************ 2 3 Copyright 1987, 1989, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21 Except as contained in this notice, the name of The Open Group shall not be 22 used in advertising or otherwise to promote the sale, use or other dealings 23 in this Software without prior written authorization from The Open Group. 24 25 Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 26 27 All Rights Reserved 28 29 Permission to use, copy, modify, and distribute this software and its 30 documentation for any purpose and without fee is hereby granted, 31 provided that the above copyright notice appear in all copies and that 32 both that copyright notice and this permission notice appear in 33 supporting documentation, and that the name of Digital not be 34 used in advertising or publicity pertaining to distribution of the 35 software without specific, written prior permission. 36 37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43 SOFTWARE. 44 45 ********************************************************/ 46 47 /* The panoramix components contained the following notice */ 48 /***************************************************************** 49 50 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 51 52 Permission is hereby granted, free of charge, to any person obtaining a copy 53 of this software and associated documentation files (the "Software"), to deal 54 in the Software without restriction, including without limitation the rights 55 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 56 copies of the Software. 57 58 The above copyright notice and this permission notice shall be included in 59 all copies or substantial portions of the Software. 60 61 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 64 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 65 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 66 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 67 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 68 69 Except as contained in this notice, the name of Digital Equipment Corporation 70 shall not be used in advertising or otherwise to promote the sale, use or other 71 dealings in this Software without prior written authorization from Digital 72 Equipment Corporation. 73 74 ******************************************************************/ 75 76 /* XSERVER_DTRACE additions: 77 * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved. 78 * 79 * Permission is hereby granted, free of charge, to any person obtaining a 80 * copy of this software and associated documentation files (the "Software"), 81 * to deal in the Software without restriction, including without limitation 82 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 83 * and/or sell copies of the Software, and to permit persons to whom the 84 * Software is furnished to do so, subject to the following conditions: 85 * 86 * The above copyright notice and this permission notice (including the next 87 * paragraph) shall be included in all copies or substantial portions of the 88 * Software. 89 * 90 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 91 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 92 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 93 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 94 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 95 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 96 * DEALINGS IN THE SOFTWARE. 97 */ 98 99 #ifdef HAVE_DIX_CONFIG_H 100 #include <dix-config.h> 101 #include <version-config.h> 102 #endif 103 104 #ifdef PANORAMIX_DEBUG 105 #include <stdio.h> 106 int ProcInitialConnection(); 107 #endif 108 109 #include "windowstr.h" 110 #include <X11/fonts/fontstruct.h> 111 #include <X11/fonts/libxfont2.h> 112 #include "dixfontstr.h" 113 #include "gcstruct.h" 114 #include "selection.h" 115 #include "colormapst.h" 116 #include "cursorstr.h" 117 #include "scrnintstr.h" 118 #include "opaque.h" 119 #include "input.h" 120 #include "servermd.h" 121 #include "extnsionst.h" 122 #include "dixfont.h" 123 #include "dispatch.h" 124 #include "swaprep.h" 125 #include "swapreq.h" 126 #include "privates.h" 127 #include "xace.h" 128 #include "inputstr.h" 129 #include "xkbsrv.h" 130 #include "client.h" 131 #include "xfixesint.h" 132 133 #ifdef XSERVER_DTRACE 134 #include "registry.h" 135 #include "probes.h" 136 #endif 137 138 #define mskcnt ((MAXCLIENTS + 31) / 32) 139 #define BITMASK(i) (1U << ((i) & 31)) 140 #define MASKIDX(i) ((i) >> 5) 141 #define MASKWORD(buf, i) buf[MASKIDX(i)] 142 #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) 143 #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) 144 #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) 145 146 xConnSetupPrefix connSetupPrefix; 147 148 PaddingInfo PixmapWidthPaddingInfo[33]; 149 150 static ClientPtr grabClient; 151 static ClientPtr currentClient; /* Client for the request currently being dispatched */ 152 153 #define GrabNone 0 154 #define GrabActive 1 155 static int grabState = GrabNone; 156 static long grabWaiters[mskcnt]; 157 CallbackListPtr ServerGrabCallback = NULL; 158 HWEventQueuePtr checkForInput[2]; 159 int connBlockScreenStart; 160 161 static void KillAllClients(void); 162 163 static int nextFreeClientID; /* always MIN free client ID */ 164 165 static int nClients; /* number of authorized clients */ 166 167 CallbackListPtr ClientStateCallback; 168 OsTimerPtr dispatchExceptionTimer; 169 170 /* dispatchException & isItTimeToYield must be declared volatile since they 171 * are modified by signal handlers - otherwise optimizer may assume it doesn't 172 * need to actually check value in memory when used and may miss changes from 173 * signal handlers. 174 */ 175 volatile char dispatchException = 0; 176 volatile char isItTimeToYield; 177 178 #define SAME_SCREENS(a, b) (\ 179 (a.pScreen == b.pScreen)) 180 181 ClientPtr 182 GetCurrentClient(void) 183 { 184 if (in_input_thread()) { 185 static Bool warned; 186 187 if (!warned) { 188 ErrorF("[dix] Error GetCurrentClient called from input-thread\n"); 189 warned = TRUE; 190 } 191 192 return NULL; 193 } 194 195 return currentClient; 196 } 197 198 void 199 SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) 200 { 201 checkForInput[0] = c0; 202 checkForInput[1] = c1; 203 } 204 205 void 206 UpdateCurrentTime(void) 207 { 208 TimeStamp systime; 209 210 /* To avoid time running backwards, we must call GetTimeInMillis before 211 * calling ProcessInputEvents. 212 */ 213 systime.months = currentTime.months; 214 systime.milliseconds = GetTimeInMillis(); 215 if (systime.milliseconds < currentTime.milliseconds) 216 systime.months++; 217 if (InputCheckPending()) 218 ProcessInputEvents(); 219 if (CompareTimeStamps(systime, currentTime) == LATER) 220 currentTime = systime; 221 } 222 223 /* Like UpdateCurrentTime, but can't call ProcessInputEvents */ 224 void 225 UpdateCurrentTimeIf(void) 226 { 227 TimeStamp systime; 228 229 systime.months = currentTime.months; 230 systime.milliseconds = GetTimeInMillis(); 231 if (systime.milliseconds < currentTime.milliseconds) 232 systime.months++; 233 if (CompareTimeStamps(systime, currentTime) == LATER) 234 currentTime = systime; 235 } 236 237 #undef SMART_DEBUG 238 239 /* in milliseconds */ 240 #define SMART_SCHEDULE_DEFAULT_INTERVAL 5 241 #define SMART_SCHEDULE_MAX_SLICE 15 242 243 #ifdef HAVE_SETITIMER 244 Bool SmartScheduleSignalEnable = TRUE; 245 #endif 246 247 long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; 248 long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; 249 long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; 250 long SmartScheduleTime; 251 int SmartScheduleLatencyLimited = 0; 252 static ClientPtr SmartLastClient; 253 static int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1]; 254 255 #ifdef SMART_DEBUG 256 long SmartLastPrint; 257 #endif 258 259 void Dispatch(void); 260 261 static struct xorg_list ready_clients; 262 static struct xorg_list saved_ready_clients; 263 struct xorg_list output_pending_clients; 264 265 static void 266 init_client_ready(void) 267 { 268 xorg_list_init(&ready_clients); 269 xorg_list_init(&saved_ready_clients); 270 xorg_list_init(&output_pending_clients); 271 } 272 273 Bool 274 clients_are_ready(void) 275 { 276 return !xorg_list_is_empty(&ready_clients); 277 } 278 279 /* Client has requests queued or data on the network */ 280 void 281 mark_client_ready(ClientPtr client) 282 { 283 if (xorg_list_is_empty(&client->ready)) 284 xorg_list_append(&client->ready, &ready_clients); 285 } 286 287 /* 288 * Client has requests queued or data on the network, but awaits a 289 * server grab release 290 */ 291 void mark_client_saved_ready(ClientPtr client) 292 { 293 if (xorg_list_is_empty(&client->ready)) 294 xorg_list_append(&client->ready, &saved_ready_clients); 295 } 296 297 /* Client has no requests queued and no data on network */ 298 void 299 mark_client_not_ready(ClientPtr client) 300 { 301 xorg_list_del(&client->ready); 302 } 303 304 static void 305 mark_client_grab(ClientPtr grab) 306 { 307 ClientPtr client, tmp; 308 309 xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) { 310 if (client != grab) { 311 xorg_list_del(&client->ready); 312 xorg_list_append(&client->ready, &saved_ready_clients); 313 } 314 } 315 } 316 317 static void 318 mark_client_ungrab(void) 319 { 320 ClientPtr client, tmp; 321 322 xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) { 323 xorg_list_del(&client->ready); 324 xorg_list_append(&client->ready, &ready_clients); 325 } 326 } 327 328 static ClientPtr 329 SmartScheduleClient(void) 330 { 331 ClientPtr pClient, best = NULL; 332 int bestRobin, robin; 333 long now = SmartScheduleTime; 334 long idle; 335 int nready = 0; 336 337 bestRobin = 0; 338 idle = 2 * SmartScheduleSlice; 339 340 xorg_list_for_each_entry(pClient, &ready_clients, ready) { 341 nready++; 342 343 /* Praise clients which haven't run in a while */ 344 if ((now - pClient->smart_stop_tick) >= idle) { 345 if (pClient->smart_priority < 0) 346 pClient->smart_priority++; 347 } 348 349 /* check priority to select best client */ 350 robin = 351 (pClient->index - 352 SmartLastIndex[pClient->smart_priority - 353 SMART_MIN_PRIORITY]) & 0xff; 354 355 /* pick the best client */ 356 if (!best || 357 pClient->priority > best->priority || 358 (pClient->priority == best->priority && 359 (pClient->smart_priority > best->smart_priority || 360 (pClient->smart_priority == best->smart_priority && robin > bestRobin)))) 361 { 362 best = pClient; 363 bestRobin = robin; 364 } 365 #ifdef SMART_DEBUG 366 if ((now - SmartLastPrint) >= 5000) 367 fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority); 368 #endif 369 } 370 #ifdef SMART_DEBUG 371 if ((now - SmartLastPrint) >= 5000) { 372 fprintf(stderr, " use %2d\n", best->index); 373 SmartLastPrint = now; 374 } 375 #endif 376 SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index; 377 /* 378 * Set current client pointer 379 */ 380 if (SmartLastClient != best) { 381 best->smart_start_tick = now; 382 SmartLastClient = best; 383 } 384 /* 385 * Adjust slice 386 */ 387 if (nready == 1 && SmartScheduleLatencyLimited == 0) { 388 /* 389 * If it's been a long time since another client 390 * has run, bump the slice up to get maximal 391 * performance from a single client 392 */ 393 if ((now - best->smart_start_tick) > 1000 && 394 SmartScheduleSlice < SmartScheduleMaxSlice) { 395 SmartScheduleSlice += SmartScheduleInterval; 396 } 397 } 398 else { 399 SmartScheduleSlice = SmartScheduleInterval; 400 } 401 return best; 402 } 403 404 static CARD32 405 DispatchExceptionCallback(OsTimerPtr timer, CARD32 time, void *arg) 406 { 407 dispatchException |= dispatchExceptionAtReset; 408 409 /* Don't re-arm the timer */ 410 return 0; 411 } 412 413 static void 414 CancelDispatchExceptionTimer(void) 415 { 416 TimerFree(dispatchExceptionTimer); 417 dispatchExceptionTimer = NULL; 418 } 419 420 static void 421 SetDispatchExceptionTimer(void) 422 { 423 /* The timer delay is only for terminate, not reset */ 424 if (!(dispatchExceptionAtReset & DE_TERMINATE)) { 425 dispatchException |= dispatchExceptionAtReset; 426 return; 427 } 428 429 CancelDispatchExceptionTimer(); 430 431 if (terminateDelay == 0) 432 dispatchException |= dispatchExceptionAtReset; 433 else 434 dispatchExceptionTimer = TimerSet(dispatchExceptionTimer, 435 0, terminateDelay * 1000 /* msec */, 436 &DispatchExceptionCallback, 437 NULL); 438 } 439 440 static Bool 441 ShouldDisconnectRemainingClients(void) 442 { 443 int i; 444 445 for (i = 1; i < currentMaxClients; i++) { 446 if (clients[i]) { 447 if (!XFixesShouldDisconnectClient(clients[i])) 448 return FALSE; 449 } 450 } 451 452 /* All remaining clients can be safely ignored */ 453 return TRUE; 454 } 455 456 void 457 EnableLimitedSchedulingLatency(void) 458 { 459 ++SmartScheduleLatencyLimited; 460 SmartScheduleSlice = SmartScheduleInterval; 461 } 462 463 void 464 DisableLimitedSchedulingLatency(void) 465 { 466 --SmartScheduleLatencyLimited; 467 468 /* protect against bugs */ 469 if (SmartScheduleLatencyLimited < 0) 470 SmartScheduleLatencyLimited = 0; 471 } 472 473 void 474 Dispatch(void) 475 { 476 int result; 477 ClientPtr client; 478 long start_tick; 479 480 nextFreeClientID = 1; 481 nClients = 0; 482 483 SmartScheduleSlice = SmartScheduleInterval; 484 init_client_ready(); 485 486 while (!dispatchException) { 487 if (InputCheckPending()) { 488 ProcessInputEvents(); 489 FlushIfCriticalOutputPending(); 490 } 491 492 if (!WaitForSomething(clients_are_ready())) 493 continue; 494 495 /***************** 496 * Handle events in round robin fashion, doing input between 497 * each round 498 *****************/ 499 500 if (!dispatchException && clients_are_ready()) { 501 client = SmartScheduleClient(); 502 503 isItTimeToYield = FALSE; 504 505 start_tick = SmartScheduleTime; 506 while (!isItTimeToYield) { 507 if (InputCheckPending()) 508 ProcessInputEvents(); 509 510 FlushIfCriticalOutputPending(); 511 if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice) 512 { 513 /* Penalize clients which consume ticks */ 514 if (client->smart_priority > SMART_MIN_PRIORITY) 515 client->smart_priority--; 516 break; 517 } 518 519 /* now, finally, deal with client requests */ 520 result = ReadRequestFromClient(client); 521 if (result == 0) 522 break; 523 else if (result == -1) { 524 CloseDownClient(client); 525 break; 526 } 527 528 client->sequence++; 529 client->majorOp = ((xReq *) client->requestBuffer)->reqType; 530 client->minorOp = 0; 531 if (client->majorOp >= EXTENSION_BASE) { 532 ExtensionEntry *ext = GetExtensionEntry(client->majorOp); 533 534 if (ext) 535 client->minorOp = ext->MinorOpcode(client); 536 } 537 #ifdef XSERVER_DTRACE 538 if (XSERVER_REQUEST_START_ENABLED()) 539 XSERVER_REQUEST_START(LookupMajorName(client->majorOp), 540 client->majorOp, 541 ((xReq *) client->requestBuffer)->length, 542 client->index, 543 client->requestBuffer); 544 #endif 545 if (result < 0 || result > (maxBigRequestSize << 2)) 546 result = BadLength; 547 else { 548 result = XaceHookDispatch(client, client->majorOp); 549 if (result == Success) { 550 currentClient = client; 551 result = 552 (*client->requestVector[client->majorOp]) (client); 553 currentClient = NULL; 554 } 555 } 556 if (!SmartScheduleSignalEnable) 557 SmartScheduleTime = GetTimeInMillis(); 558 559 #ifdef XSERVER_DTRACE 560 if (XSERVER_REQUEST_DONE_ENABLED()) 561 XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp), 562 client->majorOp, client->sequence, 563 client->index, result); 564 #endif 565 566 if (client->noClientException != Success) { 567 CloseDownClient(client); 568 break; 569 } 570 else if (result != Success) { 571 SendErrorToClient(client, client->majorOp, 572 client->minorOp, 573 client->errorValue, result); 574 break; 575 } 576 } 577 FlushAllOutput(); 578 if (client == SmartLastClient) 579 client->smart_stop_tick = SmartScheduleTime; 580 } 581 dispatchException &= ~DE_PRIORITYCHANGE; 582 } 583 #if defined(DDXBEFORERESET) 584 ddxBeforeReset(); 585 #endif 586 KillAllClients(); 587 dispatchException &= ~DE_RESET; 588 SmartScheduleLatencyLimited = 0; 589 ResetOsBuffers(); 590 } 591 592 static int VendorRelease = VENDOR_RELEASE; 593 594 void 595 SetVendorRelease(int release) 596 { 597 VendorRelease = release; 598 } 599 600 Bool 601 CreateConnectionBlock(void) 602 { 603 xConnSetup setup; 604 xWindowRoot root; 605 xDepth depth; 606 xVisualType visual; 607 xPixmapFormat format; 608 unsigned long vid; 609 int i, j, k, lenofblock, sizesofar = 0; 610 char *pBuf; 611 const char VendorString[] = VENDOR_NAME; 612 613 memset(&setup, 0, sizeof(xConnSetup)); 614 /* Leave off the ridBase and ridMask, these must be sent with 615 connection */ 616 617 setup.release = VendorRelease; 618 /* 619 * per-server image and bitmap parameters are defined in Xmd.h 620 */ 621 setup.imageByteOrder = screenInfo.imageByteOrder; 622 623 setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit; 624 setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad; 625 626 setup.bitmapBitOrder = screenInfo.bitmapBitOrder; 627 setup.motionBufferSize = NumMotionEvents(); 628 setup.numRoots = screenInfo.numScreens; 629 setup.nbytesVendor = strlen(VendorString); 630 setup.numFormats = screenInfo.numPixmapFormats; 631 setup.maxRequestSize = MAX_REQUEST_SIZE; 632 QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode); 633 634 lenofblock = sizeof(xConnSetup) + 635 pad_to_int32(setup.nbytesVendor) + 636 (setup.numFormats * sizeof(xPixmapFormat)) + 637 (setup.numRoots * sizeof(xWindowRoot)); 638 ConnectionInfo = malloc(lenofblock); 639 if (!ConnectionInfo) 640 return FALSE; 641 642 memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup)); 643 sizesofar = sizeof(xConnSetup); 644 pBuf = ConnectionInfo + sizeof(xConnSetup); 645 646 memmove(pBuf, VendorString, (int) setup.nbytesVendor); 647 sizesofar += setup.nbytesVendor; 648 pBuf += setup.nbytesVendor; 649 i = padding_for_int32(setup.nbytesVendor); 650 sizesofar += i; 651 while (--i >= 0) 652 *pBuf++ = 0; 653 654 memset(&format, 0, sizeof(xPixmapFormat)); 655 for (i = 0; i < screenInfo.numPixmapFormats; i++) { 656 format.depth = screenInfo.formats[i].depth; 657 format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel; 658 format.scanLinePad = screenInfo.formats[i].scanlinePad; 659 memmove(pBuf, (char *) &format, sizeof(xPixmapFormat)); 660 pBuf += sizeof(xPixmapFormat); 661 sizesofar += sizeof(xPixmapFormat); 662 } 663 664 connBlockScreenStart = sizesofar; 665 memset(&depth, 0, sizeof(xDepth)); 666 memset(&visual, 0, sizeof(xVisualType)); 667 for (i = 0; i < screenInfo.numScreens; i++) { 668 ScreenPtr pScreen; 669 DepthPtr pDepth; 670 VisualPtr pVisual; 671 672 pScreen = screenInfo.screens[i]; 673 root.windowId = pScreen->root->drawable.id; 674 root.defaultColormap = pScreen->defColormap; 675 root.whitePixel = pScreen->whitePixel; 676 root.blackPixel = pScreen->blackPixel; 677 root.currentInputMask = 0; /* filled in when sent */ 678 root.pixWidth = pScreen->width; 679 root.pixHeight = pScreen->height; 680 root.mmWidth = pScreen->mmWidth; 681 root.mmHeight = pScreen->mmHeight; 682 root.minInstalledMaps = pScreen->minInstalledCmaps; 683 root.maxInstalledMaps = pScreen->maxInstalledCmaps; 684 root.rootVisualID = pScreen->rootVisual; 685 root.backingStore = pScreen->backingStoreSupport; 686 root.saveUnders = FALSE; 687 root.rootDepth = pScreen->rootDepth; 688 root.nDepths = pScreen->numDepths; 689 memmove(pBuf, (char *) &root, sizeof(xWindowRoot)); 690 sizesofar += sizeof(xWindowRoot); 691 pBuf += sizeof(xWindowRoot); 692 693 pDepth = pScreen->allowedDepths; 694 for (j = 0; j < pScreen->numDepths; j++, pDepth++) { 695 lenofblock += sizeof(xDepth) + 696 (pDepth->numVids * sizeof(xVisualType)); 697 pBuf = (char *) realloc(ConnectionInfo, lenofblock); 698 if (!pBuf) { 699 free(ConnectionInfo); 700 return FALSE; 701 } 702 ConnectionInfo = pBuf; 703 pBuf += sizesofar; 704 depth.depth = pDepth->depth; 705 depth.nVisuals = pDepth->numVids; 706 memmove(pBuf, (char *) &depth, sizeof(xDepth)); 707 pBuf += sizeof(xDepth); 708 sizesofar += sizeof(xDepth); 709 for (k = 0; k < pDepth->numVids; k++) { 710 vid = pDepth->vids[k]; 711 for (pVisual = pScreen->visuals; 712 pVisual->vid != vid; pVisual++); 713 visual.visualID = vid; 714 visual.class = pVisual->class; 715 visual.bitsPerRGB = pVisual->bitsPerRGBValue; 716 visual.colormapEntries = pVisual->ColormapEntries; 717 visual.redMask = pVisual->redMask; 718 visual.greenMask = pVisual->greenMask; 719 visual.blueMask = pVisual->blueMask; 720 memmove(pBuf, (char *) &visual, sizeof(xVisualType)); 721 pBuf += sizeof(xVisualType); 722 sizesofar += sizeof(xVisualType); 723 } 724 } 725 } 726 connSetupPrefix.success = xTrue; 727 connSetupPrefix.length = lenofblock / 4; 728 connSetupPrefix.majorVersion = X_PROTOCOL; 729 connSetupPrefix.minorVersion = X_PROTOCOL_REVISION; 730 return TRUE; 731 } 732 733 int 734 ProcBadRequest(ClientPtr client) 735 { 736 return BadRequest; 737 } 738 739 int 740 ProcCreateWindow(ClientPtr client) 741 { 742 WindowPtr pParent, pWin; 743 744 REQUEST(xCreateWindowReq); 745 int len, rc; 746 747 REQUEST_AT_LEAST_SIZE(xCreateWindowReq); 748 749 LEGAL_NEW_RESOURCE(stuff->wid, client); 750 rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); 751 if (rc != Success) 752 return rc; 753 len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq)); 754 if (Ones(stuff->mask) != len) 755 return BadLength; 756 if (!stuff->width || !stuff->height) { 757 client->errorValue = 0; 758 return BadValue; 759 } 760 pWin = CreateWindow(stuff->wid, pParent, stuff->x, 761 stuff->y, stuff->width, stuff->height, 762 stuff->borderWidth, stuff->class, 763 stuff->mask, (XID *) &stuff[1], 764 (int) stuff->depth, client, stuff->visual, &rc); 765 if (pWin) { 766 Mask mask = pWin->eventMask; 767 768 pWin->eventMask = 0; /* subterfuge in case AddResource fails */ 769 if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin)) 770 return BadAlloc; 771 pWin->eventMask = mask; 772 } 773 return rc; 774 } 775 776 int 777 ProcChangeWindowAttributes(ClientPtr client) 778 { 779 WindowPtr pWin; 780 781 REQUEST(xChangeWindowAttributesReq); 782 int len, rc; 783 Mask access_mode = 0; 784 785 REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); 786 access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0; 787 access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0; 788 rc = dixLookupWindow(&pWin, stuff->window, client, access_mode); 789 if (rc != Success) 790 return rc; 791 len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq)); 792 if (len != Ones(stuff->valueMask)) 793 return BadLength; 794 return ChangeWindowAttributes(pWin, 795 stuff->valueMask, (XID *) &stuff[1], client); 796 } 797 798 int 799 ProcGetWindowAttributes(ClientPtr client) 800 { 801 WindowPtr pWin; 802 803 REQUEST(xResourceReq); 804 xGetWindowAttributesReply wa; 805 int rc; 806 807 REQUEST_SIZE_MATCH(xResourceReq); 808 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 809 if (rc != Success) 810 return rc; 811 memset(&wa, 0, sizeof(xGetWindowAttributesReply)); 812 GetWindowAttributes(pWin, client, &wa); 813 WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); 814 return Success; 815 } 816 817 int 818 ProcDestroyWindow(ClientPtr client) 819 { 820 WindowPtr pWin; 821 822 REQUEST(xResourceReq); 823 int rc; 824 825 REQUEST_SIZE_MATCH(xResourceReq); 826 rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess); 827 if (rc != Success) 828 return rc; 829 if (pWin->parent) { 830 rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client, 831 DixRemoveAccess); 832 if (rc != Success) 833 return rc; 834 FreeResource(stuff->id, RT_NONE); 835 } 836 return Success; 837 } 838 839 int 840 ProcDestroySubwindows(ClientPtr client) 841 { 842 WindowPtr pWin; 843 844 REQUEST(xResourceReq); 845 int rc; 846 847 REQUEST_SIZE_MATCH(xResourceReq); 848 rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess); 849 if (rc != Success) 850 return rc; 851 DestroySubwindows(pWin, client); 852 return Success; 853 } 854 855 int 856 ProcChangeSaveSet(ClientPtr client) 857 { 858 WindowPtr pWin; 859 860 REQUEST(xChangeSaveSetReq); 861 int rc; 862 863 REQUEST_SIZE_MATCH(xChangeSaveSetReq); 864 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 865 if (rc != Success) 866 return rc; 867 if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) 868 return BadMatch; 869 if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) 870 return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); 871 client->errorValue = stuff->mode; 872 return BadValue; 873 } 874 875 int 876 ProcReparentWindow(ClientPtr client) 877 { 878 WindowPtr pWin, pParent; 879 880 REQUEST(xReparentWindowReq); 881 int rc; 882 883 REQUEST_SIZE_MATCH(xReparentWindowReq); 884 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 885 if (rc != Success) 886 return rc; 887 rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); 888 if (rc != Success) 889 return rc; 890 if (!SAME_SCREENS(pWin->drawable, pParent->drawable)) 891 return BadMatch; 892 if ((pWin->backgroundState == ParentRelative) && 893 (pParent->drawable.depth != pWin->drawable.depth)) 894 return BadMatch; 895 if ((pWin->drawable.class != InputOnly) && 896 (pParent->drawable.class == InputOnly)) 897 return BadMatch; 898 return ReparentWindow(pWin, pParent, 899 (short) stuff->x, (short) stuff->y, client); 900 } 901 902 int 903 ProcMapWindow(ClientPtr client) 904 { 905 WindowPtr pWin; 906 907 REQUEST(xResourceReq); 908 int rc; 909 910 REQUEST_SIZE_MATCH(xResourceReq); 911 rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess); 912 if (rc != Success) 913 return rc; 914 MapWindow(pWin, client); 915 /* update cache to say it is mapped */ 916 return Success; 917 } 918 919 int 920 ProcMapSubwindows(ClientPtr client) 921 { 922 WindowPtr pWin; 923 924 REQUEST(xResourceReq); 925 int rc; 926 927 REQUEST_SIZE_MATCH(xResourceReq); 928 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 929 if (rc != Success) 930 return rc; 931 MapSubwindows(pWin, client); 932 /* update cache to say it is mapped */ 933 return Success; 934 } 935 936 int 937 ProcUnmapWindow(ClientPtr client) 938 { 939 WindowPtr pWin; 940 941 REQUEST(xResourceReq); 942 int rc; 943 944 REQUEST_SIZE_MATCH(xResourceReq); 945 rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess); 946 if (rc != Success) 947 return rc; 948 UnmapWindow(pWin, FALSE); 949 /* update cache to say it is mapped */ 950 return Success; 951 } 952 953 int 954 ProcUnmapSubwindows(ClientPtr client) 955 { 956 WindowPtr pWin; 957 958 REQUEST(xResourceReq); 959 int rc; 960 961 REQUEST_SIZE_MATCH(xResourceReq); 962 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 963 if (rc != Success) 964 return rc; 965 UnmapSubwindows(pWin); 966 return Success; 967 } 968 969 int 970 ProcConfigureWindow(ClientPtr client) 971 { 972 WindowPtr pWin; 973 974 REQUEST(xConfigureWindowReq); 975 int len, rc; 976 977 REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); 978 rc = dixLookupWindow(&pWin, stuff->window, client, 979 DixManageAccess | DixSetAttrAccess); 980 if (rc != Success) 981 return rc; 982 len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq)); 983 if (Ones((Mask) stuff->mask) != len) 984 return BadLength; 985 return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client); 986 } 987 988 int 989 ProcCirculateWindow(ClientPtr client) 990 { 991 WindowPtr pWin; 992 993 REQUEST(xCirculateWindowReq); 994 int rc; 995 996 REQUEST_SIZE_MATCH(xCirculateWindowReq); 997 if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) { 998 client->errorValue = stuff->direction; 999 return BadValue; 1000 } 1001 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 1002 if (rc != Success) 1003 return rc; 1004 CirculateWindow(pWin, (int) stuff->direction, client); 1005 return Success; 1006 } 1007 1008 static int 1009 GetGeometry(ClientPtr client, xGetGeometryReply * rep) 1010 { 1011 DrawablePtr pDraw; 1012 int rc; 1013 1014 REQUEST(xResourceReq); 1015 REQUEST_SIZE_MATCH(xResourceReq); 1016 1017 rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess); 1018 if (rc != Success) 1019 return rc; 1020 1021 rep->type = X_Reply; 1022 rep->length = 0; 1023 rep->sequenceNumber = client->sequence; 1024 rep->root = pDraw->pScreen->root->drawable.id; 1025 rep->depth = pDraw->depth; 1026 rep->width = pDraw->width; 1027 rep->height = pDraw->height; 1028 1029 if (WindowDrawable(pDraw->type)) { 1030 WindowPtr pWin = (WindowPtr) pDraw; 1031 1032 rep->x = pWin->origin.x - wBorderWidth(pWin); 1033 rep->y = pWin->origin.y - wBorderWidth(pWin); 1034 rep->borderWidth = pWin->borderWidth; 1035 } 1036 else { /* DRAWABLE_PIXMAP */ 1037 1038 rep->x = rep->y = rep->borderWidth = 0; 1039 } 1040 1041 return Success; 1042 } 1043 1044 int 1045 ProcGetGeometry(ClientPtr client) 1046 { 1047 xGetGeometryReply rep = { .type = X_Reply }; 1048 int status; 1049 1050 if ((status = GetGeometry(client, &rep)) != Success) 1051 return status; 1052 1053 WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); 1054 return Success; 1055 } 1056 1057 int 1058 ProcQueryTree(ClientPtr client) 1059 { 1060 xQueryTreeReply reply; 1061 int rc, numChildren = 0; 1062 WindowPtr pChild, pWin, pHead; 1063 Window *childIDs = (Window *) NULL; 1064 1065 REQUEST(xResourceReq); 1066 1067 REQUEST_SIZE_MATCH(xResourceReq); 1068 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 1069 if (rc != Success) 1070 return rc; 1071 1072 reply = (xQueryTreeReply) { 1073 .type = X_Reply, 1074 .sequenceNumber = client->sequence, 1075 .root = pWin->drawable.pScreen->root->drawable.id, 1076 .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None 1077 }; 1078 pHead = RealChildHead(pWin); 1079 for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) 1080 numChildren++; 1081 if (numChildren) { 1082 int curChild = 0; 1083 1084 childIDs = xallocarray(numChildren, sizeof(Window)); 1085 if (!childIDs) 1086 return BadAlloc; 1087 for (pChild = pWin->lastChild; pChild != pHead; 1088 pChild = pChild->prevSib) 1089 childIDs[curChild++] = pChild->drawable.id; 1090 } 1091 1092 reply.nChildren = numChildren; 1093 reply.length = bytes_to_int32(numChildren * sizeof(Window)); 1094 1095 WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); 1096 if (numChildren) { 1097 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 1098 WriteSwappedDataToClient(client, numChildren * sizeof(Window), 1099 childIDs); 1100 free(childIDs); 1101 } 1102 1103 return Success; 1104 } 1105 1106 int 1107 ProcInternAtom(ClientPtr client) 1108 { 1109 Atom atom; 1110 char *tchar; 1111 1112 REQUEST(xInternAtomReq); 1113 1114 REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); 1115 if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) { 1116 client->errorValue = stuff->onlyIfExists; 1117 return BadValue; 1118 } 1119 tchar = (char *) &stuff[1]; 1120 atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); 1121 if (atom != BAD_RESOURCE) { 1122 xInternAtomReply reply = { 1123 .type = X_Reply, 1124 .sequenceNumber = client->sequence, 1125 .length = 0, 1126 .atom = atom 1127 }; 1128 WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); 1129 return Success; 1130 } 1131 else 1132 return BadAlloc; 1133 } 1134 1135 int 1136 ProcGetAtomName(ClientPtr client) 1137 { 1138 const char *str; 1139 1140 REQUEST(xResourceReq); 1141 1142 REQUEST_SIZE_MATCH(xResourceReq); 1143 if ((str = NameForAtom(stuff->id))) { 1144 int len = strlen(str); 1145 xGetAtomNameReply reply = { 1146 .type = X_Reply, 1147 .sequenceNumber = client->sequence, 1148 .length = bytes_to_int32(len), 1149 .nameLength = len 1150 }; 1151 1152 WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); 1153 WriteToClient(client, len, str); 1154 return Success; 1155 } 1156 else { 1157 client->errorValue = stuff->id; 1158 return BadAtom; 1159 } 1160 } 1161 1162 int 1163 ProcGrabServer(ClientPtr client) 1164 { 1165 int rc; 1166 1167 REQUEST_SIZE_MATCH(xReq); 1168 if (grabState != GrabNone && client != grabClient) { 1169 ResetCurrentRequest(client); 1170 client->sequence--; 1171 BITSET(grabWaiters, client->index); 1172 IgnoreClient(client); 1173 return Success; 1174 } 1175 rc = OnlyListenToOneClient(client); 1176 if (rc != Success) 1177 return rc; 1178 grabState = GrabActive; 1179 grabClient = client; 1180 mark_client_grab(client); 1181 1182 if (ServerGrabCallback) { 1183 ServerGrabInfoRec grabinfo; 1184 1185 grabinfo.client = client; 1186 grabinfo.grabstate = SERVER_GRABBED; 1187 CallCallbacks(&ServerGrabCallback, (void *) &grabinfo); 1188 } 1189 1190 return Success; 1191 } 1192 1193 static void 1194 UngrabServer(ClientPtr client) 1195 { 1196 int i; 1197 1198 grabState = GrabNone; 1199 ListenToAllClients(); 1200 mark_client_ungrab(); 1201 for (i = mskcnt; --i >= 0 && !grabWaiters[i];); 1202 if (i >= 0) { 1203 i <<= 5; 1204 while (!GETBIT(grabWaiters, i)) 1205 i++; 1206 BITCLEAR(grabWaiters, i); 1207 AttendClient(clients[i]); 1208 } 1209 1210 if (ServerGrabCallback) { 1211 ServerGrabInfoRec grabinfo; 1212 1213 grabinfo.client = client; 1214 grabinfo.grabstate = SERVER_UNGRABBED; 1215 CallCallbacks(&ServerGrabCallback, (void *) &grabinfo); 1216 } 1217 } 1218 1219 int 1220 ProcUngrabServer(ClientPtr client) 1221 { 1222 REQUEST_SIZE_MATCH(xReq); 1223 UngrabServer(client); 1224 return Success; 1225 } 1226 1227 int 1228 ProcTranslateCoords(ClientPtr client) 1229 { 1230 REQUEST(xTranslateCoordsReq); 1231 1232 WindowPtr pWin, pDst; 1233 xTranslateCoordsReply rep; 1234 int rc; 1235 1236 REQUEST_SIZE_MATCH(xTranslateCoordsReq); 1237 rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess); 1238 if (rc != Success) 1239 return rc; 1240 rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess); 1241 if (rc != Success) 1242 return rc; 1243 1244 rep = (xTranslateCoordsReply) { 1245 .type = X_Reply, 1246 .sequenceNumber = client->sequence, 1247 .length = 0 1248 }; 1249 if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) { 1250 rep.sameScreen = xFalse; 1251 rep.child = None; 1252 rep.dstX = rep.dstY = 0; 1253 } 1254 else { 1255 INT16 x, y; 1256 1257 rep.sameScreen = xTrue; 1258 rep.child = None; 1259 /* computing absolute coordinates -- adjust to destination later */ 1260 x = pWin->drawable.x + stuff->srcX; 1261 y = pWin->drawable.y + stuff->srcY; 1262 pWin = pDst->firstChild; 1263 while (pWin) { 1264 BoxRec box; 1265 1266 if ((pWin->mapped) && 1267 (x >= pWin->drawable.x - wBorderWidth(pWin)) && 1268 (x < pWin->drawable.x + (int) pWin->drawable.width + 1269 wBorderWidth(pWin)) && 1270 (y >= pWin->drawable.y - wBorderWidth(pWin)) && 1271 (y < pWin->drawable.y + (int) pWin->drawable.height + 1272 wBorderWidth(pWin)) 1273 /* When a window is shaped, a further check 1274 * is made to see if the point is inside 1275 * borderSize 1276 */ 1277 && (!wBoundingShape(pWin) || 1278 RegionContainsPoint(&pWin->borderSize, x, y, &box)) 1279 1280 && (!wInputShape(pWin) || 1281 RegionContainsPoint(wInputShape(pWin), 1282 x - pWin->drawable.x, 1283 y - pWin->drawable.y, &box)) 1284 ) { 1285 rep.child = pWin->drawable.id; 1286 pWin = (WindowPtr) NULL; 1287 } 1288 else 1289 pWin = pWin->nextSib; 1290 } 1291 /* adjust to destination coordinates */ 1292 rep.dstX = x - pDst->drawable.x; 1293 rep.dstY = y - pDst->drawable.y; 1294 } 1295 WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); 1296 return Success; 1297 } 1298 1299 int 1300 ProcOpenFont(ClientPtr client) 1301 { 1302 int err; 1303 1304 REQUEST(xOpenFontReq); 1305 1306 REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); 1307 client->errorValue = stuff->fid; 1308 LEGAL_NEW_RESOURCE(stuff->fid, client); 1309 err = OpenFont(client, stuff->fid, (Mask) 0, 1310 stuff->nbytes, (char *) &stuff[1]); 1311 if (err == Success) { 1312 return Success; 1313 } 1314 else 1315 return err; 1316 } 1317 1318 int 1319 ProcCloseFont(ClientPtr client) 1320 { 1321 FontPtr pFont; 1322 int rc; 1323 1324 REQUEST(xResourceReq); 1325 1326 REQUEST_SIZE_MATCH(xResourceReq); 1327 rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT, 1328 client, DixDestroyAccess); 1329 if (rc == Success) { 1330 FreeResource(stuff->id, RT_NONE); 1331 return Success; 1332 } 1333 else { 1334 client->errorValue = stuff->id; 1335 return rc; 1336 } 1337 } 1338 1339 int 1340 ProcQueryFont(ClientPtr client) 1341 { 1342 xQueryFontReply *reply; 1343 FontPtr pFont; 1344 int rc; 1345 1346 REQUEST(xResourceReq); 1347 REQUEST_SIZE_MATCH(xResourceReq); 1348 1349 rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess); 1350 if (rc != Success) 1351 return rc; 1352 1353 { 1354 xCharInfo *pmax = FONTINKMAX(pFont); 1355 xCharInfo *pmin = FONTINKMIN(pFont); 1356 int nprotoxcistructs; 1357 int rlength; 1358 1359 nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing && 1360 pmax->leftSideBearing == pmin->leftSideBearing && 1361 pmax->descent == pmin->descent && 1362 pmax->ascent == pmin->ascent && 1363 pmax->characterWidth == pmin->characterWidth) ? 1364 0 : N2dChars(pFont); 1365 1366 rlength = sizeof(xQueryFontReply) + 1367 FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + 1368 nprotoxcistructs * sizeof(xCharInfo); 1369 reply = calloc(1, rlength); 1370 if (!reply) { 1371 return BadAlloc; 1372 } 1373 1374 reply->type = X_Reply; 1375 reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); 1376 reply->sequenceNumber = client->sequence; 1377 QueryFont(pFont, reply, nprotoxcistructs); 1378 1379 WriteReplyToClient(client, rlength, reply); 1380 free(reply); 1381 return Success; 1382 } 1383 } 1384 1385 int 1386 ProcQueryTextExtents(ClientPtr client) 1387 { 1388 xQueryTextExtentsReply reply; 1389 FontPtr pFont; 1390 ExtentInfoRec info; 1391 unsigned long length; 1392 int rc; 1393 1394 REQUEST(xQueryTextExtentsReq); 1395 REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); 1396 1397 rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess); 1398 if (rc != Success) 1399 return rc; 1400 1401 length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq)); 1402 length = length << 1; 1403 if (stuff->oddLength) { 1404 if (length == 0) 1405 return BadLength; 1406 length--; 1407 } 1408 if (!xfont2_query_text_extents(pFont, length, (unsigned char *) &stuff[1], &info)) 1409 return BadAlloc; 1410 reply = (xQueryTextExtentsReply) { 1411 .type = X_Reply, 1412 .drawDirection = info.drawDirection, 1413 .sequenceNumber = client->sequence, 1414 .length = 0, 1415 .fontAscent = info.fontAscent, 1416 .fontDescent = info.fontDescent, 1417 .overallAscent = info.overallAscent, 1418 .overallDescent = info.overallDescent, 1419 .overallWidth = info.overallWidth, 1420 .overallLeft = info.overallLeft, 1421 .overallRight = info.overallRight 1422 }; 1423 WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); 1424 return Success; 1425 } 1426 1427 int 1428 ProcListFonts(ClientPtr client) 1429 { 1430 REQUEST(xListFontsReq); 1431 1432 REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); 1433 1434 return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, 1435 stuff->maxNames); 1436 } 1437 1438 int 1439 ProcListFontsWithInfo(ClientPtr client) 1440 { 1441 REQUEST(xListFontsWithInfoReq); 1442 1443 REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); 1444 1445 return StartListFontsWithInfo(client, stuff->nbytes, 1446 (unsigned char *) &stuff[1], stuff->maxNames); 1447 } 1448 1449 /** 1450 * 1451 * \param value must conform to DeleteType 1452 */ 1453 int 1454 dixDestroyPixmap(void *value, XID pid) 1455 { 1456 PixmapPtr pPixmap = (PixmapPtr) value; 1457 1458 return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); 1459 } 1460 1461 int 1462 ProcCreatePixmap(ClientPtr client) 1463 { 1464 PixmapPtr pMap; 1465 DrawablePtr pDraw; 1466 1467 REQUEST(xCreatePixmapReq); 1468 DepthPtr pDepth; 1469 int i, rc; 1470 1471 REQUEST_SIZE_MATCH(xCreatePixmapReq); 1472 client->errorValue = stuff->pid; 1473 LEGAL_NEW_RESOURCE(stuff->pid, client); 1474 1475 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 1476 DixGetAttrAccess); 1477 if (rc != Success) 1478 return rc; 1479 1480 if (!stuff->width || !stuff->height) { 1481 client->errorValue = 0; 1482 return BadValue; 1483 } 1484 if (stuff->width > 32767 || stuff->height > 32767) { 1485 /* It is allowed to try and allocate a pixmap which is larger than 1486 * 32767 in either dimension. However, all of the framebuffer code 1487 * is buggy and does not reliably draw to such big pixmaps, basically 1488 * because the Region data structure operates with signed shorts 1489 * for the rectangles in it. 1490 * 1491 * Furthermore, several places in the X server computes the 1492 * size in bytes of the pixmap and tries to store it in an 1493 * integer. This integer can overflow and cause the allocated size 1494 * to be much smaller. 1495 * 1496 * So, such big pixmaps are rejected here with a BadAlloc 1497 */ 1498 return BadAlloc; 1499 } 1500 if (stuff->depth != 1) { 1501 pDepth = pDraw->pScreen->allowedDepths; 1502 for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 1503 if (pDepth->depth == stuff->depth) 1504 goto CreatePmap; 1505 client->errorValue = stuff->depth; 1506 return BadValue; 1507 } 1508 CreatePmap: 1509 pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap) 1510 (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0); 1511 if (pMap) { 1512 pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1513 pMap->drawable.id = stuff->pid; 1514 /* security creation/labeling check */ 1515 rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 1516 pMap, RT_NONE, NULL, DixCreateAccess); 1517 if (rc != Success) { 1518 (*pDraw->pScreen->DestroyPixmap) (pMap); 1519 return rc; 1520 } 1521 if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap)) 1522 return Success; 1523 } 1524 return BadAlloc; 1525 } 1526 1527 int 1528 ProcFreePixmap(ClientPtr client) 1529 { 1530 PixmapPtr pMap; 1531 int rc; 1532 1533 REQUEST(xResourceReq); 1534 REQUEST_SIZE_MATCH(xResourceReq); 1535 1536 rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP, 1537 client, DixDestroyAccess); 1538 if (rc == Success) { 1539 FreeResource(stuff->id, RT_NONE); 1540 return Success; 1541 } 1542 else { 1543 client->errorValue = stuff->id; 1544 return rc; 1545 } 1546 } 1547 1548 int 1549 ProcCreateGC(ClientPtr client) 1550 { 1551 int error, rc; 1552 GC *pGC; 1553 DrawablePtr pDraw; 1554 unsigned len; 1555 1556 REQUEST(xCreateGCReq); 1557 1558 REQUEST_AT_LEAST_SIZE(xCreateGCReq); 1559 client->errorValue = stuff->gc; 1560 LEGAL_NEW_RESOURCE(stuff->gc, client); 1561 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 1562 DixGetAttrAccess); 1563 if (rc != Success) 1564 return rc; 1565 1566 len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq)); 1567 if (len != Ones(stuff->mask)) 1568 return BadLength; 1569 pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error, 1570 stuff->gc, client); 1571 if (error != Success) 1572 return error; 1573 if (!AddResource(stuff->gc, RT_GC, (void *) pGC)) 1574 return BadAlloc; 1575 return Success; 1576 } 1577 1578 int 1579 ProcChangeGC(ClientPtr client) 1580 { 1581 GC *pGC; 1582 int result; 1583 unsigned len; 1584 1585 REQUEST(xChangeGCReq); 1586 REQUEST_AT_LEAST_SIZE(xChangeGCReq); 1587 1588 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 1589 if (result != Success) 1590 return result; 1591 1592 len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq)); 1593 if (len != Ones(stuff->mask)) 1594 return BadLength; 1595 1596 return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]); 1597 } 1598 1599 int 1600 ProcCopyGC(ClientPtr client) 1601 { 1602 GC *dstGC; 1603 GC *pGC; 1604 int result; 1605 1606 REQUEST(xCopyGCReq); 1607 REQUEST_SIZE_MATCH(xCopyGCReq); 1608 1609 result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess); 1610 if (result != Success) 1611 return result; 1612 result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess); 1613 if (result != Success) 1614 return result; 1615 if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) 1616 return BadMatch; 1617 if (stuff->mask & ~GCAllBits) { 1618 client->errorValue = stuff->mask; 1619 return BadValue; 1620 } 1621 return CopyGC(pGC, dstGC, stuff->mask); 1622 } 1623 1624 int 1625 ProcSetDashes(ClientPtr client) 1626 { 1627 GC *pGC; 1628 int result; 1629 1630 REQUEST(xSetDashesReq); 1631 1632 REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); 1633 if (stuff->nDashes == 0) { 1634 client->errorValue = 0; 1635 return BadValue; 1636 } 1637 1638 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 1639 if (result != Success) 1640 return result; 1641 1642 /* If there's an error, either there's no sensible errorValue, 1643 * or there was a dash segment of 0. */ 1644 client->errorValue = 0; 1645 return SetDashes(pGC, stuff->dashOffset, stuff->nDashes, 1646 (unsigned char *) &stuff[1]); 1647 } 1648 1649 int 1650 ProcSetClipRectangles(ClientPtr client) 1651 { 1652 int nr, result; 1653 GC *pGC; 1654 1655 REQUEST(xSetClipRectanglesReq); 1656 1657 REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); 1658 if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && 1659 (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) { 1660 client->errorValue = stuff->ordering; 1661 return BadValue; 1662 } 1663 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 1664 if (result != Success) 1665 return result; 1666 1667 nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); 1668 if (nr & 4) 1669 return BadLength; 1670 nr >>= 3; 1671 return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, 1672 nr, (xRectangle *) &stuff[1], (int) stuff->ordering); 1673 } 1674 1675 int 1676 ProcFreeGC(ClientPtr client) 1677 { 1678 GC *pGC; 1679 int rc; 1680 1681 REQUEST(xResourceReq); 1682 REQUEST_SIZE_MATCH(xResourceReq); 1683 1684 rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess); 1685 if (rc != Success) 1686 return rc; 1687 1688 FreeResource(stuff->id, RT_NONE); 1689 return Success; 1690 } 1691 1692 int 1693 ProcClearToBackground(ClientPtr client) 1694 { 1695 REQUEST(xClearAreaReq); 1696 WindowPtr pWin; 1697 int rc; 1698 1699 REQUEST_SIZE_MATCH(xClearAreaReq); 1700 rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); 1701 if (rc != Success) 1702 return rc; 1703 if (pWin->drawable.class == InputOnly) { 1704 client->errorValue = stuff->window; 1705 return BadMatch; 1706 } 1707 if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) { 1708 client->errorValue = stuff->exposures; 1709 return BadValue; 1710 } 1711 (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y, 1712 stuff->width, stuff->height, 1713 (Bool) stuff->exposures); 1714 return Success; 1715 } 1716 1717 /* send GraphicsExpose events, or a NoExpose event, based on the region */ 1718 void 1719 SendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable, 1720 int major, int minor) 1721 { 1722 if (pRgn && !RegionNil(pRgn)) { 1723 xEvent *pEvent; 1724 xEvent *pe; 1725 BoxPtr pBox; 1726 int i; 1727 int numRects; 1728 1729 numRects = RegionNumRects(pRgn); 1730 pBox = RegionRects(pRgn); 1731 if (!(pEvent = calloc(numRects, sizeof(xEvent)))) 1732 return; 1733 pe = pEvent; 1734 1735 for (i = 1; i <= numRects; i++, pe++, pBox++) { 1736 pe->u.u.type = GraphicsExpose; 1737 pe->u.graphicsExposure.drawable = drawable; 1738 pe->u.graphicsExposure.x = pBox->x1; 1739 pe->u.graphicsExposure.y = pBox->y1; 1740 pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; 1741 pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; 1742 pe->u.graphicsExposure.count = numRects - i; 1743 pe->u.graphicsExposure.majorEvent = major; 1744 pe->u.graphicsExposure.minorEvent = minor; 1745 } 1746 /* GraphicsExpose is a "critical event", which TryClientEvents 1747 * handles specially. */ 1748 TryClientEvents(client, NULL, pEvent, numRects, 1749 (Mask) 0, NoEventMask, NullGrab); 1750 free(pEvent); 1751 } 1752 else { 1753 xEvent event = { 1754 .u.noExposure.drawable = drawable, 1755 .u.noExposure.majorEvent = major, 1756 .u.noExposure.minorEvent = minor 1757 }; 1758 event.u.u.type = NoExpose; 1759 WriteEventsToClient(client, 1, &event); 1760 } 1761 } 1762 1763 int 1764 ProcCopyArea(ClientPtr client) 1765 { 1766 DrawablePtr pDst; 1767 DrawablePtr pSrc; 1768 GC *pGC; 1769 1770 REQUEST(xCopyAreaReq); 1771 RegionPtr pRgn; 1772 int rc; 1773 1774 REQUEST_SIZE_MATCH(xCopyAreaReq); 1775 1776 VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess); 1777 if (stuff->dstDrawable != stuff->srcDrawable) { 1778 rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0, 1779 DixReadAccess); 1780 if (rc != Success) 1781 return rc; 1782 if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) { 1783 client->errorValue = stuff->dstDrawable; 1784 return BadMatch; 1785 } 1786 } 1787 else 1788 pSrc = pDst; 1789 1790 pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY, 1791 stuff->width, stuff->height, 1792 stuff->dstX, stuff->dstY); 1793 if (pGC->graphicsExposures) { 1794 SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0); 1795 if (pRgn) 1796 RegionDestroy(pRgn); 1797 } 1798 1799 return Success; 1800 } 1801 1802 int 1803 ProcCopyPlane(ClientPtr client) 1804 { 1805 DrawablePtr psrcDraw, pdstDraw; 1806 GC *pGC; 1807 1808 REQUEST(xCopyPlaneReq); 1809 RegionPtr pRgn; 1810 int rc; 1811 1812 REQUEST_SIZE_MATCH(xCopyPlaneReq); 1813 1814 VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess); 1815 if (stuff->dstDrawable != stuff->srcDrawable) { 1816 rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0, 1817 DixReadAccess); 1818 if (rc != Success) 1819 return rc; 1820 1821 if (pdstDraw->pScreen != psrcDraw->pScreen) { 1822 client->errorValue = stuff->dstDrawable; 1823 return BadMatch; 1824 } 1825 } 1826 else 1827 psrcDraw = pdstDraw; 1828 1829 /* Check to see if stuff->bitPlane has exactly ONE good bit set */ 1830 if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || 1831 (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) { 1832 client->errorValue = stuff->bitPlane; 1833 return BadValue; 1834 } 1835 1836 pRgn = 1837 (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX, 1838 stuff->srcY, stuff->width, stuff->height, 1839 stuff->dstX, stuff->dstY, stuff->bitPlane); 1840 if (pGC->graphicsExposures) { 1841 SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); 1842 if (pRgn) 1843 RegionDestroy(pRgn); 1844 } 1845 return Success; 1846 } 1847 1848 int 1849 ProcPolyPoint(ClientPtr client) 1850 { 1851 int npoint; 1852 GC *pGC; 1853 DrawablePtr pDraw; 1854 1855 REQUEST(xPolyPointReq); 1856 1857 REQUEST_AT_LEAST_SIZE(xPolyPointReq); 1858 if ((stuff->coordMode != CoordModeOrigin) && 1859 (stuff->coordMode != CoordModePrevious)) { 1860 client->errorValue = stuff->coordMode; 1861 return BadValue; 1862 } 1863 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 1864 npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq)); 1865 if (npoint) 1866 (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint, 1867 (xPoint *) &stuff[1]); 1868 return Success; 1869 } 1870 1871 int 1872 ProcPolyLine(ClientPtr client) 1873 { 1874 int npoint; 1875 GC *pGC; 1876 DrawablePtr pDraw; 1877 1878 REQUEST(xPolyLineReq); 1879 1880 REQUEST_AT_LEAST_SIZE(xPolyLineReq); 1881 if ((stuff->coordMode != CoordModeOrigin) && 1882 (stuff->coordMode != CoordModePrevious)) { 1883 client->errorValue = stuff->coordMode; 1884 return BadValue; 1885 } 1886 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 1887 npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq)); 1888 if (npoint > 1) 1889 (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint, 1890 (DDXPointPtr) &stuff[1]); 1891 return Success; 1892 } 1893 1894 int 1895 ProcPolySegment(ClientPtr client) 1896 { 1897 int nsegs; 1898 GC *pGC; 1899 DrawablePtr pDraw; 1900 1901 REQUEST(xPolySegmentReq); 1902 1903 REQUEST_AT_LEAST_SIZE(xPolySegmentReq); 1904 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 1905 nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); 1906 if (nsegs & 4) 1907 return BadLength; 1908 nsegs >>= 3; 1909 if (nsegs) 1910 (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]); 1911 return Success; 1912 } 1913 1914 int 1915 ProcPolyRectangle(ClientPtr client) 1916 { 1917 int nrects; 1918 GC *pGC; 1919 DrawablePtr pDraw; 1920 1921 REQUEST(xPolyRectangleReq); 1922 1923 REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); 1924 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 1925 nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); 1926 if (nrects & 4) 1927 return BadLength; 1928 nrects >>= 3; 1929 if (nrects) 1930 (*pGC->ops->PolyRectangle) (pDraw, pGC, 1931 nrects, (xRectangle *) &stuff[1]); 1932 return Success; 1933 } 1934 1935 int 1936 ProcPolyArc(ClientPtr client) 1937 { 1938 int narcs; 1939 GC *pGC; 1940 DrawablePtr pDraw; 1941 1942 REQUEST(xPolyArcReq); 1943 1944 REQUEST_AT_LEAST_SIZE(xPolyArcReq); 1945 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 1946 narcs = (client->req_len << 2) - sizeof(xPolyArcReq); 1947 if (narcs % sizeof(xArc)) 1948 return BadLength; 1949 narcs /= sizeof(xArc); 1950 if (narcs) 1951 (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); 1952 return Success; 1953 } 1954 1955 int 1956 ProcFillPoly(ClientPtr client) 1957 { 1958 int things; 1959 GC *pGC; 1960 DrawablePtr pDraw; 1961 1962 REQUEST(xFillPolyReq); 1963 1964 REQUEST_AT_LEAST_SIZE(xFillPolyReq); 1965 if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && 1966 (stuff->shape != Convex)) { 1967 client->errorValue = stuff->shape; 1968 return BadValue; 1969 } 1970 if ((stuff->coordMode != CoordModeOrigin) && 1971 (stuff->coordMode != CoordModePrevious)) { 1972 client->errorValue = stuff->coordMode; 1973 return BadValue; 1974 } 1975 1976 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 1977 things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq)); 1978 if (things) 1979 (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, 1980 stuff->coordMode, things, 1981 (DDXPointPtr) &stuff[1]); 1982 return Success; 1983 } 1984 1985 int 1986 ProcPolyFillRectangle(ClientPtr client) 1987 { 1988 int things; 1989 GC *pGC; 1990 DrawablePtr pDraw; 1991 1992 REQUEST(xPolyFillRectangleReq); 1993 1994 REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); 1995 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 1996 things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); 1997 if (things & 4) 1998 return BadLength; 1999 things >>= 3; 2000 2001 if (things) 2002 (*pGC->ops->PolyFillRect) (pDraw, pGC, things, 2003 (xRectangle *) &stuff[1]); 2004 return Success; 2005 } 2006 2007 int 2008 ProcPolyFillArc(ClientPtr client) 2009 { 2010 int narcs; 2011 GC *pGC; 2012 DrawablePtr pDraw; 2013 2014 REQUEST(xPolyFillArcReq); 2015 2016 REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); 2017 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 2018 narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); 2019 if (narcs % sizeof(xArc)) 2020 return BadLength; 2021 narcs /= sizeof(xArc); 2022 if (narcs) 2023 (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); 2024 return Success; 2025 } 2026 2027 #ifdef MATCH_CLIENT_ENDIAN 2028 2029 int 2030 ServerOrder(void) 2031 { 2032 int whichbyte = 1; 2033 2034 if (*((char *) &whichbyte)) 2035 return LSBFirst; 2036 return MSBFirst; 2037 } 2038 2039 #define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) 2040 2041 void 2042 ReformatImage(char *base, int nbytes, int bpp, int order) 2043 { 2044 switch (bpp) { 2045 case 1: /* yuck */ 2046 if (BITMAP_BIT_ORDER != order) 2047 BitOrderInvert((unsigned char *) base, nbytes); 2048 #if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 2049 ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order); 2050 #endif 2051 break; 2052 case 4: 2053 break; /* yuck */ 2054 case 8: 2055 break; 2056 case 16: 2057 if (IMAGE_BYTE_ORDER != order) 2058 TwoByteSwap((unsigned char *) base, nbytes); 2059 break; 2060 case 32: 2061 if (IMAGE_BYTE_ORDER != order) 2062 FourByteSwap((unsigned char *) base, nbytes); 2063 break; 2064 } 2065 } 2066 #else 2067 #define ReformatImage(b,n,bpp,o) 2068 #endif 2069 2070 /* 64-bit server notes: the protocol restricts padding of images to 2071 * 8-, 16-, or 32-bits. We would like to have 64-bits for the server 2072 * to use internally. Removes need for internal alignment checking. 2073 * All of the PutImage functions could be changed individually, but 2074 * as currently written, they call other routines which require things 2075 * to be 64-bit padded on scanlines, so we changed things here. 2076 * If an image would be padded differently for 64- versus 32-, then 2077 * copy each scanline to a 64-bit padded scanline. 2078 * Also, we need to make sure that the image is aligned on a 64-bit 2079 * boundary, even if the scanlines are padded to our satisfaction. 2080 */ 2081 int 2082 ProcPutImage(ClientPtr client) 2083 { 2084 GC *pGC; 2085 DrawablePtr pDraw; 2086 long length; /* length of scanline server padded */ 2087 long lengthProto; /* length of scanline protocol padded */ 2088 char *tmpImage; 2089 2090 REQUEST(xPutImageReq); 2091 2092 REQUEST_AT_LEAST_SIZE(xPutImageReq); 2093 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 2094 if (stuff->format == XYBitmap) { 2095 if ((stuff->depth != 1) || 2096 (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad)) 2097 return BadMatch; 2098 length = BitmapBytePad(stuff->width + stuff->leftPad); 2099 } 2100 else if (stuff->format == XYPixmap) { 2101 if ((pDraw->depth != stuff->depth) || 2102 (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad)) 2103 return BadMatch; 2104 length = BitmapBytePad(stuff->width + stuff->leftPad); 2105 length *= stuff->depth; 2106 } 2107 else if (stuff->format == ZPixmap) { 2108 if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) 2109 return BadMatch; 2110 length = PixmapBytePad(stuff->width, stuff->depth); 2111 } 2112 else { 2113 client->errorValue = stuff->format; 2114 return BadValue; 2115 } 2116 2117 tmpImage = (char *) &stuff[1]; 2118 lengthProto = length; 2119 2120 if (stuff->height != 0 && lengthProto >= (INT32_MAX / stuff->height)) 2121 return BadLength; 2122 2123 if ((bytes_to_int32(lengthProto * stuff->height) + 2124 bytes_to_int32(sizeof(xPutImageReq))) != client->req_len) 2125 return BadLength; 2126 2127 ReformatImage(tmpImage, lengthProto * stuff->height, 2128 stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1, 2129 ClientOrder(client)); 2130 2131 (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, 2132 stuff->width, stuff->height, 2133 stuff->leftPad, stuff->format, tmpImage); 2134 2135 return Success; 2136 } 2137 2138 static int 2139 DoGetImage(ClientPtr client, int format, Drawable drawable, 2140 int x, int y, int width, int height, 2141 Mask planemask) 2142 { 2143 DrawablePtr pDraw, pBoundingDraw; 2144 int nlines, linesPerBuf, rc; 2145 int linesDone; 2146 2147 /* coordinates relative to the bounding drawable */ 2148 int relx, rely; 2149 long widthBytesLine, length; 2150 Mask plane = 0; 2151 char *pBuf; 2152 xGetImageReply xgi; 2153 RegionPtr pVisibleRegion = NULL; 2154 2155 if ((format != XYPixmap) && (format != ZPixmap)) { 2156 client->errorValue = format; 2157 return BadValue; 2158 } 2159 rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess); 2160 if (rc != Success) 2161 return rc; 2162 2163 memset(&xgi, 0, sizeof(xGetImageReply)); 2164 2165 relx = x; 2166 rely = y; 2167 2168 if (pDraw->type == DRAWABLE_WINDOW) { 2169 WindowPtr pWin = (WindowPtr) pDraw; 2170 2171 /* "If the drawable is a window, the window must be viewable ... or a 2172 * BadMatch error results" */ 2173 if (!pWin->viewable) 2174 return BadMatch; 2175 2176 /* If the drawable is a window, the rectangle must be contained within 2177 * its bounds (including the border). */ 2178 if (x < -wBorderWidth(pWin) || 2179 x + width > wBorderWidth(pWin) + (int) pDraw->width || 2180 y < -wBorderWidth(pWin) || 2181 y + height > wBorderWidth(pWin) + (int) pDraw->height) 2182 return BadMatch; 2183 2184 relx += pDraw->x; 2185 rely += pDraw->y; 2186 2187 if (pDraw->pScreen->GetWindowPixmap) { 2188 PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin); 2189 2190 pBoundingDraw = &pPix->drawable; 2191 #ifdef COMPOSITE 2192 relx -= pPix->screen_x; 2193 rely -= pPix->screen_y; 2194 #endif 2195 } 2196 else { 2197 pBoundingDraw = (DrawablePtr) pDraw->pScreen->root; 2198 } 2199 2200 xgi.visual = wVisual(pWin); 2201 } 2202 else { 2203 pBoundingDraw = pDraw; 2204 xgi.visual = None; 2205 } 2206 2207 /* "If the drawable is a pixmap, the given rectangle must be wholly 2208 * contained within the pixmap, or a BadMatch error results. If the 2209 * drawable is a window [...] it must be the case that if there were no 2210 * inferiors or overlapping windows, the specified rectangle of the window 2211 * would be fully visible on the screen and wholly contained within the 2212 * outside edges of the window, or a BadMatch error results." 2213 * 2214 * We relax the window case slightly to mean that the rectangle must exist 2215 * within the bounds of the window's backing pixmap. In particular, this 2216 * means that a GetImage request may succeed or fail with BadMatch depending 2217 * on whether any of its ancestor windows are redirected. */ 2218 if (relx < 0 || relx + width > (int) pBoundingDraw->width || 2219 rely < 0 || rely + height > (int) pBoundingDraw->height) 2220 return BadMatch; 2221 2222 xgi.type = X_Reply; 2223 xgi.sequenceNumber = client->sequence; 2224 xgi.depth = pDraw->depth; 2225 if (format == ZPixmap) { 2226 widthBytesLine = PixmapBytePad(width, pDraw->depth); 2227 length = widthBytesLine * height; 2228 2229 } 2230 else { 2231 widthBytesLine = BitmapBytePad(width); 2232 plane = ((Mask) 1) << (pDraw->depth - 1); 2233 /* only planes asked for */ 2234 length = widthBytesLine * height * 2235 Ones(planemask & (plane | (plane - 1))); 2236 2237 } 2238 2239 xgi.length = length; 2240 2241 xgi.length = bytes_to_int32(xgi.length); 2242 if (widthBytesLine == 0 || height == 0) 2243 linesPerBuf = 0; 2244 else if (widthBytesLine >= IMAGE_BUFSIZE) 2245 linesPerBuf = 1; 2246 else { 2247 linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; 2248 if (linesPerBuf > height) 2249 linesPerBuf = height; 2250 } 2251 length = linesPerBuf * widthBytesLine; 2252 if (linesPerBuf < height) { 2253 /* we have to make sure intermediate buffers don't need padding */ 2254 while ((linesPerBuf > 1) && 2255 (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) { 2256 linesPerBuf--; 2257 length -= widthBytesLine; 2258 } 2259 while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) { 2260 linesPerBuf++; 2261 length += widthBytesLine; 2262 } 2263 } 2264 if (!(pBuf = calloc(1, length))) 2265 return BadAlloc; 2266 WriteReplyToClient(client, sizeof(xGetImageReply), &xgi); 2267 2268 if (pDraw->type == DRAWABLE_WINDOW) { 2269 pVisibleRegion = &((WindowPtr) pDraw)->borderClip; 2270 pDraw->pScreen->SourceValidate(pDraw, x, y, width, height, 2271 IncludeInferiors); 2272 } 2273 2274 if (linesPerBuf == 0) { 2275 /* nothing to do */ 2276 } 2277 else if (format == ZPixmap) { 2278 linesDone = 0; 2279 while (height - linesDone > 0) { 2280 nlines = min(linesPerBuf, height - linesDone); 2281 (*pDraw->pScreen->GetImage) (pDraw, 2282 x, 2283 y + linesDone, 2284 width, 2285 nlines, 2286 format, planemask, (void *) pBuf); 2287 if (pVisibleRegion) 2288 XaceCensorImage(client, pVisibleRegion, widthBytesLine, 2289 pDraw, x, y + linesDone, width, 2290 nlines, format, pBuf); 2291 2292 /* Note that this is NOT a call to WriteSwappedDataToClient, 2293 as we do NOT byte swap */ 2294 ReformatImage(pBuf, (int) (nlines * widthBytesLine), 2295 BitsPerPixel(pDraw->depth), ClientOrder(client)); 2296 2297 WriteToClient(client, (int) (nlines * widthBytesLine), pBuf); 2298 linesDone += nlines; 2299 } 2300 } 2301 else { /* XYPixmap */ 2302 2303 for (; plane; plane >>= 1) { 2304 if (planemask & plane) { 2305 linesDone = 0; 2306 while (height - linesDone > 0) { 2307 nlines = min(linesPerBuf, height - linesDone); 2308 (*pDraw->pScreen->GetImage) (pDraw, 2309 x, 2310 y + linesDone, 2311 width, 2312 nlines, 2313 format, plane, (void *) pBuf); 2314 if (pVisibleRegion) 2315 XaceCensorImage(client, pVisibleRegion, 2316 widthBytesLine, 2317 pDraw, x, y + linesDone, width, 2318 nlines, format, pBuf); 2319 2320 /* Note: NOT a call to WriteSwappedDataToClient, 2321 as we do NOT byte swap */ 2322 ReformatImage(pBuf, (int) (nlines * widthBytesLine), 2323 1, ClientOrder(client)); 2324 2325 WriteToClient(client, (int)(nlines * widthBytesLine), pBuf); 2326 linesDone += nlines; 2327 } 2328 } 2329 } 2330 } 2331 free(pBuf); 2332 return Success; 2333 } 2334 2335 int 2336 ProcGetImage(ClientPtr client) 2337 { 2338 REQUEST(xGetImageReq); 2339 2340 REQUEST_SIZE_MATCH(xGetImageReq); 2341 2342 return DoGetImage(client, stuff->format, stuff->drawable, 2343 stuff->x, stuff->y, 2344 (int) stuff->width, (int) stuff->height, 2345 stuff->planeMask); 2346 } 2347 2348 int 2349 ProcPolyText(ClientPtr client) 2350 { 2351 int err; 2352 2353 REQUEST(xPolyTextReq); 2354 DrawablePtr pDraw; 2355 GC *pGC; 2356 2357 REQUEST_AT_LEAST_SIZE(xPolyTextReq); 2358 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 2359 2360 err = PolyText(client, 2361 pDraw, 2362 pGC, 2363 (unsigned char *) &stuff[1], 2364 ((unsigned char *) stuff) + (client->req_len << 2), 2365 stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2366 2367 if (err == Success) { 2368 return Success; 2369 } 2370 else 2371 return err; 2372 } 2373 2374 int 2375 ProcImageText8(ClientPtr client) 2376 { 2377 int err; 2378 DrawablePtr pDraw; 2379 GC *pGC; 2380 2381 REQUEST(xImageTextReq); 2382 2383 REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); 2384 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 2385 2386 err = ImageText(client, 2387 pDraw, 2388 pGC, 2389 stuff->nChars, 2390 (unsigned char *) &stuff[1], 2391 stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2392 2393 if (err == Success) { 2394 return Success; 2395 } 2396 else 2397 return err; 2398 } 2399 2400 int 2401 ProcImageText16(ClientPtr client) 2402 { 2403 int err; 2404 DrawablePtr pDraw; 2405 GC *pGC; 2406 2407 REQUEST(xImageTextReq); 2408 2409 REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); 2410 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 2411 2412 err = ImageText(client, 2413 pDraw, 2414 pGC, 2415 stuff->nChars, 2416 (unsigned char *) &stuff[1], 2417 stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2418 2419 if (err == Success) { 2420 return Success; 2421 } 2422 else 2423 return err; 2424 } 2425 2426 int 2427 ProcCreateColormap(ClientPtr client) 2428 { 2429 VisualPtr pVisual; 2430 ColormapPtr pmap; 2431 Colormap mid; 2432 WindowPtr pWin; 2433 ScreenPtr pScreen; 2434 2435 REQUEST(xCreateColormapReq); 2436 int i, result; 2437 2438 REQUEST_SIZE_MATCH(xCreateColormapReq); 2439 2440 if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) { 2441 client->errorValue = stuff->alloc; 2442 return BadValue; 2443 } 2444 mid = stuff->mid; 2445 LEGAL_NEW_RESOURCE(mid, client); 2446 result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2447 if (result != Success) 2448 return result; 2449 2450 pScreen = pWin->drawable.pScreen; 2451 for (i = 0, pVisual = pScreen->visuals; 2452 i < pScreen->numVisuals; i++, pVisual++) { 2453 if (pVisual->vid != stuff->visual) 2454 continue; 2455 return CreateColormap(mid, pScreen, pVisual, &pmap, 2456 (int) stuff->alloc, client->index); 2457 } 2458 client->errorValue = stuff->visual; 2459 return BadMatch; 2460 } 2461 2462 int 2463 ProcFreeColormap(ClientPtr client) 2464 { 2465 ColormapPtr pmap; 2466 int rc; 2467 2468 REQUEST(xResourceReq); 2469 2470 REQUEST_SIZE_MATCH(xResourceReq); 2471 rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP, 2472 client, DixDestroyAccess); 2473 if (rc == Success) { 2474 /* Freeing a default colormap is a no-op */ 2475 if (!(pmap->flags & IsDefault)) 2476 FreeResource(stuff->id, RT_NONE); 2477 return Success; 2478 } 2479 else { 2480 client->errorValue = stuff->id; 2481 return rc; 2482 } 2483 } 2484 2485 int 2486 ProcCopyColormapAndFree(ClientPtr client) 2487 { 2488 Colormap mid; 2489 ColormapPtr pSrcMap; 2490 2491 REQUEST(xCopyColormapAndFreeReq); 2492 int rc; 2493 2494 REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); 2495 mid = stuff->mid; 2496 LEGAL_NEW_RESOURCE(mid, client); 2497 rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap, 2498 RT_COLORMAP, client, 2499 DixReadAccess | DixRemoveAccess); 2500 if (rc == Success) 2501 return CopyColormapAndFree(mid, pSrcMap, client->index); 2502 client->errorValue = stuff->srcCmap; 2503 return rc; 2504 } 2505 2506 int 2507 ProcInstallColormap(ClientPtr client) 2508 { 2509 ColormapPtr pcmp; 2510 int rc; 2511 2512 REQUEST(xResourceReq); 2513 REQUEST_SIZE_MATCH(xResourceReq); 2514 2515 rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP, 2516 client, DixInstallAccess); 2517 if (rc != Success) 2518 goto out; 2519 2520 rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); 2521 if (rc != Success) { 2522 if (rc == BadValue) 2523 rc = BadColor; 2524 goto out; 2525 } 2526 2527 (*(pcmp->pScreen->InstallColormap)) (pcmp); 2528 return Success; 2529 2530 out: 2531 client->errorValue = stuff->id; 2532 return rc; 2533 } 2534 2535 int 2536 ProcUninstallColormap(ClientPtr client) 2537 { 2538 ColormapPtr pcmp; 2539 int rc; 2540 2541 REQUEST(xResourceReq); 2542 REQUEST_SIZE_MATCH(xResourceReq); 2543 2544 rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP, 2545 client, DixUninstallAccess); 2546 if (rc != Success) 2547 goto out; 2548 2549 rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); 2550 if (rc != Success) { 2551 if (rc == BadValue) 2552 rc = BadColor; 2553 goto out; 2554 } 2555 2556 if (pcmp->mid != pcmp->pScreen->defColormap) 2557 (*(pcmp->pScreen->UninstallColormap)) (pcmp); 2558 return Success; 2559 2560 out: 2561 client->errorValue = stuff->id; 2562 return rc; 2563 } 2564 2565 int 2566 ProcListInstalledColormaps(ClientPtr client) 2567 { 2568 xListInstalledColormapsReply *preply; 2569 int nummaps, rc; 2570 WindowPtr pWin; 2571 2572 REQUEST(xResourceReq); 2573 REQUEST_SIZE_MATCH(xResourceReq); 2574 2575 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 2576 if (rc != Success) 2577 return rc; 2578 2579 rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen, 2580 DixGetAttrAccess); 2581 if (rc != Success) 2582 return rc; 2583 2584 preply = malloc(sizeof(xListInstalledColormapsReply) + 2585 pWin->drawable.pScreen->maxInstalledCmaps * 2586 sizeof(Colormap)); 2587 if (!preply) 2588 return BadAlloc; 2589 2590 preply->type = X_Reply; 2591 preply->sequenceNumber = client->sequence; 2592 nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) 2593 (pWin->drawable.pScreen, (Colormap *) &preply[1]); 2594 preply->nColormaps = nummaps; 2595 preply->length = nummaps; 2596 WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply); 2597 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 2598 WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); 2599 free(preply); 2600 return Success; 2601 } 2602 2603 int 2604 ProcAllocColor(ClientPtr client) 2605 { 2606 ColormapPtr pmap; 2607 int rc; 2608 2609 REQUEST(xAllocColorReq); 2610 2611 REQUEST_SIZE_MATCH(xAllocColorReq); 2612 rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP, 2613 client, DixAddAccess); 2614 if (rc == Success) { 2615 xAllocColorReply acr = { 2616 .type = X_Reply, 2617 .sequenceNumber = client->sequence, 2618 .length = 0, 2619 .red = stuff->red, 2620 .green = stuff->green, 2621 .blue = stuff->blue, 2622 .pixel = 0 2623 }; 2624 if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, 2625 &acr.pixel, client->index))) 2626 return rc; 2627 #ifdef PANORAMIX 2628 if (noPanoramiXExtension || !pmap->pScreen->myNum) 2629 #endif 2630 WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); 2631 return Success; 2632 2633 } 2634 else { 2635 client->errorValue = stuff->cmap; 2636 return rc; 2637 } 2638 } 2639 2640 int 2641 ProcAllocNamedColor(ClientPtr client) 2642 { 2643 ColormapPtr pcmp; 2644 int rc; 2645 2646 REQUEST(xAllocNamedColorReq); 2647 2648 REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); 2649 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2650 client, DixAddAccess); 2651 if (rc == Success) { 2652 xAllocNamedColorReply ancr = { 2653 .type = X_Reply, 2654 .sequenceNumber = client->sequence, 2655 .length = 0 2656 }; 2657 if (OsLookupColor 2658 (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes, 2659 &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) { 2660 ancr.screenRed = ancr.exactRed; 2661 ancr.screenGreen = ancr.exactGreen; 2662 ancr.screenBlue = ancr.exactBlue; 2663 ancr.pixel = 0; 2664 if ((rc = AllocColor(pcmp, 2665 &ancr.screenRed, &ancr.screenGreen, 2666 &ancr.screenBlue, &ancr.pixel, client->index))) 2667 return rc; 2668 #ifdef PANORAMIX 2669 if (noPanoramiXExtension || !pcmp->pScreen->myNum) 2670 #endif 2671 WriteReplyToClient(client, sizeof(xAllocNamedColorReply), 2672 &ancr); 2673 return Success; 2674 } 2675 else 2676 return BadName; 2677 2678 } 2679 else { 2680 client->errorValue = stuff->cmap; 2681 return rc; 2682 } 2683 } 2684 2685 int 2686 ProcAllocColorCells(ClientPtr client) 2687 { 2688 ColormapPtr pcmp; 2689 int rc; 2690 2691 REQUEST(xAllocColorCellsReq); 2692 2693 REQUEST_SIZE_MATCH(xAllocColorCellsReq); 2694 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2695 client, DixAddAccess); 2696 if (rc == Success) { 2697 int npixels, nmasks; 2698 long length; 2699 Pixel *ppixels, *pmasks; 2700 2701 npixels = stuff->colors; 2702 if (!npixels) { 2703 client->errorValue = npixels; 2704 return BadValue; 2705 } 2706 if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) { 2707 client->errorValue = stuff->contiguous; 2708 return BadValue; 2709 } 2710 nmasks = stuff->planes; 2711 length = ((long) npixels + (long) nmasks) * sizeof(Pixel); 2712 ppixels = malloc(length); 2713 if (!ppixels) 2714 return BadAlloc; 2715 pmasks = ppixels + npixels; 2716 2717 if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks, 2718 (Bool) stuff->contiguous, ppixels, pmasks))) { 2719 free(ppixels); 2720 return rc; 2721 } 2722 #ifdef PANORAMIX 2723 if (noPanoramiXExtension || !pcmp->pScreen->myNum) 2724 #endif 2725 { 2726 xAllocColorCellsReply accr = { 2727 .type = X_Reply, 2728 .sequenceNumber = client->sequence, 2729 .length = bytes_to_int32(length), 2730 .nPixels = npixels, 2731 .nMasks = nmasks 2732 }; 2733 WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr); 2734 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 2735 WriteSwappedDataToClient(client, length, ppixels); 2736 } 2737 free(ppixels); 2738 return Success; 2739 } 2740 else { 2741 client->errorValue = stuff->cmap; 2742 return rc; 2743 } 2744 } 2745 2746 int 2747 ProcAllocColorPlanes(ClientPtr client) 2748 { 2749 ColormapPtr pcmp; 2750 int rc; 2751 2752 REQUEST(xAllocColorPlanesReq); 2753 2754 REQUEST_SIZE_MATCH(xAllocColorPlanesReq); 2755 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2756 client, DixAddAccess); 2757 if (rc == Success) { 2758 xAllocColorPlanesReply acpr; 2759 int npixels; 2760 long length; 2761 Pixel *ppixels; 2762 2763 npixels = stuff->colors; 2764 if (!npixels) { 2765 client->errorValue = npixels; 2766 return BadValue; 2767 } 2768 if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) { 2769 client->errorValue = stuff->contiguous; 2770 return BadValue; 2771 } 2772 acpr = (xAllocColorPlanesReply) { 2773 .type = X_Reply, 2774 .sequenceNumber = client->sequence, 2775 .nPixels = npixels 2776 }; 2777 length = (long) npixels *sizeof(Pixel); 2778 2779 ppixels = malloc(length); 2780 if (!ppixels) 2781 return BadAlloc; 2782 if ((rc = AllocColorPlanes(client->index, pcmp, npixels, 2783 (int) stuff->red, (int) stuff->green, 2784 (int) stuff->blue, (Bool) stuff->contiguous, 2785 ppixels, &acpr.redMask, &acpr.greenMask, 2786 &acpr.blueMask))) { 2787 free(ppixels); 2788 return rc; 2789 } 2790 acpr.length = bytes_to_int32(length); 2791 #ifdef PANORAMIX 2792 if (noPanoramiXExtension || !pcmp->pScreen->myNum) 2793 #endif 2794 { 2795 WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); 2796 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 2797 WriteSwappedDataToClient(client, length, ppixels); 2798 } 2799 free(ppixels); 2800 return Success; 2801 } 2802 else { 2803 client->errorValue = stuff->cmap; 2804 return rc; 2805 } 2806 } 2807 2808 int 2809 ProcFreeColors(ClientPtr client) 2810 { 2811 ColormapPtr pcmp; 2812 int rc; 2813 2814 REQUEST(xFreeColorsReq); 2815 2816 REQUEST_AT_LEAST_SIZE(xFreeColorsReq); 2817 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2818 client, DixRemoveAccess); 2819 if (rc == Success) { 2820 int count; 2821 2822 if (pcmp->flags & AllAllocated) 2823 return BadAccess; 2824 count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq)); 2825 return FreeColors(pcmp, client->index, count, 2826 (Pixel *) &stuff[1], (Pixel) stuff->planeMask); 2827 } 2828 else { 2829 client->errorValue = stuff->cmap; 2830 return rc; 2831 } 2832 } 2833 2834 int 2835 ProcStoreColors(ClientPtr client) 2836 { 2837 ColormapPtr pcmp; 2838 int rc; 2839 2840 REQUEST(xStoreColorsReq); 2841 2842 REQUEST_AT_LEAST_SIZE(xStoreColorsReq); 2843 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2844 client, DixWriteAccess); 2845 if (rc == Success) { 2846 int count; 2847 2848 count = (client->req_len << 2) - sizeof(xStoreColorsReq); 2849 if (count % sizeof(xColorItem)) 2850 return BadLength; 2851 count /= sizeof(xColorItem); 2852 return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client); 2853 } 2854 else { 2855 client->errorValue = stuff->cmap; 2856 return rc; 2857 } 2858 } 2859 2860 int 2861 ProcStoreNamedColor(ClientPtr client) 2862 { 2863 ColormapPtr pcmp; 2864 int rc; 2865 2866 REQUEST(xStoreNamedColorReq); 2867 2868 REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); 2869 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2870 client, DixWriteAccess); 2871 if (rc == Success) { 2872 xColorItem def; 2873 2874 if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1], 2875 stuff->nbytes, &def.red, &def.green, &def.blue)) { 2876 def.flags = stuff->flags; 2877 def.pixel = stuff->pixel; 2878 return StoreColors(pcmp, 1, &def, client); 2879 } 2880 return BadName; 2881 } 2882 else { 2883 client->errorValue = stuff->cmap; 2884 return rc; 2885 } 2886 } 2887 2888 int 2889 ProcQueryColors(ClientPtr client) 2890 { 2891 ColormapPtr pcmp; 2892 int rc; 2893 2894 REQUEST(xQueryColorsReq); 2895 2896 REQUEST_AT_LEAST_SIZE(xQueryColorsReq); 2897 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2898 client, DixReadAccess); 2899 if (rc == Success) { 2900 int count; 2901 xrgb *prgbs; 2902 xQueryColorsReply qcr; 2903 2904 count = 2905 bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq)); 2906 prgbs = calloc(count, sizeof(xrgb)); 2907 if (!prgbs && count) 2908 return BadAlloc; 2909 if ((rc = 2910 QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) { 2911 free(prgbs); 2912 return rc; 2913 } 2914 qcr = (xQueryColorsReply) { 2915 .type = X_Reply, 2916 .sequenceNumber = client->sequence, 2917 .length = bytes_to_int32(count * sizeof(xrgb)), 2918 .nColors = count 2919 }; 2920 WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); 2921 if (count) { 2922 client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; 2923 WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); 2924 } 2925 free(prgbs); 2926 return Success; 2927 2928 } 2929 else { 2930 client->errorValue = stuff->cmap; 2931 return rc; 2932 } 2933 } 2934 2935 int 2936 ProcLookupColor(ClientPtr client) 2937 { 2938 ColormapPtr pcmp; 2939 int rc; 2940 2941 REQUEST(xLookupColorReq); 2942 2943 REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); 2944 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2945 client, DixReadAccess); 2946 if (rc == Success) { 2947 CARD16 exactRed, exactGreen, exactBlue; 2948 2949 if (OsLookupColor 2950 (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes, 2951 &exactRed, &exactGreen, &exactBlue)) { 2952 xLookupColorReply lcr = { 2953 .type = X_Reply, 2954 .sequenceNumber = client->sequence, 2955 .length = 0, 2956 .exactRed = exactRed, 2957 .exactGreen = exactGreen, 2958 .exactBlue = exactBlue, 2959 .screenRed = exactRed, 2960 .screenGreen = exactGreen, 2961 .screenBlue = exactBlue 2962 }; 2963 (*pcmp->pScreen->ResolveColor) (&lcr.screenRed, 2964 &lcr.screenGreen, 2965 &lcr.screenBlue, pcmp->pVisual); 2966 WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); 2967 return Success; 2968 } 2969 return BadName; 2970 } 2971 else { 2972 client->errorValue = stuff->cmap; 2973 return rc; 2974 } 2975 } 2976 2977 int 2978 ProcCreateCursor(ClientPtr client) 2979 { 2980 CursorPtr pCursor; 2981 PixmapPtr src; 2982 PixmapPtr msk; 2983 unsigned char *srcbits; 2984 unsigned char *mskbits; 2985 unsigned short width, height; 2986 long n; 2987 CursorMetricRec cm; 2988 int rc; 2989 2990 REQUEST(xCreateCursorReq); 2991 2992 REQUEST_SIZE_MATCH(xCreateCursorReq); 2993 LEGAL_NEW_RESOURCE(stuff->cid, client); 2994 2995 rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP, 2996 client, DixReadAccess); 2997 if (rc != Success) { 2998 client->errorValue = stuff->source; 2999 return rc; 3000 } 3001 3002 if (src->drawable.depth != 1) 3003 return (BadMatch); 3004 3005 /* Find and validate cursor mask pixmap, if one is provided */ 3006 if (stuff->mask != None) { 3007 rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP, 3008 client, DixReadAccess); 3009 if (rc != Success) { 3010 client->errorValue = stuff->mask; 3011 return rc; 3012 } 3013 3014 if (src->drawable.width != msk->drawable.width 3015 || src->drawable.height != msk->drawable.height 3016 || src->drawable.depth != 1 || msk->drawable.depth != 1) 3017 return BadMatch; 3018 } 3019 else 3020 msk = NULL; 3021 3022 width = src->drawable.width; 3023 height = src->drawable.height; 3024 3025 if (stuff->x > width || stuff->y > height) 3026 return BadMatch; 3027 3028 srcbits = calloc(BitmapBytePad(width), height); 3029 if (!srcbits) 3030 return BadAlloc; 3031 n = BitmapBytePad(width) * height; 3032 mskbits = malloc(n); 3033 if (!mskbits) { 3034 free(srcbits); 3035 return BadAlloc; 3036 } 3037 3038 (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height, 3039 XYPixmap, 1, (void *) srcbits); 3040 if (msk == (PixmapPtr) NULL) { 3041 unsigned char *bits = mskbits; 3042 3043 while (--n >= 0) 3044 *bits++ = ~0; 3045 } 3046 else { 3047 /* zeroing the (pad) bits helps some ddx cursor handling */ 3048 memset((char *) mskbits, 0, n); 3049 (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width, 3050 height, XYPixmap, 1, 3051 (void *) mskbits); 3052 } 3053 cm.width = width; 3054 cm.height = height; 3055 cm.xhot = stuff->x; 3056 cm.yhot = stuff->y; 3057 rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm, 3058 stuff->foreRed, stuff->foreGreen, stuff->foreBlue, 3059 stuff->backRed, stuff->backGreen, stuff->backBlue, 3060 &pCursor, client, stuff->cid); 3061 3062 if (rc != Success) 3063 goto bail; 3064 if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) { 3065 rc = BadAlloc; 3066 goto bail; 3067 } 3068 3069 return Success; 3070 bail: 3071 free(srcbits); 3072 free(mskbits); 3073 return rc; 3074 } 3075 3076 int 3077 ProcCreateGlyphCursor(ClientPtr client) 3078 { 3079 CursorPtr pCursor; 3080 int res; 3081 3082 REQUEST(xCreateGlyphCursorReq); 3083 3084 REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); 3085 LEGAL_NEW_RESOURCE(stuff->cid, client); 3086 3087 res = AllocGlyphCursor(stuff->source, stuff->sourceChar, 3088 stuff->mask, stuff->maskChar, 3089 stuff->foreRed, stuff->foreGreen, stuff->foreBlue, 3090 stuff->backRed, stuff->backGreen, stuff->backBlue, 3091 &pCursor, client, stuff->cid); 3092 if (res != Success) 3093 return res; 3094 if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) 3095 return Success; 3096 return BadAlloc; 3097 } 3098 3099 int 3100 ProcFreeCursor(ClientPtr client) 3101 { 3102 CursorPtr pCursor; 3103 int rc; 3104 3105 REQUEST(xResourceReq); 3106 3107 REQUEST_SIZE_MATCH(xResourceReq); 3108 rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR, 3109 client, DixDestroyAccess); 3110 if (rc == Success) { 3111 if (pCursor == rootCursor) { 3112 client->errorValue = stuff->id; 3113 return BadCursor; 3114 } 3115 FreeResource(stuff->id, RT_NONE); 3116 return Success; 3117 } 3118 else { 3119 client->errorValue = stuff->id; 3120 return rc; 3121 } 3122 } 3123 3124 int 3125 ProcQueryBestSize(ClientPtr client) 3126 { 3127 xQueryBestSizeReply reply; 3128 DrawablePtr pDraw; 3129 ScreenPtr pScreen; 3130 int rc; 3131 3132 REQUEST(xQueryBestSizeReq); 3133 REQUEST_SIZE_MATCH(xQueryBestSizeReq); 3134 3135 if ((stuff->class != CursorShape) && 3136 (stuff->class != TileShape) && (stuff->class != StippleShape)) { 3137 client->errorValue = stuff->class; 3138 return BadValue; 3139 } 3140 3141 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 3142 DixGetAttrAccess); 3143 if (rc != Success) 3144 return rc; 3145 if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) 3146 return BadMatch; 3147 pScreen = pDraw->pScreen; 3148 rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); 3149 if (rc != Success) 3150 return rc; 3151 (*pScreen->QueryBestSize) (stuff->class, &stuff->width, 3152 &stuff->height, pScreen); 3153 reply = (xQueryBestSizeReply) { 3154 .type = X_Reply, 3155 .sequenceNumber = client->sequence, 3156 .length = 0, 3157 .width = stuff->width, 3158 .height = stuff->height 3159 }; 3160 WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); 3161 return Success; 3162 } 3163 3164 int 3165 ProcSetScreenSaver(ClientPtr client) 3166 { 3167 int rc, i, blankingOption, exposureOption; 3168 3169 REQUEST(xSetScreenSaverReq); 3170 REQUEST_SIZE_MATCH(xSetScreenSaverReq); 3171 3172 for (i = 0; i < screenInfo.numScreens; i++) { 3173 rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], 3174 DixSetAttrAccess); 3175 if (rc != Success) 3176 return rc; 3177 } 3178 3179 blankingOption = stuff->preferBlank; 3180 if ((blankingOption != DontPreferBlanking) && 3181 (blankingOption != PreferBlanking) && 3182 (blankingOption != DefaultBlanking)) { 3183 client->errorValue = blankingOption; 3184 return BadValue; 3185 } 3186 exposureOption = stuff->allowExpose; 3187 if ((exposureOption != DontAllowExposures) && 3188 (exposureOption != AllowExposures) && 3189 (exposureOption != DefaultExposures)) { 3190 client->errorValue = exposureOption; 3191 return BadValue; 3192 } 3193 if (stuff->timeout < -1) { 3194 client->errorValue = stuff->timeout; 3195 return BadValue; 3196 } 3197 if (stuff->interval < -1) { 3198 client->errorValue = stuff->interval; 3199 return BadValue; 3200 } 3201 3202 if (blankingOption == DefaultBlanking) 3203 ScreenSaverBlanking = defaultScreenSaverBlanking; 3204 else 3205 ScreenSaverBlanking = blankingOption; 3206 if (exposureOption == DefaultExposures) 3207 ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; 3208 else 3209 ScreenSaverAllowExposures = exposureOption; 3210 3211 if (stuff->timeout >= 0) 3212 ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; 3213 else 3214 ScreenSaverTime = defaultScreenSaverTime; 3215 if (stuff->interval >= 0) 3216 ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; 3217 else 3218 ScreenSaverInterval = defaultScreenSaverInterval; 3219 3220 SetScreenSaverTimer(); 3221 return Success; 3222 } 3223 3224 int 3225 ProcGetScreenSaver(ClientPtr client) 3226 { 3227 xGetScreenSaverReply rep; 3228 int rc, i; 3229 3230 REQUEST_SIZE_MATCH(xReq); 3231 3232 for (i = 0; i < screenInfo.numScreens; i++) { 3233 rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], 3234 DixGetAttrAccess); 3235 if (rc != Success) 3236 return rc; 3237 } 3238 3239 rep = (xGetScreenSaverReply) { 3240 .type = X_Reply, 3241 .sequenceNumber = client->sequence, 3242 .length = 0, 3243 .timeout = ScreenSaverTime / MILLI_PER_SECOND, 3244 .interval = ScreenSaverInterval / MILLI_PER_SECOND, 3245 .preferBlanking = ScreenSaverBlanking, 3246 .allowExposures = ScreenSaverAllowExposures 3247 }; 3248 WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); 3249 return Success; 3250 } 3251 3252 int 3253 ProcChangeHosts(ClientPtr client) 3254 { 3255 REQUEST(xChangeHostsReq); 3256 3257 REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); 3258 3259 if (stuff->mode == HostInsert) 3260 return AddHost(client, (int) stuff->hostFamily, 3261 stuff->hostLength, (void *) &stuff[1]); 3262 if (stuff->mode == HostDelete) 3263 return RemoveHost(client, (int) stuff->hostFamily, 3264 stuff->hostLength, (void *) &stuff[1]); 3265 client->errorValue = stuff->mode; 3266 return BadValue; 3267 } 3268 3269 int 3270 ProcListHosts(ClientPtr client) 3271 { 3272 xListHostsReply reply; 3273 int len, nHosts, result; 3274 BOOL enabled; 3275 void *pdata; 3276 3277 /* REQUEST(xListHostsReq); */ 3278 3279 REQUEST_SIZE_MATCH(xListHostsReq); 3280 3281 /* untrusted clients can't list hosts */ 3282 result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess); 3283 if (result != Success) 3284 return result; 3285 3286 result = GetHosts(&pdata, &nHosts, &len, &enabled); 3287 if (result != Success) 3288 return result; 3289 3290 reply = (xListHostsReply) { 3291 .type = X_Reply, 3292 .enabled = enabled, 3293 .sequenceNumber = client->sequence, 3294 .length = bytes_to_int32(len), 3295 .nHosts = nHosts 3296 }; 3297 WriteReplyToClient(client, sizeof(xListHostsReply), &reply); 3298 if (nHosts) { 3299 client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; 3300 WriteSwappedDataToClient(client, len, pdata); 3301 } 3302 free(pdata); 3303 return Success; 3304 } 3305 3306 int 3307 ProcChangeAccessControl(ClientPtr client) 3308 { 3309 REQUEST(xSetAccessControlReq); 3310 3311 REQUEST_SIZE_MATCH(xSetAccessControlReq); 3312 if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) { 3313 client->errorValue = stuff->mode; 3314 return BadValue; 3315 } 3316 return ChangeAccessControl(client, stuff->mode == EnableAccess); 3317 } 3318 3319 /********************* 3320 * CloseDownRetainedResources 3321 * 3322 * Find all clients that are gone and have terminated in RetainTemporary 3323 * and destroy their resources. 3324 *********************/ 3325 3326 static void 3327 CloseDownRetainedResources(void) 3328 { 3329 int i; 3330 ClientPtr client; 3331 3332 for (i = 1; i < currentMaxClients; i++) { 3333 client = clients[i]; 3334 if (client && (client->closeDownMode == RetainTemporary) 3335 && (client->clientGone)) 3336 CloseDownClient(client); 3337 } 3338 } 3339 3340 int 3341 ProcKillClient(ClientPtr client) 3342 { 3343 REQUEST(xResourceReq); 3344 ClientPtr killclient; 3345 int rc; 3346 3347 REQUEST_SIZE_MATCH(xResourceReq); 3348 if (stuff->id == AllTemporary) { 3349 CloseDownRetainedResources(); 3350 return Success; 3351 } 3352 3353 rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess); 3354 if (rc == Success) { 3355 CloseDownClient(killclient); 3356 if (client == killclient) { 3357 /* force yield and return Success, so that Dispatch() 3358 * doesn't try to touch client 3359 */ 3360 isItTimeToYield = TRUE; 3361 } 3362 return Success; 3363 } 3364 else 3365 return rc; 3366 } 3367 3368 int 3369 ProcSetFontPath(ClientPtr client) 3370 { 3371 unsigned char *ptr; 3372 unsigned long nbytes, total; 3373 long nfonts; 3374 int n; 3375 3376 REQUEST(xSetFontPathReq); 3377 3378 REQUEST_AT_LEAST_SIZE(xSetFontPathReq); 3379 3380 nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); 3381 total = nbytes; 3382 ptr = (unsigned char *) &stuff[1]; 3383 nfonts = stuff->nFonts; 3384 while (--nfonts >= 0) { 3385 if ((total == 0) || (total < (n = (*ptr + 1)))) 3386 return BadLength; 3387 total -= n; 3388 ptr += n; 3389 } 3390 if (total >= 4) 3391 return BadLength; 3392 return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]); 3393 } 3394 3395 int 3396 ProcGetFontPath(ClientPtr client) 3397 { 3398 xGetFontPathReply reply; 3399 int rc, stringLens, numpaths; 3400 unsigned char *bufferStart; 3401 3402 /* REQUEST (xReq); */ 3403 3404 REQUEST_SIZE_MATCH(xReq); 3405 rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart); 3406 if (rc != Success) 3407 return rc; 3408 3409 reply = (xGetFontPathReply) { 3410 .type = X_Reply, 3411 .sequenceNumber = client->sequence, 3412 .length = bytes_to_int32(stringLens + numpaths), 3413 .nPaths = numpaths 3414 }; 3415 3416 WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); 3417 if (stringLens || numpaths) 3418 WriteToClient(client, stringLens + numpaths, bufferStart); 3419 return Success; 3420 } 3421 3422 int 3423 ProcChangeCloseDownMode(ClientPtr client) 3424 { 3425 int rc; 3426 3427 REQUEST(xSetCloseDownModeReq); 3428 REQUEST_SIZE_MATCH(xSetCloseDownModeReq); 3429 3430 rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess); 3431 if (rc != Success) 3432 return rc; 3433 3434 if ((stuff->mode == AllTemporary) || 3435 (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) { 3436 client->closeDownMode = stuff->mode; 3437 return Success; 3438 } 3439 else { 3440 client->errorValue = stuff->mode; 3441 return BadValue; 3442 } 3443 } 3444 3445 int 3446 ProcForceScreenSaver(ClientPtr client) 3447 { 3448 int rc; 3449 3450 REQUEST(xForceScreenSaverReq); 3451 3452 REQUEST_SIZE_MATCH(xForceScreenSaverReq); 3453 3454 if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) { 3455 client->errorValue = stuff->mode; 3456 return BadValue; 3457 } 3458 rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode); 3459 if (rc != Success) 3460 return rc; 3461 return Success; 3462 } 3463 3464 int 3465 ProcNoOperation(ClientPtr client) 3466 { 3467 REQUEST_AT_LEAST_SIZE(xReq); 3468 3469 /* noop -- don't do anything */ 3470 return Success; 3471 } 3472 3473 /********************** 3474 * CloseDownClient 3475 * 3476 * Client can either mark his resources destroy or retain. If retained and 3477 * then killed again, the client is really destroyed. 3478 *********************/ 3479 3480 char dispatchExceptionAtReset = DE_RESET; 3481 int terminateDelay = 0; 3482 3483 void 3484 CloseDownClient(ClientPtr client) 3485 { 3486 Bool really_close_down = client->clientGone || 3487 client->closeDownMode == DestroyAll; 3488 3489 if (!client->clientGone) { 3490 /* ungrab server if grabbing client dies */ 3491 if (grabState != GrabNone && grabClient == client) { 3492 UngrabServer(client); 3493 } 3494 BITCLEAR(grabWaiters, client->index); 3495 DeleteClientFromAnySelections(client); 3496 ReleaseActiveGrabs(client); 3497 DeleteClientFontStuff(client); 3498 if (!really_close_down) { 3499 /* This frees resources that should never be retained 3500 * no matter what the close down mode is. Actually we 3501 * could do this unconditionally, but it's probably 3502 * better not to traverse all the client's resources 3503 * twice (once here, once a few lines down in 3504 * FreeClientResources) in the common case of 3505 * really_close_down == TRUE. 3506 */ 3507 FreeClientNeverRetainResources(client); 3508 client->clientState = ClientStateRetained; 3509 if (ClientStateCallback) { 3510 NewClientInfoRec clientinfo; 3511 3512 clientinfo.client = client; 3513 clientinfo.prefix = (xConnSetupPrefix *) NULL; 3514 clientinfo.setup = (xConnSetup *) NULL; 3515 CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3516 } 3517 } 3518 client->clientGone = TRUE; /* so events aren't sent to client */ 3519 if (ClientIsAsleep(client)) 3520 ClientSignal(client); 3521 ProcessWorkQueueZombies(); 3522 CloseDownConnection(client); 3523 output_pending_clear(client); 3524 mark_client_not_ready(client); 3525 3526 /* If the client made it to the Running stage, nClients has 3527 * been incremented on its behalf, so we need to decrement it 3528 * now. If it hasn't gotten to Running, nClients has *not* 3529 * been incremented, so *don't* decrement it. 3530 */ 3531 if (client->clientState != ClientStateInitial) { 3532 --nClients; 3533 } 3534 } 3535 3536 if (really_close_down) { 3537 if (client->clientState == ClientStateRunning && nClients == 0) 3538 SetDispatchExceptionTimer(); 3539 3540 client->clientState = ClientStateGone; 3541 if (ClientStateCallback) { 3542 NewClientInfoRec clientinfo; 3543 3544 clientinfo.client = client; 3545 clientinfo.prefix = (xConnSetupPrefix *) NULL; 3546 clientinfo.setup = (xConnSetup *) NULL; 3547 CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3548 } 3549 TouchListenerGone(client->clientAsMask); 3550 GestureListenerGone(client->clientAsMask); 3551 FreeClientResources(client); 3552 /* Disable client ID tracking. This must be done after 3553 * ClientStateCallback. */ 3554 ReleaseClientIds(client); 3555 #ifdef XSERVER_DTRACE 3556 XSERVER_CLIENT_DISCONNECT(client->index); 3557 #endif 3558 if (client->index < nextFreeClientID) 3559 nextFreeClientID = client->index; 3560 clients[client->index] = NullClient; 3561 SmartLastClient = NullClient; 3562 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 3563 3564 while (!clients[currentMaxClients - 1]) 3565 currentMaxClients--; 3566 } 3567 3568 if (ShouldDisconnectRemainingClients()) 3569 SetDispatchExceptionTimer(); 3570 } 3571 3572 static void 3573 KillAllClients(void) 3574 { 3575 int i; 3576 3577 for (i = 1; i < currentMaxClients; i++) 3578 if (clients[i]) { 3579 /* Make sure Retained clients are released. */ 3580 clients[i]->closeDownMode = DestroyAll; 3581 CloseDownClient(clients[i]); 3582 } 3583 } 3584 3585 void 3586 InitClient(ClientPtr client, int i, void *ospriv) 3587 { 3588 client->index = i; 3589 xorg_list_init(&client->ready); 3590 xorg_list_init(&client->output_pending); 3591 client->clientAsMask = ((Mask) i) << CLIENTOFFSET; 3592 client->closeDownMode = i ? DestroyAll : RetainPermanent; 3593 client->requestVector = InitialVector; 3594 client->osPrivate = ospriv; 3595 QueryMinMaxKeyCodes(&client->minKC, &client->maxKC); 3596 client->smart_start_tick = SmartScheduleTime; 3597 client->smart_stop_tick = SmartScheduleTime; 3598 client->clientIds = NULL; 3599 } 3600 3601 /************************ 3602 * int NextAvailableClient(ospriv) 3603 * 3604 * OS dependent portion can't assign client id's because of CloseDownModes. 3605 * Returns NULL if there are no free clients. 3606 *************************/ 3607 3608 ClientPtr 3609 NextAvailableClient(void *ospriv) 3610 { 3611 int i; 3612 ClientPtr client; 3613 xReq data; 3614 3615 i = nextFreeClientID; 3616 if (i == LimitClients) 3617 return (ClientPtr) NULL; 3618 clients[i] = client = 3619 dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT); 3620 if (!client) 3621 return (ClientPtr) NULL; 3622 InitClient(client, i, ospriv); 3623 if (!InitClientResources(client)) { 3624 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 3625 return (ClientPtr) NULL; 3626 } 3627 data.reqType = 1; 3628 data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix); 3629 if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) { 3630 FreeClientResources(client); 3631 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 3632 return (ClientPtr) NULL; 3633 } 3634 if (i == currentMaxClients) 3635 currentMaxClients++; 3636 while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID]) 3637 nextFreeClientID++; 3638 3639 /* Enable client ID tracking. This must be done before 3640 * ClientStateCallback. */ 3641 ReserveClientIds(client); 3642 3643 if (ClientStateCallback) { 3644 NewClientInfoRec clientinfo; 3645 3646 clientinfo.client = client; 3647 clientinfo.prefix = (xConnSetupPrefix *) NULL; 3648 clientinfo.setup = (xConnSetup *) NULL; 3649 CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3650 } 3651 return client; 3652 } 3653 3654 int 3655 ProcInitialConnection(ClientPtr client) 3656 { 3657 REQUEST(xReq); 3658 xConnClientPrefix *prefix; 3659 int whichbyte = 1; 3660 char order; 3661 3662 prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq); 3663 order = prefix->byteOrder; 3664 if (order != 'l' && order != 'B' && order != 'r' && order != 'R') 3665 return client->noClientException = -1; 3666 if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || 3667 (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { 3668 client->swapped = TRUE; 3669 SwapConnClientPrefix(prefix); 3670 } 3671 stuff->reqType = 2; 3672 stuff->length += bytes_to_int32(prefix->nbytesAuthProto) + 3673 bytes_to_int32(prefix->nbytesAuthString); 3674 if (client->swapped) { 3675 swaps(&stuff->length); 3676 } 3677 if (order == 'r' || order == 'R') { 3678 client->local = FALSE; 3679 } 3680 ResetCurrentRequest(client); 3681 return Success; 3682 } 3683 3684 static int 3685 SendConnSetup(ClientPtr client, const char *reason) 3686 { 3687 xWindowRoot *root; 3688 int i; 3689 int numScreens; 3690 char *lConnectionInfo; 3691 xConnSetupPrefix *lconnSetupPrefix; 3692 3693 if (reason) { 3694 xConnSetupPrefix csp; 3695 3696 csp.success = xFalse; 3697 csp.lengthReason = strlen(reason); 3698 csp.length = bytes_to_int32(csp.lengthReason); 3699 csp.majorVersion = X_PROTOCOL; 3700 csp.minorVersion = X_PROTOCOL_REVISION; 3701 if (client->swapped) 3702 WriteSConnSetupPrefix(client, &csp); 3703 else 3704 WriteToClient(client, sz_xConnSetupPrefix, &csp); 3705 WriteToClient(client, (int) csp.lengthReason, reason); 3706 return client->noClientException = -1; 3707 } 3708 3709 numScreens = screenInfo.numScreens; 3710 lConnectionInfo = ConnectionInfo; 3711 lconnSetupPrefix = &connSetupPrefix; 3712 3713 /* We're about to start speaking X protocol back to the client by 3714 * sending the connection setup info. This means the authorization 3715 * step is complete, and we can count the client as an 3716 * authorized one. 3717 */ 3718 nClients++; 3719 3720 client->requestVector = client->swapped ? SwappedProcVector : ProcVector; 3721 client->sequence = 0; 3722 ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask; 3723 ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK; 3724 #ifdef MATCH_CLIENT_ENDIAN 3725 ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client); 3726 ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client); 3727 #endif 3728 /* fill in the "currentInputMask" */ 3729 root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart); 3730 #ifdef PANORAMIX 3731 if (noPanoramiXExtension) 3732 numScreens = screenInfo.numScreens; 3733 else 3734 numScreens = ((xConnSetup *) ConnectionInfo)->numRoots; 3735 #endif 3736 3737 for (i = 0; i < numScreens; i++) { 3738 unsigned int j; 3739 xDepth *pDepth; 3740 WindowPtr pRoot = screenInfo.screens[i]->root; 3741 3742 root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot); 3743 pDepth = (xDepth *) (root + 1); 3744 for (j = 0; j < root->nDepths; j++) { 3745 pDepth = (xDepth *) (((char *) (pDepth + 1)) + 3746 pDepth->nVisuals * sizeof(xVisualType)); 3747 } 3748 root = (xWindowRoot *) pDepth; 3749 } 3750 3751 if (client->swapped) { 3752 WriteSConnSetupPrefix(client, lconnSetupPrefix); 3753 WriteSConnectionInfo(client, 3754 (unsigned long) (lconnSetupPrefix->length << 2), 3755 lConnectionInfo); 3756 } 3757 else { 3758 WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix); 3759 WriteToClient(client, (int) (lconnSetupPrefix->length << 2), 3760 lConnectionInfo); 3761 } 3762 client->clientState = ClientStateRunning; 3763 if (ClientStateCallback) { 3764 NewClientInfoRec clientinfo; 3765 3766 clientinfo.client = client; 3767 clientinfo.prefix = lconnSetupPrefix; 3768 clientinfo.setup = (xConnSetup *) lConnectionInfo; 3769 CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3770 } 3771 CancelDispatchExceptionTimer(); 3772 return Success; 3773 } 3774 3775 int 3776 ProcEstablishConnection(ClientPtr client) 3777 { 3778 const char *reason; 3779 char *auth_proto, *auth_string; 3780 xConnClientPrefix *prefix; 3781 3782 REQUEST(xReq); 3783 3784 prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq); 3785 auth_proto = (char *) prefix + sz_xConnClientPrefix; 3786 auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto); 3787 3788 if (client->swapped && !AllowByteSwappedClients) { 3789 reason = "Prohibited client endianess, see the Xserver man page "; 3790 } else if ((client->req_len << 2) != sz_xReq + sz_xConnClientPrefix + 3791 pad_to_int32(prefix->nbytesAuthProto) + 3792 pad_to_int32(prefix->nbytesAuthString)) 3793 reason = "Bad length"; 3794 else if ((prefix->majorVersion != X_PROTOCOL) || 3795 (prefix->minorVersion != X_PROTOCOL_REVISION)) 3796 reason = "Protocol version mismatch"; 3797 else 3798 reason = ClientAuthorized(client, 3799 (unsigned short) prefix->nbytesAuthProto, 3800 auth_proto, 3801 (unsigned short) prefix->nbytesAuthString, 3802 auth_string); 3803 3804 return (SendConnSetup(client, reason)); 3805 } 3806 3807 void 3808 SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, 3809 XID resId, int errorCode) 3810 { 3811 xError rep = { 3812 .type = X_Error, 3813 .errorCode = errorCode, 3814 .resourceID = resId, 3815 .minorCode = minorCode, 3816 .majorCode = majorCode 3817 }; 3818 3819 WriteEventsToClient(client, 1, (xEvent *) &rep); 3820 } 3821 3822 void 3823 MarkClientException(ClientPtr client) 3824 { 3825 client->noClientException = -1; 3826 } 3827 3828 /* 3829 * This array encodes the answer to the question "what is the log base 2 3830 * of the number of pixels that fit in a scanline pad unit?" 3831 * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 3832 */ 3833 static int answer[6][4] = { 3834 /* pad pad pad pad */ 3835 /* 8 16 32 64 */ 3836 3837 {3, 4, 5, 6}, /* 1 bit per pixel */ 3838 {1, 2, 3, 4}, /* 4 bits per pixel */ 3839 {0, 1, 2, 3}, /* 8 bits per pixel */ 3840 {~0, 0, 1, 2}, /* 16 bits per pixel */ 3841 {~0, ~0, 0, 1}, /* 24 bits per pixel */ 3842 {~0, ~0, 0, 1} /* 32 bits per pixel */ 3843 }; 3844 3845 /* 3846 * This array gives the answer to the question "what is the first index for 3847 * the answer array above given the number of bits per pixel?" 3848 * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 3849 */ 3850 static int indexForBitsPerPixel[33] = { 3851 ~0, 0, ~0, ~0, /* 1 bit per pixel */ 3852 1, ~0, ~0, ~0, /* 4 bits per pixel */ 3853 2, ~0, ~0, ~0, /* 8 bits per pixel */ 3854 ~0, ~0, ~0, ~0, 3855 3, ~0, ~0, ~0, /* 16 bits per pixel */ 3856 ~0, ~0, ~0, ~0, 3857 4, ~0, ~0, ~0, /* 24 bits per pixel */ 3858 ~0, ~0, ~0, ~0, 3859 5 /* 32 bits per pixel */ 3860 }; 3861 3862 /* 3863 * This array gives the bytesperPixel value for cases where the number 3864 * of bits per pixel is a multiple of 8 but not a power of 2. 3865 */ 3866 static int answerBytesPerPixel[33] = { 3867 ~0, 0, ~0, ~0, /* 1 bit per pixel */ 3868 0, ~0, ~0, ~0, /* 4 bits per pixel */ 3869 0, ~0, ~0, ~0, /* 8 bits per pixel */ 3870 ~0, ~0, ~0, ~0, 3871 0, ~0, ~0, ~0, /* 16 bits per pixel */ 3872 ~0, ~0, ~0, ~0, 3873 3, ~0, ~0, ~0, /* 24 bits per pixel */ 3874 ~0, ~0, ~0, ~0, 3875 0 /* 32 bits per pixel */ 3876 }; 3877 3878 /* 3879 * This array gives the answer to the question "what is the second index for 3880 * the answer array above given the number of bits per scanline pad unit?" 3881 * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 3882 */ 3883 static int indexForScanlinePad[65] = { 3884 ~0, ~0, ~0, ~0, 3885 ~0, ~0, ~0, ~0, 3886 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */ 3887 ~0, ~0, ~0, ~0, 3888 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */ 3889 ~0, ~0, ~0, ~0, 3890 ~0, ~0, ~0, ~0, 3891 ~0, ~0, ~0, ~0, 3892 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */ 3893 ~0, ~0, ~0, ~0, 3894 ~0, ~0, ~0, ~0, 3895 ~0, ~0, ~0, ~0, 3896 ~0, ~0, ~0, ~0, 3897 ~0, ~0, ~0, ~0, 3898 ~0, ~0, ~0, ~0, 3899 ~0, ~0, ~0, ~0, 3900 3 /* 64 bits per scanline pad unit */ 3901 }; 3902 3903 /* 3904 grow the array of screenRecs if necessary. 3905 call the device-supplied initialization procedure 3906 with its screen number, a pointer to its ScreenRec, argc, and argv. 3907 return the number of successfully installed screens. 3908 3909 */ 3910 3911 static int init_screen(ScreenPtr pScreen, int i, Bool gpu) 3912 { 3913 int scanlinepad, format, depth, bitsPerPixel, j, k; 3914 3915 dixInitScreenSpecificPrivates(pScreen); 3916 3917 if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) { 3918 return -1; 3919 } 3920 pScreen->myNum = i; 3921 if (gpu) { 3922 pScreen->myNum += GPU_SCREEN_OFFSET; 3923 pScreen->isGPU = TRUE; 3924 } 3925 pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */ 3926 pScreen->ClipNotify = 0; /* for R4 ddx compatibility */ 3927 pScreen->CreateScreenResources = 0; 3928 3929 xorg_list_init(&pScreen->pixmap_dirty_list); 3930 xorg_list_init(&pScreen->secondary_list); 3931 3932 /* 3933 * This loop gets run once for every Screen that gets added, 3934 * but that's ok. If the ddx layer initializes the formats 3935 * one at a time calling AddScreen() after each, then each 3936 * iteration will make it a little more accurate. Worst case 3937 * we do this loop N * numPixmapFormats where N is # of screens. 3938 * Anyway, this must be called after InitOutput and before the 3939 * screen init routine is called. 3940 */ 3941 for (format = 0; format < screenInfo.numPixmapFormats; format++) { 3942 depth = screenInfo.formats[format].depth; 3943 bitsPerPixel = screenInfo.formats[format].bitsPerPixel; 3944 scanlinepad = screenInfo.formats[format].scanlinePad; 3945 j = indexForBitsPerPixel[bitsPerPixel]; 3946 k = indexForScanlinePad[scanlinepad]; 3947 PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k]; 3948 PixmapWidthPaddingInfo[depth].padRoundUp = 3949 (scanlinepad / bitsPerPixel) - 1; 3950 j = indexForBitsPerPixel[8]; /* bits per byte */ 3951 PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k]; 3952 PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel; 3953 if (answerBytesPerPixel[bitsPerPixel]) { 3954 PixmapWidthPaddingInfo[depth].notPower2 = 1; 3955 PixmapWidthPaddingInfo[depth].bytesPerPixel = 3956 answerBytesPerPixel[bitsPerPixel]; 3957 } 3958 else { 3959 PixmapWidthPaddingInfo[depth].notPower2 = 0; 3960 } 3961 } 3962 return 0; 3963 } 3964 3965 int 3966 AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , 3967 int /*argc */ , 3968 char ** /*argv */ 3969 ), int argc, char **argv) 3970 { 3971 3972 int i; 3973 ScreenPtr pScreen; 3974 Bool ret; 3975 3976 i = screenInfo.numScreens; 3977 if (i == MAXSCREENS) 3978 return -1; 3979 3980 pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); 3981 if (!pScreen) 3982 return -1; 3983 3984 ret = init_screen(pScreen, i, FALSE); 3985 if (ret != 0) { 3986 free(pScreen); 3987 return ret; 3988 } 3989 /* This is where screen specific stuff gets initialized. Load the 3990 screen structure, call the hardware, whatever. 3991 This is also where the default colormap should be allocated and 3992 also pixel values for blackPixel, whitePixel, and the cursor 3993 Note that InitScreen is NOT allowed to modify argc, argv, or 3994 any of the strings pointed to by argv. They may be passed to 3995 multiple screens. 3996 */ 3997 screenInfo.screens[i] = pScreen; 3998 screenInfo.numScreens++; 3999 if (!(*pfnInit) (pScreen, argc, argv)) { 4000 dixFreeScreenSpecificPrivates(pScreen); 4001 dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); 4002 free(pScreen); 4003 screenInfo.numScreens--; 4004 return -1; 4005 } 4006 4007 update_desktop_dimensions(); 4008 4009 dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR, 4010 0); 4011 4012 return i; 4013 } 4014 4015 int 4016 AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , 4017 int /*argc */ , 4018 char ** /*argv */ 4019 ), 4020 int argc, char **argv) 4021 { 4022 int i; 4023 ScreenPtr pScreen; 4024 Bool ret; 4025 4026 i = screenInfo.numGPUScreens; 4027 if (i == MAXGPUSCREENS) 4028 return -1; 4029 4030 pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); 4031 if (!pScreen) 4032 return -1; 4033 4034 ret = init_screen(pScreen, i, TRUE); 4035 if (ret != 0) { 4036 free(pScreen); 4037 return ret; 4038 } 4039 4040 /* This is where screen specific stuff gets initialized. Load the 4041 screen structure, call the hardware, whatever. 4042 This is also where the default colormap should be allocated and 4043 also pixel values for blackPixel, whitePixel, and the cursor 4044 Note that InitScreen is NOT allowed to modify argc, argv, or 4045 any of the strings pointed to by argv. They may be passed to 4046 multiple screens. 4047 */ 4048 screenInfo.gpuscreens[i] = pScreen; 4049 screenInfo.numGPUScreens++; 4050 if (!(*pfnInit) (pScreen, argc, argv)) { 4051 dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); 4052 free(pScreen); 4053 screenInfo.numGPUScreens--; 4054 return -1; 4055 } 4056 4057 update_desktop_dimensions(); 4058 4059 /* 4060 * We cannot register the Screen PRIVATE_CURSOR key if cursors are already 4061 * created, because dix/privates.c does not have relocation code for 4062 * PRIVATE_CURSOR. Once this is fixed the if() can be removed and we can 4063 * register the Screen PRIVATE_CURSOR key unconditionally. 4064 */ 4065 if (!dixPrivatesCreated(PRIVATE_CURSOR)) 4066 dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, 4067 PRIVATE_CURSOR, 0); 4068 4069 return i; 4070 } 4071 4072 void 4073 RemoveGPUScreen(ScreenPtr pScreen) 4074 { 4075 int idx, j; 4076 if (!pScreen->isGPU) 4077 return; 4078 4079 idx = pScreen->myNum - GPU_SCREEN_OFFSET; 4080 for (j = idx; j < screenInfo.numGPUScreens - 1; j++) { 4081 screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1]; 4082 screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET; 4083 } 4084 screenInfo.numGPUScreens--; 4085 4086 /* this gets freed later in the resource list, but without 4087 * the screen existing it causes crashes - so remove it here */ 4088 if (pScreen->defColormap) 4089 FreeResource(pScreen->defColormap, RT_COLORMAP); 4090 free(pScreen); 4091 4092 } 4093 4094 void 4095 AttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new) 4096 { 4097 assert(new->isGPU); 4098 assert(!new->current_primary); 4099 xorg_list_add(&new->secondary_head, &pScreen->secondary_list); 4100 new->current_primary = pScreen; 4101 } 4102 4103 void 4104 DetachUnboundGPU(ScreenPtr secondary) 4105 { 4106 assert(secondary->isGPU); 4107 assert(!secondary->is_output_secondary); 4108 assert(!secondary->is_offload_secondary); 4109 xorg_list_del(&secondary->secondary_head); 4110 secondary->current_primary = NULL; 4111 } 4112 4113 void 4114 AttachOutputGPU(ScreenPtr pScreen, ScreenPtr new) 4115 { 4116 assert(new->isGPU); 4117 assert(!new->is_output_secondary); 4118 assert(new->current_primary == pScreen); 4119 new->is_output_secondary = TRUE; 4120 new->current_primary->output_secondarys++; 4121 } 4122 4123 void 4124 DetachOutputGPU(ScreenPtr secondary) 4125 { 4126 assert(secondary->isGPU); 4127 assert(secondary->is_output_secondary); 4128 secondary->current_primary->output_secondarys--; 4129 secondary->is_output_secondary = FALSE; 4130 } 4131 4132 void 4133 AttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new) 4134 { 4135 assert(new->isGPU); 4136 assert(!new->is_offload_secondary); 4137 assert(new->current_primary == pScreen); 4138 new->is_offload_secondary = TRUE; 4139 } 4140 4141 void 4142 DetachOffloadGPU(ScreenPtr secondary) 4143 { 4144 assert(secondary->isGPU); 4145 assert(secondary->is_offload_secondary); 4146 secondary->is_offload_secondary = FALSE; 4147 } 4148 4149