XRes.c revision 7bf574cc
1/* 2 Copyright (c) 2002 XFree86 Inc 3*/ 4 5#ifdef HAVE_CONFIG_H 6#include <config.h> 7#endif 8#include <stdlib.h> 9#include <X11/Xlibint.h> 10#include <X11/Xutil.h> 11#include <X11/extensions/Xext.h> 12#include <X11/extensions/extutil.h> 13#include <X11/extensions/XResproto.h> 14#include <X11/extensions/XRes.h> 15#include <assert.h> 16#include <limits.h> 17 18static XExtensionInfo _xres_ext_info_data; 19static XExtensionInfo *xres_ext_info = &_xres_ext_info_data; 20static const char *xres_extension_name = XRES_NAME; 21 22#define XResCheckExtension(dpy,i,val) \ 23 XextCheckExtension (dpy, i, xres_extension_name, val) 24 25static XEXT_GENERATE_CLOSE_DISPLAY(close_display, xres_ext_info) 26 27static XExtensionHooks xres_extension_hooks = { 28 NULL, /* create_gc */ 29 NULL, /* copy_gc */ 30 NULL, /* flush_gc */ 31 NULL, /* free_gc */ 32 NULL, /* create_font */ 33 NULL, /* free_font */ 34 close_display, /* close_display */ 35 NULL, /* wire_to_event */ 36 NULL, /* event_to_wire */ 37 NULL, /* error */ 38 NULL, /* error_string */ 39}; 40 41static 42XEXT_GENERATE_FIND_DISPLAY(find_display, xres_ext_info, xres_extension_name, 43 &xres_extension_hooks, 0, NULL) 44 45Bool 46XResQueryExtension(Display *dpy, 47 int *event_base_return, int *error_base_return) 48{ 49 XExtDisplayInfo *info = find_display(dpy); 50 51 if (XextHasExtension(info)) { 52 *event_base_return = info->codes->first_event; 53 *error_base_return = info->codes->first_error; 54 return True; 55 } 56 else { 57 return False; 58 } 59} 60 61Status 62XResQueryVersion(Display *dpy, 63 int *major_version_return, int *minor_version_return) 64{ 65 XExtDisplayInfo *info = find_display(dpy); 66 xXResQueryVersionReply rep; 67 xXResQueryVersionReq *req; 68 69 XResCheckExtension(dpy, info, 0); 70 71 LockDisplay(dpy); 72 GetReq(XResQueryVersion, req); 73 req->reqType = (CARD8) info->codes->major_opcode; 74 req->XResReqType = X_XResQueryVersion; 75 req->client_major = XRES_MAJOR_VERSION; 76 req->client_minor = XRES_MINOR_VERSION; 77 if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) { 78 UnlockDisplay(dpy); 79 SyncHandle(); 80 return 0; 81 } 82 *major_version_return = rep.server_major; 83 *minor_version_return = rep.server_minor; 84 UnlockDisplay(dpy); 85 SyncHandle(); 86 return 1; 87} 88 89Status 90XResQueryClients(Display *dpy, int *num_clients, XResClient **clients) 91{ 92 XExtDisplayInfo *info = find_display(dpy); 93 xXResQueryClientsReq *req; 94 xXResQueryClientsReply rep; 95 int result = 0; 96 97 *num_clients = 0; 98 *clients = NULL; 99 100 XResCheckExtension(dpy, info, 0); 101 102 LockDisplay(dpy); 103 GetReq(XResQueryClients, req); 104 req->reqType = (CARD8) info->codes->major_opcode; 105 req->XResReqType = X_XResQueryClients; 106 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 107 UnlockDisplay(dpy); 108 SyncHandle(); 109 return 0; 110 } 111 112 if (rep.num_clients) { 113 XResClient *clnts; 114 115 if (rep.num_clients < (INT_MAX / sizeof(XResClient))) 116 clnts = Xcalloc(rep.num_clients, sizeof(XResClient)); 117 else 118 clnts = NULL; 119 120 if (clnts != NULL) { 121 for (CARD32 i = 0; i < rep.num_clients; i++) { 122 xXResClient scratch; 123 124 _XRead(dpy, (char *) &scratch, sz_xXResClient); 125 clnts[i].resource_base = scratch.resource_base; 126 clnts[i].resource_mask = scratch.resource_mask; 127 } 128 *clients = clnts; 129 *num_clients = (int) rep.num_clients; 130 result = 1; 131 } 132 else { 133 _XEatDataWords(dpy, rep.length); 134 } 135 } 136 137 UnlockDisplay(dpy); 138 SyncHandle(); 139 return result; 140} 141 142Status 143XResQueryClientResources(Display *dpy, XID xid, 144 int *num_types, XResType **types) 145{ 146 XExtDisplayInfo *info = find_display(dpy); 147 xXResQueryClientResourcesReq *req; 148 xXResQueryClientResourcesReply rep; 149 int result = 0; 150 151 *num_types = 0; 152 *types = NULL; 153 154 XResCheckExtension(dpy, info, 0); 155 156 LockDisplay(dpy); 157 GetReq(XResQueryClientResources, req); 158 req->reqType = (CARD8) info->codes->major_opcode; 159 req->XResReqType = X_XResQueryClientResources; 160 req->xid = (CARD32) xid; 161 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 162 UnlockDisplay(dpy); 163 SyncHandle(); 164 return 0; 165 } 166 167 if (rep.num_types) { 168 XResType *typs; 169 170 if (rep.num_types < (INT_MAX / sizeof(XResType))) 171 typs = Xcalloc(rep.num_types, sizeof(XResType)); 172 else 173 typs = NULL; 174 175 if (typs != NULL) { 176 for (CARD32 i = 0; i < rep.num_types; i++) { 177 xXResType scratch; 178 179 _XRead(dpy, (char *) &scratch, sz_xXResType); 180 typs[i].resource_type = scratch.resource_type; 181 typs[i].count = scratch.count; 182 } 183 *types = typs; 184 *num_types = (int) rep.num_types; 185 result = 1; 186 } 187 else { 188 _XEatDataWords(dpy, rep.length); 189 } 190 } 191 192 UnlockDisplay(dpy); 193 SyncHandle(); 194 return result; 195} 196 197Status 198XResQueryClientPixmapBytes(Display *dpy, XID xid, unsigned long *bytes) 199{ 200 XExtDisplayInfo *info = find_display(dpy); 201 xXResQueryClientPixmapBytesReq *req; 202 xXResQueryClientPixmapBytesReply rep; 203 204 *bytes = 0; 205 206 XResCheckExtension(dpy, info, 0); 207 208 LockDisplay(dpy); 209 GetReq(XResQueryClientPixmapBytes, req); 210 req->reqType = (CARD8) info->codes->major_opcode; 211 req->XResReqType = X_XResQueryClientPixmapBytes; 212 req->xid = (CARD32) xid; 213 if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) { 214 UnlockDisplay(dpy); 215 SyncHandle(); 216 return 0; 217 } 218 219#ifdef LONG64 220 *bytes = (rep.bytes_overflow * 4294967296UL) + rep.bytes; 221#else 222 *bytes = rep.bytes_overflow ? 0xffffffff : rep.bytes; 223#endif 224 225 UnlockDisplay(dpy); 226 SyncHandle(); 227 return 1; 228} 229 230static Bool 231ReadClientValues(Display *dpy, long num_ids, 232 XResClientIdValue *client_ids /* out */) 233{ 234 for (int c = 0; c < num_ids; ++c) { 235 XResClientIdValue *client = client_ids + c; 236 long int value; 237 238 _XRead32(dpy, &value, 4); 239 client->spec.client = (XID) value; 240 _XRead32(dpy, &value, 4); 241 client->spec.mask = (unsigned int) value; 242 _XRead32(dpy, &value, 4); 243 client->length = value; 244 client->value = malloc((unsigned long) client->length); 245 _XRead(dpy, client->value, client->length); 246 } 247 return True; 248} 249 250/* Returns an array of uint32_t values, not an array of long */ 251Status 252XResQueryClientIds( 253 Display *dpy, 254 long num_specs, 255 XResClientIdSpec *client_specs, /* in */ 256 long *num_ids, /* out */ 257 XResClientIdValue **client_ids /* out */ 258) 259{ 260 XExtDisplayInfo *info = find_display(dpy); 261 xXResQueryClientIdsReq *req; 262 xXResQueryClientIdsReply rep; 263 264 *num_ids = 0; 265 266 XResCheckExtension(dpy, info, 0); 267 LockDisplay(dpy); 268 GetReq(XResQueryClientIds, req); 269 req->reqType = (CARD8) info->codes->major_opcode; 270 req->XResReqType = X_XResQueryClientIds; 271 req->length += num_specs * 2; /* 2 longs per client id spec */ 272 req->numSpecs = (CARD32) num_specs; 273 274 for (int c = 0; c < num_specs; ++c) { 275 Data32(dpy, &client_specs[c].client, 4); 276 Data32(dpy, &client_specs[c].mask, 4); 277 } 278 279 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 280 goto error; 281 } 282 283 *client_ids = calloc(rep.numIds, sizeof(**client_ids)); 284 *num_ids = rep.numIds; 285 286 if (!ReadClientValues(dpy, *num_ids, *client_ids)) { 287 goto error; 288 } 289 290 UnlockDisplay(dpy); 291 SyncHandle(); 292 return Success; 293 294 error: 295 XResClientIdsDestroy(*num_ids, *client_ids); 296 *client_ids = NULL; 297 298 UnlockDisplay(dpy); 299 SyncHandle(); 300 return !Success; 301} 302 303void 304XResClientIdsDestroy(long num_ids, XResClientIdValue *client_ids) 305{ 306 for (int c = 0; c < num_ids; ++c) { 307 free(client_ids[c].value); 308 } 309 free(client_ids); 310} 311 312XResClientIdType 313XResGetClientIdType(XResClientIdValue *value) 314{ 315 XResClientIdType idType = 0; 316 Bool found = False; 317 318 for (unsigned int bit = 0; bit < XRES_CLIENT_ID_NR; ++bit) { 319 if (value->spec.mask & (1 << bit)) { 320 assert(!found); 321 found = True; 322 idType = bit; 323 } 324 } 325 326 assert(found); 327 328 return idType; 329} 330 331pid_t 332XResGetClientPid(XResClientIdValue *value) 333{ 334 if (value->spec.mask & XRES_CLIENT_ID_PID_MASK && value->length >= 4) { 335 return (pid_t) * (CARD32 *) value->value; 336 } 337 else { 338 return (pid_t) - 1; 339 } 340} 341 342static Status 343ReadResourceSizeSpec(Display *dpy, XResResourceSizeSpec *size) 344{ 345 long int value; 346 347 _XRead32(dpy, &value, 4); 348 size->spec.resource = (XID) value; 349 _XRead32(dpy, &value, 4); 350 size->spec.type = (Atom) value; 351 _XRead32(dpy, &value, 4); 352 size->bytes = value; 353 _XRead32(dpy, &value, 4); 354 size->ref_count = value; 355 _XRead32(dpy, &value, 4); 356 size->use_count = value; 357 return 0; 358} 359 360static Status 361ReadResourceSizeValues(Display *dpy, 362 long num_sizes, XResResourceSizeValue *sizes) 363{ 364 for (int c = 0; c < num_sizes; ++c) { 365 long int num; 366 367 ReadResourceSizeSpec(dpy, &sizes[c].size); 368 _XRead32(dpy, &num, 4); 369 sizes[c].num_cross_references = num; 370 sizes[c].cross_references = 371 num ? calloc(num, sizeof(*sizes[c].cross_references)) : NULL; 372 for (int d = 0; d < num; ++d) { 373 ReadResourceSizeSpec(dpy, &sizes[c].cross_references[d]); 374 } 375 } 376 return Success; 377} 378 379Status 380XResQueryResourceBytes( 381 Display *dpy, 382 XID client, 383 long num_specs, 384 XResResourceIdSpec *resource_specs, /* in */ 385 long *num_sizes, /* out */ 386 XResResourceSizeValue **sizes /* out */ 387) 388{ 389 XExtDisplayInfo *info = find_display(dpy); 390 xXResQueryResourceBytesReq *req; 391 xXResQueryResourceBytesReply rep; 392 393 *num_sizes = 0; 394 395 XResCheckExtension(dpy, info, 0); 396 397 LockDisplay(dpy); 398 GetReq(XResQueryResourceBytes, req); 399 req->reqType = (CARD8) info->codes->major_opcode; 400 req->XResReqType = X_XResQueryResourceBytes; 401 req->length += num_specs * 2; /* 2 longs per client id spec */ 402 req->client = (CARD32) client; 403 req->numSpecs = (CARD32) num_specs; 404 405 for (int c = 0; c < num_specs; ++c) { 406 Data32(dpy, &resource_specs[c].resource, 4); 407 Data32(dpy, &resource_specs[c].type, 4); 408 } 409 410 *num_sizes = 0; 411 *sizes = NULL; 412 413 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 414 goto error; 415 } 416 417 *sizes = calloc(rep.numSizes, sizeof(**sizes)); 418 *num_sizes = rep.numSizes; 419 420 if (ReadResourceSizeValues(dpy, *num_sizes, *sizes) != Success) { 421 goto error; 422 } 423 424 UnlockDisplay(dpy); 425 SyncHandle(); 426 return Success; 427 428 error: 429 XResResourceSizeValuesDestroy(*num_sizes, *sizes); 430 431 UnlockDisplay(dpy); 432 SyncHandle(); 433 return !Success; 434} 435 436void 437XResResourceSizeValuesDestroy(long num_sizes, XResResourceSizeValue *sizes) 438{ 439 for (int c = 0; c < num_sizes; ++c) { 440 free(sizes[c].cross_references); 441 } 442 free(sizes); 443} 444