ephyr.c revision 05b261ec
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/* TODO: 27 * 28 * o Support multiple screens, shouldn't be hard just alot of rejigging. 29 */ 30 31#ifdef HAVE_CONFIG_H 32#include <kdrive-config.h> 33#endif 34#include "ephyr.h" 35 36#include "inputstr.h" 37 38extern int KdTsPhyScreen; 39KdKeyboardInfo *ephyrKbd; 40KdPointerInfo *ephyrMouse; 41EphyrKeySyms ephyrKeySyms; 42 43static int mouseState = 0; 44 45typedef struct _EphyrInputPrivate { 46 Bool enabled; 47} EphyrKbdPrivate, EphyrPointerPrivate; 48 49Bool EphyrWantGrayScale = 0; 50 51Bool 52ephyrInitialize (KdCardInfo *card, EphyrPriv *priv) 53{ 54 OsSignal(SIGUSR1, hostx_handle_signal); 55 56 priv->base = 0; 57 priv->bytes_per_line = 0; 58 return TRUE; 59} 60 61Bool 62ephyrCardInit (KdCardInfo *card) 63{ 64 EphyrPriv *priv; 65 66 priv = (EphyrPriv *) xalloc (sizeof (EphyrPriv)); 67 if (!priv) 68 return FALSE; 69 70 if (!ephyrInitialize (card, priv)) 71 { 72 xfree (priv); 73 return FALSE; 74 } 75 card->driver = priv; 76 77 return TRUE; 78} 79 80Bool 81ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv) 82{ 83 int width = 640, height = 480; 84 unsigned long redMask, greenMask, blueMask; 85 86 if (hostx_want_screen_size(&width, &height) 87 || !screen->width || !screen->height) 88 { 89 screen->width = width; 90 screen->height = height; 91 } 92 93 if (EphyrWantGrayScale) 94 screen->fb[0].depth = 8; 95 96 if (screen->fb[0].depth && screen->fb[0].depth != hostx_get_depth()) 97 { 98 if (screen->fb[0].depth < hostx_get_depth() 99 && (screen->fb[0].depth == 24 || screen->fb[0].depth == 16 100 || screen->fb[0].depth == 8)) 101 { 102 hostx_set_server_depth(screen->fb[0].depth); 103 } 104 else 105 ErrorF("\nXephyr: requested screen depth not supported, setting to match hosts.\n"); 106 } 107 108 screen->fb[0].depth = hostx_get_server_depth(); 109 screen->rate = 72; 110 111 if (screen->fb[0].depth <= 8) 112 { 113 if (EphyrWantGrayScale) 114 screen->fb[0].visuals = ((1 << StaticGray) | (1 << GrayScale)); 115 else 116 screen->fb[0].visuals = ((1 << StaticGray) | 117 (1 << GrayScale) | 118 (1 << StaticColor) | 119 (1 << PseudoColor) | 120 (1 << TrueColor) | 121 (1 << DirectColor)); 122 123 screen->fb[0].redMask = 0x00; 124 screen->fb[0].greenMask = 0x00; 125 screen->fb[0].blueMask = 0x00; 126 screen->fb[0].depth = 8; 127 screen->fb[0].bitsPerPixel = 8; 128 } 129 else 130 { 131 screen->fb[0].visuals = (1 << TrueColor); 132 133 if (screen->fb[0].depth <= 15) 134 { 135 screen->fb[0].depth = 15; 136 screen->fb[0].bitsPerPixel = 16; 137 } 138 else if (screen->fb[0].depth <= 16) 139 { 140 screen->fb[0].depth = 16; 141 screen->fb[0].bitsPerPixel = 16; 142 } 143 else 144 { 145 screen->fb[0].depth = 24; 146 screen->fb[0].bitsPerPixel = 32; 147 } 148 149 hostx_get_visual_masks (&redMask, &greenMask, &blueMask); 150 151 screen->fb[0].redMask = (Pixel) redMask; 152 screen->fb[0].greenMask = (Pixel) greenMask; 153 screen->fb[0].blueMask = (Pixel) blueMask; 154 155 } 156 157 scrpriv->randr = screen->randr; 158 159 return ephyrMapFramebuffer (screen); 160} 161 162Bool 163ephyrScreenInit (KdScreenInfo *screen) 164{ 165 EphyrScrPriv *scrpriv; 166 167 scrpriv = xalloc (sizeof (EphyrScrPriv)); 168 169 if (!scrpriv) 170 return FALSE; 171 172 memset (scrpriv, 0, sizeof (EphyrScrPriv)); 173 screen->driver = scrpriv; 174 175 if (!ephyrScreenInitialize (screen, scrpriv)) 176 { 177 screen->driver = 0; 178 xfree (scrpriv); 179 return FALSE; 180 } 181 182 return TRUE; 183} 184 185void* 186ephyrWindowLinear (ScreenPtr pScreen, 187 CARD32 row, 188 CARD32 offset, 189 int mode, 190 CARD32 *size, 191 void *closure) 192{ 193 KdScreenPriv(pScreen); 194 EphyrPriv *priv = pScreenPriv->card->driver; 195 196 if (!pScreenPriv->enabled) 197 { 198 return 0; 199 } 200 201 *size = priv->bytes_per_line; 202 return priv->base + row * priv->bytes_per_line + offset; 203} 204 205Bool 206ephyrMapFramebuffer (KdScreenInfo *screen) 207{ 208 EphyrScrPriv *scrpriv = screen->driver; 209 EphyrPriv *priv = screen->card->driver; 210 KdPointerMatrix m; 211 int buffer_height; 212 213 EPHYR_DBG(" screen->width: %d, screen->height: %d", 214 screen->width, screen->height); 215 216 KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); 217 KdSetPointerMatrix (&m); 218 219 priv->bytes_per_line = ((screen->width * screen->fb[0].bitsPerPixel + 31) >> 5) << 2; 220 221 /* point the framebuffer to the data in an XImage */ 222 /* If fakexa is enabled, allocate a larger buffer so that fakexa has space to 223 * put offscreen pixmaps. 224 */ 225 if (ephyrFuncs.initAccel == NULL) 226 buffer_height = screen->height; 227 else 228 buffer_height = 3 * screen->height; 229 230 priv->base = hostx_screen_init (screen->width, screen->height, buffer_height); 231 232 screen->memory_base = (CARD8 *) (priv->base); 233 screen->memory_size = priv->bytes_per_line * buffer_height; 234 screen->off_screen_base = priv->bytes_per_line * screen->height; 235 236 if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) 237 { 238 scrpriv->shadow = FALSE; 239 240 screen->fb[0].byteStride = priv->bytes_per_line; 241 screen->fb[0].pixelStride = screen->width; 242 screen->fb[0].frameBuffer = (CARD8 *) (priv->base); 243 } 244 else 245 { 246 /* Rotated/Reflected so we need to use shadow fb */ 247 scrpriv->shadow = TRUE; 248 249 EPHYR_DBG("allocing shadow"); 250 251 KdShadowFbAlloc (screen, 0, 252 scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)); 253 } 254 255 return TRUE; 256} 257 258void 259ephyrSetScreenSizes (ScreenPtr pScreen) 260{ 261 KdScreenPriv(pScreen); 262 KdScreenInfo *screen = pScreenPriv->screen; 263 EphyrScrPriv *scrpriv = screen->driver; 264 265 if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) 266 { 267 pScreen->width = screen->width; 268 pScreen->height = screen->height; 269 pScreen->mmWidth = screen->width_mm; 270 pScreen->mmHeight = screen->height_mm; 271 } 272 else 273 { 274 pScreen->width = screen->height; 275 pScreen->height = screen->width; 276 pScreen->mmWidth = screen->height_mm; 277 pScreen->mmHeight = screen->width_mm; 278 } 279} 280 281Bool 282ephyrUnmapFramebuffer (KdScreenInfo *screen) 283{ 284 EphyrScrPriv *scrpriv = screen->driver; 285 286 if (scrpriv->shadow) 287 KdShadowFbFree (screen, 0); 288 289 /* Note, priv->base will get freed when XImage recreated */ 290 291 return TRUE; 292} 293 294void 295ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) 296{ 297 KdScreenPriv(pScreen); 298 KdScreenInfo *screen = pScreenPriv->screen; 299 300 EPHYR_DBG("slow paint"); 301 302 /* FIXME: Slow Rotated/Reflected updates could be much 303 * much faster efficiently updating via tranforming 304 * pBuf->pDamage regions 305 */ 306 shadowUpdateRotatePacked(pScreen, pBuf); 307 hostx_paint_rect(0,0,0,0, screen->width, screen->height); 308} 309 310static void 311ephyrInternalDamageRedisplay (ScreenPtr pScreen) 312{ 313 KdScreenPriv(pScreen); 314 KdScreenInfo *screen = pScreenPriv->screen; 315 EphyrScrPriv *scrpriv = screen->driver; 316 RegionPtr pRegion; 317 318 if (!scrpriv || !scrpriv->pDamage) 319 return; 320 321 pRegion = DamageRegion (scrpriv->pDamage); 322 323 if (REGION_NOTEMPTY (pScreen, pRegion)) 324 { 325 int nbox; 326 BoxPtr pbox; 327 328 nbox = REGION_NUM_RECTS (pRegion); 329 pbox = REGION_RECTS (pRegion); 330 331 while (nbox--) 332 { 333 hostx_paint_rect(pbox->x1, pbox->y1, 334 pbox->x1, pbox->y1, 335 pbox->x2 - pbox->x1, 336 pbox->y2 - pbox->y1); 337 pbox++; 338 } 339 340 DamageEmpty (scrpriv->pDamage); 341 } 342} 343 344static void 345ephyrInternalDamageBlockHandler (pointer data, 346 OSTimePtr pTimeout, 347 pointer pRead) 348{ 349 ScreenPtr pScreen = (ScreenPtr) data; 350 351 ephyrInternalDamageRedisplay (pScreen); 352} 353 354static void 355ephyrInternalDamageWakeupHandler (pointer data, int i, pointer LastSelectMask) 356{ 357 /* FIXME: Not needed ? */ 358} 359 360Bool 361ephyrSetInternalDamage (ScreenPtr pScreen) 362{ 363 KdScreenPriv(pScreen); 364 KdScreenInfo *screen = pScreenPriv->screen; 365 EphyrScrPriv *scrpriv = screen->driver; 366 PixmapPtr pPixmap = NULL; 367 368 scrpriv->pDamage = DamageCreate ((DamageReportFunc) 0, 369 (DamageDestroyFunc) 0, 370 DamageReportNone, 371 TRUE, 372 pScreen, 373 pScreen); 374 375 if (!RegisterBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler, 376 ephyrInternalDamageWakeupHandler, 377 (pointer) pScreen)) 378 return FALSE; 379 380 pPixmap = (*pScreen->GetScreenPixmap) (pScreen); 381 382 DamageRegister (&pPixmap->drawable, scrpriv->pDamage); 383 384 return TRUE; 385} 386 387void 388ephyrUnsetInternalDamage (ScreenPtr pScreen) 389{ 390 KdScreenPriv(pScreen); 391 KdScreenInfo *screen = pScreenPriv->screen; 392 EphyrScrPriv *scrpriv = screen->driver; 393 PixmapPtr pPixmap = NULL; 394 395 pPixmap = (*pScreen->GetScreenPixmap) (pScreen); 396 DamageUnregister (&pPixmap->drawable, scrpriv->pDamage); 397 DamageDestroy (scrpriv->pDamage); 398 399 RemoveBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler, 400 ephyrInternalDamageWakeupHandler, 401 (pointer) pScreen); 402} 403 404#ifdef RANDR 405Bool 406ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) 407{ 408 KdScreenPriv(pScreen); 409 KdScreenInfo *screen = pScreenPriv->screen; 410 EphyrScrPriv *scrpriv = screen->driver; 411 RRScreenSizePtr pSize; 412 Rotation randr; 413 int n = 0; 414 415 EPHYR_DBG("mark"); 416 417 struct { int width, height; } sizes[] = 418 { 419 { 1600, 1200 }, 420 { 1400, 1050 }, 421 { 1280, 960 }, 422 { 1280, 1024 }, 423 { 1152, 864 }, 424 { 1024, 768 }, 425 { 832, 624 }, 426 { 800, 600 }, 427 { 720, 400 }, 428 { 480, 640 }, 429 { 640, 480 }, 430 { 640, 400 }, 431 { 320, 240 }, 432 { 240, 320 }, 433 { 160, 160 }, 434 { 0, 0 } 435 }; 436 437 *rotations = RR_Rotate_All|RR_Reflect_All; 438 439 if (!hostx_want_preexisting_window() 440 && !hostx_want_fullscreen()) /* only if no -parent switch */ 441 { 442 while (sizes[n].width != 0 && sizes[n].height != 0) 443 { 444 RRRegisterSize (pScreen, 445 sizes[n].width, 446 sizes[n].height, 447 (sizes[n].width * screen->width_mm)/screen->width, 448 (sizes[n].height *screen->height_mm)/screen->height 449 ); 450 n++; 451 } 452 } 453 454 pSize = RRRegisterSize (pScreen, 455 screen->width, 456 screen->height, 457 screen->width_mm, 458 screen->height_mm); 459 460 randr = KdSubRotation (scrpriv->randr, screen->randr); 461 462 RRSetCurrentConfig (pScreen, randr, 0, pSize); 463 464 return TRUE; 465} 466 467Bool 468ephyrRandRSetConfig (ScreenPtr pScreen, 469 Rotation randr, 470 int rate, 471 RRScreenSizePtr pSize) 472{ 473 KdScreenPriv(pScreen); 474 KdScreenInfo *screen = pScreenPriv->screen; 475 EphyrScrPriv *scrpriv = screen->driver; 476 Bool wasEnabled = pScreenPriv->enabled; 477 EphyrScrPriv oldscr; 478 int oldwidth, oldheight, oldmmwidth, oldmmheight; 479 Bool oldshadow; 480 int newwidth, newheight; 481 482 if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) 483 { 484 newwidth = pSize->width; 485 newheight = pSize->height; 486 } 487 else 488 { 489 newwidth = pSize->height; 490 newheight = pSize->width; 491 } 492 493 if (wasEnabled) 494 KdDisableScreen (pScreen); 495 496 oldscr = *scrpriv; 497 498 oldwidth = screen->width; 499 oldheight = screen->height; 500 oldmmwidth = pScreen->mmWidth; 501 oldmmheight = pScreen->mmHeight; 502 oldshadow = scrpriv->shadow; 503 504 /* 505 * Set new configuration 506 */ 507 508 scrpriv->randr = KdAddRotation (screen->randr, randr); 509 510 KdOffscreenSwapOut (screen->pScreen); 511 512 ephyrUnmapFramebuffer (screen); 513 514 screen->width = newwidth; 515 screen->height = newheight; 516 517 if (!ephyrMapFramebuffer (screen)) 518 goto bail4; 519 520 /* FIXME below should go in own call */ 521 522 if (oldshadow) 523 KdShadowUnset (screen->pScreen); 524 else 525 ephyrUnsetInternalDamage(screen->pScreen); 526 527 if (scrpriv->shadow) 528 { 529 if (!KdShadowSet (screen->pScreen, 530 scrpriv->randr, 531 ephyrShadowUpdate, 532 ephyrWindowLinear)) 533 goto bail4; 534 } 535 else 536 { 537 /* Without shadow fb ( non rotated ) we need 538 * to use damage to efficiently update display 539 * via signal regions what to copy from 'fb'. 540 */ 541 if (!ephyrSetInternalDamage(screen->pScreen)) 542 goto bail4; 543 } 544 545 ephyrSetScreenSizes (screen->pScreen); 546 547 /* 548 * Set frame buffer mapping 549 */ 550 (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), 551 pScreen->width, 552 pScreen->height, 553 screen->fb[0].depth, 554 screen->fb[0].bitsPerPixel, 555 screen->fb[0].byteStride, 556 screen->fb[0].frameBuffer); 557 558 /* set the subpixel order */ 559 560 KdSetSubpixelOrder (pScreen, scrpriv->randr); 561 562 if (wasEnabled) 563 KdEnableScreen (pScreen); 564 565 return TRUE; 566 567 bail4: 568 EPHYR_DBG("bailed"); 569 570 ephyrUnmapFramebuffer (screen); 571 *scrpriv = oldscr; 572 (void) ephyrMapFramebuffer (screen); 573 574 pScreen->width = oldwidth; 575 pScreen->height = oldheight; 576 pScreen->mmWidth = oldmmwidth; 577 pScreen->mmHeight = oldmmheight; 578 579 if (wasEnabled) 580 KdEnableScreen (pScreen); 581 return FALSE; 582} 583 584Bool 585ephyrRandRInit (ScreenPtr pScreen) 586{ 587 rrScrPrivPtr pScrPriv; 588 589 if (!RRScreenInit (pScreen)) 590 { 591 return FALSE; 592 } 593 594 pScrPriv = rrGetScrPriv(pScreen); 595 pScrPriv->rrGetInfo = ephyrRandRGetInfo; 596 pScrPriv->rrSetConfig = ephyrRandRSetConfig; 597 return TRUE; 598} 599#endif 600 601Bool 602ephyrCreateColormap (ColormapPtr pmap) 603{ 604 return fbInitializeColormap (pmap); 605} 606 607Bool 608ephyrInitScreen (ScreenPtr pScreen) 609{ 610 pScreen->CreateColormap = ephyrCreateColormap; 611 return TRUE; 612} 613 614Bool 615ephyrFinishInitScreen (ScreenPtr pScreen) 616{ 617 /* FIXME: Calling this even if not using shadow. 618 * Seems harmless enough. But may be safer elsewhere. 619 */ 620 if (!shadowSetup (pScreen)) 621 return FALSE; 622 623#ifdef RANDR 624 if (!ephyrRandRInit (pScreen)) 625 return FALSE; 626#endif 627 628 return TRUE; 629} 630 631Bool 632ephyrCreateResources (ScreenPtr pScreen) 633{ 634 KdScreenPriv(pScreen); 635 KdScreenInfo *screen = pScreenPriv->screen; 636 EphyrScrPriv *scrpriv = screen->driver; 637 638 EPHYR_DBG("mark"); 639 640 if (scrpriv->shadow) 641 return KdShadowSet (pScreen, 642 scrpriv->randr, 643 ephyrShadowUpdate, 644 ephyrWindowLinear); 645 else 646 return ephyrSetInternalDamage(pScreen); 647} 648 649void 650ephyrPreserve (KdCardInfo *card) 651{ 652} 653 654Bool 655ephyrEnable (ScreenPtr pScreen) 656{ 657 return TRUE; 658} 659 660Bool 661ephyrDPMS (ScreenPtr pScreen, int mode) 662{ 663 return TRUE; 664} 665 666void 667ephyrDisable (ScreenPtr pScreen) 668{ 669} 670 671void 672ephyrRestore (KdCardInfo *card) 673{ 674} 675 676void 677ephyrScreenFini (KdScreenInfo *screen) 678{ 679 xfree(screen->driver); 680 screen->driver = NULL; 681} 682 683/* 684 * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug. 685 * See https://bugs.freedesktop.org/show_bug.cgi?id=3030 686 */ 687void 688ephyrUpdateModifierState(unsigned int state) 689{ 690 DeviceIntPtr pkeydev; 691 KeyClassPtr keyc; 692 int i; 693 CARD8 mask; 694 695 pkeydev = (DeviceIntPtr)LookupKeyboardDevice(); 696 697 if (!pkeydev) 698 return; 699 700 keyc = pkeydev->key; 701 702 state = state & 0xff; 703 704 if (keyc->state == state) 705 return; 706 707 for (i = 0, mask = 1; i < 8; i++, mask <<= 1) 708 { 709 int key; 710 711 /* Modifier is down, but shouldn't be */ 712 if ((keyc->state & mask) && !(state & mask)) 713 { 714 int count = keyc->modifierKeyCount[i]; 715 716 for (key = 0; key < MAP_LENGTH; key++) 717 if (keyc->modifierMap[key] & mask) 718 { 719 int bit; 720 BYTE *kptr; 721 722 kptr = &keyc->down[key >> 3]; 723 bit = 1 << (key & 7); 724 725 if (*kptr & bit && ephyrKbd && 726 ((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) 727 KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE); /* release */ 728 729 if (--count == 0) 730 break; 731 } 732 } 733 734 /* Modifier shoud be down, but isn't */ 735 if (!(keyc->state & mask) && (state & mask)) 736 for (key = 0; key < MAP_LENGTH; key++) 737 if (keyc->modifierMap[key] & mask) 738 { 739 if (keyc->modifierMap[key] & mask && ephyrKbd && 740 ((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) 741 KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE); /* press */ 742 break; 743 } 744 } 745} 746 747void 748ephyrPoll(void) 749{ 750 EphyrHostXEvent ev; 751 752 while (hostx_get_event(&ev)) 753 { 754 switch (ev.type) 755 { 756 case EPHYR_EV_MOUSE_MOTION: 757 if (!ephyrMouse || 758 !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) 759 continue; 760 KdEnqueuePointerEvent(ephyrMouse, mouseState, 761 ev.data.mouse_motion.x, 762 ev.data.mouse_motion.y, 763 0); 764 break; 765 766 case EPHYR_EV_MOUSE_PRESS: 767 if (!ephyrMouse || 768 !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) 769 continue; 770 ephyrUpdateModifierState(ev.key_state); 771 mouseState |= ev.data.mouse_down.button_num; 772 KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); 773 break; 774 775 case EPHYR_EV_MOUSE_RELEASE: 776 if (!ephyrMouse || 777 !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) 778 continue; 779 ephyrUpdateModifierState(ev.key_state); 780 mouseState &= ~ev.data.mouse_up.button_num; 781 KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); 782 break; 783 784 case EPHYR_EV_KEY_PRESS: 785 if (!ephyrKbd || 786 !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) 787 continue; 788 ephyrUpdateModifierState(ev.key_state); 789 KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_down.scancode, FALSE); 790 break; 791 792 case EPHYR_EV_KEY_RELEASE: 793 if (!ephyrKbd || 794 !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) 795 continue; 796 ephyrUpdateModifierState(ev.key_state); 797 KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE); 798 break; 799 800 default: 801 break; 802 } 803 } 804} 805 806void 807ephyrCardFini (KdCardInfo *card) 808{ 809 EphyrPriv *priv = card->driver; 810 xfree (priv); 811} 812 813void 814ephyrGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) 815{ 816 /* XXX Not sure if this is right */ 817 818 EPHYR_DBG("mark"); 819 820 while (n--) 821 { 822 pdefs->red = 0; 823 pdefs->green = 0; 824 pdefs->blue = 0; 825 pdefs++; 826 } 827 828} 829 830void 831ephyrPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) 832{ 833 int min, max, p; 834 835 /* XXX Not sure if this is right */ 836 837 min = 256; 838 max = 0; 839 840 while (n--) 841 { 842 p = pdefs->pixel; 843 if (p < min) 844 min = p; 845 if (p > max) 846 max = p; 847 848 hostx_set_cmap_entry(p, 849 pdefs->red >> 8, 850 pdefs->green >> 8, 851 pdefs->blue >> 8); 852 pdefs++; 853 } 854} 855 856/* Mouse calls */ 857 858static Status 859MouseInit (KdPointerInfo *pi) 860{ 861 pi->driverPrivate = (EphyrPointerPrivate *) 862 xcalloc(sizeof(EphyrPointerPrivate), 1); 863 ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE; 864 pi->nAxes = 3; 865 pi->nButtons = 32; 866 pi->name = KdSaveString("Xephyr virtual mouse"); 867 ephyrMouse = pi; 868 return Success; 869} 870 871static Status 872MouseEnable (KdPointerInfo *pi) 873{ 874 ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = TRUE; 875 return Success; 876} 877 878static void 879MouseDisable (KdPointerInfo *pi) 880{ 881 ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE; 882 return; 883} 884 885static void 886MouseFini (KdPointerInfo *pi) 887{ 888 ephyrMouse = NULL; 889 return; 890} 891 892KdPointerDriver EphyrMouseDriver = { 893 "ephyr", 894 MouseInit, 895 MouseEnable, 896 MouseDisable, 897 MouseFini, 898 NULL, 899}; 900 901/* Keyboard */ 902 903static Status 904EphyrKeyboardInit (KdKeyboardInfo *ki) 905{ 906 ki->driverPrivate = (EphyrKbdPrivate *) 907 xcalloc(sizeof(EphyrKbdPrivate), 1); 908 hostx_load_keymap(); 909 if (!ephyrKeySyms.map) { 910 ErrorF("Couldn't load keymap from host\n"); 911 return BadAlloc; 912 } 913 ki->keySyms.minKeyCode = ephyrKeySyms.minKeyCode; 914 ki->keySyms.maxKeyCode = ephyrKeySyms.maxKeyCode; 915 ki->minScanCode = ki->keySyms.minKeyCode; 916 ki->maxScanCode = ki->keySyms.maxKeyCode; 917 ki->keySyms.mapWidth = ephyrKeySyms.mapWidth; 918 xfree(ki->keySyms.map); 919 ki->keySyms.map = ephyrKeySyms.map; 920 ki->name = KdSaveString("Xephyr virtual keyboard"); 921 ephyrKbd = ki; 922 return Success; 923} 924 925static Status 926EphyrKeyboardEnable (KdKeyboardInfo *ki) 927{ 928 ((EphyrKbdPrivate *)ki->driverPrivate)->enabled = TRUE; 929 930 return Success; 931} 932 933static void 934EphyrKeyboardDisable (KdKeyboardInfo *ki) 935{ 936 ((EphyrKbdPrivate *)ki->driverPrivate)->enabled = FALSE; 937} 938 939static void 940EphyrKeyboardFini (KdKeyboardInfo *ki) 941{ 942 /* not xfree: we call malloc from hostx.c. */ 943 free(ki->keySyms.map); 944 ephyrKbd = NULL; 945 return; 946} 947 948static void 949EphyrKeyboardLeds (KdKeyboardInfo *ki, int leds) 950{ 951} 952 953static void 954EphyrKeyboardBell (KdKeyboardInfo *ki, int volume, int frequency, int duration) 955{ 956} 957 958KdKeyboardDriver EphyrKeyboardDriver = { 959 "ephyr", 960 EphyrKeyboardInit, 961 EphyrKeyboardEnable, 962 EphyrKeyboardLeds, 963 EphyrKeyboardBell, 964 EphyrKeyboardDisable, 965 EphyrKeyboardFini, 966 NULL, 967}; 968