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