1706f2543Smrg/*
2706f2543Smrg * Xephyr - A kdrive X server thats runs in a host X window.
3706f2543Smrg *          Authored by Matthew Allum <mallum@openedhand.com>
4706f2543Smrg *
5706f2543Smrg * Copyright � 2004 Nokia
6706f2543Smrg *
7706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
8706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
9706f2543Smrg * the above copyright notice appear in all copies and that both that
10706f2543Smrg * copyright notice and this permission notice appear in supporting
11706f2543Smrg * documentation, and that the name of Nokia not be used in
12706f2543Smrg * advertising or publicity pertaining to distribution of the software without
13706f2543Smrg * specific, written prior permission. Nokia makes no
14706f2543Smrg * representations about the suitability of this software for any purpose.  It
15706f2543Smrg * is provided "as is" without express or implied warranty.
16706f2543Smrg *
17706f2543Smrg * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19706f2543Smrg * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
24706f2543Smrg */
25706f2543Smrg
26706f2543Smrg#ifdef HAVE_CONFIG_H
27706f2543Smrg#include <kdrive-config.h>
28706f2543Smrg#endif
29706f2543Smrg#include "ephyr.h"
30706f2543Smrg
31706f2543Smrg#include "inputstr.h"
32706f2543Smrg#include "scrnintstr.h"
33706f2543Smrg#include "ephyrlog.h"
34706f2543Smrg
35706f2543Smrg#ifdef XF86DRI
36706f2543Smrg#include "ephyrdri.h"
37706f2543Smrg#include "ephyrdriext.h"
38706f2543Smrg#include "ephyrglxext.h"
39706f2543Smrg#endif /* XF86DRI */
40706f2543Smrg
41706f2543Smrg#include "xkbsrv.h"
42706f2543Smrg
43706f2543Smrgextern int KdTsPhyScreen;
44706f2543Smrg#ifdef GLXEXT
45706f2543Smrgextern Bool noGlxVisualInit;
46706f2543Smrg#endif
47706f2543Smrg
48706f2543SmrgKdKeyboardInfo *ephyrKbd;
49706f2543SmrgKdPointerInfo *ephyrMouse;
50706f2543SmrgEphyrKeySyms ephyrKeySyms;
51706f2543SmrgBool ephyrNoDRI=FALSE ;
52706f2543SmrgBool ephyrNoXV=FALSE ;
53706f2543Smrg
54706f2543Smrgstatic int mouseState = 0;
55706f2543Smrg
56706f2543Smrgtypedef struct _EphyrInputPrivate {
57706f2543Smrg    Bool    enabled;
58706f2543Smrg} EphyrKbdPrivate, EphyrPointerPrivate;
59706f2543Smrg
60706f2543SmrgBool   EphyrWantGrayScale = 0;
61706f2543Smrg
62706f2543Smrg
63706f2543SmrgBool
64706f2543SmrgephyrInitialize (KdCardInfo *card, EphyrPriv *priv)
65706f2543Smrg{
66706f2543Smrg  OsSignal(SIGUSR1, hostx_handle_signal);
67706f2543Smrg
68706f2543Smrg  priv->base = 0;
69706f2543Smrg  priv->bytes_per_line = 0;
70706f2543Smrg  return TRUE;
71706f2543Smrg}
72706f2543Smrg
73706f2543SmrgBool
74706f2543SmrgephyrCardInit (KdCardInfo *card)
75706f2543Smrg{
76706f2543Smrg  EphyrPriv	*priv;
77706f2543Smrg
78706f2543Smrg  priv = (EphyrPriv *) malloc(sizeof (EphyrPriv));
79706f2543Smrg  if (!priv)
80706f2543Smrg    return FALSE;
81706f2543Smrg
82706f2543Smrg  if (!ephyrInitialize (card, priv))
83706f2543Smrg    {
84706f2543Smrg      free(priv);
85706f2543Smrg      return FALSE;
86706f2543Smrg    }
87706f2543Smrg  card->driver = priv;
88706f2543Smrg
89706f2543Smrg  return TRUE;
90706f2543Smrg}
91706f2543Smrg
92706f2543SmrgBool
93706f2543SmrgephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv)
94706f2543Smrg{
95706f2543Smrg  int width = 640, height = 480;
96706f2543Smrg  CARD32 redMask, greenMask, blueMask;
97706f2543Smrg
98706f2543Smrg  if (hostx_want_screen_size(screen, &width, &height)
99706f2543Smrg      || !screen->width || !screen->height)
100706f2543Smrg    {
101706f2543Smrg      screen->width = width;
102706f2543Smrg      screen->height = height;
103706f2543Smrg    }
104706f2543Smrg
105706f2543Smrg  if (EphyrWantGrayScale)
106706f2543Smrg    screen->fb.depth = 8;
107706f2543Smrg
108706f2543Smrg  if (screen->fb.depth && screen->fb.depth != hostx_get_depth())
109706f2543Smrg    {
110706f2543Smrg      if (screen->fb.depth < hostx_get_depth()
111706f2543Smrg	  && (screen->fb.depth == 24 || screen->fb.depth == 16
112706f2543Smrg	      || screen->fb.depth == 8))
113706f2543Smrg	{
114706f2543Smrg	  hostx_set_server_depth(screen, screen->fb.depth);
115706f2543Smrg	}
116706f2543Smrg      else
117706f2543Smrg	ErrorF("\nXephyr: requested screen depth not supported, setting to match hosts.\n");
118706f2543Smrg    }
119706f2543Smrg
120706f2543Smrg  screen->fb.depth = hostx_get_server_depth(screen);
121706f2543Smrg  screen->rate = 72;
122706f2543Smrg
123706f2543Smrg  if (screen->fb.depth <= 8)
124706f2543Smrg    {
125706f2543Smrg      if (EphyrWantGrayScale)
126706f2543Smrg	screen->fb.visuals = ((1 << StaticGray) | (1 << GrayScale));
127706f2543Smrg      else
128706f2543Smrg	screen->fb.visuals = ((1 << StaticGray) |
129706f2543Smrg			      (1 << GrayScale) |
130706f2543Smrg			      (1 << StaticColor) |
131706f2543Smrg			      (1 << PseudoColor) |
132706f2543Smrg			      (1 << TrueColor) |
133706f2543Smrg			      (1 << DirectColor));
134706f2543Smrg
135706f2543Smrg      screen->fb.redMask   = 0x00;
136706f2543Smrg      screen->fb.greenMask = 0x00;
137706f2543Smrg      screen->fb.blueMask  = 0x00;
138706f2543Smrg      screen->fb.depth        = 8;
139706f2543Smrg      screen->fb.bitsPerPixel = 8;
140706f2543Smrg    }
141706f2543Smrg  else
142706f2543Smrg    {
143706f2543Smrg      screen->fb.visuals = (1 << TrueColor);
144706f2543Smrg
145706f2543Smrg      if (screen->fb.depth <= 15)
146706f2543Smrg	{
147706f2543Smrg	  screen->fb.depth = 15;
148706f2543Smrg	  screen->fb.bitsPerPixel = 16;
149706f2543Smrg	}
150706f2543Smrg      else if (screen->fb.depth <= 16)
151706f2543Smrg	{
152706f2543Smrg	  screen->fb.depth = 16;
153706f2543Smrg	  screen->fb.bitsPerPixel = 16;
154706f2543Smrg	}
155706f2543Smrg      else if (screen->fb.depth <= 24)
156706f2543Smrg	{
157706f2543Smrg	  screen->fb.depth = 24;
158706f2543Smrg	  screen->fb.bitsPerPixel = 32;
159706f2543Smrg	}
160706f2543Smrg      else if (screen->fb.depth <= 30)
161706f2543Smrg	{
162706f2543Smrg	  screen->fb.depth = 30;
163706f2543Smrg	  screen->fb.bitsPerPixel = 32;
164706f2543Smrg	}
165706f2543Smrg      else
166706f2543Smrg	{
167706f2543Smrg	  ErrorF("\nXephyr: Unsupported screen depth %d\n",
168706f2543Smrg	         screen->fb.depth);
169706f2543Smrg	  return FALSE;
170706f2543Smrg	}
171706f2543Smrg
172706f2543Smrg      hostx_get_visual_masks (screen, &redMask, &greenMask, &blueMask);
173706f2543Smrg
174706f2543Smrg      screen->fb.redMask = (Pixel) redMask;
175706f2543Smrg      screen->fb.greenMask = (Pixel) greenMask;
176706f2543Smrg      screen->fb.blueMask = (Pixel) blueMask;
177706f2543Smrg
178706f2543Smrg    }
179706f2543Smrg
180706f2543Smrg  scrpriv->randr = screen->randr;
181706f2543Smrg
182706f2543Smrg  return ephyrMapFramebuffer (screen);
183706f2543Smrg}
184706f2543Smrg
185706f2543SmrgBool
186706f2543SmrgephyrScreenInit (KdScreenInfo *screen)
187706f2543Smrg{
188706f2543Smrg  EphyrScrPriv *scrpriv;
189706f2543Smrg
190706f2543Smrg  scrpriv = calloc(1, sizeof (EphyrScrPriv));
191706f2543Smrg
192706f2543Smrg  if (!scrpriv)
193706f2543Smrg    return FALSE;
194706f2543Smrg
195706f2543Smrg  screen->driver = scrpriv;
196706f2543Smrg
197706f2543Smrg  if (!ephyrScreenInitialize (screen, scrpriv))
198706f2543Smrg    {
199706f2543Smrg      screen->driver = 0;
200706f2543Smrg      free(scrpriv);
201706f2543Smrg      return FALSE;
202706f2543Smrg    }
203706f2543Smrg
204706f2543Smrg  return TRUE;
205706f2543Smrg}
206706f2543Smrg
207706f2543Smrgvoid*
208706f2543SmrgephyrWindowLinear (ScreenPtr	pScreen,
209706f2543Smrg		   CARD32	row,
210706f2543Smrg		   CARD32	offset,
211706f2543Smrg		   int		mode,
212706f2543Smrg		   CARD32	*size,
213706f2543Smrg		   void		*closure)
214706f2543Smrg{
215706f2543Smrg  KdScreenPriv(pScreen);
216706f2543Smrg  EphyrPriv	    *priv = pScreenPriv->card->driver;
217706f2543Smrg
218706f2543Smrg  if (!pScreenPriv->enabled)
219706f2543Smrg    return 0;
220706f2543Smrg
221706f2543Smrg  *size = priv->bytes_per_line;
222706f2543Smrg  return priv->base + row * priv->bytes_per_line + offset;
223706f2543Smrg}
224706f2543Smrg
225706f2543Smrg/**
226706f2543Smrg * Figure out display buffer size. If fakexa is enabled, allocate a larger
227706f2543Smrg * buffer so that fakexa has space to put offscreen pixmaps.
228706f2543Smrg */
229706f2543Smrgint
230706f2543SmrgephyrBufferHeight(KdScreenInfo *screen)
231706f2543Smrg{
232706f2543Smrg    int buffer_height;
233706f2543Smrg    if (ephyrFuncs.initAccel == NULL)
234706f2543Smrg	buffer_height = screen->height;
235706f2543Smrg    else
236706f2543Smrg	buffer_height = 3 * screen->height;
237706f2543Smrg    return buffer_height;
238706f2543Smrg}
239706f2543Smrg
240706f2543Smrg
241706f2543SmrgBool
242706f2543SmrgephyrMapFramebuffer (KdScreenInfo *screen)
243706f2543Smrg{
244706f2543Smrg  EphyrScrPriv  *scrpriv = screen->driver;
245706f2543Smrg  EphyrPriv	  *priv    = screen->card->driver;
246706f2543Smrg  KdPointerMatrix m;
247706f2543Smrg  int buffer_height;
248706f2543Smrg
249706f2543Smrg  EPHYR_LOG("screen->width: %d, screen->height: %d index=%d",
250706f2543Smrg	     screen->width, screen->height, screen->mynum);
251706f2543Smrg
252706f2543Smrg  KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height);
253706f2543Smrg  KdSetPointerMatrix (&m);
254706f2543Smrg
255706f2543Smrg  priv->bytes_per_line = ((screen->width * screen->fb.bitsPerPixel + 31) >> 5) << 2;
256706f2543Smrg
257706f2543Smrg  buffer_height = ephyrBufferHeight(screen);
258706f2543Smrg
259706f2543Smrg  priv->base = hostx_screen_init (screen, screen->width, screen->height, buffer_height);
260706f2543Smrg
261706f2543Smrg  if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All))
262706f2543Smrg    {
263706f2543Smrg      scrpriv->shadow = FALSE;
264706f2543Smrg
265706f2543Smrg      screen->fb.byteStride = priv->bytes_per_line;
266706f2543Smrg      screen->fb.pixelStride = screen->width;
267706f2543Smrg      screen->fb.frameBuffer = (CARD8 *) (priv->base);
268706f2543Smrg    }
269706f2543Smrg  else
270706f2543Smrg    {
271706f2543Smrg      /* Rotated/Reflected so we need to use shadow fb */
272706f2543Smrg      scrpriv->shadow = TRUE;
273706f2543Smrg
274706f2543Smrg      EPHYR_LOG("allocing shadow");
275706f2543Smrg
276706f2543Smrg      KdShadowFbAlloc (screen,
277706f2543Smrg		       scrpriv->randr & (RR_Rotate_90|RR_Rotate_270));
278706f2543Smrg    }
279706f2543Smrg
280706f2543Smrg  return TRUE;
281706f2543Smrg}
282706f2543Smrg
283706f2543Smrgvoid
284706f2543SmrgephyrSetScreenSizes (ScreenPtr pScreen)
285706f2543Smrg{
286706f2543Smrg  KdScreenPriv(pScreen);
287706f2543Smrg  KdScreenInfo	*screen = pScreenPriv->screen;
288706f2543Smrg  EphyrScrPriv	*scrpriv = screen->driver;
289706f2543Smrg
290706f2543Smrg  if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180))
291706f2543Smrg    {
292706f2543Smrg      pScreen->width = screen->width;
293706f2543Smrg      pScreen->height = screen->height;
294706f2543Smrg      pScreen->mmWidth = screen->width_mm;
295706f2543Smrg      pScreen->mmHeight = screen->height_mm;
296706f2543Smrg    }
297706f2543Smrg  else
298706f2543Smrg    {
299706f2543Smrg      pScreen->width = screen->height;
300706f2543Smrg      pScreen->height = screen->width;
301706f2543Smrg      pScreen->mmWidth = screen->height_mm;
302706f2543Smrg      pScreen->mmHeight = screen->width_mm;
303706f2543Smrg    }
304706f2543Smrg}
305706f2543Smrg
306706f2543SmrgBool
307706f2543SmrgephyrUnmapFramebuffer (KdScreenInfo *screen)
308706f2543Smrg{
309706f2543Smrg  EphyrScrPriv  *scrpriv = screen->driver;
310706f2543Smrg
311706f2543Smrg  if (scrpriv->shadow)
312706f2543Smrg    KdShadowFbFree (screen);
313706f2543Smrg
314706f2543Smrg  /* Note, priv->base will get freed when XImage recreated */
315706f2543Smrg
316706f2543Smrg  return TRUE;
317706f2543Smrg}
318706f2543Smrg
319706f2543Smrgvoid
320706f2543SmrgephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
321706f2543Smrg{
322706f2543Smrg  KdScreenPriv(pScreen);
323706f2543Smrg  KdScreenInfo *screen = pScreenPriv->screen;
324706f2543Smrg
325706f2543Smrg  EPHYR_LOG("slow paint");
326706f2543Smrg
327706f2543Smrg  /* FIXME: Slow Rotated/Reflected updates could be much
328706f2543Smrg   * much faster efficiently updating via tranforming
329706f2543Smrg   * pBuf->pDamage  regions
330706f2543Smrg  */
331706f2543Smrg  shadowUpdateRotatePacked(pScreen, pBuf);
332706f2543Smrg  hostx_paint_rect(screen, 0,0,0,0, screen->width, screen->height);
333706f2543Smrg}
334706f2543Smrg
335706f2543Smrgstatic void
336706f2543SmrgephyrInternalDamageRedisplay (ScreenPtr pScreen)
337706f2543Smrg{
338706f2543Smrg  KdScreenPriv(pScreen);
339706f2543Smrg  KdScreenInfo	*screen = pScreenPriv->screen;
340706f2543Smrg  EphyrScrPriv	*scrpriv = screen->driver;
341706f2543Smrg  RegionPtr	 pRegion;
342706f2543Smrg
343706f2543Smrg  if (!scrpriv || !scrpriv->pDamage)
344706f2543Smrg    return;
345706f2543Smrg
346706f2543Smrg  pRegion = DamageRegion (scrpriv->pDamage);
347706f2543Smrg
348706f2543Smrg  if (RegionNotEmpty(pRegion))
349706f2543Smrg    {
350706f2543Smrg      int           nbox;
351706f2543Smrg      BoxPtr        pbox;
352706f2543Smrg
353706f2543Smrg      nbox = RegionNumRects (pRegion);
354706f2543Smrg      pbox = RegionRects (pRegion);
355706f2543Smrg
356706f2543Smrg      while (nbox--)
357706f2543Smrg        {
358706f2543Smrg          hostx_paint_rect(screen,
359706f2543Smrg                           pbox->x1, pbox->y1,
360706f2543Smrg                           pbox->x1, pbox->y1,
361706f2543Smrg                           pbox->x2 - pbox->x1,
362706f2543Smrg                           pbox->y2 - pbox->y1);
363706f2543Smrg          pbox++;
364706f2543Smrg        }
365706f2543Smrg      DamageEmpty (scrpriv->pDamage);
366706f2543Smrg    }
367706f2543Smrg}
368706f2543Smrg
369706f2543Smrgstatic void
370706f2543SmrgephyrInternalDamageBlockHandler (pointer   data,
371706f2543Smrg				 OSTimePtr pTimeout,
372706f2543Smrg				 pointer   pRead)
373706f2543Smrg{
374706f2543Smrg  ScreenPtr pScreen = (ScreenPtr) data;
375706f2543Smrg
376706f2543Smrg  ephyrInternalDamageRedisplay (pScreen);
377706f2543Smrg}
378706f2543Smrg
379706f2543Smrgstatic void
380706f2543SmrgephyrInternalDamageWakeupHandler (pointer data, int i, pointer LastSelectMask)
381706f2543Smrg{
382706f2543Smrg  /* FIXME: Not needed ? */
383706f2543Smrg}
384706f2543Smrg
385706f2543SmrgBool
386706f2543SmrgephyrSetInternalDamage (ScreenPtr pScreen)
387706f2543Smrg{
388706f2543Smrg  KdScreenPriv(pScreen);
389706f2543Smrg  KdScreenInfo	*screen = pScreenPriv->screen;
390706f2543Smrg  EphyrScrPriv	*scrpriv = screen->driver;
391706f2543Smrg  PixmapPtr      pPixmap = NULL;
392706f2543Smrg
393706f2543Smrg  scrpriv->pDamage = DamageCreate ((DamageReportFunc) 0,
394706f2543Smrg				   (DamageDestroyFunc) 0,
395706f2543Smrg				   DamageReportNone,
396706f2543Smrg				   TRUE,
397706f2543Smrg				   pScreen,
398706f2543Smrg				   pScreen);
399706f2543Smrg
400706f2543Smrg  if (!RegisterBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler,
401706f2543Smrg				       ephyrInternalDamageWakeupHandler,
402706f2543Smrg				       (pointer) pScreen))
403706f2543Smrg    return FALSE;
404706f2543Smrg
405706f2543Smrg  pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
406706f2543Smrg
407706f2543Smrg  DamageRegister (&pPixmap->drawable, scrpriv->pDamage);
408706f2543Smrg
409706f2543Smrg  return TRUE;
410706f2543Smrg}
411706f2543Smrg
412706f2543Smrgvoid
413706f2543SmrgephyrUnsetInternalDamage (ScreenPtr pScreen)
414706f2543Smrg{
415706f2543Smrg  KdScreenPriv(pScreen);
416706f2543Smrg  KdScreenInfo	*screen = pScreenPriv->screen;
417706f2543Smrg  EphyrScrPriv	*scrpriv = screen->driver;
418706f2543Smrg  PixmapPtr      pPixmap = NULL;
419706f2543Smrg
420706f2543Smrg  pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
421706f2543Smrg  DamageUnregister (&pPixmap->drawable, scrpriv->pDamage);
422706f2543Smrg  DamageDestroy (scrpriv->pDamage);
423706f2543Smrg
424706f2543Smrg  RemoveBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler,
425706f2543Smrg				ephyrInternalDamageWakeupHandler,
426706f2543Smrg				(pointer) pScreen);
427706f2543Smrg}
428706f2543Smrg
429706f2543Smrg#ifdef RANDR
430706f2543SmrgBool
431706f2543SmrgephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
432706f2543Smrg{
433706f2543Smrg  KdScreenPriv(pScreen);
434706f2543Smrg  KdScreenInfo	    *screen = pScreenPriv->screen;
435706f2543Smrg  EphyrScrPriv	    *scrpriv = screen->driver;
436706f2543Smrg  RRScreenSizePtr	    pSize;
437706f2543Smrg  Rotation		    randr;
438706f2543Smrg  int			    n = 0;
439706f2543Smrg
440706f2543Smrg  struct { int width, height; } sizes[] =
441706f2543Smrg    {
442706f2543Smrg      { 1600, 1200 },
443706f2543Smrg      { 1400, 1050 },
444706f2543Smrg      { 1280, 960  },
445706f2543Smrg      { 1280, 1024 },
446706f2543Smrg      { 1152, 864 },
447706f2543Smrg      { 1024, 768 },
448706f2543Smrg      { 832, 624 },
449706f2543Smrg      { 800, 600 },
450706f2543Smrg      { 720, 400 },
451706f2543Smrg      { 480, 640 },
452706f2543Smrg      { 640, 480 },
453706f2543Smrg      { 640, 400 },
454706f2543Smrg      { 320, 240 },
455706f2543Smrg      { 240, 320 },
456706f2543Smrg      { 160, 160 },
457706f2543Smrg      { 0, 0 }
458706f2543Smrg    };
459706f2543Smrg
460706f2543Smrg  EPHYR_LOG("mark");
461706f2543Smrg
462706f2543Smrg  *rotations = RR_Rotate_All|RR_Reflect_All;
463706f2543Smrg
464706f2543Smrg  if (!hostx_want_preexisting_window (screen)
465706f2543Smrg      && !hostx_want_fullscreen ()) /* only if no -parent switch */
466706f2543Smrg    {
467706f2543Smrg      while (sizes[n].width != 0 && sizes[n].height != 0)
468706f2543Smrg	{
469706f2543Smrg	  RRRegisterSize (pScreen,
470706f2543Smrg			  sizes[n].width,
471706f2543Smrg			  sizes[n].height,
472706f2543Smrg			  (sizes[n].width * screen->width_mm)/screen->width,
473706f2543Smrg			  (sizes[n].height *screen->height_mm)/screen->height
474706f2543Smrg			  );
475706f2543Smrg	  n++;
476706f2543Smrg	}
477706f2543Smrg    }
478706f2543Smrg
479706f2543Smrg  pSize = RRRegisterSize (pScreen,
480706f2543Smrg			  screen->width,
481706f2543Smrg			  screen->height,
482706f2543Smrg			  screen->width_mm,
483706f2543Smrg			  screen->height_mm);
484706f2543Smrg
485706f2543Smrg  randr = KdSubRotation (scrpriv->randr, screen->randr);
486706f2543Smrg
487706f2543Smrg  RRSetCurrentConfig (pScreen, randr, 0, pSize);
488706f2543Smrg
489706f2543Smrg  return TRUE;
490706f2543Smrg}
491706f2543Smrg
492706f2543SmrgBool
493706f2543SmrgephyrRandRSetConfig (ScreenPtr		pScreen,
494706f2543Smrg		     Rotation		randr,
495706f2543Smrg		     int		rate,
496706f2543Smrg		     RRScreenSizePtr	pSize)
497706f2543Smrg{
498706f2543Smrg  KdScreenPriv(pScreen);
499706f2543Smrg  KdScreenInfo	*screen    = pScreenPriv->screen;
500706f2543Smrg  EphyrScrPriv	*scrpriv   = screen->driver;
501706f2543Smrg  Bool		wasEnabled = pScreenPriv->enabled;
502706f2543Smrg  EphyrScrPriv	oldscr;
503706f2543Smrg  int		oldwidth, oldheight, oldmmwidth, oldmmheight;
504706f2543Smrg  Bool          oldshadow;
505706f2543Smrg  int		newwidth, newheight;
506706f2543Smrg
507706f2543Smrg  if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
508706f2543Smrg    {
509706f2543Smrg      newwidth = pSize->width;
510706f2543Smrg      newheight = pSize->height;
511706f2543Smrg    }
512706f2543Smrg  else
513706f2543Smrg    {
514706f2543Smrg      newwidth = pSize->height;
515706f2543Smrg      newheight = pSize->width;
516706f2543Smrg    }
517706f2543Smrg
518706f2543Smrg  if (wasEnabled)
519706f2543Smrg    KdDisableScreen (pScreen);
520706f2543Smrg
521706f2543Smrg  oldscr = *scrpriv;
522706f2543Smrg
523706f2543Smrg  oldwidth    = screen->width;
524706f2543Smrg  oldheight   = screen->height;
525706f2543Smrg  oldmmwidth  = pScreen->mmWidth;
526706f2543Smrg  oldmmheight = pScreen->mmHeight;
527706f2543Smrg  oldshadow   = scrpriv->shadow;
528706f2543Smrg
529706f2543Smrg  /*
530706f2543Smrg   * Set new configuration
531706f2543Smrg   */
532706f2543Smrg
533706f2543Smrg  scrpriv->randr = KdAddRotation (screen->randr, randr);
534706f2543Smrg
535706f2543Smrg  ephyrUnmapFramebuffer (screen);
536706f2543Smrg
537706f2543Smrg  screen->width  = newwidth;
538706f2543Smrg  screen->height = newheight;
539706f2543Smrg
540706f2543Smrg  if (!ephyrMapFramebuffer (screen))
541706f2543Smrg    goto bail4;
542706f2543Smrg
543706f2543Smrg  /* FIXME below should go in own call */
544706f2543Smrg
545706f2543Smrg  if (oldshadow)
546706f2543Smrg    KdShadowUnset (screen->pScreen);
547706f2543Smrg  else
548706f2543Smrg    ephyrUnsetInternalDamage(screen->pScreen);
549706f2543Smrg
550706f2543Smrg  if (scrpriv->shadow)
551706f2543Smrg    {
552706f2543Smrg      if (!KdShadowSet (screen->pScreen,
553706f2543Smrg			scrpriv->randr,
554706f2543Smrg			ephyrShadowUpdate,
555706f2543Smrg			ephyrWindowLinear))
556706f2543Smrg	goto bail4;
557706f2543Smrg    }
558706f2543Smrg  else
559706f2543Smrg    {
560706f2543Smrg      /* Without shadow fb ( non rotated ) we need
561706f2543Smrg       * to use damage to efficiently update display
562706f2543Smrg       * via signal regions what to copy from 'fb'.
563706f2543Smrg       */
564706f2543Smrg      if (!ephyrSetInternalDamage(screen->pScreen))
565706f2543Smrg	goto bail4;
566706f2543Smrg    }
567706f2543Smrg
568706f2543Smrg  ephyrSetScreenSizes (screen->pScreen);
569706f2543Smrg
570706f2543Smrg  /*
571706f2543Smrg   * Set frame buffer mapping
572706f2543Smrg   */
573706f2543Smrg  (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
574706f2543Smrg				  pScreen->width,
575706f2543Smrg				  pScreen->height,
576706f2543Smrg				  screen->fb.depth,
577706f2543Smrg				  screen->fb.bitsPerPixel,
578706f2543Smrg				  screen->fb.byteStride,
579706f2543Smrg				  screen->fb.frameBuffer);
580706f2543Smrg
581706f2543Smrg  /* set the subpixel order */
582706f2543Smrg
583706f2543Smrg  KdSetSubpixelOrder (pScreen, scrpriv->randr);
584706f2543Smrg
585706f2543Smrg  if (wasEnabled)
586706f2543Smrg    KdEnableScreen (pScreen);
587706f2543Smrg
588706f2543Smrg  return TRUE;
589706f2543Smrg
590706f2543Smrg bail4:
591706f2543Smrg  EPHYR_LOG("bailed");
592706f2543Smrg
593706f2543Smrg  ephyrUnmapFramebuffer (screen);
594706f2543Smrg  *scrpriv = oldscr;
595706f2543Smrg  (void) ephyrMapFramebuffer (screen);
596706f2543Smrg
597706f2543Smrg  pScreen->width = oldwidth;
598706f2543Smrg  pScreen->height = oldheight;
599706f2543Smrg  pScreen->mmWidth = oldmmwidth;
600706f2543Smrg  pScreen->mmHeight = oldmmheight;
601706f2543Smrg
602706f2543Smrg  if (wasEnabled)
603706f2543Smrg    KdEnableScreen (pScreen);
604706f2543Smrg  return FALSE;
605706f2543Smrg}
606706f2543Smrg
607706f2543SmrgBool
608706f2543SmrgephyrRandRInit (ScreenPtr pScreen)
609706f2543Smrg{
610706f2543Smrg  rrScrPrivPtr    pScrPriv;
611706f2543Smrg
612706f2543Smrg  if (!RRScreenInit (pScreen))
613706f2543Smrg    return FALSE;
614706f2543Smrg
615706f2543Smrg  pScrPriv = rrGetScrPriv(pScreen);
616706f2543Smrg  pScrPriv->rrGetInfo = ephyrRandRGetInfo;
617706f2543Smrg  pScrPriv->rrSetConfig = ephyrRandRSetConfig;
618706f2543Smrg  return TRUE;
619706f2543Smrg}
620706f2543Smrg#endif
621706f2543Smrg
622706f2543SmrgBool
623706f2543SmrgephyrCreateColormap (ColormapPtr pmap)
624706f2543Smrg{
625706f2543Smrg  return fbInitializeColormap (pmap);
626706f2543Smrg}
627706f2543Smrg
628706f2543SmrgBool
629706f2543SmrgephyrInitScreen (ScreenPtr pScreen)
630706f2543Smrg{
631706f2543Smrg  KdScreenPriv(pScreen);
632706f2543Smrg  KdScreenInfo	*screen    = pScreenPriv->screen;
633706f2543Smrg
634706f2543Smrg  EPHYR_LOG ("pScreen->myNum:%d\n", pScreen->myNum) ;
635706f2543Smrg  hostx_set_screen_number (screen, pScreen->myNum);
636706f2543Smrg  hostx_set_win_title (screen, "(ctrl+shift grabs mouse and keyboard)") ;
637706f2543Smrg  pScreen->CreateColormap = ephyrCreateColormap;
638706f2543Smrg
639706f2543Smrg#ifdef XV
640706f2543Smrg  if (!ephyrNoXV) {
641706f2543Smrg      if (!ephyrInitVideo (pScreen)) {
642706f2543Smrg          EPHYR_LOG_ERROR ("failed to initialize xvideo\n") ;
643706f2543Smrg      } else {
644706f2543Smrg          EPHYR_LOG ("initialized xvideo okay\n") ;
645706f2543Smrg      }
646706f2543Smrg  }
647706f2543Smrg#endif /*XV*/
648706f2543Smrg
649706f2543Smrg#ifdef XF86DRI
650706f2543Smrg  if (!ephyrNoDRI && !hostx_has_dri ()) {
651706f2543Smrg      EPHYR_LOG ("host x does not support DRI. Disabling DRI forwarding\n") ;
652706f2543Smrg      ephyrNoDRI = TRUE ;
653706f2543Smrg#ifdef GLXEXT
654706f2543Smrg      noGlxVisualInit = FALSE ;
655706f2543Smrg#endif
656706f2543Smrg  }
657706f2543Smrg  if (!ephyrNoDRI) {
658706f2543Smrg    ephyrDRIExtensionInit (pScreen) ;
659706f2543Smrg    ephyrHijackGLXExtension () ;
660706f2543Smrg  }
661706f2543Smrg#endif
662706f2543Smrg
663706f2543Smrg#ifdef GLXEXT
664706f2543Smrg  if (ephyrNoDRI) {
665706f2543Smrg      noGlxVisualInit = FALSE ;
666706f2543Smrg  }
667706f2543Smrg#endif
668706f2543Smrg
669706f2543Smrg  return TRUE;
670706f2543Smrg}
671706f2543Smrg
672706f2543SmrgBool
673706f2543SmrgephyrFinishInitScreen (ScreenPtr pScreen)
674706f2543Smrg{
675706f2543Smrg  /* FIXME: Calling this even if not using shadow.
676706f2543Smrg   * Seems harmless enough. But may be safer elsewhere.
677706f2543Smrg   */
678706f2543Smrg  if (!shadowSetup (pScreen))
679706f2543Smrg    return FALSE;
680706f2543Smrg
681706f2543Smrg#ifdef RANDR
682706f2543Smrg  if (!ephyrRandRInit (pScreen))
683706f2543Smrg    return FALSE;
684706f2543Smrg#endif
685706f2543Smrg
686706f2543Smrg  return TRUE;
687706f2543Smrg}
688706f2543Smrg
689706f2543SmrgBool
690706f2543SmrgephyrCreateResources (ScreenPtr pScreen)
691706f2543Smrg{
692706f2543Smrg  KdScreenPriv(pScreen);
693706f2543Smrg  KdScreenInfo	*screen    = pScreenPriv->screen;
694706f2543Smrg  EphyrScrPriv	*scrpriv   = screen->driver;
695706f2543Smrg
696706f2543Smrg  EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d",
697706f2543Smrg            pScreen, pScreen->myNum, scrpriv->shadow);
698706f2543Smrg
699706f2543Smrg  if (scrpriv->shadow)
700706f2543Smrg    return KdShadowSet (pScreen,
701706f2543Smrg			scrpriv->randr,
702706f2543Smrg			ephyrShadowUpdate,
703706f2543Smrg			ephyrWindowLinear);
704706f2543Smrg  else
705706f2543Smrg    return ephyrSetInternalDamage(pScreen);
706706f2543Smrg}
707706f2543Smrg
708706f2543Smrgvoid
709706f2543SmrgephyrPreserve (KdCardInfo *card)
710706f2543Smrg{
711706f2543Smrg}
712706f2543Smrg
713706f2543SmrgBool
714706f2543SmrgephyrEnable (ScreenPtr pScreen)
715706f2543Smrg{
716706f2543Smrg  return TRUE;
717706f2543Smrg}
718706f2543Smrg
719706f2543SmrgBool
720706f2543SmrgephyrDPMS (ScreenPtr pScreen, int mode)
721706f2543Smrg{
722706f2543Smrg  return TRUE;
723706f2543Smrg}
724706f2543Smrg
725706f2543Smrgvoid
726706f2543SmrgephyrDisable (ScreenPtr pScreen)
727706f2543Smrg{
728706f2543Smrg}
729706f2543Smrg
730706f2543Smrgvoid
731706f2543SmrgephyrRestore (KdCardInfo *card)
732706f2543Smrg{
733706f2543Smrg}
734706f2543Smrg
735706f2543Smrgvoid
736706f2543SmrgephyrScreenFini (KdScreenInfo *screen)
737706f2543Smrg{
738706f2543Smrg    EphyrScrPriv  *scrpriv = screen->driver;
739706f2543Smrg    if (scrpriv->shadow) {
740706f2543Smrg        KdShadowFbFree (screen);
741706f2543Smrg    }
742706f2543Smrg    free(screen->driver);
743706f2543Smrg    screen->driver = NULL;
744706f2543Smrg}
745706f2543Smrg
746706f2543Smrg/*
747706f2543Smrg * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug.
748706f2543Smrg * See https://bugs.freedesktop.org/show_bug.cgi?id=3030
749706f2543Smrg */
750706f2543Smrgvoid
751706f2543SmrgephyrUpdateModifierState(unsigned int state)
752706f2543Smrg{
753706f2543Smrg
754706f2543Smrg  DeviceIntPtr pDev = inputInfo.keyboard;
755706f2543Smrg  KeyClassPtr keyc = pDev->key;
756706f2543Smrg  int i;
757706f2543Smrg  CARD8 mask;
758706f2543Smrg  int xkb_state;
759706f2543Smrg
760706f2543Smrg  if (!pDev)
761706f2543Smrg      return;
762706f2543Smrg
763706f2543Smrg  xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state);
764706f2543Smrg  state = state & 0xff;
765706f2543Smrg
766706f2543Smrg  if (xkb_state == state)
767706f2543Smrg    return;
768706f2543Smrg
769706f2543Smrg  for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
770706f2543Smrg    int key;
771706f2543Smrg
772706f2543Smrg    /* Modifier is down, but shouldn't be
773706f2543Smrg     */
774706f2543Smrg    if ((xkb_state & mask) && !(state & mask)) {
775706f2543Smrg      int count = keyc->modifierKeyCount[i];
776706f2543Smrg
777706f2543Smrg      for (key = 0; key < MAP_LENGTH; key++)
778706f2543Smrg        if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
779706f2543Smrg          if (key_is_down(pDev, key, KEY_PROCESSED))
780706f2543Smrg	        KdEnqueueKeyboardEvent (ephyrKbd, key, TRUE);
781706f2543Smrg
782706f2543Smrg          if (--count == 0)
783706f2543Smrg            break;
784706f2543Smrg        }
785706f2543Smrg    }
786706f2543Smrg
787706f2543Smrg    /* Modifier shoud be down, but isn't
788706f2543Smrg     */
789706f2543Smrg    if (!(xkb_state & mask) && (state & mask))
790706f2543Smrg      for (key = 0; key < MAP_LENGTH; key++)
791706f2543Smrg        if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
792706f2543Smrg	        KdEnqueueKeyboardEvent (ephyrKbd, key, FALSE);
793706f2543Smrg          break;
794706f2543Smrg        }
795706f2543Smrg  }
796706f2543Smrg}
797706f2543Smrg
798706f2543Smrgstatic void
799706f2543SmrgephyrBlockSigio (void)
800706f2543Smrg{
801706f2543Smrg    sigset_t set;
802706f2543Smrg
803706f2543Smrg    sigemptyset (&set);
804706f2543Smrg    sigaddset (&set, SIGIO);
805706f2543Smrg    sigprocmask (SIG_BLOCK, &set, 0);
806706f2543Smrg}
807706f2543Smrg
808706f2543Smrgstatic void
809706f2543SmrgephyrUnblockSigio (void)
810706f2543Smrg{
811706f2543Smrg    sigset_t set;
812706f2543Smrg
813706f2543Smrg    sigemptyset (&set);
814706f2543Smrg    sigaddset (&set, SIGIO);
815706f2543Smrg    sigprocmask (SIG_UNBLOCK, &set, 0);
816706f2543Smrg}
817706f2543Smrg
818706f2543Smrgstatic Bool
819706f2543SmrgephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
820706f2543Smrg{
821706f2543Smrg  return FALSE;
822706f2543Smrg}
823706f2543Smrg
824706f2543Smrgstatic void
825706f2543SmrgephyrCrossScreen (ScreenPtr pScreen, Bool entering)
826706f2543Smrg{
827706f2543Smrg}
828706f2543Smrg
829706f2543Smrgint ephyrCurScreen; /*current event screen*/
830706f2543Smrg
831706f2543Smrgstatic void
832706f2543SmrgephyrWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
833706f2543Smrg{
834706f2543Smrg    ephyrBlockSigio ();
835706f2543Smrg    ephyrCurScreen = pScreen->myNum;
836706f2543Smrg    miPointerWarpCursor (inputInfo.pointer, pScreen, x, y);
837706f2543Smrg    ephyrUnblockSigio ();
838706f2543Smrg}
839706f2543Smrg
840706f2543SmrgmiPointerScreenFuncRec ephyrPointerScreenFuncs =
841706f2543Smrg{
842706f2543Smrg  ephyrCursorOffScreen,
843706f2543Smrg  ephyrCrossScreen,
844706f2543Smrg  ephyrWarpCursor,
845706f2543Smrg  NULL,
846706f2543Smrg  NULL
847706f2543Smrg};
848706f2543Smrg
849706f2543Smrg#ifdef XF86DRI
850706f2543Smrg/**
851706f2543Smrg * find if the remote window denoted by a_remote
852706f2543Smrg * is paired with an internal Window within the Xephyr server.
853706f2543Smrg * If the remove window is paired with an internal window, send an
854706f2543Smrg * expose event to the client insterested in the internal window expose event.
855706f2543Smrg *
856706f2543Smrg * Pairing happens when a drawable inside Xephyr is associated with
857706f2543Smrg * a GL surface in a DRI environment.
858706f2543Smrg * Look at the function ProcXF86DRICreateDrawable in ephyrdriext.c to
859706f2543Smrg * know a paired window is created.
860706f2543Smrg *
861706f2543Smrg * This is useful to make GL drawables (only windows for now) handle
862706f2543Smrg * expose events and send those events to clients.
863706f2543Smrg */
864706f2543Smrgstatic void
865706f2543SmrgephyrExposePairedWindow (int a_remote)
866706f2543Smrg{
867706f2543Smrg    EphyrWindowPair *pair = NULL;
868706f2543Smrg    RegionRec reg;
869706f2543Smrg    ScreenPtr screen;
870706f2543Smrg
871706f2543Smrg    if (!findWindowPairFromRemote (a_remote, &pair)) {
872706f2543Smrg	EPHYR_LOG ("did not find a pair for this window\n");
873706f2543Smrg	return;
874706f2543Smrg    }
875706f2543Smrg    screen = pair->local->drawable.pScreen;
876706f2543Smrg    RegionNull(&reg);
877706f2543Smrg    RegionCopy(&reg, &pair->local->clipList);
878706f2543Smrg    screen->WindowExposures (pair->local, &reg, NullRegion);
879706f2543Smrg    RegionUninit(&reg);
880706f2543Smrg}
881706f2543Smrg#endif /* XF86DRI */
882706f2543Smrg
883706f2543Smrgvoid
884706f2543SmrgephyrPoll(void)
885706f2543Smrg{
886706f2543Smrg  EphyrHostXEvent ev;
887706f2543Smrg
888706f2543Smrg  while (hostx_get_event(&ev))
889706f2543Smrg    {
890706f2543Smrg      switch (ev.type)
891706f2543Smrg        {
892706f2543Smrg        case EPHYR_EV_MOUSE_MOTION:
893706f2543Smrg          if (!ephyrMouse ||
894706f2543Smrg              !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) {
895706f2543Smrg              EPHYR_LOG ("skipping mouse motion:%d\n", ephyrCurScreen) ;
896706f2543Smrg              continue;
897706f2543Smrg          }
898706f2543Smrg          {
899706f2543Smrg            if (ev.data.mouse_motion.screen >=0
900706f2543Smrg                && (ephyrCurScreen != ev.data.mouse_motion.screen))
901706f2543Smrg              {
902706f2543Smrg                  EPHYR_LOG ("warping mouse cursor. "
903706f2543Smrg                             "cur_screen%d, motion_screen:%d\n",
904706f2543Smrg                             ephyrCurScreen, ev.data.mouse_motion.screen) ;
905706f2543Smrg                  if (ev.data.mouse_motion.screen >= 0)
906706f2543Smrg                    {
907706f2543Smrg                      ephyrWarpCursor
908706f2543Smrg                            (inputInfo.pointer, screenInfo.screens[ev.data.mouse_motion.screen],
909706f2543Smrg                             ev.data.mouse_motion.x,
910706f2543Smrg                             ev.data.mouse_motion.y );
911706f2543Smrg                    }
912706f2543Smrg              }
913706f2543Smrg            else
914706f2543Smrg              {
915706f2543Smrg                  int x=0, y=0;
916706f2543Smrg#ifdef XF86DRI
917706f2543Smrg                  EphyrWindowPair *pair = NULL;
918706f2543Smrg#endif
919706f2543Smrg                  EPHYR_LOG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ;
920706f2543Smrg                  x = ev.data.mouse_motion.x;
921706f2543Smrg                  y = ev.data.mouse_motion.y;
922706f2543Smrg                  EPHYR_LOG ("initial (x,y):(%d,%d)\n", x, y) ;
923706f2543Smrg#ifdef XF86DRI
924706f2543Smrg                  EPHYR_LOG ("is this window peered by a gl drawable ?\n") ;
925706f2543Smrg                  if (findWindowPairFromRemote (ev.data.mouse_motion.window,
926706f2543Smrg                                                &pair))
927706f2543Smrg                    {
928706f2543Smrg                        EPHYR_LOG ("yes, it is peered\n") ;
929706f2543Smrg                        x += pair->local->drawable.x;
930706f2543Smrg                        y += pair->local->drawable.y;
931706f2543Smrg                    }
932706f2543Smrg                  else
933706f2543Smrg                    {
934706f2543Smrg                        EPHYR_LOG ("no, it is not peered\n") ;
935706f2543Smrg                    }
936706f2543Smrg                  EPHYR_LOG ("final (x,y):(%d,%d)\n", x, y) ;
937706f2543Smrg#endif
938706f2543Smrg                  KdEnqueuePointerEvent(ephyrMouse, mouseState, x, y, 0);
939706f2543Smrg              }
940706f2543Smrg          }
941706f2543Smrg          break;
942706f2543Smrg
943706f2543Smrg        case EPHYR_EV_MOUSE_PRESS:
944706f2543Smrg          if (!ephyrMouse ||
945706f2543Smrg              !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) {
946706f2543Smrg              EPHYR_LOG ("skipping mouse press:%d\n", ephyrCurScreen) ;
947706f2543Smrg              continue;
948706f2543Smrg          }
949706f2543Smrg          EPHYR_LOG ("enqueuing mouse press:%d\n", ephyrCurScreen) ;
950706f2543Smrg	  ephyrUpdateModifierState(ev.key_state);
951706f2543Smrg	  mouseState |= ev.data.mouse_down.button_num;
952706f2543Smrg	  KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0);
953706f2543Smrg	  break;
954706f2543Smrg
955706f2543Smrg	case EPHYR_EV_MOUSE_RELEASE:
956706f2543Smrg          if (!ephyrMouse ||
957706f2543Smrg              !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled)
958706f2543Smrg              continue;
959706f2543Smrg	  ephyrUpdateModifierState(ev.key_state);
960706f2543Smrg	  mouseState &= ~ev.data.mouse_up.button_num;
961706f2543Smrg          EPHYR_LOG ("enqueuing mouse release:%d\n", ephyrCurScreen) ;
962706f2543Smrg	  KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0);
963706f2543Smrg	  break;
964706f2543Smrg
965706f2543Smrg	case EPHYR_EV_KEY_PRESS:
966706f2543Smrg          if (!ephyrKbd ||
967706f2543Smrg              !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled)
968706f2543Smrg              continue;
969706f2543Smrg	  ephyrUpdateModifierState(ev.key_state);
970706f2543Smrg	  KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_down.scancode, FALSE);
971706f2543Smrg	  break;
972706f2543Smrg
973706f2543Smrg	case EPHYR_EV_KEY_RELEASE:
974706f2543Smrg          if (!ephyrKbd ||
975706f2543Smrg              !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled)
976706f2543Smrg              continue;
977706f2543Smrg	  ephyrUpdateModifierState(ev.key_state);
978706f2543Smrg	  KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE);
979706f2543Smrg	  break;
980706f2543Smrg
981706f2543Smrg#ifdef XF86DRI
982706f2543Smrg	case EPHYR_EV_EXPOSE:
983706f2543Smrg	  /*
984706f2543Smrg	   * We only receive expose events when the expose event have
985706f2543Smrg	   * be generated for a drawable that is a host X window managed
986706f2543Smrg	   * by Xephyr. Host X windows managed by Xephyr exists for instance
987706f2543Smrg	   * when Xephyr is asked to create a GL drawable in a DRI environment.
988706f2543Smrg	   */
989706f2543Smrg	  ephyrExposePairedWindow (ev.data.expose.window);
990706f2543Smrg	  break;
991706f2543Smrg#endif /* XF86DRI */
992706f2543Smrg
993706f2543Smrg	default:
994706f2543Smrg	  break;
995706f2543Smrg	}
996706f2543Smrg    }
997706f2543Smrg}
998706f2543Smrg
999706f2543Smrgvoid
1000706f2543SmrgephyrCardFini (KdCardInfo *card)
1001706f2543Smrg{
1002706f2543Smrg  EphyrPriv	*priv = card->driver;
1003706f2543Smrg  free(priv);
1004706f2543Smrg}
1005706f2543Smrg
1006706f2543Smrgvoid
1007706f2543SmrgephyrGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
1008706f2543Smrg{
1009706f2543Smrg  /* XXX Not sure if this is right */
1010706f2543Smrg
1011706f2543Smrg  EPHYR_LOG("mark");
1012706f2543Smrg
1013706f2543Smrg  while (n--)
1014706f2543Smrg    {
1015706f2543Smrg      pdefs->red = 0;
1016706f2543Smrg      pdefs->green = 0;
1017706f2543Smrg      pdefs->blue = 0;
1018706f2543Smrg      pdefs++;
1019706f2543Smrg    }
1020706f2543Smrg
1021706f2543Smrg}
1022706f2543Smrg
1023706f2543Smrgvoid
1024706f2543SmrgephyrPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
1025706f2543Smrg{
1026706f2543Smrg  int min, max, p;
1027706f2543Smrg
1028706f2543Smrg  /* XXX Not sure if this is right */
1029706f2543Smrg
1030706f2543Smrg  min = 256;
1031706f2543Smrg  max = 0;
1032706f2543Smrg
1033706f2543Smrg  while (n--)
1034706f2543Smrg    {
1035706f2543Smrg      p = pdefs->pixel;
1036706f2543Smrg      if (p < min)
1037706f2543Smrg	min = p;
1038706f2543Smrg      if (p > max)
1039706f2543Smrg	max = p;
1040706f2543Smrg
1041706f2543Smrg      hostx_set_cmap_entry(p,
1042706f2543Smrg			   pdefs->red >> 8,
1043706f2543Smrg			   pdefs->green >> 8,
1044706f2543Smrg			   pdefs->blue >> 8);
1045706f2543Smrg      pdefs++;
1046706f2543Smrg    }
1047706f2543Smrg}
1048706f2543Smrg
1049706f2543Smrg/* Mouse calls */
1050706f2543Smrg
1051706f2543Smrgstatic Status
1052706f2543SmrgMouseInit (KdPointerInfo *pi)
1053706f2543Smrg{
1054706f2543Smrg    pi->driverPrivate = (EphyrPointerPrivate *)
1055706f2543Smrg                         calloc(sizeof(EphyrPointerPrivate), 1);
1056706f2543Smrg    ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE;
1057706f2543Smrg    pi->nAxes = 3;
1058706f2543Smrg    pi->nButtons = 32;
1059706f2543Smrg    free(pi->name);
1060706f2543Smrg    pi->name = strdup("Xephyr virtual mouse");
1061706f2543Smrg    ephyrMouse = pi;
1062706f2543Smrg    return Success;
1063706f2543Smrg}
1064706f2543Smrg
1065706f2543Smrgstatic Status
1066706f2543SmrgMouseEnable (KdPointerInfo *pi)
1067706f2543Smrg{
1068706f2543Smrg    ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = TRUE;
1069706f2543Smrg    return Success;
1070706f2543Smrg}
1071706f2543Smrg
1072706f2543Smrgstatic void
1073706f2543SmrgMouseDisable (KdPointerInfo *pi)
1074706f2543Smrg{
1075706f2543Smrg    ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE;
1076706f2543Smrg    return;
1077706f2543Smrg}
1078706f2543Smrg
1079706f2543Smrgstatic void
1080706f2543SmrgMouseFini (KdPointerInfo *pi)
1081706f2543Smrg{
1082706f2543Smrg    ephyrMouse = NULL;
1083706f2543Smrg    return;
1084706f2543Smrg}
1085706f2543Smrg
1086706f2543SmrgKdPointerDriver EphyrMouseDriver = {
1087706f2543Smrg    "ephyr",
1088706f2543Smrg    MouseInit,
1089706f2543Smrg    MouseEnable,
1090706f2543Smrg    MouseDisable,
1091706f2543Smrg    MouseFini,
1092706f2543Smrg    NULL,
1093706f2543Smrg};
1094706f2543Smrg
1095706f2543Smrg/* Keyboard */
1096706f2543Smrg
1097706f2543Smrgstatic Status
1098706f2543SmrgEphyrKeyboardInit (KdKeyboardInfo *ki)
1099706f2543Smrg{
1100706f2543Smrg  ki->driverPrivate = (EphyrKbdPrivate *)
1101706f2543Smrg                       calloc(sizeof(EphyrKbdPrivate), 1);
1102706f2543Smrg  hostx_load_keymap();
1103706f2543Smrg  if (!ephyrKeySyms.map) {
1104706f2543Smrg      ErrorF("Couldn't load keymap from host\n");
1105706f2543Smrg      return BadAlloc;
1106706f2543Smrg  }
1107706f2543Smrg  ki->minScanCode = ephyrKeySyms.minKeyCode;
1108706f2543Smrg  ki->maxScanCode = ephyrKeySyms.maxKeyCode;
1109706f2543Smrg  free(ki->name);
1110706f2543Smrg  ki->name = strdup("Xephyr virtual keyboard");
1111706f2543Smrg  ephyrKbd = ki;
1112706f2543Smrg  return Success;
1113706f2543Smrg}
1114706f2543Smrg
1115706f2543Smrgstatic Status
1116706f2543SmrgEphyrKeyboardEnable (KdKeyboardInfo *ki)
1117706f2543Smrg{
1118706f2543Smrg    ((EphyrKbdPrivate *)ki->driverPrivate)->enabled = TRUE;
1119706f2543Smrg
1120706f2543Smrg    return Success;
1121706f2543Smrg}
1122706f2543Smrg
1123706f2543Smrgstatic void
1124706f2543SmrgEphyrKeyboardDisable (KdKeyboardInfo *ki)
1125706f2543Smrg{
1126706f2543Smrg    ((EphyrKbdPrivate *)ki->driverPrivate)->enabled = FALSE;
1127706f2543Smrg}
1128706f2543Smrg
1129706f2543Smrgstatic void
1130706f2543SmrgEphyrKeyboardFini (KdKeyboardInfo *ki)
1131706f2543Smrg{
1132706f2543Smrg    ephyrKbd = NULL;
1133706f2543Smrg    return;
1134706f2543Smrg}
1135706f2543Smrg
1136706f2543Smrgstatic void
1137706f2543SmrgEphyrKeyboardLeds (KdKeyboardInfo *ki, int leds)
1138706f2543Smrg{
1139706f2543Smrg}
1140706f2543Smrg
1141706f2543Smrgstatic void
1142706f2543SmrgEphyrKeyboardBell (KdKeyboardInfo *ki, int volume, int frequency, int duration)
1143706f2543Smrg{
1144706f2543Smrg}
1145706f2543Smrg
1146706f2543Smrg
1147706f2543SmrgKdKeyboardDriver EphyrKeyboardDriver = {
1148706f2543Smrg    "ephyr",
1149706f2543Smrg    EphyrKeyboardInit,
1150706f2543Smrg    EphyrKeyboardEnable,
1151706f2543Smrg    EphyrKeyboardLeds,
1152706f2543Smrg    EphyrKeyboardBell,
1153706f2543Smrg    EphyrKeyboardDisable,
1154706f2543Smrg    EphyrKeyboardFini,
1155706f2543Smrg    NULL,
1156706f2543Smrg};
1157