XrrProperty.c revision 67594505
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#include <limits.h> 35 36Atom * 37XRRListOutputProperties (Display *dpy, RROutput output, int *nprop) 38{ 39 XExtDisplayInfo *info = XRRFindDisplay(dpy); 40 xRRListOutputPropertiesReply rep; 41 xRRListOutputPropertiesReq *req; 42 int nbytes, rbytes; 43 Atom *props = NULL; 44 45 RRCheckExtension (dpy, info, NULL); 46 47 LockDisplay (dpy); 48 GetReq (RRListOutputProperties, req); 49 req->reqType = info->codes->major_opcode; 50 req->randrReqType = X_RRListOutputProperties; 51 req->output = output; 52 53 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { 54 UnlockDisplay (dpy); 55 SyncHandle (); 56 *nprop = 0; 57 return NULL; 58 } 59 60 if (rep.nAtoms) { 61 rbytes = rep.nAtoms * sizeof (Atom); 62 nbytes = rep.nAtoms << 2; 63 64 props = (Atom *) Xmalloc (rbytes); 65 if (props == NULL) { 66 _XEatDataWords (dpy, rep.length); 67 UnlockDisplay (dpy); 68 SyncHandle (); 69 *nprop = 0; 70 return NULL; 71 } 72 73 _XRead32 (dpy, (long *) props, nbytes); 74 } 75 76 *nprop = rep.nAtoms; 77 UnlockDisplay (dpy); 78 SyncHandle (); 79 return props; 80} 81 82XRRPropertyInfo * 83XRRQueryOutputProperty (Display *dpy, RROutput output, Atom property) 84{ 85 XExtDisplayInfo *info = XRRFindDisplay(dpy); 86 xRRQueryOutputPropertyReply rep; 87 xRRQueryOutputPropertyReq *req; 88 unsigned int rbytes, nbytes; 89 XRRPropertyInfo *prop_info; 90 91 RRCheckExtension (dpy, info, NULL); 92 93 LockDisplay (dpy); 94 GetReq (RRQueryOutputProperty, req); 95 req->reqType = info->codes->major_opcode; 96 req->randrReqType = X_RRQueryOutputProperty; 97 req->output = output; 98 req->property = property; 99 100 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { 101 UnlockDisplay (dpy); 102 SyncHandle (); 103 return NULL; 104 } 105 106 if (rep.length < ((INT_MAX / sizeof(long)) - sizeof (XRRPropertyInfo))) { 107 rbytes = sizeof (XRRPropertyInfo) + (rep.length * sizeof (long)); 108 nbytes = rep.length << 2; 109 110 prop_info = Xmalloc (rbytes); 111 } else 112 prop_info = NULL; 113 114 if (prop_info == NULL) { 115 _XEatDataWords(dpy, rep.length); 116 UnlockDisplay (dpy); 117 SyncHandle (); 118 return NULL; 119 } 120 121 prop_info->pending = rep.pending; 122 prop_info->range = rep.range; 123 prop_info->immutable = rep.immutable; 124 prop_info->num_values = rep.length; 125 if (rep.length != 0) { 126 prop_info->values = (long *) (prop_info + 1); 127 _XRead32 (dpy, prop_info->values, nbytes); 128 } else { 129 prop_info->values = NULL; 130 } 131 132 UnlockDisplay (dpy); 133 SyncHandle (); 134 return prop_info; 135} 136 137void 138XRRConfigureOutputProperty (Display *dpy, RROutput output, Atom property, 139 Bool pending, Bool range, int num_values, 140 long *values) 141{ 142 XExtDisplayInfo *info = XRRFindDisplay(dpy); 143 xRRConfigureOutputPropertyReq *req; 144 long len; 145 146 RRSimpleCheckExtension (dpy, info); 147 148 LockDisplay(dpy); 149 GetReq (RRConfigureOutputProperty, req); 150 req->reqType = info->codes->major_opcode; 151 req->randrReqType = X_RRConfigureOutputProperty; 152 req->output = output; 153 req->property = property; 154 req->pending = pending; 155 req->range = range; 156 157 len = num_values; 158 if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { 159 SetReqLen(req, len, len); 160 len = (long)num_values << 2; 161 Data32 (dpy, values, len); 162 } /* else force BadLength */ 163 164 UnlockDisplay(dpy); 165 SyncHandle(); 166} 167 168void 169XRRChangeOutputProperty (Display *dpy, RROutput output, 170 Atom property, Atom type, 171 int format, int mode, 172 _Xconst unsigned char *data, int nelements) 173{ 174 XExtDisplayInfo *info = XRRFindDisplay(dpy); 175 xRRChangeOutputPropertyReq *req; 176 long len; 177 178 RRSimpleCheckExtension (dpy, info); 179 180 LockDisplay(dpy); 181 GetReq (RRChangeOutputProperty, req); 182 req->reqType = info->codes->major_opcode; 183 req->randrReqType = X_RRChangeOutputProperty; 184 req->output = output; 185 req->property = property; 186 req->type = type; 187 req->mode = mode; 188 if (nelements < 0) { 189 req->nUnits = 0; 190 req->format = 0; /* ask for garbage, get garbage */ 191 } else { 192 req->nUnits = nelements; 193 req->format = format; 194 } 195 196 switch (req->format) { 197 case 8: 198 len = ((long)nelements + 3) >> 2; 199 if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { 200 SetReqLen(req, len, len); 201 Data (dpy, (char *)data, nelements); 202 } /* else force BadLength */ 203 break; 204 205 case 16: 206 len = ((long)nelements + 1) >> 1; 207 if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { 208 SetReqLen(req, len, len); 209 len = (long)nelements << 1; 210 Data16 (dpy, (short *) data, len); 211 } /* else force BadLength */ 212 break; 213 214 case 32: 215 len = nelements; 216 if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { 217 SetReqLen(req, len, len); 218 len = (long)nelements << 2; 219 Data32 (dpy, (long *) data, len); 220 } /* else force BadLength */ 221 break; 222 223 default: 224 /* BadValue will be generated */ ; 225 } 226 227 UnlockDisplay(dpy); 228 SyncHandle(); 229} 230 231void 232XRRDeleteOutputProperty (Display *dpy, RROutput output, Atom property) 233{ 234 XExtDisplayInfo *info = XRRFindDisplay(dpy); 235 xRRDeleteOutputPropertyReq *req; 236 237 RRSimpleCheckExtension (dpy, info); 238 239 LockDisplay(dpy); 240 GetReq(RRDeleteOutputProperty, req); 241 req->reqType = info->codes->major_opcode; 242 req->randrReqType = X_RRDeleteOutputProperty; 243 req->output = output; 244 req->property = property; 245 UnlockDisplay(dpy); 246 SyncHandle(); 247} 248 249int 250XRRGetOutputProperty (Display *dpy, RROutput output, 251 Atom property, long offset, long length, 252 Bool delete, Bool pending, Atom req_type, 253 Atom *actual_type, int *actual_format, 254 unsigned long *nitems, unsigned long *bytes_after, 255 unsigned char **prop) 256{ 257 XExtDisplayInfo *info = XRRFindDisplay(dpy); 258 xRRGetOutputPropertyReply rep; 259 xRRGetOutputPropertyReq *req; 260 unsigned long nbytes, rbytes; 261 262 /* Always initialize return values, in case callers fail to initialize 263 them and fail to check the return code for an error. */ 264 *actual_type = None; 265 *actual_format = 0; 266 *nitems = *bytes_after = 0L; 267 *prop = (unsigned char *) NULL; 268 269 RRCheckExtension (dpy, info, 1); 270 271 LockDisplay (dpy); 272 GetReq (RRGetOutputProperty, req); 273 req->reqType = info->codes->major_opcode; 274 req->randrReqType = X_RRGetOutputProperty; 275 req->output = output; 276 req->property = property; 277 req->type = req_type; 278 req->longOffset = offset; 279 req->longLength = length; 280 req->delete = delete; 281 req->pending = pending; 282 283 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 284 { 285 UnlockDisplay (dpy); 286 SyncHandle (); 287 return ((xError *)&rep)->errorCode; 288 } 289 290 if (rep.propertyType != None) { 291 int format = rep.format; 292 293 /* 294 * Protect against both integer overflow and just plain oversized 295 * memory allocation - no server should ever return this many props. 296 */ 297 if (rep.nItems >= (INT_MAX >> 4)) 298 format = -1; /* fall through to default error case */ 299 300 /* 301 * One extra byte is malloced than is needed to contain the property 302 * data, but this last byte is null terminated and convenient for 303 * returning string properties, so the client doesn't then have to 304 * recopy the string to make it null terminated. 305 */ 306 switch (format) { 307 case 8: 308 nbytes = rep.nItems; 309 rbytes = rep.nItems + 1; 310 if (rbytes > 0 && (*prop = Xmalloc (rbytes))) 311 _XReadPad (dpy, (char *) *prop, nbytes); 312 break; 313 314 case 16: 315 nbytes = rep.nItems << 1; 316 rbytes = rep.nItems * sizeof (short) + 1; 317 if (rbytes > 0 && (*prop = Xmalloc (rbytes))) 318 _XRead16Pad (dpy, (short *) *prop, nbytes); 319 break; 320 321 case 32: 322 nbytes = rep.nItems << 2; 323 rbytes = rep.nItems * sizeof (long) + 1; 324 if (rbytes > 0 && (*prop = Xmalloc (rbytes))) 325 _XRead32 (dpy, (long *) *prop, nbytes); 326 break; 327 328 default: 329 /* 330 * This part of the code should never be reached. If it is, 331 * the server sent back a property with an invalid format. 332 */ 333 _XEatDataWords(dpy, rep.length); 334 UnlockDisplay(dpy); 335 SyncHandle(); 336 return(BadImplementation); 337 } 338 if (! *prop) { 339 _XEatDataWords(dpy, rep.length); 340 UnlockDisplay(dpy); 341 SyncHandle(); 342 return(BadAlloc); 343 } 344 (*prop)[rbytes - 1] = '\0'; 345 } 346 347 *actual_type = rep.propertyType; 348 *actual_format = rep.format; 349 *nitems = rep.nItems; 350 *bytes_after = rep.bytesAfter; 351 UnlockDisplay (dpy); 352 SyncHandle (); 353 354 return Success; 355} 356