xserver: Branch 'master' - 2 commits

Dodji Seketeli dodji at kemper.freedesktop.org
Tue Oct 2 04:52:43 PDT 2007


 dix/events.c                |   55 +++
 hw/kdrive/ephyr/ephyr.c     |  164 +++++++----
 hw/kdrive/ephyr/ephyr.h     |    2 
 hw/kdrive/ephyr/ephyrinit.c |   59 +++
 hw/kdrive/ephyr/hostx.c     |  654 +++++++++++++++++++++++++++-----------------
 hw/kdrive/ephyr/hostx.h     |   39 +-
 hw/kdrive/ephyr/os.c        |    8 
 include/dix.h               |    3 
 mi/mipointer.c              |    1 
 9 files changed, 669 insertions(+), 316 deletions(-)

New commits:
diff-tree e5e6514ffa0fd132e0cc1b15b94119e6e8755f43 (from 81692b628f41cb64329f3cccc0503fb216a2b8e3)
Author: Andrew Christan <andrew.christian at nokia.com>
Date:   Tue Oct 2 13:25:51 2007 +0200

    Xephyr: add "multiscreen" suport
    
    	* This patch adds multiscreen support to Xephyr. For instance,
    	  the command line : "Xephyr :4 -ac -screen 320x240 -screen 640x480"
    	  will launch with two "screens" - namely two main windows.
    	  The first main window represents a screen that has the number :4.0, with
    	  a geometry of 320x240 pixels, and the second one represents a screen
    	  that has the number :4.1 with a geometry of 640x480.
    	  The command line: "DISPLAY=:4.1 xclock" will launch the xclock program
    	  on the second screen, for intance.
    
    	*   this patch was edited by Dodji Seketeli <dodji at openedhand.com> for:
    	  - better style compliance with the rest of the Xephyr code
    	  - make sure Xephyr could be launched with no -screen option. By
    	    default that creates a default screen of 640x480 pixel like before
    	  - display full titles on the windows - with insctructions to grab
    	    keyboard and mouse - like before.

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index e8001df..c5cb21a 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -34,6 +34,7 @@
 #include "ephyr.h"
 
 #include "inputstr.h"
+#include "scrnintstr.h"
 
 extern int KdTsPhyScreen;
 KdKeyboardInfo *ephyrKbd;
@@ -83,7 +84,7 @@ ephyrScreenInitialize (KdScreenInfo *scr
   int width = 640, height = 480; 
   unsigned long redMask, greenMask, blueMask;
   
-  if (hostx_want_screen_size(&width, &height) 
+  if (hostx_want_screen_size(screen, &width, &height)
       || !screen->width || !screen->height)
     {
       screen->width = width;
@@ -99,13 +100,13 @@ ephyrScreenInitialize (KdScreenInfo *scr
 	  && (screen->fb[0].depth == 24 || screen->fb[0].depth == 16
 	      || screen->fb[0].depth == 8))
 	{
-	  hostx_set_server_depth(screen->fb[0].depth);
+	  hostx_set_server_depth(screen, screen->fb[0].depth);
 	}
-      else 
+      else
 	ErrorF("\nXephyr: requested screen depth not supported, setting to match hosts.\n");
     }
   
-  screen->fb[0].depth = hostx_get_server_depth();
+  screen->fb[0].depth = hostx_get_server_depth(screen);
   screen->rate = 72;
   
   if (screen->fb[0].depth <= 8)
@@ -146,7 +147,7 @@ ephyrScreenInitialize (KdScreenInfo *scr
 	  screen->fb[0].bitsPerPixel = 32;
 	}
 
-      hostx_get_visual_masks (&redMask, &greenMask, &blueMask);
+      hostx_get_visual_masks (screen, &redMask, &greenMask, &blueMask);
 
       screen->fb[0].redMask = (Pixel) redMask;
       screen->fb[0].greenMask = (Pixel) greenMask;
@@ -194,9 +195,7 @@ ephyrWindowLinear (ScreenPtr	pScreen,
   EphyrPriv	    *priv = pScreenPriv->card->driver;
   
   if (!pScreenPriv->enabled)
-    {
-      return 0;
-    }
+    return 0;
 
   *size = priv->bytes_per_line;
   return priv->base + row * priv->bytes_per_line + offset;
@@ -210,8 +209,8 @@ ephyrMapFramebuffer (KdScreenInfo *scree
   KdPointerMatrix m;
   int buffer_height;
   
-  EPHYR_DBG(" screen->width: %d, screen->height: %d",
-	    screen->width, screen->height);
+  EPHYR_DBG("screen->width: %d, screen->height: %d index=%d",
+	     screen->width, screen->height, screen->mynum);
   
   KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height);
   KdSetPointerMatrix (&m);
@@ -226,8 +225,8 @@ ephyrMapFramebuffer (KdScreenInfo *scree
     buffer_height = screen->height;
   else
     buffer_height = 3 * screen->height;
-  
-  priv->base = hostx_screen_init (screen->width, screen->height, buffer_height);
+
+  priv->base = hostx_screen_init (screen, screen->width, screen->height, buffer_height);
 
   screen->memory_base  = (CARD8 *) (priv->base);
   screen->memory_size  = priv->bytes_per_line * buffer_height;
@@ -304,7 +303,7 @@ ephyrShadowUpdate (ScreenPtr pScreen, sh
    * pBuf->pDamage  regions     
   */
   shadowUpdateRotatePacked(pScreen, pBuf);
-  hostx_paint_rect(0,0,0,0, screen->width, screen->height);
+  hostx_paint_rect(screen, 0,0,0,0, screen->width, screen->height);
 }
 
 static void
@@ -314,29 +313,29 @@ ephyrInternalDamageRedisplay (ScreenPtr 
   KdScreenInfo	*screen = pScreenPriv->screen;
   EphyrScrPriv	*scrpriv = screen->driver;
   RegionPtr	 pRegion;
-  
+
   if (!scrpriv || !scrpriv->pDamage)
     return;
-  
+
   pRegion = DamageRegion (scrpriv->pDamage);
-  
+
   if (REGION_NOTEMPTY (pScreen, pRegion))
     {
       int           nbox;
       BoxPtr        pbox;
-      
+
       nbox = REGION_NUM_RECTS (pRegion);
       pbox = REGION_RECTS (pRegion);
-      
+
       while (nbox--)
-	{
-	  hostx_paint_rect(pbox->x1, pbox->y1,
-			   pbox->x1, pbox->y1,
-			   pbox->x2 - pbox->x1,
-			   pbox->y2 - pbox->y1);
-	  pbox++;
-	}
-      
+        {
+          hostx_paint_rect(screen,
+                           pbox->x1, pbox->y1,
+                           pbox->x1, pbox->y1,
+                           pbox->x2 - pbox->x1,
+                           pbox->y2 - pbox->y1);
+          pbox++;
+        }
       DamageEmpty (scrpriv->pDamage);
     }
 }
@@ -432,11 +431,11 @@ ephyrRandRGetInfo (ScreenPtr pScreen, Ro
       { 160, 160 }, 
       { 0, 0 }
     };
-  
+
   *rotations = RR_Rotate_All|RR_Reflect_All;
-  
-  if (!hostx_want_preexisting_window()
-      && !hostx_want_fullscreen()) /* only if no -parent switch */
+
+  if (!hostx_want_preexisting_window (screen)
+      && !hostx_want_fullscreen ()) /* only if no -parent switch */
     {
       while (sizes[n].width != 0 && sizes[n].height != 0)
 	{
@@ -586,9 +585,7 @@ ephyrRandRInit (ScreenPtr pScreen)
   rrScrPrivPtr    pScrPriv;
   
   if (!RRScreenInit (pScreen))
-    {
-      return FALSE;
-    }
+    return FALSE;
   
   pScrPriv = rrGetScrPriv(pScreen);
   pScrPriv->rrGetInfo = ephyrRandRGetInfo;
@@ -606,6 +603,12 @@ ephyrCreateColormap (ColormapPtr pmap)
 Bool
 ephyrInitScreen (ScreenPtr pScreen)
 {
+  KdScreenPriv(pScreen);
+  KdScreenInfo	*screen    = pScreenPriv->screen;
+
+  EPHYR_DBG ("pScreen->myNum:%d\n", pScreen->myNum) ;
+  hostx_set_screen_number (screen, pScreen->myNum);
+  hostx_set_win_title (screen, "(ctrl+shift grabs mouse and keyboard)") ;
   pScreen->CreateColormap = ephyrCreateColormap;
   return TRUE;
 }
@@ -634,7 +637,8 @@ ephyrCreateResources (ScreenPtr pScreen)
   KdScreenInfo	*screen    = pScreenPriv->screen;
   EphyrScrPriv	*scrpriv   = screen->driver;
 
-  EPHYR_DBG("mark");
+  EPHYR_DBG("mark pScreen=%p mynum=%d shadow=%d",
+            pScreen, pScreen->myNum, scrpriv->shadow);
 
   if (scrpriv->shadow) 
     return KdShadowSet (pScreen, 
@@ -743,6 +747,56 @@ ephyrUpdateModifierState(unsigned int st
     }
 }
 
+static void
+ephyrBlockSigio (void)
+{
+    sigset_t set;
+
+    sigemptyset (&set);
+    sigaddset (&set, SIGIO);
+    sigprocmask (SIG_BLOCK, &set, 0);
+}
+
+static void
+ephyrUnblockSigio (void)
+{
+    sigset_t set;
+
+    sigemptyset (&set);
+    sigaddset (&set, SIGIO);
+    sigprocmask (SIG_UNBLOCK, &set, 0);
+}
+
+static Bool
+ephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
+{
+  return FALSE;
+}
+
+static void
+ephyrCrossScreen (ScreenPtr pScreen, Bool entering)
+{
+}
+
+int ephyrCurScreen; /*current event screen*/
+
+static void
+ephyrWarpCursor (ScreenPtr pScreen, int x, int y)
+{
+    ephyrBlockSigio ();
+    ephyrCurScreen = pScreen->myNum;
+    miPointerWarpCursor (pScreen, x, y);
+    ephyrUnblockSigio ();
+}
+
+miPointerScreenFuncRec ephyrPointerScreenFuncs =
+{
+  ephyrCursorOffScreen,
+  ephyrCrossScreen,
+  ephyrWarpCursor
+};
+
+
 void
 ephyrPoll(void)
 {
@@ -751,21 +805,39 @@ ephyrPoll(void)
   while (hostx_get_event(&ev))
     {
       switch (ev.type)
-	{
-	case EPHYR_EV_MOUSE_MOTION:
+        {
+        case EPHYR_EV_MOUSE_MOTION:
           if (!ephyrMouse ||
-              !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled)
+              !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) {
+              EPHYR_DBG ("skipping mouse motion:%d\n", ephyrCurScreen) ;
               continue;
-	  KdEnqueuePointerEvent(ephyrMouse, mouseState,  
-			        ev.data.mouse_motion.x, 
-			        ev.data.mouse_motion.y,
-                                0);
-	  break;
-	  
-	case EPHYR_EV_MOUSE_PRESS:
+          }
+          {
+            if (ephyrCurScreen != ev.data.mouse_motion.screen)
+              {
+                  EPHYR_DBG ("warping mouse cursor:%d\n", ephyrCurScreen) ;
+                  ephyrWarpCursor(screenInfo.screens[ev.data.mouse_motion.screen],
+                                   ev.data.mouse_motion.x,
+                                   ev.data.mouse_motion.y );
+              }
+            else
+              {
+                  EPHYR_DBG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ;
+                  KdEnqueuePointerEvent(ephyrMouse, mouseState,
+                                        ev.data.mouse_motion.x,
+                                        ev.data.mouse_motion.y,
+                                        0);
+              }
+          }
+          break;
+
+        case EPHYR_EV_MOUSE_PRESS:
           if (!ephyrMouse ||
-              !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled)
+              !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) {
+              EPHYR_DBG ("skipping mouse press:%d\n", ephyrCurScreen) ;
               continue;
+          }
+          EPHYR_DBG ("enqueuing mouse press:%d\n", ephyrCurScreen) ;
 	  ephyrUpdateModifierState(ev.key_state);
 	  mouseState |= ev.data.mouse_down.button_num;
 	  KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0);
@@ -777,6 +849,7 @@ ephyrPoll(void)
               continue;
 	  ephyrUpdateModifierState(ev.key_state);
 	  mouseState &= ~ev.data.mouse_up.button_num;
+          EPHYR_DBG ("enqueuing mouse release:%d\n", ephyrCurScreen) ;
 	  KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0);
 	  break;
 
@@ -792,7 +865,6 @@ ephyrPoll(void)
           if (!ephyrKbd ||
               !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled)
               continue;
-	  ephyrUpdateModifierState(ev.key_state);
 	  KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE);
 	  break;
 
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index f49d920..1c9b4f8 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -71,6 +71,8 @@ extern KdCardFuncs ephyrFuncs;
 extern KdKeyboardInfo *ephyrKbd;
 extern KdPointerInfo *ephyrMouse;
 
+extern miPointerScreenFuncRec ephyrPointerScreenFuncs;
+
 Bool
 ephyrInitialize (KdCardInfo *card, EphyrPriv *priv);
 
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index a76da03..6874609 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -33,6 +33,8 @@ extern Bool   EphyrWantGrayScale;
 extern Bool   kdHasPointer;
 extern Bool   kdHasKbd;
 
+void processScreenArg (char *screen_size, char *parent_id) ;
+
 void
 InitCard (char *name)
 {
@@ -100,19 +102,60 @@ ddxUseMsg (void)
   exit(1);
 }
 
+void
+processScreenArg (char *screen_size, char *parent_id)
+{
+  KdCardInfo   *card;
+  static int card_exists;
+
+  InitCard (0);  /*Put each screen on a separate card*/
+  card = KdCardInfoLast ();
+
+  if (card)
+    {
+      KdScreenInfo *screen;
+      unsigned long p_id = 0;
+
+      screen = KdScreenInfoAdd (card);
+      KdParseScreen (screen, screen_size);
+
+      if (parent_id)
+        {
+          p_id = strtol (parent_id, NULL, 0);
+        }
+      EPHYR_DBG ("screen number:%d\n", screen->mynum) ;
+      hostx_add_screen (screen, p_id, screen->mynum);
+    }
+  else
+    {
+      ErrorF("No matching card found!\n");
+    }
+}
+
 int
 ddxProcessArgument (int argc, char **argv, int i)
 {
-  EPHYR_DBG("mark");
+  EPHYR_DBG("mark argv[%d]='%s'", i, argv[i] );
 
   if (!strcmp (argv[i], "-parent"))
     {
-      if(i+1 < argc) 
+      if(i+1 < argc)
 	{
-	  hostx_use_preexisting_window(strtol(argv[i+1], NULL, 0));
+	  processScreenArg ("100x100", argv[i+1]);
 	  return 2;
-	} 
-      
+	}
+
+      UseMsg();
+      exit(1);
+    }
+  else if (!strcmp (argv[i], "-screen"))
+    {
+      if ((i+1) < argc)
+	{
+	  processScreenArg (argv[i+1], NULL);
+	  return 2;
+	}
+
       UseMsg();
       exit(1);
     }
@@ -198,8 +241,10 @@ miPointerSpriteFuncRec EphyrPointerSprit
 Bool
 ephyrCursorInit(ScreenPtr pScreen)
 {
-  miPointerInitialize(pScreen, &EphyrPointerSpriteFuncs,
-		      &kdPointerScreenFuncs, FALSE);
+  miPointerInitialize(pScreen, 
+		      &EphyrPointerSpriteFuncs,
+		      &ephyrPointerScreenFuncs, 
+		      FALSE);
 
   return TRUE;
 }
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 36d3cbd..81678d9 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -47,33 +47,44 @@
  * to get clobbered. 
  */
 
+struct EphyrHostScreen
+{
+  Window          win;
+  Window          win_pre_existing; 	/* Set via -parent option like xnest */
+  XImage         *ximg;
+  int             win_width, win_height;
+  int             server_depth;
+  unsigned char  *fb_data;   	/* only used when host bpp != server bpp */
+  XShmSegmentInfo shminfo;
+
+  void           *info;   /* Pointer to the screen this is associated with */
+  int             mynum;  /* Screen number */
+};
+
 struct EphyrHostXVars
 {
   char           *server_dpy_name;
   Display        *dpy;
   int             screen;
   Visual         *visual;
-  Window          win, winroot;
-  Window          win_pre_existing; 	/* Set via -parent option like xnest */
+  Window          winroot;
   GC              gc;
   int             depth;
-  int             server_depth;
-  XImage         *ximg;
-  int             win_width, win_height;
   Bool            use_host_cursor;
   Bool            use_fullscreen;
   Bool            have_shm;
 
+  int             n_screens;
+  struct EphyrHostScreen *screens;
+
   long            damage_debug_msec;
 
-  unsigned char  *fb_data;   	/* only used when host bpp != server bpp */
   unsigned long   cmap[256];
-
-  XShmSegmentInfo shminfo;
 };
 
 /* memset ( missing> ) instead of below  */
-static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+/*static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};*/
+static EphyrHostXVars HostX;
 
 static int            HostXWantDamageDebug = 0;
 
@@ -89,8 +100,22 @@ hostx_set_fullscreen_hint(void);
 static int trapped_error_code = 0;
 static int (*old_error_handler) (Display *d, XErrorEvent *e);
 
-#define host_depth_matches_server() (HostX.depth == HostX.server_depth)
+#define host_depth_matches_server(_vars) (HostX.depth == (_vars)->server_depth)
 
+static struct EphyrHostScreen *
+host_screen_from_screen_info (EphyrScreenInfo *screen)
+{
+  int i;
+
+  for (i = 0 ; i < HostX.n_screens ; i++)
+    {
+      if ( HostX.screens[i].info == screen)
+        {
+          return &HostX.screens[i];
+        }
+    }
+  return NULL;
+}
 
 static int
 error_handler(Display     *display,
@@ -115,13 +140,16 @@ hostx_errors_untrap(void)
 }
 
 int
-hostx_want_screen_size(int *width, int *height)
+hostx_want_screen_size (EphyrScreenInfo screen, int *width, int *height )
 {
- if (HostX.win_pre_existing != None
-     || HostX.use_fullscreen == True)
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+  if (host_screen &&
+       (host_screen->win_pre_existing != None ||
+         HostX.use_fullscreen == True))
     {
-      *width  = HostX.win_width;
-      *height = HostX.win_height;
+      *width  = host_screen->win_width;
+      *height = host_screen->win_height;
       return 1;
     }
 
@@ -129,100 +157,140 @@ hostx_want_screen_size(int *width, int *
 }
 
 void
-hostx_set_display_name(char *name)
+hostx_add_screen (EphyrScreenInfo screen,
+                  unsigned long win_id,
+                  int screen_num)
 {
-  HostX.server_dpy_name = strdup(name);
+  int index = HostX.n_screens;
+
+  HostX.n_screens += 1;
+  HostX.screens = realloc (HostX.screens,
+                           HostX.n_screens * sizeof(struct EphyrHostScreen));
+  memset (&HostX.screens[index], 0, sizeof (struct EphyrHostScreen));
+
+  HostX.screens[index].info       = screen;
+  HostX.screens[index].win_pre_existing = win_id;
 }
 
+
 void
-hostx_set_win_title(char *extra_text)
+hostx_set_display_name (char *name)
 {
-  char buf[256];
+  HostX.server_dpy_name = strdup (name);
+}
 
-  snprintf(buf, 256, "Xephyr on %s %s", 
-	   HostX.server_dpy_name,
-	   (extra_text != NULL) ? extra_text : "");
+void
+hostx_set_screen_number(EphyrScreenInfo screen, int number)
+{
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+  if (host_screen) {
+    host_screen->mynum = number;
+    hostx_set_win_title (host_screen->info, "") ;
+  }}
+
+void
+hostx_set_win_title (EphyrScreenInfo screen, char *extra_text)
+{
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+#define BUF_LEN 256
+  char buf[BUF_LEN+1];
 
-  XStoreName(HostX.dpy, HostX.win, buf);
+  if (!host_screen)
+    return;
+
+  memset (buf, 0, BUF_LEN+1) ;
+  snprintf (buf, BUF_LEN, "Xephyr on %s.%d %s", 
+            HostX.server_dpy_name, 
+            host_screen->mynum,
+            (extra_text != NULL) ? extra_text : "");
+
+  XStoreName (HostX.dpy, host_screen->win, buf);
 }
 
 int
-hostx_want_host_cursor(void)
+hostx_want_host_cursor (void)
 {
   return HostX.use_host_cursor;
 }
 
 void
-hostx_use_host_cursor(void)
+hostx_use_host_cursor (void)
 {
   HostX.use_host_cursor = True;
 }
 
 int
-hostx_want_preexisting_window(void)
+hostx_want_preexisting_window (EphyrScreenInfo screen)
 {
-  if (HostX.win_pre_existing) 
-    return 1;
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+  if (host_screen && host_screen->win_pre_existing)
+    {
+      return 1;
+    }
   else
+    {
     return 0;
+    }
 }
 
 void
-hostx_use_fullscreen(void)
+hostx_use_fullscreen (void)
 {
   HostX.use_fullscreen = True;
 }
 
 int
-hostx_want_fullscreen(void)
+hostx_want_fullscreen (void)
 {
   return HostX.use_fullscreen;
 }
 
 static void
-hostx_set_fullscreen_hint(void)
+hostx_set_fullscreen_hint (void)
 {
   Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN;
+  int index;
 
   atom_WINDOW_STATE 
     = XInternAtom(HostX.dpy, "_NET_WM_STATE", False);
   atom_WINDOW_STATE_FULLSCREEN 
     = XInternAtom(HostX.dpy, "_NET_WM_STATE_FULLSCREEN",False);
 
-  XChangeProperty(HostX.dpy, HostX.win,
-		  atom_WINDOW_STATE, XA_ATOM, 32,
-		  PropModeReplace,
-		  (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
+  for (index = 0 ; index < HostX.n_screens ; index++)
+    {
+      XChangeProperty (HostX.dpy, HostX.screens[index].win,
+                       atom_WINDOW_STATE, XA_ATOM, 32,
+                       PropModeReplace,
+                       (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
+    }
 }
 
-void
-hostx_use_preexisting_window(unsigned long win_id)
-{
-  HostX.win_pre_existing = win_id;
-}
 
 static void
-hostx_toggle_damage_debug(void)
+hostx_toggle_damage_debug (void)
 {
   HostXWantDamageDebug ^= 1;
 }
 
-void 
-hostx_handle_signal(int signum)
+void
+hostx_handle_signal (int signum)
 {
   hostx_toggle_damage_debug();
-  EPHYR_DBG("Signal caught. Damage Debug:%i\n", HostXWantDamageDebug);
+  EPHYR_DBG ("Signal caught. Damage Debug:%i\n",
+              HostXWantDamageDebug);
 }
 
 int
-hostx_init(void)
+hostx_init (void)
 {
   XSetWindowAttributes  attr;
   Cursor                empty_cursor;
   Pixmap                cursor_pxm;
   XColor                col;
+  int                   index;
 
-  attr.event_mask = 
+  attr.event_mask =
     ButtonPressMask
     |ButtonReleaseMask
     |PointerMotionMask
@@ -233,126 +301,142 @@ hostx_init(void)
   EPHYR_DBG("mark");
 
   if ((HostX.dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
-  {
-    fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
-    exit(1);
-  }
+    {
+      fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
+      exit(1);
+    }
 
   HostX.screen  = DefaultScreen(HostX.dpy);
   HostX.winroot = RootWindow(HostX.dpy, HostX.screen);
   HostX.gc      = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL);
   HostX.depth   = DefaultDepth(HostX.dpy, HostX.screen);
-  HostX.visual  = DefaultVisual(HostX.dpy, HostX.screen); 
-
-  HostX.server_depth = HostX.depth;
- 
-  if (HostX.win_pre_existing != None)
-    {
-      Status            result;
-      XWindowAttributes prewin_attr;
-
-      /* Get screen size from existing window */
-
-      hostx_errors_trap();
-
-      result = XGetWindowAttributes(HostX.dpy, 
-				    HostX.win_pre_existing, 
-				    &prewin_attr);
-
-
-      if (hostx_errors_untrap() || !result)
-	{
-	  fprintf(stderr, "\nXephyr -parent window' does not exist!\n");
-	  exit(1);
-	}
-
-      HostX.win_width  = prewin_attr.width;
-      HostX.win_height = prewin_attr.height;
+  HostX.visual  = DefaultVisual(HostX.dpy, HostX.screen);
 
-      HostX.win = XCreateWindow(HostX.dpy,
-				HostX.win_pre_existing,
-				0,0,HostX.win_width,HostX.win_height,
-				0,
-				CopyFromParent,
-				CopyFromParent,
-				CopyFromParent,
-				CWEventMask,
-				&attr);
-    }
-  else
+  for (index = 0 ; index < HostX.n_screens ; index++)
     {
-      HostX.win = XCreateWindow(HostX.dpy,
-				HostX.winroot,
-				0,0,100,100, /* will resize  */
-				0,
-			        CopyFromParent,
-				CopyFromParent,
-				CopyFromParent,
-				CWEventMask,
-				&attr);
+      struct EphyrHostScreen *host_screen = &HostX.screens[index];
 
-      hostx_set_win_title("( ctrl+shift grabs mouse and keyboard )");
-
-      if (HostX.use_fullscreen)
-	{
-	  HostX.win_width  = DisplayWidth(HostX.dpy, HostX.screen); 
-	  HostX.win_height = DisplayHeight(HostX.dpy, HostX.screen); 
-
-	  hostx_set_fullscreen_hint();
-	}
+      host_screen->server_depth = HostX.depth;
+      if (host_screen->win_pre_existing != None)
+        {
+          Status            result;
+          XWindowAttributes prewin_attr;
+
+          /* Get screen size from existing window */
+
+          hostx_errors_trap();
+
+          result = XGetWindowAttributes (HostX.dpy,
+                                         host_screen->win_pre_existing,
+                                         &prewin_attr);
+
+
+          if (hostx_errors_untrap() || !result)
+          {
+              fprintf (stderr, "\nXephyr -parent window' does not exist!\n");
+              exit (1);
+          }
+
+          host_screen->win_width  = prewin_attr.width;
+          host_screen->win_height = prewin_attr.height;
+
+          host_screen->win = XCreateWindow (HostX.dpy,
+                                            host_screen->win_pre_existing,
+                                            0,0,
+                                            host_screen->win_width,
+                                            host_screen->win_height,
+                                            0,
+                                            CopyFromParent,
+                                            CopyFromParent,
+                                            CopyFromParent,
+                                            CWEventMask,
+                                            &attr);
+        }
+      else
+        {
+          host_screen->win = XCreateWindow (HostX.dpy,
+                                            HostX.winroot,
+                                            0,0,100,100, /* will resize */
+                                            0,
+                                            CopyFromParent,
+                                            CopyFromParent,
+                                            CopyFromParent,
+                                            CWEventMask,
+                                            &attr);
+
+          hostx_set_win_title (host_screen->info,
+                               "(ctrl+shift grabs mouse and keyboard)");
+
+          if (HostX.use_fullscreen)
+            {
+              host_screen->win_width  = DisplayWidth(HostX.dpy, HostX.screen);
+              host_screen->win_height = DisplayHeight(HostX.dpy, HostX.screen);
+
+              hostx_set_fullscreen_hint();
+            }
+        }
     }
 
 
-  XParseColor(HostX.dpy, DefaultColormap(HostX.dpy,HostX.screen), "red", &col);
-  XAllocColor(HostX.dpy, DefaultColormap(HostX.dpy, HostX.screen), &col);
-  XSetForeground(HostX.dpy, HostX.gc, col.pixel);
+  XParseColor (HostX.dpy, DefaultColormap (HostX.dpy,HostX.screen),
+               "red", &col);
+  XAllocColor (HostX.dpy, DefaultColormap (HostX.dpy, HostX.screen),
+               &col);
+  XSetForeground (HostX.dpy, HostX.gc, col.pixel);
 
-  if (!hostx_want_host_cursor())
+  if (!hostx_want_host_cursor ())
     {
       /* Ditch the cursor, we provide our 'own' */
       cursor_pxm = XCreatePixmap (HostX.dpy, HostX.winroot, 1, 1, 1);
       memset (&col, 0, sizeof (col));
-      empty_cursor = XCreatePixmapCursor (HostX.dpy, 
-					  cursor_pxm, cursor_pxm, 
-					  &col, &col, 1, 1);
-      XDefineCursor (HostX.dpy, HostX.win, empty_cursor);
+      empty_cursor = XCreatePixmapCursor (HostX.dpy,
+                                          cursor_pxm, cursor_pxm, 
+                                          &col, &col, 1, 1);
+      for ( index = 0 ; index < HostX.n_screens ; index++ )
+        {
+          XDefineCursor (HostX.dpy,
+                         HostX.screens[index].win,
+                         empty_cursor);
+        }
       XFreePixmap (HostX.dpy, cursor_pxm);
     }
 
-  HostX.ximg   = NULL;
-
+  for (index = 0 ; index < HostX.n_screens ; index++)
+    {
+      HostX.screens[index].ximg   = NULL;
+    }
   /* Try to get share memory ximages for a little bit more speed */
 
-  if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM")) 
+  if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM"))
     {
       fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
       HostX.have_shm = False;
-    } 
-  else 		            
-    {	
+    }
+  else
+    {
       /* Really really check we have shm - better way ?*/
-      XShmSegmentInfo shminfo; 
+      XShmSegmentInfo shminfo;
 
-      HostX.have_shm = True;
+        HostX.have_shm = True;
 
-      shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777);
-      shminfo.shmaddr=shmat(shminfo.shmid,0,0);
-      shminfo.readOnly=True;
+        shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777);
+        shminfo.shmaddr=shmat(shminfo.shmid,0,0);
+        shminfo.readOnly=True;
 
-      hostx_errors_trap();
-      
-      XShmAttach(HostX.dpy, &shminfo);
-      XSync(HostX.dpy, False);
+        hostx_errors_trap();
 
-      if (hostx_errors_untrap())
-	{
-	  fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
-	  HostX.have_shm = False;
-	}
+        XShmAttach(HostX.dpy, &shminfo);
+        XSync(HostX.dpy, False);
 
-      shmdt(shminfo.shmaddr);
-      shmctl(shminfo.shmid, IPC_RMID, 0);
-    }
+        if (hostx_errors_untrap())
+          {
+            fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
+            HostX.have_shm = False;
+          }
+
+        shmdt(shminfo.shmaddr);
+        shmctl(shminfo.shmid, IPC_RMID, 0);
+}
 
   XFlush(HostX.dpy);
 
@@ -360,10 +444,10 @@ hostx_init(void)
 
   HostX.damage_debug_msec = 20000; /* 1/50 th of a second */
 
-  if (getenv("XEPHYR_PAUSE"))
+  if (getenv ("XEPHYR_PAUSE"))
     {
-      HostX.damage_debug_msec = strtol(getenv("XEPHYR_PAUSE"), NULL, 0);
-      EPHYR_DBG("pause is %li\n", HostX.damage_debug_msec);
+      HostX.damage_debug_msec = strtol (getenv ("XEPHYR_PAUSE"), NULL, 0);
+      EPHYR_DBG ("pause is %li\n", HostX.damage_debug_msec);
     }
 
   return 1;
@@ -376,38 +460,54 @@ hostx_get_depth (void)
 }
 
 int
-hostx_get_server_depth (void)
+hostx_get_server_depth (EphyrScreenInfo screen)
 {
-  return HostX.server_depth;
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+  return (host_screen ? host_screen->server_depth : 0);
 }
 
 void
-hostx_set_server_depth(int depth)
+hostx_set_server_depth (EphyrScreenInfo screen, int depth)
 {
-  HostX.server_depth = depth;
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+  if (host_screen)
+    host_screen->server_depth = depth;
 }
 
 int
-hostx_get_bpp(void)
+hostx_get_bpp (EphyrScreenInfo screen)
 {
-  if (host_depth_matches_server())
-    return  HostX.visual->bits_per_rgb;
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+  if (!host_screen)
+    return 0;
+
+  if (host_depth_matches_server (host_screen))
+    return HostX.visual->bits_per_rgb;
   else
-    return HostX.server_depth; 	/* XXX correct ? */
+    return host_screen->server_depth; /*XXX correct ?*/
 }
 
 void
-hostx_get_visual_masks (CARD32 *rmsk, 
-			CARD32 *gmsk, 
+hostx_get_visual_masks (EphyrScreenInfo screen,
+			CARD32 *rmsk,
+			CARD32 *gmsk,
 			CARD32 *bmsk)
 {
-  if (host_depth_matches_server())
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+  if (!host_screen)
+    return;
+
+  if (host_depth_matches_server(host_screen))
     {
       *rmsk = HostX.visual->red_mask;
       *gmsk = HostX.visual->green_mask;
       *bmsk = HostX.visual->blue_mask;
     }
-  else if (HostX.server_depth == 16)
+  else if (host_screen->server_depth == 16)
     {
       /* Assume 16bpp 565 */
       *rmsk = 0xf800;
@@ -423,9 +523,9 @@ hostx_get_visual_masks (CARD32 *rmsk, 
 }
 
 void
-hostx_set_cmap_entry(unsigned char idx, 
-		     unsigned char r, 
-		     unsigned char g, 
+hostx_set_cmap_entry(unsigned char idx,
+		     unsigned char r,
+		     unsigned char g,
 		     unsigned char b)
 {
   /* XXX Will likely break for 8 on 16, not sure if this is correct */
@@ -445,15 +545,25 @@ hostx_set_cmap_entry(unsigned char idx, 
  * by fakexa for storing offscreen pixmap data.
  */
 void*
-hostx_screen_init (int width, int height, int buffer_height)
+hostx_screen_init (EphyrScreenInfo screen,
+                   int width, int height,
+                   int buffer_height)
 {
   int         bitmap_pad;
   Bool        shm_success = False;
   XSizeHints *size_hints;
 
-  EPHYR_DBG("mark");
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+  if (!host_screen)
+    {
+      fprintf (stderr, "%s: Error in accessing hostx data\n", __func__ );
+      exit(1);
+    }
 
-  if (HostX.ximg != NULL)
+  EPHYR_DBG ("host_screen=%p wxh=%dx%d, buffer_height=%d",
+             host_screen, width, height, buffer_height);
+
+  if (host_screen->ximg != NULL)
     {
       /* Free up the image data if previously used
        * i.ie called by server reset
@@ -461,47 +571,48 @@ hostx_screen_init (int width, int height
 
       if (HostX.have_shm)
 	{
-	  XShmDetach(HostX.dpy, &HostX.shminfo);
-	  XDestroyImage (HostX.ximg);
-	  shmdt(HostX.shminfo.shmaddr);
-	  shmctl(HostX.shminfo.shmid, IPC_RMID, 0);
+	  XShmDetach(HostX.dpy, &host_screen->shminfo);
+	  XDestroyImage (host_screen->ximg);
+	  shmdt(host_screen->shminfo.shmaddr);
+	  shmctl(host_screen->shminfo.shmid, IPC_RMID, 0);
 	}
       else
 	{
-	  if (HostX.ximg->data) 
+	  if (host_screen->ximg->data) 
 	    {
-	      free(HostX.ximg->data);
-	      HostX.ximg->data = NULL;
+	      free(host_screen->ximg->data);
+	      host_screen->ximg->data = NULL;
 	    } 
 
-	  XDestroyImage(HostX.ximg);
+	  XDestroyImage(host_screen->ximg);
 	}
     }
 
   if (HostX.have_shm)
     {
-      HostX.ximg = XShmCreateImage(HostX.dpy, HostX.visual, HostX.depth, 
-				   ZPixmap, NULL, &HostX.shminfo,
-				   width, buffer_height );
-	  
-      HostX.shminfo.shmid = shmget(IPC_PRIVATE,
-				   HostX.ximg->bytes_per_line * buffer_height,
-				   IPC_CREAT|0777);
-      HostX.shminfo.shmaddr = HostX.ximg->data = shmat(HostX.shminfo.shmid,
-						       0, 0);
+      host_screen->ximg = XShmCreateImage (HostX.dpy, HostX.visual, HostX.depth,
+                                           ZPixmap, NULL, &host_screen->shminfo,
+                                           width, buffer_height );
+
+      host_screen->shminfo.shmid =
+                      shmget(IPC_PRIVATE,
+                             host_screen->ximg->bytes_per_line * buffer_height,
+                             IPC_CREAT|0777);
+      host_screen->ximg->data = shmat(host_screen->shminfo.shmid, 0, 0);
+      host_screen->shminfo.shmaddr = host_screen->ximg->data;
 
-      if (HostX.ximg->data == (char *)-1)
+      if (host_screen->ximg->data == (char *)-1)
 	{
 	  EPHYR_DBG("Can't attach SHM Segment, falling back to plain XImages");
 	  HostX.have_shm = False;
-	  XDestroyImage(HostX.ximg);
-	  shmctl(HostX.shminfo.shmid, IPC_RMID, 0);
+	  XDestroyImage(host_screen->ximg);
+	  shmctl(host_screen->shminfo.shmid, IPC_RMID, 0);
 	}
       else
 	{
-	  EPHYR_DBG("SHM segment attached");
-	  HostX.shminfo.readOnly = False;
-	  XShmAttach(HostX.dpy, &HostX.shminfo);
+	  EPHYR_DBG("SHM segment attached %p", host_screen->shminfo.shmaddr);
+	  host_screen->shminfo.readOnly = False;
+	  XShmAttach(HostX.dpy, &host_screen->shminfo);
 	  shm_success = True;
 	}
     }
@@ -509,63 +620,74 @@ hostx_screen_init (int width, int height
   if (!shm_success)
     {
       bitmap_pad = ( HostX.depth > 16 )? 32 : (( HostX.depth > 8 )? 16 : 8 );
-	  
-      HostX.ximg = XCreateImage( HostX.dpy, 
-				 HostX.visual, 
-				 HostX.depth, 
-				 ZPixmap, 0, 0,
-				 width, 
-				 buffer_height, 
-				 bitmap_pad, 
-				 0);
 
-      HostX.ximg->data = malloc( HostX.ximg->bytes_per_line * buffer_height );
-    }
+      EPHYR_DBG("Creating image %dx%d for screen host_screen=%p\n",
+                width, buffer_height, host_screen );
+      host_screen->ximg = XCreateImage (HostX.dpy,
+                                        HostX.visual,
+                                        HostX.depth,
+                                        ZPixmap, 0, 0,
+                                        width,
+                                        buffer_height,
+                                        bitmap_pad,
+                                        0);
 
+      host_screen->ximg->data =
+              malloc (host_screen->ximg->bytes_per_line * buffer_height);
+    }
 
-  XResizeWindow(HostX.dpy, HostX.win, width, height);
+  XResizeWindow (HostX.dpy, host_screen->win, width, height);
 
   /* Ask the WM to keep our size static */
   size_hints = XAllocSizeHints();
   size_hints->max_width = size_hints->min_width = width;
   size_hints->max_height = size_hints->min_height = height;
   size_hints->flags = PMinSize|PMaxSize;
-  XSetWMNormalHints(HostX.dpy, HostX.win, size_hints);
+  XSetWMNormalHints(HostX.dpy, host_screen->win, size_hints);
   XFree(size_hints);
 
-  XMapWindow(HostX.dpy, HostX.win);
+  XMapWindow(HostX.dpy, host_screen->win);
 
   XSync(HostX.dpy, False);
 
-  HostX.win_width  = width;
-  HostX.win_height = height;
+  host_screen->win_width  = width;
+  host_screen->win_height = height;
 
-  if (host_depth_matches_server())
+  if (host_depth_matches_server(host_screen))
     {
       EPHYR_DBG("Host matches server");
-      return HostX.ximg->data;
+      return host_screen->ximg->data;
     }
   else
     {
-      EPHYR_DBG("server bpp %i", HostX.server_depth>>3);
-      HostX.fb_data = malloc(width*buffer_height*(HostX.server_depth>>3));
-      return HostX.fb_data;
+      EPHYR_DBG("server bpp %i", host_screen->server_depth>>3);
+      host_screen->fb_data = malloc(width*buffer_height*(host_screen->server_depth>>3));
+      return host_screen->fb_data;
     }
 }
 
+static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen,
+                                    int x,     int y,
+                                    int width, int height);
+
 void
-hostx_paint_rect(int sx,    int sy,
-		 int dx,    int dy, 
-		 int width, int height)
+hostx_paint_rect (EphyrScreenInfo screen,
+                  int sx,    int sy,
+                  int dx,    int dy,
+                  int width, int height)
 {
-  /* 
+  struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+  EPHYR_DBG ("painting in screen %d\n", host_screen->mynum) ;
+
+  /*
    *  Copy the image data updated by the shadow layer
    *  on to the window
    */
 
   if (HostXWantDamageDebug)
     {
-      hostx_paint_debug_rect(dx, dy, width, height);
+      hostx_paint_debug_rect(host_screen, dx, dy, width, height);
     }
 
   /* 
@@ -580,22 +702,23 @@ hostx_paint_rect(int sx,    int sy,
    *       ... and it will be slower than the matching depth case.
    */
 
-  if (!host_depth_matches_server())
+  if (!host_depth_matches_server(host_screen))
     {
-      int            x,y,idx, bytes_per_pixel = (HostX.server_depth>>3);
+      int            x,y,idx, bytes_per_pixel = (host_screen->server_depth>>3);
       unsigned char  r,g,b;
       unsigned long  host_pixel;
 
+      EPHYR_DBG("Unmatched host depth host_screen=%p\n", host_screen);
       for (y=sy; y<sy+height; y++)
 	for (x=sx; x<sx+width; x++)
 	  {
-	    idx = (HostX.win_width*y*bytes_per_pixel)+(x*bytes_per_pixel);
-	    
-	    switch (HostX.server_depth)
+	    idx = (host_screen->win_width*y*bytes_per_pixel)+(x*bytes_per_pixel);
+
+	    switch (host_screen->server_depth)
 	      {
 	      case 16:
 		{
-		  unsigned short pixel = *(unsigned short*)(HostX.fb_data+idx);
+		  unsigned short pixel = *(unsigned short*)(host_screen->fb_data+idx);
 
 		  r = ((pixel & 0xf800) >> 8);
 		  g = ((pixel & 0x07e0) >> 3);
@@ -603,13 +726,13 @@ hostx_paint_rect(int sx,    int sy,
 
 		  host_pixel = (r << 16) | (g << 8) | (b);
 		  
-		  XPutPixel(HostX.ximg, x, y, host_pixel);
+		  XPutPixel(host_screen->ximg, x, y, host_pixel);
 		  break;
 		}
 	      case 8:
 		{
-		  unsigned char pixel = *(unsigned char*)(HostX.fb_data+idx);
-		  XPutPixel(HostX.ximg, x, y, HostX.cmap[pixel]);
+		  unsigned char pixel = *(unsigned char*)(host_screen->fb_data+idx);
+		  XPutPixel(host_screen->ximg, x, y, HostX.cmap[pixel]);
 		  break;
 		}
 	      default:
@@ -620,21 +743,23 @@ hostx_paint_rect(int sx,    int sy,
 
   if (HostX.have_shm)
     {
-      XShmPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, 
-		       sx, sy, dx, dy, width, height, False);
+      XShmPutImage (HostX.dpy, host_screen->win,
+                    HostX.gc, host_screen->ximg,
+                    sx, sy, dx, dy, width, height, False);
     }
   else
     {
-      XPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, 
-		sx, sy, dx, dy, width, height);
+      XPutImage (HostX.dpy, host_screen->win, HostX.gc, host_screen->ximg, 
+                 sx, sy, dx, dy, width, height);
     }
 
-  XSync(HostX.dpy, False);
+  XSync (HostX.dpy, False);
 }
 
-void
-hostx_paint_debug_rect(int x,     int y, 
-		       int width, int height)
+static void
+hostx_paint_debug_rect (struct EphyrHostScreen *host_screen,
+                        int x,     int y,
+                        int width, int height)
 {
   struct timespec tspec;
 
@@ -646,8 +771,8 @@ hostx_paint_debug_rect(int x,     int y,
 
   /* fprintf(stderr, "Xephyr updating: %i+%i %ix%i\n", x, y, width, height); */
 
-  XFillRectangle(HostX.dpy, HostX.win, HostX.gc, x, y, width,height); 
-  XSync(HostX.dpy, False);
+  XFillRectangle (HostX.dpy, host_screen->win, HostX.gc, x, y, width,height);
+  XSync (HostX.dpy, False);
 
   /* nanosleep seems to work better than usleep for me... */
   nanosleep(&tspec, NULL);
@@ -660,14 +785,14 @@ hostx_load_keymap(void)
   int              host_width, min_keycode, max_keycode, width;
   int              i,j;
 
-  XDisplayKeycodes(HostX.dpy, &min_keycode, &max_keycode);
+  XDisplayKeycodes (HostX.dpy, &min_keycode, &max_keycode);
 
-  EPHYR_DBG("min: %d, max: %d", min_keycode, max_keycode);
+  EPHYR_DBG ("min: %d, max: %d", min_keycode, max_keycode);
 
-  keymap = XGetKeyboardMapping(HostX.dpy, 
-			       min_keycode,
-			       max_keycode - min_keycode + 1,
-			       &host_width);
+  keymap = XGetKeyboardMapping (HostX.dpy,
+			        min_keycode,
+			        max_keycode - min_keycode + 1,
+			        &host_width);
 
   /* Try and copy the hosts keymap into our keymap to avoid loads
    * of messing around.
@@ -688,7 +813,7 @@ hostx_load_keymap(void)
       ephyrKeySyms.map[(i*width)+j] = (CARD32) keymap[(i*host_width) + j];
 
   EPHYR_DBG("keymap width, host:%d kdrive:%d", host_width, width);
-  
+
   ephyrKeySyms.minKeyCode  = min_keycode;
   ephyrKeySyms.maxKeyCode  = max_keycode;
   ephyrKeySyms.mapWidth    = width;
@@ -696,11 +821,26 @@ hostx_load_keymap(void)
   XFree(keymap);
 }
 
+static struct EphyrHostScreen *
+host_screen_from_window (Window w)
+{
+  int index;
+
+  for (index = 0 ; index < HostX.n_screens ; index++)
+    {
+      if (HostX.screens[index].win == w)
+        {
+          return &HostX.screens[index];
+        }
+    }
+  return NULL;
+}
+
 int
 hostx_get_event(EphyrHostXEvent *ev)
 {
   XEvent      xev;
-  static Bool grabbed;
+  static int  grabbed_screen = -1;
 
   if (XPending(HostX.dpy))
     {
@@ -710,15 +850,27 @@ hostx_get_event(EphyrHostXEvent *ev)
 	{
 	case Expose:
 	  /* Not so great event compression, but works ok */
-	  while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window, 
+	  while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window,
 					Expose, &xev));
-	  hostx_paint_rect(0, 0, 0, 0, HostX.win_width, HostX.win_height);
+	  {
+	    struct EphyrHostScreen *host_screen =
+                host_screen_from_window (xev.xexpose.window);
+	    hostx_paint_rect (host_screen->info, 0, 0, 0, 0,
+                              host_screen->win_width,
+                              host_screen->win_height);
+	  }
 	  return 0;
 
 	case MotionNotify:
-	  ev->type = EPHYR_EV_MOUSE_MOTION;
-	  ev->data.mouse_motion.x = xev.xmotion.x; 
-	  ev->data.mouse_motion.y = xev.xmotion.y;
+	  {
+	    struct EphyrHostScreen *host_screen =
+                host_screen_from_window (xev.xmotion.window);
+
+	    ev->type = EPHYR_EV_MOUSE_MOTION;
+	    ev->data.mouse_motion.x = xev.xmotion.x; 
+	    ev->data.mouse_motion.y = xev.xmotion.y;
+	    ev->data.mouse_motion.screen = (host_screen ? host_screen->mynum : -1);
+	  }
 	  return 1;
 
 	case ButtonPress:
@@ -750,29 +902,35 @@ hostx_get_event(EphyrHostXEvent *ev)
 	       || XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_R)
 	      && (xev.xkey.state & ControlMask))
 	    {
-	      if (grabbed) 
+	      struct EphyrHostScreen *host_screen =
+                  host_screen_from_window (xev.xexpose.window);
+
+	      if (grabbed_screen != -1)
 		{
 		  XUngrabKeyboard (HostX.dpy, CurrentTime);
 		  XUngrabPointer (HostX.dpy, CurrentTime);
-		  grabbed = False;
-		  hostx_set_win_title("( ctrl+shift grabs mouse and keyboard )");
-		} 
-	      else 
+		  grabbed_screen = -1;
+		  hostx_set_win_title (host_screen->info,
+                                       "(ctrl+shift grabs mouse and keyboard)");
+		}
+	      else
 		{
 		  /* Attempt grab */
-		  if (XGrabKeyboard (HostX.dpy, HostX.win, True, 
+		  if (XGrabKeyboard (HostX.dpy, host_screen->win, True, 
 				     GrabModeAsync, 
 				     GrabModeAsync, 
 				     CurrentTime) == 0)
 		    {
-		      if (XGrabPointer (HostX.dpy, HostX.win, True, 
+		      if (XGrabPointer (HostX.dpy, host_screen->win, True, 
 					NoEventMask, 
 					GrabModeAsync, 
 					GrabModeAsync, 
-					HostX.win, None, CurrentTime) == 0)
+					host_screen->win, None, CurrentTime) == 0)
 			{
-			  grabbed = True;
-			  hostx_set_win_title("( ctrl+shift releases mouse and keyboard )");
+			  grabbed_screen = host_screen->mynum;
+			  hostx_set_win_title
+                                  (host_screen->info,
+                                   "(ctrl+shift releases mouse and keyboard)");
 			}
 		      else 	/* Failed pointer grabm  ungrab keyboard */
 			XUngrabKeyboard (HostX.dpy, CurrentTime);
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
index 4d5f37f..93765d0 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -40,8 +40,8 @@
 
 typedef struct EphyrHostXVars  EphyrHostXVars;
 typedef struct EphyrHostXEvent EphyrHostXEvent;
-
-typedef enum EphyrHostXEventType 
+typedef void* EphyrScreenInfo ;
+typedef enum EphyrHostXEventType
 {
   EPHYR_EV_MOUSE_MOTION,
   EPHYR_EV_MOUSE_PRESS,
@@ -68,6 +68,7 @@ struct EphyrHostXEvent
     struct mouse_motion { 	
       int x;
       int y;
+      int screen;
     } mouse_motion;
 
     struct mouse_down { 	
@@ -92,7 +93,7 @@ struct EphyrHostXEvent
 };
 
 int
-hostx_want_screen_size(int *width, int *height);
+hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height);
 
 int
 hostx_want_host_cursor(void);
@@ -107,7 +108,7 @@ int
 hostx_want_fullscreen(void);
 
 int
-hostx_want_preexisting_window(void);
+hostx_want_preexisting_window(EphyrScreenInfo screen);
 
 void
 hostx_use_preexisting_window(unsigned long win_id);
@@ -119,25 +120,32 @@ int
 hostx_init(void);
 
 void
+hostx_add_screen(EphyrScreenInfo screen, unsigned long win_id, int screen_num);
+
+void
 hostx_set_display_name(char *name);
 
 void
-hostx_set_win_title(char *extra_text);
+hostx_set_screen_number(EphyrScreenInfo screen, int number);
+
+void
+hostx_set_win_title(EphyrScreenInfo screen, char *extra_text);
 
 int
 hostx_get_depth (void);
 
 int
-hostx_get_server_depth (void);
+hostx_get_server_depth (EphyrScreenInfo screen);
 
 void
-hostx_set_server_depth(int depth);
+hostx_set_server_depth(EphyrScreenInfo screen, int depth);
 
 int
-hostx_get_bpp(void);
+hostx_get_bpp(void *info);
 
 void
-hostx_get_visual_masks (CARD32 *rmsk, 
+hostx_get_visual_masks (void   *info,
+			CARD32 *rmsk, 
 			CARD32 *gmsk, 
 			CARD32 *bmsk);
 void
@@ -147,15 +155,16 @@ hostx_set_cmap_entry(unsigned char idx, 
 		     unsigned char b);
 
 void*
-hostx_screen_init (int width, int height, int buffer_height);
+hostx_screen_init (EphyrScreenInfo screen,
+                   int width, int height,
+                   int buffer_height);
 
 void
-hostx_paint_rect(int sx,    int sy,
-		 int dx,    int dy, 
+hostx_paint_rect(EphyrScreenInfo screen,
+		 int sx,    int sy,
+		 int dx,    int dy,
 		 int width, int height);
-void
-hostx_paint_debug_rect(int x,     int y, 
-		       int width, int height);
+
 
 void
 hostx_load_keymap(void);
diff --git a/hw/kdrive/ephyr/os.c b/hw/kdrive/ephyr/os.c
index 1a42495..b58daae 100644
--- a/hw/kdrive/ephyr/os.c
+++ b/hw/kdrive/ephyr/os.c
@@ -31,6 +31,14 @@
 static int
 EphyrInit (void)
 {
+  /*
+   * make sure at least one screen
+   * has been added to the system.
+   */
+  if (!KdCardInfoLast ())
+    {
+        processScreenArg ("640x480", NULL) ;
+    }
   return hostx_init();
 }
 
diff-tree 81692b628f41cb64329f3cccc0503fb216a2b8e3 (from dc90d500085dd74e90073be008fc514bd97b160a)
Author: Dodji Seketeli <dodji at openedhand.com>
Date:   Tue Oct 2 13:11:28 2007 +0200

    Fix #12650: "windows not receiving mouse events in multiple screens context"
    
    	* dix/events.c, include/dix.h:
    	  (UpdateSpriteForScreen): added this to update the mouse sprite context
    	   when we switch from a pScreen to another.
    	* mi/mipointer.c:
    	  (miPointerWarpCursor): as we are switching to a new pScreen,
    	   don't forget to update the mouse sprite context.

diff --git a/dix/events.c b/dix/events.c
index 7b4cab0..61dd534 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2352,6 +2352,61 @@ DefineInitialRootWindow(WindowPtr win)
 #endif
 }
 
+/**
+ * Update the mouse sprite info when the server switches from a pScreen to another.
+ * Otherwise, the pScreen of the mouse sprite is never updated when we switch
+ * from a pScreen to another. Never updating the pScreen of the mouse sprite
+ * implies that windows that are in pScreen whose pScreen->myNum >0 will never
+ * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
+ * always points to the first pScreen it has been set by
+ * DefineInitialRootWindow().
+ *
+ * Calling this function is useful for use cases where the server
+ * has more than one pScreen.
+ * This function is similar to DefineInitialRootWindow() but it does not
+ * reset the mouse pointer position.
+ * @param win must be the new pScreen we are switching to.
+ */
+void
+UpdateSpriteForScreen(ScreenPtr pScreen)
+{
+    WindowPtr win = NULL;
+    if (!pScreen)
+        return ;
+    win = WindowTable[pScreen->myNum];
+
+    sprite.hotPhys.pScreen = pScreen;
+    sprite.hot = sprite.hotPhys;
+    sprite.hotLimits.x2 = pScreen->width;
+    sprite.hotLimits.y2 = pScreen->height;
+#ifdef XEVIE
+    xeviewin =
+#endif
+    sprite.win = win;
+    sprite.current = wCursor (win);
+    sprite.current->refcnt++;
+    spriteTraceGood = 1;
+    ROOT = win;
+    (*pScreen->CursorLimits) (pScreen,
+                              sprite.current,
+                              &sprite.hotLimits,
+                              &sprite.physLimits);
+    sprite.confined = FALSE;
+    (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
+    (*pScreen->DisplayCursor) (pScreen, sprite.current);
+
+#ifdef PANORAMIX
+    if(!noPanoramiXExtension) {
+        sprite.hotLimits.x1 = -panoramiXdataPtr[0].x;
+        sprite.hotLimits.y1 = -panoramiXdataPtr[0].y;
+        sprite.hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
+        sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
+        sprite.physLimits = sprite.hotLimits;
+        sprite.screen = pScreen;
+    }
+#endif
+}
+
 /*
  * This does not take any shortcuts, and even ignores its argument, since
  * it does not happen very often, and one has to walk up the tree since
diff --git a/include/dix.h b/include/dix.h
index c1d609a..6a67d14 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -415,6 +415,9 @@ extern int DeliverDeviceEvents(
 extern void DefineInitialRootWindow(
     WindowPtr /* win */);
 
+extern void UpdateSpriteForScreen(
+     ScreenPtr /* pScreen */);
+
 extern void WindowHasNewCursor(
     WindowPtr /* pWin */);
 
diff --git a/mi/mipointer.c b/mi/mipointer.c
index b86a26a..24ff4cc 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -262,6 +262,7 @@ miPointerWarpCursor (pScreen, x, y)
 	miPointer.y = y;
 	miPointer.pScreen = pScreen;
     }
+    UpdateSpriteForScreen (pScreen) ;
 }
 
 /*


More information about the xorg-commit mailing list