1135 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1135 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Xephyr - A kdrive X server thats runs in a host X window.
 | 
						|
 *          Authored by Matthew Allum <mallum@openedhand.com>
 | 
						|
 * 
 | 
						|
 * Copyright © 2004 Nokia 
 | 
						|
 *
 | 
						|
 * Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
 * documentation for any purpose is hereby granted without fee, provided that
 | 
						|
 * the above copyright notice appear in all copies and that both that
 | 
						|
 * copyright notice and this permission notice appear in supporting
 | 
						|
 * documentation, and that the name of Nokia not be used in
 | 
						|
 * advertising or publicity pertaining to distribution of the software without
 | 
						|
 * specific, written prior permission. Nokia makes no
 | 
						|
 * representations about the suitability of this software for any purpose.  It
 | 
						|
 * is provided "as is" without express or implied warranty.
 | 
						|
 *
 | 
						|
 * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | 
						|
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | 
						|
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
						|
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
						|
 * PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_CONFIG_H
 | 
						|
#include <kdrive-config.h>
 | 
						|
#endif
 | 
						|
#include "ephyr.h"
 | 
						|
 | 
						|
#include "inputstr.h"
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "ephyrlog.h"
 | 
						|
 | 
						|
#ifdef XF86DRI
 | 
						|
#include "ephyrdri.h"
 | 
						|
#include "ephyrdriext.h"
 | 
						|
#include "ephyrglxext.h"
 | 
						|
#endif                          /* XF86DRI */
 | 
						|
 | 
						|
#include "xkbsrv.h"
 | 
						|
 | 
						|
extern int KdTsPhyScreen;
 | 
						|
 | 
						|
#ifdef GLXEXT
 | 
						|
extern Bool noGlxVisualInit;
 | 
						|
#endif
 | 
						|
 | 
						|
KdKeyboardInfo *ephyrKbd;
 | 
						|
KdPointerInfo *ephyrMouse;
 | 
						|
EphyrKeySyms ephyrKeySyms;
 | 
						|
Bool ephyrNoDRI = FALSE;
 | 
						|
Bool ephyrNoXV = FALSE;
 | 
						|
 | 
						|
static int mouseState = 0;
 | 
						|
static Rotation ephyrRandr = RR_Rotate_0;
 | 
						|
 | 
						|
typedef struct _EphyrInputPrivate {
 | 
						|
    Bool enabled;
 | 
						|
} EphyrKbdPrivate, EphyrPointerPrivate;
 | 
						|
 | 
						|
Bool EphyrWantGrayScale = 0;
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrInitialize(KdCardInfo * card, EphyrPriv * priv)
 | 
						|
{
 | 
						|
    OsSignal(SIGUSR1, hostx_handle_signal);
 | 
						|
 | 
						|
    priv->base = 0;
 | 
						|
    priv->bytes_per_line = 0;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrCardInit(KdCardInfo * card)
 | 
						|
{
 | 
						|
    EphyrPriv *priv;
 | 
						|
 | 
						|
    priv = (EphyrPriv *) malloc(sizeof(EphyrPriv));
 | 
						|
    if (!priv)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (!ephyrInitialize(card, priv)) {
 | 
						|
        free(priv);
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
    card->driver = priv;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrScreenInitialize(KdScreenInfo * screen, EphyrScrPriv * scrpriv)
 | 
						|
{
 | 
						|
    int width = 640, height = 480;
 | 
						|
    CARD32 redMask, greenMask, blueMask;
 | 
						|
 | 
						|
    if (hostx_want_screen_size(screen, &width, &height)
 | 
						|
        || !screen->width || !screen->height) {
 | 
						|
        screen->width = width;
 | 
						|
        screen->height = height;
 | 
						|
    }
 | 
						|
 | 
						|
    if (EphyrWantGrayScale)
 | 
						|
        screen->fb.depth = 8;
 | 
						|
 | 
						|
    if (screen->fb.depth && screen->fb.depth != hostx_get_depth()) {
 | 
						|
        if (screen->fb.depth < hostx_get_depth()
 | 
						|
            && (screen->fb.depth == 24 || screen->fb.depth == 16
 | 
						|
                || screen->fb.depth == 8)) {
 | 
						|
            hostx_set_server_depth(screen, screen->fb.depth);
 | 
						|
        }
 | 
						|
        else
 | 
						|
            ErrorF
 | 
						|
                ("\nXephyr: requested screen depth not supported, setting to match hosts.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    screen->fb.depth = hostx_get_server_depth(screen);
 | 
						|
    screen->rate = 72;
 | 
						|
 | 
						|
    if (screen->fb.depth <= 8) {
 | 
						|
        if (EphyrWantGrayScale)
 | 
						|
            screen->fb.visuals = ((1 << StaticGray) | (1 << GrayScale));
 | 
						|
        else
 | 
						|
            screen->fb.visuals = ((1 << StaticGray) |
 | 
						|
                                  (1 << GrayScale) |
 | 
						|
                                  (1 << StaticColor) |
 | 
						|
                                  (1 << PseudoColor) |
 | 
						|
                                  (1 << TrueColor) | (1 << DirectColor));
 | 
						|
 | 
						|
        screen->fb.redMask = 0x00;
 | 
						|
        screen->fb.greenMask = 0x00;
 | 
						|
        screen->fb.blueMask = 0x00;
 | 
						|
        screen->fb.depth = 8;
 | 
						|
        screen->fb.bitsPerPixel = 8;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        screen->fb.visuals = (1 << TrueColor);
 | 
						|
 | 
						|
        if (screen->fb.depth <= 15) {
 | 
						|
            screen->fb.depth = 15;
 | 
						|
            screen->fb.bitsPerPixel = 16;
 | 
						|
        }
 | 
						|
        else if (screen->fb.depth <= 16) {
 | 
						|
            screen->fb.depth = 16;
 | 
						|
            screen->fb.bitsPerPixel = 16;
 | 
						|
        }
 | 
						|
        else if (screen->fb.depth <= 24) {
 | 
						|
            screen->fb.depth = 24;
 | 
						|
            screen->fb.bitsPerPixel = 32;
 | 
						|
        }
 | 
						|
        else if (screen->fb.depth <= 30) {
 | 
						|
            screen->fb.depth = 30;
 | 
						|
            screen->fb.bitsPerPixel = 32;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            ErrorF("\nXephyr: Unsupported screen depth %d\n", screen->fb.depth);
 | 
						|
            return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        hostx_get_visual_masks(screen, &redMask, &greenMask, &blueMask);
 | 
						|
 | 
						|
        screen->fb.redMask = (Pixel) redMask;
 | 
						|
        screen->fb.greenMask = (Pixel) greenMask;
 | 
						|
        screen->fb.blueMask = (Pixel) blueMask;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    scrpriv->randr = screen->randr;
 | 
						|
 | 
						|
    return ephyrMapFramebuffer(screen);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrScreenInit(KdScreenInfo * screen)
 | 
						|
{
 | 
						|
    EphyrScrPriv *scrpriv;
 | 
						|
 | 
						|
    scrpriv = calloc(1, sizeof(EphyrScrPriv));
 | 
						|
 | 
						|
    if (!scrpriv)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    screen->driver = scrpriv;
 | 
						|
 | 
						|
    if (!ephyrScreenInitialize(screen, scrpriv)) {
 | 
						|
        screen->driver = 0;
 | 
						|
        free(scrpriv);
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void *
 | 
						|
ephyrWindowLinear(ScreenPtr pScreen,
 | 
						|
                  CARD32 row,
 | 
						|
                  CARD32 offset, int mode, CARD32 *size, void *closure)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    EphyrPriv *priv = pScreenPriv->card->driver;
 | 
						|
 | 
						|
    if (!pScreenPriv->enabled)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    *size = priv->bytes_per_line;
 | 
						|
    return priv->base + row * priv->bytes_per_line + offset;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Figure out display buffer size. If fakexa is enabled, allocate a larger
 | 
						|
 * buffer so that fakexa has space to put offscreen pixmaps.
 | 
						|
 */
 | 
						|
int
 | 
						|
ephyrBufferHeight(KdScreenInfo * screen)
 | 
						|
{
 | 
						|
    int buffer_height;
 | 
						|
 | 
						|
    if (ephyrFuncs.initAccel == NULL)
 | 
						|
        buffer_height = screen->height;
 | 
						|
    else
 | 
						|
        buffer_height = 3 * screen->height;
 | 
						|
    return buffer_height;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrMapFramebuffer(KdScreenInfo * screen)
 | 
						|
{
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
    EphyrPriv *priv = screen->card->driver;
 | 
						|
    KdPointerMatrix m;
 | 
						|
    int buffer_height;
 | 
						|
 | 
						|
    EPHYR_LOG("screen->width: %d, screen->height: %d index=%d",
 | 
						|
              screen->width, screen->height, screen->mynum);
 | 
						|
 | 
						|
    /*
 | 
						|
     * Use the rotation last applied to ourselves (in the Xephyr case the fb
 | 
						|
     * coordinate system moves independently of the pointer coordiante system).
 | 
						|
     */
 | 
						|
    KdComputePointerMatrix(&m, ephyrRandr, screen->width, screen->height);
 | 
						|
    KdSetPointerMatrix(&m);
 | 
						|
 | 
						|
    priv->bytes_per_line =
 | 
						|
        ((screen->width * screen->fb.bitsPerPixel + 31) >> 5) << 2;
 | 
						|
 | 
						|
    buffer_height = ephyrBufferHeight(screen);
 | 
						|
 | 
						|
    priv->base =
 | 
						|
        hostx_screen_init(screen, screen->width, screen->height, buffer_height);
 | 
						|
 | 
						|
    if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) {
 | 
						|
        scrpriv->shadow = FALSE;
 | 
						|
 | 
						|
        screen->fb.byteStride = priv->bytes_per_line;
 | 
						|
        screen->fb.pixelStride = screen->width;
 | 
						|
        screen->fb.frameBuffer = (CARD8 *) (priv->base);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        /* Rotated/Reflected so we need to use shadow fb */
 | 
						|
        scrpriv->shadow = TRUE;
 | 
						|
 | 
						|
        EPHYR_LOG("allocing shadow");
 | 
						|
 | 
						|
        KdShadowFbAlloc(screen,
 | 
						|
                        scrpriv->randr & (RR_Rotate_90 | RR_Rotate_270));
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrSetScreenSizes(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
 | 
						|
    if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) {
 | 
						|
        pScreen->width = screen->width;
 | 
						|
        pScreen->height = screen->height;
 | 
						|
        pScreen->mmWidth = screen->width_mm;
 | 
						|
        pScreen->mmHeight = screen->height_mm;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        pScreen->width = screen->height;
 | 
						|
        pScreen->height = screen->width;
 | 
						|
        pScreen->mmWidth = screen->height_mm;
 | 
						|
        pScreen->mmHeight = screen->width_mm;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrUnmapFramebuffer(KdScreenInfo * screen)
 | 
						|
{
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
 | 
						|
    if (scrpriv->shadow)
 | 
						|
        KdShadowFbFree(screen);
 | 
						|
 | 
						|
    /* Note, priv->base will get freed when XImage recreated */
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
 | 
						|
    EPHYR_LOG("slow paint");
 | 
						|
 | 
						|
    /* FIXME: Slow Rotated/Reflected updates could be much
 | 
						|
     * much faster efficiently updating via tranforming 
 | 
						|
     * pBuf->pDamage  regions     
 | 
						|
     */
 | 
						|
    shadowUpdateRotatePacked(pScreen, pBuf);
 | 
						|
    hostx_paint_rect(screen, 0, 0, 0, 0, screen->width, screen->height);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
ephyrInternalDamageRedisplay(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
    RegionPtr pRegion;
 | 
						|
 | 
						|
    if (!scrpriv || !scrpriv->pDamage)
 | 
						|
        return;
 | 
						|
 | 
						|
    pRegion = DamageRegion(scrpriv->pDamage);
 | 
						|
 | 
						|
    if (RegionNotEmpty(pRegion)) {
 | 
						|
        int nbox;
 | 
						|
        BoxPtr pbox;
 | 
						|
 | 
						|
        nbox = RegionNumRects(pRegion);
 | 
						|
        pbox = RegionRects(pRegion);
 | 
						|
 | 
						|
        while (nbox--) {
 | 
						|
            hostx_paint_rect(screen,
 | 
						|
                             pbox->x1, pbox->y1,
 | 
						|
                             pbox->x1, pbox->y1,
 | 
						|
                             pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
 | 
						|
            pbox++;
 | 
						|
        }
 | 
						|
        DamageEmpty(scrpriv->pDamage);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
ephyrInternalDamageBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = (ScreenPtr) data;
 | 
						|
 | 
						|
    ephyrInternalDamageRedisplay(pScreen);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
ephyrInternalDamageWakeupHandler(pointer data, int i, pointer LastSelectMask)
 | 
						|
{
 | 
						|
    /* FIXME: Not needed ? */
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrSetInternalDamage(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
    PixmapPtr pPixmap = NULL;
 | 
						|
 | 
						|
    scrpriv->pDamage = DamageCreate((DamageReportFunc) 0,
 | 
						|
                                    (DamageDestroyFunc) 0,
 | 
						|
                                    DamageReportNone, TRUE, pScreen, pScreen);
 | 
						|
 | 
						|
    if (!RegisterBlockAndWakeupHandlers(ephyrInternalDamageBlockHandler,
 | 
						|
                                        ephyrInternalDamageWakeupHandler,
 | 
						|
                                        (pointer) pScreen))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
 | 
						|
 | 
						|
    DamageRegister(&pPixmap->drawable, scrpriv->pDamage);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrUnsetInternalDamage(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
    PixmapPtr pPixmap = NULL;
 | 
						|
 | 
						|
    pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
 | 
						|
    DamageUnregister(&pPixmap->drawable, scrpriv->pDamage);
 | 
						|
    DamageDestroy(scrpriv->pDamage);
 | 
						|
 | 
						|
    RemoveBlockAndWakeupHandlers(ephyrInternalDamageBlockHandler,
 | 
						|
                                 ephyrInternalDamageWakeupHandler,
 | 
						|
                                 (pointer) pScreen);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef RANDR
 | 
						|
Bool
 | 
						|
ephyrRandRGetInfo(ScreenPtr pScreen, Rotation * rotations)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
    RRScreenSizePtr pSize;
 | 
						|
    Rotation randr;
 | 
						|
    int n = 0;
 | 
						|
 | 
						|
    struct {
 | 
						|
        int width, height;
 | 
						|
    } sizes[] = {
 | 
						|
        {
 | 
						|
        1600, 1200}, {
 | 
						|
        1400, 1050}, {
 | 
						|
        1280, 960}, {
 | 
						|
        1280, 1024}, {
 | 
						|
        1152, 864}, {
 | 
						|
        1024, 768}, {
 | 
						|
        832, 624}, {
 | 
						|
        800, 600}, {
 | 
						|
        720, 400}, {
 | 
						|
        480, 640}, {
 | 
						|
        640, 480}, {
 | 
						|
        640, 400}, {
 | 
						|
        320, 240}, {
 | 
						|
        240, 320}, {
 | 
						|
        160, 160}, {
 | 
						|
        0, 0}
 | 
						|
    };
 | 
						|
 | 
						|
    EPHYR_LOG("mark");
 | 
						|
 | 
						|
    *rotations = RR_Rotate_All | RR_Reflect_All;
 | 
						|
 | 
						|
    if (!hostx_want_preexisting_window(screen)
 | 
						|
        && !hostx_want_fullscreen()) {  /* only if no -parent switch */
 | 
						|
        while (sizes[n].width != 0 && sizes[n].height != 0) {
 | 
						|
            RRRegisterSize(pScreen,
 | 
						|
                           sizes[n].width,
 | 
						|
                           sizes[n].height,
 | 
						|
                           (sizes[n].width * screen->width_mm) / screen->width,
 | 
						|
                           (sizes[n].height * screen->height_mm) /
 | 
						|
                           screen->height);
 | 
						|
            n++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    pSize = RRRegisterSize(pScreen,
 | 
						|
                           screen->width,
 | 
						|
                           screen->height, screen->width_mm, screen->height_mm);
 | 
						|
 | 
						|
    randr = KdSubRotation(scrpriv->randr, screen->randr);
 | 
						|
 | 
						|
    RRSetCurrentConfig(pScreen, randr, 0, pSize);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrRandRSetConfig(ScreenPtr pScreen,
 | 
						|
                    Rotation randr, int rate, RRScreenSizePtr pSize)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
    Bool wasEnabled = pScreenPriv->enabled;
 | 
						|
    EphyrScrPriv oldscr;
 | 
						|
    int oldwidth, oldheight, oldmmwidth, oldmmheight;
 | 
						|
    Bool oldshadow;
 | 
						|
    int newwidth, newheight;
 | 
						|
 | 
						|
    if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) {
 | 
						|
        newwidth = pSize->width;
 | 
						|
        newheight = pSize->height;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        newwidth = pSize->height;
 | 
						|
        newheight = pSize->width;
 | 
						|
    }
 | 
						|
 | 
						|
    if (wasEnabled)
 | 
						|
        KdDisableScreen(pScreen);
 | 
						|
 | 
						|
    oldscr = *scrpriv;
 | 
						|
 | 
						|
    oldwidth = screen->width;
 | 
						|
    oldheight = screen->height;
 | 
						|
    oldmmwidth = pScreen->mmWidth;
 | 
						|
    oldmmheight = pScreen->mmHeight;
 | 
						|
    oldshadow = scrpriv->shadow;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Set new configuration
 | 
						|
     */
 | 
						|
 | 
						|
    /*
 | 
						|
     * We need to store the rotation value for pointer coords transformation;
 | 
						|
     * though initially the pointer and fb rotation are identical, when we map
 | 
						|
     * the fb, the screen will be reinitialized and return into an unrotated
 | 
						|
     * state (presumably the HW is taking care of the rotation of the fb), but the
 | 
						|
     * pointer still needs to be transformed.
 | 
						|
     */
 | 
						|
    ephyrRandr = KdAddRotation(screen->randr, randr);
 | 
						|
    scrpriv->randr = ephyrRandr;
 | 
						|
 | 
						|
    ephyrUnmapFramebuffer(screen);
 | 
						|
 | 
						|
    screen->width = newwidth;
 | 
						|
    screen->height = newheight;
 | 
						|
 | 
						|
    if (!ephyrMapFramebuffer(screen))
 | 
						|
        goto bail4;
 | 
						|
 | 
						|
    /* FIXME below should go in own call */
 | 
						|
 | 
						|
    if (oldshadow)
 | 
						|
        KdShadowUnset(screen->pScreen);
 | 
						|
    else
 | 
						|
        ephyrUnsetInternalDamage(screen->pScreen);
 | 
						|
 | 
						|
    if (scrpriv->shadow) {
 | 
						|
        if (!KdShadowSet(screen->pScreen,
 | 
						|
                         scrpriv->randr, ephyrShadowUpdate, ephyrWindowLinear))
 | 
						|
            goto bail4;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        /* Without shadow fb ( non rotated ) we need 
 | 
						|
         * to use damage to efficiently update display
 | 
						|
         * via signal regions what to copy from 'fb'.
 | 
						|
         */
 | 
						|
        if (!ephyrSetInternalDamage(screen->pScreen))
 | 
						|
            goto bail4;
 | 
						|
    }
 | 
						|
 | 
						|
    ephyrSetScreenSizes(screen->pScreen);
 | 
						|
 | 
						|
    /*
 | 
						|
     * Set frame buffer mapping
 | 
						|
     */
 | 
						|
    (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap(pScreen),
 | 
						|
                                    pScreen->width,
 | 
						|
                                    pScreen->height,
 | 
						|
                                    screen->fb.depth,
 | 
						|
                                    screen->fb.bitsPerPixel,
 | 
						|
                                    screen->fb.byteStride,
 | 
						|
                                    screen->fb.frameBuffer);
 | 
						|
 | 
						|
    /* set the subpixel order */
 | 
						|
 | 
						|
    KdSetSubpixelOrder(pScreen, scrpriv->randr);
 | 
						|
 | 
						|
    if (wasEnabled)
 | 
						|
        KdEnableScreen(pScreen);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
 | 
						|
 bail4:
 | 
						|
    EPHYR_LOG("bailed");
 | 
						|
 | 
						|
    ephyrUnmapFramebuffer(screen);
 | 
						|
    *scrpriv = oldscr;
 | 
						|
    (void) ephyrMapFramebuffer(screen);
 | 
						|
 | 
						|
    pScreen->width = oldwidth;
 | 
						|
    pScreen->height = oldheight;
 | 
						|
    pScreen->mmWidth = oldmmwidth;
 | 
						|
    pScreen->mmHeight = oldmmheight;
 | 
						|
 | 
						|
    if (wasEnabled)
 | 
						|
        KdEnableScreen(pScreen);
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrRandRInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    rrScrPrivPtr pScrPriv;
 | 
						|
 | 
						|
    if (!RRScreenInit(pScreen))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    pScrPriv = rrGetScrPriv(pScreen);
 | 
						|
    pScrPriv->rrGetInfo = ephyrRandRGetInfo;
 | 
						|
    pScrPriv->rrSetConfig = ephyrRandRSetConfig;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrCreateColormap(ColormapPtr pmap)
 | 
						|
{
 | 
						|
    return fbInitializeColormap(pmap);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrInitScreen(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
 | 
						|
    EPHYR_LOG("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;
 | 
						|
 | 
						|
#ifdef XV
 | 
						|
    if (!ephyrNoXV) {
 | 
						|
        if (!ephyrInitVideo(pScreen)) {
 | 
						|
            EPHYR_LOG_ERROR("failed to initialize xvideo\n");
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            EPHYR_LOG("initialized xvideo okay\n");
 | 
						|
        }
 | 
						|
    }
 | 
						|
#endif /*XV*/
 | 
						|
#ifdef XF86DRI
 | 
						|
        if (!ephyrNoDRI && !hostx_has_dri()) {
 | 
						|
        EPHYR_LOG("host x does not support DRI. Disabling DRI forwarding\n");
 | 
						|
        ephyrNoDRI = TRUE;
 | 
						|
#ifdef GLXEXT
 | 
						|
        noGlxVisualInit = FALSE;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
    if (!ephyrNoDRI) {
 | 
						|
        ephyrDRIExtensionInit(pScreen);
 | 
						|
        ephyrHijackGLXExtension();
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef GLXEXT
 | 
						|
    if (ephyrNoDRI) {
 | 
						|
        noGlxVisualInit = FALSE;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrFinishInitScreen(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    /* FIXME: Calling this even if not using shadow.  
 | 
						|
     * Seems harmless enough. But may be safer elsewhere.
 | 
						|
     */
 | 
						|
    if (!shadowSetup(pScreen))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
#ifdef RANDR
 | 
						|
    if (!ephyrRandRInit(pScreen))
 | 
						|
        return FALSE;
 | 
						|
#endif
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrCreateResources(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
 | 
						|
    EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d",
 | 
						|
              pScreen, pScreen->myNum, scrpriv->shadow);
 | 
						|
 | 
						|
    if (scrpriv->shadow)
 | 
						|
        return KdShadowSet(pScreen,
 | 
						|
                           scrpriv->randr,
 | 
						|
                           ephyrShadowUpdate, ephyrWindowLinear);
 | 
						|
    else
 | 
						|
        return ephyrSetInternalDamage(pScreen);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrPreserve(KdCardInfo * card)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrEnable(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ephyrDPMS(ScreenPtr pScreen, int mode)
 | 
						|
{
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrDisable(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrRestore(KdCardInfo * card)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrScreenFini(KdScreenInfo * screen)
 | 
						|
{
 | 
						|
    EphyrScrPriv *scrpriv = screen->driver;
 | 
						|
 | 
						|
    if (scrpriv->shadow) {
 | 
						|
        KdShadowFbFree(screen);
 | 
						|
    }
 | 
						|
    free(screen->driver);
 | 
						|
    screen->driver = NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*  
 | 
						|
 * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug.
 | 
						|
 * See https://bugs.freedesktop.org/show_bug.cgi?id=3030
 | 
						|
 */
 | 
						|
void
 | 
						|
ephyrUpdateModifierState(unsigned int state)
 | 
						|
{
 | 
						|
 | 
						|
    DeviceIntPtr pDev = inputInfo.keyboard;
 | 
						|
    KeyClassPtr keyc = pDev->key;
 | 
						|
    int i;
 | 
						|
    CARD8 mask;
 | 
						|
    int xkb_state;
 | 
						|
 | 
						|
    if (!pDev)
 | 
						|
        return;
 | 
						|
 | 
						|
    xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state);
 | 
						|
    state = state & 0xff;
 | 
						|
 | 
						|
    if (xkb_state == state)
 | 
						|
        return;
 | 
						|
 | 
						|
    for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
 | 
						|
        int key;
 | 
						|
 | 
						|
        /* Modifier is down, but shouldn't be
 | 
						|
         */
 | 
						|
        if ((xkb_state & mask) && !(state & mask)) {
 | 
						|
            int count = keyc->modifierKeyCount[i];
 | 
						|
 | 
						|
            for (key = 0; key < MAP_LENGTH; key++)
 | 
						|
                if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
 | 
						|
                    if (key_is_down(pDev, key, KEY_PROCESSED))
 | 
						|
                        KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE);
 | 
						|
 | 
						|
                    if (--count == 0)
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
        }
 | 
						|
 | 
						|
        /* Modifier shoud be down, but isn't
 | 
						|
         */
 | 
						|
        if (!(xkb_state & mask) && (state & mask))
 | 
						|
            for (key = 0; key < MAP_LENGTH; key++)
 | 
						|
                if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
 | 
						|
                    KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE);
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 | 
						|
{
 | 
						|
    ephyrBlockSigio();
 | 
						|
    ephyrCurScreen = pScreen->myNum;
 | 
						|
    miPointerWarpCursor(inputInfo.pointer, pScreen, x, y);
 | 
						|
 | 
						|
    ephyrUnblockSigio();
 | 
						|
}
 | 
						|
 | 
						|
miPointerScreenFuncRec ephyrPointerScreenFuncs = {
 | 
						|
    ephyrCursorOffScreen,
 | 
						|
    ephyrCrossScreen,
 | 
						|
    ephyrWarpCursor,
 | 
						|
    NULL,
 | 
						|
    NULL
 | 
						|
};
 | 
						|
 | 
						|
#ifdef XF86DRI
 | 
						|
/**
 | 
						|
 * find if the remote window denoted by a_remote
 | 
						|
 * is paired with an internal Window within the Xephyr server.
 | 
						|
 * If the remove window is paired with an internal window, send an
 | 
						|
 * expose event to the client insterested in the internal window expose event.
 | 
						|
 *
 | 
						|
 * Pairing happens when a drawable inside Xephyr is associated with
 | 
						|
 * a GL surface in a DRI environment.
 | 
						|
 * Look at the function ProcXF86DRICreateDrawable in ephyrdriext.c to
 | 
						|
 * know a paired window is created.
 | 
						|
 *
 | 
						|
 * This is useful to make GL drawables (only windows for now) handle
 | 
						|
 * expose events and send those events to clients.
 | 
						|
 */
 | 
						|
static void
 | 
						|
ephyrExposePairedWindow(int a_remote)
 | 
						|
{
 | 
						|
    EphyrWindowPair *pair = NULL;
 | 
						|
    RegionRec reg;
 | 
						|
    ScreenPtr screen;
 | 
						|
 | 
						|
    if (!findWindowPairFromRemote(a_remote, &pair)) {
 | 
						|
        EPHYR_LOG("did not find a pair for this window\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    screen = pair->local->drawable.pScreen;
 | 
						|
    RegionNull(®);
 | 
						|
    RegionCopy(®, &pair->local->clipList);
 | 
						|
    screen->WindowExposures(pair->local, ®, NullRegion);
 | 
						|
    RegionUninit(®);
 | 
						|
}
 | 
						|
#endif                          /* XF86DRI */
 | 
						|
 | 
						|
void
 | 
						|
ephyrPoll(void)
 | 
						|
{
 | 
						|
    EphyrHostXEvent ev;
 | 
						|
 | 
						|
    while (hostx_get_event(&ev)) {
 | 
						|
        switch (ev.type) {
 | 
						|
        case EPHYR_EV_MOUSE_MOTION:
 | 
						|
            if (!ephyrMouse ||
 | 
						|
                !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) {
 | 
						|
                EPHYR_LOG("skipping mouse motion:%d\n", ephyrCurScreen);
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            {
 | 
						|
                if (ev.data.mouse_motion.screen >= 0
 | 
						|
                    && (ephyrCurScreen != ev.data.mouse_motion.screen)) {
 | 
						|
                    EPHYR_LOG("warping mouse cursor. "
 | 
						|
                              "cur_screen%d, motion_screen:%d\n",
 | 
						|
                              ephyrCurScreen, ev.data.mouse_motion.screen);
 | 
						|
                    if (ev.data.mouse_motion.screen >= 0) {
 | 
						|
                        ephyrWarpCursor
 | 
						|
                            (inputInfo.pointer,
 | 
						|
                             screenInfo.screens[ev.data.mouse_motion.screen],
 | 
						|
                             ev.data.mouse_motion.x, ev.data.mouse_motion.y);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    int x = 0, y = 0;
 | 
						|
 | 
						|
#ifdef XF86DRI
 | 
						|
                    EphyrWindowPair *pair = NULL;
 | 
						|
#endif
 | 
						|
                    EPHYR_LOG("enqueuing mouse motion:%d\n", ephyrCurScreen);
 | 
						|
                    x = ev.data.mouse_motion.x;
 | 
						|
                    y = ev.data.mouse_motion.y;
 | 
						|
                    EPHYR_LOG("initial (x,y):(%d,%d)\n", x, y);
 | 
						|
#ifdef XF86DRI
 | 
						|
                    EPHYR_LOG("is this window peered by a gl drawable ?\n");
 | 
						|
                    if (findWindowPairFromRemote(ev.data.mouse_motion.window,
 | 
						|
                                                 &pair)) {
 | 
						|
                        EPHYR_LOG("yes, it is peered\n");
 | 
						|
                        x += pair->local->drawable.x;
 | 
						|
                        y += pair->local->drawable.y;
 | 
						|
                    }
 | 
						|
                    else {
 | 
						|
                        EPHYR_LOG("no, it is not peered\n");
 | 
						|
                    }
 | 
						|
                    EPHYR_LOG("final (x,y):(%d,%d)\n", x, y);
 | 
						|
#endif
 | 
						|
                    KdEnqueuePointerEvent(ephyrMouse, mouseState, x, y, 0);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            break;
 | 
						|
 | 
						|
        case EPHYR_EV_MOUSE_PRESS:
 | 
						|
            if (!ephyrMouse ||
 | 
						|
                !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) {
 | 
						|
                EPHYR_LOG("skipping mouse press:%d\n", ephyrCurScreen);
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            EPHYR_LOG("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);
 | 
						|
            break;
 | 
						|
 | 
						|
        case EPHYR_EV_MOUSE_RELEASE:
 | 
						|
            if (!ephyrMouse ||
 | 
						|
                !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled)
 | 
						|
                continue;
 | 
						|
            ephyrUpdateModifierState(ev.key_state);
 | 
						|
            mouseState &= ~ev.data.mouse_up.button_num;
 | 
						|
            EPHYR_LOG("enqueuing mouse release:%d\n", ephyrCurScreen);
 | 
						|
            KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_MOUSE_DELTA, 0, 0,
 | 
						|
                                  0);
 | 
						|
            break;
 | 
						|
 | 
						|
        case EPHYR_EV_KEY_PRESS:
 | 
						|
            if (!ephyrKbd ||
 | 
						|
                !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled)
 | 
						|
                continue;
 | 
						|
            ephyrUpdateModifierState(ev.key_state);
 | 
						|
            KdEnqueueKeyboardEvent(ephyrKbd, ev.data.key_down.scancode, FALSE);
 | 
						|
            break;
 | 
						|
 | 
						|
        case EPHYR_EV_KEY_RELEASE:
 | 
						|
            if (!ephyrKbd ||
 | 
						|
                !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled)
 | 
						|
                continue;
 | 
						|
            ephyrUpdateModifierState(ev.key_state);
 | 
						|
            KdEnqueueKeyboardEvent(ephyrKbd, ev.data.key_up.scancode, TRUE);
 | 
						|
            break;
 | 
						|
 | 
						|
#ifdef XF86DRI
 | 
						|
        case EPHYR_EV_EXPOSE:
 | 
						|
            /*
 | 
						|
             * We only receive expose events when the expose event have
 | 
						|
             * be generated for a drawable that is a host X window managed
 | 
						|
             * by Xephyr. Host X windows managed by Xephyr exists for instance
 | 
						|
             * when Xephyr is asked to create a GL drawable in a DRI environment.
 | 
						|
             */
 | 
						|
            ephyrExposePairedWindow(ev.data.expose.window);
 | 
						|
            break;
 | 
						|
#endif                          /* XF86DRI */
 | 
						|
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrCardFini(KdCardInfo * card)
 | 
						|
{
 | 
						|
    EphyrPriv *priv = card->driver;
 | 
						|
 | 
						|
    free(priv);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
 | 
						|
{
 | 
						|
    /* XXX Not sure if this is right */
 | 
						|
 | 
						|
    EPHYR_LOG("mark");
 | 
						|
 | 
						|
    while (n--) {
 | 
						|
        pdefs->red = 0;
 | 
						|
        pdefs->green = 0;
 | 
						|
        pdefs->blue = 0;
 | 
						|
        pdefs++;
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ephyrPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
 | 
						|
{
 | 
						|
    int min, max, p;
 | 
						|
 | 
						|
    /* XXX Not sure if this is right */
 | 
						|
 | 
						|
    min = 256;
 | 
						|
    max = 0;
 | 
						|
 | 
						|
    while (n--) {
 | 
						|
        p = pdefs->pixel;
 | 
						|
        if (p < min)
 | 
						|
            min = p;
 | 
						|
        if (p > max)
 | 
						|
            max = p;
 | 
						|
 | 
						|
        hostx_set_cmap_entry(p,
 | 
						|
                             pdefs->red >> 8,
 | 
						|
                             pdefs->green >> 8, pdefs->blue >> 8);
 | 
						|
        pdefs++;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* Mouse calls */
 | 
						|
 | 
						|
static Status
 | 
						|
MouseInit(KdPointerInfo * pi)
 | 
						|
{
 | 
						|
    pi->driverPrivate = (EphyrPointerPrivate *)
 | 
						|
        calloc(sizeof(EphyrPointerPrivate), 1);
 | 
						|
    ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = FALSE;
 | 
						|
    pi->nAxes = 3;
 | 
						|
    pi->nButtons = 32;
 | 
						|
    free(pi->name);
 | 
						|
    pi->name = strdup("Xephyr virtual mouse");
 | 
						|
 | 
						|
    /*
 | 
						|
     * Must transform pointer coords since the pointer position
 | 
						|
     * relative to the Xephyr window is controlled by the host server and
 | 
						|
     * remains constant regardless of any rotation applied to the Xephyr screen.
 | 
						|
     */
 | 
						|
    pi->transformCoordinates = TRUE;
 | 
						|
 | 
						|
    ephyrMouse = pi;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static Status
 | 
						|
MouseEnable(KdPointerInfo * pi)
 | 
						|
{
 | 
						|
    ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = TRUE;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
MouseDisable(KdPointerInfo * pi)
 | 
						|
{
 | 
						|
    ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = FALSE;
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
MouseFini(KdPointerInfo * pi)
 | 
						|
{
 | 
						|
    ephyrMouse = NULL;
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
KdPointerDriver EphyrMouseDriver = {
 | 
						|
    "ephyr",
 | 
						|
    MouseInit,
 | 
						|
    MouseEnable,
 | 
						|
    MouseDisable,
 | 
						|
    MouseFini,
 | 
						|
    NULL,
 | 
						|
};
 | 
						|
 | 
						|
/* Keyboard */
 | 
						|
 | 
						|
static Status
 | 
						|
EphyrKeyboardInit(KdKeyboardInfo * ki)
 | 
						|
{
 | 
						|
    ki->driverPrivate = (EphyrKbdPrivate *)
 | 
						|
        calloc(sizeof(EphyrKbdPrivate), 1);
 | 
						|
    hostx_load_keymap();
 | 
						|
    if (!ephyrKeySyms.map) {
 | 
						|
        ErrorF("Couldn't load keymap from host\n");
 | 
						|
        return BadAlloc;
 | 
						|
    }
 | 
						|
    ki->minScanCode = ephyrKeySyms.minKeyCode;
 | 
						|
    ki->maxScanCode = ephyrKeySyms.maxKeyCode;
 | 
						|
    free(ki->name);
 | 
						|
    ki->name = strdup("Xephyr virtual keyboard");
 | 
						|
    ephyrKbd = ki;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static Status
 | 
						|
EphyrKeyboardEnable(KdKeyboardInfo * ki)
 | 
						|
{
 | 
						|
    ((EphyrKbdPrivate *) ki->driverPrivate)->enabled = TRUE;
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
EphyrKeyboardDisable(KdKeyboardInfo * ki)
 | 
						|
{
 | 
						|
    ((EphyrKbdPrivate *) ki->driverPrivate)->enabled = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
EphyrKeyboardFini(KdKeyboardInfo * ki)
 | 
						|
{
 | 
						|
    ephyrKbd = NULL;
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
EphyrKeyboardLeds(KdKeyboardInfo * ki, int leds)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
EphyrKeyboardBell(KdKeyboardInfo * ki, int volume, int frequency, int duration)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
KdKeyboardDriver EphyrKeyboardDriver = {
 | 
						|
    "ephyr",
 | 
						|
    EphyrKeyboardInit,
 | 
						|
    EphyrKeyboardEnable,
 | 
						|
    EphyrKeyboardLeds,
 | 
						|
    EphyrKeyboardBell,
 | 
						|
    EphyrKeyboardDisable,
 | 
						|
    EphyrKeyboardFini,
 | 
						|
    NULL,
 | 
						|
};
 |