diff --git a/dix/main.c b/dix/main.c diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index e8001df..a4d72e4 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 + 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); + 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,57 @@ 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; + EPHYR_DBG ("current screen:%d\n", ephyrCurScreen) ; + miPointerWarpCursor (pScreen, x, y); + ephyrUnblockSigio (); +} + +miPointerScreenFuncRec ephyrPointerScreenFuncs = +{ + ephyrCursorOffScreen, + ephyrCrossScreen, + ephyrWarpCursor +}; + + void ephyrPoll(void) { @@ -751,18 +806,29 @@ 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) 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 ) + { + 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: if (!ephyrMouse || !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) continue; diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h index f49d920..1c9b4f8 100644 --- a/hw/kdrive/ephyr/ephyr.h +++ b/hw/kdrive/ephyr/ephyr.h @@ -71,6 +71,8 @@ extern KdCardFuncs ephyrFuncs; extern KdKeyboardInfo *ephyrKbd; extern KdPointerInfo *ephyrMouse; +extern miPointerScreenFuncRec ephyrPointerScreenFuncs; + Bool ephyrInitialize (KdCardInfo *card, EphyrPriv *priv); diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index a76da03..48f23df 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -33,6 +33,8 @@ extern Bool EphyrWantGrayScale; extern Bool kdHasPointer; extern Bool kdHasKbd; +void processScreenArg (char *screen_size, char *parent_id) ; + void InitCard (char *name) { @@ -100,19 +102,60 @@ ddxUseMsg (void) exit(1); } +void +processScreenArg (char *screen_size, char *parent_id) +{ + KdCardInfo *card; + static int card_exists; + + InitCard (0); /*Put each screen on a separate card*/ + card = KdCardInfoLast (); + + if (card) + { + KdScreenInfo *screen; + unsigned long p_id = 0; + + screen = KdScreenInfoAdd (card); + KdParseScreen (screen, screen_size); + + if (parent_id) + { + p_id = strtol (parent_id, NULL, 0); + } + EPHYR_DBG ("screen number:%d\n", screen->mynum) ; + hostx_add_screen (screen, p_id, screen->mynum); + } + else + { + ErrorF("No matching card found!\n"); + } +} + int ddxProcessArgument (int argc, char **argv, int i) { - EPHYR_DBG("mark"); + EPHYR_DBG("mark argv[%d]='%s'", i, argv[i] ); if (!strcmp (argv[i], "-parent")) { - if(i+1 < argc) + if(i+1 < argc) + { + processScreenArg ("100x100", argv[i+1]); + return 2; + } + + UseMsg(); + exit(1); + } + else if (!strcmp (argv[i], "-screen")) + { + if ((i+1) < argc) { - hostx_use_preexisting_window(strtol(argv[i+1], NULL, 0)); + processScreenArg (argv[i+1], NULL); return 2; - } - + } + UseMsg(); exit(1); } @@ -143,6 +186,11 @@ ddxProcessArgument (int argc, char **argv, int i) { hostx_set_display_name(argv[i]); } + else if (!KdCardInfoLast ()) + { + //processScreenArg ("640x480", NULL) ; + //return -1 ; + } return KdProcessArgument (argc, argv, i); } @@ -198,8 +246,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..e9841c2 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -47,33 +47,44 @@ * to get clobbered. */ +struct EphyrHostScreen +{ + Window win; + Window win_pre_existing; /* Set via -parent option like xnest */ + XImage *ximg; + int win_width, win_height; + int server_depth; + unsigned char *fb_data; /* only used when host bpp != server bpp */ + XShmSegmentInfo shminfo; + + void *info; /* Pointer to the screen this is associated with */ + int mynum; /* Screen number */ +}; + struct EphyrHostXVars { char *server_dpy_name; Display *dpy; int screen; Visual *visual; - Window win, winroot; - Window win_pre_existing; /* Set via -parent option like xnest */ + Window winroot; GC gc; int depth; - int server_depth; - XImage *ximg; - int win_width, win_height; Bool use_host_cursor; Bool use_fullscreen; Bool have_shm; + int n_screens; + struct EphyrHostScreen *screens; + long damage_debug_msec; - unsigned char *fb_data; /* only used when host bpp != server bpp */ unsigned long cmap[256]; - - XShmSegmentInfo shminfo; }; /* memset ( missing> ) instead of below */ -static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +/*static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};*/ +static EphyrHostXVars HostX; static int HostXWantDamageDebug = 0; @@ -89,8 +100,22 @@ hostx_set_fullscreen_hint(void); static int trapped_error_code = 0; static int (*old_error_handler) (Display *d, XErrorEvent *e); -#define host_depth_matches_server() (HostX.depth == HostX.server_depth) +#define host_depth_matches_server(_vars) (HostX.depth == (_vars)->server_depth) +static struct EphyrHostScreen * +host_screen_from_screen_info (EphyrScreenInfo *screen) +{ + int i; + + for (i = 0 ; i < HostX.n_screens ; i++) + { + if ( HostX.screens[i].info == screen) + { + return &HostX.screens[i]; + } + } + return NULL; +} static int error_handler(Display *display, @@ -115,13 +140,16 @@ hostx_errors_untrap(void) } int -hostx_want_screen_size(int *width, int *height) +hostx_want_screen_size (EphyrScreenInfo screen, int *width, int *height ) { - if (HostX.win_pre_existing != None - || HostX.use_fullscreen == True) + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen && + (host_screen->win_pre_existing != None || + HostX.use_fullscreen == True)) { - *width = HostX.win_width; - *height = HostX.win_height; + *width = host_screen->win_width; + *height = host_screen->win_height; return 1; } @@ -129,100 +157,140 @@ hostx_want_screen_size(int *width, int *height) } void -hostx_set_display_name(char *name) +hostx_add_screen (EphyrScreenInfo screen, + unsigned long win_id, + int screen_num) +{ + int index = HostX.n_screens; + + HostX.n_screens += 1; + HostX.screens = realloc (HostX.screens, + HostX.n_screens * sizeof(struct EphyrHostScreen)); + memset (&HostX.screens[index], 0, sizeof (struct EphyrHostScreen)); + + HostX.screens[index].info = screen; + HostX.screens[index].win_pre_existing = win_id; +} + + +void +hostx_set_display_name (char *name) { - HostX.server_dpy_name = strdup(name); + HostX.server_dpy_name = strdup (name); } void -hostx_set_win_title(char *extra_text) +hostx_set_screen_number(EphyrScreenInfo screen, int number) { - char buf[256]; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + if (host_screen) { + host_screen->mynum = number; + hostx_set_win_title (host_screen->info, "") ; + }} + +void +hostx_set_win_title (EphyrScreenInfo screen, char *extra_text) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); +#define BUF_LEN 256 + char buf[BUF_LEN+1]; + + if (!host_screen) + return; - snprintf(buf, 256, "Xephyr on %s %s", - HostX.server_dpy_name, - (extra_text != NULL) ? extra_text : ""); + memset (buf, 0, BUF_LEN+1) ; + snprintf (buf, BUF_LEN, "Xephyr on %s.%d %s", + HostX.server_dpy_name, + host_screen->mynum, + (extra_text != NULL) ? extra_text : ""); - XStoreName(HostX.dpy, HostX.win, buf); + XStoreName (HostX.dpy, host_screen->win, buf); } int -hostx_want_host_cursor(void) +hostx_want_host_cursor (void) { return HostX.use_host_cursor; } void -hostx_use_host_cursor(void) +hostx_use_host_cursor (void) { HostX.use_host_cursor = True; } int -hostx_want_preexisting_window(void) +hostx_want_preexisting_window (EphyrScreenInfo screen) { - if (HostX.win_pre_existing) - return 1; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen && host_screen->win_pre_existing) + { + return 1; + } else + { return 0; + } } void -hostx_use_fullscreen(void) +hostx_use_fullscreen (void) { HostX.use_fullscreen = True; } int -hostx_want_fullscreen(void) +hostx_want_fullscreen (void) { return HostX.use_fullscreen; } static void -hostx_set_fullscreen_hint(void) +hostx_set_fullscreen_hint (void) { Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN; + int index; atom_WINDOW_STATE = XInternAtom(HostX.dpy, "_NET_WM_STATE", False); atom_WINDOW_STATE_FULLSCREEN = XInternAtom(HostX.dpy, "_NET_WM_STATE_FULLSCREEN",False); - XChangeProperty(HostX.dpy, HostX.win, - atom_WINDOW_STATE, XA_ATOM, 32, - PropModeReplace, - (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1); + for (index = 0 ; index < HostX.n_screens ; index++) + { + XChangeProperty (HostX.dpy, HostX.screens[index].win, + atom_WINDOW_STATE, XA_ATOM, 32, + PropModeReplace, + (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1); + } } -void -hostx_use_preexisting_window(unsigned long win_id) -{ - HostX.win_pre_existing = win_id; -} static void -hostx_toggle_damage_debug(void) +hostx_toggle_damage_debug (void) { HostXWantDamageDebug ^= 1; } -void -hostx_handle_signal(int signum) +void +hostx_handle_signal (int signum) { hostx_toggle_damage_debug(); - EPHYR_DBG("Signal caught. Damage Debug:%i\n", HostXWantDamageDebug); + EPHYR_DBG ("Signal caught. Damage Debug:%i\n", + HostXWantDamageDebug); } int -hostx_init(void) +hostx_init (void) { XSetWindowAttributes attr; Cursor empty_cursor; Pixmap cursor_pxm; XColor col; + int index; - attr.event_mask = + attr.event_mask = ButtonPressMask |ButtonReleaseMask |PointerMotionMask @@ -233,126 +301,142 @@ hostx_init(void) EPHYR_DBG("mark"); if ((HostX.dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) - { - fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n"); - exit(1); - } + { + fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n"); + exit(1); + } HostX.screen = DefaultScreen(HostX.dpy); HostX.winroot = RootWindow(HostX.dpy, HostX.screen); HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL); HostX.depth = DefaultDepth(HostX.dpy, HostX.screen); - HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); + HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); - HostX.server_depth = HostX.depth; - - if (HostX.win_pre_existing != None) + for (index = 0 ; index < HostX.n_screens ; index++) { - Status result; - XWindowAttributes prewin_attr; - - /* Get screen size from existing window */ - - hostx_errors_trap(); - - result = XGetWindowAttributes(HostX.dpy, - HostX.win_pre_existing, - &prewin_attr); - - - if (hostx_errors_untrap() || !result) - { - fprintf(stderr, "\nXephyr -parent window' does not exist!\n"); - exit(1); - } - - HostX.win_width = prewin_attr.width; - HostX.win_height = prewin_attr.height; - - HostX.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); - - hostx_set_fullscreen_hint(); - } + struct EphyrHostScreen *host_screen = &HostX.screens[index]; + + host_screen->server_depth = HostX.depth; + if (host_screen->win_pre_existing != None) + { + Status result; + XWindowAttributes prewin_attr; + + /* Get screen size from existing window */ + + hostx_errors_trap(); + + result = XGetWindowAttributes (HostX.dpy, + host_screen->win_pre_existing, + &prewin_attr); + + + if (hostx_errors_untrap() || !result) + { + fprintf (stderr, "\nXephyr -parent window' does not exist!\n"); + exit (1); + } + + host_screen->win_width = prewin_attr.width; + host_screen->win_height = prewin_attr.height; + + host_screen->win = XCreateWindow (HostX.dpy, + host_screen->win_pre_existing, + 0,0, + host_screen->win_width, + host_screen->win_height, + 0, + CopyFromParent, + CopyFromParent, + CopyFromParent, + CWEventMask, + &attr); + } + else + { + host_screen->win = XCreateWindow (HostX.dpy, + HostX.winroot, + 0,0,100,100, /* will resize */ + 0, + CopyFromParent, + CopyFromParent, + CopyFromParent, + CWEventMask, + &attr); + + hostx_set_win_title (host_screen->info, + "(ctrl+shift grabs mouse and keyboard)"); + + if (HostX.use_fullscreen) + { + host_screen->win_width = DisplayWidth(HostX.dpy, HostX.screen); + host_screen->win_height = DisplayHeight(HostX.dpy, HostX.screen); + + hostx_set_fullscreen_hint(); + } + } } - XParseColor(HostX.dpy, DefaultColormap(HostX.dpy,HostX.screen), "red", &col); - XAllocColor(HostX.dpy, DefaultColormap(HostX.dpy, HostX.screen), &col); - XSetForeground(HostX.dpy, HostX.gc, col.pixel); + XParseColor (HostX.dpy, DefaultColormap (HostX.dpy,HostX.screen), + "red", &col); + XAllocColor (HostX.dpy, DefaultColormap (HostX.dpy, HostX.screen), + &col); + XSetForeground (HostX.dpy, HostX.gc, col.pixel); - if (!hostx_want_host_cursor()) + if (!hostx_want_host_cursor ()) { /* Ditch the cursor, we provide our 'own' */ cursor_pxm = XCreatePixmap (HostX.dpy, HostX.winroot, 1, 1, 1); memset (&col, 0, sizeof (col)); - empty_cursor = XCreatePixmapCursor (HostX.dpy, - cursor_pxm, cursor_pxm, - &col, &col, 1, 1); - XDefineCursor (HostX.dpy, HostX.win, empty_cursor); + empty_cursor = XCreatePixmapCursor (HostX.dpy, + cursor_pxm, cursor_pxm, + &col, &col, 1, 1); + for ( index = 0 ; index < HostX.n_screens ; index++ ) + { + XDefineCursor (HostX.dpy, + HostX.screens[index].win, + empty_cursor); + } XFreePixmap (HostX.dpy, cursor_pxm); } - HostX.ximg = NULL; - + for (index = 0 ; index < HostX.n_screens ; index++) + { + HostX.screens[index].ximg = NULL; + } /* Try to get share memory ximages for a little bit more speed */ - if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM")) + if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM")) { fprintf(stderr, "\nXephyr unable to use SHM XImages\n"); HostX.have_shm = False; - } - else - { + } + else + { /* Really really check we have shm - better way ?*/ - XShmSegmentInfo shminfo; + XShmSegmentInfo shminfo; - HostX.have_shm = True; + HostX.have_shm = True; - shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777); - shminfo.shmaddr=shmat(shminfo.shmid,0,0); - shminfo.readOnly=True; + shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777); + shminfo.shmaddr=shmat(shminfo.shmid,0,0); + shminfo.readOnly=True; - hostx_errors_trap(); - - XShmAttach(HostX.dpy, &shminfo); - XSync(HostX.dpy, False); + hostx_errors_trap(); - if (hostx_errors_untrap()) - { - fprintf(stderr, "\nXephyr unable to use SHM XImages\n"); - HostX.have_shm = False; - } + XShmAttach(HostX.dpy, &shminfo); + XSync(HostX.dpy, False); - shmdt(shminfo.shmaddr); - shmctl(shminfo.shmid, IPC_RMID, 0); - } + if (hostx_errors_untrap()) + { + fprintf(stderr, "\nXephyr unable to use SHM XImages\n"); + HostX.have_shm = False; + } + + shmdt(shminfo.shmaddr); + shmctl(shminfo.shmid, IPC_RMID, 0); +} XFlush(HostX.dpy); @@ -360,10 +444,10 @@ hostx_init(void) HostX.damage_debug_msec = 20000; /* 1/50 th of a second */ - if (getenv("XEPHYR_PAUSE")) + if (getenv ("XEPHYR_PAUSE")) { - HostX.damage_debug_msec = strtol(getenv("XEPHYR_PAUSE"), NULL, 0); - EPHYR_DBG("pause is %li\n", HostX.damage_debug_msec); + HostX.damage_debug_msec = strtol (getenv ("XEPHYR_PAUSE"), NULL, 0); + EPHYR_DBG ("pause is %li\n", HostX.damage_debug_msec); } return 1; @@ -376,38 +460,54 @@ hostx_get_depth (void) } int -hostx_get_server_depth (void) +hostx_get_server_depth (EphyrScreenInfo screen) { - return HostX.server_depth; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + return (host_screen ? host_screen->server_depth : 0); } void -hostx_set_server_depth(int depth) +hostx_set_server_depth (EphyrScreenInfo screen, int depth) { - HostX.server_depth = depth; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen) + host_screen->server_depth = depth; } int -hostx_get_bpp(void) +hostx_get_bpp (EphyrScreenInfo screen) { - if (host_depth_matches_server()) - return HostX.visual->bits_per_rgb; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (!host_screen) + return 0; + + if (host_depth_matches_server (host_screen)) + return HostX.visual->bits_per_rgb; else - return HostX.server_depth; /* XXX correct ? */ + return host_screen->server_depth; /*XXX correct ?*/ } void -hostx_get_visual_masks (CARD32 *rmsk, - CARD32 *gmsk, +hostx_get_visual_masks (EphyrScreenInfo screen, + CARD32 *rmsk, + CARD32 *gmsk, CARD32 *bmsk) { - if (host_depth_matches_server()) + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (!host_screen) + return; + + if (host_depth_matches_server(host_screen)) { *rmsk = HostX.visual->red_mask; *gmsk = HostX.visual->green_mask; *bmsk = HostX.visual->blue_mask; } - else if (HostX.server_depth == 16) + else if (host_screen->server_depth == 16) { /* Assume 16bpp 565 */ *rmsk = 0xf800; @@ -423,9 +523,9 @@ hostx_get_visual_masks (CARD32 *rmsk, } void -hostx_set_cmap_entry(unsigned char idx, - unsigned char r, - unsigned char g, +hostx_set_cmap_entry(unsigned char idx, + unsigned char r, + unsigned char g, unsigned char b) { /* XXX Will likely break for 8 on 16, not sure if this is correct */ @@ -445,15 +545,25 @@ hostx_set_cmap_entry(unsigned char idx, * by fakexa for storing offscreen pixmap data. */ void* -hostx_screen_init (int width, int height, int buffer_height) +hostx_screen_init (EphyrScreenInfo screen, + int width, int height, + int buffer_height) { int bitmap_pad; Bool shm_success = False; XSizeHints *size_hints; - EPHYR_DBG("mark"); + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + if (!host_screen) + { + fprintf (stderr, "%s: Error in accessing hostx data\n", __func__ ); + exit(1); + } - if (HostX.ximg != NULL) + EPHYR_DBG ("host_screen=%p wxh=%dx%d, buffer_height=%d", + host_screen, width, height, buffer_height); + + if (host_screen->ximg != NULL) { /* Free up the image data if previously used * i.ie called by server reset @@ -461,47 +571,48 @@ hostx_screen_init (int width, int height, 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, &host_screen->shminfo); + XDestroyImage (host_screen->ximg); + shmdt(host_screen->shminfo.shmaddr); + shmctl(host_screen->shminfo.shmid, IPC_RMID, 0); } else { - if (HostX.ximg->data) + if (host_screen->ximg->data) { - free(HostX.ximg->data); - HostX.ximg->data = NULL; + free(host_screen->ximg->data); + host_screen->ximg->data = NULL; } - XDestroyImage(HostX.ximg); + XDestroyImage(host_screen->ximg); } } if (HostX.have_shm) { - HostX.ximg = XShmCreateImage(HostX.dpy, HostX.visual, HostX.depth, - ZPixmap, NULL, &HostX.shminfo, - width, buffer_height ); - - HostX.shminfo.shmid = shmget(IPC_PRIVATE, - HostX.ximg->bytes_per_line * buffer_height, - IPC_CREAT|0777); - HostX.shminfo.shmaddr = HostX.ximg->data = shmat(HostX.shminfo.shmid, - 0, 0); - - if (HostX.ximg->data == (char *)-1) + host_screen->ximg = XShmCreateImage (HostX.dpy, HostX.visual, HostX.depth, + ZPixmap, NULL, &host_screen->shminfo, + width, buffer_height ); + + host_screen->shminfo.shmid = + shmget(IPC_PRIVATE, + host_screen->ximg->bytes_per_line * buffer_height, + IPC_CREAT|0777); + host_screen->ximg->data = shmat(host_screen->shminfo.shmid, 0, 0); + host_screen->shminfo.shmaddr = host_screen->ximg->data; + + if (host_screen->ximg->data == (char *)-1) { EPHYR_DBG("Can't attach SHM Segment, falling back to plain XImages"); HostX.have_shm = False; - XDestroyImage(HostX.ximg); - shmctl(HostX.shminfo.shmid, IPC_RMID, 0); + XDestroyImage(host_screen->ximg); + shmctl(host_screen->shminfo.shmid, IPC_RMID, 0); } else { - EPHYR_DBG("SHM segment attached"); - HostX.shminfo.readOnly = False; - XShmAttach(HostX.dpy, &HostX.shminfo); + EPHYR_DBG("SHM segment attached %p", host_screen->shminfo.shmaddr); + host_screen->shminfo.readOnly = False; + XShmAttach(HostX.dpy, &host_screen->shminfo); shm_success = True; } } @@ -509,63 +620,72 @@ 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 host_screen=%p\n", + width, buffer_height, host_screen ); + host_screen->ximg = XCreateImage (HostX.dpy, + HostX.visual, + HostX.depth, + ZPixmap, 0, 0, + width, + buffer_height, + bitmap_pad, + 0); + + host_screen->ximg->data = + malloc (host_screen->ximg->bytes_per_line * buffer_height); + } - XResizeWindow(HostX.dpy, HostX.win, width, height); + XResizeWindow (HostX.dpy, host_screen->win, width, height); /* Ask the WM to keep our size static */ size_hints = XAllocSizeHints(); size_hints->max_width = size_hints->min_width = width; size_hints->max_height = size_hints->min_height = height; size_hints->flags = PMinSize|PMaxSize; - XSetWMNormalHints(HostX.dpy, HostX.win, size_hints); + XSetWMNormalHints(HostX.dpy, host_screen->win, size_hints); XFree(size_hints); - XMapWindow(HostX.dpy, HostX.win); + XMapWindow(HostX.dpy, host_screen->win); XSync(HostX.dpy, False); - HostX.win_width = width; - HostX.win_height = height; + host_screen->win_width = width; + host_screen->win_height = height; - if (host_depth_matches_server()) + if (host_depth_matches_server(host_screen)) { EPHYR_DBG("Host matches server"); - return HostX.ximg->data; + return host_screen->ximg->data; } else { - EPHYR_DBG("server bpp %i", HostX.server_depth>>3); - HostX.fb_data = malloc(width*buffer_height*(HostX.server_depth>>3)); - return HostX.fb_data; + EPHYR_DBG("server bpp %i", host_screen->server_depth>>3); + host_screen->fb_data = malloc(width*buffer_height*(host_screen->server_depth>>3)); + return host_screen->fb_data; } } +static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen, + int x, int y, + int width, int height); + void -hostx_paint_rect(int sx, int sy, - int dx, int dy, - int width, int height) +hostx_paint_rect (EphyrScreenInfo screen, + int sx, int sy, + int dx, int dy, + int width, int height) { - /* + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + /* * Copy the image data updated by the shadow layer * on to the window */ if (HostXWantDamageDebug) { - hostx_paint_debug_rect(dx, dy, width, height); + hostx_paint_debug_rect(host_screen, dx, dy, width, height); } /* @@ -580,22 +700,23 @@ hostx_paint_rect(int sx, int sy, * ... and it will be slower than the matching depth case. */ - if (!host_depth_matches_server()) + if (!host_depth_matches_server(host_screen)) { - int x,y,idx, bytes_per_pixel = (HostX.server_depth>>3); + int x,y,idx, bytes_per_pixel = (host_screen->server_depth>>3); unsigned char r,g,b; unsigned long host_pixel; + EPHYR_DBG("Unmatched host depth host_screen=%p\n", host_screen); for (y=sy; ywin_width*y*bytes_per_pixel)+(x*bytes_per_pixel); + + switch (host_screen->server_depth) { case 16: { - unsigned short pixel = *(unsigned short*)(HostX.fb_data+idx); + unsigned short pixel = *(unsigned short*)(host_screen->fb_data+idx); r = ((pixel & 0xf800) >> 8); g = ((pixel & 0x07e0) >> 3); @@ -603,13 +724,13 @@ hostx_paint_rect(int sx, int sy, host_pixel = (r << 16) | (g << 8) | (b); - XPutPixel(HostX.ximg, x, y, host_pixel); + XPutPixel(host_screen->ximg, x, y, host_pixel); break; } case 8: { - unsigned char pixel = *(unsigned char*)(HostX.fb_data+idx); - XPutPixel(HostX.ximg, x, y, HostX.cmap[pixel]); + unsigned char pixel = *(unsigned char*)(host_screen->fb_data+idx); + XPutPixel(host_screen->ximg, x, y, HostX.cmap[pixel]); break; } default: @@ -620,21 +741,23 @@ hostx_paint_rect(int sx, int sy, if (HostX.have_shm) { - XShmPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, - sx, sy, dx, dy, width, height, False); + XShmPutImage (HostX.dpy, host_screen->win, + HostX.gc, host_screen->ximg, + sx, sy, dx, dy, width, height, False); } else { - XPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, - sx, sy, dx, dy, width, height); + XPutImage (HostX.dpy, host_screen->win, HostX.gc, host_screen->ximg, + sx, sy, dx, dy, width, height); } - XSync(HostX.dpy, False); + XSync (HostX.dpy, False); } -void -hostx_paint_debug_rect(int x, int y, - int width, int height) +static void +hostx_paint_debug_rect (struct EphyrHostScreen *host_screen, + int x, int y, + int width, int height) { struct timespec tspec; @@ -646,8 +769,8 @@ hostx_paint_debug_rect(int x, int y, /* fprintf(stderr, "Xephyr updating: %i+%i %ix%i\n", x, y, width, height); */ - XFillRectangle(HostX.dpy, HostX.win, HostX.gc, x, y, width,height); - XSync(HostX.dpy, False); + XFillRectangle (HostX.dpy, host_screen->win, HostX.gc, x, y, width,height); + XSync (HostX.dpy, False); /* nanosleep seems to work better than usleep for me... */ nanosleep(&tspec, NULL); @@ -660,14 +783,14 @@ hostx_load_keymap(void) int host_width, min_keycode, max_keycode, width; int i,j; - XDisplayKeycodes(HostX.dpy, &min_keycode, &max_keycode); + XDisplayKeycodes (HostX.dpy, &min_keycode, &max_keycode); - EPHYR_DBG("min: %d, max: %d", min_keycode, max_keycode); + EPHYR_DBG ("min: %d, max: %d", min_keycode, max_keycode); - keymap = XGetKeyboardMapping(HostX.dpy, - min_keycode, - max_keycode - min_keycode + 1, - &host_width); + keymap = XGetKeyboardMapping (HostX.dpy, + min_keycode, + max_keycode - min_keycode + 1, + &host_width); /* Try and copy the hosts keymap into our keymap to avoid loads * of messing around. @@ -688,7 +811,7 @@ hostx_load_keymap(void) ephyrKeySyms.map[(i*width)+j] = (CARD32) keymap[(i*host_width) + j]; EPHYR_DBG("keymap width, host:%d kdrive:%d", host_width, width); - + ephyrKeySyms.minKeyCode = min_keycode; ephyrKeySyms.maxKeyCode = max_keycode; ephyrKeySyms.mapWidth = width; @@ -696,11 +819,26 @@ hostx_load_keymap(void) XFree(keymap); } +static struct EphyrHostScreen * +host_screen_from_window (Window w) +{ + int index; + + for (index = 0 ; index < HostX.n_screens ; index++) + { + if (HostX.screens[index].win == w) + { + return &HostX.screens[index]; + } + } + return NULL; +} + int hostx_get_event(EphyrHostXEvent *ev) { XEvent xev; - static Bool grabbed; + static int grabbed_screen = -1; if (XPending(HostX.dpy)) { @@ -710,15 +848,27 @@ hostx_get_event(EphyrHostXEvent *ev) { case Expose: /* Not so great event compression, but works ok */ - while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window, + while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window, Expose, &xev)); - hostx_paint_rect(0, 0, 0, 0, HostX.win_width, HostX.win_height); + { + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xexpose.window); + hostx_paint_rect (host_screen->info, 0, 0, 0, 0, + host_screen->win_width, + host_screen->win_height); + } return 0; case MotionNotify: - ev->type = EPHYR_EV_MOUSE_MOTION; - ev->data.mouse_motion.x = xev.xmotion.x; - ev->data.mouse_motion.y = xev.xmotion.y; + { + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xmotion.window); + + ev->type = EPHYR_EV_MOUSE_MOTION; + ev->data.mouse_motion.x = xev.xmotion.x; + ev->data.mouse_motion.y = xev.xmotion.y; + ev->data.mouse_motion.screen = (host_screen ? host_screen->mynum : -1); + } return 1; case ButtonPress: @@ -750,29 +900,35 @@ hostx_get_event(EphyrHostXEvent *ev) || XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_R) && (xev.xkey.state & ControlMask)) { - if (grabbed) + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xexpose.window); + + if (grabbed_screen != -1) { XUngrabKeyboard (HostX.dpy, CurrentTime); XUngrabPointer (HostX.dpy, CurrentTime); - grabbed = False; - hostx_set_win_title("( ctrl+shift grabs mouse and keyboard )"); - } - else + grabbed_screen = -1; + hostx_set_win_title (host_screen->info, + "(ctrl+shift grabs mouse and keyboard)"); + } + else { /* Attempt grab */ - if (XGrabKeyboard (HostX.dpy, HostX.win, True, + if (XGrabKeyboard (HostX.dpy, host_screen->win, True, GrabModeAsync, GrabModeAsync, CurrentTime) == 0) { - if (XGrabPointer (HostX.dpy, HostX.win, True, + if (XGrabPointer (HostX.dpy, host_screen->win, True, NoEventMask, GrabModeAsync, GrabModeAsync, - HostX.win, None, CurrentTime) == 0) + host_screen->win, None, CurrentTime) == 0) { - grabbed = True; - hostx_set_win_title("( ctrl+shift releases mouse and keyboard )"); + grabbed_screen = host_screen->mynum; + hostx_set_win_title + (host_screen->info, + "(ctrl+shift releases mouse and keyboard)"); } else /* Failed pointer grabm ungrab keyboard */ XUngrabKeyboard (HostX.dpy, CurrentTime); diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 4d5f37f..93765d0 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -40,8 +40,8 @@ typedef struct EphyrHostXVars EphyrHostXVars; typedef struct EphyrHostXEvent EphyrHostXEvent; - -typedef enum EphyrHostXEventType +typedef void* EphyrScreenInfo ; +typedef enum EphyrHostXEventType { EPHYR_EV_MOUSE_MOTION, EPHYR_EV_MOUSE_PRESS, @@ -68,6 +68,7 @@ struct EphyrHostXEvent struct mouse_motion { int x; int y; + int screen; } mouse_motion; struct mouse_down { @@ -92,7 +93,7 @@ struct EphyrHostXEvent }; int -hostx_want_screen_size(int *width, int *height); +hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height); int hostx_want_host_cursor(void); @@ -107,7 +108,7 @@ int hostx_want_fullscreen(void); int -hostx_want_preexisting_window(void); +hostx_want_preexisting_window(EphyrScreenInfo screen); void hostx_use_preexisting_window(unsigned long win_id); @@ -119,25 +120,32 @@ int hostx_init(void); void +hostx_add_screen(EphyrScreenInfo screen, unsigned long win_id, int screen_num); + +void hostx_set_display_name(char *name); void -hostx_set_win_title(char *extra_text); +hostx_set_screen_number(EphyrScreenInfo screen, int number); + +void +hostx_set_win_title(EphyrScreenInfo screen, char *extra_text); int hostx_get_depth (void); int -hostx_get_server_depth (void); +hostx_get_server_depth (EphyrScreenInfo screen); void -hostx_set_server_depth(int depth); +hostx_set_server_depth(EphyrScreenInfo screen, int depth); int -hostx_get_bpp(void); +hostx_get_bpp(void *info); void -hostx_get_visual_masks (CARD32 *rmsk, +hostx_get_visual_masks (void *info, + CARD32 *rmsk, CARD32 *gmsk, CARD32 *bmsk); void @@ -147,15 +155,16 @@ hostx_set_cmap_entry(unsigned char idx, unsigned char b); void* -hostx_screen_init (int width, int height, int buffer_height); +hostx_screen_init (EphyrScreenInfo screen, + int width, int height, + int buffer_height); void -hostx_paint_rect(int sx, int sy, - int dx, int dy, +hostx_paint_rect(EphyrScreenInfo screen, + int sx, int sy, + int dx, int dy, int width, int height); -void -hostx_paint_debug_rect(int x, int y, - int width, int height); + void hostx_load_keymap(void); diff --git a/hw/kdrive/ephyr/os.c b/hw/kdrive/ephyr/os.c index 1a42495..b58daae 100644 --- a/hw/kdrive/ephyr/os.c +++ b/hw/kdrive/ephyr/os.c @@ -31,6 +31,14 @@ static int EphyrInit (void) { + /* + * make sure at least one screen + * has been added to the system. + */ + if (!KdCardInfoLast ()) + { + processScreenArg ("640x480", NULL) ; + } return hostx_init(); }