1/* 2 * Copyright 2006 by VMware, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the copyright holder(s) 23 * and author(s) shall not be used in advertising or otherwise to promote 24 * the sale, use or other dealings in this Software without prior written 25 * authorization from the copyright holder(s) and author(s). 26 */ 27 28/* 29 * vmwarexinerama.c -- 30 * 31 * The implementation of the Xinerama protocol extension. 32 */ 33 34 35#ifdef HAVE_CONFIG_H 36#include "config.h" 37#endif 38 39#include "dixstruct.h" 40#include "extnsionst.h" 41#include <X11/X.h> 42#include <X11/extensions/panoramiXproto.h> 43 44#include "vmware.h" 45 46#ifndef HAVE_XORG_SERVER_1_5_0 47#include <xf86_ansic.h> 48#include <xf86_libc.h> 49#endif 50 51/* 52 * LookupWindow was removed with video abi 11. 53 */ 54#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 4) 55#ifndef DixGetAttrAccess 56#define DixGetAttrAccess (1<<4) 57#endif 58#endif 59 60#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 2) 61static inline int 62dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access) 63{ 64 *pWin = LookupWindow(id, client); 65 if (!*pWin) 66 return BadWindow; 67 return Success; 68} 69#endif 70 71 72/* 73 *---------------------------------------------------------------------------- 74 * 75 * VMwareXineramaQueryVersion -- 76 * 77 * Implementation of QueryVersion command handler. Initialises and 78 * sends a reply. 79 * 80 * Results: 81 * Standard response codes. 82 * 83 * Side effects: 84 * Writes reply to client. 85 * 86 *---------------------------------------------------------------------------- 87 */ 88 89static int 90VMwareXineramaQueryVersion(ClientPtr client) 91{ 92 xPanoramiXQueryVersionReply rep; 93 register int n; 94 95 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); 96 rep.type = X_Reply; 97 rep.length = 0; 98 rep.sequenceNumber = client->sequence; 99 rep.majorVersion = 1; 100 rep.minorVersion = 0; 101 if(client->swapped) { 102 _swaps(&rep.sequenceNumber, n); 103 _swapl(&rep.length, n); 104 _swaps(&rep.majorVersion, n); 105 _swaps(&rep.minorVersion, n); 106 } 107 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 108 return (client->noClientException); 109} 110 111 112/* 113 *---------------------------------------------------------------------------- 114 * 115 * VMwareXineramaGetState -- 116 * 117 * Implementation of GetState command handler. Initialises and 118 * sends a reply. 119 * 120 * Results: 121 * Standard response codes. 122 * 123 * Side effects: 124 * Writes reply to client. 125 * 126 *---------------------------------------------------------------------------- 127 */ 128 129static int 130VMwareXineramaGetState(ClientPtr client) 131{ 132 REQUEST(xPanoramiXGetStateReq); 133 WindowPtr pWin; 134 xPanoramiXGetStateReply rep; 135 register int n; 136 ExtensionEntry *ext; 137 ScrnInfoPtr pScrn; 138 VMWAREPtr pVMWARE; 139 int rc; 140 141 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 142 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 143 if (rc != Success) 144 return rc; 145 146 if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { 147 return BadMatch; 148 } 149 pScrn = ext->extPrivate; 150 pVMWARE = VMWAREPTR(pScrn); 151 152 rep.type = X_Reply; 153 rep.length = 0; 154 rep.sequenceNumber = client->sequence; 155 rep.state = pVMWARE->xinerama; 156 rep.window = stuff->window; 157 if(client->swapped) { 158 _swaps (&rep.sequenceNumber, n); 159 _swapl (&rep.length, n); 160 _swapl (&rep.window, n); 161 } 162 WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 163 return client->noClientException; 164} 165 166 167/* 168 *---------------------------------------------------------------------------- 169 * 170 * VMwareXineramaGetScreenCount -- 171 * 172 * Implementation of GetScreenCount command handler. Initialises and 173 * sends a reply. 174 * 175 * Results: 176 * Standard response codes. 177 * 178 * Side effects: 179 * Writes reply to client. 180 * 181 *---------------------------------------------------------------------------- 182 */ 183 184static int 185VMwareXineramaGetScreenCount(ClientPtr client) 186{ 187 REQUEST(xPanoramiXGetScreenCountReq); 188 WindowPtr pWin; 189 xPanoramiXGetScreenCountReply rep; 190 register int n; 191 ExtensionEntry *ext; 192 ScrnInfoPtr pScrn; 193 VMWAREPtr pVMWARE; 194 int rc; 195 196 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 197 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 198 if (rc != Success) 199 return rc; 200 201 if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { 202 return BadMatch; 203 } 204 pScrn = ext->extPrivate; 205 pVMWARE = VMWAREPTR(pScrn); 206 207 rep.type = X_Reply; 208 rep.length = 0; 209 rep.sequenceNumber = client->sequence; 210 rep.ScreenCount = pVMWARE->xineramaNumOutputs; 211 rep.window = stuff->window; 212 213 if(client->swapped) { 214 _swaps(&rep.sequenceNumber, n); 215 _swapl(&rep.length, n); 216 _swapl(&rep.window, n); 217 } 218 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 219 return client->noClientException; 220} 221 222 223/* 224 *---------------------------------------------------------------------------- 225 * 226 * VMwareXineramaGetScreenSize -- 227 * 228 * Implementation of GetScreenSize command handler. Initialises and 229 * sends a reply. 230 * 231 * Results: 232 * Standard response codes. 233 * 234 * Side effects: 235 * Writes reply to client. 236 * 237 *---------------------------------------------------------------------------- 238 */ 239 240static int 241VMwareXineramaGetScreenSize(ClientPtr client) 242{ 243 REQUEST(xPanoramiXGetScreenSizeReq); 244 WindowPtr pWin; 245 xPanoramiXGetScreenSizeReply rep; 246 register int n; 247 ExtensionEntry *ext; 248 ScrnInfoPtr pScrn; 249 VMWAREPtr pVMWARE; 250 int rc; 251 252 253 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 254 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 255 if (rc != Success) 256 return rc; 257 258 if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { 259 return BadMatch; 260 } 261 pScrn = ext->extPrivate; 262 pVMWARE = VMWAREPTR(pScrn); 263 264 rep.type = X_Reply; 265 rep.length = 0; 266 rep.sequenceNumber = client->sequence; 267 rep.width = pVMWARE->xineramaState[stuff->screen].width; 268 rep.height = pVMWARE->xineramaState[stuff->screen].height; 269 rep.window = stuff->window; 270 rep.screen = stuff->screen; 271 if(client->swapped) { 272 _swaps(&rep.sequenceNumber, n); 273 _swapl(&rep.length, n); 274 _swapl(&rep.width, n); 275 _swapl(&rep.height, n); 276 _swapl(&rep.window, n); 277 _swapl(&rep.screen, n); 278 } 279 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 280 return client->noClientException; 281} 282 283 284/* 285 *---------------------------------------------------------------------------- 286 * 287 * VMwareXineramaIsActive -- 288 * 289 * Implementation of IsActive command handler. Initialises and 290 * sends a reply. 291 * 292 * Results: 293 * Standard response codes. 294 * 295 * Side effects: 296 * Writes reply to client. 297 * 298 *---------------------------------------------------------------------------- 299 */ 300 301static int 302VMwareXineramaIsActive(ClientPtr client) 303{ 304 xXineramaIsActiveReply rep; 305 ExtensionEntry *ext; 306 ScrnInfoPtr pScrn; 307 VMWAREPtr pVMWARE; 308 309 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 310 311 if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { 312 return BadMatch; 313 } 314 pScrn = ext->extPrivate; 315 pVMWARE = VMWAREPTR(pScrn); 316 317 rep.type = X_Reply; 318 rep.length = 0; 319 rep.sequenceNumber = client->sequence; 320 rep.state = pVMWARE->xinerama; 321 if(client->swapped) { 322 register int n; 323 _swaps(&rep.sequenceNumber, n); 324 _swapl(&rep.length, n); 325 _swapl(&rep.state, n); 326 } 327 WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 328 return client->noClientException; 329} 330 331 332/* 333 *---------------------------------------------------------------------------- 334 * 335 * VMwareXineramaQueryScreens -- 336 * 337 * Implementation of QueryScreens command handler. Initialises and 338 * sends a reply. 339 * 340 * Results: 341 * Standard response codes. 342 * 343 * Side effects: 344 * Writes reply to client. 345 * 346 *---------------------------------------------------------------------------- 347 */ 348 349static int 350VMwareXineramaQueryScreens(ClientPtr client) 351{ 352 xXineramaQueryScreensReply rep; 353 ExtensionEntry *ext; 354 ScrnInfoPtr pScrn; 355 VMWAREPtr pVMWARE; 356 357 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 358 359 if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { 360 return BadMatch; 361 } 362 pScrn = ext->extPrivate; 363 pVMWARE = VMWAREPTR(pScrn); 364 365 rep.type = X_Reply; 366 rep.sequenceNumber = client->sequence; 367 rep.number = pVMWARE->xinerama ? pVMWARE->xineramaNumOutputs : 0; 368 rep.length = rep.number * sz_XineramaScreenInfo >> 2; 369 if(client->swapped) { 370 register int n; 371 _swaps(&rep.sequenceNumber, n); 372 _swapl(&rep.length, n); 373 _swapl(&rep.number, n); 374 } 375 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 376 377 if(pVMWARE->xinerama) { 378 xXineramaScreenInfo scratch; 379 int i; 380 381 for(i = 0; i < pVMWARE->xineramaNumOutputs; i++) { 382 scratch.x_org = pVMWARE->xineramaState[i].x_org; 383 scratch.y_org = pVMWARE->xineramaState[i].y_org; 384 scratch.width = pVMWARE->xineramaState[i].width; 385 scratch.height = pVMWARE->xineramaState[i].height; 386 if(client->swapped) { 387 register int n; 388 _swaps(&scratch.x_org, n); 389 _swaps(&scratch.y_org, n); 390 _swaps(&scratch.width, n); 391 _swaps(&scratch.height, n); 392 } 393 WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 394 } 395 } 396 397 return client->noClientException; 398} 399 400 401/* 402 *---------------------------------------------------------------------------- 403 * 404 * VMwareXineramaDispatch -- 405 * 406 * Dispatcher for Xinerama commands. Calls the correct handler for 407 * each command type. 408 * 409 * Results: 410 * Standard response codes. 411 * 412 * Side effects: 413 * Side effects of individual command handlers. 414 * 415 *---------------------------------------------------------------------------- 416 */ 417 418static int 419VMwareXineramaDispatch(ClientPtr client) 420{ 421 REQUEST(xReq); 422 switch (stuff->data) { 423 case X_PanoramiXQueryVersion: 424 return VMwareXineramaQueryVersion(client); 425 case X_PanoramiXGetState: 426 return VMwareXineramaGetState(client); 427 case X_PanoramiXGetScreenCount: 428 return VMwareXineramaGetScreenCount(client); 429 case X_PanoramiXGetScreenSize: 430 return VMwareXineramaGetScreenSize(client); 431 case X_XineramaIsActive: 432 return VMwareXineramaIsActive(client); 433 case X_XineramaQueryScreens: 434 return VMwareXineramaQueryScreens(client); 435 } 436 return BadRequest; 437} 438 439 440/* 441 *---------------------------------------------------------------------------- 442 * 443 * SVMwareXineramaQueryVersion -- 444 * 445 * Wrapper for QueryVersion handler that handles input from other-endian 446 * clients. 447 * 448 * Results: 449 * Standard response codes. 450 * 451 * Side effects: 452 * Side effects of unswapped implementation. 453 * 454 *---------------------------------------------------------------------------- 455 */ 456 457static int 458SVMwareXineramaQueryVersion (ClientPtr client) 459{ 460 REQUEST(xPanoramiXQueryVersionReq); 461 register int n; 462 _swaps(&stuff->length,n); 463 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 464 return VMwareXineramaQueryVersion(client); 465} 466 467 468/* 469 *---------------------------------------------------------------------------- 470 * 471 * SVMwareXineramaGetState -- 472 * 473 * Wrapper for GetState handler that handles input from other-endian 474 * clients. 475 * 476 * Results: 477 * Standard response codes. 478 * 479 * Side effects: 480 * Side effects of unswapped implementation. 481 * 482 *---------------------------------------------------------------------------- 483 */ 484 485static int 486SVMwareXineramaGetState(ClientPtr client) 487{ 488 REQUEST(xPanoramiXGetStateReq); 489 register int n; 490 _swaps (&stuff->length, n); 491 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 492 return VMwareXineramaGetState(client); 493} 494 495 496/* 497 *---------------------------------------------------------------------------- 498 * 499 * SVMwareXineramaGetScreenCount -- 500 * 501 * Wrapper for GetScreenCount handler that handles input from other-endian 502 * clients. 503 * 504 * Results: 505 * Standard response codes. 506 * 507 * Side effects: 508 * Side effects of unswapped implementation. 509 * 510 *---------------------------------------------------------------------------- 511 */ 512 513static int 514SVMwareXineramaGetScreenCount(ClientPtr client) 515{ 516 REQUEST(xPanoramiXGetScreenCountReq); 517 register int n; 518 _swaps (&stuff->length, n); 519 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 520 return VMwareXineramaGetScreenCount(client); 521} 522 523 524/* 525 *---------------------------------------------------------------------------- 526 * 527 * SVMwareXineramaGetScreenSize -- 528 * 529 * Wrapper for GetScreenSize handler that handles input from other-endian 530 * clients. 531 * 532 * Results: 533 * Standard response codes. 534 * 535 * Side effects: 536 * Side effects of unswapped implementation. 537 * 538 *---------------------------------------------------------------------------- 539 */ 540 541static int 542SVMwareXineramaGetScreenSize(ClientPtr client) 543{ 544 REQUEST(xPanoramiXGetScreenSizeReq); 545 register int n; 546 _swaps (&stuff->length, n); 547 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 548 return VMwareXineramaGetScreenSize(client); 549} 550 551 552/* 553 *---------------------------------------------------------------------------- 554 * 555 * SVMwareXineramaIsActive -- 556 * 557 * Wrapper for IsActive handler that handles input from other-endian 558 * clients. 559 * 560 * Results: 561 * Standard response codes. 562 * 563 * Side effects: 564 * Side effects of unswapped implementation. 565 * 566 *---------------------------------------------------------------------------- 567 */ 568 569static int 570SVMwareXineramaIsActive(ClientPtr client) 571{ 572 REQUEST(xXineramaIsActiveReq); 573 register int n; 574 _swaps (&stuff->length, n); 575 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 576 return VMwareXineramaIsActive(client); 577} 578 579 580/* 581 *---------------------------------------------------------------------------- 582 * 583 * SVMwareXineramaQueryScreens -- 584 * 585 * Wrapper for QueryScreens handler that handles input from other-endian 586 * clients. 587 * 588 * Results: 589 * Standard response codes. 590 * 591 * Side effects: 592 * Side effects of unswapped implementation. 593 * 594 *---------------------------------------------------------------------------- 595 */ 596 597static int 598SVMwareXineramaQueryScreens(ClientPtr client) 599{ 600 REQUEST(xXineramaQueryScreensReq); 601 register int n; 602 _swaps (&stuff->length, n); 603 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 604 return VMwareXineramaQueryScreens(client); 605} 606 607 608/* 609 *---------------------------------------------------------------------------- 610 * 611 * SVMwareXineramaDispatch -- 612 * 613 * Wrapper for dispatcher that handles input from other-endian clients. 614 * 615 * Results: 616 * Standard response codes. 617 * 618 * Side effects: 619 * Side effects of individual command handlers. 620 * 621 *---------------------------------------------------------------------------- 622 */ 623 624static int 625SVMwareXineramaDispatch(ClientPtr client) 626{ 627 REQUEST(xReq); 628 switch (stuff->data) { 629 case X_PanoramiXQueryVersion: 630 return SVMwareXineramaQueryVersion(client); 631 case X_PanoramiXGetState: 632 return SVMwareXineramaGetState(client); 633 case X_PanoramiXGetScreenCount: 634 return SVMwareXineramaGetScreenCount(client); 635 case X_PanoramiXGetScreenSize: 636 return SVMwareXineramaGetScreenSize(client); 637 case X_XineramaIsActive: 638 return SVMwareXineramaIsActive(client); 639 case X_XineramaQueryScreens: 640 return SVMwareXineramaQueryScreens(client); 641 } 642 return BadRequest; 643} 644 645 646/* 647 *---------------------------------------------------------------------------- 648 * 649 * VMwareXineramaResetProc -- 650 * 651 * Cleanup handler called when the extension is removed. 652 * 653 * Results: 654 * None 655 * 656 * Side effects: 657 * None 658 * 659 *---------------------------------------------------------------------------- 660 */ 661 662static void 663VMwareXineramaResetProc(ExtensionEntry* extEntry) 664{ 665 /* Called by CloseDownExtensions() */ 666 667 ScrnInfoPtr pScrn = extEntry->extPrivate; 668 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 669 670 if (pVMWARE->xineramaState) { 671 free(pVMWARE->xineramaState); 672 pVMWARE->xineramaState = NULL; 673 pVMWARE->xineramaNumOutputs = 0; 674 pVMWARE->xinerama = FALSE; 675 } 676} 677 678 679/* 680 *---------------------------------------------------------------------------- 681 * 682 * VMwareCtrl_ExitInit -- 683 * 684 * Initialiser for the Xinerama protocol extension. 685 * 686 * Results: 687 * None. 688 * 689 * Side effects: 690 * Protocol extension will be registered if successful. 691 * 692 *---------------------------------------------------------------------------- 693 */ 694 695void 696VMwareXinerama_ExtInit(ScrnInfoPtr pScrn) 697{ 698 ExtensionEntry *myext; 699 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 700 701#ifdef PANORAMIX 702 if(!noPanoramiXExtension) { 703 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 704 "Built-in Xinerama active, not initializing VMware Xinerama\n"); 705 pVMWARE->xinerama = FALSE; 706 return; 707 } 708#endif 709 710 if (!(myext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { 711 if (!(myext = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0, 712 VMwareXineramaDispatch, 713 SVMwareXineramaDispatch, 714 VMwareXineramaResetProc, 715 StandardMinorOpcode))) { 716 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 717 "Failed to add VMware Xinerama extension.\n"); 718 return; 719 } 720 721 pVMWARE->xinerama = TRUE; 722 723 myext->extPrivate = pScrn; 724 725 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 726 "Initialized VMware Xinerama extension.\n"); 727 } 728} 729