105b261ecSmrg/*
2ed6184dfSmrg * Xephyr - A kdrive X server that runs in a host X window.
305b261ecSmrg *          Authored by Matthew Allum <mallum@openedhand.com>
435c4bbdfSmrg *
535c4bbdfSmrg * Copyright © 2004 Nokia
605b261ecSmrg *
705b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
805b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
905b261ecSmrg * the above copyright notice appear in all copies and that both that
1005b261ecSmrg * copyright notice and this permission notice appear in supporting
1105b261ecSmrg * documentation, and that the name of Nokia not be used in
1205b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1305b261ecSmrg * specific, written prior permission. Nokia makes no
1405b261ecSmrg * representations about the suitability of this software for any purpose.  It
1505b261ecSmrg * is provided "as is" without express or implied warranty.
1605b261ecSmrg *
1705b261ecSmrg * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1805b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1905b261ecSmrg * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2005b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2205b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2305b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg */
2505b261ecSmrg
261b5d61b8Smrg#ifdef HAVE_DIX_CONFIG_H
271b5d61b8Smrg#include <dix-config.h>
2805b261ecSmrg#endif
2935c4bbdfSmrg
3035c4bbdfSmrg#include <xcb/xcb_keysyms.h>
3135c4bbdfSmrg#include <X11/keysym.h>
3235c4bbdfSmrg
3305b261ecSmrg#include "ephyr.h"
3405b261ecSmrg
3505b261ecSmrg#include "inputstr.h"
364642e01fSmrg#include "scrnintstr.h"
374642e01fSmrg#include "ephyrlog.h"
384642e01fSmrg
3935c4bbdfSmrg#ifdef GLAMOR
4035c4bbdfSmrg#include "glamor.h"
4135c4bbdfSmrg#endif
4235c4bbdfSmrg#include "ephyr_glamor_glx.h"
431b5d61b8Smrg#include "glx_extinit.h"
446747b715Smrg#include "xkbsrv.h"
456747b715Smrg
4635c4bbdfSmrgextern Bool ephyr_glamor;
474642e01fSmrg
4805b261ecSmrgKdKeyboardInfo *ephyrKbd;
4905b261ecSmrgKdPointerInfo *ephyrMouse;
5035c4bbdfSmrgBool ephyrNoDRI = FALSE;
5135c4bbdfSmrgBool ephyrNoXV = FALSE;
5205b261ecSmrg
5305b261ecSmrgstatic int mouseState = 0;
5435c4bbdfSmrgstatic Rotation ephyrRandr = RR_Rotate_0;
5505b261ecSmrg
5605b261ecSmrgtypedef struct _EphyrInputPrivate {
5735c4bbdfSmrg    Bool enabled;
5805b261ecSmrg} EphyrKbdPrivate, EphyrPointerPrivate;
5905b261ecSmrg
6035c4bbdfSmrgBool EphyrWantGrayScale = 0;
6135c4bbdfSmrgBool EphyrWantResize = 0;
6235c4bbdfSmrgBool EphyrWantNoHostGrab = 0;
634642e01fSmrg
6405b261ecSmrgBool
6535c4bbdfSmrgephyrInitialize(KdCardInfo * card, EphyrPriv * priv)
6605b261ecSmrg{
6735c4bbdfSmrg    OsSignal(SIGUSR1, hostx_handle_signal);
6835c4bbdfSmrg
6935c4bbdfSmrg    priv->base = 0;
7035c4bbdfSmrg    priv->bytes_per_line = 0;
7135c4bbdfSmrg    return TRUE;
7205b261ecSmrg}
7305b261ecSmrg
7405b261ecSmrgBool
7535c4bbdfSmrgephyrCardInit(KdCardInfo * card)
7605b261ecSmrg{
7735c4bbdfSmrg    EphyrPriv *priv;
7835c4bbdfSmrg
7935c4bbdfSmrg    priv = (EphyrPriv *) malloc(sizeof(EphyrPriv));
8035c4bbdfSmrg    if (!priv)
8135c4bbdfSmrg        return FALSE;
8235c4bbdfSmrg
8335c4bbdfSmrg    if (!ephyrInitialize(card, priv)) {
8435c4bbdfSmrg        free(priv);
8535c4bbdfSmrg        return FALSE;
8605b261ecSmrg    }
8735c4bbdfSmrg    card->driver = priv;
8835c4bbdfSmrg
8935c4bbdfSmrg    return TRUE;
9005b261ecSmrg}
9105b261ecSmrg
9205b261ecSmrgBool
9335c4bbdfSmrgephyrScreenInitialize(KdScreenInfo *screen)
9405b261ecSmrg{
9535c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
9635c4bbdfSmrg    int x = 0, y = 0;
9735c4bbdfSmrg    int width = 640, height = 480;
9835c4bbdfSmrg    CARD32 redMask, greenMask, blueMask;
9935c4bbdfSmrg
10035c4bbdfSmrg    if (hostx_want_screen_geometry(screen, &width, &height, &x, &y)
10135c4bbdfSmrg        || !screen->width || !screen->height) {
10235c4bbdfSmrg        screen->width = width;
10335c4bbdfSmrg        screen->height = height;
10435c4bbdfSmrg        screen->x = x;
10535c4bbdfSmrg        screen->y = y;
10605b261ecSmrg    }
10705b261ecSmrg
10835c4bbdfSmrg    if (EphyrWantGrayScale)
10935c4bbdfSmrg        screen->fb.depth = 8;
11005b261ecSmrg
11135c4bbdfSmrg    if (screen->fb.depth && screen->fb.depth != hostx_get_depth()) {
11235c4bbdfSmrg        if (screen->fb.depth < hostx_get_depth()
11335c4bbdfSmrg            && (screen->fb.depth == 24 || screen->fb.depth == 16
11435c4bbdfSmrg                || screen->fb.depth == 8)) {
11535c4bbdfSmrg            scrpriv->server_depth = screen->fb.depth;
11635c4bbdfSmrg        }
11735c4bbdfSmrg        else
11835c4bbdfSmrg            ErrorF
11935c4bbdfSmrg                ("\nXephyr: requested screen depth not supported, setting to match hosts.\n");
12005b261ecSmrg    }
12105b261ecSmrg
12235c4bbdfSmrg    screen->fb.depth = hostx_get_server_depth(screen);
12335c4bbdfSmrg    screen->rate = 72;
12435c4bbdfSmrg
12535c4bbdfSmrg    if (screen->fb.depth <= 8) {
12635c4bbdfSmrg        if (EphyrWantGrayScale)
12735c4bbdfSmrg            screen->fb.visuals = ((1 << StaticGray) | (1 << GrayScale));
12835c4bbdfSmrg        else
12935c4bbdfSmrg            screen->fb.visuals = ((1 << StaticGray) |
13035c4bbdfSmrg                                  (1 << GrayScale) |
13135c4bbdfSmrg                                  (1 << StaticColor) |
13235c4bbdfSmrg                                  (1 << PseudoColor) |
13335c4bbdfSmrg                                  (1 << TrueColor) | (1 << DirectColor));
13435c4bbdfSmrg
13535c4bbdfSmrg        screen->fb.redMask = 0x00;
13635c4bbdfSmrg        screen->fb.greenMask = 0x00;
13735c4bbdfSmrg        screen->fb.blueMask = 0x00;
13835c4bbdfSmrg        screen->fb.depth = 8;
13935c4bbdfSmrg        screen->fb.bitsPerPixel = 8;
14035c4bbdfSmrg    }
14135c4bbdfSmrg    else {
14235c4bbdfSmrg        screen->fb.visuals = (1 << TrueColor);
14305b261ecSmrg
14435c4bbdfSmrg        if (screen->fb.depth <= 15) {
14535c4bbdfSmrg            screen->fb.depth = 15;
14635c4bbdfSmrg            screen->fb.bitsPerPixel = 16;
14735c4bbdfSmrg        }
14835c4bbdfSmrg        else if (screen->fb.depth <= 16) {
14935c4bbdfSmrg            screen->fb.depth = 16;
15035c4bbdfSmrg            screen->fb.bitsPerPixel = 16;
15135c4bbdfSmrg        }
15235c4bbdfSmrg        else if (screen->fb.depth <= 24) {
15335c4bbdfSmrg            screen->fb.depth = 24;
15435c4bbdfSmrg            screen->fb.bitsPerPixel = 32;
15535c4bbdfSmrg        }
15635c4bbdfSmrg        else if (screen->fb.depth <= 30) {
15735c4bbdfSmrg            screen->fb.depth = 30;
15835c4bbdfSmrg            screen->fb.bitsPerPixel = 32;
15935c4bbdfSmrg        }
16035c4bbdfSmrg        else {
16135c4bbdfSmrg            ErrorF("\nXephyr: Unsupported screen depth %d\n", screen->fb.depth);
16235c4bbdfSmrg            return FALSE;
16335c4bbdfSmrg        }
16405b261ecSmrg
16535c4bbdfSmrg        hostx_get_visual_masks(screen, &redMask, &greenMask, &blueMask);
16605b261ecSmrg
16735c4bbdfSmrg        screen->fb.redMask = (Pixel) redMask;
16835c4bbdfSmrg        screen->fb.greenMask = (Pixel) greenMask;
16935c4bbdfSmrg        screen->fb.blueMask = (Pixel) blueMask;
17005b261ecSmrg
17105b261ecSmrg    }
17205b261ecSmrg
17335c4bbdfSmrg    scrpriv->randr = screen->randr;
17435c4bbdfSmrg
17535c4bbdfSmrg    return ephyrMapFramebuffer(screen);
17605b261ecSmrg}
17735c4bbdfSmrg
17835c4bbdfSmrgvoid *
17935c4bbdfSmrgephyrWindowLinear(ScreenPtr pScreen,
18035c4bbdfSmrg                  CARD32 row,
18135c4bbdfSmrg                  CARD32 offset, int mode, CARD32 *size, void *closure)
18205b261ecSmrg{
18335c4bbdfSmrg    KdScreenPriv(pScreen);
18435c4bbdfSmrg    EphyrPriv *priv = pScreenPriv->card->driver;
18535c4bbdfSmrg
18635c4bbdfSmrg    if (!pScreenPriv->enabled)
18735c4bbdfSmrg        return 0;
18835c4bbdfSmrg
18935c4bbdfSmrg    *size = priv->bytes_per_line;
19035c4bbdfSmrg    return priv->base + row * priv->bytes_per_line + offset;
19105b261ecSmrg}
19205b261ecSmrg
1936747b715Smrg/**
1946747b715Smrg * Figure out display buffer size. If fakexa is enabled, allocate a larger
1956747b715Smrg * buffer so that fakexa has space to put offscreen pixmaps.
1966747b715Smrg */
1976747b715Smrgint
19835c4bbdfSmrgephyrBufferHeight(KdScreenInfo * screen)
1996747b715Smrg{
2006747b715Smrg    int buffer_height;
20135c4bbdfSmrg
2026747b715Smrg    if (ephyrFuncs.initAccel == NULL)
20335c4bbdfSmrg        buffer_height = screen->height;
2046747b715Smrg    else
20535c4bbdfSmrg        buffer_height = 3 * screen->height;
2066747b715Smrg    return buffer_height;
2076747b715Smrg}
2086747b715Smrg
20905b261ecSmrgBool
21035c4bbdfSmrgephyrMapFramebuffer(KdScreenInfo * screen)
21105b261ecSmrg{
21235c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
21335c4bbdfSmrg    EphyrPriv *priv = screen->card->driver;
21435c4bbdfSmrg    KdPointerMatrix m;
21535c4bbdfSmrg    int buffer_height;
21635c4bbdfSmrg
21735c4bbdfSmrg    EPHYR_LOG("screen->width: %d, screen->height: %d index=%d",
21835c4bbdfSmrg              screen->width, screen->height, screen->mynum);
21935c4bbdfSmrg
22035c4bbdfSmrg    /*
22135c4bbdfSmrg     * Use the rotation last applied to ourselves (in the Xephyr case the fb
222ed6184dfSmrg     * coordinate system moves independently of the pointer coordinate system).
22335c4bbdfSmrg     */
22435c4bbdfSmrg    KdComputePointerMatrix(&m, ephyrRandr, screen->width, screen->height);
22535c4bbdfSmrg    KdSetPointerMatrix(&m);
22635c4bbdfSmrg
22735c4bbdfSmrg    buffer_height = ephyrBufferHeight(screen);
22835c4bbdfSmrg
22935c4bbdfSmrg    priv->base =
23035c4bbdfSmrg        hostx_screen_init(screen, screen->x, screen->y,
23135c4bbdfSmrg                          screen->width, screen->height, buffer_height,
23235c4bbdfSmrg                          &priv->bytes_per_line, &screen->fb.bitsPerPixel);
23335c4bbdfSmrg
23435c4bbdfSmrg    if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) {
23535c4bbdfSmrg        scrpriv->shadow = FALSE;
23635c4bbdfSmrg
23735c4bbdfSmrg        screen->fb.byteStride = priv->bytes_per_line;
23835c4bbdfSmrg        screen->fb.pixelStride = screen->width;
23935c4bbdfSmrg        screen->fb.frameBuffer = (CARD8 *) (priv->base);
24005b261ecSmrg    }
24135c4bbdfSmrg    else {
24235c4bbdfSmrg        /* Rotated/Reflected so we need to use shadow fb */
24335c4bbdfSmrg        scrpriv->shadow = TRUE;
24435c4bbdfSmrg
24535c4bbdfSmrg        EPHYR_LOG("allocing shadow");
24635c4bbdfSmrg
24735c4bbdfSmrg        KdShadowFbAlloc(screen,
24835c4bbdfSmrg                        scrpriv->randr & (RR_Rotate_90 | RR_Rotate_270));
24905b261ecSmrg    }
25035c4bbdfSmrg
25135c4bbdfSmrg    return TRUE;
25205b261ecSmrg}
25305b261ecSmrg
25405b261ecSmrgvoid
25535c4bbdfSmrgephyrSetScreenSizes(ScreenPtr pScreen)
25605b261ecSmrg{
25735c4bbdfSmrg    KdScreenPriv(pScreen);
25835c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
25935c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
26035c4bbdfSmrg
26135c4bbdfSmrg    if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) {
26235c4bbdfSmrg        pScreen->width = screen->width;
26335c4bbdfSmrg        pScreen->height = screen->height;
26435c4bbdfSmrg        pScreen->mmWidth = screen->width_mm;
26535c4bbdfSmrg        pScreen->mmHeight = screen->height_mm;
26605b261ecSmrg    }
26735c4bbdfSmrg    else {
26835c4bbdfSmrg        pScreen->width = screen->height;
26935c4bbdfSmrg        pScreen->height = screen->width;
27035c4bbdfSmrg        pScreen->mmWidth = screen->height_mm;
27135c4bbdfSmrg        pScreen->mmHeight = screen->width_mm;
27205b261ecSmrg    }
27305b261ecSmrg}
27405b261ecSmrg
27505b261ecSmrgBool
27635c4bbdfSmrgephyrUnmapFramebuffer(KdScreenInfo * screen)
27705b261ecSmrg{
27835c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
27905b261ecSmrg
28035c4bbdfSmrg    if (scrpriv->shadow)
28135c4bbdfSmrg        KdShadowFbFree(screen);
28205b261ecSmrg
28335c4bbdfSmrg    /* Note, priv->base will get freed when XImage recreated */
2844642e01fSmrg
28535c4bbdfSmrg    return TRUE;
28635c4bbdfSmrg}
2874642e01fSmrg
28835c4bbdfSmrgvoid
28935c4bbdfSmrgephyrShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
29035c4bbdfSmrg{
29135c4bbdfSmrg    KdScreenPriv(pScreen);
29235c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
2934642e01fSmrg
29435c4bbdfSmrg    EPHYR_LOG("slow paint");
2954642e01fSmrg
29635c4bbdfSmrg    /* FIXME: Slow Rotated/Reflected updates could be much
297ed6184dfSmrg     * much faster efficiently updating via transforming
29835c4bbdfSmrg     * pBuf->pDamage  regions
29935c4bbdfSmrg     */
30035c4bbdfSmrg    shadowUpdateRotatePacked(pScreen, pBuf);
30135c4bbdfSmrg    hostx_paint_rect(screen, 0, 0, 0, 0, screen->width, screen->height);
30235c4bbdfSmrg}
3034642e01fSmrg
30435c4bbdfSmrgstatic void
30535c4bbdfSmrgephyrInternalDamageRedisplay(ScreenPtr pScreen)
30635c4bbdfSmrg{
30735c4bbdfSmrg    KdScreenPriv(pScreen);
30835c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
30935c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
31035c4bbdfSmrg    RegionPtr pRegion;
31135c4bbdfSmrg
31235c4bbdfSmrg    if (!scrpriv || !scrpriv->pDamage)
31335c4bbdfSmrg        return;
31435c4bbdfSmrg
31535c4bbdfSmrg    pRegion = DamageRegion(scrpriv->pDamage);
31635c4bbdfSmrg
31735c4bbdfSmrg    if (RegionNotEmpty(pRegion)) {
31835c4bbdfSmrg        int nbox;
31935c4bbdfSmrg        BoxPtr pbox;
32035c4bbdfSmrg
32135c4bbdfSmrg        if (ephyr_glamor) {
32235c4bbdfSmrg            ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion);
32335c4bbdfSmrg        } else {
32435c4bbdfSmrg            nbox = RegionNumRects(pRegion);
32535c4bbdfSmrg            pbox = RegionRects(pRegion);
32635c4bbdfSmrg
32735c4bbdfSmrg            while (nbox--) {
32835c4bbdfSmrg                hostx_paint_rect(screen,
32935c4bbdfSmrg                                 pbox->x1, pbox->y1,
33035c4bbdfSmrg                                 pbox->x1, pbox->y1,
33135c4bbdfSmrg                                 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
33235c4bbdfSmrg                pbox++;
33335c4bbdfSmrg            }
3344642e01fSmrg        }
33535c4bbdfSmrg        DamageEmpty(scrpriv->pDamage);
33605b261ecSmrg    }
33705b261ecSmrg}
33805b261ecSmrg
33905b261ecSmrgstatic void
3401b5d61b8SmrgephyrXcbProcessEvents(Bool queued_only);
34135c4bbdfSmrg
3421b5d61b8Smrgstatic Bool
3431b5d61b8SmrgephyrEventWorkProc(ClientPtr client, void *closure)
3441b5d61b8Smrg{
3451b5d61b8Smrg    ephyrXcbProcessEvents(TRUE);
3461b5d61b8Smrg    return TRUE;
34705b261ecSmrg}
34805b261ecSmrg
34905b261ecSmrgstatic void
3501b5d61b8SmrgephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout)
35105b261ecSmrg{
3521b5d61b8Smrg    KdScreenPriv(pScreen);
3531b5d61b8Smrg    KdScreenInfo *screen = pScreenPriv->screen;
3541b5d61b8Smrg    EphyrScrPriv *scrpriv = screen->driver;
3551b5d61b8Smrg
3561b5d61b8Smrg    pScreen->BlockHandler = scrpriv->BlockHandler;
3571b5d61b8Smrg    (*pScreen->BlockHandler)(pScreen, timeout);
3581b5d61b8Smrg    scrpriv->BlockHandler = pScreen->BlockHandler;
3591b5d61b8Smrg    pScreen->BlockHandler = ephyrScreenBlockHandler;
3601b5d61b8Smrg
3611b5d61b8Smrg    if (scrpriv->pDamage)
3621b5d61b8Smrg        ephyrInternalDamageRedisplay(pScreen);
3631b5d61b8Smrg
3641b5d61b8Smrg    if (hostx_has_queued_event()) {
3651b5d61b8Smrg        if (!QueueWorkProc(ephyrEventWorkProc, NULL, NULL))
3661b5d61b8Smrg            FatalError("cannot queue event processing in ephyr block handler");
3671b5d61b8Smrg        AdjustWaitForDelay(timeout, 0);
3681b5d61b8Smrg    }
36905b261ecSmrg}
37005b261ecSmrg
37105b261ecSmrgBool
37235c4bbdfSmrgephyrSetInternalDamage(ScreenPtr pScreen)
37305b261ecSmrg{
37435c4bbdfSmrg    KdScreenPriv(pScreen);
37535c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
37635c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
37735c4bbdfSmrg    PixmapPtr pPixmap = NULL;
37835c4bbdfSmrg
37935c4bbdfSmrg    scrpriv->pDamage = DamageCreate((DamageReportFunc) 0,
38035c4bbdfSmrg                                    (DamageDestroyFunc) 0,
38135c4bbdfSmrg                                    DamageReportNone, TRUE, pScreen, pScreen);
38235c4bbdfSmrg
38335c4bbdfSmrg    pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
38435c4bbdfSmrg
38535c4bbdfSmrg    DamageRegister(&pPixmap->drawable, scrpriv->pDamage);
38635c4bbdfSmrg
38735c4bbdfSmrg    return TRUE;
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrgvoid
39135c4bbdfSmrgephyrUnsetInternalDamage(ScreenPtr pScreen)
39205b261ecSmrg{
39335c4bbdfSmrg    KdScreenPriv(pScreen);
39435c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
39535c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
39635c4bbdfSmrg
39735c4bbdfSmrg    DamageDestroy(scrpriv->pDamage);
3981b5d61b8Smrg    scrpriv->pDamage = NULL;
39905b261ecSmrg}
40005b261ecSmrg
40105b261ecSmrg#ifdef RANDR
40205b261ecSmrgBool
40335c4bbdfSmrgephyrRandRGetInfo(ScreenPtr pScreen, Rotation * rotations)
40405b261ecSmrg{
40535c4bbdfSmrg    KdScreenPriv(pScreen);
40635c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
40735c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
40835c4bbdfSmrg    RRScreenSizePtr pSize;
40935c4bbdfSmrg    Rotation randr;
41035c4bbdfSmrg    int n = 0;
41135c4bbdfSmrg
41235c4bbdfSmrg    struct {
41335c4bbdfSmrg        int width, height;
41435c4bbdfSmrg    } sizes[] = {
41535c4bbdfSmrg        {1600, 1200},
41635c4bbdfSmrg        {1400, 1050},
41735c4bbdfSmrg        {1280, 960},
41835c4bbdfSmrg        {1280, 1024},
41935c4bbdfSmrg        {1152, 864},
42035c4bbdfSmrg        {1024, 768},
42135c4bbdfSmrg        {832, 624},
42235c4bbdfSmrg        {800, 600},
42335c4bbdfSmrg        {720, 400},
42435c4bbdfSmrg        {480, 640},
42535c4bbdfSmrg        {640, 480},
42635c4bbdfSmrg        {640, 400},
42735c4bbdfSmrg        {320, 240},
42835c4bbdfSmrg        {240, 320},
42935c4bbdfSmrg        {160, 160},
43035c4bbdfSmrg        {0, 0}
43105b261ecSmrg    };
4324642e01fSmrg
43335c4bbdfSmrg    EPHYR_LOG("mark");
43435c4bbdfSmrg
43535c4bbdfSmrg    *rotations = RR_Rotate_All | RR_Reflect_All;
43635c4bbdfSmrg
43735c4bbdfSmrg    if (!hostx_want_preexisting_window(screen)
43835c4bbdfSmrg        && !hostx_want_fullscreen()) {  /* only if no -parent switch */
43935c4bbdfSmrg        while (sizes[n].width != 0 && sizes[n].height != 0) {
44035c4bbdfSmrg            RRRegisterSize(pScreen,
44135c4bbdfSmrg                           sizes[n].width,
44235c4bbdfSmrg                           sizes[n].height,
44335c4bbdfSmrg                           (sizes[n].width * screen->width_mm) / screen->width,
44435c4bbdfSmrg                           (sizes[n].height * screen->height_mm) /
44535c4bbdfSmrg                           screen->height);
44635c4bbdfSmrg            n++;
44735c4bbdfSmrg        }
44805b261ecSmrg    }
44935c4bbdfSmrg
45035c4bbdfSmrg    pSize = RRRegisterSize(pScreen,
45135c4bbdfSmrg                           screen->width,
45235c4bbdfSmrg                           screen->height, screen->width_mm, screen->height_mm);
45335c4bbdfSmrg
45435c4bbdfSmrg    randr = KdSubRotation(scrpriv->randr, screen->randr);
45535c4bbdfSmrg
45635c4bbdfSmrg    RRSetCurrentConfig(pScreen, randr, 0, pSize);
45735c4bbdfSmrg
45835c4bbdfSmrg    return TRUE;
45905b261ecSmrg}
46005b261ecSmrg
46105b261ecSmrgBool
46235c4bbdfSmrgephyrRandRSetConfig(ScreenPtr pScreen,
46335c4bbdfSmrg                    Rotation randr, int rate, RRScreenSizePtr pSize)
46405b261ecSmrg{
46535c4bbdfSmrg    KdScreenPriv(pScreen);
46635c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
46735c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
46835c4bbdfSmrg    Bool wasEnabled = pScreenPriv->enabled;
46935c4bbdfSmrg    EphyrScrPriv oldscr;
47035c4bbdfSmrg    int oldwidth, oldheight, oldmmwidth, oldmmheight;
47135c4bbdfSmrg    Bool oldshadow;
47235c4bbdfSmrg    int newwidth, newheight;
47335c4bbdfSmrg
47435c4bbdfSmrg    if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) {
47535c4bbdfSmrg        newwidth = pSize->width;
47635c4bbdfSmrg        newheight = pSize->height;
47705b261ecSmrg    }
47835c4bbdfSmrg    else {
47935c4bbdfSmrg        newwidth = pSize->height;
48035c4bbdfSmrg        newheight = pSize->width;
48105b261ecSmrg    }
48235c4bbdfSmrg
48335c4bbdfSmrg    if (wasEnabled)
48435c4bbdfSmrg        KdDisableScreen(pScreen);
48535c4bbdfSmrg
48635c4bbdfSmrg    oldscr = *scrpriv;
48735c4bbdfSmrg
48835c4bbdfSmrg    oldwidth = screen->width;
48935c4bbdfSmrg    oldheight = screen->height;
49035c4bbdfSmrg    oldmmwidth = pScreen->mmWidth;
49135c4bbdfSmrg    oldmmheight = pScreen->mmHeight;
49235c4bbdfSmrg    oldshadow = scrpriv->shadow;
49335c4bbdfSmrg
49435c4bbdfSmrg    /*
49535c4bbdfSmrg     * Set new configuration
49635c4bbdfSmrg     */
49735c4bbdfSmrg
49835c4bbdfSmrg    /*
49935c4bbdfSmrg     * We need to store the rotation value for pointer coords transformation;
50035c4bbdfSmrg     * though initially the pointer and fb rotation are identical, when we map
50135c4bbdfSmrg     * the fb, the screen will be reinitialized and return into an unrotated
50235c4bbdfSmrg     * state (presumably the HW is taking care of the rotation of the fb), but the
50335c4bbdfSmrg     * pointer still needs to be transformed.
50435c4bbdfSmrg     */
50535c4bbdfSmrg    ephyrRandr = KdAddRotation(screen->randr, randr);
50635c4bbdfSmrg    scrpriv->randr = ephyrRandr;
50735c4bbdfSmrg
50835c4bbdfSmrg    ephyrUnmapFramebuffer(screen);
50935c4bbdfSmrg
51035c4bbdfSmrg    screen->width = newwidth;
51135c4bbdfSmrg    screen->height = newheight;
51235c4bbdfSmrg
5131b5d61b8Smrg    scrpriv->win_width = screen->width;
5141b5d61b8Smrg    scrpriv->win_height = screen->height;
5151b5d61b8Smrg#ifdef GLAMOR
5161b5d61b8Smrg    ephyr_glamor_set_window_size(scrpriv->glamor,
5171b5d61b8Smrg                                 scrpriv->win_width,
5181b5d61b8Smrg                                 scrpriv->win_height);
5191b5d61b8Smrg#endif
5201b5d61b8Smrg
52135c4bbdfSmrg    if (!ephyrMapFramebuffer(screen))
52235c4bbdfSmrg        goto bail4;
52335c4bbdfSmrg
52435c4bbdfSmrg    /* FIXME below should go in own call */
52535c4bbdfSmrg
52635c4bbdfSmrg    if (oldshadow)
52735c4bbdfSmrg        KdShadowUnset(screen->pScreen);
52835c4bbdfSmrg    else
52935c4bbdfSmrg        ephyrUnsetInternalDamage(screen->pScreen);
53035c4bbdfSmrg
5311b5d61b8Smrg    ephyrSetScreenSizes(screen->pScreen);
5321b5d61b8Smrg
53335c4bbdfSmrg    if (scrpriv->shadow) {
53435c4bbdfSmrg        if (!KdShadowSet(screen->pScreen,
53535c4bbdfSmrg                         scrpriv->randr, ephyrShadowUpdate, ephyrWindowLinear))
53635c4bbdfSmrg            goto bail4;
53705b261ecSmrg    }
53835c4bbdfSmrg    else {
5391b5d61b8Smrg#ifdef GLAMOR
5401b5d61b8Smrg        if (ephyr_glamor)
5411b5d61b8Smrg            ephyr_glamor_create_screen_resources(pScreen);
5421b5d61b8Smrg#endif
54335c4bbdfSmrg        /* Without shadow fb ( non rotated ) we need
54435c4bbdfSmrg         * to use damage to efficiently update display
54535c4bbdfSmrg         * via signal regions what to copy from 'fb'.
54635c4bbdfSmrg         */
54735c4bbdfSmrg        if (!ephyrSetInternalDamage(screen->pScreen))
54835c4bbdfSmrg            goto bail4;
54905b261ecSmrg    }
55035c4bbdfSmrg
55135c4bbdfSmrg    /*
55235c4bbdfSmrg     * Set frame buffer mapping
55335c4bbdfSmrg     */
55435c4bbdfSmrg    (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap(pScreen),
55535c4bbdfSmrg                                    pScreen->width,
55635c4bbdfSmrg                                    pScreen->height,
55735c4bbdfSmrg                                    screen->fb.depth,
55835c4bbdfSmrg                                    screen->fb.bitsPerPixel,
55935c4bbdfSmrg                                    screen->fb.byteStride,
56035c4bbdfSmrg                                    screen->fb.frameBuffer);
56135c4bbdfSmrg
56235c4bbdfSmrg    /* set the subpixel order */
56335c4bbdfSmrg
56435c4bbdfSmrg    KdSetSubpixelOrder(pScreen, scrpriv->randr);
56535c4bbdfSmrg
56635c4bbdfSmrg    if (wasEnabled)
56735c4bbdfSmrg        KdEnableScreen(pScreen);
56835c4bbdfSmrg
56935c4bbdfSmrg    RRScreenSizeNotify(pScreen);
57035c4bbdfSmrg
57135c4bbdfSmrg    return TRUE;
57235c4bbdfSmrg
57305b261ecSmrg bail4:
57435c4bbdfSmrg    EPHYR_LOG("bailed");
57535c4bbdfSmrg
57635c4bbdfSmrg    ephyrUnmapFramebuffer(screen);
57735c4bbdfSmrg    *scrpriv = oldscr;
57835c4bbdfSmrg    (void) ephyrMapFramebuffer(screen);
57935c4bbdfSmrg
58035c4bbdfSmrg    pScreen->width = oldwidth;
58135c4bbdfSmrg    pScreen->height = oldheight;
58235c4bbdfSmrg    pScreen->mmWidth = oldmmwidth;
58335c4bbdfSmrg    pScreen->mmHeight = oldmmheight;
58435c4bbdfSmrg
58535c4bbdfSmrg    if (wasEnabled)
58635c4bbdfSmrg        KdEnableScreen(pScreen);
58735c4bbdfSmrg    return FALSE;
58805b261ecSmrg}
58905b261ecSmrg
59005b261ecSmrgBool
59135c4bbdfSmrgephyrRandRInit(ScreenPtr pScreen)
59205b261ecSmrg{
59335c4bbdfSmrg    rrScrPrivPtr pScrPriv;
59435c4bbdfSmrg
59535c4bbdfSmrg    if (!RRScreenInit(pScreen))
59635c4bbdfSmrg        return FALSE;
59735c4bbdfSmrg
59835c4bbdfSmrg    pScrPriv = rrGetScrPriv(pScreen);
59935c4bbdfSmrg    pScrPriv->rrGetInfo = ephyrRandRGetInfo;
60035c4bbdfSmrg    pScrPriv->rrSetConfig = ephyrRandRSetConfig;
60135c4bbdfSmrg    return TRUE;
60235c4bbdfSmrg}
60335c4bbdfSmrg
60435c4bbdfSmrgstatic Bool
60535c4bbdfSmrgephyrResizeScreen (ScreenPtr           pScreen,
60635c4bbdfSmrg                  int                  newwidth,
60735c4bbdfSmrg                  int                  newheight)
60835c4bbdfSmrg{
60935c4bbdfSmrg    KdScreenPriv(pScreen);
61035c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
61135c4bbdfSmrg    RRScreenSize size = {0};
61235c4bbdfSmrg    Bool ret;
61335c4bbdfSmrg    int t;
61435c4bbdfSmrg
61535c4bbdfSmrg    if (screen->randr & (RR_Rotate_90|RR_Rotate_270)) {
61635c4bbdfSmrg        t = newwidth;
61735c4bbdfSmrg        newwidth = newheight;
61835c4bbdfSmrg        newheight = t;
61935c4bbdfSmrg    }
62035c4bbdfSmrg
62135c4bbdfSmrg    if (newwidth == screen->width && newheight == screen->height) {
62235c4bbdfSmrg        return FALSE;
62335c4bbdfSmrg    }
62435c4bbdfSmrg
62535c4bbdfSmrg    size.width = newwidth;
62635c4bbdfSmrg    size.height = newheight;
62735c4bbdfSmrg
6281b5d61b8Smrg    hostx_size_set_from_configure(TRUE);
62935c4bbdfSmrg    ret = ephyrRandRSetConfig (pScreen, screen->randr, 0, &size);
6301b5d61b8Smrg    hostx_size_set_from_configure(FALSE);
63135c4bbdfSmrg    if (ret) {
63235c4bbdfSmrg        RROutputPtr output;
63335c4bbdfSmrg
63435c4bbdfSmrg        output = RRFirstOutput(pScreen);
63535c4bbdfSmrg        if (!output)
63635c4bbdfSmrg            return FALSE;
63735c4bbdfSmrg        RROutputSetModes(output, NULL, 0, 0);
63835c4bbdfSmrg    }
63935c4bbdfSmrg
64035c4bbdfSmrg    return ret;
64105b261ecSmrg}
64205b261ecSmrg#endif
64305b261ecSmrg
64405b261ecSmrgBool
64535c4bbdfSmrgephyrCreateColormap(ColormapPtr pmap)
64605b261ecSmrg{
64735c4bbdfSmrg    return fbInitializeColormap(pmap);
64805b261ecSmrg}
64905b261ecSmrg
65005b261ecSmrgBool
65135c4bbdfSmrgephyrInitScreen(ScreenPtr pScreen)
65205b261ecSmrg{
65335c4bbdfSmrg    KdScreenPriv(pScreen);
65435c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
65535c4bbdfSmrg
65635c4bbdfSmrg    EPHYR_LOG("pScreen->myNum:%d\n", pScreen->myNum);
65735c4bbdfSmrg    hostx_set_screen_number(screen, pScreen->myNum);
65835c4bbdfSmrg    if (EphyrWantNoHostGrab) {
65935c4bbdfSmrg        hostx_set_win_title(screen, "xephyr");
66035c4bbdfSmrg    } else {
66135c4bbdfSmrg        hostx_set_win_title(screen, "(ctrl+shift grabs mouse and keyboard)");
66235c4bbdfSmrg    }
66335c4bbdfSmrg    pScreen->CreateColormap = ephyrCreateColormap;
6644642e01fSmrg
6654642e01fSmrg#ifdef XV
66635c4bbdfSmrg    if (!ephyrNoXV) {
66735c4bbdfSmrg        if (ephyr_glamor)
66835c4bbdfSmrg            ephyr_glamor_xv_init(pScreen);
66935c4bbdfSmrg        else if (!ephyrInitVideo(pScreen)) {
67035c4bbdfSmrg            EPHYR_LOG_ERROR("failed to initialize xvideo\n");
67135c4bbdfSmrg        }
67235c4bbdfSmrg        else {
67335c4bbdfSmrg            EPHYR_LOG("initialized xvideo okay\n");
67435c4bbdfSmrg        }
67535c4bbdfSmrg    }
6764642e01fSmrg#endif /*XV*/
6774642e01fSmrg
67835c4bbdfSmrg    return TRUE;
67905b261ecSmrg}
68005b261ecSmrg
68135c4bbdfSmrg
68205b261ecSmrgBool
68335c4bbdfSmrgephyrFinishInitScreen(ScreenPtr pScreen)
68405b261ecSmrg{
6851b5d61b8Smrg    KdScreenPriv(pScreen);
6861b5d61b8Smrg    KdScreenInfo *screen = pScreenPriv->screen;
6871b5d61b8Smrg    EphyrScrPriv *scrpriv = screen->driver;
6881b5d61b8Smrg
68935c4bbdfSmrg    /* FIXME: Calling this even if not using shadow.
69035c4bbdfSmrg     * Seems harmless enough. But may be safer elsewhere.
69135c4bbdfSmrg     */
69235c4bbdfSmrg    if (!shadowSetup(pScreen))
69335c4bbdfSmrg        return FALSE;
6944642e01fSmrg
69505b261ecSmrg#ifdef RANDR
69635c4bbdfSmrg    if (!ephyrRandRInit(pScreen))
69735c4bbdfSmrg        return FALSE;
69805b261ecSmrg#endif
6994642e01fSmrg
7001b5d61b8Smrg    scrpriv->BlockHandler = pScreen->BlockHandler;
7011b5d61b8Smrg    pScreen->BlockHandler = ephyrScreenBlockHandler;
7021b5d61b8Smrg
70335c4bbdfSmrg    return TRUE;
70405b261ecSmrg}
70505b261ecSmrg
70635c4bbdfSmrg/**
70735c4bbdfSmrg * Called by kdrive after calling down the
70835c4bbdfSmrg * pScreen->CreateScreenResources() chain, this gives us a chance to
70935c4bbdfSmrg * make any pixmaps after the screen and all extensions have been
71035c4bbdfSmrg * initialized.
71135c4bbdfSmrg */
71205b261ecSmrgBool
71335c4bbdfSmrgephyrCreateResources(ScreenPtr pScreen)
71405b261ecSmrg{
71535c4bbdfSmrg    KdScreenPriv(pScreen);
71635c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
71735c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
71835c4bbdfSmrg
71935c4bbdfSmrg    EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d",
72035c4bbdfSmrg              pScreen, pScreen->myNum, scrpriv->shadow);
72135c4bbdfSmrg
72235c4bbdfSmrg    if (scrpriv->shadow)
72335c4bbdfSmrg        return KdShadowSet(pScreen,
72435c4bbdfSmrg                           scrpriv->randr,
72535c4bbdfSmrg                           ephyrShadowUpdate, ephyrWindowLinear);
72635c4bbdfSmrg    else {
72735c4bbdfSmrg#ifdef GLAMOR
7281b5d61b8Smrg        if (ephyr_glamor) {
7291b5d61b8Smrg            if (!ephyr_glamor_create_screen_resources(pScreen))
7301b5d61b8Smrg                return FALSE;
7311b5d61b8Smrg        }
73235c4bbdfSmrg#endif
73335c4bbdfSmrg        return ephyrSetInternalDamage(pScreen);
73435c4bbdfSmrg    }
73505b261ecSmrg}
73605b261ecSmrg
73705b261ecSmrgvoid
73835c4bbdfSmrgephyrScreenFini(KdScreenInfo * screen)
73905b261ecSmrg{
74035c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
74135c4bbdfSmrg
7424642e01fSmrg    if (scrpriv->shadow) {
74335c4bbdfSmrg        KdShadowFbFree(screen);
7444642e01fSmrg    }
7451b5d61b8Smrg    scrpriv->BlockHandler = NULL;
74605b261ecSmrg}
74705b261ecSmrg
74835c4bbdfSmrgvoid
74935c4bbdfSmrgephyrCloseScreen(ScreenPtr pScreen)
75035c4bbdfSmrg{
75135c4bbdfSmrg    ephyrUnsetInternalDamage(pScreen);
75235c4bbdfSmrg}
75335c4bbdfSmrg
75435c4bbdfSmrg/*
75505b261ecSmrg * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug.
75605b261ecSmrg * See https://bugs.freedesktop.org/show_bug.cgi?id=3030
75705b261ecSmrg */
75805b261ecSmrgvoid
75905b261ecSmrgephyrUpdateModifierState(unsigned int state)
76005b261ecSmrg{
76105b261ecSmrg
76235c4bbdfSmrg    DeviceIntPtr pDev = inputInfo.keyboard;
76335c4bbdfSmrg    KeyClassPtr keyc = pDev->key;
76435c4bbdfSmrg    int i;
76535c4bbdfSmrg    CARD8 mask;
76635c4bbdfSmrg    int xkb_state;
7676747b715Smrg
76835c4bbdfSmrg    if (!pDev)
76935c4bbdfSmrg        return;
7706747b715Smrg
77135c4bbdfSmrg    xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state);
77235c4bbdfSmrg    state = state & 0xff;
7736747b715Smrg
77435c4bbdfSmrg    if (xkb_state == state)
77535c4bbdfSmrg        return;
7766747b715Smrg
77735c4bbdfSmrg    for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
77835c4bbdfSmrg        int key;
77905b261ecSmrg
780ed6184dfSmrg        /* Modifier is down, but shouldn't be */
78135c4bbdfSmrg        if ((xkb_state & mask) && !(state & mask)) {
78235c4bbdfSmrg            int count = keyc->modifierKeyCount[i];
7834642e01fSmrg
78435c4bbdfSmrg            for (key = 0; key < MAP_LENGTH; key++)
78535c4bbdfSmrg                if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
78635c4bbdfSmrg                    if (mask == XCB_MOD_MASK_LOCK) {
78735c4bbdfSmrg                        KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE);
78835c4bbdfSmrg                        KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE);
78935c4bbdfSmrg                    }
79035c4bbdfSmrg                    else if (key_is_down(pDev, key, KEY_PROCESSED))
79135c4bbdfSmrg                        KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE);
7924642e01fSmrg
79335c4bbdfSmrg                    if (--count == 0)
79435c4bbdfSmrg                        break;
79535c4bbdfSmrg                }
79635c4bbdfSmrg        }
7974642e01fSmrg
798ed6184dfSmrg        /* Modifier should be down, but isn't */
79935c4bbdfSmrg        if (!(xkb_state & mask) && (state & mask))
80035c4bbdfSmrg            for (key = 0; key < MAP_LENGTH; key++)
80135c4bbdfSmrg                if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
80235c4bbdfSmrg                    KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE);
80335c4bbdfSmrg                    if (mask == XCB_MOD_MASK_LOCK)
80435c4bbdfSmrg                        KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE);
80535c4bbdfSmrg                    break;
80635c4bbdfSmrg                }
80735c4bbdfSmrg    }
8084642e01fSmrg}
8094642e01fSmrg
8104642e01fSmrgstatic Bool
8114642e01fSmrgephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
8124642e01fSmrg{
81335c4bbdfSmrg    return FALSE;
8144642e01fSmrg}
8154642e01fSmrg
8164642e01fSmrgstatic void
81735c4bbdfSmrgephyrCrossScreen(ScreenPtr pScreen, Bool entering)
8184642e01fSmrg{
8194642e01fSmrg}
8204642e01fSmrg
82135c4bbdfSmrgScreenPtr ephyrCursorScreen; /* screen containing the cursor */
8224642e01fSmrg
8234642e01fSmrgstatic void
82435c4bbdfSmrgephyrWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
8254642e01fSmrg{
8261b5d61b8Smrg    input_lock();
82735c4bbdfSmrg    ephyrCursorScreen = pScreen;
82835c4bbdfSmrg    miPointerWarpCursor(inputInfo.pointer, pScreen, x, y);
82935c4bbdfSmrg
8301b5d61b8Smrg    input_unlock();
8314642e01fSmrg}
8324642e01fSmrg
83335c4bbdfSmrgmiPointerScreenFuncRec ephyrPointerScreenFuncs = {
83435c4bbdfSmrg    ephyrCursorOffScreen,
83535c4bbdfSmrg    ephyrCrossScreen,
83635c4bbdfSmrg    ephyrWarpCursor,
8374642e01fSmrg};
8384642e01fSmrg
83935c4bbdfSmrgstatic KdScreenInfo *
84035c4bbdfSmrgscreen_from_window(Window w)
84105b261ecSmrg{
84235c4bbdfSmrg    int i = 0;
84335c4bbdfSmrg
84435c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
84535c4bbdfSmrg        ScreenPtr pScreen = screenInfo.screens[i];
84635c4bbdfSmrg        KdPrivScreenPtr kdscrpriv = KdGetScreenPriv(pScreen);
84735c4bbdfSmrg        KdScreenInfo *screen = kdscrpriv->screen;
84835c4bbdfSmrg        EphyrScrPriv *scrpriv = screen->driver;
84935c4bbdfSmrg
85035c4bbdfSmrg        if (scrpriv->win == w
85135c4bbdfSmrg            || scrpriv->peer_win == w
85235c4bbdfSmrg            || scrpriv->win_pre_existing == w) {
85335c4bbdfSmrg            return screen;
85435c4bbdfSmrg        }
85535c4bbdfSmrg    }
85635c4bbdfSmrg
85735c4bbdfSmrg    return NULL;
85835c4bbdfSmrg}
85935c4bbdfSmrg
86035c4bbdfSmrgstatic void
86135c4bbdfSmrgephyrProcessErrorEvent(xcb_generic_event_t *xev)
86235c4bbdfSmrg{
86335c4bbdfSmrg    xcb_generic_error_t *e = (xcb_generic_error_t *)xev;
86435c4bbdfSmrg
86535c4bbdfSmrg    FatalError("X11 error\n"
86635c4bbdfSmrg               "Error code: %hhu\n"
86735c4bbdfSmrg               "Sequence number: %hu\n"
86835c4bbdfSmrg               "Major code: %hhu\tMinor code: %hu\n"
86935c4bbdfSmrg               "Error value: %u\n",
87035c4bbdfSmrg               e->error_code,
87135c4bbdfSmrg               e->sequence,
87235c4bbdfSmrg               e->major_code, e->minor_code,
87335c4bbdfSmrg               e->resource_id);
87435c4bbdfSmrg}
87535c4bbdfSmrg
87635c4bbdfSmrgstatic void
87735c4bbdfSmrgephyrProcessExpose(xcb_generic_event_t *xev)
87835c4bbdfSmrg{
87935c4bbdfSmrg    xcb_expose_event_t *expose = (xcb_expose_event_t *)xev;
88035c4bbdfSmrg    KdScreenInfo *screen = screen_from_window(expose->window);
88135c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
88235c4bbdfSmrg
88335c4bbdfSmrg    /* Wait for the last expose event in a series of cliprects
88435c4bbdfSmrg     * to actually paint our screen.
88535c4bbdfSmrg     */
88635c4bbdfSmrg    if (expose->count != 0)
88735c4bbdfSmrg        return;
88835c4bbdfSmrg
88935c4bbdfSmrg    if (scrpriv) {
89035c4bbdfSmrg        hostx_paint_rect(scrpriv->screen, 0, 0, 0, 0,
89135c4bbdfSmrg                         scrpriv->win_width,
89235c4bbdfSmrg                         scrpriv->win_height);
89335c4bbdfSmrg    } else {
89435c4bbdfSmrg        EPHYR_LOG_ERROR("failed to get host screen\n");
89535c4bbdfSmrg    }
89635c4bbdfSmrg}
89735c4bbdfSmrg
89835c4bbdfSmrgstatic void
89935c4bbdfSmrgephyrProcessMouseMotion(xcb_generic_event_t *xev)
90035c4bbdfSmrg{
90135c4bbdfSmrg    xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)xev;
90235c4bbdfSmrg    KdScreenInfo *screen = screen_from_window(motion->event);
90335c4bbdfSmrg
90435c4bbdfSmrg    if (!ephyrMouse ||
90535c4bbdfSmrg        !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) {
90635c4bbdfSmrg        EPHYR_LOG("skipping mouse motion:%d\n", screen->pScreen->myNum);
90735c4bbdfSmrg        return;
90835c4bbdfSmrg    }
90935c4bbdfSmrg
91035c4bbdfSmrg    if (ephyrCursorScreen != screen->pScreen) {
91135c4bbdfSmrg        EPHYR_LOG("warping mouse cursor. "
91235c4bbdfSmrg                  "cur_screen:%d, motion_screen:%d\n",
91335c4bbdfSmrg                  ephyrCursorScreen->myNum, screen->pScreen->myNum);
91435c4bbdfSmrg        ephyrWarpCursor(inputInfo.pointer, screen->pScreen,
91535c4bbdfSmrg                        motion->event_x, motion->event_y);
91635c4bbdfSmrg    }
91735c4bbdfSmrg    else {
91835c4bbdfSmrg        int x = 0, y = 0;
91935c4bbdfSmrg
92035c4bbdfSmrg        EPHYR_LOG("enqueuing mouse motion:%d\n", screen->pScreen->myNum);
92135c4bbdfSmrg        x = motion->event_x;
92235c4bbdfSmrg        y = motion->event_y;
92335c4bbdfSmrg        EPHYR_LOG("initial (x,y):(%d,%d)\n", x, y);
92405b261ecSmrg
92535c4bbdfSmrg        /* convert coords into desktop-wide coordinates.
92635c4bbdfSmrg         * fill_pointer_events will convert that back to
92735c4bbdfSmrg         * per-screen coordinates where needed */
92835c4bbdfSmrg        x += screen->pScreen->x;
92935c4bbdfSmrg        y += screen->pScreen->y;
93035c4bbdfSmrg
93135c4bbdfSmrg        KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_POINTER_DESKTOP, x, y, 0);
93235c4bbdfSmrg    }
93335c4bbdfSmrg}
93435c4bbdfSmrg
93535c4bbdfSmrgstatic void
93635c4bbdfSmrgephyrProcessButtonPress(xcb_generic_event_t *xev)
93735c4bbdfSmrg{
93835c4bbdfSmrg    xcb_button_press_event_t *button = (xcb_button_press_event_t *)xev;
93935c4bbdfSmrg
94035c4bbdfSmrg    if (!ephyrMouse ||
94135c4bbdfSmrg        !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) {
94235c4bbdfSmrg        EPHYR_LOG("skipping mouse press:%d\n", screen_from_window(button->event)->pScreen->myNum);
94335c4bbdfSmrg        return;
94435c4bbdfSmrg    }
94535c4bbdfSmrg
94635c4bbdfSmrg    ephyrUpdateModifierState(button->state);
94735c4bbdfSmrg    /* This is a bit hacky. will break for button 5 ( defined as 0x10 )
94835c4bbdfSmrg     * Check KD_BUTTON defines in kdrive.h
94935c4bbdfSmrg     */
95035c4bbdfSmrg    mouseState |= 1 << (button->detail - 1);
95135c4bbdfSmrg
95235c4bbdfSmrg    EPHYR_LOG("enqueuing mouse press:%d\n", screen_from_window(button->event)->pScreen->myNum);
95335c4bbdfSmrg    KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_MOUSE_DELTA, 0, 0, 0);
95435c4bbdfSmrg}
95535c4bbdfSmrg
95635c4bbdfSmrgstatic void
95735c4bbdfSmrgephyrProcessButtonRelease(xcb_generic_event_t *xev)
95835c4bbdfSmrg{
95935c4bbdfSmrg    xcb_button_press_event_t *button = (xcb_button_press_event_t *)xev;
96035c4bbdfSmrg
96135c4bbdfSmrg    if (!ephyrMouse ||
96235c4bbdfSmrg        !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) {
96335c4bbdfSmrg        return;
96435c4bbdfSmrg    }
96535c4bbdfSmrg
96635c4bbdfSmrg    ephyrUpdateModifierState(button->state);
96735c4bbdfSmrg    mouseState &= ~(1 << (button->detail - 1));
96835c4bbdfSmrg
96935c4bbdfSmrg    EPHYR_LOG("enqueuing mouse release:%d\n", screen_from_window(button->event)->pScreen->myNum);
97035c4bbdfSmrg    KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_MOUSE_DELTA, 0, 0, 0);
97135c4bbdfSmrg}
97235c4bbdfSmrg
97335c4bbdfSmrg/* Xephyr wants ctrl+shift to grab the window, but that conflicts with
97435c4bbdfSmrg   ctrl+alt+shift key combos. Remember the modifier state on key presses and
97535c4bbdfSmrg   releases, if mod1 is pressed, we need ctrl, shift and mod1 released
97635c4bbdfSmrg   before we allow a shift-ctrl grab activation.
97735c4bbdfSmrg
97835c4bbdfSmrg   note: a key event contains the mask _before_ the current key takes
97935c4bbdfSmrg   effect, so mod1_was_down will be reset on the first key press after all
98035c4bbdfSmrg   three were released, not on the last release. That'd require some more
98135c4bbdfSmrg   effort.
98235c4bbdfSmrg */
98335c4bbdfSmrgstatic int
98435c4bbdfSmrgephyrUpdateGrabModifierState(int state)
98535c4bbdfSmrg{
98635c4bbdfSmrg    static int mod1_was_down = 0;
98735c4bbdfSmrg
98835c4bbdfSmrg    if ((state & (XCB_MOD_MASK_CONTROL|XCB_MOD_MASK_SHIFT|XCB_MOD_MASK_1)) == 0)
98935c4bbdfSmrg        mod1_was_down = 0;
99035c4bbdfSmrg    else if (state & XCB_MOD_MASK_1)
99135c4bbdfSmrg        mod1_was_down = 1;
99235c4bbdfSmrg
99335c4bbdfSmrg    return mod1_was_down;
99435c4bbdfSmrg}
99535c4bbdfSmrg
99635c4bbdfSmrgstatic void
99735c4bbdfSmrgephyrProcessKeyPress(xcb_generic_event_t *xev)
99835c4bbdfSmrg{
99935c4bbdfSmrg    xcb_key_press_event_t *key = (xcb_key_press_event_t *)xev;
100035c4bbdfSmrg
100135c4bbdfSmrg    if (!ephyrKbd ||
100235c4bbdfSmrg        !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) {
100335c4bbdfSmrg        return;
100435c4bbdfSmrg    }
100535c4bbdfSmrg
100635c4bbdfSmrg    ephyrUpdateGrabModifierState(key->state);
100735c4bbdfSmrg    ephyrUpdateModifierState(key->state);
100835c4bbdfSmrg    KdEnqueueKeyboardEvent(ephyrKbd, key->detail, FALSE);
100935c4bbdfSmrg}
101035c4bbdfSmrg
101135c4bbdfSmrgstatic void
101235c4bbdfSmrgephyrProcessKeyRelease(xcb_generic_event_t *xev)
101335c4bbdfSmrg{
101435c4bbdfSmrg    xcb_connection_t *conn = hostx_get_xcbconn();
101535c4bbdfSmrg    xcb_key_release_event_t *key = (xcb_key_release_event_t *)xev;
101635c4bbdfSmrg    static xcb_key_symbols_t *keysyms;
101735c4bbdfSmrg    static int grabbed_screen = -1;
101835c4bbdfSmrg    int mod1_down = ephyrUpdateGrabModifierState(key->state);
101935c4bbdfSmrg
102035c4bbdfSmrg    if (!keysyms)
102135c4bbdfSmrg        keysyms = xcb_key_symbols_alloc(conn);
102235c4bbdfSmrg
102335c4bbdfSmrg    if (!EphyrWantNoHostGrab &&
102435c4bbdfSmrg        (((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_L
102535c4bbdfSmrg          || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_R)
102635c4bbdfSmrg         && (key->state & XCB_MOD_MASK_CONTROL)) ||
102735c4bbdfSmrg        ((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_L
102835c4bbdfSmrg          || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_R)
102935c4bbdfSmrg         && (key->state & XCB_MOD_MASK_SHIFT)))) {
103035c4bbdfSmrg        KdScreenInfo *screen = screen_from_window(key->event);
103135c4bbdfSmrg        EphyrScrPriv *scrpriv = screen->driver;
103235c4bbdfSmrg
103335c4bbdfSmrg        if (grabbed_screen != -1) {
103435c4bbdfSmrg            xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME);
103535c4bbdfSmrg            xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME);
103635c4bbdfSmrg            grabbed_screen = -1;
103735c4bbdfSmrg            hostx_set_win_title(screen,
103835c4bbdfSmrg                                "(ctrl+shift grabs mouse and keyboard)");
103935c4bbdfSmrg        }
104035c4bbdfSmrg        else if (!mod1_down) {
104135c4bbdfSmrg            /* Attempt grab */
104235c4bbdfSmrg            xcb_grab_keyboard_cookie_t kbgrabc =
104335c4bbdfSmrg                xcb_grab_keyboard(conn,
104435c4bbdfSmrg                                  TRUE,
104535c4bbdfSmrg                                  scrpriv->win,
104635c4bbdfSmrg                                  XCB_TIME_CURRENT_TIME,
104735c4bbdfSmrg                                  XCB_GRAB_MODE_ASYNC,
104835c4bbdfSmrg                                  XCB_GRAB_MODE_ASYNC);
104935c4bbdfSmrg            xcb_grab_keyboard_reply_t *kbgrabr;
105035c4bbdfSmrg            xcb_grab_pointer_cookie_t pgrabc =
105135c4bbdfSmrg                xcb_grab_pointer(conn,
105235c4bbdfSmrg                                 TRUE,
105335c4bbdfSmrg                                 scrpriv->win,
105435c4bbdfSmrg                                 0,
105535c4bbdfSmrg                                 XCB_GRAB_MODE_ASYNC,
105635c4bbdfSmrg                                 XCB_GRAB_MODE_ASYNC,
105735c4bbdfSmrg                                 scrpriv->win,
105835c4bbdfSmrg                                 XCB_NONE,
105935c4bbdfSmrg                                 XCB_TIME_CURRENT_TIME);
106035c4bbdfSmrg            xcb_grab_pointer_reply_t *pgrabr;
106135c4bbdfSmrg            kbgrabr = xcb_grab_keyboard_reply(conn, kbgrabc, NULL);
106235c4bbdfSmrg            if (!kbgrabr || kbgrabr->status != XCB_GRAB_STATUS_SUCCESS) {
106335c4bbdfSmrg                xcb_discard_reply(conn, pgrabc.sequence);
106435c4bbdfSmrg                xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME);
106535c4bbdfSmrg            } else {
106635c4bbdfSmrg                pgrabr = xcb_grab_pointer_reply(conn, pgrabc, NULL);
106735c4bbdfSmrg                if (!pgrabr || pgrabr->status != XCB_GRAB_STATUS_SUCCESS)
106835c4bbdfSmrg                    {
106935c4bbdfSmrg                        xcb_ungrab_keyboard(conn,
107035c4bbdfSmrg                                            XCB_TIME_CURRENT_TIME);
107135c4bbdfSmrg                    } else {
107235c4bbdfSmrg                    grabbed_screen = scrpriv->mynum;
107335c4bbdfSmrg                    hostx_set_win_title
107435c4bbdfSmrg                        (screen,
107535c4bbdfSmrg                         "(ctrl+shift releases mouse and keyboard)");
107635c4bbdfSmrg                }
107735c4bbdfSmrg            }
107835c4bbdfSmrg        }
107935c4bbdfSmrg    }
108035c4bbdfSmrg
108135c4bbdfSmrg    if (!ephyrKbd ||
108235c4bbdfSmrg        !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) {
108335c4bbdfSmrg        return;
108435c4bbdfSmrg    }
108535c4bbdfSmrg
108635c4bbdfSmrg    /* Still send the release event even if above has happened server
108735c4bbdfSmrg     * will get confused with just an up event.  Maybe it would be
108835c4bbdfSmrg     * better to just block shift+ctrls getting to kdrive all
108935c4bbdfSmrg     * together.
109035c4bbdfSmrg     */
109135c4bbdfSmrg    ephyrUpdateModifierState(key->state);
109235c4bbdfSmrg    KdEnqueueKeyboardEvent(ephyrKbd, key->detail, TRUE);
109335c4bbdfSmrg}
109435c4bbdfSmrg
109535c4bbdfSmrgstatic void
109635c4bbdfSmrgephyrProcessConfigureNotify(xcb_generic_event_t *xev)
109735c4bbdfSmrg{
109835c4bbdfSmrg    xcb_configure_notify_event_t *configure =
109935c4bbdfSmrg        (xcb_configure_notify_event_t *)xev;
110035c4bbdfSmrg    KdScreenInfo *screen = screen_from_window(configure->window);
110135c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
110235c4bbdfSmrg
110335c4bbdfSmrg    if (!scrpriv ||
110435c4bbdfSmrg        (scrpriv->win_pre_existing == None && !EphyrWantResize)) {
110535c4bbdfSmrg        return;
110605b261ecSmrg    }
110735c4bbdfSmrg
110835c4bbdfSmrg#ifdef RANDR
110935c4bbdfSmrg    ephyrResizeScreen(screen->pScreen, configure->width, configure->height);
111035c4bbdfSmrg#endif /* RANDR */
111105b261ecSmrg}
111205b261ecSmrg
11131b5d61b8Smrgstatic void
11141b5d61b8SmrgephyrXcbProcessEvents(Bool queued_only)
111505b261ecSmrg{
111635c4bbdfSmrg    xcb_connection_t *conn = hostx_get_xcbconn();
11171b5d61b8Smrg    xcb_generic_event_t *expose = NULL, *configure = NULL;
111835c4bbdfSmrg
111935c4bbdfSmrg    while (TRUE) {
11201b5d61b8Smrg        xcb_generic_event_t *xev = hostx_get_event(queued_only);
11211b5d61b8Smrg
112235c4bbdfSmrg        if (!xev) {
112335c4bbdfSmrg            /* If our XCB connection has died (for example, our window was
112435c4bbdfSmrg             * closed), exit now.
112535c4bbdfSmrg             */
112635c4bbdfSmrg            if (xcb_connection_has_error(conn)) {
112735c4bbdfSmrg                CloseWellKnownConnections();
112835c4bbdfSmrg                OsCleanup(1);
112935c4bbdfSmrg                exit(1);
113035c4bbdfSmrg            }
113135c4bbdfSmrg
113235c4bbdfSmrg            break;
113335c4bbdfSmrg        }
113435c4bbdfSmrg
113535c4bbdfSmrg        switch (xev->response_type & 0x7f) {
113635c4bbdfSmrg        case 0:
113735c4bbdfSmrg            ephyrProcessErrorEvent(xev);
113835c4bbdfSmrg            break;
113935c4bbdfSmrg
114035c4bbdfSmrg        case XCB_EXPOSE:
11411b5d61b8Smrg            free(expose);
11421b5d61b8Smrg            expose = xev;
11431b5d61b8Smrg            xev = NULL;
114435c4bbdfSmrg            break;
114535c4bbdfSmrg
114635c4bbdfSmrg        case XCB_MOTION_NOTIFY:
114735c4bbdfSmrg            ephyrProcessMouseMotion(xev);
114835c4bbdfSmrg            break;
114935c4bbdfSmrg
115035c4bbdfSmrg        case XCB_KEY_PRESS:
115135c4bbdfSmrg            ephyrProcessKeyPress(xev);
115235c4bbdfSmrg            break;
115335c4bbdfSmrg
115435c4bbdfSmrg        case XCB_KEY_RELEASE:
115535c4bbdfSmrg            ephyrProcessKeyRelease(xev);
115635c4bbdfSmrg            break;
115735c4bbdfSmrg
115835c4bbdfSmrg        case XCB_BUTTON_PRESS:
115935c4bbdfSmrg            ephyrProcessButtonPress(xev);
116035c4bbdfSmrg            break;
116135c4bbdfSmrg
116235c4bbdfSmrg        case XCB_BUTTON_RELEASE:
116335c4bbdfSmrg            ephyrProcessButtonRelease(xev);
116435c4bbdfSmrg            break;
116535c4bbdfSmrg
116635c4bbdfSmrg        case XCB_CONFIGURE_NOTIFY:
11671b5d61b8Smrg            free(configure);
11681b5d61b8Smrg            configure = xev;
11691b5d61b8Smrg            xev = NULL;
117035c4bbdfSmrg            break;
117135c4bbdfSmrg        }
117235c4bbdfSmrg
11731b5d61b8Smrg        if (xev) {
11741b5d61b8Smrg            if (ephyr_glamor)
11751b5d61b8Smrg                ephyr_glamor_process_event(xev);
11761b5d61b8Smrg
11771b5d61b8Smrg            free(xev);
11781b5d61b8Smrg        }
11791b5d61b8Smrg    }
118035c4bbdfSmrg
11811b5d61b8Smrg    if (configure) {
11821b5d61b8Smrg        ephyrProcessConfigureNotify(configure);
11831b5d61b8Smrg        free(configure);
118435c4bbdfSmrg    }
11851b5d61b8Smrg
11861b5d61b8Smrg    if (expose) {
11871b5d61b8Smrg        ephyrProcessExpose(expose);
11881b5d61b8Smrg        free(expose);
11891b5d61b8Smrg    }
11901b5d61b8Smrg}
11911b5d61b8Smrg
11921b5d61b8Smrgstatic void
11931b5d61b8SmrgephyrXcbNotify(int fd, int ready, void *data)
11941b5d61b8Smrg{
11951b5d61b8Smrg    ephyrXcbProcessEvents(FALSE);
119605b261ecSmrg}
119705b261ecSmrg
119805b261ecSmrgvoid
119935c4bbdfSmrgephyrCardFini(KdCardInfo * card)
120005b261ecSmrg{
120135c4bbdfSmrg    EphyrPriv *priv = card->driver;
120235c4bbdfSmrg
120335c4bbdfSmrg    free(priv);
120435c4bbdfSmrg}
120535c4bbdfSmrg
120635c4bbdfSmrgvoid
120735c4bbdfSmrgephyrGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
120835c4bbdfSmrg{
120935c4bbdfSmrg    /* XXX Not sure if this is right */
121035c4bbdfSmrg
121135c4bbdfSmrg    EPHYR_LOG("mark");
121235c4bbdfSmrg
121335c4bbdfSmrg    while (n--) {
121435c4bbdfSmrg        pdefs->red = 0;
121535c4bbdfSmrg        pdefs->green = 0;
121635c4bbdfSmrg        pdefs->blue = 0;
121735c4bbdfSmrg        pdefs++;
121805b261ecSmrg    }
121905b261ecSmrg
122005b261ecSmrg}
122105b261ecSmrg
122205b261ecSmrgvoid
122335c4bbdfSmrgephyrPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
122405b261ecSmrg{
122535c4bbdfSmrg    KdScreenPriv(pScreen);
122635c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
122735c4bbdfSmrg    EphyrScrPriv *scrpriv = screen->driver;
122835c4bbdfSmrg    int min, max, p;
122935c4bbdfSmrg
123035c4bbdfSmrg    /* XXX Not sure if this is right */
123135c4bbdfSmrg
123235c4bbdfSmrg    min = 256;
123335c4bbdfSmrg    max = 0;
123435c4bbdfSmrg
123535c4bbdfSmrg    while (n--) {
123635c4bbdfSmrg        p = pdefs->pixel;
123735c4bbdfSmrg        if (p < min)
123835c4bbdfSmrg            min = p;
123935c4bbdfSmrg        if (p > max)
124035c4bbdfSmrg            max = p;
124135c4bbdfSmrg
124235c4bbdfSmrg        hostx_set_cmap_entry(pScreen, p,
124335c4bbdfSmrg                             pdefs->red >> 8,
124435c4bbdfSmrg                             pdefs->green >> 8, pdefs->blue >> 8);
124535c4bbdfSmrg        pdefs++;
124635c4bbdfSmrg    }
124735c4bbdfSmrg    if (scrpriv->pDamage) {
124835c4bbdfSmrg        BoxRec box;
124935c4bbdfSmrg        RegionRec region;
125035c4bbdfSmrg
125135c4bbdfSmrg        box.x1 = 0;
125235c4bbdfSmrg        box.y1 = 0;
125335c4bbdfSmrg        box.x2 = pScreen->width;
125435c4bbdfSmrg        box.y2 = pScreen->height;
125535c4bbdfSmrg        RegionInit(&region, &box, 1);
125635c4bbdfSmrg        DamageReportDamage(scrpriv->pDamage, &region);
125735c4bbdfSmrg        RegionUninit(&region);
125805b261ecSmrg    }
125905b261ecSmrg}
126005b261ecSmrg
126105b261ecSmrg/* Mouse calls */
126205b261ecSmrg
126305b261ecSmrgstatic Status
126435c4bbdfSmrgMouseInit(KdPointerInfo * pi)
126505b261ecSmrg{
126605b261ecSmrg    pi->driverPrivate = (EphyrPointerPrivate *)
126735c4bbdfSmrg        calloc(sizeof(EphyrPointerPrivate), 1);
126835c4bbdfSmrg    ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = FALSE;
126905b261ecSmrg    pi->nAxes = 3;
127005b261ecSmrg    pi->nButtons = 32;
12716747b715Smrg    free(pi->name);
12726747b715Smrg    pi->name = strdup("Xephyr virtual mouse");
127335c4bbdfSmrg
127435c4bbdfSmrg    /*
127535c4bbdfSmrg     * Must transform pointer coords since the pointer position
127635c4bbdfSmrg     * relative to the Xephyr window is controlled by the host server and
127735c4bbdfSmrg     * remains constant regardless of any rotation applied to the Xephyr screen.
127835c4bbdfSmrg     */
127935c4bbdfSmrg    pi->transformCoordinates = TRUE;
128035c4bbdfSmrg
128105b261ecSmrg    ephyrMouse = pi;
128205b261ecSmrg    return Success;
128305b261ecSmrg}
128405b261ecSmrg
128505b261ecSmrgstatic Status
128635c4bbdfSmrgMouseEnable(KdPointerInfo * pi)
128705b261ecSmrg{
128835c4bbdfSmrg    ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = TRUE;
12891b5d61b8Smrg    SetNotifyFd(hostx_get_fd(), ephyrXcbNotify, X_NOTIFY_READ, NULL);
129005b261ecSmrg    return Success;
129105b261ecSmrg}
129205b261ecSmrg
129305b261ecSmrgstatic void
129435c4bbdfSmrgMouseDisable(KdPointerInfo * pi)
129505b261ecSmrg{
129635c4bbdfSmrg    ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = FALSE;
12971b5d61b8Smrg    RemoveNotifyFd(hostx_get_fd());
129805b261ecSmrg    return;
129905b261ecSmrg}
130005b261ecSmrg
130105b261ecSmrgstatic void
130235c4bbdfSmrgMouseFini(KdPointerInfo * pi)
130305b261ecSmrg{
13041b5d61b8Smrg    free(pi->driverPrivate);
130535c4bbdfSmrg    ephyrMouse = NULL;
130605b261ecSmrg    return;
130705b261ecSmrg}
130805b261ecSmrg
130905b261ecSmrgKdPointerDriver EphyrMouseDriver = {
131005b261ecSmrg    "ephyr",
131105b261ecSmrg    MouseInit,
131205b261ecSmrg    MouseEnable,
131305b261ecSmrg    MouseDisable,
131405b261ecSmrg    MouseFini,
131505b261ecSmrg    NULL,
131605b261ecSmrg};
131705b261ecSmrg
131805b261ecSmrg/* Keyboard */
131905b261ecSmrg
132005b261ecSmrgstatic Status
132135c4bbdfSmrgEphyrKeyboardInit(KdKeyboardInfo * ki)
132205b261ecSmrg{
13231b5d61b8Smrg    KeySymsRec keySyms;
13241b5d61b8Smrg    CARD8 modmap[MAP_LENGTH];
13251b5d61b8Smrg    XkbControlsRec controls;
13261b5d61b8Smrg
132735c4bbdfSmrg    ki->driverPrivate = (EphyrKbdPrivate *)
132835c4bbdfSmrg        calloc(sizeof(EphyrKbdPrivate), 1);
13291b5d61b8Smrg
13301b5d61b8Smrg    if (hostx_load_keymap(&keySyms, modmap, &controls)) {
13311b5d61b8Smrg        XkbApplyMappingChange(ki->dixdev, &keySyms,
13321b5d61b8Smrg                              keySyms.minKeyCode,
13331b5d61b8Smrg                              keySyms.maxKeyCode - keySyms.minKeyCode + 1,
13341b5d61b8Smrg                              modmap, serverClient);
13351b5d61b8Smrg        XkbDDXChangeControls(ki->dixdev, &controls, &controls);
13361b5d61b8Smrg        free(keySyms.map);
13371b5d61b8Smrg    }
13381b5d61b8Smrg
13391b5d61b8Smrg    ki->minScanCode = keySyms.minKeyCode;
13401b5d61b8Smrg    ki->maxScanCode = keySyms.maxKeyCode;
13411b5d61b8Smrg
13421b5d61b8Smrg    if (ki->name != NULL) {
13431b5d61b8Smrg        free(ki->name);
134435c4bbdfSmrg    }
13451b5d61b8Smrg
134635c4bbdfSmrg    ki->name = strdup("Xephyr virtual keyboard");
134735c4bbdfSmrg    ephyrKbd = ki;
134835c4bbdfSmrg    return Success;
134905b261ecSmrg}
135005b261ecSmrg
135105b261ecSmrgstatic Status
135235c4bbdfSmrgEphyrKeyboardEnable(KdKeyboardInfo * ki)
135305b261ecSmrg{
135435c4bbdfSmrg    ((EphyrKbdPrivate *) ki->driverPrivate)->enabled = TRUE;
135505b261ecSmrg
135605b261ecSmrg    return Success;
135705b261ecSmrg}
135805b261ecSmrg
135905b261ecSmrgstatic void
136035c4bbdfSmrgEphyrKeyboardDisable(KdKeyboardInfo * ki)
136105b261ecSmrg{
136235c4bbdfSmrg    ((EphyrKbdPrivate *) ki->driverPrivate)->enabled = FALSE;
136305b261ecSmrg}
136405b261ecSmrg
136505b261ecSmrgstatic void
136635c4bbdfSmrgEphyrKeyboardFini(KdKeyboardInfo * ki)
136705b261ecSmrg{
13681b5d61b8Smrg    free(ki->driverPrivate);
136905b261ecSmrg    ephyrKbd = NULL;
137005b261ecSmrg    return;
137105b261ecSmrg}
137205b261ecSmrg
137305b261ecSmrgstatic void
137435c4bbdfSmrgEphyrKeyboardLeds(KdKeyboardInfo * ki, int leds)
137505b261ecSmrg{
137605b261ecSmrg}
137705b261ecSmrg
137805b261ecSmrgstatic void
137935c4bbdfSmrgEphyrKeyboardBell(KdKeyboardInfo * ki, int volume, int frequency, int duration)
138005b261ecSmrg{
138105b261ecSmrg}
138205b261ecSmrg
138305b261ecSmrgKdKeyboardDriver EphyrKeyboardDriver = {
138405b261ecSmrg    "ephyr",
138505b261ecSmrg    EphyrKeyboardInit,
138605b261ecSmrg    EphyrKeyboardEnable,
138705b261ecSmrg    EphyrKeyboardLeds,
138805b261ecSmrg    EphyrKeyboardBell,
138905b261ecSmrg    EphyrKeyboardDisable,
139005b261ecSmrg    EphyrKeyboardFini,
139105b261ecSmrg    NULL,
139205b261ecSmrg};
1393