rrdispatch.c revision 1b5d61b8
105b261ecSmrg/*
205b261ecSmrg * Copyright © 2006 Keith Packard
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that copyright
705b261ecSmrg * notice and this permission notice appear in supporting documentation, and
805b261ecSmrg * that the name of the copyright holders not be used in advertising or
905b261ecSmrg * publicity pertaining to distribution of the software without specific,
1005b261ecSmrg * written prior permission.  The copyright holders make no representations
1105b261ecSmrg * about the suitability of this software for any purpose.  It is provided "as
1205b261ecSmrg * is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2005b261ecSmrg * OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg
2305b261ecSmrg#include "randrstr.h"
246747b715Smrg#include "protocol-versions.h"
2505b261ecSmrg
2605b261ecSmrgBool
2735c4bbdfSmrgRRClientKnowsRates(ClientPtr pClient)
2805b261ecSmrg{
2905b261ecSmrg    rrClientPriv(pClient);
3005b261ecSmrg
3135c4bbdfSmrg    return version_compare(pRRClient->major_version, pRRClient->minor_version,
3235c4bbdfSmrg                           1, 1) >= 0;
3305b261ecSmrg}
3405b261ecSmrg
3505b261ecSmrgstatic int
3635c4bbdfSmrgProcRRQueryVersion(ClientPtr client)
3705b261ecSmrg{
3835c4bbdfSmrg    xRRQueryVersionReply rep = {
3935c4bbdfSmrg        .type = X_Reply,
4035c4bbdfSmrg        .sequenceNumber = client->sequence,
4135c4bbdfSmrg        .length = 0
4235c4bbdfSmrg    };
4305b261ecSmrg    REQUEST(xRRQueryVersionReq);
4405b261ecSmrg    rrClientPriv(client);
4505b261ecSmrg
4605b261ecSmrg    REQUEST_SIZE_MATCH(xRRQueryVersionReq);
4705b261ecSmrg    pRRClient->major_version = stuff->majorVersion;
4805b261ecSmrg    pRRClient->minor_version = stuff->minorVersion;
496747b715Smrg
5035c4bbdfSmrg    if (version_compare(stuff->majorVersion, stuff->minorVersion,
5135c4bbdfSmrg                        SERVER_RANDR_MAJOR_VERSION,
5235c4bbdfSmrg                        SERVER_RANDR_MINOR_VERSION) < 0) {
5335c4bbdfSmrg        rep.majorVersion = stuff->majorVersion;
5435c4bbdfSmrg        rep.minorVersion = stuff->minorVersion;
5535c4bbdfSmrg    }
5635c4bbdfSmrg    else {
576747b715Smrg        rep.majorVersion = SERVER_RANDR_MAJOR_VERSION;
586747b715Smrg        rep.minorVersion = SERVER_RANDR_MINOR_VERSION;
596747b715Smrg    }
606747b715Smrg
6105b261ecSmrg    if (client->swapped) {
6235c4bbdfSmrg        swaps(&rep.sequenceNumber);
6335c4bbdfSmrg        swapl(&rep.length);
6435c4bbdfSmrg        swapl(&rep.majorVersion);
6535c4bbdfSmrg        swapl(&rep.minorVersion);
6605b261ecSmrg    }
6735c4bbdfSmrg    WriteToClient(client, sizeof(xRRQueryVersionReply), &rep);
686747b715Smrg    return Success;
6905b261ecSmrg}
7005b261ecSmrg
7105b261ecSmrgstatic int
7235c4bbdfSmrgProcRRSelectInput(ClientPtr client)
7305b261ecSmrg{
7405b261ecSmrg    REQUEST(xRRSelectInputReq);
7505b261ecSmrg    rrClientPriv(client);
7635c4bbdfSmrg    RRTimesPtr pTimes;
7735c4bbdfSmrg    WindowPtr pWin;
7835c4bbdfSmrg    RREventPtr pRREvent, *pHead;
7935c4bbdfSmrg    XID clientResource;
8035c4bbdfSmrg    int rc;
8105b261ecSmrg
8205b261ecSmrg    REQUEST_SIZE_MATCH(xRRSelectInputReq);
834642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
8405b261ecSmrg    if (rc != Success)
8535c4bbdfSmrg        return rc;
8635c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
8735c4bbdfSmrg                                 RREventType, client, DixWriteAccess);
886747b715Smrg    if (rc != Success && rc != BadValue)
8935c4bbdfSmrg        return rc;
9035c4bbdfSmrg
9135c4bbdfSmrg    if (stuff->enable & (RRScreenChangeNotifyMask |
9235c4bbdfSmrg                         RRCrtcChangeNotifyMask |
9335c4bbdfSmrg                         RROutputChangeNotifyMask |
9435c4bbdfSmrg                         RROutputPropertyNotifyMask |
9535c4bbdfSmrg                         RRProviderChangeNotifyMask |
9635c4bbdfSmrg                         RRProviderPropertyNotifyMask |
9735c4bbdfSmrg                         RRResourceChangeNotifyMask)) {
9835c4bbdfSmrg        ScreenPtr pScreen = pWin->drawable.pScreen;
9905b261ecSmrg
10035c4bbdfSmrg        rrScrPriv(pScreen);
10105b261ecSmrg
10235c4bbdfSmrg        pRREvent = NULL;
10335c4bbdfSmrg        if (pHead) {
10435c4bbdfSmrg            /* check for existing entry. */
10535c4bbdfSmrg            for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
10635c4bbdfSmrg                if (pRREvent->client == client)
10735c4bbdfSmrg                    break;
10835c4bbdfSmrg        }
10905b261ecSmrg
11035c4bbdfSmrg        if (!pRREvent) {
11135c4bbdfSmrg            /* build the entry */
11235c4bbdfSmrg            pRREvent = (RREventPtr) malloc(sizeof(RREventRec));
11335c4bbdfSmrg            if (!pRREvent)
11435c4bbdfSmrg                return BadAlloc;
11535c4bbdfSmrg            pRREvent->next = 0;
11635c4bbdfSmrg            pRREvent->client = client;
11735c4bbdfSmrg            pRREvent->window = pWin;
11835c4bbdfSmrg            pRREvent->mask = stuff->enable;
11935c4bbdfSmrg            /*
12035c4bbdfSmrg             * add a resource that will be deleted when
12135c4bbdfSmrg             * the client goes away
12235c4bbdfSmrg             */
12335c4bbdfSmrg            clientResource = FakeClientID(client->index);
12435c4bbdfSmrg            pRREvent->clientResource = clientResource;
12535c4bbdfSmrg            if (!AddResource(clientResource, RRClientType, (void *) pRREvent))
12635c4bbdfSmrg                return BadAlloc;
12735c4bbdfSmrg            /*
12835c4bbdfSmrg             * create a resource to contain a pointer to the list
12935c4bbdfSmrg             * of clients selecting input.  This must be indirect as
13035c4bbdfSmrg             * the list may be arbitrarily rearranged which cannot be
13135c4bbdfSmrg             * done through the resource database.
13235c4bbdfSmrg             */
13335c4bbdfSmrg            if (!pHead) {
13435c4bbdfSmrg                pHead = (RREventPtr *) malloc(sizeof(RREventPtr));
13535c4bbdfSmrg                if (!pHead ||
13635c4bbdfSmrg                    !AddResource(pWin->drawable.id, RREventType,
13735c4bbdfSmrg                                 (void *) pHead)) {
13835c4bbdfSmrg                    FreeResource(clientResource, RT_NONE);
13935c4bbdfSmrg                    return BadAlloc;
14035c4bbdfSmrg                }
14135c4bbdfSmrg                *pHead = 0;
14235c4bbdfSmrg            }
14335c4bbdfSmrg            pRREvent->next = *pHead;
14435c4bbdfSmrg            *pHead = pRREvent;
14535c4bbdfSmrg        }
14635c4bbdfSmrg        /*
14735c4bbdfSmrg         * Now see if the client needs an event
14835c4bbdfSmrg         */
14935c4bbdfSmrg        if (pScrPriv) {
15035c4bbdfSmrg            pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
15135c4bbdfSmrg            if (CompareTimeStamps(pTimes->setTime,
15235c4bbdfSmrg                                  pScrPriv->lastSetTime) != 0 ||
15335c4bbdfSmrg                CompareTimeStamps(pTimes->configTime,
15435c4bbdfSmrg                                  pScrPriv->lastConfigTime) != 0) {
15535c4bbdfSmrg                if (pRREvent->mask & RRScreenChangeNotifyMask) {
15635c4bbdfSmrg                    RRDeliverScreenEvent(client, pWin, pScreen);
15735c4bbdfSmrg                }
1589ace9065Smrg
15935c4bbdfSmrg                if (pRREvent->mask & RRCrtcChangeNotifyMask) {
16035c4bbdfSmrg                    int i;
1619ace9065Smrg
16235c4bbdfSmrg                    for (i = 0; i < pScrPriv->numCrtcs; i++) {
16335c4bbdfSmrg                        RRDeliverCrtcEvent(client, pWin, pScrPriv->crtcs[i]);
16435c4bbdfSmrg                    }
16535c4bbdfSmrg                }
1669ace9065Smrg
16735c4bbdfSmrg                if (pRREvent->mask & RROutputChangeNotifyMask) {
16835c4bbdfSmrg                    int i;
1699ace9065Smrg
17035c4bbdfSmrg                    for (i = 0; i < pScrPriv->numOutputs; i++) {
17135c4bbdfSmrg                        RRDeliverOutputEvent(client, pWin,
17235c4bbdfSmrg                                             pScrPriv->outputs[i]);
17335c4bbdfSmrg                    }
17435c4bbdfSmrg                }
1759ace9065Smrg
17635c4bbdfSmrg                /* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't
17735c4bbdfSmrg                 * say if there ought to be notifications of changes to output properties
17835c4bbdfSmrg                 * if those changes occurred before the time RRSelectInput is called.
17935c4bbdfSmrg                 */
18035c4bbdfSmrg            }
18135c4bbdfSmrg        }
18205b261ecSmrg    }
18335c4bbdfSmrg    else if (stuff->enable == 0) {
18435c4bbdfSmrg        /* delete the interest */
18535c4bbdfSmrg        if (pHead) {
18635c4bbdfSmrg            RREventPtr pNewRREvent = 0;
18735c4bbdfSmrg
18835c4bbdfSmrg            for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
18935c4bbdfSmrg                if (pRREvent->client == client)
19035c4bbdfSmrg                    break;
19135c4bbdfSmrg                pNewRREvent = pRREvent;
19235c4bbdfSmrg            }
19335c4bbdfSmrg            if (pRREvent) {
19435c4bbdfSmrg                FreeResource(pRREvent->clientResource, RRClientType);
19535c4bbdfSmrg                if (pNewRREvent)
19635c4bbdfSmrg                    pNewRREvent->next = pRREvent->next;
19735c4bbdfSmrg                else
19835c4bbdfSmrg                    *pHead = pRREvent->next;
19935c4bbdfSmrg                free(pRREvent);
20035c4bbdfSmrg            }
20135c4bbdfSmrg        }
20205b261ecSmrg    }
20335c4bbdfSmrg    else {
20435c4bbdfSmrg        client->errorValue = stuff->enable;
20535c4bbdfSmrg        return BadValue;
20605b261ecSmrg    }
20705b261ecSmrg    return Success;
20805b261ecSmrg}
20905b261ecSmrg
21035c4bbdfSmrgint (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = {
21135c4bbdfSmrg    ProcRRQueryVersion,         /* 0 */
21205b261ecSmrg/* we skip 1 to make old clients fail pretty immediately */
21335c4bbdfSmrg        NULL,                   /* 1 ProcRandrOldGetScreenInfo */
21405b261ecSmrg/* V1.0 apps share the same set screen config request id */
21535c4bbdfSmrg        ProcRRSetScreenConfig,  /* 2 */
21635c4bbdfSmrg        NULL,                   /* 3 ProcRandrOldScreenChangeSelectInput */
21705b261ecSmrg/* 3 used to be ScreenChangeSelectInput; deprecated */
21835c4bbdfSmrg        ProcRRSelectInput,      /* 4 */
21935c4bbdfSmrg        ProcRRGetScreenInfo,    /* 5 */
22005b261ecSmrg/* V1.2 additions */
22135c4bbdfSmrg        ProcRRGetScreenSizeRange,       /* 6 */
22235c4bbdfSmrg        ProcRRSetScreenSize,    /* 7 */
22335c4bbdfSmrg        ProcRRGetScreenResources,       /* 8 */
22435c4bbdfSmrg        ProcRRGetOutputInfo,    /* 9 */
22535c4bbdfSmrg        ProcRRListOutputProperties,     /* 10 */
22635c4bbdfSmrg        ProcRRQueryOutputProperty,      /* 11 */
22735c4bbdfSmrg        ProcRRConfigureOutputProperty,  /* 12 */
22835c4bbdfSmrg        ProcRRChangeOutputProperty,     /* 13 */
22935c4bbdfSmrg        ProcRRDeleteOutputProperty,     /* 14 */
23035c4bbdfSmrg        ProcRRGetOutputProperty,        /* 15 */
23135c4bbdfSmrg        ProcRRCreateMode,       /* 16 */
23235c4bbdfSmrg        ProcRRDestroyMode,      /* 17 */
23335c4bbdfSmrg        ProcRRAddOutputMode,    /* 18 */
23435c4bbdfSmrg        ProcRRDeleteOutputMode, /* 19 */
23535c4bbdfSmrg        ProcRRGetCrtcInfo,      /* 20 */
23635c4bbdfSmrg        ProcRRSetCrtcConfig,    /* 21 */
23735c4bbdfSmrg        ProcRRGetCrtcGammaSize, /* 22 */
23835c4bbdfSmrg        ProcRRGetCrtcGamma,     /* 23 */
23935c4bbdfSmrg        ProcRRSetCrtcGamma,     /* 24 */
2404642e01fSmrg/* V1.3 additions */
24135c4bbdfSmrg        ProcRRGetScreenResourcesCurrent,        /* 25 */
24235c4bbdfSmrg        ProcRRSetCrtcTransform, /* 26 */
24335c4bbdfSmrg        ProcRRGetCrtcTransform, /* 27 */
24435c4bbdfSmrg        ProcRRGetPanning,       /* 28 */
24535c4bbdfSmrg        ProcRRSetPanning,       /* 29 */
24635c4bbdfSmrg        ProcRRSetOutputPrimary, /* 30 */
24735c4bbdfSmrg        ProcRRGetOutputPrimary, /* 31 */
24835c4bbdfSmrg/* V1.4 additions */
24935c4bbdfSmrg        ProcRRGetProviders,     /* 32 */
25035c4bbdfSmrg        ProcRRGetProviderInfo,  /* 33 */
25135c4bbdfSmrg        ProcRRSetProviderOffloadSink, /* 34 */
25235c4bbdfSmrg        ProcRRSetProviderOutputSource, /* 35 */
25335c4bbdfSmrg        ProcRRListProviderProperties,    /* 36 */
25435c4bbdfSmrg        ProcRRQueryProviderProperty,     /* 37 */
25535c4bbdfSmrg        ProcRRConfigureProviderProperty, /* 38 */
25635c4bbdfSmrg        ProcRRChangeProviderProperty, /* 39 */
25735c4bbdfSmrg        ProcRRDeleteProviderProperty, /* 40 */
25835c4bbdfSmrg        ProcRRGetProviderProperty,    /* 41 */
2591b5d61b8Smrg/* V1.5 additions */
26035c4bbdfSmrg        ProcRRGetMonitors,            /* 42 */
26135c4bbdfSmrg        ProcRRSetMonitor,             /* 43 */
26235c4bbdfSmrg        ProcRRDeleteMonitor,          /* 44 */
2631b5d61b8Smrg/* V1.6 additions */
2641b5d61b8Smrg        ProcRRCreateLease,            /* 45 */
2651b5d61b8Smrg        ProcRRFreeLease,              /* 46 */
26605b261ecSmrg};
267