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