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