From 0dba1be7969aa56f934d93889cbd589b3dafd3d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 20 Nov 2006 20:59:18 -0800 Subject: Change properties to have a pending value and report valid values. Pending values are transferred to current values at mode set, allowing a queue of values to accrue in preparation for the modeset operation while still reporting valid 'current' values for applications. The set of valid values is also available so applications can present a reasonable list to the user during configuration. --- include/X11/extensions/Xrandr.h | 18 ++- src/Makefile.am | 1 + src/XrrOutput.c | 227 -------------------------- src/XrrProperty.c | 344 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 362 insertions(+), 228 deletions(-) create mode 100644 src/XrrProperty.c diff --git a/include/X11/extensions/Xrandr.h b/include/X11/extensions/Xrandr.h index c1de54a..bd64e84 100644 --- a/include/X11/extensions/Xrandr.h +++ b/include/X11/extensions/Xrandr.h @@ -268,6 +268,22 @@ XRRFreeOutputInfo (XRROutputInfo *outputInfo); Atom * XRRListOutputProperties (Display *dpy, RROutput output, int *nprop); +typedef struct { + Bool pending; + Bool range; + Bool immutable; + int num_values; + long *values; +} XRRPropertyInfo; + +XRRPropertyInfo * +XRRQueryOutputProperty (Display *dpy, RROutput output, Atom property); + +void +XRRConfigureOutputProperty (Display *dpy, RROutput output, Atom property, + Bool pending, Bool range, int num_values, + long *values); + void XRRChangeOutputProperty (Display *dpy, RROutput output, Atom property, Atom type, @@ -280,7 +296,7 @@ XRRDeleteOutputProperty (Display *dpy, RROutput output, Atom property); int XRRGetOutputProperty (Display *dpy, RROutput output, Atom property, long offset, long length, - Bool delete, Atom req_type, + Bool delete, Bool pending, Atom req_type, Atom *actual_type, int *actual_format, unsigned long *nitems, unsigned long *bytes_after, unsigned char **prop); diff --git a/src/Makefile.am b/src/Makefile.am index 5bd0936..b884a39 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,7 @@ libXrandr_la_SOURCES = \ XrrCrtc.c \ XrrMode.c \ XrrOutput.c \ + XrrProperty.c \ XrrScreen.c libXrandr_la_LIBADD = @X_LIBS@ @RANDR_LIBS@ diff --git a/src/XrrOutput.c b/src/XrrOutput.c index c908bbc..1fe03ae 100644 --- a/src/XrrOutput.c +++ b/src/XrrOutput.c @@ -129,230 +129,3 @@ XRRFreeOutputInfo (XRROutputInfo *outputInfo) { Xfree (outputInfo); } - -Atom * -XRRListOutputProperties (Display *dpy, RROutput output, int *nprop) -{ - XExtDisplayInfo *info = XRRFindDisplay(dpy); - xRRListOutputPropertiesReply rep; - xRRListOutputPropertiesReq *req; - int nbytes, nbytesRead, netbytes; - int i; - xRRQueryVersionReq *vreq; - Atom *props; - - RRCheckExtension (dpy, info, 0); - - LockDisplay (dpy); - GetReq (RRListOutputProperties, req); - req->reqType = info->codes->major_opcode; - req->randrReqType = X_RRListOutputProperties; - req->output = output; - - if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { - UnlockDisplay (dpy); - SyncHandle (); - *nprop = 0; - return NULL; - } - - if (rep.nProperties) { - nbytes = rep.nProperties * sizeof (Atom); - netbytes = rep.nProperties << 2; - - props = (Atom *) Xmalloc (nbytes); - if (props == NULL) { - _XEatData (dpy, nbytes); - UnlockDisplay (dpy); - SyncHandle (); - *nprop = 0; - return NULL; - } - - _XRead32 (dpy, props, nbytes); - } - - *nprop = rep.nProperties; - UnlockDisplay (dpy); - SyncHandle (); - return props; -} - -void -XRRChangeOutputProperty (Display *dpy, RROutput output, - Atom property, Atom type, - int format, int mode, - _Xconst unsigned char *data, int nelements) -{ - XExtDisplayInfo *info = XRRFindDisplay(dpy); - xRRChangeOutputPropertyReq *req; - xRRQueryVersionReq *vreq; - long len; - - RRSimpleCheckExtension (dpy, info); - - LockDisplay(dpy); - GetReq (RRChangeOutputProperty, req); - req->reqType = info->codes->major_opcode; - req->randrReqType = X_RRChangeOutputProperty; - req->output = output; - req->property = property; - req->type = type; - req->mode = mode; - if (nelements < 0) { - req->nUnits = 0; - req->format = 0; /* ask for garbage, get garbage */ - } else { - req->nUnits = nelements; - req->format = format; - } - - switch (req->format) { - case 8: - len = ((long)nelements + 3) >> 2; - if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { - SetReqLen(req, len, len); - Data (dpy, (char *)data, nelements); - } /* else force BadLength */ - break; - - case 16: - len = ((long)nelements + 1) >> 1; - if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { - SetReqLen(req, len, len); - len = (long)nelements << 1; - Data16 (dpy, (short *) data, len); - } /* else force BadLength */ - break; - - case 32: - len = nelements; - if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { - SetReqLen(req, len, len); - len = (long)nelements << 2; - Data32 (dpy, (long *) data, len); - } /* else force BadLength */ - break; - - default: - /* BadValue will be generated */ ; - } - - UnlockDisplay(dpy); - SyncHandle(); -} - -void -XRRDeleteOutputProperty (Display *dpy, RROutput output, Atom property) -{ - XExtDisplayInfo *info = XRRFindDisplay(dpy); - xRRDeleteOutputPropertyReq *req; - - RRSimpleCheckExtension (dpy, info); - - LockDisplay(dpy); - GetReq(RRDeleteOutputProperty, req); - req->reqType = info->codes->major_opcode; - req->randrReqType = X_RRDeleteOutputProperty; - req->output = output; - req->property = property; - UnlockDisplay(dpy); - SyncHandle(); -} - -int -XRRGetOutputProperty (Display *dpy, RROutput output, - Atom property, long offset, long length, - Bool delete, Atom req_type, - Atom *actual_type, int *actual_format, - unsigned long *nitems, unsigned long *bytes_after, - unsigned char **prop) -{ - XExtDisplayInfo *info = XRRFindDisplay(dpy); - xRRGetOutputPropertyReply rep; - xRRGetOutputPropertyReq *req; - int nbytes, nbytesRead; - int i; - xRRQueryVersionReq *vreq; - - RRCheckExtension (dpy, info, 1); - - LockDisplay (dpy); - GetReq (RRGetOutputProperty, req); - req->reqType = info->codes->major_opcode; - req->randrReqType = X_RRGetOutputProperty; - req->output = output; - req->property = property; - req->type = req_type; - req->longOffset = offset; - req->longLength = length; - req->delete = delete; - - if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) - { - UnlockDisplay (dpy); - SyncHandle (); - return 1; - } - - *prop = (unsigned char *) NULL; - if (rep.propertyType != None) { - long nbytes, netbytes; - /* - * One extra byte is malloced than is needed to contain the property - * data, but this last byte is null terminated and convenient for - * returning string properties, so the client doesn't then have to - * recopy the string to make it null terminated. - */ - switch (rep.format) { - case 8: - nbytes = netbytes = rep.nItems; - if (nbytes + 1 > 0 && - (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1))) - _XReadPad (dpy, (char *) *prop, netbytes); - break; - - case 16: - nbytes = rep.nItems * sizeof (short); - netbytes = rep.nItems << 1; - if (nbytes + 1 > 0 && - (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1))) - _XRead16Pad (dpy, (short *) *prop, netbytes); - break; - - case 32: - nbytes = rep.nItems * sizeof (long); - netbytes = rep.nItems << 2; - if (nbytes + 1 > 0 && - (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1))) - _XRead32 (dpy, (long *) *prop, netbytes); - break; - - default: - /* - * This part of the code should never be reached. If it is, - * the server sent back a property with an invalid format. - */ - _XEatData(dpy, (unsigned long) netbytes); - UnlockDisplay(dpy); - SyncHandle(); - return(BadImplementation); - } - if (! *prop) { - _XEatData(dpy, (unsigned long) netbytes); - UnlockDisplay(dpy); - SyncHandle(); - return(BadAlloc); - } - (*prop)[nbytes] = '\0'; - } - - *actual_type = rep.propertyType; - *actual_format = rep.format; - *nitems = rep.nItems; - *bytes_after = rep.bytesAfter; - UnlockDisplay (dpy); - SyncHandle (); - - return Success; -} diff --git a/src/XrrProperty.c b/src/XrrProperty.c new file mode 100644 index 0000000..3b16491 --- /dev/null +++ b/src/XrrProperty.c @@ -0,0 +1,344 @@ +/* + * Copyright © 2006 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +/* we need to be able to manipulate the Display structure on events */ +#include +#include +#include +#include "Xrandrint.h" + +Atom * +XRRListOutputProperties (Display *dpy, RROutput output, int *nprop) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRListOutputPropertiesReply rep; + xRRListOutputPropertiesReq *req; + int nbytes, nbytesRead, netbytes; + int i; + xRRQueryVersionReq *vreq; + Atom *props; + + RRCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (RRListOutputProperties, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRListOutputProperties; + req->output = output; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay (dpy); + SyncHandle (); + *nprop = 0; + return NULL; + } + + if (rep.nProperties) { + nbytes = rep.nProperties * sizeof (Atom); + netbytes = rep.nProperties << 2; + + props = (Atom *) Xmalloc (nbytes); + if (props == NULL) { + _XEatData (dpy, netbytes); + UnlockDisplay (dpy); + SyncHandle (); + *nprop = 0; + return NULL; + } + + _XRead32 (dpy, props, nbytes); + } + + *nprop = rep.nProperties; + UnlockDisplay (dpy); + SyncHandle (); + return props; +} + +XRRPropertyInfo * +XRRQueryOutputProperty (Display *dpy, RROutput output, Atom property) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRQueryOutputPropertyReply rep; + xRRQueryOutputPropertyReq *req; + int nbytes, nbytesRead, netbytes; + int i; + xRRQueryVersionReq *vreq; + XRRPropertyInfo *prop_info; + + RRCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (RRQueryOutputProperty, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRQueryOutputProperty; + req->output = output; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + if (rep.length) { + nbytes = rep.length * sizeof (long); + netbytes = rep.length << 2; + + prop_info = (XRRPropertyInfo *) Xmalloc (nbytes + + sizeof (XRRPropertyInfo)); + if (prop_info == NULL) { + _XEatData (dpy, netbytes); + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + prop_info->pending = rep.pending; + prop_info->range = rep.range; + prop_info->immutable = rep.immutable; + prop_info->num_values = rep.length; + prop_info->values = (long *) (prop_info + 1); + + _XRead32 (dpy, prop_info->values, nbytes); + } + + UnlockDisplay (dpy); + SyncHandle (); + return prop_info; +} + +void +XRRConfigureOutputProperty (Display *dpy, RROutput output, Atom property, + Bool pending, Bool range, int num_values, + long *values) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRConfigureOutputPropertyReq *req; + xRRQueryVersionReq *vreq; + long len; + + RRSimpleCheckExtension (dpy, info); + + LockDisplay(dpy); + GetReq (RRConfigureOutputProperty, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRConfigureOutputProperty; + req->output = output; + req->property = property; + req->pending = pending; + req->range = range; + + len = num_values; + if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { + SetReqLen(req, len, len); + len = (long)num_values << 2; + Data32 (dpy, values, len); + } /* else force BadLength */ + + UnlockDisplay(dpy); + SyncHandle(); +} + +void +XRRChangeOutputProperty (Display *dpy, RROutput output, + Atom property, Atom type, + int format, int mode, + _Xconst unsigned char *data, int nelements) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRChangeOutputPropertyReq *req; + xRRQueryVersionReq *vreq; + long len; + + RRSimpleCheckExtension (dpy, info); + + LockDisplay(dpy); + GetReq (RRChangeOutputProperty, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRChangeOutputProperty; + req->output = output; + req->property = property; + req->type = type; + req->mode = mode; + if (nelements < 0) { + req->nUnits = 0; + req->format = 0; /* ask for garbage, get garbage */ + } else { + req->nUnits = nelements; + req->format = format; + } + + switch (req->format) { + case 8: + len = ((long)nelements + 3) >> 2; + if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { + SetReqLen(req, len, len); + Data (dpy, (char *)data, nelements); + } /* else force BadLength */ + break; + + case 16: + len = ((long)nelements + 1) >> 1; + if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { + SetReqLen(req, len, len); + len = (long)nelements << 1; + Data16 (dpy, (short *) data, len); + } /* else force BadLength */ + break; + + case 32: + len = nelements; + if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) { + SetReqLen(req, len, len); + len = (long)nelements << 2; + Data32 (dpy, (long *) data, len); + } /* else force BadLength */ + break; + + default: + /* BadValue will be generated */ ; + } + + UnlockDisplay(dpy); + SyncHandle(); +} + +void +XRRDeleteOutputProperty (Display *dpy, RROutput output, Atom property) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRDeleteOutputPropertyReq *req; + + RRSimpleCheckExtension (dpy, info); + + LockDisplay(dpy); + GetReq(RRDeleteOutputProperty, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRDeleteOutputProperty; + req->output = output; + req->property = property; + UnlockDisplay(dpy); + SyncHandle(); +} + +int +XRRGetOutputProperty (Display *dpy, RROutput output, + Atom property, long offset, long length, + Bool delete, Bool pending, Atom req_type, + Atom *actual_type, int *actual_format, + unsigned long *nitems, unsigned long *bytes_after, + unsigned char **prop) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetOutputPropertyReply rep; + xRRGetOutputPropertyReq *req; + int nbytes, nbytesRead; + int i; + xRRQueryVersionReq *vreq; + + RRCheckExtension (dpy, info, 1); + + LockDisplay (dpy); + GetReq (RRGetOutputProperty, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetOutputProperty; + req->output = output; + req->property = property; + req->type = req_type; + req->longOffset = offset; + req->longLength = length; + req->delete = delete; + req->pending = pending; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + UnlockDisplay (dpy); + SyncHandle (); + return 1; + } + + *prop = (unsigned char *) NULL; + if (rep.propertyType != None) { + long nbytes, netbytes; + /* + * One extra byte is malloced than is needed to contain the property + * data, but this last byte is null terminated and convenient for + * returning string properties, so the client doesn't then have to + * recopy the string to make it null terminated. + */ + switch (rep.format) { + case 8: + nbytes = netbytes = rep.nItems; + if (nbytes + 1 > 0 && + (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1))) + _XReadPad (dpy, (char *) *prop, netbytes); + break; + + case 16: + nbytes = rep.nItems * sizeof (short); + netbytes = rep.nItems << 1; + if (nbytes + 1 > 0 && + (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1))) + _XRead16Pad (dpy, (short *) *prop, netbytes); + break; + + case 32: + nbytes = rep.nItems * sizeof (long); + netbytes = rep.nItems << 2; + if (nbytes + 1 > 0 && + (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1))) + _XRead32 (dpy, (long *) *prop, netbytes); + break; + + default: + /* + * This part of the code should never be reached. If it is, + * the server sent back a property with an invalid format. + */ + _XEatData(dpy, (unsigned long) netbytes); + UnlockDisplay(dpy); + SyncHandle(); + return(BadImplementation); + } + if (! *prop) { + _XEatData(dpy, (unsigned long) netbytes); + UnlockDisplay(dpy); + SyncHandle(); + return(BadAlloc); + } + (*prop)[nbytes] = '\0'; + } + + *actual_type = rep.propertyType; + *actual_format = rep.format; + *nitems = rep.nItems; + *bytes_after = rep.bytesAfter; + UnlockDisplay (dpy); + SyncHandle (); + + return Success; +} -- cgit v1.2.3