Home | History | Annotate | Line # | Download | only in ephyr
      1 /*
      2  * Xephyr - A kdrive X server thats runs in a host X window.
      3  *          Authored by Matthew Allum <mallum (at) 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 
     43 extern int KdTsPhyScreen;
     44 #ifdef GLXEXT
     45 extern Bool noGlxVisualInit;
     46 #endif
     47 
     48 KdKeyboardInfo *ephyrKbd;
     49 KdPointerInfo *ephyrMouse;
     50 EphyrKeySyms ephyrKeySyms;
     51 Bool ephyrNoDRI=FALSE ;
     52 Bool ephyrNoXV=FALSE ;
     53 
     54 static int mouseState = 0;
     55 
     56 typedef struct _EphyrInputPrivate {
     57     Bool    enabled;
     58 } EphyrKbdPrivate, EphyrPointerPrivate;
     59 
     60 Bool   EphyrWantGrayScale = 0;
     61 
     62 
     63 Bool
     64 ephyrInitialize (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 
     73 Bool
     74 ephyrCardInit (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 
     92 Bool
     93 ephyrScreenInitialize (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 
    185 Bool
    186 ephyrScreenInit (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 
    207 void*
    208 ephyrWindowLinear (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  */
    229 int
    230 ephyrBufferHeight(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 
    241 Bool
    242 ephyrMapFramebuffer (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 
    283 void
    284 ephyrSetScreenSizes (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 
    306 Bool
    307 ephyrUnmapFramebuffer (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 
    319 void
    320 ephyrShadowUpdate (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 
    335 static void
    336 ephyrInternalDamageRedisplay (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 
    369 static void
    370 ephyrInternalDamageBlockHandler (pointer   data,
    371 				 OSTimePtr pTimeout,
    372 				 pointer   pRead)
    373 {
    374   ScreenPtr pScreen = (ScreenPtr) data;
    375 
    376   ephyrInternalDamageRedisplay (pScreen);
    377 }
    378 
    379 static void
    380 ephyrInternalDamageWakeupHandler (pointer data, int i, pointer LastSelectMask)
    381 {
    382   /* FIXME: Not needed ? */
    383 }
    384 
    385 Bool
    386 ephyrSetInternalDamage (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 
    412 void
    413 ephyrUnsetInternalDamage (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
    430 Bool
    431 ephyrRandRGetInfo (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 
    492 Bool
    493 ephyrRandRSetConfig (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 
    607 Bool
    608 ephyrRandRInit (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 
    622 Bool
    623 ephyrCreateColormap (ColormapPtr pmap)
    624 {
    625   return fbInitializeColormap (pmap);
    626 }
    627 
    628 Bool
    629 ephyrInitScreen (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 
    672 Bool
    673 ephyrFinishInitScreen (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 
    689 Bool
    690 ephyrCreateResources (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 
    708 void
    709 ephyrPreserve (KdCardInfo *card)
    710 {
    711 }
    712 
    713 Bool
    714 ephyrEnable (ScreenPtr pScreen)
    715 {
    716   return TRUE;
    717 }
    718 
    719 Bool
    720 ephyrDPMS (ScreenPtr pScreen, int mode)
    721 {
    722   return TRUE;
    723 }
    724 
    725 void
    726 ephyrDisable (ScreenPtr pScreen)
    727 {
    728 }
    729 
    730 void
    731 ephyrRestore (KdCardInfo *card)
    732 {
    733 }
    734 
    735 void
    736 ephyrScreenFini (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  */
    750 void
    751 ephyrUpdateModifierState(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 
    798 static void
    799 ephyrBlockSigio (void)
    800 {
    801     sigset_t set;
    802 
    803     sigemptyset (&set);
    804     sigaddset (&set, SIGIO);
    805     sigprocmask (SIG_BLOCK, &set, 0);
    806 }
    807 
    808 static void
    809 ephyrUnblockSigio (void)
    810 {
    811     sigset_t set;
    812 
    813     sigemptyset (&set);
    814     sigaddset (&set, SIGIO);
    815     sigprocmask (SIG_UNBLOCK, &set, 0);
    816 }
    817 
    818 static Bool
    819 ephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
    820 {
    821   return FALSE;
    822 }
    823 
    824 static void
    825 ephyrCrossScreen (ScreenPtr pScreen, Bool entering)
    826 {
    827 }
    828 
    829 int ephyrCurScreen; /*current event screen*/
    830 
    831 static void
    832 ephyrWarpCursor (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 
    840 miPointerScreenFuncRec 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  */
    864 static void
    865 ephyrExposePairedWindow (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(&reg);
    877     RegionCopy(&reg, &pair->local->clipList);
    878     screen->WindowExposures (pair->local, &reg, NullRegion);
    879     RegionUninit(&reg);
    880 }
    881 #endif /* XF86DRI */
    882 
    883 void
    884 ephyrPoll(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 
    999 void
   1000 ephyrCardFini (KdCardInfo *card)
   1001 {
   1002   EphyrPriv	*priv = card->driver;
   1003   free(priv);
   1004 }
   1005 
   1006 void
   1007 ephyrGetColors (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 
   1023 void
   1024 ephyrPutColors (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 
   1051 static Status
   1052 MouseInit (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 
   1065 static Status
   1066 MouseEnable (KdPointerInfo *pi)
   1067 {
   1068     ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = TRUE;
   1069     return Success;
   1070 }
   1071 
   1072 static void
   1073 MouseDisable (KdPointerInfo *pi)
   1074 {
   1075     ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE;
   1076     return;
   1077 }
   1078 
   1079 static void
   1080 MouseFini (KdPointerInfo *pi)
   1081 {
   1082     ephyrMouse = NULL;
   1083     return;
   1084 }
   1085 
   1086 KdPointerDriver EphyrMouseDriver = {
   1087     "ephyr",
   1088     MouseInit,
   1089     MouseEnable,
   1090     MouseDisable,
   1091     MouseFini,
   1092     NULL,
   1093 };
   1094 
   1095 /* Keyboard */
   1096 
   1097 static Status
   1098 EphyrKeyboardInit (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 
   1115 static Status
   1116 EphyrKeyboardEnable (KdKeyboardInfo *ki)
   1117 {
   1118     ((EphyrKbdPrivate *)ki->driverPrivate)->enabled = TRUE;
   1119 
   1120     return Success;
   1121 }
   1122 
   1123 static void
   1124 EphyrKeyboardDisable (KdKeyboardInfo *ki)
   1125 {
   1126     ((EphyrKbdPrivate *)ki->driverPrivate)->enabled = FALSE;
   1127 }
   1128 
   1129 static void
   1130 EphyrKeyboardFini (KdKeyboardInfo *ki)
   1131 {
   1132     ephyrKbd = NULL;
   1133     return;
   1134 }
   1135 
   1136 static void
   1137 EphyrKeyboardLeds (KdKeyboardInfo *ki, int leds)
   1138 {
   1139 }
   1140 
   1141 static void
   1142 EphyrKeyboardBell (KdKeyboardInfo *ki, int volume, int frequency, int duration)
   1143 {
   1144 }
   1145 
   1146 
   1147 KdKeyboardDriver EphyrKeyboardDriver = {
   1148     "ephyr",
   1149     EphyrKeyboardInit,
   1150     EphyrKeyboardEnable,
   1151     EphyrKeyboardLeds,
   1152     EphyrKeyboardBell,
   1153     EphyrKeyboardDisable,
   1154     EphyrKeyboardFini,
   1155     NULL,
   1156 };
   1157