randr: add provider object and provider property support (v6)
This adds the initial provider object and provider property support to the randr dix code. v2: destroy provider in screen close v2.1: fix whitespace v3: update for latest rev of protocol + renumber after 1.4 tearout. v4: fix logic issue, thanks Samsagax on irc v5: keithp's review: fix current_role, fix copyrights, fix master reporting crtc/outputs. v6: port to new randr interface, drop all set role bits for now v7: drop devPrivate in provider, not needed, add BadMatch returns for NULL SetProviderOffloadSink and SetProviderOutputSource, drop the old typedef. Reviewed-by: Keith Packard <keithp@keithp.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
44eae69f1d
commit
66d92afeae
|
@ -432,14 +432,17 @@ xf86platformAddDevice(int index)
|
|||
xf86DeleteScreen(xf86GPUScreens[i]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
scr_index = AddGPUScreen(xf86GPUScreens[i]->ScreenInit, 0, NULL);
|
||||
|
||||
|
||||
dixSetPrivate(&xf86GPUScreens[i]->pScreen->devPrivates,
|
||||
xf86ScreenKey, xf86GPUScreens[i]);
|
||||
|
||||
CreateScratchPixmapsForScreen(xf86GPUScreens[i]->pScreen);
|
||||
|
||||
|
||||
/* attach unbound to 0 protocol screen */
|
||||
AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ librandr_la_SOURCES = \
|
|||
rroutput.c \
|
||||
rrpointer.c \
|
||||
rrproperty.c \
|
||||
rrprovider.c \
|
||||
rrproviderproperty.c \
|
||||
rrscreen.c \
|
||||
rrsdispatch.c \
|
||||
rrtransform.h \
|
||||
|
|
|
@ -94,6 +94,9 @@ RRCloseScreen(ScreenPtr pScreen)
|
|||
for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
|
||||
RROutputDestroy(pScrPriv->outputs[j]);
|
||||
|
||||
if (pScrPriv->provider)
|
||||
RRProviderDestroy(pScrPriv->provider);
|
||||
|
||||
free(pScrPriv->crtcs);
|
||||
free(pScrPriv->outputs);
|
||||
free(pScrPriv);
|
||||
|
@ -175,6 +178,47 @@ SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,
|
|||
/* pad4 */
|
||||
}
|
||||
|
||||
static void
|
||||
SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from,
|
||||
xRRProviderChangeNotifyEvent * to)
|
||||
{
|
||||
to->type = from->type;
|
||||
to->subCode = from->subCode;
|
||||
cpswaps(from->sequenceNumber, to->sequenceNumber);
|
||||
cpswapl(from->timestamp, to->timestamp);
|
||||
cpswapl(from->window, to->window);
|
||||
cpswapl(from->provider, to->provider);
|
||||
}
|
||||
|
||||
static void
|
||||
SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from,
|
||||
xRRProviderPropertyNotifyEvent * to)
|
||||
{
|
||||
to->type = from->type;
|
||||
to->subCode = from->subCode;
|
||||
cpswaps(from->sequenceNumber, to->sequenceNumber);
|
||||
cpswapl(from->window, to->window);
|
||||
cpswapl(from->provider, to->provider);
|
||||
cpswapl(from->atom, to->atom);
|
||||
cpswapl(from->timestamp, to->timestamp);
|
||||
to->state = from->state;
|
||||
/* pad1 */
|
||||
/* pad2 */
|
||||
/* pad3 */
|
||||
/* pad4 */
|
||||
}
|
||||
|
||||
static void
|
||||
SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,
|
||||
xRRResourceChangeNotifyEvent * to)
|
||||
{
|
||||
to->type = from->type;
|
||||
to->subCode = from->subCode;
|
||||
cpswaps(from->sequenceNumber, to->sequenceNumber);
|
||||
cpswapl(from->timestamp, to->timestamp);
|
||||
cpswapl(from->window, to->window);
|
||||
}
|
||||
|
||||
static void
|
||||
SRRNotifyEvent(xEvent *from, xEvent *to)
|
||||
{
|
||||
|
@ -191,6 +235,17 @@ SRRNotifyEvent(xEvent *from, xEvent *to)
|
|||
SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from,
|
||||
(xRROutputPropertyNotifyEvent *) to);
|
||||
break;
|
||||
case RRNotify_ProviderChange:
|
||||
SRRProviderChangeNotifyEvent((xRRProviderChangeNotifyEvent *) from,
|
||||
(xRRProviderChangeNotifyEvent *) to);
|
||||
break;
|
||||
case RRNotify_ProviderProperty:
|
||||
SRRProviderPropertyNotifyEvent((xRRProviderPropertyNotifyEvent *) from,
|
||||
(xRRProviderPropertyNotifyEvent *) to);
|
||||
break;
|
||||
case RRNotify_ResourceChange:
|
||||
SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from,
|
||||
(xRRResourceChangeNotifyEvent *) to);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -356,7 +411,7 @@ RRExtensionInit(void)
|
|||
RRModeInitErrorValue();
|
||||
RRCrtcInitErrorValue();
|
||||
RROutputInitErrorValue();
|
||||
|
||||
RRProviderInitErrorValue();
|
||||
#ifdef PANORAMIX
|
||||
RRXineramaExtensionInit();
|
||||
#endif
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
typedef XID RRMode;
|
||||
typedef XID RROutput;
|
||||
typedef XID RRCrtc;
|
||||
typedef XID RRProvider;
|
||||
|
||||
extern _X_EXPORT int RREventBase, RRErrorBase;
|
||||
|
||||
|
@ -78,6 +79,7 @@ typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr;
|
|||
typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr;
|
||||
typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
|
||||
typedef struct _rrOutput RROutputRec, *RROutputPtr;
|
||||
typedef struct _rrProvider RRProviderRec, *RRProviderPtr;
|
||||
|
||||
struct _rrMode {
|
||||
int refcnt;
|
||||
|
@ -152,6 +154,16 @@ struct _rrOutput {
|
|||
void *devPrivate;
|
||||
};
|
||||
|
||||
struct _rrProvider {
|
||||
RRProvider id;
|
||||
ScreenPtr pScreen;
|
||||
uint32_t capabilities;
|
||||
char *name;
|
||||
int nameLength;
|
||||
RRPropertyPtr properties;
|
||||
Bool pendingProperties;
|
||||
};
|
||||
|
||||
#if RANDR_12_INTERFACE
|
||||
typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen,
|
||||
CARD16 width,
|
||||
|
@ -197,6 +209,13 @@ typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn,
|
|||
|
||||
#endif /* RANDR_13_INTERFACE */
|
||||
|
||||
typedef Bool (*RRProviderGetPropertyProcPtr) (ScreenPtr pScreen,
|
||||
RRProviderPtr provider, Atom property);
|
||||
typedef Bool (*RRProviderSetPropertyProcPtr) (ScreenPtr pScreen,
|
||||
RRProviderPtr provider,
|
||||
Atom property,
|
||||
RRPropertyValuePtr value);
|
||||
|
||||
typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation * rotations);
|
||||
typedef Bool (*RRCloseScreenProcPtr) (ScreenPtr pscreen);
|
||||
|
||||
|
@ -247,6 +266,8 @@ typedef struct _rrScrPriv {
|
|||
RRSetPanningProcPtr rrSetPanning;
|
||||
#endif
|
||||
|
||||
RRProviderGetPropertyProcPtr rrProviderGetProperty;
|
||||
RRProviderSetPropertyProcPtr rrProviderSetProperty;
|
||||
/*
|
||||
* Private part of the structure; not considered part of the ABI
|
||||
*/
|
||||
|
@ -288,6 +309,8 @@ typedef struct _rrScrPriv {
|
|||
int size;
|
||||
#endif
|
||||
Bool discontiguous;
|
||||
|
||||
RRProviderPtr provider;
|
||||
} rrScrPrivRec, *rrScrPrivPtr;
|
||||
|
||||
extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
|
||||
|
@ -331,7 +354,7 @@ extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for ev
|
|||
extern _X_EXPORT DevPrivateKeyRec RRClientPrivateKeyRec;
|
||||
|
||||
#define RRClientPrivateKey (&RRClientPrivateKeyRec)
|
||||
extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
|
||||
extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType, RRProviderType;
|
||||
|
||||
#define VERIFY_RR_OUTPUT(id, ptr, a)\
|
||||
{\
|
||||
|
@ -363,6 +386,16 @@ extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
|
|||
}\
|
||||
}
|
||||
|
||||
#define VERIFY_RR_PROVIDER(id, ptr, a)\
|
||||
{\
|
||||
int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
|
||||
RRProviderType, client, a);\
|
||||
if (rc != Success) {\
|
||||
client->errorValue = id;\
|
||||
return rc;\
|
||||
}\
|
||||
}
|
||||
|
||||
#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey))
|
||||
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
|
||||
|
||||
|
@ -824,6 +857,69 @@ extern _X_EXPORT int
|
|||
extern _X_EXPORT int
|
||||
ProcRRDeleteOutputProperty(ClientPtr client);
|
||||
|
||||
/* rrprovider.c */
|
||||
extern _X_EXPORT void
|
||||
RRProviderInitErrorValue(void);
|
||||
|
||||
extern _X_EXPORT int
|
||||
ProcRRGetProviders(ClientPtr client);
|
||||
|
||||
extern _X_EXPORT int
|
||||
ProcRRGetProviderInfo(ClientPtr client);
|
||||
|
||||
|
||||
extern _X_EXPORT Bool
|
||||
RRProviderInit(void);
|
||||
|
||||
extern _X_EXPORT RRProviderPtr
|
||||
RRProviderCreate(ScreenPtr pScreen, const char *name,
|
||||
int nameLength);
|
||||
|
||||
extern _X_EXPORT void
|
||||
RRProviderDestroy (RRProviderPtr provider);
|
||||
|
||||
extern _X_EXPORT void
|
||||
RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities);
|
||||
|
||||
extern _X_EXPORT Bool
|
||||
RRProviderLookup(XID id, RRProviderPtr *provider_p);
|
||||
|
||||
/* rrproviderproperty.c */
|
||||
|
||||
extern _X_EXPORT void
|
||||
RRDeleteAllProviderProperties(RRProviderPtr provider);
|
||||
|
||||
extern _X_EXPORT RRPropertyValuePtr
|
||||
RRGetProviderProperty(RRProviderPtr provider, Atom property, Bool pending);
|
||||
|
||||
extern _X_EXPORT RRPropertyPtr
|
||||
RRQueryProviderProperty(RRProviderPtr provider, Atom property);
|
||||
|
||||
extern _X_EXPORT void
|
||||
RRDeleteProviderProperty(RRProviderPtr provider, Atom property);
|
||||
|
||||
extern _X_EXPORT int
|
||||
RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type,
|
||||
int format, int mode, unsigned long len,
|
||||
pointer value, Bool sendevent, Bool pending);
|
||||
|
||||
extern _X_EXPORT int
|
||||
ProcRRGetProviderProperty(ClientPtr client);
|
||||
|
||||
extern _X_EXPORT int
|
||||
ProcRRListProviderProperties(ClientPtr client);
|
||||
|
||||
extern _X_EXPORT int
|
||||
ProcRRQueryProviderProperty(ClientPtr client);
|
||||
|
||||
extern _X_EXPORT int
|
||||
ProcRRConfigureProviderProperty(ClientPtr client);
|
||||
|
||||
extern _X_EXPORT int
|
||||
ProcRRChangeProviderProperty(ClientPtr client);
|
||||
|
||||
extern _X_EXPORT int
|
||||
ProcRRDeleteProviderProperty(ClientPtr client);
|
||||
/* rrxinerama.c */
|
||||
#ifdef XINERAMA
|
||||
extern _X_EXPORT void
|
||||
|
|
|
@ -90,7 +90,8 @@ ProcRRSelectInput(ClientPtr client)
|
|||
if (stuff->enable & (RRScreenChangeNotifyMask |
|
||||
RRCrtcChangeNotifyMask |
|
||||
RROutputChangeNotifyMask |
|
||||
RROutputPropertyNotifyMask)) {
|
||||
RROutputPropertyNotifyMask |
|
||||
RRProviderPropertyNotifyMask)) {
|
||||
ScreenPtr pScreen = pWin->drawable.pScreen;
|
||||
|
||||
rrScrPriv(pScreen);
|
||||
|
@ -241,4 +242,15 @@ int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = {
|
|||
ProcRRSetPanning, /* 29 */
|
||||
ProcRRSetOutputPrimary, /* 30 */
|
||||
ProcRRGetOutputPrimary, /* 31 */
|
||||
/* V1.4 additions */
|
||||
ProcRRGetProviders, /* 32 */
|
||||
ProcRRGetProviderInfo, /* 33 */
|
||||
NULL, /* 34 */
|
||||
NULL, /* 35 */
|
||||
ProcRRListProviderProperties, /* 36 */
|
||||
ProcRRQueryProviderProperty, /* 37 */
|
||||
ProcRRConfigureProviderProperty, /* 38 */
|
||||
ProcRRChangeProviderProperty, /* 39 */
|
||||
ProcRRDeleteProviderProperty, /* 40 */
|
||||
ProcRRGetProviderProperty, /* 41 */
|
||||
};
|
||||
|
|
279
randr/rrprovider.c
Normal file
279
randr/rrprovider.c
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* Copyright © 2012 Red Hat Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
*/
|
||||
|
||||
#include "randrstr.h"
|
||||
#include "swaprep.h"
|
||||
|
||||
RESTYPE RRProviderType;
|
||||
|
||||
/*
|
||||
* Initialize provider type error value
|
||||
*/
|
||||
void
|
||||
RRProviderInitErrorValue(void)
|
||||
{
|
||||
SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider);
|
||||
}
|
||||
|
||||
#define ADD_PROVIDER(_pScreen) do { \
|
||||
pScrPriv = rrGetScrPriv((_pScreen)); \
|
||||
if (pScrPriv->provider) { \
|
||||
providers[count_providers] = pScrPriv->provider->id; \
|
||||
if (client->swapped) \
|
||||
swapl(&providers[count_providers]); \
|
||||
count_providers++; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
int
|
||||
ProcRRGetProviders (ClientPtr client)
|
||||
{
|
||||
REQUEST(xRRGetProvidersReq);
|
||||
xRRGetProvidersReply rep;
|
||||
WindowPtr pWin;
|
||||
ScreenPtr pScreen;
|
||||
rrScrPrivPtr pScrPriv;
|
||||
int rc;
|
||||
CARD8 *extra;
|
||||
unsigned int extraLen;
|
||||
RRProvider *providers;
|
||||
int total_providers = 0, count_providers = 0;
|
||||
|
||||
REQUEST_SIZE_MATCH(xRRGetProvidersReq);
|
||||
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
||||
pScreen = pWin->drawable.pScreen;
|
||||
|
||||
pScrPriv = rrGetScrPriv(pScreen);
|
||||
|
||||
if (pScrPriv->provider)
|
||||
total_providers++;
|
||||
|
||||
pScrPriv = rrGetScrPriv(pScreen);
|
||||
rep.pad = 0;
|
||||
|
||||
if (!pScrPriv)
|
||||
{
|
||||
rep.type = X_Reply;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.length = 0;
|
||||
rep.timestamp = currentTime.milliseconds;
|
||||
rep.nProviders = 0;
|
||||
extra = NULL;
|
||||
extraLen = 0;
|
||||
} else {
|
||||
rep.type = X_Reply;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
|
||||
rep.nProviders = total_providers;
|
||||
rep.length = total_providers;
|
||||
extraLen = rep.length << 2;
|
||||
if (extraLen) {
|
||||
extra = malloc(extraLen);
|
||||
if (!extra)
|
||||
return BadAlloc;
|
||||
} else
|
||||
extra = NULL;
|
||||
|
||||
providers = (RRProvider *)extra;
|
||||
ADD_PROVIDER(pScreen);
|
||||
}
|
||||
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
swapl(&rep.timestamp);
|
||||
swaps(&rep.nProviders);
|
||||
}
|
||||
WriteToClient(client, sizeof(xRRGetProvidersReply), (char *)&rep);
|
||||
if (extraLen)
|
||||
{
|
||||
WriteToClient (client, extraLen, (char *) extra);
|
||||
free(extra);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
ProcRRGetProviderInfo (ClientPtr client)
|
||||
{
|
||||
REQUEST(xRRGetProviderInfoReq);
|
||||
xRRGetProviderInfoReply rep;
|
||||
rrScrPrivPtr pScrPriv;
|
||||
RRProviderPtr provider;
|
||||
ScreenPtr pScreen;
|
||||
CARD8 *extra;
|
||||
unsigned int extraLen = 0;
|
||||
RRCrtc *crtcs;
|
||||
RROutput *outputs;
|
||||
int i;
|
||||
char *name;
|
||||
ScreenPtr provscreen;
|
||||
RRProvider *providers;
|
||||
uint32_t *prov_cap;
|
||||
|
||||
REQUEST_SIZE_MATCH(xRRGetProviderInfoReq);
|
||||
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
|
||||
|
||||
pScreen = provider->pScreen;
|
||||
pScrPriv = rrGetScrPriv(pScreen);
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.status = RRSetConfigSuccess;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.length = 0;
|
||||
rep.capabilities = provider->capabilities;
|
||||
rep.nameLength = provider->nameLength;
|
||||
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
|
||||
rep.nCrtcs = pScrPriv->numCrtcs;
|
||||
rep.nOutputs = pScrPriv->numOutputs;
|
||||
|
||||
/* count associated providers */
|
||||
rep.nAssociatedProviders = 0;
|
||||
rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs +
|
||||
(rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength));
|
||||
|
||||
extraLen = rep.length << 2;
|
||||
if (extraLen) {
|
||||
extra = malloc(extraLen);
|
||||
if (!extra)
|
||||
return BadAlloc;
|
||||
}
|
||||
else
|
||||
extra = NULL;
|
||||
|
||||
crtcs = (RRCrtc *)extra;
|
||||
outputs = (RROutput *)(crtcs + rep.nCrtcs);
|
||||
providers = (RRProvider *)(outputs + rep.nOutputs);
|
||||
prov_cap = (unsigned int *)(providers + rep.nAssociatedProviders);
|
||||
name = (char *)(prov_cap + rep.nAssociatedProviders);
|
||||
|
||||
for (i = 0; i < pScrPriv->numCrtcs; i++) {
|
||||
crtcs[i] = pScrPriv->crtcs[i]->id;
|
||||
if (client->swapped)
|
||||
swapl(&crtcs[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < pScrPriv->numOutputs; i++) {
|
||||
outputs[i] = pScrPriv->outputs[i]->id;
|
||||
if (client->swapped)
|
||||
swapl(&outputs[i]);
|
||||
}
|
||||
|
||||
memcpy(name, provider->name, rep.nameLength);
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
swapl(&rep.capabilities);
|
||||
swaps(&rep.nCrtcs);
|
||||
swaps(&rep.nOutputs);
|
||||
swaps(&rep.nameLength);
|
||||
}
|
||||
WriteToClient(client, sizeof(xRRGetProviderInfoReply), (char *)&rep);
|
||||
if (extraLen)
|
||||
{
|
||||
WriteToClient (client, extraLen, (char *) extra);
|
||||
free(extra);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
RRProviderPtr
|
||||
RRProviderCreate(ScreenPtr pScreen, const char *name,
|
||||
int nameLength)
|
||||
{
|
||||
RRProviderPtr provider;
|
||||
rrScrPrivPtr pScrPriv;
|
||||
|
||||
pScrPriv = rrGetScrPriv(pScreen);
|
||||
|
||||
provider = calloc(1, sizeof(RRProviderRec) + nameLength + 1);
|
||||
if (!provider)
|
||||
return NULL;
|
||||
|
||||
provider->id = FakeClientID(0);
|
||||
provider->pScreen = pScreen;
|
||||
provider->name = (char *) (provider + 1);
|
||||
provider->nameLength = nameLength;
|
||||
memcpy(provider->name, name, nameLength);
|
||||
provider->name[nameLength] = '\0';
|
||||
|
||||
if (!AddResource (provider->id, RRProviderType, (pointer) provider))
|
||||
return NULL;
|
||||
pScrPriv->provider = provider;
|
||||
return provider;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy a provider at shutdown
|
||||
*/
|
||||
void
|
||||
RRProviderDestroy (RRProviderPtr provider)
|
||||
{
|
||||
FreeResource (provider->id, 0);
|
||||
}
|
||||
|
||||
void
|
||||
RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities)
|
||||
{
|
||||
provider->capabilities = capabilities;
|
||||
}
|
||||
|
||||
static int
|
||||
RRProviderDestroyResource (pointer value, XID pid)
|
||||
{
|
||||
RRProviderPtr provider = (RRProviderPtr)value;
|
||||
ScreenPtr pScreen = provider->pScreen;
|
||||
|
||||
if (pScreen)
|
||||
{
|
||||
rrScrPriv(pScreen);
|
||||
|
||||
pScrPriv->provider = NULL;
|
||||
}
|
||||
free(provider);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Bool
|
||||
RRProviderInit(void)
|
||||
{
|
||||
RRProviderType = CreateNewResourceType(RRProviderDestroyResource, "Provider");
|
||||
if (!RRProviderType)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern _X_EXPORT Bool
|
||||
RRProviderLookup(XID id, RRProviderPtr *provider_p)
|
||||
{
|
||||
int rc = dixLookupResourceByType((void **)provider_p, id,
|
||||
RRProviderType, NullClient, DixReadAccess);
|
||||
if (rc == Success)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
716
randr/rrproviderproperty.c
Normal file
716
randr/rrproviderproperty.c
Normal file
|
@ -0,0 +1,716 @@
|
|||
/*
|
||||
* 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 "randrstr.h"
|
||||
#include "propertyst.h"
|
||||
#include "swaprep.h"
|
||||
|
||||
static int
|
||||
DeliverPropertyEvent(WindowPtr pWin, void *value)
|
||||
{
|
||||
xRRProviderPropertyNotifyEvent *event = value;
|
||||
RREventPtr *pHead, pRREvent;
|
||||
|
||||
dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
|
||||
RREventType, serverClient, DixReadAccess);
|
||||
if (!pHead)
|
||||
return WT_WALKCHILDREN;
|
||||
|
||||
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
|
||||
if (!(pRREvent->mask & RRProviderPropertyNotifyMask))
|
||||
continue;
|
||||
|
||||
event->window = pRREvent->window->drawable.id;
|
||||
WriteEventsToClient(pRREvent->client, 1, (xEvent *) event);
|
||||
}
|
||||
|
||||
return WT_WALKCHILDREN;
|
||||
}
|
||||
|
||||
static void
|
||||
RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event)
|
||||
{
|
||||
if (!(dispatchException & (DE_RESET | DE_TERMINATE)))
|
||||
WalkTree(pScreen, DeliverPropertyEvent, event);
|
||||
}
|
||||
|
||||
static void
|
||||
RRDestroyProviderProperty(RRPropertyPtr prop)
|
||||
{
|
||||
free(prop->valid_values);
|
||||
free(prop->current.data);
|
||||
free(prop->pending.data);
|
||||
free(prop);
|
||||
}
|
||||
|
||||
static void
|
||||
RRDeleteProperty(RRProviderRec * provider, RRPropertyRec * prop)
|
||||
{
|
||||
xRRProviderPropertyNotifyEvent event;
|
||||
|
||||
event.type = RREventBase + RRNotify;
|
||||
event.subCode = RRNotify_ProviderProperty;
|
||||
event.provider = provider->id;
|
||||
event.state = PropertyDelete;
|
||||
event.atom = prop->propertyName;
|
||||
event.timestamp = currentTime.milliseconds;
|
||||
|
||||
RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
|
||||
|
||||
RRDestroyProviderProperty(prop);
|
||||
}
|
||||
|
||||
void
|
||||
RRDeleteAllProviderProperties(RRProviderPtr provider)
|
||||
{
|
||||
RRPropertyPtr prop, next;
|
||||
|
||||
for (prop = provider->properties; prop; prop = next) {
|
||||
next = prop->next;
|
||||
RRDeleteProperty(provider, prop);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
RRInitProviderPropertyValue(RRPropertyValuePtr property_value)
|
||||
{
|
||||
property_value->type = None;
|
||||
property_value->format = 0;
|
||||
property_value->size = 0;
|
||||
property_value->data = NULL;
|
||||
}
|
||||
|
||||
static RRPropertyPtr
|
||||
RRCreateProviderProperty(Atom property)
|
||||
{
|
||||
RRPropertyPtr prop;
|
||||
|
||||
prop = (RRPropertyPtr) malloc(sizeof(RRPropertyRec));
|
||||
if (!prop)
|
||||
return NULL;
|
||||
prop->next = NULL;
|
||||
prop->propertyName = property;
|
||||
prop->is_pending = FALSE;
|
||||
prop->range = FALSE;
|
||||
prop->immutable = FALSE;
|
||||
prop->num_valid = 0;
|
||||
prop->valid_values = NULL;
|
||||
RRInitProviderPropertyValue(&prop->current);
|
||||
RRInitProviderPropertyValue(&prop->pending);
|
||||
return prop;
|
||||
}
|
||||
|
||||
void
|
||||
RRDeleteProviderProperty(RRProviderPtr provider, Atom property)
|
||||
{
|
||||
RRPropertyRec *prop, **prev;
|
||||
|
||||
for (prev = &provider->properties; (prop = *prev); prev = &(prop->next))
|
||||
if (prop->propertyName == property) {
|
||||
*prev = prop->next;
|
||||
RRDeleteProperty(provider, prop);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type,
|
||||
int format, int mode, unsigned long len,
|
||||
pointer value, Bool sendevent, Bool pending)
|
||||
{
|
||||
RRPropertyPtr prop;
|
||||
xRRProviderPropertyNotifyEvent event;
|
||||
rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen);
|
||||
int size_in_bytes;
|
||||
int total_size;
|
||||
unsigned long total_len;
|
||||
RRPropertyValuePtr prop_value;
|
||||
RRPropertyValueRec new_value;
|
||||
Bool add = FALSE;
|
||||
|
||||
size_in_bytes = format >> 3;
|
||||
|
||||
/* first see if property already exists */
|
||||
prop = RRQueryProviderProperty(provider, property);
|
||||
if (!prop) { /* just add to list */
|
||||
prop = RRCreateProviderProperty(property);
|
||||
if (!prop)
|
||||
return BadAlloc;
|
||||
add = TRUE;
|
||||
mode = PropModeReplace;
|
||||
}
|
||||
if (pending && prop->is_pending)
|
||||
prop_value = &prop->pending;
|
||||
else
|
||||
prop_value = &prop->current;
|
||||
|
||||
/* To append or prepend to a property the request format and type
|
||||
must match those of the already defined property. The
|
||||
existing format and type are irrelevant when using the mode
|
||||
"PropModeReplace" since they will be written over. */
|
||||
|
||||
if ((format != prop_value->format) && (mode != PropModeReplace))
|
||||
return BadMatch;
|
||||
if ((prop_value->type != type) && (mode != PropModeReplace))
|
||||
return BadMatch;
|
||||
new_value = *prop_value;
|
||||
if (mode == PropModeReplace)
|
||||
total_len = len;
|
||||
else
|
||||
total_len = prop_value->size + len;
|
||||
|
||||
if (mode == PropModeReplace || len > 0) {
|
||||
pointer new_data = NULL, old_data = NULL;
|
||||
|
||||
total_size = total_len * size_in_bytes;
|
||||
new_value.data = (pointer) malloc(total_size);
|
||||
if (!new_value.data && total_size) {
|
||||
if (add)
|
||||
RRDestroyProviderProperty(prop);
|
||||
return BadAlloc;
|
||||
}
|
||||
new_value.size = len;
|
||||
new_value.type = type;
|
||||
new_value.format = format;
|
||||
|
||||
switch (mode) {
|
||||
case PropModeReplace:
|
||||
new_data = new_value.data;
|
||||
old_data = NULL;
|
||||
break;
|
||||
case PropModeAppend:
|
||||
new_data = (pointer) (((char *) new_value.data) +
|
||||
(prop_value->size * size_in_bytes));
|
||||
old_data = new_value.data;
|
||||
break;
|
||||
case PropModePrepend:
|
||||
new_data = new_value.data;
|
||||
old_data = (pointer) (((char *) new_value.data) +
|
||||
(prop_value->size * size_in_bytes));
|
||||
break;
|
||||
}
|
||||
if (new_data)
|
||||
memcpy((char *) new_data, (char *) value, len * size_in_bytes);
|
||||
if (old_data)
|
||||
memcpy((char *) old_data, (char *) prop_value->data,
|
||||
prop_value->size * size_in_bytes);
|
||||
|
||||
if (pending && pScrPriv->rrProviderSetProperty &&
|
||||
!pScrPriv->rrProviderSetProperty(provider->pScreen, provider,
|
||||
prop->propertyName, &new_value)) {
|
||||
free(new_value.data);
|
||||
return BadValue;
|
||||
}
|
||||
free(prop_value->data);
|
||||
*prop_value = new_value;
|
||||
}
|
||||
|
||||
else if (len == 0) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
if (add) {
|
||||
prop->next = provider->properties;
|
||||
provider->properties = prop;
|
||||
}
|
||||
|
||||
if (pending && prop->is_pending)
|
||||
provider->pendingProperties = TRUE;
|
||||
|
||||
if (sendevent) {
|
||||
event.type = RREventBase + RRNotify;
|
||||
event.subCode = RRNotify_ProviderProperty;
|
||||
event.provider = provider->id;
|
||||
event.state = PropertyNewValue;
|
||||
event.atom = prop->propertyName;
|
||||
event.timestamp = currentTime.milliseconds;
|
||||
RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
Bool
|
||||
RRPostProviderPendingProperties(RRProviderPtr provider)
|
||||
{
|
||||
RRPropertyValuePtr pending_value;
|
||||
RRPropertyValuePtr current_value;
|
||||
RRPropertyPtr property;
|
||||
Bool ret = TRUE;
|
||||
|
||||
if (!provider->pendingProperties)
|
||||
return TRUE;
|
||||
|
||||
provider->pendingProperties = FALSE;
|
||||
for (property = provider->properties; property; property = property->next) {
|
||||
/* Skip non-pending properties */
|
||||
if (!property->is_pending)
|
||||
continue;
|
||||
|
||||
pending_value = &property->pending;
|
||||
current_value = &property->current;
|
||||
|
||||
/*
|
||||
* If the pending and current values are equal, don't mark it
|
||||
* as changed (which would deliver an event)
|
||||
*/
|
||||
if (pending_value->type == current_value->type &&
|
||||
pending_value->format == current_value->format &&
|
||||
pending_value->size == current_value->size &&
|
||||
!memcmp(pending_value->data, current_value->data,
|
||||
pending_value->size * (pending_value->format / 8)))
|
||||
continue;
|
||||
|
||||
if (RRChangeProviderProperty(provider, property->propertyName,
|
||||
pending_value->type, pending_value->format,
|
||||
PropModeReplace, pending_value->size,
|
||||
pending_value->data, TRUE, FALSE) != Success)
|
||||
ret = FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RRPropertyPtr
|
||||
RRQueryProviderProperty(RRProviderPtr provider, Atom property)
|
||||
{
|
||||
RRPropertyPtr prop;
|
||||
|
||||
for (prop = provider->properties; prop; prop = prop->next)
|
||||
if (prop->propertyName == property)
|
||||
return prop;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RRPropertyValuePtr
|
||||
RRGetProviderProperty(RRProviderPtr provider, Atom property, Bool pending)
|
||||
{
|
||||
RRPropertyPtr prop = RRQueryProviderProperty(provider, property);
|
||||
rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen);
|
||||
|
||||
if (!prop)
|
||||
return NULL;
|
||||
if (pending && prop->is_pending)
|
||||
return &prop->pending;
|
||||
else {
|
||||
#if RANDR_13_INTERFACE
|
||||
/* If we can, try to update the property value first */
|
||||
if (pScrPriv->rrProviderGetProperty)
|
||||
pScrPriv->rrProviderGetProperty(provider->pScreen, provider,
|
||||
prop->propertyName);
|
||||
#endif
|
||||
return &prop->current;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
RRConfigureProviderProperty(RRProviderPtr provider, Atom property,
|
||||
Bool pending, Bool range, Bool immutable,
|
||||
int num_values, INT32 *values)
|
||||
{
|
||||
RRPropertyPtr prop = RRQueryProviderProperty(provider, property);
|
||||
Bool add = FALSE;
|
||||
INT32 *new_values;
|
||||
|
||||
if (!prop) {
|
||||
prop = RRCreateProviderProperty(property);
|
||||
if (!prop)
|
||||
return BadAlloc;
|
||||
add = TRUE;
|
||||
}
|
||||
else if (prop->immutable && !immutable)
|
||||
return BadAccess;
|
||||
|
||||
/*
|
||||
* ranges must have even number of values
|
||||
*/
|
||||
if (range && (num_values & 1))
|
||||
return BadMatch;
|
||||
|
||||
new_values = malloc(num_values * sizeof(INT32));
|
||||
if (!new_values && num_values)
|
||||
return BadAlloc;
|
||||
if (num_values)
|
||||
memcpy(new_values, values, num_values * sizeof(INT32));
|
||||
|
||||
/*
|
||||
* Property moving from pending to non-pending
|
||||
* loses any pending values
|
||||
*/
|
||||
if (prop->is_pending && !pending) {
|
||||
free(prop->pending.data);
|
||||
RRInitProviderPropertyValue(&prop->pending);
|
||||
}
|
||||
|
||||
prop->is_pending = pending;
|
||||
prop->range = range;
|
||||
prop->immutable = immutable;
|
||||
prop->num_valid = num_values;
|
||||
free(prop->valid_values);
|
||||
prop->valid_values = new_values;
|
||||
|
||||
if (add) {
|
||||
prop->next = provider->properties;
|
||||
provider->properties = prop;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
ProcRRListProviderProperties(ClientPtr client)
|
||||
{
|
||||
REQUEST(xRRListProviderPropertiesReq);
|
||||
Atom *pAtoms = NULL, *temppAtoms;
|
||||
xRRListProviderPropertiesReply rep;
|
||||
int numProps = 0;
|
||||
RRProviderPtr provider;
|
||||
RRPropertyPtr prop;
|
||||
|
||||
REQUEST_SIZE_MATCH(xRRListProviderPropertiesReq);
|
||||
|
||||
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
|
||||
|
||||
for (prop = provider->properties; prop; prop = prop->next)
|
||||
numProps++;
|
||||
if (numProps)
|
||||
if (!(pAtoms = (Atom *) malloc(numProps * sizeof(Atom))))
|
||||
return BadAlloc;
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.length = bytes_to_int32(numProps * sizeof(Atom));
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.nAtoms = numProps;
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
swaps(&rep.nAtoms);
|
||||
}
|
||||
temppAtoms = pAtoms;
|
||||
for (prop = provider->properties; prop; prop = prop->next)
|
||||
*temppAtoms++ = prop->propertyName;
|
||||
|
||||
WriteToClient(client, sizeof(xRRListProviderPropertiesReply), (char *) &rep);
|
||||
if (numProps) {
|
||||
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
|
||||
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
|
||||
free(pAtoms);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
ProcRRQueryProviderProperty(ClientPtr client)
|
||||
{
|
||||
REQUEST(xRRQueryProviderPropertyReq);
|
||||
xRRQueryProviderPropertyReply rep;
|
||||
RRProviderPtr provider;
|
||||
RRPropertyPtr prop;
|
||||
char *extra = NULL;
|
||||
|
||||
REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq);
|
||||
|
||||
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
|
||||
|
||||
prop = RRQueryProviderProperty(provider, stuff->property);
|
||||
if (!prop)
|
||||
return BadName;
|
||||
|
||||
if (prop->num_valid) {
|
||||
extra = malloc(prop->num_valid * sizeof(INT32));
|
||||
if (!extra)
|
||||
return BadAlloc;
|
||||
}
|
||||
rep.type = X_Reply;
|
||||
rep.length = prop->num_valid;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.pending = prop->is_pending;
|
||||
rep.range = prop->range;
|
||||
rep.immutable = prop->immutable;
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
}
|
||||
WriteToClient(client, sizeof(xRRQueryProviderPropertyReply), (char *) &rep);
|
||||
if (prop->num_valid) {
|
||||
memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32));
|
||||
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
|
||||
WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32),
|
||||
extra);
|
||||
free(extra);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
ProcRRConfigureProviderProperty(ClientPtr client)
|
||||
{
|
||||
REQUEST(xRRConfigureProviderPropertyReq);
|
||||
RRProviderPtr provider;
|
||||
int num_valid;
|
||||
|
||||
REQUEST_AT_LEAST_SIZE(xRRConfigureProviderPropertyReq);
|
||||
|
||||
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
|
||||
|
||||
num_valid =
|
||||
stuff->length - bytes_to_int32(sizeof(xRRConfigureProviderPropertyReq));
|
||||
return RRConfigureProviderProperty(provider, stuff->property, stuff->pending,
|
||||
stuff->range, FALSE, num_valid,
|
||||
(INT32 *) (stuff + 1));
|
||||
}
|
||||
|
||||
int
|
||||
ProcRRChangeProviderProperty(ClientPtr client)
|
||||
{
|
||||
REQUEST(xRRChangeProviderPropertyReq);
|
||||
RRProviderPtr provider;
|
||||
char format, mode;
|
||||
unsigned long len;
|
||||
int sizeInBytes;
|
||||
int totalSize;
|
||||
int err;
|
||||
|
||||
REQUEST_AT_LEAST_SIZE(xRRChangeProviderPropertyReq);
|
||||
UpdateCurrentTime();
|
||||
format = stuff->format;
|
||||
mode = stuff->mode;
|
||||
if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
|
||||
(mode != PropModePrepend)) {
|
||||
client->errorValue = mode;
|
||||
return BadValue;
|
||||
}
|
||||
if ((format != 8) && (format != 16) && (format != 32)) {
|
||||
client->errorValue = format;
|
||||
return BadValue;
|
||||
}
|
||||
len = stuff->nUnits;
|
||||
if (len > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq))))
|
||||
return BadLength;
|
||||
sizeInBytes = format >> 3;
|
||||
totalSize = len * sizeInBytes;
|
||||
REQUEST_FIXED_SIZE(xRRChangeProviderPropertyReq, totalSize);
|
||||
|
||||
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
|
||||
|
||||
if (!ValidAtom(stuff->property)) {
|
||||
client->errorValue = stuff->property;
|
||||
return BadAtom;
|
||||
}
|
||||
if (!ValidAtom(stuff->type)) {
|
||||
client->errorValue = stuff->type;
|
||||
return BadAtom;
|
||||
}
|
||||
|
||||
err = RRChangeProviderProperty(provider, stuff->property,
|
||||
stuff->type, (int) format,
|
||||
(int) mode, len, (pointer) &stuff[1], TRUE,
|
||||
TRUE);
|
||||
if (err != Success)
|
||||
return err;
|
||||
else
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
ProcRRDeleteProviderProperty(ClientPtr client)
|
||||
{
|
||||
REQUEST(xRRDeleteProviderPropertyReq);
|
||||
RRProviderPtr provider;
|
||||
RRPropertyPtr prop;
|
||||
|
||||
REQUEST_SIZE_MATCH(xRRDeleteProviderPropertyReq);
|
||||
UpdateCurrentTime();
|
||||
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
|
||||
|
||||
if (!ValidAtom(stuff->property)) {
|
||||
client->errorValue = stuff->property;
|
||||
return BadAtom;
|
||||
}
|
||||
|
||||
prop = RRQueryProviderProperty(provider, stuff->property);
|
||||
if (!prop) {
|
||||
client->errorValue = stuff->property;
|
||||
return BadName;
|
||||
}
|
||||
|
||||
if (prop->immutable) {
|
||||
client->errorValue = stuff->property;
|
||||
return BadAccess;
|
||||
}
|
||||
|
||||
RRDeleteProviderProperty(provider, stuff->property);
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
ProcRRGetProviderProperty(ClientPtr client)
|
||||
{
|
||||
REQUEST(xRRGetProviderPropertyReq);
|
||||
RRPropertyPtr prop, *prev;
|
||||
RRPropertyValuePtr prop_value;
|
||||
unsigned long n, len, ind;
|
||||
RRProviderPtr provider;
|
||||
xRRGetProviderPropertyReply reply;
|
||||
char *extra = NULL;
|
||||
|
||||
REQUEST_SIZE_MATCH(xRRGetProviderPropertyReq);
|
||||
if (stuff->delete)
|
||||
UpdateCurrentTime();
|
||||
VERIFY_RR_PROVIDER(stuff->provider, provider,
|
||||
stuff->delete ? DixWriteAccess : DixReadAccess);
|
||||
|
||||
if (!ValidAtom(stuff->property)) {
|
||||
client->errorValue = stuff->property;
|
||||
return BadAtom;
|
||||
}
|
||||
if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) {
|
||||
client->errorValue = stuff->delete;
|
||||
return BadValue;
|
||||
}
|
||||
if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) {
|
||||
client->errorValue = stuff->type;
|
||||
return BadAtom;
|
||||
}
|
||||
|
||||
for (prev = &provider->properties; (prop = *prev); prev = &prop->next)
|
||||
if (prop->propertyName == stuff->property)
|
||||
break;
|
||||
|
||||
reply.type = X_Reply;
|
||||
reply.sequenceNumber = client->sequence;
|
||||
if (!prop) {
|
||||
reply.nItems = 0;
|
||||
reply.length = 0;
|
||||
reply.bytesAfter = 0;
|
||||
reply.propertyType = None;
|
||||
reply.format = 0;
|
||||
if (client->swapped) {
|
||||
swaps(&reply.sequenceNumber);
|
||||
swapl(&reply.length);
|
||||
swapl(&reply.propertyType);
|
||||
swapl(&reply.bytesAfter);
|
||||
swapl(&reply.nItems);
|
||||
}
|
||||
WriteToClient(client, sizeof(xRRGetProviderPropertyReply), &reply);
|
||||
return Success;
|
||||
}
|
||||
|
||||
if (prop->immutable && stuff->delete)
|
||||
return BadAccess;
|
||||
|
||||
prop_value = RRGetProviderProperty(provider, stuff->property, stuff->pending);
|
||||
if (!prop_value)
|
||||
return BadAtom;
|
||||
|
||||
/* If the request type and actual type don't match. Return the
|
||||
property information, but not the data. */
|
||||
|
||||
if (((stuff->type != prop_value->type) && (stuff->type != AnyPropertyType))
|
||||
) {
|
||||
reply.bytesAfter = prop_value->size;
|
||||
reply.format = prop_value->format;
|
||||
reply.length = 0;
|
||||
reply.nItems = 0;
|
||||
reply.propertyType = prop_value->type;
|
||||
if (client->swapped) {
|
||||
swaps(&reply.sequenceNumber);
|
||||
swapl(&reply.length);
|
||||
swapl(&reply.propertyType);
|
||||
swapl(&reply.bytesAfter);
|
||||
swapl(&reply.nItems);
|
||||
}
|
||||
WriteToClient(client, sizeof(xRRGetProviderPropertyReply), &reply);
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return type, format, value to client
|
||||
*/
|
||||
n = (prop_value->format / 8) * prop_value->size; /* size (bytes) of prop */
|
||||
ind = stuff->longOffset << 2;
|
||||
|
||||
/* If longOffset is invalid such that it causes "len" to
|
||||
be negative, it's a value error. */
|
||||
|
||||
if (n < ind) {
|
||||
client->errorValue = stuff->longOffset;
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
len = min(n - ind, 4 * stuff->longLength);
|
||||
|
||||
if (len) {
|
||||
extra = malloc(len);
|
||||
if (!extra)
|
||||
return BadAlloc;
|
||||
}
|
||||
reply.bytesAfter = n - (ind + len);
|
||||
reply.format = prop_value->format;
|
||||
reply.length = bytes_to_int32(len);
|
||||
if (prop_value->format)
|
||||
reply.nItems = len / (prop_value->format / 8);
|
||||
else
|
||||
reply.nItems = 0;
|
||||
reply.propertyType = prop_value->type;
|
||||
|
||||
if (stuff->delete && (reply.bytesAfter == 0)) {
|
||||
xRRProviderPropertyNotifyEvent event;
|
||||
|
||||
event.type = RREventBase + RRNotify;
|
||||
event.subCode = RRNotify_ProviderProperty;
|
||||
event.provider = provider->id;
|
||||
event.state = PropertyDelete;
|
||||
event.atom = prop->propertyName;
|
||||
event.timestamp = currentTime.milliseconds;
|
||||
RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
|
||||
}
|
||||
|
||||
if (client->swapped) {
|
||||
swaps(&reply.sequenceNumber);
|
||||
swapl(&reply.length);
|
||||
swapl(&reply.propertyType);
|
||||
swapl(&reply.bytesAfter);
|
||||
swapl(&reply.nItems);
|
||||
}
|
||||
WriteToClient(client, sizeof(xGenericReply), &reply);
|
||||
if (len) {
|
||||
memcpy(extra, (char *) prop_value->data + ind, len);
|
||||
switch (reply.format) {
|
||||
case 32:
|
||||
client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
|
||||
break;
|
||||
case 16:
|
||||
client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
|
||||
break;
|
||||
default:
|
||||
client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
|
||||
break;
|
||||
}
|
||||
WriteSwappedDataToClient(client, len, extra);
|
||||
free(extra);
|
||||
}
|
||||
|
||||
if (stuff->delete && (reply.bytesAfter == 0)) { /* delete the Property */
|
||||
*prev = prop->next;
|
||||
RRDestroyProviderProperty(prop);
|
||||
}
|
||||
return Success;
|
||||
}
|
Loading…
Reference in New Issue
Block a user