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 "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
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,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 *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);
@ -226,8 +225,8 @@ ephyrMapFramebuffer (KdScreenInfo *screen)
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, 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
@ -314,29 +313,29 @@ ephyrInternalDamageRedisplay (ScreenPtr pScreen)
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, Rotation *rotations)
{ 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 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)
{
@ -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;

View File

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

View File

@ -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 EphyrPointerSpriteFuncs = {
Bool
ephyrCursorInit(ScreenPtr pScreen)
{
miPointerInitialize(pScreen, &EphyrPointerSpriteFuncs,
&kdPointerScreenFuncs, FALSE);
miPointerInitialize(pScreen,
&EphyrPointerSpriteFuncs,
&ephyrPointerScreenFuncs,
FALSE);
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@ -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);
@ -118,26 +119,33 @@ hostx_handle_signal(int signum);
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);

View File

@ -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();
}