ephyr.c revision 6747b715
1/* 2 * Xephyr - A kdrive X server thats runs in a host X window. 3 * Authored by Matthew Allum <mallum@openedhand.com> 4 * 5 * Copyright � 2004 Nokia 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and its 8 * documentation for any purpose is hereby granted without fee, provided that 9 * the above copyright notice appear in all copies and that both that 10 * copyright notice and this permission notice appear in supporting 11 * documentation, and that the name of Nokia not be used in 12 * advertising or publicity pertaining to distribution of the software without 13 * specific, written prior permission. Nokia makes no 14 * representations about the suitability of this software for any purpose. It 15 * is provided "as is" without express or implied warranty. 16 * 17 * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23 * PERFORMANCE OF THIS SOFTWARE. 24 */ 25 26#ifdef HAVE_CONFIG_H 27#include <kdrive-config.h> 28#endif 29#include "ephyr.h" 30 31#include "inputstr.h" 32#include "scrnintstr.h" 33#include "ephyrlog.h" 34 35#ifdef XF86DRI 36#include "ephyrdri.h" 37#include "ephyrdriext.h" 38#include "ephyrglxext.h" 39#endif /* XF86DRI */ 40 41#include "xkbsrv.h" 42 43extern int KdTsPhyScreen; 44#ifdef GLXEXT 45extern Bool noGlxVisualInit; 46#endif 47 48KdKeyboardInfo *ephyrKbd; 49KdPointerInfo *ephyrMouse; 50EphyrKeySyms ephyrKeySyms; 51Bool ephyrNoDRI=FALSE ; 52Bool ephyrNoXV=FALSE ; 53 54static int mouseState = 0; 55 56typedef struct _EphyrInputPrivate { 57 Bool enabled; 58} EphyrKbdPrivate, EphyrPointerPrivate; 59 60Bool EphyrWantGrayScale = 0; 61 62 63Bool 64ephyrInitialize (KdCardInfo *card, EphyrPriv *priv) 65{ 66 OsSignal(SIGUSR1, hostx_handle_signal); 67 68 priv->base = 0; 69 priv->bytes_per_line = 0; 70 return TRUE; 71} 72 73Bool 74ephyrCardInit (KdCardInfo *card) 75{ 76 EphyrPriv *priv; 77 78 priv = (EphyrPriv *) malloc(sizeof (EphyrPriv)); 79 if (!priv) 80 return FALSE; 81 82 if (!ephyrInitialize (card, priv)) 83 { 84 free(priv); 85 return FALSE; 86 } 87 card->driver = priv; 88 89 return TRUE; 90} 91 92Bool 93ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv) 94{ 95 int width = 640, height = 480; 96 CARD32 redMask, greenMask, blueMask; 97 98 if (hostx_want_screen_size(screen, &width, &height) 99 || !screen->width || !screen->height) 100 { 101 screen->width = width; 102 screen->height = height; 103 } 104 105 if (EphyrWantGrayScale) 106 screen->fb.depth = 8; 107 108 if (screen->fb.depth && screen->fb.depth != hostx_get_depth()) 109 { 110 if (screen->fb.depth < hostx_get_depth() 111 && (screen->fb.depth == 24 || screen->fb.depth == 16 112 || screen->fb.depth == 8)) 113 { 114 hostx_set_server_depth(screen, screen->fb.depth); 115 } 116 else 117 ErrorF("\nXephyr: requested screen depth not supported, setting to match hosts.\n"); 118 } 119 120 screen->fb.depth = hostx_get_server_depth(screen); 121 screen->rate = 72; 122 123 if (screen->fb.depth <= 8) 124 { 125 if (EphyrWantGrayScale) 126 screen->fb.visuals = ((1 << StaticGray) | (1 << GrayScale)); 127 else 128 screen->fb.visuals = ((1 << StaticGray) | 129 (1 << GrayScale) | 130 (1 << StaticColor) | 131 (1 << PseudoColor) | 132 (1 << TrueColor) | 133 (1 << DirectColor)); 134 135 screen->fb.redMask = 0x00; 136 screen->fb.greenMask = 0x00; 137 screen->fb.blueMask = 0x00; 138 screen->fb.depth = 8; 139 screen->fb.bitsPerPixel = 8; 140 } 141 else 142 { 143 screen->fb.visuals = (1 << TrueColor); 144 145 if (screen->fb.depth <= 15) 146 { 147 screen->fb.depth = 15; 148 screen->fb.bitsPerPixel = 16; 149 } 150 else if (screen->fb.depth <= 16) 151 { 152 screen->fb.depth = 16; 153 screen->fb.bitsPerPixel = 16; 154 } 155 else if (screen->fb.depth <= 24) 156 { 157 screen->fb.depth = 24; 158 screen->fb.bitsPerPixel = 32; 159 } 160 else if (screen->fb.depth <= 30) 161 { 162 screen->fb.depth = 30; 163 screen->fb.bitsPerPixel = 32; 164 } 165 else 166 { 167 ErrorF("\nXephyr: Unsupported screen depth %d\n", 168 screen->fb.depth); 169 return FALSE; 170 } 171 172 hostx_get_visual_masks (screen, &redMask, &greenMask, &blueMask); 173 174 screen->fb.redMask = (Pixel) redMask; 175 screen->fb.greenMask = (Pixel) greenMask; 176 screen->fb.blueMask = (Pixel) blueMask; 177 178 } 179 180 scrpriv->randr = screen->randr; 181 182 return ephyrMapFramebuffer (screen); 183} 184 185Bool 186ephyrScreenInit (KdScreenInfo *screen) 187{ 188 EphyrScrPriv *scrpriv; 189 190 scrpriv = calloc(1, sizeof (EphyrScrPriv)); 191 192 if (!scrpriv) 193 return FALSE; 194 195 screen->driver = scrpriv; 196 197 if (!ephyrScreenInitialize (screen, scrpriv)) 198 { 199 screen->driver = 0; 200 free(scrpriv); 201 return FALSE; 202 } 203 204 return TRUE; 205} 206 207void* 208ephyrWindowLinear (ScreenPtr pScreen, 209 CARD32 row, 210 CARD32 offset, 211 int mode, 212 CARD32 *size, 213 void *closure) 214{ 215 KdScreenPriv(pScreen); 216 EphyrPriv *priv = pScreenPriv->card->driver; 217 218 if (!pScreenPriv->enabled) 219 return 0; 220 221 *size = priv->bytes_per_line; 222 return priv->base + row * priv->bytes_per_line + offset; 223} 224 225/** 226 * Figure out display buffer size. If fakexa is enabled, allocate a larger 227 * buffer so that fakexa has space to put offscreen pixmaps. 228 */ 229int 230ephyrBufferHeight(KdScreenInfo *screen) 231{ 232 int buffer_height; 233 if (ephyrFuncs.initAccel == NULL) 234 buffer_height = screen->height; 235 else 236 buffer_height = 3 * screen->height; 237 return buffer_height; 238} 239 240 241Bool 242ephyrMapFramebuffer (KdScreenInfo *screen) 243{ 244 EphyrScrPriv *scrpriv = screen->driver; 245 EphyrPriv *priv = screen->card->driver; 246 KdPointerMatrix m; 247 int buffer_height; 248 249 EPHYR_LOG("screen->width: %d, screen->height: %d index=%d", 250 screen->width, screen->height, screen->mynum); 251 252 KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); 253 KdSetPointerMatrix (&m); 254 255 priv->bytes_per_line = ((screen->width * screen->fb.bitsPerPixel + 31) >> 5) << 2; 256 257 buffer_height = ephyrBufferHeight(screen); 258 259 priv->base = hostx_screen_init (screen, screen->width, screen->height, buffer_height); 260 261 if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) 262 { 263 scrpriv->shadow = FALSE; 264 265 screen->fb.byteStride = priv->bytes_per_line; 266 screen->fb.pixelStride = screen->width; 267 screen->fb.frameBuffer = (CARD8 *) (priv->base); 268 } 269 else 270 { 271 /* Rotated/Reflected so we need to use shadow fb */ 272 scrpriv->shadow = TRUE; 273 274 EPHYR_LOG("allocing shadow"); 275 276 KdShadowFbAlloc (screen, 277 scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)); 278 } 279 280 return TRUE; 281} 282 283void 284ephyrSetScreenSizes (ScreenPtr pScreen) 285{ 286 KdScreenPriv(pScreen); 287 KdScreenInfo *screen = pScreenPriv->screen; 288 EphyrScrPriv *scrpriv = screen->driver; 289 290 if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) 291 { 292 pScreen->width = screen->width; 293 pScreen->height = screen->height; 294 pScreen->mmWidth = screen->width_mm; 295 pScreen->mmHeight = screen->height_mm; 296 } 297 else 298 { 299 pScreen->width = screen->height; 300 pScreen->height = screen->width; 301 pScreen->mmWidth = screen->height_mm; 302 pScreen->mmHeight = screen->width_mm; 303 } 304} 305 306Bool 307ephyrUnmapFramebuffer (KdScreenInfo *screen) 308{ 309 EphyrScrPriv *scrpriv = screen->driver; 310 311 if (scrpriv->shadow) 312 KdShadowFbFree (screen); 313 314 /* Note, priv->base will get freed when XImage recreated */ 315 316 return TRUE; 317} 318 319void 320ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) 321{ 322 KdScreenPriv(pScreen); 323 KdScreenInfo *screen = pScreenPriv->screen; 324 325 EPHYR_LOG("slow paint"); 326 327 /* FIXME: Slow Rotated/Reflected updates could be much 328 * much faster efficiently updating via tranforming 329 * pBuf->pDamage regions 330 */ 331 shadowUpdateRotatePacked(pScreen, pBuf); 332 hostx_paint_rect(screen, 0,0,0,0, screen->width, screen->height); 333} 334 335static void 336ephyrInternalDamageRedisplay (ScreenPtr pScreen) 337{ 338 KdScreenPriv(pScreen); 339 KdScreenInfo *screen = pScreenPriv->screen; 340 EphyrScrPriv *scrpriv = screen->driver; 341 RegionPtr pRegion; 342 343 if (!scrpriv || !scrpriv->pDamage) 344 return; 345 346 pRegion = DamageRegion (scrpriv->pDamage); 347 348 if (RegionNotEmpty(pRegion)) 349 { 350 int nbox; 351 BoxPtr pbox; 352 353 nbox = RegionNumRects (pRegion); 354 pbox = RegionRects (pRegion); 355 356 while (nbox--) 357 { 358 hostx_paint_rect(screen, 359 pbox->x1, pbox->y1, 360 pbox->x1, pbox->y1, 361 pbox->x2 - pbox->x1, 362 pbox->y2 - pbox->y1); 363 pbox++; 364 } 365 DamageEmpty (scrpriv->pDamage); 366 } 367} 368 369static void 370ephyrInternalDamageBlockHandler (pointer data, 371 OSTimePtr pTimeout, 372 pointer pRead) 373{ 374 ScreenPtr pScreen = (ScreenPtr) data; 375 376 ephyrInternalDamageRedisplay (pScreen); 377} 378 379static void 380ephyrInternalDamageWakeupHandler (pointer data, int i, pointer LastSelectMask) 381{ 382 /* FIXME: Not needed ? */ 383} 384 385Bool 386ephyrSetInternalDamage (ScreenPtr pScreen) 387{ 388 KdScreenPriv(pScreen); 389 KdScreenInfo *screen = pScreenPriv->screen; 390 EphyrScrPriv *scrpriv = screen->driver; 391 PixmapPtr pPixmap = NULL; 392 393 scrpriv->pDamage = DamageCreate ((DamageReportFunc) 0, 394 (DamageDestroyFunc) 0, 395 DamageReportNone, 396 TRUE, 397 pScreen, 398 pScreen); 399 400 if (!RegisterBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler, 401 ephyrInternalDamageWakeupHandler, 402 (pointer) pScreen)) 403 return FALSE; 404 405 pPixmap = (*pScreen->GetScreenPixmap) (pScreen); 406 407 DamageRegister (&pPixmap->drawable, scrpriv->pDamage); 408 409 return TRUE; 410} 411 412void 413ephyrUnsetInternalDamage (ScreenPtr pScreen) 414{ 415 KdScreenPriv(pScreen); 416 KdScreenInfo *screen = pScreenPriv->screen; 417 EphyrScrPriv *scrpriv = screen->driver; 418 PixmapPtr pPixmap = NULL; 419 420 pPixmap = (*pScreen->GetScreenPixmap) (pScreen); 421 DamageUnregister (&pPixmap->drawable, scrpriv->pDamage); 422 DamageDestroy (scrpriv->pDamage); 423 424 RemoveBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler, 425 ephyrInternalDamageWakeupHandler, 426 (pointer) pScreen); 427} 428 429#ifdef RANDR 430Bool 431ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) 432{ 433 KdScreenPriv(pScreen); 434 KdScreenInfo *screen = pScreenPriv->screen; 435 EphyrScrPriv *scrpriv = screen->driver; 436 RRScreenSizePtr pSize; 437 Rotation randr; 438 int n = 0; 439 440 struct { int width, height; } sizes[] = 441 { 442 { 1600, 1200 }, 443 { 1400, 1050 }, 444 { 1280, 960 }, 445 { 1280, 1024 }, 446 { 1152, 864 }, 447 { 1024, 768 }, 448 { 832, 624 }, 449 { 800, 600 }, 450 { 720, 400 }, 451 { 480, 640 }, 452 { 640, 480 }, 453 { 640, 400 }, 454 { 320, 240 }, 455 { 240, 320 }, 456 { 160, 160 }, 457 { 0, 0 } 458 }; 459 460 EPHYR_LOG("mark"); 461 462 *rotations = RR_Rotate_All|RR_Reflect_All; 463 464 if (!hostx_want_preexisting_window (screen) 465 && !hostx_want_fullscreen ()) /* only if no -parent switch */ 466 { 467 while (sizes[n].width != 0 && sizes[n].height != 0) 468 { 469 RRRegisterSize (pScreen, 470 sizes[n].width, 471 sizes[n].height, 472 (sizes[n].width * screen->width_mm)/screen->width, 473 (sizes[n].height *screen->height_mm)/screen->height 474 ); 475 n++; 476 } 477 } 478 479 pSize = RRRegisterSize (pScreen, 480 screen->width, 481 screen->height, 482 screen->width_mm, 483 screen->height_mm); 484 485 randr = KdSubRotation (scrpriv->randr, screen->randr); 486 487 RRSetCurrentConfig (pScreen, randr, 0, pSize); 488 489 return TRUE; 490} 491 492Bool 493ephyrRandRSetConfig (ScreenPtr pScreen, 494 Rotation randr, 495 int rate, 496 RRScreenSizePtr pSize) 497{ 498 KdScreenPriv(pScreen); 499 KdScreenInfo *screen = pScreenPriv->screen; 500 EphyrScrPriv *scrpriv = screen->driver; 501 Bool wasEnabled = pScreenPriv->enabled; 502 EphyrScrPriv oldscr; 503 int oldwidth, oldheight, oldmmwidth, oldmmheight; 504 Bool oldshadow; 505 int newwidth, newheight; 506 507 if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) 508 { 509 newwidth = pSize->width; 510 newheight = pSize->height; 511 } 512 else 513 { 514 newwidth = pSize->height; 515 newheight = pSize->width; 516 } 517 518 if (wasEnabled) 519 KdDisableScreen (pScreen); 520 521 oldscr = *scrpriv; 522 523 oldwidth = screen->width; 524 oldheight = screen->height; 525 oldmmwidth = pScreen->mmWidth; 526 oldmmheight = pScreen->mmHeight; 527 oldshadow = scrpriv->shadow; 528 529 /* 530 * Set new configuration 531 */ 532 533 scrpriv->randr = KdAddRotation (screen->randr, randr); 534 535 ephyrUnmapFramebuffer (screen); 536 537 screen->width = newwidth; 538 screen->height = newheight; 539 540 if (!ephyrMapFramebuffer (screen)) 541 goto bail4; 542 543 /* FIXME below should go in own call */ 544 545 if (oldshadow) 546 KdShadowUnset (screen->pScreen); 547 else 548 ephyrUnsetInternalDamage(screen->pScreen); 549 550 if (scrpriv->shadow) 551 { 552 if (!KdShadowSet (screen->pScreen, 553 scrpriv->randr, 554 ephyrShadowUpdate, 555 ephyrWindowLinear)) 556 goto bail4; 557 } 558 else 559 { 560 /* Without shadow fb ( non rotated ) we need 561 * to use damage to efficiently update display 562 * via signal regions what to copy from 'fb'. 563 */ 564 if (!ephyrSetInternalDamage(screen->pScreen)) 565 goto bail4; 566 } 567 568 ephyrSetScreenSizes (screen->pScreen); 569 570 /* 571 * Set frame buffer mapping 572 */ 573 (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), 574 pScreen->width, 575 pScreen->height, 576 screen->fb.depth, 577 screen->fb.bitsPerPixel, 578 screen->fb.byteStride, 579 screen->fb.frameBuffer); 580 581 /* set the subpixel order */ 582 583 KdSetSubpixelOrder (pScreen, scrpriv->randr); 584 585 if (wasEnabled) 586 KdEnableScreen (pScreen); 587 588 return TRUE; 589 590 bail4: 591 EPHYR_LOG("bailed"); 592 593 ephyrUnmapFramebuffer (screen); 594 *scrpriv = oldscr; 595 (void) ephyrMapFramebuffer (screen); 596 597 pScreen->width = oldwidth; 598 pScreen->height = oldheight; 599 pScreen->mmWidth = oldmmwidth; 600 pScreen->mmHeight = oldmmheight; 601 602 if (wasEnabled) 603 KdEnableScreen (pScreen); 604 return FALSE; 605} 606 607Bool 608ephyrRandRInit (ScreenPtr pScreen) 609{ 610 rrScrPrivPtr pScrPriv; 611 612 if (!RRScreenInit (pScreen)) 613 return FALSE; 614 615 pScrPriv = rrGetScrPriv(pScreen); 616 pScrPriv->rrGetInfo = ephyrRandRGetInfo; 617 pScrPriv->rrSetConfig = ephyrRandRSetConfig; 618 return TRUE; 619} 620#endif 621 622Bool 623ephyrCreateColormap (ColormapPtr pmap) 624{ 625 return fbInitializeColormap (pmap); 626} 627 628Bool 629ephyrInitScreen (ScreenPtr pScreen) 630{ 631 KdScreenPriv(pScreen); 632 KdScreenInfo *screen = pScreenPriv->screen; 633 634 EPHYR_LOG ("pScreen->myNum:%d\n", pScreen->myNum) ; 635 hostx_set_screen_number (screen, pScreen->myNum); 636 hostx_set_win_title (screen, "(ctrl+shift grabs mouse and keyboard)") ; 637 pScreen->CreateColormap = ephyrCreateColormap; 638 639#ifdef XV 640 if (!ephyrNoXV) { 641 if (!ephyrInitVideo (pScreen)) { 642 EPHYR_LOG_ERROR ("failed to initialize xvideo\n") ; 643 } else { 644 EPHYR_LOG ("initialized xvideo okay\n") ; 645 } 646 } 647#endif /*XV*/ 648 649#ifdef XF86DRI 650 if (!ephyrNoDRI && !hostx_has_dri ()) { 651 EPHYR_LOG ("host x does not support DRI. Disabling DRI forwarding\n") ; 652 ephyrNoDRI = TRUE ; 653#ifdef GLXEXT 654 noGlxVisualInit = FALSE ; 655#endif 656 } 657 if (!ephyrNoDRI) { 658 ephyrDRIExtensionInit (pScreen) ; 659 ephyrHijackGLXExtension () ; 660 } 661#endif 662 663#ifdef GLXEXT 664 if (ephyrNoDRI) { 665 noGlxVisualInit = FALSE ; 666 } 667#endif 668 669 return TRUE; 670} 671 672Bool 673ephyrFinishInitScreen (ScreenPtr pScreen) 674{ 675 /* FIXME: Calling this even if not using shadow. 676 * Seems harmless enough. But may be safer elsewhere. 677 */ 678 if (!shadowSetup (pScreen)) 679 return FALSE; 680 681#ifdef RANDR 682 if (!ephyrRandRInit (pScreen)) 683 return FALSE; 684#endif 685 686 return TRUE; 687} 688 689Bool 690ephyrCreateResources (ScreenPtr pScreen) 691{ 692 KdScreenPriv(pScreen); 693 KdScreenInfo *screen = pScreenPriv->screen; 694 EphyrScrPriv *scrpriv = screen->driver; 695 696 EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d", 697 pScreen, pScreen->myNum, scrpriv->shadow); 698 699 if (scrpriv->shadow) 700 return KdShadowSet (pScreen, 701 scrpriv->randr, 702 ephyrShadowUpdate, 703 ephyrWindowLinear); 704 else 705 return ephyrSetInternalDamage(pScreen); 706} 707 708void 709ephyrPreserve (KdCardInfo *card) 710{ 711} 712 713Bool 714ephyrEnable (ScreenPtr pScreen) 715{ 716 return TRUE; 717} 718 719Bool 720ephyrDPMS (ScreenPtr pScreen, int mode) 721{ 722 return TRUE; 723} 724 725void 726ephyrDisable (ScreenPtr pScreen) 727{ 728} 729 730void 731ephyrRestore (KdCardInfo *card) 732{ 733} 734 735void 736ephyrScreenFini (KdScreenInfo *screen) 737{ 738 EphyrScrPriv *scrpriv = screen->driver; 739 if (scrpriv->shadow) { 740 KdShadowFbFree (screen); 741 } 742 free(screen->driver); 743 screen->driver = NULL; 744} 745 746/* 747 * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug. 748 * See https://bugs.freedesktop.org/show_bug.cgi?id=3030 749 */ 750void 751ephyrUpdateModifierState(unsigned int state) 752{ 753 754 DeviceIntPtr pDev = inputInfo.keyboard; 755 KeyClassPtr keyc = pDev->key; 756 int i; 757 CARD8 mask; 758 int xkb_state; 759 760 if (!pDev) 761 return; 762 763 xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state); 764 state = state & 0xff; 765 766 if (xkb_state == state) 767 return; 768 769 for (i = 0, mask = 1; i < 8; i++, mask <<= 1) { 770 int key; 771 772 /* Modifier is down, but shouldn't be 773 */ 774 if ((xkb_state & mask) && !(state & mask)) { 775 int count = keyc->modifierKeyCount[i]; 776 777 for (key = 0; key < MAP_LENGTH; key++) 778 if (keyc->xkbInfo->desc->map->modmap[key] & mask) { 779 if (key_is_down(pDev, key, KEY_PROCESSED)) 780 KdEnqueueKeyboardEvent (ephyrKbd, key, TRUE); 781 782 if (--count == 0) 783 break; 784 } 785 } 786 787 /* Modifier shoud be down, but isn't 788 */ 789 if (!(xkb_state & mask) && (state & mask)) 790 for (key = 0; key < MAP_LENGTH; key++) 791 if (keyc->xkbInfo->desc->map->modmap[key] & mask) { 792 KdEnqueueKeyboardEvent (ephyrKbd, key, FALSE); 793 break; 794 } 795 } 796} 797 798static void 799ephyrBlockSigio (void) 800{ 801 sigset_t set; 802 803 sigemptyset (&set); 804 sigaddset (&set, SIGIO); 805 sigprocmask (SIG_BLOCK, &set, 0); 806} 807 808static void 809ephyrUnblockSigio (void) 810{ 811 sigset_t set; 812 813 sigemptyset (&set); 814 sigaddset (&set, SIGIO); 815 sigprocmask (SIG_UNBLOCK, &set, 0); 816} 817 818static Bool 819ephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) 820{ 821 return FALSE; 822} 823 824static void 825ephyrCrossScreen (ScreenPtr pScreen, Bool entering) 826{ 827} 828 829int ephyrCurScreen; /*current event screen*/ 830 831static void 832ephyrWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 833{ 834 ephyrBlockSigio (); 835 ephyrCurScreen = pScreen->myNum; 836 miPointerWarpCursor (inputInfo.pointer, pScreen, x, y); 837 ephyrUnblockSigio (); 838} 839 840miPointerScreenFuncRec ephyrPointerScreenFuncs = 841{ 842 ephyrCursorOffScreen, 843 ephyrCrossScreen, 844 ephyrWarpCursor, 845 NULL, 846 NULL 847}; 848 849#ifdef XF86DRI 850/** 851 * find if the remote window denoted by a_remote 852 * is paired with an internal Window within the Xephyr server. 853 * If the remove window is paired with an internal window, send an 854 * expose event to the client insterested in the internal window expose event. 855 * 856 * Pairing happens when a drawable inside Xephyr is associated with 857 * a GL surface in a DRI environment. 858 * Look at the function ProcXF86DRICreateDrawable in ephyrdriext.c to 859 * know a paired window is created. 860 * 861 * This is useful to make GL drawables (only windows for now) handle 862 * expose events and send those events to clients. 863 */ 864static void 865ephyrExposePairedWindow (int a_remote) 866{ 867 EphyrWindowPair *pair = NULL; 868 RegionRec reg; 869 ScreenPtr screen; 870 871 if (!findWindowPairFromRemote (a_remote, &pair)) { 872 EPHYR_LOG ("did not find a pair for this window\n"); 873 return; 874 } 875 screen = pair->local->drawable.pScreen; 876 RegionNull(®); 877 RegionCopy(®, &pair->local->clipList); 878 screen->WindowExposures (pair->local, ®, NullRegion); 879 RegionUninit(®); 880} 881#endif /* XF86DRI */ 882 883void 884ephyrPoll(void) 885{ 886 EphyrHostXEvent ev; 887 888 while (hostx_get_event(&ev)) 889 { 890 switch (ev.type) 891 { 892 case EPHYR_EV_MOUSE_MOTION: 893 if (!ephyrMouse || 894 !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) { 895 EPHYR_LOG ("skipping mouse motion:%d\n", ephyrCurScreen) ; 896 continue; 897 } 898 { 899 if (ev.data.mouse_motion.screen >=0 900 && (ephyrCurScreen != ev.data.mouse_motion.screen)) 901 { 902 EPHYR_LOG ("warping mouse cursor. " 903 "cur_screen%d, motion_screen:%d\n", 904 ephyrCurScreen, ev.data.mouse_motion.screen) ; 905 if (ev.data.mouse_motion.screen >= 0) 906 { 907 ephyrWarpCursor 908 (inputInfo.pointer, screenInfo.screens[ev.data.mouse_motion.screen], 909 ev.data.mouse_motion.x, 910 ev.data.mouse_motion.y ); 911 } 912 } 913 else 914 { 915 int x=0, y=0; 916#ifdef XF86DRI 917 EphyrWindowPair *pair = NULL; 918#endif 919 EPHYR_LOG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ; 920 x = ev.data.mouse_motion.x; 921 y = ev.data.mouse_motion.y; 922 EPHYR_LOG ("initial (x,y):(%d,%d)\n", x, y) ; 923#ifdef XF86DRI 924 EPHYR_LOG ("is this window peered by a gl drawable ?\n") ; 925 if (findWindowPairFromRemote (ev.data.mouse_motion.window, 926 &pair)) 927 { 928 EPHYR_LOG ("yes, it is peered\n") ; 929 x += pair->local->drawable.x; 930 y += pair->local->drawable.y; 931 } 932 else 933 { 934 EPHYR_LOG ("no, it is not peered\n") ; 935 } 936 EPHYR_LOG ("final (x,y):(%d,%d)\n", x, y) ; 937#endif 938 KdEnqueuePointerEvent(ephyrMouse, mouseState, x, y, 0); 939 } 940 } 941 break; 942 943 case EPHYR_EV_MOUSE_PRESS: 944 if (!ephyrMouse || 945 !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) { 946 EPHYR_LOG ("skipping mouse press:%d\n", ephyrCurScreen) ; 947 continue; 948 } 949 EPHYR_LOG ("enqueuing mouse press:%d\n", ephyrCurScreen) ; 950 ephyrUpdateModifierState(ev.key_state); 951 mouseState |= ev.data.mouse_down.button_num; 952 KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); 953 break; 954 955 case EPHYR_EV_MOUSE_RELEASE: 956 if (!ephyrMouse || 957 !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) 958 continue; 959 ephyrUpdateModifierState(ev.key_state); 960 mouseState &= ~ev.data.mouse_up.button_num; 961 EPHYR_LOG ("enqueuing mouse release:%d\n", ephyrCurScreen) ; 962 KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); 963 break; 964 965 case EPHYR_EV_KEY_PRESS: 966 if (!ephyrKbd || 967 !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) 968 continue; 969 ephyrUpdateModifierState(ev.key_state); 970 KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_down.scancode, FALSE); 971 break; 972 973 case EPHYR_EV_KEY_RELEASE: 974 if (!ephyrKbd || 975 !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) 976 continue; 977 ephyrUpdateModifierState(ev.key_state); 978 KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE); 979 break; 980 981#ifdef XF86DRI 982 case EPHYR_EV_EXPOSE: 983 /* 984 * We only receive expose events when the expose event have 985 * be generated for a drawable that is a host X window managed 986 * by Xephyr. Host X windows managed by Xephyr exists for instance 987 * when Xephyr is asked to create a GL drawable in a DRI environment. 988 */ 989 ephyrExposePairedWindow (ev.data.expose.window); 990 break; 991#endif /* XF86DRI */ 992 993 default: 994 break; 995 } 996 } 997} 998 999void 1000ephyrCardFini (KdCardInfo *card) 1001{ 1002 EphyrPriv *priv = card->driver; 1003 free(priv); 1004} 1005 1006void 1007ephyrGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs) 1008{ 1009 /* XXX Not sure if this is right */ 1010 1011 EPHYR_LOG("mark"); 1012 1013 while (n--) 1014 { 1015 pdefs->red = 0; 1016 pdefs->green = 0; 1017 pdefs->blue = 0; 1018 pdefs++; 1019 } 1020 1021} 1022 1023void 1024ephyrPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs) 1025{ 1026 int min, max, p; 1027 1028 /* XXX Not sure if this is right */ 1029 1030 min = 256; 1031 max = 0; 1032 1033 while (n--) 1034 { 1035 p = pdefs->pixel; 1036 if (p < min) 1037 min = p; 1038 if (p > max) 1039 max = p; 1040 1041 hostx_set_cmap_entry(p, 1042 pdefs->red >> 8, 1043 pdefs->green >> 8, 1044 pdefs->blue >> 8); 1045 pdefs++; 1046 } 1047} 1048 1049/* Mouse calls */ 1050 1051static Status 1052MouseInit (KdPointerInfo *pi) 1053{ 1054 pi->driverPrivate = (EphyrPointerPrivate *) 1055 calloc(sizeof(EphyrPointerPrivate), 1); 1056 ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE; 1057 pi->nAxes = 3; 1058 pi->nButtons = 32; 1059 free(pi->name); 1060 pi->name = strdup("Xephyr virtual mouse"); 1061 ephyrMouse = pi; 1062 return Success; 1063} 1064 1065static Status 1066MouseEnable (KdPointerInfo *pi) 1067{ 1068 ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = TRUE; 1069 return Success; 1070} 1071 1072static void 1073MouseDisable (KdPointerInfo *pi) 1074{ 1075 ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE; 1076 return; 1077} 1078 1079static void 1080MouseFini (KdPointerInfo *pi) 1081{ 1082 ephyrMouse = NULL; 1083 return; 1084} 1085 1086KdPointerDriver EphyrMouseDriver = { 1087 "ephyr", 1088 MouseInit, 1089 MouseEnable, 1090 MouseDisable, 1091 MouseFini, 1092 NULL, 1093}; 1094 1095/* Keyboard */ 1096 1097static Status 1098EphyrKeyboardInit (KdKeyboardInfo *ki) 1099{ 1100 ki->driverPrivate = (EphyrKbdPrivate *) 1101 calloc(sizeof(EphyrKbdPrivate), 1); 1102 hostx_load_keymap(); 1103 if (!ephyrKeySyms.map) { 1104 ErrorF("Couldn't load keymap from host\n"); 1105 return BadAlloc; 1106 } 1107 ki->minScanCode = ephyrKeySyms.minKeyCode; 1108 ki->maxScanCode = ephyrKeySyms.maxKeyCode; 1109 free(ki->name); 1110 ki->name = strdup("Xephyr virtual keyboard"); 1111 ephyrKbd = ki; 1112 return Success; 1113} 1114 1115static Status 1116EphyrKeyboardEnable (KdKeyboardInfo *ki) 1117{ 1118 ((EphyrKbdPrivate *)ki->driverPrivate)->enabled = TRUE; 1119 1120 return Success; 1121} 1122 1123static void 1124EphyrKeyboardDisable (KdKeyboardInfo *ki) 1125{ 1126 ((EphyrKbdPrivate *)ki->driverPrivate)->enabled = FALSE; 1127} 1128 1129static void 1130EphyrKeyboardFini (KdKeyboardInfo *ki) 1131{ 1132 ephyrKbd = NULL; 1133 return; 1134} 1135 1136static void 1137EphyrKeyboardLeds (KdKeyboardInfo *ki, int leds) 1138{ 1139} 1140 1141static void 1142EphyrKeyboardBell (KdKeyboardInfo *ki, int volume, int frequency, int duration) 1143{ 1144} 1145 1146 1147KdKeyboardDriver EphyrKeyboardDriver = { 1148 "ephyr", 1149 EphyrKeyboardInit, 1150 EphyrKeyboardEnable, 1151 EphyrKeyboardLeds, 1152 EphyrKeyboardBell, 1153 EphyrKeyboardDisable, 1154 EphyrKeyboardFini, 1155 NULL, 1156}; 1157