[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