Delivered-To: dodji.seketeli@gmail.com Received: by 10.82.108.11 with SMTP id g11cs509068buc; Mon, 6 Aug 2007 12:46:44 -0700 (PDT) Received: by 10.66.221.18 with SMTP id t18mr5387148ugg.1186429604565; Mon, 06 Aug 2007 12:46:44 -0700 (PDT) Return-Path: Received: from smtpout1.online.net (smtpout1.online.net [212.27.35.141]) by mx.google.com with ESMTP id m4si3088724ugc.2007.08.06.12.46.44; Mon, 06 Aug 2007 12:46:44 -0700 (PDT) Received-SPF: neutral (google.com: 212.27.35.141 is neither permitted nor denied by best guess record for domain of xorg-bounces@lists.freedesktop.org) Received: from mx6.online.net (mx6.online.net [212.27.35.136]) by smtpout1.online.net (Postfix) with SMTP id 103BA94AB35 for ; Mon, 6 Aug 2007 21:46:44 +0200 (CEST) Received: (qmail 9849 invoked by uid 189508); 6 Aug 2007 19:46:44 -0000 Delivered-To: seketeli.org-dodji@seketeli.org Received: (qmail 9846 invoked from network); 6 Aug 2007 19:46:44 -0000 Received: from 131.252.210.177 (HELO gabe.freedesktop.org) (131.252.210.177) by mx6.online.net with SMTP; 6 Aug 2007 19:46:44 -0000 Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A606A9E9B8; Mon, 6 Aug 2007 12:46:39 -0700 (PDT) X-Original-To: xorg@lists.freedesktop.org Delivered-To: xorg@lists.freedesktop.org Received: from mgw-ext12.nokia.com (smtp.nokia.com [131.228.20.171]) by gabe.freedesktop.org (Postfix) with ESMTP id D96F89E95B for ; Mon, 6 Aug 2007 12:46:35 -0700 (PDT) Received: from esebh106.NOE.Nokia.com (esebh106.ntc.nokia.com [172.21.138.213]) by mgw-ext12.nokia.com (Switch-3.2.5/Switch-3.2.5) with ESMTP id l76JJja0020541 for ; Mon, 6 Aug 2007 22:20:00 +0300 Received: from daebh102.NOE.Nokia.com ([10.241.35.112]) by esebh106.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 6 Aug 2007 22:19:54 +0300 Received: from daebe102.NOE.Nokia.com ([10.241.35.115]) by daebh102.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 6 Aug 2007 14:19:52 -0500 x-mimeole: Produced By Microsoft Exchange V6.5 Content-class: urn:content-classes:message MIME-Version: 1.0 Subject: [PATCH] Ephyr multiple screen implementation Date: Mon, 6 Aug 2007 14:19:51 -0500 Message-ID: X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: [PATCH] Ephyr multiple screen implementation Thread-Index: AcfYXsKHpTMwk4owRqyLYK3xQSRzrQ== From: To: X-OriginalArrivalTime: 06 Aug 2007 19:19:52.0525 (UTC) FILETIME=[C3B457D0:01C7D85E] X-Nokia-AV: Clean X-BeenThere: xorg@lists.freedesktop.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Discuss issues related to the xorg tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: xorg-bounces@lists.freedesktop.org Errors-To: xorg-bounces@lists.freedesktop.org X-Virus-Scanned: ClamAV using ClamSMTP 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; ywin_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 _______________________________________________ xorg mailing list xorg@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/xorg