2
Copyright (c) 2002 XFree86 Inc
5
#ifdef HAVE_DIX_CONFIG_H
6
#include <dix-config.h>
12
#include <X11/Xproto.h>
16
#include "dixstruct.h"
17
#include "extnsionst.h"
20
#include <X11/extensions/XResproto.h>
21
#include "pixmapstr.h"
22
#include "windowstr.h"
25
#include "protocol-versions.h"
30
#include "hashtable.h"
31
#include "picturestr.h"
37
/** @brief Holds fragments of responses for ConstructClientIds.
39
* note: there is no consideration for data alignment */
46
#define FRAGMENT_DATA(ptr) ((void*) ((char*) (ptr) + sizeof(FragmentList)))
48
/** @brief Holds structure for the generated response to
49
ProcXResQueryClientIds; used by ConstructClientId* -functions */
53
struct xorg_list response;
54
int sentClientMasks[MAXCLIENTS];
55
} ConstructClientIdCtx;
57
/** @brief Holds the structure for information required to
58
generate the response to XResQueryResourceBytes. In addition
59
to response it contains information on the query as well,
60
as well as some volatile information required by a few
61
functions that cannot take that information directly
62
via a parameter, as they are called via already-existing
63
higher order functions. */
68
struct xorg_list response;
71
xXResResourceIdSpec *specs;
72
HashTable visitedResources;
74
/* Used by AddSubResourceSizeSpec when AddResourceSizeValue is
75
handling crossreferences */
76
HashTable visitedSubResources;
78
/* used when ConstructResourceBytesCtx is passed to
79
AddResourceSizeValue2 via FindClientResourcesByType */
82
/* used when ConstructResourceBytesCtx is passed to
83
AddResourceSizeValueByResource from ConstructResourceBytesByResource */
84
xXResResourceIdSpec *curSpec;
86
/** Used when iterating through a single resource's subresources
88
@see AddSubResourceSizeSpec */
89
xXResResourceSizeValue *sizeValue;
90
} ConstructResourceBytesCtx;
92
/** @brief Allocate and add a sequence of bytes at the end of a fragment list.
93
Call DestroyFragments to release the list.
95
@param frags A pointer to head of an initialized linked list
96
@param bytes Number of bytes to allocate
97
@return Returns a pointer to the allocated non-zeroed region
98
that is to be filled by the caller. On error (out of memory)
99
returns NULL and makes no changes to the list.
102
AddFragment(struct xorg_list *frags, int bytes)
104
FragmentList *f = malloc(sizeof(FragmentList) + bytes);
109
xorg_list_add(&f->l, frags->prev);
110
return (char*) f + sizeof(*f);
114
/** @brief Sends all fragments in the list to the client. Does not
117
@param client The client to send the fragments to
118
@param frags The head of the list of fragments
121
WriteFragmentsToClient(ClientPtr client, struct xorg_list *frags)
124
xorg_list_for_each_entry(it, frags, l) {
125
WriteToClient(client, it->bytes, (char*) it + sizeof(*it));
129
/** @brief Frees a list of fragments. Does not free() root node.
131
@param frags The head of the list of fragments
134
DestroyFragments(struct xorg_list *frags)
136
FragmentList *it, *tmp;
137
xorg_list_for_each_entry_safe(it, tmp, frags, l) {
138
xorg_list_del(&it->l);
143
/** @brief Constructs a context record for ConstructClientId* functions
146
InitConstructClientIdCtx(ConstructClientIdCtx *ctx)
149
ctx->resultBytes = 0;
150
xorg_list_init(&ctx->response);
151
memset(ctx->sentClientMasks, 0, sizeof(ctx->sentClientMasks));
154
/** @brief Destroys a context record, releases all memory (except the storage
157
DestroyConstructClientIdCtx(ConstructClientIdCtx *ctx)
159
DestroyFragments(&ctx->response);
163
InitConstructResourceBytesCtx(ConstructResourceBytesCtx *ctx,
164
ClientPtr sendClient,
166
xXResResourceIdSpec *specs)
168
ctx->sendClient = sendClient;
170
ctx->resultBytes = 0;
171
xorg_list_init(&ctx->response);
172
ctx->status = Success;
173
ctx->numSpecs = numSpecs;
175
ctx->visitedResources = ht_create(sizeof(XID), 0,
176
ht_resourceid_hash, ht_resourceid_compare,
179
if (!ctx->visitedResources) {
187
DestroyConstructResourceBytesCtx(ConstructResourceBytesCtx *ctx)
189
DestroyFragments(&ctx->response);
190
ht_destroy(ctx->visitedResources);
194
ProcXResQueryVersion(ClientPtr client)
196
xXResQueryVersionReply rep = {
198
.sequenceNumber = client->sequence,
200
.server_major = SERVER_XRES_MAJOR_VERSION,
201
.server_minor = SERVER_XRES_MINOR_VERSION
204
REQUEST_SIZE_MATCH(xXResQueryVersionReq);
206
if (client->swapped) {
207
swaps(&rep.sequenceNumber);
209
swaps(&rep.server_major);
210
swaps(&rep.server_minor);
212
WriteToClient(client, sizeof(xXResQueryVersionReply), &rep);
217
ProcXResQueryClients(ClientPtr client)
219
/* REQUEST(xXResQueryClientsReq); */
220
xXResQueryClientsReply rep;
221
int *current_clients;
224
REQUEST_SIZE_MATCH(xXResQueryClientsReq);
226
current_clients = malloc(currentMaxClients * sizeof(int));
229
for (i = 0; i < currentMaxClients; i++) {
231
current_clients[num_clients] = i;
236
rep = (xXResQueryClientsReply) {
238
.sequenceNumber = client->sequence,
239
.length = bytes_to_int32(num_clients * sz_xXResClient),
240
.num_clients = num_clients
242
if (client->swapped) {
243
swaps(&rep.sequenceNumber);
245
swapl(&rep.num_clients);
247
WriteToClient(client, sizeof(xXResQueryClientsReply), &rep);
252
for (i = 0; i < num_clients; i++) {
253
scratch.resource_base = clients[current_clients[i]]->clientAsMask;
254
scratch.resource_mask = RESOURCE_ID_MASK;
256
if (client->swapped) {
257
swapl(&scratch.resource_base);
258
swapl(&scratch.resource_mask);
260
WriteToClient(client, sz_xXResClient, &scratch);
264
free(current_clients);
270
ResFindAllRes(void *value, XID id, RESTYPE type, void *cdata)
272
int *counts = (int *) cdata;
274
counts[(type & TypeMask) - 1]++;
278
ProcXResQueryClientResources(ClientPtr client)
280
REQUEST(xXResQueryClientResourcesReq);
281
xXResQueryClientResourcesReply rep;
282
int i, clientID, num_types;
285
REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq);
287
clientID = CLIENT_ID(stuff->xid);
289
if ((clientID >= currentMaxClients) || !clients[clientID]) {
290
client->errorValue = stuff->xid;
294
counts = calloc(lastResourceType + 1, sizeof(int));
296
FindAllClientResources(clients[clientID], ResFindAllRes, counts);
300
for (i = 0; i <= lastResourceType; i++) {
305
rep = (xXResQueryClientResourcesReply) {
307
.sequenceNumber = client->sequence,
308
.length = bytes_to_int32(num_types * sz_xXResType),
309
.num_types = num_types
311
if (client->swapped) {
312
swaps(&rep.sequenceNumber);
314
swapl(&rep.num_types);
317
WriteToClient(client, sizeof(xXResQueryClientResourcesReply), &rep);
323
for (i = 0; i < lastResourceType; i++) {
327
name = LookupResourceName(i + 1);
328
if (strcmp(name, XREGISTRY_UNKNOWN))
329
scratch.resource_type = MakeAtom(name, strlen(name), TRUE);
333
snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1);
334
scratch.resource_type = MakeAtom(buf, strlen(buf), TRUE);
337
scratch.count = counts[i];
339
if (client->swapped) {
340
swapl(&scratch.resource_type);
341
swapl(&scratch.count);
343
WriteToClient(client, sz_xXResType, &scratch);
353
ResGetApproxPixmapBytes(PixmapPtr pix)
355
unsigned long nPixels;
358
bytesPerPixel = (float)pix->drawable.bitsPerPixel / 8.0;
359
nPixels = pix->drawable.width * pix->drawable.height;
361
/* Divide by refcnt as pixmap could be shared between clients,
362
* so total pixmap mem is shared between these.
364
return (nPixels * bytesPerPixel) / pix->refcnt;
368
ResFindResourcePixmaps(void *value, XID id, RESTYPE type, void *cdata)
370
SizeType sizeFunc = GetResourceTypeSizeFunc(type);
371
ResourceSizeRec size = { 0, 0, 0 };
372
unsigned long *bytes = cdata;
374
sizeFunc(value, id, &size);
375
*bytes += size.pixmapRefSize;
379
ResFindPixmaps(void *value, XID id, void *cdata)
381
unsigned long *bytes = (unsigned long *) cdata;
382
PixmapPtr pix = (PixmapPtr) value;
384
*bytes += ResGetApproxPixmapBytes(pix);
388
ResFindWindowPixmaps(void *value, XID id, void *cdata)
390
unsigned long *bytes = (unsigned long *) cdata;
391
WindowPtr pWin = (WindowPtr) value;
393
if (pWin->backgroundState == BackgroundPixmap)
394
*bytes += ResGetApproxPixmapBytes(pWin->background.pixmap);
396
if (pWin->border.pixmap != NULL && !pWin->borderIsPixel)
397
*bytes += ResGetApproxPixmapBytes(pWin->border.pixmap);
401
ResFindGCPixmaps(void *value, XID id, void *cdata)
403
unsigned long *bytes = (unsigned long *) cdata;
404
GCPtr pGC = (GCPtr) value;
406
if (pGC->stipple != NULL)
407
*bytes += ResGetApproxPixmapBytes(pGC->stipple);
409
if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel)
410
*bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
414
ResFindPicturePixmaps(void *value, XID id, void *cdata)
417
ResFindResourcePixmaps(value, id, PictureType, cdata);
422
ResFindCompositeClientWindowPixmaps (void *value, XID id, void *cdata)
425
ResFindResourcePixmaps(value, id, CompositeClientWindowType, cdata);
430
ProcXResQueryClientPixmapBytes(ClientPtr client)
432
REQUEST(xXResQueryClientPixmapBytesReq);
433
xXResQueryClientPixmapBytesReply rep;
437
REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq);
439
clientID = CLIENT_ID(stuff->xid);
441
if ((clientID >= currentMaxClients) || !clients[clientID]) {
442
client->errorValue = stuff->xid;
448
FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps,
452
* Make sure win background pixmaps also held to account.
454
FindClientResourcesByType(clients[clientID], RT_WINDOW,
455
ResFindWindowPixmaps, (void *) (&bytes));
458
* GC Tile & Stipple pixmaps too.
460
FindClientResourcesByType(clients[clientID], RT_GC,
461
ResFindGCPixmaps, (void *) (&bytes));
464
/* Render extension picture pixmaps. */
465
FindClientResourcesByType(clients[clientID], PictureType,
466
ResFindPicturePixmaps,
471
/* Composite extension client window pixmaps. */
472
FindClientResourcesByType(clients[clientID], CompositeClientWindowType,
473
ResFindCompositeClientWindowPixmaps,
477
rep = (xXResQueryClientPixmapBytesReply) {
479
.sequenceNumber = client->sequence,
483
.bytes_overflow = bytes >> 32
488
if (client->swapped) {
489
swaps(&rep.sequenceNumber);
492
swapl(&rep.bytes_overflow);
494
WriteToClient(client, sizeof(xXResQueryClientPixmapBytesReply), &rep);
499
/** @brief Finds out if a client's information need to be put into the
500
response; marks client having been handled, if that is the case.
502
@param client The client to send information about
503
@param mask The request mask (0 to send everything, otherwise a
504
bitmask of X_XRes*Mask)
505
@param ctx The context record that tells which clients and id types
506
have been already handled
507
@param sendMask Which id type are we now considering. One of X_XRes*Mask.
509
@return Returns TRUE if the client information needs to be on the
510
response, otherwise FALSE.
513
WillConstructMask(ClientPtr client, CARD32 mask,
514
ConstructClientIdCtx *ctx, int sendMask)
516
if ((!mask || (mask & sendMask))
517
&& !(ctx->sentClientMasks[client->index] & sendMask)) {
518
ctx->sentClientMasks[client->index] |= sendMask;
525
/** @brief Constructs a response about a single client, based on a certain
528
@param sendClient Which client wishes to receive this answer. Used for
530
@param client Which client are we considering.
531
@param mask The client id spec mask indicating which information
532
we want about this client.
533
@param ctx The context record containing the constructed response
534
and information on which clients and masks have been
537
@return Return TRUE if everything went OK, otherwise FALSE which indicates
538
a memory allocation problem.
541
ConstructClientIdValue(ClientPtr sendClient, ClientPtr client, CARD32 mask,
542
ConstructClientIdCtx *ctx)
544
xXResClientIdValue rep;
546
rep.spec.client = client->clientAsMask;
547
if (client->swapped) {
548
swapl (&rep.spec.client);
551
if (WillConstructMask(client, mask, ctx, X_XResClientXIDMask)) {
552
void *ptr = AddFragment(&ctx->response, sizeof(rep));
557
rep.spec.mask = X_XResClientXIDMask;
559
if (sendClient->swapped) {
560
swapl (&rep.spec.mask);
561
/* swapl (&rep.length, n); - not required for rep.length = 0 */
564
memcpy(ptr, &rep, sizeof(rep));
566
ctx->resultBytes += sizeof(rep);
569
if (WillConstructMask(client, mask, ctx, X_XResLocalClientPIDMask)) {
570
pid_t pid = GetClientPid(client);
573
void *ptr = AddFragment(&ctx->response,
574
sizeof(rep) + sizeof(CARD32));
575
CARD32 *value = (void*) ((char*) ptr + sizeof(rep));
581
rep.spec.mask = X_XResLocalClientPIDMask;
584
if (sendClient->swapped) {
585
swapl (&rep.spec.mask);
589
if (sendClient->swapped) {
592
memcpy(ptr, &rep, sizeof(rep));
595
ctx->resultBytes += sizeof(rep) + sizeof(CARD32);
600
/* memory allocation errors earlier may return with FALSE */
604
/** @brief Constructs a response about all clients, based on a client id specs
606
@param client Which client which we are constructing the response for.
607
@param numSpecs Number of client id specs in specs
608
@param specs Client id specs
610
@return Return Success if everything went OK, otherwise a Bad* (currently
611
BadAlloc or BadValue)
614
ConstructClientIds(ClientPtr client,
615
int numSpecs, xXResClientIdSpec* specs,
616
ConstructClientIdCtx *ctx)
620
for (specIdx = 0; specIdx < numSpecs; ++specIdx) {
621
if (specs[specIdx].client == 0) {
623
for (c = 0; c < currentMaxClients; ++c) {
625
if (!ConstructClientIdValue(client, clients[c],
626
specs[specIdx].mask, ctx)) {
632
int clientID = CLIENT_ID(specs[specIdx].client);
634
if ((clientID < currentMaxClients) && clients[clientID]) {
635
if (!ConstructClientIdValue(client, clients[clientID],
636
specs[specIdx].mask, ctx)) {
643
/* memory allocation errors earlier may return with BadAlloc */
647
/** @brief Response to XResQueryClientIds request introduced in XResProto v1.2
649
@param client Which client which we are constructing the response for.
651
@return Returns the value returned from ConstructClientIds with the same
655
ProcXResQueryClientIds (ClientPtr client)
657
REQUEST(xXResQueryClientIdsReq);
659
xXResClientIdSpec *specs = (void*) ((char*) stuff + sizeof(*stuff));
661
ConstructClientIdCtx ctx;
663
InitConstructClientIdCtx(&ctx);
665
REQUEST_AT_LEAST_SIZE(xXResQueryClientIdsReq);
666
REQUEST_FIXED_SIZE(xXResQueryClientIdsReq,
667
stuff->numSpecs * sizeof(specs[0]));
669
rc = ConstructClientIds(client, stuff->numSpecs, specs, &ctx);
672
xXResQueryClientIdsReply rep = {
674
.sequenceNumber = client->sequence,
675
.length = bytes_to_int32(ctx.resultBytes),
679
assert((ctx.resultBytes & 3) == 0);
681
if (client->swapped) {
682
swaps (&rep.sequenceNumber);
687
WriteToClient(client, sizeof(rep), &rep);
688
WriteFragmentsToClient(client, &ctx.response);
691
DestroyConstructClientIdCtx(&ctx);
696
/** @brief Swaps xXResResourceIdSpec endianess */
698
SwapXResResourceIdSpec(xXResResourceIdSpec *spec)
700
swapl(&spec->resource);
704
/** @brief Swaps xXResResourceSizeSpec endianess */
706
SwapXResResourceSizeSpec(xXResResourceSizeSpec *size)
708
SwapXResResourceIdSpec(&size->spec);
710
swapl(&size->refCount);
711
swapl(&size->useCount);
714
/** @brief Swaps xXResResourceSizeValue endianess */
716
SwapXResResourceSizeValue(xXResResourceSizeValue *rep)
718
SwapXResResourceSizeSpec(&rep->size);
719
swapl(&rep->numCrossReferences);
722
/** @brief Swaps the response bytes */
724
SwapXResQueryResourceBytes(struct xorg_list *response)
726
struct xorg_list *it = response->next;
729
while (it != response) {
730
xXResResourceSizeValue *value = FRAGMENT_DATA(it);
732
for (c = 0; c < value->numCrossReferences; ++c) {
733
xXResResourceSizeSpec *spec = FRAGMENT_DATA(it);
734
SwapXResResourceSizeSpec(spec);
737
SwapXResResourceSizeValue(value);
741
/** @brief Adds xXResResourceSizeSpec describing a resource's size into
742
the buffer contained in the context. The resource is considered
745
@see AddResourceSizeValue
747
@param[in] value The X resource object on which to add information
749
@param[in] id The ID of the X resource
750
@param[in] type The type of the X resource
751
@param[in/out] cdata The context object of type ConstructResourceBytesCtx.
752
Void pointer type is used here to satisfy the type
756
AddSubResourceSizeSpec(void *value,
761
ConstructResourceBytesCtx *ctx = cdata;
763
if (ctx->status == Success) {
764
xXResResourceSizeSpec **prevCrossRef =
765
ht_find(ctx->visitedSubResources, &value);
768
xXResResourceSizeSpec *crossRef =
769
AddFragment(&ctx->response, sizeof(xXResResourceSizeSpec));
770
ok = ok && crossRef != NULL;
772
xXResResourceSizeSpec **p;
773
p = ht_add(ctx->visitedSubResources, &value);
781
ctx->status = BadAlloc;
783
SizeType sizeFunc = GetResourceTypeSizeFunc(type);
784
ResourceSizeRec size = { 0, 0, 0 };
785
sizeFunc(value, id, &size);
787
crossRef->spec.resource = id;
788
crossRef->spec.type = type;
789
crossRef->bytes = size.resourceSize;
790
crossRef->refCount = size.refCnt;
791
crossRef->useCount = 1;
793
++ctx->sizeValue->numCrossReferences;
795
ctx->resultBytes += sizeof(*crossRef);
798
/* if we have visited the subresource earlier (from current parent
799
resource), just increase its use count by one */
800
++(*prevCrossRef)->useCount;
805
/** @brief Adds xXResResourceSizeValue describing a resource's size into
806
the buffer contained in the context. In addition, the
807
subresources are iterated and added as xXResResourceSizeSpec's
808
by using AddSubResourceSizeSpec
810
@see AddSubResourceSizeSpec
812
@param[in] value The X resource object on which to add information
814
@param[in] id The ID of the X resource
815
@param[in] type The type of the X resource
816
@param[in/out] cdata The context object of type ConstructResourceBytesCtx.
817
Void pointer type is used here to satisfy the type
821
AddResourceSizeValue(void *ptr, XID id, RESTYPE type, void *cdata)
823
ConstructResourceBytesCtx *ctx = cdata;
824
if (ctx->status == Success &&
825
!ht_find(ctx->visitedResources, &id)) {
828
HtGenericHashSetupRec htSetup = {
829
.keySize = sizeof(void*)
832
/* it doesn't matter that we don't undo the work done here
833
* immediately. All but ht_init will be undone at the end
834
* of the request and there can happen no failure after
835
* ht_init, so we don't need to clean it up here in any
838
xXResResourceSizeValue *value =
839
AddFragment(&ctx->response, sizeof(xXResResourceSizeValue));
843
ok = ok && ht_add(ctx->visitedResources, &id);
845
ht = ht_create(htSetup.keySize,
846
sizeof(xXResResourceSizeSpec*),
847
ht_generic_hash, ht_generic_compare,
853
ctx->status = BadAlloc;
855
SizeType sizeFunc = GetResourceTypeSizeFunc(type);
856
ResourceSizeRec size = { 0, 0, 0 };
858
sizeFunc(ptr, id, &size);
860
value->size.spec.resource = id;
861
value->size.spec.type = type;
862
value->size.bytes = size.resourceSize;
863
value->size.refCount = size.refCnt;
864
value->size.useCount = 1;
865
value->numCrossReferences = 0;
867
ctx->sizeValue = value;
868
ctx->visitedSubResources = ht;
869
FindSubResources(ptr, type, AddSubResourceSizeSpec, ctx);
870
ctx->visitedSubResources = NULL;
871
ctx->sizeValue = NULL;
873
ctx->resultBytes += sizeof(*value);
881
/** @brief A variant of AddResourceSizeValue that passes the resource type
882
through the context object to satisfy the type FindResType
884
@see AddResourceSizeValue
886
@param[in] ptr The resource
887
@param[in] id The resource ID
888
@param[in/out] cdata The context object that contains the resource type
891
AddResourceSizeValueWithResType(void *ptr, XID id, void *cdata)
893
ConstructResourceBytesCtx *ctx = cdata;
894
AddResourceSizeValue(ptr, id, ctx->resType, cdata);
897
/** @brief Adds the information of a resource into the buffer if it matches
900
@see AddResourceSizeValue
902
@param[in] ptr The resource
903
@param[in] id The resource ID
904
@param[in] type The resource type
905
@param[in/out] cdata The context object as a void pointer to satisfy the
909
AddResourceSizeValueByResource(void *ptr, XID id, RESTYPE type, void *cdata)
911
ConstructResourceBytesCtx *ctx = cdata;
912
xXResResourceIdSpec *spec = ctx->curSpec;
914
if ((!spec->type || spec->type == type) &&
915
(!spec->resource || spec->resource == id)) {
916
AddResourceSizeValue(ptr, id, type, ctx);
920
/** @brief Add all resources of the client into the result buffer
921
disregarding all those specifications that specify the
922
resource by its ID. Those are handled by
923
ConstructResourceBytesByResource
925
@see ConstructResourceBytesByResource
927
@param[in] aboutClient Which client is being considered
928
@param[in/out] ctx The context that contains the resource id
929
specifications as well as the result buffer
932
ConstructClientResourceBytes(ClientPtr aboutClient,
933
ConstructResourceBytesCtx *ctx)
936
for (specIdx = 0; specIdx < ctx->numSpecs; ++specIdx) {
937
xXResResourceIdSpec* spec = ctx->specs + specIdx;
938
if (spec->resource) {
939
/* these specs are handled elsewhere */
940
} else if (spec->type) {
941
ctx->resType = spec->type;
942
FindClientResourcesByType(aboutClient, spec->type,
943
AddResourceSizeValueWithResType, ctx);
945
FindAllClientResources(aboutClient, AddResourceSizeValue, ctx);
950
/** @brief Add the sizes of all such resources that can are specified by
951
their ID in the resource id specification. The scan can
952
by limited to a client with the aboutClient parameter
954
@see ConstructResourceBytesByResource
956
@param[in] aboutClient Which client is being considered. This may be None
958
@param[in/out] ctx The context that contains the resource id
959
specifications as well as the result buffer. In
960
addition this function uses the curSpec field to
961
keep a pointer to the current resource id
962
specification in it, which can be used by
963
AddResourceSizeValueByResource .
966
ConstructResourceBytesByResource(XID aboutClient, ConstructResourceBytesCtx *ctx)
969
for (specIdx = 0; specIdx < ctx->numSpecs; ++specIdx) {
970
xXResResourceIdSpec *spec = ctx->specs + specIdx;
971
if (spec->resource) {
972
int cid = CLIENT_ID(spec->resource);
973
if (cid < currentMaxClients &&
974
(aboutClient == None || cid == aboutClient)) {
975
ClientPtr client = clients[cid];
978
FindAllClientResources(client,
979
AddResourceSizeValueByResource,
987
/** @brief Build the resource size response for the given client
988
(or all if not specified) per the parameters set up
989
in the context object.
991
@param[in] aboutClient Which client to consider or None for all clients
992
@param[in/out] ctx The context object that contains the request as well
993
as the response buffer.
996
ConstructResourceBytes(XID aboutClient,
997
ConstructResourceBytesCtx *ctx)
1000
int clientIdx = CLIENT_ID(aboutClient);
1001
ClientPtr client = NullClient;
1003
if ((clientIdx >= currentMaxClients) || !clients[clientIdx]) {
1004
ctx->sendClient->errorValue = aboutClient;
1008
client = clients[clientIdx];
1010
ConstructClientResourceBytes(client, ctx);
1011
ConstructResourceBytesByResource(aboutClient, ctx);
1015
ConstructClientResourceBytes(NULL, ctx);
1017
for (clientIdx = 0; clientIdx < currentMaxClients; ++clientIdx) {
1018
ClientPtr client = clients[clientIdx];
1021
ConstructClientResourceBytes(client, ctx);
1025
ConstructResourceBytesByResource(None, ctx);
1032
/** @brief Implements the XResQueryResourceBytes of XResProto v1.2 */
1034
ProcXResQueryResourceBytes (ClientPtr client)
1036
REQUEST(xXResQueryResourceBytesReq);
1039
ConstructResourceBytesCtx ctx;
1041
REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq);
1042
REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq,
1043
stuff->numSpecs * sizeof(ctx.specs[0]));
1045
if (!InitConstructResourceBytesCtx(&ctx, client,
1047
(void*) ((char*) stuff +
1048
sz_xXResQueryResourceBytesReq))) {
1052
rc = ConstructResourceBytes(stuff->client, &ctx);
1054
if (rc == Success) {
1055
xXResQueryResourceBytesReply rep = {
1057
.sequenceNumber = client->sequence,
1058
.length = bytes_to_int32(ctx.resultBytes),
1059
.numSizes = ctx.numSizes
1062
if (client->swapped) {
1063
swaps (&rep.sequenceNumber);
1064
swapl (&rep.length);
1065
swapl (&rep.numSizes);
1067
SwapXResQueryResourceBytes(&ctx.response);
1070
WriteToClient(client, sizeof(rep), &rep);
1071
WriteFragmentsToClient(client, &ctx.response);
1074
DestroyConstructResourceBytesCtx(&ctx);
1080
ProcResDispatch(ClientPtr client)
1083
switch (stuff->data) {
1084
case X_XResQueryVersion:
1085
return ProcXResQueryVersion(client);
1086
case X_XResQueryClients:
1087
return ProcXResQueryClients(client);
1088
case X_XResQueryClientResources:
1089
return ProcXResQueryClientResources(client);
1090
case X_XResQueryClientPixmapBytes:
1091
return ProcXResQueryClientPixmapBytes(client);
1092
case X_XResQueryClientIds:
1093
return ProcXResQueryClientIds(client);
1094
case X_XResQueryResourceBytes:
1095
return ProcXResQueryResourceBytes(client);
1103
SProcXResQueryVersion(ClientPtr client)
1105
REQUEST_SIZE_MATCH(xXResQueryVersionReq);
1106
return ProcXResQueryVersion(client);
1110
SProcXResQueryClientResources(ClientPtr client)
1112
REQUEST(xXResQueryClientResourcesReq);
1113
REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq);
1115
return ProcXResQueryClientResources(client);
1119
SProcXResQueryClientPixmapBytes(ClientPtr client)
1121
REQUEST(xXResQueryClientPixmapBytesReq);
1122
REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq);
1124
return ProcXResQueryClientPixmapBytes(client);
1128
SProcXResQueryClientIds (ClientPtr client)
1130
REQUEST(xXResQueryClientIdsReq);
1132
REQUEST_AT_LEAST_SIZE (xXResQueryClientIdsReq);
1133
swapl(&stuff->numSpecs);
1134
return ProcXResQueryClientIds(client);
1137
/** @brief Implements the XResQueryResourceBytes of XResProto v1.2.
1138
This variant byteswaps request contents before issuing the
1139
rest of the work to ProcXResQueryResourceBytes */
1141
SProcXResQueryResourceBytes (ClientPtr client)
1143
REQUEST(xXResQueryResourceBytesReq);
1145
xXResResourceIdSpec *specs = (void*) ((char*) stuff + sizeof(*stuff));
1147
swapl(&stuff->numSpecs);
1148
REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq);
1149
REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq,
1150
stuff->numSpecs * sizeof(specs[0]));
1152
for (c = 0; c < stuff->numSpecs; ++c) {
1153
SwapXResResourceIdSpec(specs + c);
1156
return ProcXResQueryResourceBytes(client);
1160
SProcResDispatch (ClientPtr client)
1163
swaps(&stuff->length);
1165
switch (stuff->data) {
1166
case X_XResQueryVersion:
1167
return SProcXResQueryVersion(client);
1168
case X_XResQueryClients: /* nothing to swap */
1169
return ProcXResQueryClients(client);
1170
case X_XResQueryClientResources:
1171
return SProcXResQueryClientResources(client);
1172
case X_XResQueryClientPixmapBytes:
1173
return SProcXResQueryClientPixmapBytes(client);
1174
case X_XResQueryClientIds:
1175
return SProcXResQueryClientIds(client);
1176
case X_XResQueryResourceBytes:
1177
return SProcXResQueryResourceBytes(client);
1185
ResExtensionInit(void)
1187
(void) AddExtension(XRES_NAME, 0, 0,
1188
ProcResDispatch, SProcResDispatch,
1189
NULL, StandardMinorOpcode);