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 REQUEST(xXResQueryVersionReq
);
197 xXResQueryVersionReply rep
= {
199 .sequenceNumber
= client
->sequence
,
201 .server_major
= SERVER_XRES_MAJOR_VERSION
,
202 .server_minor
= SERVER_XRES_MINOR_VERSION
205 REQUEST_SIZE_MATCH(xXResQueryVersionReq
);
207 if (client
->swapped
) {
208 swaps(&rep
.sequenceNumber
);
210 swaps(&rep
.server_major
);
211 swaps(&rep
.server_minor
);
213 WriteToClient(client
, sizeof(xXResQueryVersionReply
), &rep
);
218 ProcXResQueryClients(ClientPtr client
)
220 /* REQUEST(xXResQueryClientsReq); */
221 xXResQueryClientsReply rep
;
222 int *current_clients
;
225 REQUEST_SIZE_MATCH(xXResQueryClientsReq
);
227 current_clients
= malloc(currentMaxClients
* sizeof(int));
230 for (i
= 0; i
< currentMaxClients
; i
++) {
232 current_clients
[num_clients
] = i
;
237 rep
= (xXResQueryClientsReply
) {
239 .sequenceNumber
= client
->sequence
,
240 .length
= bytes_to_int32(num_clients
* sz_xXResClient
),
241 .num_clients
= num_clients
243 if (client
->swapped
) {
244 swaps(&rep
.sequenceNumber
);
246 swapl(&rep
.num_clients
);
248 WriteToClient(client
, sizeof(xXResQueryClientsReply
), &rep
);
253 for (i
= 0; i
< num_clients
; i
++) {
254 scratch
.resource_base
= clients
[current_clients
[i
]]->clientAsMask
;
255 scratch
.resource_mask
= RESOURCE_ID_MASK
;
257 if (client
->swapped
) {
258 swapl(&scratch
.resource_base
);
259 swapl(&scratch
.resource_mask
);
261 WriteToClient(client
, sz_xXResClient
, &scratch
);
265 free(current_clients
);
271 ResFindAllRes(pointer value
, XID id
, RESTYPE type
, pointer cdata
)
273 int *counts
= (int *) cdata
;
275 counts
[(type
& TypeMask
) - 1]++;
279 ProcXResQueryClientResources(ClientPtr client
)
281 REQUEST(xXResQueryClientResourcesReq
);
282 xXResQueryClientResourcesReply rep
;
283 int i
, clientID
, num_types
;
286 REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq
);
288 clientID
= CLIENT_ID(stuff
->xid
);
290 if ((clientID
>= currentMaxClients
) || !clients
[clientID
]) {
291 client
->errorValue
= stuff
->xid
;
295 counts
= calloc(lastResourceType
+ 1, sizeof(int));
297 FindAllClientResources(clients
[clientID
], ResFindAllRes
, counts
);
301 for (i
= 0; i
<= lastResourceType
; i
++) {
306 rep
= (xXResQueryClientResourcesReply
) {
308 .sequenceNumber
= client
->sequence
,
309 .length
= bytes_to_int32(num_types
* sz_xXResType
),
310 .num_types
= num_types
312 if (client
->swapped
) {
313 swaps(&rep
.sequenceNumber
);
315 swapl(&rep
.num_types
);
318 WriteToClient(client
, sizeof(xXResQueryClientResourcesReply
), &rep
);
324 for (i
= 0; i
< lastResourceType
; i
++) {
328 name
= LookupResourceName(i
+ 1);
329 if (strcmp(name
, XREGISTRY_UNKNOWN
))
330 scratch
.resource_type
= MakeAtom(name
, strlen(name
), TRUE
);
334 snprintf(buf
, sizeof(buf
), "Unregistered resource %i", i
+ 1);
335 scratch
.resource_type
= MakeAtom(buf
, strlen(buf
), TRUE
);
338 scratch
.count
= counts
[i
];
340 if (client
->swapped
) {
341 swapl(&scratch
.resource_type
);
342 swapl(&scratch
.count
);
344 WriteToClient(client
, sz_xXResType
, &scratch
);
354 ResGetApproxPixmapBytes(PixmapPtr pix
)
356 unsigned long nPixels
;
359 bytesPerPixel
= pix
->drawable
.bitsPerPixel
>> 3;
360 nPixels
= pix
->drawable
.width
* pix
->drawable
.height
;
362 /* Divide by refcnt as pixmap could be shared between clients,
363 * so total pixmap mem is shared between these.
365 return (nPixels
* bytesPerPixel
) / pix
->refcnt
;
369 ResFindResourcePixmaps(pointer value
, XID id
, RESTYPE type
, pointer cdata
)
371 SizeType sizeFunc
= GetResourceTypeSizeFunc(type
);
372 ResourceSizeRec size
= { 0, 0, 0 };
373 unsigned long *bytes
= cdata
;
375 sizeFunc(value
, id
, &size
);
376 *bytes
+= size
.pixmapRefSize
;
380 ResFindPixmaps(pointer value
, XID id
, pointer cdata
)
382 unsigned long *bytes
= (unsigned long *) cdata
;
383 PixmapPtr pix
= (PixmapPtr
) value
;
385 *bytes
+= ResGetApproxPixmapBytes(pix
);
389 ResFindWindowPixmaps(pointer value
, XID id
, pointer cdata
)
391 unsigned long *bytes
= (unsigned long *) cdata
;
392 WindowPtr pWin
= (WindowPtr
) value
;
394 if (pWin
->backgroundState
== BackgroundPixmap
)
395 *bytes
+= ResGetApproxPixmapBytes(pWin
->background
.pixmap
);
397 if (pWin
->border
.pixmap
!= NULL
&& !pWin
->borderIsPixel
)
398 *bytes
+= ResGetApproxPixmapBytes(pWin
->border
.pixmap
);
402 ResFindGCPixmaps(pointer value
, XID id
, pointer cdata
)
404 unsigned long *bytes
= (unsigned long *) cdata
;
405 GCPtr pGC
= (GCPtr
) value
;
407 if (pGC
->stipple
!= NULL
)
408 *bytes
+= ResGetApproxPixmapBytes(pGC
->stipple
);
410 if (pGC
->tile
.pixmap
!= NULL
&& !pGC
->tileIsPixel
)
411 *bytes
+= ResGetApproxPixmapBytes(pGC
->tile
.pixmap
);
415 ResFindPicturePixmaps(pointer value
, XID id
, pointer cdata
)
418 ResFindResourcePixmaps(value
, id
, PictureType
, cdata
);
423 ResFindCompositeClientWindowPixmaps (pointer value
, XID id
, pointer cdata
)
426 ResFindResourcePixmaps(value
, id
, CompositeClientWindowType
, cdata
);
431 ProcXResQueryClientPixmapBytes(ClientPtr client
)
433 REQUEST(xXResQueryClientPixmapBytesReq
);
434 xXResQueryClientPixmapBytesReply rep
;
438 REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq
);
440 clientID
= CLIENT_ID(stuff
->xid
);
442 if ((clientID
>= currentMaxClients
) || !clients
[clientID
]) {
443 client
->errorValue
= stuff
->xid
;
449 FindClientResourcesByType(clients
[clientID
], RT_PIXMAP
, ResFindPixmaps
,
453 * Make sure win background pixmaps also held to account.
455 FindClientResourcesByType(clients
[clientID
], RT_WINDOW
,
456 ResFindWindowPixmaps
, (pointer
) (&bytes
));
459 * GC Tile & Stipple pixmaps too.
461 FindClientResourcesByType(clients
[clientID
], RT_GC
,
462 ResFindGCPixmaps
, (pointer
) (&bytes
));
465 /* Render extension picture pixmaps. */
466 FindClientResourcesByType(clients
[clientID
], PictureType
,
467 ResFindPicturePixmaps
,
472 /* Composite extension client window pixmaps. */
473 FindClientResourcesByType(clients
[clientID
], CompositeClientWindowType
,
474 ResFindCompositeClientWindowPixmaps
,
478 rep
= (xXResQueryClientPixmapBytesReply
) {
480 .sequenceNumber
= client
->sequence
,
484 .bytes_overflow
= bytes
>> 32
489 if (client
->swapped
) {
490 swaps(&rep
.sequenceNumber
);
493 swapl(&rep
.bytes_overflow
);
495 WriteToClient(client
, sizeof(xXResQueryClientPixmapBytesReply
), &rep
);
500 /** @brief Finds out if a client's information need to be put into the
501 response; marks client having been handled, if that is the case.
503 @param client The client to send information about
504 @param mask The request mask (0 to send everything, otherwise a
505 bitmask of X_XRes*Mask)
506 @param ctx The context record that tells which clients and id types
507 have been already handled
508 @param sendMask Which id type are we now considering. One of X_XRes*Mask.
510 @return Returns TRUE if the client information needs to be on the
511 response, otherwise FALSE.
514 WillConstructMask(ClientPtr client
, CARD32 mask
,
515 ConstructClientIdCtx
*ctx
, int sendMask
)
517 if ((!mask
|| (mask
& sendMask
))
518 && !(ctx
->sentClientMasks
[client
->index
] & sendMask
)) {
519 ctx
->sentClientMasks
[client
->index
] |= sendMask
;
526 /** @brief Constructs a response about a single client, based on a certain
529 @param sendClient Which client wishes to receive this answer. Used for
531 @param client Which client are we considering.
532 @param mask The client id spec mask indicating which information
533 we want about this client.
534 @param ctx The context record containing the constructed response
535 and information on which clients and masks have been
538 @return Return TRUE if everything went OK, otherwise FALSE which indicates
539 a memory allocation problem.
542 ConstructClientIdValue(ClientPtr sendClient
, ClientPtr client
, CARD32 mask
,
543 ConstructClientIdCtx
*ctx
)
545 xXResClientIdValue rep
;
547 rep
.spec
.client
= client
->clientAsMask
;
548 if (client
->swapped
) {
549 swapl (&rep
.spec
.client
);
552 if (WillConstructMask(client
, mask
, ctx
, X_XResClientXIDMask
)) {
553 void *ptr
= AddFragment(&ctx
->response
, sizeof(rep
));
558 rep
.spec
.mask
= X_XResClientXIDMask
;
560 if (sendClient
->swapped
) {
561 swapl (&rep
.spec
.mask
);
562 /* swapl (&rep.length, n); - not required for rep.length = 0 */
565 memcpy(ptr
, &rep
, sizeof(rep
));
567 ctx
->resultBytes
+= sizeof(rep
);
570 if (WillConstructMask(client
, mask
, ctx
, X_XResLocalClientPIDMask
)) {
571 pid_t pid
= GetClientPid(client
);
574 void *ptr
= AddFragment(&ctx
->response
,
575 sizeof(rep
) + sizeof(CARD32
));
576 CARD32
*value
= (void*) ((char*) ptr
+ sizeof(rep
));
582 rep
.spec
.mask
= X_XResLocalClientPIDMask
;
585 if (sendClient
->swapped
) {
586 swapl (&rep
.spec
.mask
);
590 if (sendClient
->swapped
) {
593 memcpy(ptr
, &rep
, sizeof(rep
));
596 ctx
->resultBytes
+= sizeof(rep
) + sizeof(CARD32
);
601 /* memory allocation errors earlier may return with FALSE */
605 /** @brief Constructs a response about all clients, based on a client id specs
607 @param client Which client which we are constructing the response for.
608 @param numSpecs Number of client id specs in specs
609 @param specs Client id specs
611 @return Return Success if everything went OK, otherwise a Bad* (currently
612 BadAlloc or BadValue)
615 ConstructClientIds(ClientPtr client
,
616 int numSpecs
, xXResClientIdSpec
* specs
,
617 ConstructClientIdCtx
*ctx
)
621 for (specIdx
= 0; specIdx
< numSpecs
; ++specIdx
) {
622 if (specs
[specIdx
].client
== 0) {
624 for (c
= 0; c
< currentMaxClients
; ++c
) {
626 if (!ConstructClientIdValue(client
, clients
[c
],
627 specs
[specIdx
].mask
, ctx
)) {
633 int clientID
= CLIENT_ID(specs
[specIdx
].client
);
635 if ((clientID
< currentMaxClients
) && clients
[clientID
]) {
636 if (!ConstructClientIdValue(client
, clients
[clientID
],
637 specs
[specIdx
].mask
, ctx
)) {
644 /* memory allocation errors earlier may return with BadAlloc */
648 /** @brief Response to XResQueryClientIds request introduced in XResProto v1.2
650 @param client Which client which we are constructing the response for.
652 @return Returns the value returned from ConstructClientIds with the same
656 ProcXResQueryClientIds (ClientPtr client
)
658 REQUEST(xXResQueryClientIdsReq
);
660 xXResClientIdSpec
*specs
= (void*) ((char*) stuff
+ sizeof(*stuff
));
662 ConstructClientIdCtx ctx
;
664 InitConstructClientIdCtx(&ctx
);
666 REQUEST_AT_LEAST_SIZE(xXResQueryClientIdsReq
);
667 REQUEST_FIXED_SIZE(xXResQueryClientIdsReq
,
668 stuff
->numSpecs
* sizeof(specs
[0]));
670 rc
= ConstructClientIds(client
, stuff
->numSpecs
, specs
, &ctx
);
673 xXResQueryClientIdsReply rep
= {
675 .sequenceNumber
= client
->sequence
,
676 .length
= bytes_to_int32(ctx
.resultBytes
),
680 assert((ctx
.resultBytes
& 3) == 0);
682 if (client
->swapped
) {
683 swaps (&rep
.sequenceNumber
);
688 WriteToClient(client
, sizeof(rep
), &rep
);
689 WriteFragmentsToClient(client
, &ctx
.response
);
692 DestroyConstructClientIdCtx(&ctx
);
697 /** @brief Swaps xXResResourceIdSpec endianess */
699 SwapXResResourceIdSpec(xXResResourceIdSpec
*spec
)
701 swapl(&spec
->resource
);
705 /** @brief Swaps xXResResourceSizeSpec endianess */
707 SwapXResResourceSizeSpec(xXResResourceSizeSpec
*size
)
709 SwapXResResourceIdSpec(&size
->spec
);
711 swapl(&size
->refCount
);
712 swapl(&size
->useCount
);
715 /** @brief Swaps xXResResourceSizeValue endianess */
717 SwapXResResourceSizeValue(xXResResourceSizeValue
*rep
)
719 SwapXResResourceSizeSpec(&rep
->size
);
720 swapl(&rep
->numCrossReferences
);
723 /** @brief Swaps the response bytes */
725 SwapXResQueryResourceBytes(struct xorg_list
*response
)
727 struct xorg_list
*it
= response
->next
;
730 while (it
!= response
) {
731 xXResResourceSizeValue
*value
= FRAGMENT_DATA(it
);
733 for (c
= 0; c
< value
->numCrossReferences
; ++c
) {
734 xXResResourceSizeSpec
*spec
= FRAGMENT_DATA(it
);
735 SwapXResResourceSizeSpec(spec
);
738 SwapXResResourceSizeValue(value
);
742 /** @brief Adds xXResResourceSizeSpec describing a resource's size into
743 the buffer contained in the context. The resource is considered
746 @see AddResourceSizeValue
748 @param[in] value The X resource object on which to add information
750 @param[in] id The ID of the X resource
751 @param[in] type The type of the X resource
752 @param[in/out] cdata The context object of type ConstructResourceBytesCtx.
753 Void pointer type is used here to satisfy the type
757 AddSubResourceSizeSpec(pointer value
,
762 ConstructResourceBytesCtx
*ctx
= cdata
;
764 if (ctx
->status
== Success
) {
765 xXResResourceSizeSpec
**prevCrossRef
=
766 ht_find(ctx
->visitedSubResources
, &value
);
769 xXResResourceSizeSpec
*crossRef
=
770 AddFragment(&ctx
->response
, sizeof(xXResResourceSizeSpec
));
771 ok
= ok
&& crossRef
!= NULL
;
773 xXResResourceSizeSpec
**p
;
774 p
= ht_add(ctx
->visitedSubResources
, &value
);
782 ctx
->status
= BadAlloc
;
784 SizeType sizeFunc
= GetResourceTypeSizeFunc(type
);
785 ResourceSizeRec size
= { 0, 0, 0 };
786 sizeFunc(value
, id
, &size
);
788 crossRef
->spec
.resource
= id
;
789 crossRef
->spec
.type
= type
;
790 crossRef
->bytes
= size
.resourceSize
;
791 crossRef
->refCount
= size
.refCnt
;
792 crossRef
->useCount
= 1;
794 ++ctx
->sizeValue
->numCrossReferences
;
796 ctx
->resultBytes
+= sizeof(*crossRef
);
799 /* if we have visited the subresource earlier (from current parent
800 resource), just increase its use count by one */
801 ++(*prevCrossRef
)->useCount
;
806 /** @brief Adds xXResResourceSizeValue describing a resource's size into
807 the buffer contained in the context. In addition, the
808 subresources are iterated and added as xXResResourceSizeSpec's
809 by using AddSubResourceSizeSpec
811 @see AddSubResourceSizeSpec
813 @param[in] value The X resource object on which to add information
815 @param[in] id The ID of the X resource
816 @param[in] type The type of the X resource
817 @param[in/out] cdata The context object of type ConstructResourceBytesCtx.
818 Void pointer type is used here to satisfy the type
822 AddResourceSizeValue(pointer ptr
, XID id
, RESTYPE type
, pointer cdata
)
824 ConstructResourceBytesCtx
*ctx
= cdata
;
825 if (ctx
->status
== Success
&&
826 !ht_find(ctx
->visitedResources
, &id
)) {
829 HtGenericHashSetupRec htSetup
= {
830 .keySize
= sizeof(void*)
833 /* it doesn't matter that we don't undo the work done here
834 * immediately. All but ht_init will be undone at the end
835 * of the request and there can happen no failure after
836 * ht_init, so we don't need to clean it up here in any
839 xXResResourceSizeValue
*value
=
840 AddFragment(&ctx
->response
, sizeof(xXResResourceSizeValue
));
844 ok
= ok
&& ht_add(ctx
->visitedResources
, &id
);
846 ht
= ht_create(htSetup
.keySize
,
847 sizeof(xXResResourceSizeSpec
*),
848 ht_generic_hash
, ht_generic_compare
,
854 ctx
->status
= BadAlloc
;
856 SizeType sizeFunc
= GetResourceTypeSizeFunc(type
);
857 ResourceSizeRec size
= { 0, 0, 0 };
859 sizeFunc(ptr
, id
, &size
);
861 value
->size
.spec
.resource
= id
;
862 value
->size
.spec
.type
= type
;
863 value
->size
.bytes
= size
.resourceSize
;
864 value
->size
.refCount
= size
.refCnt
;
865 value
->size
.useCount
= 1;
866 value
->numCrossReferences
= 0;
868 ctx
->sizeValue
= value
;
869 ctx
->visitedSubResources
= ht
;
870 FindSubResources(ptr
, type
, AddSubResourceSizeSpec
, ctx
);
871 ctx
->visitedSubResources
= NULL
;
872 ctx
->sizeValue
= NULL
;
874 ctx
->resultBytes
+= sizeof(*value
);
882 /** @brief A variant of AddResourceSizeValue that passes the resource type
883 through the context object to satisfy the type FindResType
885 @see AddResourceSizeValue
887 @param[in] ptr The resource
888 @param[in] id The resource ID
889 @param[in/out] cdata The context object that contains the resource type
892 AddResourceSizeValueWithResType(pointer ptr
, XID id
, pointer cdata
)
894 ConstructResourceBytesCtx
*ctx
= cdata
;
895 AddResourceSizeValue(ptr
, id
, ctx
->resType
, cdata
);
898 /** @brief Adds the information of a resource into the buffer if it matches
901 @see AddResourceSizeValue
903 @param[in] ptr The resource
904 @param[in] id The resource ID
905 @param[in] type The resource type
906 @param[in/out] cdata The context object as a void pointer to satisfy the
910 AddResourceSizeValueByResource(pointer ptr
, XID id
, RESTYPE type
, pointer cdata
)
912 ConstructResourceBytesCtx
*ctx
= cdata
;
913 xXResResourceIdSpec
*spec
= ctx
->curSpec
;
915 if ((!spec
->type
|| spec
->type
== type
) &&
916 (!spec
->resource
|| spec
->resource
== id
)) {
917 AddResourceSizeValue(ptr
, id
, type
, ctx
);
921 /** @brief Add all resources of the client into the result buffer
922 disregarding all those specifications that specify the
923 resource by its ID. Those are handled by
924 ConstructResourceBytesByResource
926 @see ConstructResourceBytesByResource
928 @param[in] aboutClient Which client is being considered
929 @param[in/out] ctx The context that contains the resource id
930 specifications as well as the result buffer
933 ConstructClientResourceBytes(ClientPtr aboutClient
,
934 ConstructResourceBytesCtx
*ctx
)
937 for (specIdx
= 0; specIdx
< ctx
->numSpecs
; ++specIdx
) {
938 xXResResourceIdSpec
* spec
= ctx
->specs
+ specIdx
;
939 if (spec
->resource
) {
940 /* these specs are handled elsewhere */
941 } else if (spec
->type
) {
942 ctx
->resType
= spec
->type
;
943 FindClientResourcesByType(aboutClient
, spec
->type
,
944 AddResourceSizeValueWithResType
, ctx
);
946 FindAllClientResources(aboutClient
, AddResourceSizeValue
, ctx
);
951 /** @brief Add the sizes of all such resources that can are specified by
952 their ID in the resource id specification. The scan can
953 by limited to a client with the aboutClient parameter
955 @see ConstructResourceBytesByResource
957 @param[in] aboutClient Which client is being considered. This may be None
959 @param[in/out] ctx The context that contains the resource id
960 specifications as well as the result buffer. In
961 addition this function uses the curSpec field to
962 keep a pointer to the current resource id
963 specification in it, which can be used by
964 AddResourceSizeValueByResource .
967 ConstructResourceBytesByResource(XID aboutClient
, ConstructResourceBytesCtx
*ctx
)
970 for (specIdx
= 0; specIdx
< ctx
->numSpecs
; ++specIdx
) {
971 xXResResourceIdSpec
*spec
= ctx
->specs
+ specIdx
;
972 if (spec
->resource
) {
973 int cid
= CLIENT_ID(spec
->resource
);
974 if (cid
< currentMaxClients
&&
975 (aboutClient
== None
|| cid
== aboutClient
)) {
976 ClientPtr client
= clients
[cid
];
979 FindAllClientResources(client
,
980 AddResourceSizeValueByResource
,
988 /** @brief Build the resource size response for the given client
989 (or all if not specified) per the parameters set up
990 in the context object.
992 @param[in] aboutClient Which client to consider or None for all clients
993 @param[in/out] ctx The context object that contains the request as well
994 as the response buffer.
997 ConstructResourceBytes(XID aboutClient
,
998 ConstructResourceBytesCtx
*ctx
)
1001 int clientIdx
= CLIENT_ID(aboutClient
);
1002 ClientPtr client
= NullClient
;
1004 if ((clientIdx
>= currentMaxClients
) || !clients
[clientIdx
]) {
1005 ctx
->sendClient
->errorValue
= aboutClient
;
1009 client
= clients
[clientIdx
];
1011 ConstructClientResourceBytes(client
, ctx
);
1012 ConstructResourceBytesByResource(aboutClient
, ctx
);
1016 ConstructClientResourceBytes(NULL
, ctx
);
1018 for (clientIdx
= 0; clientIdx
< currentMaxClients
; ++clientIdx
) {
1019 ClientPtr client
= clients
[clientIdx
];
1022 ConstructClientResourceBytes(client
, ctx
);
1026 ConstructResourceBytesByResource(None
, ctx
);
1033 /** @brief Implements the XResQueryResourceBytes of XResProto v1.2 */
1035 ProcXResQueryResourceBytes (ClientPtr client
)
1037 REQUEST(xXResQueryResourceBytesReq
);
1040 ConstructResourceBytesCtx ctx
;
1042 REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq
);
1043 REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq
,
1044 stuff
->numSpecs
* sizeof(ctx
.specs
[0]));
1046 if (!InitConstructResourceBytesCtx(&ctx
, client
,
1048 (void*) ((char*) stuff
+
1049 sz_xXResQueryResourceBytesReq
))) {
1053 rc
= ConstructResourceBytes(stuff
->client
, &ctx
);
1055 if (rc
== Success
) {
1056 xXResQueryResourceBytesReply rep
= {
1058 .sequenceNumber
= client
->sequence
,
1059 .length
= bytes_to_int32(ctx
.resultBytes
),
1060 .numSizes
= ctx
.numSizes
1063 if (client
->swapped
) {
1064 swaps (&rep
.sequenceNumber
);
1065 swapl (&rep
.length
);
1066 swapl (&rep
.numSizes
);
1068 SwapXResQueryResourceBytes(&ctx
.response
);
1071 WriteToClient(client
, sizeof(rep
), &rep
);
1072 WriteFragmentsToClient(client
, &ctx
.response
);
1075 DestroyConstructResourceBytesCtx(&ctx
);
1081 ProcResDispatch(ClientPtr client
)
1084 switch (stuff
->data
) {
1085 case X_XResQueryVersion
:
1086 return ProcXResQueryVersion(client
);
1087 case X_XResQueryClients
:
1088 return ProcXResQueryClients(client
);
1089 case X_XResQueryClientResources
:
1090 return ProcXResQueryClientResources(client
);
1091 case X_XResQueryClientPixmapBytes
:
1092 return ProcXResQueryClientPixmapBytes(client
);
1093 case X_XResQueryClientIds
:
1094 return ProcXResQueryClientIds(client
);
1095 case X_XResQueryResourceBytes
:
1096 return ProcXResQueryResourceBytes(client
);
1104 SProcXResQueryVersion(ClientPtr client
)
1106 REQUEST(xXResQueryVersionReq
);
1107 REQUEST_SIZE_MATCH(xXResQueryVersionReq
);
1108 return ProcXResQueryVersion(client
);
1112 SProcXResQueryClientResources(ClientPtr client
)
1114 REQUEST(xXResQueryClientResourcesReq
);
1115 REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq
);
1117 return ProcXResQueryClientResources(client
);
1121 SProcXResQueryClientPixmapBytes(ClientPtr client
)
1123 REQUEST(xXResQueryClientPixmapBytesReq
);
1124 REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq
);
1126 return ProcXResQueryClientPixmapBytes(client
);
1130 SProcXResQueryClientIds (ClientPtr client
)
1132 REQUEST(xXResQueryClientIdsReq
);
1134 REQUEST_AT_LEAST_SIZE (xXResQueryClientIdsReq
);
1135 swapl(&stuff
->numSpecs
);
1136 return ProcXResQueryClientIds(client
);
1139 /** @brief Implements the XResQueryResourceBytes of XResProto v1.2.
1140 This variant byteswaps request contents before issuing the
1141 rest of the work to ProcXResQueryResourceBytes */
1143 SProcXResQueryResourceBytes (ClientPtr client
)
1145 REQUEST(xXResQueryResourceBytesReq
);
1147 xXResResourceIdSpec
*specs
= (void*) ((char*) stuff
+ sizeof(*stuff
));
1149 swapl(&stuff
->numSpecs
);
1150 REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq
);
1151 REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq
,
1152 stuff
->numSpecs
* sizeof(specs
[0]));
1154 for (c
= 0; c
< stuff
->numSpecs
; ++c
) {
1155 SwapXResResourceIdSpec(specs
+ c
);
1158 return ProcXResQueryResourceBytes(client
);
1162 SProcResDispatch (ClientPtr client
)
1165 swaps(&stuff
->length
);
1167 switch (stuff
->data
) {
1168 case X_XResQueryVersion
:
1169 return SProcXResQueryVersion(client
);
1170 case X_XResQueryClients
: /* nothing to swap */
1171 return ProcXResQueryClients(client
);
1172 case X_XResQueryClientResources
:
1173 return SProcXResQueryClientResources(client
);
1174 case X_XResQueryClientPixmapBytes
:
1175 return SProcXResQueryClientPixmapBytes(client
);
1176 case X_XResQueryClientIds
:
1177 return SProcXResQueryClientIds(client
);
1178 case X_XResQueryResourceBytes
:
1179 return SProcXResQueryResourceBytes(client
);
1187 ResExtensionInit(void)
1189 (void) AddExtension(XRES_NAME
, 0, 0,
1190 ProcResDispatch
, SProcResDispatch
,
1191 NULL
, StandardMinorOpcode
);