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(&reg);
877    RegionCopy(&reg, &pair->local->clipList);
878    screen->WindowExposures (pair->local, &reg, NullRegion);
879    RegionUninit(&reg);
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