[PATCH] Ephyr multiple screen implementation

Andrew.Christian at nokia.com Andrew.Christian at nokia.com
Mon Aug 6 12:19:51 PDT 2007


This patch adds multiple screen support to Xephyr.

  - Andrew



---
 hw/kdrive/ephyr/ephyr.c     |  106 ++++++++--
 hw/kdrive/ephyr/ephyr.h     |    2 +
 hw/kdrive/ephyr/ephyrinit.c |   46 ++++-
 hw/kdrive/ephyr/hostx.c     |  488
++++++++++++++++++++++++++----------------
 hw/kdrive/ephyr/hostx.h     |   31 ++-
 5 files changed, 448 insertions(+), 225 deletions(-)

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index e8001df..8bc40e8 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 *screen,
EphyrScrPriv *scrpriv)
   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 *screen,
EphyrScrPriv *scrpriv)
 	  && (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 
 	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 *screen,
EphyrScrPriv *scrpriv)
 	  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,10 +195,8 @@ 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 *screen)
   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);
@@ -227,7 +226,7 @@ ephyrMapFramebuffer (KdScreenInfo *screen)
   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, shadowBufPtr
pBuf)
    * 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
@@ -324,13 +323,14 @@ ephyrInternalDamageRedisplay (ScreenPtr pScreen)
     {
       int           nbox;
       BoxPtr        pbox;
-      
+  
       nbox = REGION_NUM_RECTS (pRegion);
       pbox = REGION_RECTS (pRegion);
       
       while (nbox--)
 	{
-	  hostx_paint_rect(pbox->x1, pbox->y1,
+	  hostx_paint_rect(screen, 
+			   pbox->x1, pbox->y1,
 			   pbox->x1, pbox->y1,
 			   pbox->x2 - pbox->x1,
 			   pbox->y2 - pbox->y1);
@@ -435,7 +435,7 @@ ephyrRandRGetInfo (ScreenPtr pScreen, Rotation
*rotations)
   
   *rotations = RR_Rotate_All|RR_Reflect_All;
   
-  if (!hostx_want_preexisting_window()
+  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 +586,7 @@ ephyrRandRInit (ScreenPtr pScreen)
   rrScrPrivPtr    pScrPriv;
   
   if (!RRScreenInit (pScreen))
-    {
-      return FALSE;
-    }
+    return FALSE;
   
   pScrPriv = rrGetScrPriv(pScreen);
   pScrPriv->rrGetInfo = ephyrRandRGetInfo;
@@ -606,6 +604,11 @@ ephyrCreateColormap (ColormapPtr pmap)
 Bool
 ephyrInitScreen (ScreenPtr pScreen)
 {
+  KdScreenPriv(pScreen);
+  KdScreenInfo	*screen    = pScreenPriv->screen;
+
+  hostx_set_screen_number( screen, pScreen->myNum );
+
   pScreen->CreateColormap = ephyrCreateColormap;
   return TRUE;
 }
@@ -634,7 +637,7 @@ 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 +746,56 @@ ephyrUpdateModifierState(unsigned int state)
     }
 }
 
+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)
 {
@@ -756,10 +809,17 @@ ephyrPoll(void)
           if (!ephyrMouse ||
               !((EphyrPointerPrivate
*)ephyrMouse->driverPrivate)->enabled)
               continue;
-	  KdEnqueuePointerEvent(ephyrMouse, mouseState,  
-			        ev.data.mouse_motion.x, 
-			        ev.data.mouse_motion.y,
-                                0);
+	  {
+	    if ( ephyrCurScreen != ev.data.mouse_motion.screen )
+	      ephyrWarpCursor(
screenInfo.screens[ev.data.mouse_motion.screen],
+			       ev.data.mouse_motion.x, 
+			       ev.data.mouse_motion.y );
+	    else
+	      KdEnqueuePointerEvent(ephyrMouse, mouseState,  
+				    ev.data.mouse_motion.x, 
+				    ev.data.mouse_motion.y,
+				    0);
+	  }
 	  break;
 	  
 	case EPHYR_EV_MOUSE_PRESS:
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 45e2d30..1a72871 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -87,16 +87,52 @@ ddxUseMsg (void)
   exit(1);
 }
 
+static void
+process_screen_arg( char *screen_size, char *parent_id )
+{
+  KdCardInfo   *card;
+
+  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 );
+      hostx_add_screen( screen, p_id );
+    } 
+  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) 
 	{
-	  hostx_use_preexisting_window(strtol(argv[i+1], NULL, 0));
+	  process_screen_arg( "100x100", argv[i+1]);
+	  return 2;
+	} 
+      
+      UseMsg();
+      exit(1);
+    }
+  else if (!strcmp (argv[i], "-screen"))
+    {
+      if ((i+1) < argc) 
+	{
+	  process_screen_arg( argv[i+1], NULL );
 	  return 2;
 	} 
       
@@ -185,8 +221,10 @@ miPointerSpriteFuncRec EphyrPointerSpriteFuncs = {
 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..ed7d0a3 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -47,33 +47,44 @@
  * to get clobbered. 
  */
 
+struct EphyrHostScreenVars
+{
+  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 EphyrHostScreenVars *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,19 @@ 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 EphyrHostScreenVars *
+screen_vars_from_screen_info( void *info )
+{
+  int i;
+
+  for ( i = 0 ; i < HostX.n_screens ; i++ )
+    if ( HostX.screens[i].info == info )
+      return &HostX.screens[i];
 
+  return NULL;
+}
 
 static int
 error_handler(Display     *display,
@@ -115,13 +137,16 @@ hostx_errors_untrap(void)
 }
 
 int
-hostx_want_screen_size(int *width, int *height)
+hostx_want_screen_size( void *info, int *width, int *height )
 {
- if (HostX.win_pre_existing != None
-     || HostX.use_fullscreen == True)
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+
+  if ( vars && 
+       ( vars->win_pre_existing != None ||
+	 HostX.use_fullscreen == True ))
     {
-      *width  = HostX.win_width;
-      *height = HostX.win_height;
+      *width  = vars->win_width;
+      *height = vars->win_height;
       return 1;
     }
 
@@ -129,21 +154,51 @@ hostx_want_screen_size(int *width, int *height)
 }
 
 void
+hostx_add_screen( void *info, unsigned long win_id )
+{
+  int index = HostX.n_screens;
+  
+  HostX.n_screens += 1;
+  HostX.screens = realloc( HostX.screens, 
+			   HostX.n_screens * sizeof(struct
EphyrHostScreenVars));
+  memset( &HostX.screens[index], 0, sizeof(struct
EphyrHostScreenVars));
+
+  HostX.screens[index].info       = info;
+  HostX.screens[index].win_pre_existing = win_id;
+}
+
+
+void
 hostx_set_display_name(char *name)
 {
   HostX.server_dpy_name = strdup(name);
 }
 
 void
-hostx_set_win_title(char *extra_text)
+hostx_set_screen_number(void *info, int number)
+{
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+  if ( vars ) {
+    vars->mynum = number;
+    hostx_set_win_title( vars->info, "" );
+  }
+}
+
+void
+hostx_set_win_title( void *info, char *extra_text )
 {
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
   char buf[256];
 
-  snprintf(buf, 256, "Xephyr on %s %s", 
-	   HostX.server_dpy_name,
+  if ( !vars )
+    return;
+
+  snprintf(buf, 256, "Xephyr on %s.%d %s", 
+	   HostX.server_dpy_name, 
+	   vars->mynum,
 	   (extra_text != NULL) ? extra_text : "");
 
-  XStoreName(HostX.dpy, HostX.win, buf);
+  XStoreName(HostX.dpy, vars->win, buf);
 }
 
 int
@@ -159,9 +214,11 @@ hostx_use_host_cursor(void)
 }
 
 int
-hostx_want_preexisting_window(void)
+hostx_want_preexisting_window( void *info )
 {
-  if (HostX.win_pre_existing) 
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+
+  if (vars && vars->win_pre_existing) 
     return 1;
   else
     return 0;
@@ -183,23 +240,20 @@ static 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)
@@ -221,6 +275,7 @@ hostx_init(void)
   Cursor                empty_cursor;
   Pixmap                cursor_pxm;
   XColor                col;
+  int                   index;
 
   attr.event_mask = 
     ButtonPressMask
@@ -244,63 +299,66 @@ hostx_init(void)
   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;
+  for ( index = 0 ; index < HostX.n_screens ; index++ ) {
+    struct EphyrHostScreenVars *vars = &HostX.screens[index];
 
-      /* Get screen size from existing window */
+    vars->server_depth = HostX.depth;
+    if (vars->win_pre_existing != None)
+      {
+	Status            result;
+	XWindowAttributes prewin_attr;
 
-      hostx_errors_trap();
+	/* Get screen size from existing window */
 
-      result = XGetWindowAttributes(HostX.dpy, 
-				    HostX.win_pre_existing, 
-				    &prewin_attr);
+	hostx_errors_trap();
 
+	result = XGetWindowAttributes(HostX.dpy, 
+				      vars->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.win = XCreateWindow(HostX.dpy,
-				HostX.win_pre_existing,
-				0,0,HostX.win_width,HostX.win_height,
-				0,
-				CopyFromParent,
-				CopyFromParent,
-				CopyFromParent,
-				CWEventMask,
-				&attr);
-    }
-  else
-    {
-      HostX.win = XCreateWindow(HostX.dpy,
-				HostX.winroot,
-				0,0,100,100, /* will resize  */
-				0,
-			        CopyFromParent,
-				CopyFromParent,
-				CopyFromParent,
-				CWEventMask,
-				&attr);
-
-      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); 
+	if (hostx_errors_untrap() || !result)
+	  {
+	    fprintf(stderr, "\nXephyr -parent window' does not
exist!\n");
+	    exit(1);
+	  }
 
-	  hostx_set_fullscreen_hint();
-	}
-    }
+	vars->win_width  = prewin_attr.width;
+	vars->win_height = prewin_attr.height;
+
+	vars->win = XCreateWindow(HostX.dpy,
+					     vars->win_pre_existing,
+
0,0,vars->win_width,vars->win_height,
+					     0,
+					     CopyFromParent,
+					     CopyFromParent,
+					     CopyFromParent,
+					     CWEventMask,
+					     &attr);
+      }
+    else
+      {
+	vars->win = XCreateWindow(HostX.dpy,
+					     HostX.winroot,
+					     0,0,100,100, /* will resize
*/
+					     0,
+					     CopyFromParent,
+					     CopyFromParent,
+					     CopyFromParent,
+					     CWEventMask,
+					     &attr);
+
+	hostx_set_win_title( vars->info, "( ctrl+shift grabs mouse and
keyboard )");
+
+	if (HostX.use_fullscreen)
+	  {
+	    vars->win_width  = DisplayWidth(HostX.dpy, HostX.screen); 
+	    vars->win_height = DisplayHeight(HostX.dpy, HostX.screen); 
+
+	    hostx_set_fullscreen_hint();
+	  }
+      }
+  }
 
 
   XParseColor(HostX.dpy, DefaultColormap(HostX.dpy,HostX.screen),
"red", &col);
@@ -315,12 +373,14 @@ hostx_init(void)
       empty_cursor = XCreatePixmapCursor (HostX.dpy, 
 					  cursor_pxm, cursor_pxm, 
 					  &col, &col, 1, 1);
-      XDefineCursor (HostX.dpy, HostX.win, empty_cursor);
+      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")) 
@@ -332,26 +392,26 @@ hostx_init(void)
     {	
       /* Really really check we have shm - better way ?*/
       XShmSegmentInfo shminfo; 
-
-      HostX.have_shm = 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);
-
-      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);
+	HostX.have_shm = 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);
+	
+	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);
@@ -376,38 +436,54 @@ hostx_get_depth (void)
 }
 
 int
-hostx_get_server_depth (void)
+hostx_get_server_depth (void *info)
 {
-  return HostX.server_depth;
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+
+  return ( vars ? vars->server_depth : 0 );
 }
 
 void
-hostx_set_server_depth(int depth)
+hostx_set_server_depth (void *info, int depth)
 {
-  HostX.server_depth = depth;
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+
+  if ( vars )
+    vars->server_depth = depth;
 }
 
 int
-hostx_get_bpp(void)
+hostx_get_bpp(void *info)
 {
-  if (host_depth_matches_server())
-    return  HostX.visual->bits_per_rgb;
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+
+  if ( !vars )
+    return 0;
+
+  if (host_depth_matches_server(vars))
+    return HostX.visual->bits_per_rgb;
   else
-    return HostX.server_depth; 	/* XXX correct ? */
+    return vars->server_depth; 	/* XXX correct ? */
 }
 
 void
-hostx_get_visual_masks (CARD32 *rmsk, 
+hostx_get_visual_masks (void   *info,
+			CARD32 *rmsk, 
 			CARD32 *gmsk, 
 			CARD32 *bmsk)
 {
-  if (host_depth_matches_server())
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+
+  if ( !vars )
+    return;
+
+  if (host_depth_matches_server(vars))
     {
       *rmsk = HostX.visual->red_mask;
       *gmsk = HostX.visual->green_mask;
       *bmsk = HostX.visual->blue_mask;
     }
-  else if (HostX.server_depth == 16)
+  else if (vars->server_depth == 16)
     {
       /* Assume 16bpp 565 */
       *rmsk = 0xf800;
@@ -445,15 +521,21 @@ 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 (void *info, int width, int height, int
buffer_height)
 {
   int         bitmap_pad;
   Bool        shm_success = False;
   XSizeHints *size_hints;
 
-  EPHYR_DBG("mark");
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+  if ( !vars ) {
+    fprintf(stderr, "%s: Error in accessing hostx data\n", __func__ );
+    exit(1);
+  }
+
+  EPHYR_DBG("vars=%p wxh=%dx%d, buffer_height=%d", vars, width, height,
buffer_height);
 
-  if (HostX.ximg != NULL)
+  if (vars->ximg != NULL)
     {
       /* Free up the image data if previously used
        * i.ie called by server reset
@@ -461,47 +543,47 @@ hostx_screen_init (int width, int height, int
buffer_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, &vars->shminfo);
+	  XDestroyImage (vars->ximg);
+	  shmdt(vars->shminfo.shmaddr);
+	  shmctl(vars->shminfo.shmid, IPC_RMID, 0);
 	}
       else
 	{
-	  if (HostX.ximg->data) 
+	  if (vars->ximg->data) 
 	    {
-	      free(HostX.ximg->data);
-	      HostX.ximg->data = NULL;
+	      free(vars->ximg->data);
+	      vars->ximg->data = NULL;
 	    } 
 
-	  XDestroyImage(HostX.ximg);
+	  XDestroyImage(vars->ximg);
 	}
     }
 
   if (HostX.have_shm)
     {
-      HostX.ximg = XShmCreateImage(HostX.dpy, HostX.visual,
HostX.depth, 
-				   ZPixmap, NULL, &HostX.shminfo,
+      vars->ximg = XShmCreateImage(HostX.dpy, HostX.visual,
HostX.depth, 
+				   ZPixmap, NULL, &vars->shminfo,
 				   width, buffer_height );
 	  
-      HostX.shminfo.shmid = shmget(IPC_PRIVATE,
-				   HostX.ximg->bytes_per_line *
buffer_height,
+      vars->shminfo.shmid = shmget(IPC_PRIVATE,
+				   vars->ximg->bytes_per_line *
buffer_height,
 				   IPC_CREAT|0777);
-      HostX.shminfo.shmaddr = HostX.ximg->data =
shmat(HostX.shminfo.shmid,
-						       0, 0);
+      vars->ximg->data = shmat(vars->shminfo.shmid, 0, 0);
+      vars->shminfo.shmaddr = vars->ximg->data;
 
-      if (HostX.ximg->data == (char *)-1)
+      if (vars->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(vars->ximg);
+	  shmctl(vars->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", vars->shminfo.shmaddr);
+	  vars->shminfo.readOnly = False;
+	  XShmAttach(HostX.dpy, &vars->shminfo);
 	  shm_success = True;
 	}
     }
@@ -509,55 +591,65 @@ hostx_screen_init (int width, int height, int
buffer_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 vars=%p\n", width,
buffer_height, vars );
+      vars->ximg = XCreateImage( HostX.dpy, 
+						HostX.visual, 
+						HostX.depth, 
+						ZPixmap, 0, 0,
+						width, 
+						buffer_height, 
+						bitmap_pad, 
+						0);
+
+      vars->ximg->data = malloc( vars->ximg->bytes_per_line *
buffer_height );
+    }
 
-  XResizeWindow(HostX.dpy, HostX.win, width, height);
+  XResizeWindow(HostX.dpy, vars->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, vars->win, size_hints);
   XFree(size_hints);
 
-  XMapWindow(HostX.dpy, HostX.win);
+  XMapWindow(HostX.dpy, vars->win);
 
   XSync(HostX.dpy, False);
 
-  HostX.win_width  = width;
-  HostX.win_height = height;
+  vars->win_width  = width;
+  vars->win_height = height;
 
-  if (host_depth_matches_server())
+  if (host_depth_matches_server(vars))
     {
       EPHYR_DBG("Host matches server");
-      return HostX.ximg->data;
+      return vars->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", vars->server_depth>>3);
+      vars->fb_data =
malloc(width*buffer_height*(vars->server_depth>>3));
+      return vars->fb_data;
     }
 }
 
+static void hostx_paint_debug_rect(struct EphyrHostScreenVars *vars,
+				   int x,     int y, 
+				   int width, int height);
+
 void
-hostx_paint_rect(int sx,    int sy,
+hostx_paint_rect(void *info,
+		 int sx,    int sy,
 		 int dx,    int dy, 
 		 int width, int height)
 {
+  struct EphyrHostScreenVars *vars = screen_vars_from_screen_info( info
);
+
+  //  EPHYR_DBG(" screen=%p s=%d,%d d=%d,%d size=%dx%d",
+  //	    vars, sx, sy, dx, dy, width, height );
+  
   /* 
    *  Copy the image data updated by the shadow layer
    *  on to the window
@@ -565,7 +657,7 @@ hostx_paint_rect(int sx,    int sy,
 
   if (HostXWantDamageDebug)
     {
-      hostx_paint_debug_rect(dx, dy, width, height);
+      hostx_paint_debug_rect(vars, dx, dy, width, height);
     }
 
   /* 
@@ -580,22 +672,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(vars))
     {
-      int            x,y,idx, bytes_per_pixel =
(HostX.server_depth>>3);
+      int            x,y,idx, bytes_per_pixel =
(vars->server_depth>>3);
       unsigned char  r,g,b;
       unsigned long  host_pixel;
 
+      EPHYR_DBG("Unmatched host depth vars=%p\n", vars);
       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);
+	    idx =
(vars->win_width*y*bytes_per_pixel)+(x*bytes_per_pixel);
 	    
-	    switch (HostX.server_depth)
+	    switch (vars->server_depth)
 	      {
 	      case 16:
 		{
-		  unsigned short pixel = *(unsigned
short*)(HostX.fb_data+idx);
+		  unsigned short pixel = *(unsigned
short*)(vars->fb_data+idx);
 
 		  r = ((pixel & 0xf800) >> 8);
 		  g = ((pixel & 0x07e0) >> 3);
@@ -603,13 +696,13 @@ hostx_paint_rect(int sx,    int sy,
 
 		  host_pixel = (r << 16) | (g << 8) | (b);
 		  
-		  XPutPixel(HostX.ximg, x, y, host_pixel);
+		  XPutPixel(vars->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*)(vars->fb_data+idx);
+		  XPutPixel(vars->ximg, x, y, HostX.cmap[pixel]);
 		  break;
 		}
 	      default:
@@ -620,20 +713,21 @@ hostx_paint_rect(int sx,    int sy,
 
   if (HostX.have_shm)
     {
-      XShmPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, 
+      XShmPutImage(HostX.dpy, vars->win, HostX.gc, vars->ximg, 
 		       sx, sy, dx, dy, width, height, False);
     }
   else
     {
-      XPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, 
+      XPutImage(HostX.dpy, vars->win, HostX.gc, vars->ximg, 
 		sx, sy, dx, dy, width, height);
     }
 
   XSync(HostX.dpy, False);
 }
 
-void
-hostx_paint_debug_rect(int x,     int y, 
+static void
+hostx_paint_debug_rect(struct EphyrHostScreenVars *vars,
+		       int x,     int y, 
 		       int width, int height)
 {
   struct timespec tspec;
@@ -646,7 +740,7 @@ 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); 
+  XFillRectangle(HostX.dpy, vars->win, HostX.gc, x, y, width,height); 
   XSync(HostX.dpy, False);
 
   /* nanosleep seems to work better than usleep for me... */
@@ -696,11 +790,23 @@ hostx_load_keymap(void)
   XFree(keymap);
 }
 
+static struct EphyrHostScreenVars *
+vars_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))
     {
@@ -712,13 +818,21 @@ hostx_get_event(EphyrHostXEvent *ev)
 	  /* Not so great event compression, but works ok */
 	  while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window, 
 					Expose, &xev));
-	  hostx_paint_rect(0, 0, 0, 0, HostX.win_width,
HostX.win_height);
+	  {
+	    struct EphyrHostScreenVars *vars = vars_from_window(
xev.xexpose.window );
+	    hostx_paint_rect(vars->info, 0, 0, 0, 0, vars->win_width,
vars->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 EphyrHostScreenVars *vars = vars_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 = ( vars ? vars->mynum : -1 );
+	  }
 	  return 1;
 
 	case ButtonPress:
@@ -750,29 +864,31 @@ hostx_get_event(EphyrHostXEvent *ev)
 	       || XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) ==
XK_Shift_R)
 	      && (xev.xkey.state & ControlMask))
 	    {
-	      if (grabbed) 
+	      struct EphyrHostScreenVars *vars = vars_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 )");
+		  grabbed_screen = -1;
+		  hostx_set_win_title(vars->info, "( ctrl+shift grabs
mouse and keyboard )");
 		} 
 	      else 
 		{
 		  /* Attempt grab */
-		  if (XGrabKeyboard (HostX.dpy, HostX.win, True, 
+		  if (XGrabKeyboard (HostX.dpy, vars->win, True, 
 				     GrabModeAsync, 
 				     GrabModeAsync, 
 				     CurrentTime) == 0)
 		    {
-		      if (XGrabPointer (HostX.dpy, HostX.win, True, 
+		      if (XGrabPointer (HostX.dpy, vars->win, True, 
 					NoEventMask, 
 					GrabModeAsync, 
 					GrabModeAsync, 
-					HostX.win, None, CurrentTime) ==
0)
+					vars->win, None, CurrentTime) ==
0)
 			{
-			  grabbed = True;
-			  hostx_set_win_title("( ctrl+shift releases
mouse and keyboard )");
+			  grabbed_screen = vars->mynum;
+			  hostx_set_win_title(vars->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..5115818 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -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(void *info, 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(void *info);
 
 void
 hostx_use_preexisting_window(unsigned long win_id);
@@ -119,25 +120,32 @@ int
 hostx_init(void);
 
 void
+hostx_add_screen(void *info, unsigned long win_id);
+
+void
 hostx_set_display_name(char *name);
 
 void
-hostx_set_win_title(char *extra_text);
+hostx_set_screen_number(void *info, int number);
+
+void
+hostx_set_win_title(void *info, char *extra_text);
 
 int
 hostx_get_depth (void);
 
 int
-hostx_get_server_depth (void);
+hostx_get_server_depth (void *info);
 
 void
-hostx_set_server_depth(int depth);
+hostx_set_server_depth(void *info, 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,14 @@ hostx_set_cmap_entry(unsigned char idx,
 		     unsigned char b);
 
 void*
-hostx_screen_init (int width, int height, int buffer_height);
+hostx_screen_init (void *info, int width, int height, int
buffer_height);
 
 void
-hostx_paint_rect(int sx,    int sy,
+hostx_paint_rect(void *info,
+		 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);
-- 
1.4.4.2



More information about the xorg mailing list