@@ -12,19 +12,9 @@
#include <X11/extensions/extutil.h>
#include <X11/extensions/XResproto.h>
#include <X11/extensions/XRes.h>
+#include <assert.h>
#include <limits.h>
-#ifndef HAVE__XEATDATAWORDS
-static inline void _XEatDataWords(Display *dpy, unsigned long n)
-{
-# ifndef LONG64
- if (n >= (ULONG_MAX >> 2))
- _XIOError(dpy);
-# endif
- _XEatData (dpy, n << 2);
-}
-#endif
-
static XExtensionInfo _xres_ext_info_data;
static XExtensionInfo *xres_ext_info = &_xres_ext_info_data;
static const char *xres_extension_name = XRES_NAME;
@@ -239,7 +229,7 @@
}
#ifdef LONG64
- *bytes = (rep.bytes_overflow * 4294967295) + rep.bytes;
+ *bytes = (rep.bytes_overflow * 4294967296UL) + rep.bytes;
#else
*bytes = rep.bytes_overflow ? 0xffffffff : rep.bytes;
#endif
@@ -249,3 +239,227 @@
return 1;
}
+static Bool ReadClientValues(
+ Display *dpy,
+ long num_ids,
+ XResClientIdValue *client_ids /* out */
+)
+{
+ int c;
+ for (c = 0; c < num_ids; ++c) {
+ XResClientIdValue* client = client_ids + c;
+ long int value;
+ _XRead32 (dpy, &value, 4);
+ client->spec.client = value;
+ _XRead32 (dpy, &value, 4);
+ client->spec.mask = value;
+ _XRead32 (dpy, &value, 4);
+ client->length = value;
+ client->value = malloc(client->length);
+ _XRead32 (dpy, client->value, client->length);
+ }
+ return True;
+}
+
+Status XResQueryClientIds (
+ Display *dpy,
+ long num_specs,
+ XResClientIdSpec *client_specs, /* in */
+ long *num_ids, /* out */
+ XResClientIdValue **client_ids /* out */
+)
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXResQueryClientIdsReq *req;
+ xXResQueryClientIdsReply rep;
+ int c;
+
+ *num_ids = 0;
+
+ XResCheckExtension (dpy, info, 0);
+ LockDisplay (dpy);
+ GetReq (XResQueryClientIds, req);
+ req->reqType = info->codes->major_opcode;
+ req->XResReqType = X_XResQueryClientIds;
+ req->length += num_specs * 2; /* 2 longs per client id spec */
+ req->numSpecs = num_specs;
+
+ for (c = 0; c < num_specs; ++c) {
+ Data32(dpy, &client_specs[c].client, 4);
+ Data32(dpy, &client_specs[c].mask, 4);
+ }
+
+ if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
+ goto error;
+ }
+
+ *client_ids = calloc(rep.numIds, sizeof(**client_ids));
+ *num_ids = rep.numIds;
+
+ if (!ReadClientValues(dpy, *num_ids, *client_ids)) {
+ goto error;
+ }
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return Success;
+
+ error:
+ XResClientIdsDestroy (*num_ids, *client_ids);
+ *client_ids = NULL;
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return !Success;
+}
+
+void XResClientIdsDestroy (
+ long num_ids,
+ XResClientIdValue *client_ids
+)
+{
+ int c;
+ for (c = 0; c < num_ids; ++c) {
+ free(client_ids[c].value);
+ }
+ free(client_ids);
+}
+
+XResClientIdType XResGetClientIdType(
+ XResClientIdValue* value
+)
+{
+ int bit;
+ XResClientIdType idType = 0;
+ Bool found = False;
+ for (bit = 0; bit < XRES_CLIENT_ID_NR; ++bit) {
+ if (value->spec.mask & (1 << bit)) {
+ assert(!found);
+ found = True;
+ idType = bit;
+ }
+ }
+
+ assert(found);
+
+ return idType;
+}
+
+pid_t XResGetClientPid(
+ XResClientIdValue* value
+)
+{
+ if (value->spec.mask & XRES_CLIENT_ID_PID_MASK && value->length >= 4) {
+ return (pid_t) * (CARD32*) value->value;
+ } else {
+ return (pid_t) -1;
+ }
+}
+
+static Status ReadResourceSizeSpec(
+ Display *dpy,
+ XResResourceSizeSpec *size
+)
+{
+ long int value;
+ _XRead32(dpy, &value, 4);
+ size->spec.resource = value;
+ _XRead32(dpy, &value, 4);
+ size->spec.type = value;
+ _XRead32(dpy, &value, 4);
+ size->bytes = value;
+ _XRead32(dpy, &value, 4);
+ size->ref_count = value;
+ _XRead32(dpy, &value, 4);
+ size->use_count = value;
+ return 0;
+}
+
+static Status ReadResourceSizeValues(
+ Display *dpy,
+ long num_sizes,
+ XResResourceSizeValue *sizes)
+{
+ int c;
+ int d;
+ for (c = 0; c < num_sizes; ++c) {
+ long int num;
+ ReadResourceSizeSpec(dpy, &sizes[c].size);
+ _XRead32(dpy, &num, 4);
+ sizes[c].num_cross_references = num;
+ sizes[c].cross_references = num ? calloc(num, sizeof(*sizes[c].cross_references)) : NULL;
+ for (d = 0; d < num; ++d) {
+ ReadResourceSizeSpec(dpy, &sizes[c].cross_references[d]);
+ }
+ }
+ return Success;
+}
+
+Status XResQueryResourceBytes (
+ Display *dpy,
+ XID client,
+ long num_specs,
+ XResResourceIdSpec *resource_specs, /* in */
+ long *num_sizes, /* out */
+ XResResourceSizeValue **sizes /* out */
+)
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXResQueryResourceBytesReq *req;
+ xXResQueryResourceBytesReply rep;
+ int c;
+
+ *num_sizes = 0;
+
+ XResCheckExtension (dpy, info, 0);
+
+ LockDisplay (dpy);
+ GetReq (XResQueryResourceBytes, req);
+ req->reqType = info->codes->major_opcode;
+ req->XResReqType = X_XResQueryResourceBytes;
+ req->length += num_specs * 2; /* 2 longs per client id spec */
+ req->client = client;
+ req->numSpecs = num_specs;
+
+ for (c = 0; c < num_specs; ++c) {
+ Data32(dpy, &resource_specs[c].resource, 4);
+ Data32(dpy, &resource_specs[c].type, 4);
+ }
+
+ *num_sizes = 0;
+ *sizes = NULL;
+
+ if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
+ goto error;
+ }
+
+ *sizes = calloc(rep.numSizes, sizeof(**sizes));
+ *num_sizes = rep.numSizes;
+
+ if (ReadResourceSizeValues(dpy, *num_sizes, *sizes) != Success) {
+ goto error;
+ }
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return Success;
+
+ error:
+ XResResourceSizeValuesDestroy(*num_sizes, *sizes);
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return !Success;
+}
+
+void XResResourceSizeValuesDestroy (
+ long num_sizes,
+ XResResourceSizeValue *sizes
+)
+{
+ int c;
+ for (c = 0; c < num_sizes; ++c) {
+ free(sizes[c].cross_references);
+ }
+ free(sizes);
+}