Proposal for X Server Plug-in Picker

Deron Johnson Deron.Johnson at Sun.COM
Thu Nov 30 12:47:39 PST 2006


As a further illustration of this proposal, here is the code for the 
changed dix routines:

void
ComputeFreezes()
{
    register DeviceIntPtr replayDev = syncEvents.replayDev;
    register int i;
    WindowPtr w;
    register xEvent *xE;
    int count;
    GrabPtr grab;
    register DeviceIntPtr dev;

    for (dev = inputInfo.devices; dev; dev = dev->next)
        FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
    if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
        return;
    syncEvents.playingEvents = TRUE;
    if (replayDev)
    {
        xE = replayDev->sync.event;
        count = replayDev->sync.evcount;
        syncEvents.replayDev = (DeviceIntPtr)NULL;

#ifdef PICKER
        PICKER_WINDOWS_RESTRUCTURED(syncEvents.replayWin);
#endif /* PICKER */

        w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY);

        for (i = 0; i < spriteTraceGood; i++)
        {
            if (syncEvents.replayWin == spriteTrace[i])
            {
                if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
                    if (replayDev->focus)
                        DeliverFocusedEvent(replayDev, xE, w, count);
                    else
                        DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
                                                replayDev, count);
                }
                goto playmore;
            }
        }
        /* must not still be in the same stack */
        if (replayDev->focus)
            DeliverFocusedEvent(replayDev, xE, w, count);
        else
            DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, 
count);
    }
playmore:
    for (dev = inputInfo.devices; dev; dev = dev->next)
    {
        if (!dev->sync.frozen)
        {
            PlayReleasedEvents();
            break;
        }
    }
    syncEvents.playingEvents = FALSE;
    /* the following may have been skipped during replay, so do it now */
    if ((grab = inputInfo.pointer->grab) && grab->confineTo)
    {
        if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
            sprite.hotPhys.x = sprite.hotPhys.y = 0;
        ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
    }
    else
        ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
                              TRUE, FALSE);
    PostNewCursor();
}

static void
FixUpEventFromWindow(
    xEvent *xE,
    WindowPtr pWin,
    Window child,
    Bool calcChild)
{
#ifdef PICKER
    PICKER_FIXUP_EVENT_FROM_WINDOW(pWin, xE, pWin, child, calcChild);
#else
    if (calcChild)
    {
        WindowPtr w=spriteTrace[spriteTraceGood-1];
        /* If the search ends up past the root should the child field be
                set to none or should the value in the argument be passed
                through. It probably doesn't matter since everyone calls
                this function with child == None anyway. */

        while (w)
        {
            /* If the source window is same as event window, child should be
                none.  Don't bother going all all the way back to the 
root. */

            if (w == pWin)
            {
                child = None;
                break;
            }
           
            if (w->parent == pWin)
            {
                child = w->drawable.id;
                break;
            }
            w = w->parent;
        }          
    }
    XE_KBPTR.root = ROOT->drawable.id;
    XE_KBPTR.event = pWin->drawable.id;
    if (sprite.hot.pScreen == pWin->drawable.pScreen)
    {
        XE_KBPTR.sameScreen = xTrue;
        XE_KBPTR.child = child;
        XE_KBPTR.eventX =
        XE_KBPTR.rootX - pWin->drawable.x;
        XE_KBPTR.eventY =
        XE_KBPTR.rootY - pWin->drawable.y;
    }
    else
    {
        XE_KBPTR.sameScreen = xFalse;
        XE_KBPTR.child = None;
        XE_KBPTR.eventX = 0;
        XE_KBPTR.eventY = 0;
    }
#endif /* PICKER */
}

static WindowPtr
XYToWindow(int x, int y)
{
#ifdef PICKER
    return PICKER_XY_TO_WINDOW(x, y);
#else
    register WindowPtr  pWin;
    BoxRec              box;

    spriteTraceGood = 1;        /* root window still there */
    pWin = ROOT->firstChild;
    while (pWin)
    {
        if ((pWin->mapped) &&
            (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
            (x < pWin->drawable.x + (int)pWin->drawable.width +
             wBorderWidth(pWin)) &&
            (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
            (y < pWin->drawable.y + (int)pWin->drawable.height +
             wBorderWidth (pWin))
#ifdef SHAPE
            /* When a window is shaped, a further check
             * is made to see if the point is inside
             * borderSize
             */
            && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
            && (!wInputShape(pWin) ||
                POINT_IN_REGION(pWin->drawable.pScreen,
                                wInputShape(pWin),
                                x - pWin->drawable.x,
                                y - pWin->drawable.y, &box))
#endif
            )
        {
            if (spriteTraceGood >= spriteTraceSize)
            {
                spriteTraceSize += 10;
                Must_have_memory = TRUE; /* XXX */
                spriteTrace = (WindowPtr *)xrealloc(
                    spriteTrace, spriteTraceSize*sizeof(WindowPtr));
                Must_have_memory = FALSE; /* XXX */
            }
            spriteTrace[spriteTraceGood++] = pWin;
            pWin = pWin->firstChild;
        }
        else
            pWin = pWin->nextSib;
    }
    return spriteTrace[spriteTraceGood-1];
#endif /* PICKER */
}

static Bool
CheckMotion(xEvent *xE)
{
    WindowPtr prevSpriteWin = sprite.win;

#ifdef PANORAMIX
    if(!noPanoramiXExtension)
        return XineramaCheckMotion(xE);
#endif

    if (xE && !syncEvents.playingEvents)
    {
        if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
        {
            sprite.hot.pScreen = sprite.hotPhys.pScreen;
            ROOT = WindowTable[sprite.hot.pScreen->myNum];
        }
#ifdef XEVIE
        xeviehot.x =
#endif
        sprite.hot.x = XE_KBPTR.rootX;
#ifdef XEVIE
        xeviehot.y =
#endif
        sprite.hot.y = XE_KBPTR.rootY;
        if (sprite.hot.x < sprite.physLimits.x1)
#ifdef XEVIE
            xeviehot.x =
#endif
            sprite.hot.x = sprite.physLimits.x1;
        else if (sprite.hot.x >= sprite.physLimits.x2)
#ifdef XEVIE
            xeviehot.x =
#endif
            sprite.hot.x = sprite.physLimits.x2 - 1;
        if (sprite.hot.y < sprite.physLimits.y1)
#ifdef XEVIE
            xeviehot.y =
#endif
            sprite.hot.y = sprite.physLimits.y1;
        else if (sprite.hot.y >= sprite.physLimits.y2)
#ifdef XEVIE
            xeviehot.y =
#endif
            sprite.hot.y = sprite.physLimits.y2 - 1;
#ifdef SHAPE
        if (sprite.hotShape)
            ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
#endif
        sprite.hotPhys = sprite.hot;
        if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
            (sprite.hotPhys.y != XE_KBPTR.rootY))
        {
            (*sprite.hotPhys.pScreen->SetCursorPosition)(
                sprite.hotPhys.pScreen,
                sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
        }
        XE_KBPTR.rootX = sprite.hot.x;
        XE_KBPTR.rootY = sprite.hot.y;
    }

#ifdef PICKER
    if (xE == NULL) {
#ifdef XEVIE
        xeviewin =
#endif
        sprite.win = PICKER_WINDOWS_RESTRUCTURED(sprite.win);
    }
#endif /* PICKER */

#ifdef XEVIE
    xeviewin =
#endif
    sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);

#ifdef notyet
    if (!(sprite.win->deliverableEvents &
          Motion_Filter(inputInfo.pointer->button))
        !syncEvents.playingEvents)
    {
        /* XXX Do PointerNonInterestBox here */
    }
#endif
    if (sprite.win != prevSpriteWin)
    {
        if (prevSpriteWin != NullWindow) {
            if (!xE)
                UpdateCurrentTimeIf();
            DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
        }
        PostNewCursor();
        return FALSE;
    }
    return TRUE;
}

int
ProcQueryPointer(ClientPtr client)
{
    xQueryPointerReply rep;
    WindowPtr pWin, t;
    REQUEST(xResourceReq);
    DeviceIntPtr mouse = inputInfo.pointer;

    REQUEST_SIZE_MATCH(xResourceReq);
    pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess);
    if (!pWin)
        return BadWindow;
    if (mouse->valuator->motionHintWindow)
        MaybeStopHint(mouse, client);
    rep.type = X_Reply;
    rep.sequenceNumber = client->sequence;
    rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
    rep.length = 0;
    rep.root = (ROOT)->drawable.id;
    rep.rootX = sprite.hot.x;
    rep.rootY = sprite.hot.y;
    rep.child = None;
#ifdef PICKER
    PICKER_QUERY_POINTER(sprite.win, pWin, x, y, &rep.winX, &rep.winY, 
&rep.child, &rep.sameScreen);
#else
    if (sprite.hot.pScreen == pWin->drawable.pScreen)
    {
        rep.sameScreen = xTrue;
        rep.winX = sprite.hot.x - pWin->drawable.x;
        rep.winY = sprite.hot.y - pWin->drawable.y;
        for (t = sprite.win; t; t = t->parent)
            if (t->parent == pWin)
            {
                rep.child = t->drawable.id;
                break;
            }
    }
    else
    {
        rep.sameScreen = xFalse;
        rep.winX = 0;
        rep.winY = 0;
    }
#endif /* PICKER */

#ifdef PANORAMIX
    if(!noPanoramiXExtension) {
        rep.rootX += panoramiXdataPtr[0].x;
        rep.rootY += panoramiXdataPtr[0].y;
        if(stuff->id == rep.root) {
            rep.winX += panoramiXdataPtr[0].x;
            rep.winY += panoramiXdataPtr[0].y;
        }
    }
#endif

    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);

    return(Success);   
}

int
ProcTranslateCoords(register ClientPtr client)
{
    REQUEST(xTranslateCoordsReq);

    register WindowPtr pWin, pDst;
    xTranslateCoordsReply rep;

    REQUEST_SIZE_MATCH(xTranslateCoordsReq);
    pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client,
                                           SecurityReadAccess);
    if (!pWin)
        return(BadWindow);
    pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client,
                                           SecurityReadAccess);
    if (!pDst)
        return(BadWindow);
    rep.type = X_Reply;
    rep.length = 0;
    rep.sequenceNumber = client->sequence;
#ifdef PICKER
    PICKER_TRANSLATE_COORDS(pWin, pDst, x, y, &rep.dstX, &rep.dstY, 
&rep.child, &rep.sameScreen);
#else
    if (!SAME_SCREENS(pWin->drawable, pDst->drawable))
    {
        rep.sameScreen = xFalse;
        rep.child = None;
        rep.dstX = rep.dstY = 0;
    }
    else
    {
        rep.sameScreen = xTrue;
        rep.child = None;
        INT16 x, y;
        rep.sameScreen = xTrue;
        rep.child = None;
        /* computing absolute coordinates -- adjust to destination later */
        x = pWin->drawable.x + stuff->srcX;
        y = pWin->drawable.y + stuff->srcY;
        pWin = pDst->firstChild;
        while (pWin)
        {
#ifdef SHAPE
            BoxRec  box;
#endif
            if ((pWin->mapped) &&
                (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
                (x < pWin->drawable.x + (int)pWin->drawable.width +
                 wBorderWidth (pWin)) &&
                (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
                (y < pWin->drawable.y + (int)pWin->drawable.height +
                 wBorderWidth (pWin))
#ifdef SHAPE
                /* When a window is shaped, a further check
                 * is made to see if the point is inside
                 * borderSize
                 */
                && (!wBoundingShape(pWin) ||
                    POINT_IN_REGION(pWin->drawable.pScreen,
                                        &pWin->borderSize, x, y, &box))

                && (!wInputShape(pWin) ||
                    POINT_IN_REGION(pWin->drawable.pScreen,
                                    wInputShape(pWin),
                                    x - pWin->drawable.x,
                                    y - pWin->drawable.y, &box))
#endif
                )
            {
                rep.child = pWin->drawable.id;
                pWin = (WindowPtr) NULL;
            }
            else
                pWin = pWin->nextSib;
        }
        /* adjust to destination coordinates */
        rep.dstX = x - pDst->drawable.x;
        rep.dstY = y - pDst->drawable.y;
#endif /* PICKER */
    }
    WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
    return(client->noClientException);
}








 




More information about the xorg mailing list