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