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
18 static XExtensionInfo _xres_ext_info_data;
19 static XExtensionInfo *xres_ext_info = &_xres_ext_info_data;
20 static const char *xres_extension_name = XRES_NAME;
21
22 #define XResCheckExtension(dpy,i,val) \
23 XextCheckExtension (dpy, i, xres_extension_name, val)
24
25 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xres_ext_info)
26
27 static 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
41 static XEXT_GENERATE_FIND_DISPLAY (find_display, xres_ext_info,
42 xres_extension_name,
43 &xres_extension_hooks,
44 0, NULL)
45
XResQueryExtension(Display * dpy,int * event_base_return,int * error_base_return)46 Bool 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
XResQueryVersion(Display * dpy,int * major_version_return,int * minor_version_return)63 Status 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
XResQueryClients(Display * dpy,int * num_clients,XResClient ** clients)94 Status 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
XResQueryClientResources(Display * dpy,XID xid,int * num_types,XResType ** types)149 Status 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
XResQueryClientPixmapBytes(Display * dpy,XID xid,unsigned long * bytes)206 Status 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
ReadClientValues(Display * dpy,long num_ids,XResClientIdValue * client_ids)242 static 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 */
XResQueryClientIds(Display * dpy,long num_specs,XResClientIdSpec * client_specs,long * num_ids,XResClientIdValue ** client_ids)265 Status 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
XResClientIdsDestroy(long num_ids,XResClientIdValue * client_ids)317 void 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
XResGetClientIdType(XResClientIdValue * value)329 XResClientIdType 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
XResGetClientPid(XResClientIdValue * value)349 pid_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
ReadResourceSizeSpec(Display * dpy,XResResourceSizeSpec * size)360 static 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
ReadResourceSizeValues(Display * dpy,long num_sizes,XResResourceSizeValue * sizes)379 static 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
XResQueryResourceBytes(Display * dpy,XID client,long num_specs,XResResourceIdSpec * resource_specs,long * num_sizes,XResResourceSizeValue ** sizes)399 Status 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
XResResourceSizeValuesDestroy(long num_sizes,XResResourceSizeValue * sizes)456 void 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