XrrProperty.c revision 0597fb56
1/*
2 * Copyright © 2006 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  The copyright holders make no representations
11 * about the suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <stdio.h>
28#include <X11/Xlib.h>
29/* we need to be able to manipulate the Display structure on events */
30#include <X11/Xlibint.h>
31#include <X11/extensions/render.h>
32#include <X11/extensions/Xrender.h>
33#include "Xrandrint.h"
34
35Atom *
36XRRListOutputProperties (Display *dpy, RROutput output, int *nprop)
37{
38    XExtDisplayInfo		*info = XRRFindDisplay(dpy);
39    xRRListOutputPropertiesReply rep;
40    xRRListOutputPropertiesReq	*req;
41    int				nbytes, rbytes;
42    Atom			*props = NULL;
43
44    RRCheckExtension (dpy, info, NULL);
45
46    LockDisplay (dpy);
47    GetReq (RRListOutputProperties, req);
48    req->reqType = info->codes->major_opcode;
49    req->randrReqType = X_RRListOutputProperties;
50    req->output = output;
51
52    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
53	UnlockDisplay (dpy);
54	SyncHandle ();
55	*nprop = 0;
56	return NULL;
57    }
58
59    if (rep.nAtoms) {
60	rbytes = rep.nAtoms * sizeof (Atom);
61	nbytes = rep.nAtoms << 2;
62
63	props = (Atom *) Xmalloc (rbytes);
64	if (props == NULL) {
65	    _XEatData (dpy, nbytes);
66	    UnlockDisplay (dpy);
67	    SyncHandle ();
68	    *nprop = 0;
69	    return NULL;
70	}
71
72	_XRead32 (dpy, props, nbytes);
73    }
74
75    *nprop = rep.nAtoms;
76    UnlockDisplay (dpy);
77    SyncHandle ();
78    return props;
79}
80
81XRRPropertyInfo *
82XRRQueryOutputProperty (Display *dpy, RROutput output, Atom property)
83{
84    XExtDisplayInfo		*info = XRRFindDisplay(dpy);
85    xRRQueryOutputPropertyReply rep;
86    xRRQueryOutputPropertyReq	*req;
87    int				rbytes, nbytes;
88    XRRPropertyInfo		*prop_info;
89
90    RRCheckExtension (dpy, info, NULL);
91
92    LockDisplay (dpy);
93    GetReq (RRQueryOutputProperty, req);
94    req->reqType = info->codes->major_opcode;
95    req->randrReqType = X_RRQueryOutputProperty;
96    req->output = output;
97    req->property = property;
98
99    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
100	UnlockDisplay (dpy);
101	SyncHandle ();
102	return NULL;
103    }
104
105    rbytes = sizeof (XRRPropertyInfo) + rep.length * sizeof (long);
106    nbytes = rep.length << 2;
107
108    prop_info = (XRRPropertyInfo *) Xmalloc (rbytes);
109    if (prop_info == NULL) {
110	_XEatData (dpy, nbytes);
111	UnlockDisplay (dpy);
112	SyncHandle ();
113	return NULL;
114    }
115
116    prop_info->pending = rep.pending;
117    prop_info->range = rep.range;
118    prop_info->immutable = rep.immutable;
119    prop_info->num_values = rep.length;
120    if (rep.length != 0) {
121	prop_info->values = (long *) (prop_info + 1);
122	_XRead32 (dpy, prop_info->values, nbytes);
123    } else {
124	prop_info->values = NULL;
125    }
126
127    UnlockDisplay (dpy);
128    SyncHandle ();
129    return prop_info;
130}
131
132void
133XRRConfigureOutputProperty (Display *dpy, RROutput output, Atom property,
134			    Bool pending, Bool range, int num_values,
135			    long *values)
136{
137    XExtDisplayInfo		    *info = XRRFindDisplay(dpy);
138    xRRConfigureOutputPropertyReq   *req;
139    long len;
140
141    RRSimpleCheckExtension (dpy, info);
142
143    LockDisplay(dpy);
144    GetReq (RRConfigureOutputProperty, req);
145    req->reqType = info->codes->major_opcode;
146    req->randrReqType = X_RRConfigureOutputProperty;
147    req->output = output;
148    req->property = property;
149    req->pending = pending;
150    req->range = range;
151
152    len = num_values;
153    if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
154	SetReqLen(req, len, len);
155	len = (long)num_values << 2;
156	Data32 (dpy, values, len);
157    } /* else force BadLength */
158
159    UnlockDisplay(dpy);
160    SyncHandle();
161}
162
163void
164XRRChangeOutputProperty (Display *dpy, RROutput output,
165			 Atom property, Atom type,
166			 int format, int mode,
167			 _Xconst unsigned char *data, int nelements)
168{
169    XExtDisplayInfo		*info = XRRFindDisplay(dpy);
170    xRRChangeOutputPropertyReq	*req;
171    long len;
172
173    RRSimpleCheckExtension (dpy, info);
174
175    LockDisplay(dpy);
176    GetReq (RRChangeOutputProperty, req);
177    req->reqType = info->codes->major_opcode;
178    req->randrReqType = X_RRChangeOutputProperty;
179    req->output = output;
180    req->property = property;
181    req->type = type;
182    req->mode = mode;
183    if (nelements < 0) {
184	req->nUnits = 0;
185	req->format = 0; /* ask for garbage, get garbage */
186    } else {
187	req->nUnits = nelements;
188	req->format = format;
189    }
190
191    switch (req->format) {
192    case 8:
193	len = ((long)nelements + 3) >> 2;
194	if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
195	    SetReqLen(req, len, len);
196	    Data (dpy, (char *)data, nelements);
197	} /* else force BadLength */
198	break;
199
200    case 16:
201	len = ((long)nelements + 1) >> 1;
202	if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
203	    SetReqLen(req, len, len);
204	    len = (long)nelements << 1;
205	    Data16 (dpy, (short *) data, len);
206	} /* else force BadLength */
207	break;
208
209    case 32:
210	len = nelements;
211	if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
212	    SetReqLen(req, len, len);
213	    len = (long)nelements << 2;
214	    Data32 (dpy, (long *) data, len);
215	} /* else force BadLength */
216	break;
217
218    default:
219	/* BadValue will be generated */ ;
220    }
221
222    UnlockDisplay(dpy);
223    SyncHandle();
224}
225
226void
227XRRDeleteOutputProperty (Display *dpy, RROutput output, Atom property)
228{
229    XExtDisplayInfo		*info = XRRFindDisplay(dpy);
230    xRRDeleteOutputPropertyReq *req;
231
232    RRSimpleCheckExtension (dpy, info);
233
234    LockDisplay(dpy);
235    GetReq(RRDeleteOutputProperty, req);
236    req->reqType = info->codes->major_opcode;
237    req->randrReqType = X_RRDeleteOutputProperty;
238    req->output = output;
239    req->property = property;
240    UnlockDisplay(dpy);
241    SyncHandle();
242}
243
244int
245XRRGetOutputProperty (Display *dpy, RROutput output,
246		      Atom property, long offset, long length,
247		      Bool delete, Bool pending, Atom req_type,
248		      Atom *actual_type, int *actual_format,
249		      unsigned long *nitems, unsigned long *bytes_after,
250		      unsigned char **prop)
251{
252    XExtDisplayInfo		*info = XRRFindDisplay(dpy);
253    xRRGetOutputPropertyReply	rep;
254    xRRGetOutputPropertyReq	*req;
255    long    			nbytes, rbytes;
256
257    RRCheckExtension (dpy, info, 1);
258
259    LockDisplay (dpy);
260    GetReq (RRGetOutputProperty, req);
261    req->reqType = info->codes->major_opcode;
262    req->randrReqType = X_RRGetOutputProperty;
263    req->output = output;
264    req->property = property;
265    req->type = req_type;
266    req->longOffset = offset;
267    req->longLength = length;
268    req->delete = delete;
269    req->pending = pending;
270
271    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
272    {
273	UnlockDisplay (dpy);
274	SyncHandle ();
275	return ((xError *)&rep)->errorCode;
276    }
277
278    *prop = (unsigned char *) NULL;
279    if (rep.propertyType != None) {
280	/*
281	 * One extra byte is malloced than is needed to contain the property
282	 * data, but this last byte is null terminated and convenient for
283	 * returning string properties, so the client doesn't then have to
284	 * recopy the string to make it null terminated.
285	 */
286	switch (rep.format) {
287	case 8:
288	    nbytes = rep.nItems;
289	    rbytes = rep.nItems + 1;
290	    if (rbytes > 0 &&
291		(*prop = (unsigned char *) Xmalloc ((unsigned)rbytes)))
292		_XReadPad (dpy, (char *) *prop, nbytes);
293	    break;
294
295	case 16:
296	    nbytes = rep.nItems << 1;
297	    rbytes = rep.nItems * sizeof (short) + 1;
298	    if (rbytes > 0 &&
299		(*prop = (unsigned char *) Xmalloc ((unsigned)rbytes)))
300		_XRead16Pad (dpy, (short *) *prop, nbytes);
301	    break;
302
303	case 32:
304	    nbytes = rep.nItems << 2;
305	    rbytes = rep.nItems * sizeof (long) + 1;
306	    if (rbytes > 0 &&
307		(*prop = (unsigned char *) Xmalloc ((unsigned)rbytes)))
308		_XRead32 (dpy, (long *) *prop, nbytes);
309	    break;
310
311	default:
312	    /*
313	     * This part of the code should never be reached.  If it is,
314	     * the server sent back a property with an invalid format.
315	     */
316	    nbytes = rep.length << 2;
317	    _XEatData(dpy, (unsigned long) nbytes);
318	    UnlockDisplay(dpy);
319	    SyncHandle();
320	    return(BadImplementation);
321	}
322	if (! *prop) {
323	    _XEatData(dpy, (unsigned long) nbytes);
324	    UnlockDisplay(dpy);
325	    SyncHandle();
326	    return(BadAlloc);
327	}
328	(*prop)[rbytes - 1] = '\0';
329    }
330
331    *actual_type = rep.propertyType;
332    *actual_format = rep.format;
333    *nitems = rep.nItems;
334    *bytes_after = rep.bytesAfter;
335    UnlockDisplay (dpy);
336    SyncHandle ();
337
338    return Success;
339}
340