280 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			280 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright © 2006 Keith Packard
 | 
						|
 *
 | 
						|
 * 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 the copyright holders not be used in advertising or
 | 
						|
 * publicity pertaining to distribution of the software without specific,
 | 
						|
 * written prior permission.  The copyright holders make no representations
 | 
						|
 * about the suitability of this software for any purpose.  It is provided "as
 | 
						|
 * is" without express or implied warranty.
 | 
						|
 *
 | 
						|
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL THE COPYRIGHT HOLDERS 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.
 | 
						|
 */
 | 
						|
#include <dix-config.h>
 | 
						|
 | 
						|
#include "dix/dix_priv.h"
 | 
						|
#include "randr/randrstr_priv.h"
 | 
						|
#include "randr/rrdispatch_priv.h"
 | 
						|
#include "os/fmt.h"
 | 
						|
 | 
						|
#include "protocol-versions.h"
 | 
						|
 | 
						|
Bool
 | 
						|
RRClientKnowsRates(ClientPtr pClient)
 | 
						|
{
 | 
						|
    rrClientPriv(pClient);
 | 
						|
 | 
						|
    return version_compare(pRRClient->major_version, pRRClient->minor_version,
 | 
						|
                           1, 1) >= 0;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRQueryVersion(ClientPtr client)
 | 
						|
{
 | 
						|
    xRRQueryVersionReply rep = {
 | 
						|
        .type = X_Reply,
 | 
						|
        .sequenceNumber = client->sequence,
 | 
						|
    };
 | 
						|
    REQUEST(xRRQueryVersionReq);
 | 
						|
    rrClientPriv(client);
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xRRQueryVersionReq);
 | 
						|
    pRRClient->major_version = stuff->majorVersion;
 | 
						|
    pRRClient->minor_version = stuff->minorVersion;
 | 
						|
 | 
						|
    if (version_compare(stuff->majorVersion, stuff->minorVersion,
 | 
						|
                        SERVER_RANDR_MAJOR_VERSION,
 | 
						|
                        SERVER_RANDR_MINOR_VERSION) < 0) {
 | 
						|
        rep.majorVersion = stuff->majorVersion;
 | 
						|
        rep.minorVersion = stuff->minorVersion;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        rep.majorVersion = SERVER_RANDR_MAJOR_VERSION;
 | 
						|
        rep.minorVersion = SERVER_RANDR_MINOR_VERSION;
 | 
						|
    }
 | 
						|
 | 
						|
    if (client->swapped) {
 | 
						|
        swaps(&rep.sequenceNumber);
 | 
						|
        swapl(&rep.length);
 | 
						|
        swapl(&rep.majorVersion);
 | 
						|
        swapl(&rep.minorVersion);
 | 
						|
    }
 | 
						|
    WriteToClient(client, sizeof(xRRQueryVersionReply), &rep);
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRSelectInput(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRSelectInputReq);
 | 
						|
    rrClientPriv(client);
 | 
						|
    RRTimesPtr pTimes;
 | 
						|
    WindowPtr pWin;
 | 
						|
    RREventPtr pRREvent, *pHead;
 | 
						|
    XID clientResource;
 | 
						|
    int rc;
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xRRSelectInputReq);
 | 
						|
    rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
 | 
						|
    if (rc != Success)
 | 
						|
        return rc;
 | 
						|
    rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
 | 
						|
                                 RREventType, client, DixWriteAccess);
 | 
						|
    if (rc != Success && rc != BadValue)
 | 
						|
        return rc;
 | 
						|
 | 
						|
    if (stuff->enable & (RRScreenChangeNotifyMask |
 | 
						|
                         RRCrtcChangeNotifyMask |
 | 
						|
                         RROutputChangeNotifyMask |
 | 
						|
                         RROutputPropertyNotifyMask |
 | 
						|
                         RRProviderChangeNotifyMask |
 | 
						|
                         RRProviderPropertyNotifyMask |
 | 
						|
                         RRResourceChangeNotifyMask)) {
 | 
						|
        ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
 | 
						|
        rrScrPriv(pScreen);
 | 
						|
 | 
						|
        pRREvent = NULL;
 | 
						|
        if (pHead) {
 | 
						|
            /* check for existing entry. */
 | 
						|
            for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
 | 
						|
                if (pRREvent->client == client)
 | 
						|
                    break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (!pRREvent) {
 | 
						|
            /* build the entry */
 | 
						|
            pRREvent = (RREventPtr) malloc(sizeof(RREventRec));
 | 
						|
            if (!pRREvent)
 | 
						|
                return BadAlloc;
 | 
						|
            pRREvent->next = 0;
 | 
						|
            pRREvent->client = client;
 | 
						|
            pRREvent->window = pWin;
 | 
						|
            pRREvent->mask = stuff->enable;
 | 
						|
            /*
 | 
						|
             * add a resource that will be deleted when
 | 
						|
             * the client goes away
 | 
						|
             */
 | 
						|
            clientResource = FakeClientID(client->index);
 | 
						|
            pRREvent->clientResource = clientResource;
 | 
						|
            if (!AddResource(clientResource, RRClientType, (void *) pRREvent))
 | 
						|
                return BadAlloc;
 | 
						|
            /*
 | 
						|
             * create a resource to contain a pointer to the list
 | 
						|
             * of clients selecting input.  This must be indirect as
 | 
						|
             * the list may be arbitrarily rearranged which cannot be
 | 
						|
             * done through the resource database.
 | 
						|
             */
 | 
						|
            if (!pHead) {
 | 
						|
                pHead = (RREventPtr *) malloc(sizeof(RREventPtr));
 | 
						|
                if (!pHead ||
 | 
						|
                    !AddResource(pWin->drawable.id, RREventType,
 | 
						|
                                 (void *) pHead)) {
 | 
						|
                    FreeResource(clientResource, X11_RESTYPE_NONE);
 | 
						|
                    return BadAlloc;
 | 
						|
                }
 | 
						|
                *pHead = 0;
 | 
						|
            }
 | 
						|
            pRREvent->next = *pHead;
 | 
						|
            *pHead = pRREvent;
 | 
						|
        }
 | 
						|
        /*
 | 
						|
         * Now see if the client needs an event
 | 
						|
         */
 | 
						|
        if (pScrPriv) {
 | 
						|
            pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
 | 
						|
            if (CompareTimeStamps(pTimes->setTime,
 | 
						|
                                  pScrPriv->lastSetTime) != 0 ||
 | 
						|
                CompareTimeStamps(pTimes->configTime,
 | 
						|
                                  pScrPriv->lastConfigTime) != 0) {
 | 
						|
                if (pRREvent->mask & RRScreenChangeNotifyMask) {
 | 
						|
                    RRDeliverScreenEvent(client, pWin, pScreen);
 | 
						|
                }
 | 
						|
 | 
						|
                if (pRREvent->mask & RRCrtcChangeNotifyMask) {
 | 
						|
                    int i;
 | 
						|
 | 
						|
                    for (i = 0; i < pScrPriv->numCrtcs; i++) {
 | 
						|
                        RRDeliverCrtcEvent(client, pWin, pScrPriv->crtcs[i]);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (pRREvent->mask & RROutputChangeNotifyMask) {
 | 
						|
                    int i;
 | 
						|
 | 
						|
                    for (i = 0; i < pScrPriv->numOutputs; i++) {
 | 
						|
                        RRDeliverOutputEvent(client, pWin,
 | 
						|
                                             pScrPriv->outputs[i]);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                /* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't
 | 
						|
                 * say if there ought to be notifications of changes to output properties
 | 
						|
                 * if those changes occurred before the time RRSelectInput is called.
 | 
						|
                 */
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if (stuff->enable == 0) {
 | 
						|
        /* delete the interest */
 | 
						|
        if (pHead) {
 | 
						|
            RREventPtr pNewRREvent = 0;
 | 
						|
 | 
						|
            for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
 | 
						|
                if (pRREvent->client == client)
 | 
						|
                    break;
 | 
						|
                pNewRREvent = pRREvent;
 | 
						|
            }
 | 
						|
            if (pRREvent) {
 | 
						|
                FreeResource(pRREvent->clientResource, RRClientType);
 | 
						|
                if (pNewRREvent)
 | 
						|
                    pNewRREvent->next = pRREvent->next;
 | 
						|
                else
 | 
						|
                    *pHead = pRREvent->next;
 | 
						|
                free(pRREvent);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        client->errorValue = stuff->enable;
 | 
						|
        return BadValue;
 | 
						|
    }
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRDispatch(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xReq);
 | 
						|
    UpdateCurrentTimeIf();
 | 
						|
 | 
						|
    switch (stuff->data) {
 | 
						|
        case X_RRQueryVersion:              return ProcRRQueryVersion(client);
 | 
						|
        case X_RRSetScreenConfig:           return ProcRRSetScreenConfig(client);
 | 
						|
        case X_RRSelectInput:               return ProcRRSelectInput(client);
 | 
						|
        case X_RRGetScreenInfo:             return ProcRRGetScreenInfo(client);
 | 
						|
 | 
						|
        /* V1.2 additions */
 | 
						|
        case X_RRGetScreenSizeRange:        return ProcRRGetScreenSizeRange(client);
 | 
						|
        case X_RRSetScreenSize:             return ProcRRSetScreenSize(client);
 | 
						|
        case X_RRGetScreenResources:        return ProcRRGetScreenResources(client);
 | 
						|
        case X_RRGetOutputInfo:             return ProcRRGetOutputInfo(client);
 | 
						|
        case X_RRListOutputProperties:      return ProcRRListOutputProperties(client);
 | 
						|
        case X_RRQueryOutputProperty:       return ProcRRQueryOutputProperty(client);
 | 
						|
        case X_RRConfigureOutputProperty:   return ProcRRConfigureOutputProperty(client);
 | 
						|
        case X_RRChangeOutputProperty:      return ProcRRChangeOutputProperty(client);
 | 
						|
        case X_RRDeleteOutputProperty:      return ProcRRDeleteOutputProperty(client);
 | 
						|
        case X_RRGetOutputProperty:         return ProcRRGetOutputProperty(client);
 | 
						|
        case X_RRCreateMode:                return ProcRRCreateMode(client);
 | 
						|
        case X_RRDestroyMode:               return ProcRRDestroyMode(client);
 | 
						|
        case X_RRAddOutputMode:             return ProcRRAddOutputMode(client);
 | 
						|
        case X_RRDeleteOutputMode:          return ProcRRDeleteOutputMode(client);
 | 
						|
        case X_RRGetCrtcInfo:               return ProcRRGetCrtcInfo(client);
 | 
						|
        case X_RRSetCrtcConfig:             return ProcRRSetCrtcConfig(client);
 | 
						|
        case X_RRGetCrtcGammaSize:          return ProcRRGetCrtcGammaSize(client);
 | 
						|
        case X_RRGetCrtcGamma:              return ProcRRGetCrtcGamma(client);
 | 
						|
        case X_RRSetCrtcGamma:              return ProcRRSetCrtcGamma(client);
 | 
						|
 | 
						|
        /* V1.3 additions */
 | 
						|
        case X_RRGetScreenResourcesCurrent: return ProcRRGetScreenResourcesCurrent(client);
 | 
						|
        case X_RRSetCrtcTransform:          return ProcRRSetCrtcTransform(client);
 | 
						|
        case X_RRGetCrtcTransform:          return ProcRRGetCrtcTransform(client);
 | 
						|
        case X_RRGetPanning:                return ProcRRGetPanning(client);
 | 
						|
        case X_RRSetPanning:                return ProcRRSetPanning(client);
 | 
						|
        case X_RRSetOutputPrimary:          return ProcRRSetOutputPrimary(client);
 | 
						|
        case X_RRGetOutputPrimary:          return ProcRRGetOutputPrimary(client);
 | 
						|
 | 
						|
        /* V1.4 additions */
 | 
						|
        case X_RRGetProviders:              return ProcRRGetProviders(client);
 | 
						|
        case X_RRGetProviderInfo:           return ProcRRGetProviderInfo(client);
 | 
						|
        case X_RRSetProviderOffloadSink:    return ProcRRSetProviderOffloadSink(client);
 | 
						|
        case X_RRSetProviderOutputSource:   return ProcRRSetProviderOutputSource(client);
 | 
						|
        case X_RRListProviderProperties:    return ProcRRListProviderProperties(client);
 | 
						|
        case X_RRQueryProviderProperty:     return ProcRRQueryProviderProperty(client);
 | 
						|
        case X_RRConfigureProviderProperty: return ProcRRConfigureProviderProperty(client);
 | 
						|
        case X_RRChangeProviderProperty:    return ProcRRChangeProviderProperty(client);
 | 
						|
        case X_RRDeleteProviderProperty:    return ProcRRDeleteProviderProperty(client);
 | 
						|
        case X_RRGetProviderProperty:       return ProcRRGetProviderProperty(client);
 | 
						|
 | 
						|
        /* V1.5 additions */
 | 
						|
        case X_RRGetMonitors:               return ProcRRGetMonitors(client);
 | 
						|
        case X_RRSetMonitor:                return ProcRRSetMonitor(client);
 | 
						|
        case X_RRDeleteMonitor:             return ProcRRDeleteMonitor(client);
 | 
						|
 | 
						|
        /* V1.6 additions */
 | 
						|
        case X_RRCreateLease:               return ProcRRCreateLease(client);
 | 
						|
        case X_RRFreeLease:                 return ProcRRFreeLease(client);
 | 
						|
    }
 | 
						|
 | 
						|
    return BadRequest;
 | 
						|
}
 |