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@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.
This commit is contained in:
Andrew Christan 2007-10-02 13:25:51 +02:00 committed by Dodji Seketeli
parent 81692b628f
commit e5e6514ffa
6 changed files with 606 additions and 312 deletions

View File

@ -34,6 +34,7 @@
#include "ephyr.h" #include "ephyr.h"
#include "inputstr.h" #include "inputstr.h"
#include "scrnintstr.h"
extern int KdTsPhyScreen; extern int KdTsPhyScreen;
KdKeyboardInfo *ephyrKbd; KdKeyboardInfo *ephyrKbd;
@ -83,7 +84,7 @@ ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv)
int width = 640, height = 480; int width = 640, height = 480;
unsigned long redMask, greenMask, blueMask; 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 || !screen->height)
{ {
screen->width = width; 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 == 24 || screen->fb[0].depth == 16
|| screen->fb[0].depth == 8)) || 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"); 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; screen->rate = 72;
if (screen->fb[0].depth <= 8) if (screen->fb[0].depth <= 8)
@ -146,7 +147,7 @@ ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv)
screen->fb[0].bitsPerPixel = 32; 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].redMask = (Pixel) redMask;
screen->fb[0].greenMask = (Pixel) greenMask; screen->fb[0].greenMask = (Pixel) greenMask;
@ -194,9 +195,7 @@ ephyrWindowLinear (ScreenPtr pScreen,
EphyrPriv *priv = pScreenPriv->card->driver; EphyrPriv *priv = pScreenPriv->card->driver;
if (!pScreenPriv->enabled) if (!pScreenPriv->enabled)
{ return 0;
return 0;
}
*size = priv->bytes_per_line; *size = priv->bytes_per_line;
return priv->base + row * priv->bytes_per_line + offset; return priv->base + row * priv->bytes_per_line + offset;
@ -210,8 +209,8 @@ ephyrMapFramebuffer (KdScreenInfo *screen)
KdPointerMatrix m; KdPointerMatrix m;
int buffer_height; int buffer_height;
EPHYR_DBG(" screen->width: %d, screen->height: %d", EPHYR_DBG("screen->width: %d, screen->height: %d index=%d",
screen->width, screen->height); screen->width, screen->height, screen->mynum);
KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height);
KdSetPointerMatrix (&m); KdSetPointerMatrix (&m);
@ -226,8 +225,8 @@ ephyrMapFramebuffer (KdScreenInfo *screen)
buffer_height = screen->height; buffer_height = screen->height;
else else
buffer_height = 3 * screen->height; 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_base = (CARD8 *) (priv->base);
screen->memory_size = priv->bytes_per_line * buffer_height; screen->memory_size = priv->bytes_per_line * buffer_height;
@ -304,7 +303,7 @@ ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
* pBuf->pDamage regions * pBuf->pDamage regions
*/ */
shadowUpdateRotatePacked(pScreen, pBuf); 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 static void
@ -314,29 +313,29 @@ ephyrInternalDamageRedisplay (ScreenPtr pScreen)
KdScreenInfo *screen = pScreenPriv->screen; KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver; EphyrScrPriv *scrpriv = screen->driver;
RegionPtr pRegion; RegionPtr pRegion;
if (!scrpriv || !scrpriv->pDamage) if (!scrpriv || !scrpriv->pDamage)
return; return;
pRegion = DamageRegion (scrpriv->pDamage); pRegion = DamageRegion (scrpriv->pDamage);
if (REGION_NOTEMPTY (pScreen, pRegion)) if (REGION_NOTEMPTY (pScreen, pRegion))
{ {
int nbox; int nbox;
BoxPtr pbox; BoxPtr pbox;
nbox = REGION_NUM_RECTS (pRegion); nbox = REGION_NUM_RECTS (pRegion);
pbox = REGION_RECTS (pRegion); pbox = REGION_RECTS (pRegion);
while (nbox--) 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->x1, pbox->y1,
pbox->y2 - pbox->y1); pbox->x2 - pbox->x1,
pbox++; pbox->y2 - pbox->y1);
} pbox++;
}
DamageEmpty (scrpriv->pDamage); DamageEmpty (scrpriv->pDamage);
} }
} }
@ -432,11 +431,11 @@ ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
{ 160, 160 }, { 160, 160 },
{ 0, 0 } { 0, 0 }
}; };
*rotations = RR_Rotate_All|RR_Reflect_All; *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 */ && !hostx_want_fullscreen ()) /* only if no -parent switch */
{ {
while (sizes[n].width != 0 && sizes[n].height != 0) while (sizes[n].width != 0 && sizes[n].height != 0)
{ {
@ -586,9 +585,7 @@ ephyrRandRInit (ScreenPtr pScreen)
rrScrPrivPtr pScrPriv; rrScrPrivPtr pScrPriv;
if (!RRScreenInit (pScreen)) if (!RRScreenInit (pScreen))
{ return FALSE;
return FALSE;
}
pScrPriv = rrGetScrPriv(pScreen); pScrPriv = rrGetScrPriv(pScreen);
pScrPriv->rrGetInfo = ephyrRandRGetInfo; pScrPriv->rrGetInfo = ephyrRandRGetInfo;
@ -606,6 +603,12 @@ ephyrCreateColormap (ColormapPtr pmap)
Bool Bool
ephyrInitScreen (ScreenPtr pScreen) 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; pScreen->CreateColormap = ephyrCreateColormap;
return TRUE; return TRUE;
} }
@ -634,7 +637,8 @@ ephyrCreateResources (ScreenPtr pScreen)
KdScreenInfo *screen = pScreenPriv->screen; KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver; EphyrScrPriv *scrpriv = screen->driver;
EPHYR_DBG("mark"); EPHYR_DBG("mark pScreen=%p mynum=%d shadow=%d",
pScreen, pScreen->myNum, scrpriv->shadow);
if (scrpriv->shadow) if (scrpriv->shadow)
return KdShadowSet (pScreen, return KdShadowSet (pScreen,
@ -743,6 +747,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 void
ephyrPoll(void) ephyrPoll(void)
{ {
@ -751,21 +805,39 @@ ephyrPoll(void)
while (hostx_get_event(&ev)) while (hostx_get_event(&ev))
{ {
switch (ev.type) switch (ev.type)
{ {
case EPHYR_EV_MOUSE_MOTION: case EPHYR_EV_MOUSE_MOTION:
if (!ephyrMouse || if (!ephyrMouse ||
!((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) {
EPHYR_DBG ("skipping mouse motion:%d\n", ephyrCurScreen) ;
continue; continue;
KdEnqueuePointerEvent(ephyrMouse, mouseState, }
ev.data.mouse_motion.x, {
ev.data.mouse_motion.y, if (ephyrCurScreen != ev.data.mouse_motion.screen)
0); {
break; EPHYR_DBG ("warping mouse cursor:%d\n", ephyrCurScreen) ;
ephyrWarpCursor(screenInfo.screens[ev.data.mouse_motion.screen],
case EPHYR_EV_MOUSE_PRESS: 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 || if (!ephyrMouse ||
!((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) {
EPHYR_DBG ("skipping mouse press:%d\n", ephyrCurScreen) ;
continue; continue;
}
EPHYR_DBG ("enqueuing mouse press:%d\n", ephyrCurScreen) ;
ephyrUpdateModifierState(ev.key_state); ephyrUpdateModifierState(ev.key_state);
mouseState |= ev.data.mouse_down.button_num; mouseState |= ev.data.mouse_down.button_num;
KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0);
@ -777,6 +849,7 @@ ephyrPoll(void)
continue; continue;
ephyrUpdateModifierState(ev.key_state); ephyrUpdateModifierState(ev.key_state);
mouseState &= ~ev.data.mouse_up.button_num; mouseState &= ~ev.data.mouse_up.button_num;
EPHYR_DBG ("enqueuing mouse release:%d\n", ephyrCurScreen) ;
KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0);
break; break;
@ -792,7 +865,6 @@ ephyrPoll(void)
if (!ephyrKbd || if (!ephyrKbd ||
!((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled)
continue; continue;
ephyrUpdateModifierState(ev.key_state);
KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE); KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE);
break; break;

View File

@ -71,6 +71,8 @@ extern KdCardFuncs ephyrFuncs;
extern KdKeyboardInfo *ephyrKbd; extern KdKeyboardInfo *ephyrKbd;
extern KdPointerInfo *ephyrMouse; extern KdPointerInfo *ephyrMouse;
extern miPointerScreenFuncRec ephyrPointerScreenFuncs;
Bool Bool
ephyrInitialize (KdCardInfo *card, EphyrPriv *priv); ephyrInitialize (KdCardInfo *card, EphyrPriv *priv);

View File

@ -33,6 +33,8 @@ extern Bool EphyrWantGrayScale;
extern Bool kdHasPointer; extern Bool kdHasPointer;
extern Bool kdHasKbd; extern Bool kdHasKbd;
void processScreenArg (char *screen_size, char *parent_id) ;
void void
InitCard (char *name) InitCard (char *name)
{ {
@ -100,19 +102,60 @@ ddxUseMsg (void)
exit(1); 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 int
ddxProcessArgument (int argc, char **argv, int i) 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 (!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; return 2;
} }
UseMsg();
exit(1);
}
else if (!strcmp (argv[i], "-screen"))
{
if ((i+1) < argc)
{
processScreenArg (argv[i+1], NULL);
return 2;
}
UseMsg(); UseMsg();
exit(1); exit(1);
} }
@ -198,8 +241,10 @@ miPointerSpriteFuncRec EphyrPointerSpriteFuncs = {
Bool Bool
ephyrCursorInit(ScreenPtr pScreen) ephyrCursorInit(ScreenPtr pScreen)
{ {
miPointerInitialize(pScreen, &EphyrPointerSpriteFuncs, miPointerInitialize(pScreen,
&kdPointerScreenFuncs, FALSE); &EphyrPointerSpriteFuncs,
&ephyrPointerScreenFuncs,
FALSE);
return TRUE; return TRUE;
} }

File diff suppressed because it is too large Load Diff

View File

@ -40,8 +40,8 @@
typedef struct EphyrHostXVars EphyrHostXVars; typedef struct EphyrHostXVars EphyrHostXVars;
typedef struct EphyrHostXEvent EphyrHostXEvent; typedef struct EphyrHostXEvent EphyrHostXEvent;
typedef void* EphyrScreenInfo ;
typedef enum EphyrHostXEventType typedef enum EphyrHostXEventType
{ {
EPHYR_EV_MOUSE_MOTION, EPHYR_EV_MOUSE_MOTION,
EPHYR_EV_MOUSE_PRESS, EPHYR_EV_MOUSE_PRESS,
@ -68,6 +68,7 @@ struct EphyrHostXEvent
struct mouse_motion { struct mouse_motion {
int x; int x;
int y; int y;
int screen;
} mouse_motion; } mouse_motion;
struct mouse_down { struct mouse_down {
@ -92,7 +93,7 @@ struct EphyrHostXEvent
}; };
int int
hostx_want_screen_size(int *width, int *height); hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height);
int int
hostx_want_host_cursor(void); hostx_want_host_cursor(void);
@ -107,7 +108,7 @@ int
hostx_want_fullscreen(void); hostx_want_fullscreen(void);
int int
hostx_want_preexisting_window(void); hostx_want_preexisting_window(EphyrScreenInfo screen);
void void
hostx_use_preexisting_window(unsigned long win_id); hostx_use_preexisting_window(unsigned long win_id);
@ -118,26 +119,33 @@ hostx_handle_signal(int signum);
int int
hostx_init(void); hostx_init(void);
void
hostx_add_screen(EphyrScreenInfo screen, unsigned long win_id, int screen_num);
void void
hostx_set_display_name(char *name); hostx_set_display_name(char *name);
void 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 int
hostx_get_depth (void); hostx_get_depth (void);
int int
hostx_get_server_depth (void); hostx_get_server_depth (EphyrScreenInfo screen);
void void
hostx_set_server_depth(int depth); hostx_set_server_depth(EphyrScreenInfo screen, int depth);
int int
hostx_get_bpp(void); hostx_get_bpp(void *info);
void void
hostx_get_visual_masks (CARD32 *rmsk, hostx_get_visual_masks (void *info,
CARD32 *rmsk,
CARD32 *gmsk, CARD32 *gmsk,
CARD32 *bmsk); CARD32 *bmsk);
void void
@ -147,15 +155,16 @@ hostx_set_cmap_entry(unsigned char idx,
unsigned char b); unsigned char b);
void* void*
hostx_screen_init (int width, int height, int buffer_height); hostx_screen_init (EphyrScreenInfo screen,
int width, int height,
int buffer_height);
void void
hostx_paint_rect(int sx, int sy, hostx_paint_rect(EphyrScreenInfo screen,
int dx, int dy, int sx, int sy,
int dx, int dy,
int width, int height); int width, int height);
void
hostx_paint_debug_rect(int x, int y,
int width, int height);
void void
hostx_load_keymap(void); hostx_load_keymap(void);

View File

@ -31,6 +31,14 @@
static int static int
EphyrInit (void) EphyrInit (void)
{ {
/*
* make sure at least one screen
* has been added to the system.
*/
if (!KdCardInfoLast ())
{
processScreenArg ("640x480", NULL) ;
}
return hostx_init(); return hostx_init();
} }