diff options
author | Eric Anholt <eric@anholt.net> | 2006-11-27 15:41:03 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2006-11-27 15:41:03 -0800 |
commit | 7fcdcbb0f9c4736bd678be7f9bf76d472293233f (patch) | |
tree | d04fbf955a483508874f8d0981293791de538587 /src | |
parent | 875867f275803682e58f0649f054a83293c6e02c (diff) | |
parent | 0dba1be7969aa56f934d93889cbd589b3dafd3d4 (diff) |
Merge branch 'randr-1.2'
Conflicts:
configure.ac
Diffstat (limited to 'src')
-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/Xrandr.c | 506 | ||||
-rw-r--r-- | src/Xrandrint.h | 16 | ||||
-rw-r--r-- | src/XrrConfig.c | 424 | ||||
-rw-r--r-- | src/XrrCrtc.c | 178 | ||||
-rw-r--r-- | src/XrrMode.c | 63 | ||||
-rw-r--r-- | src/XrrOutput.c | 131 | ||||
-rw-r--r-- | src/XrrProperty.c | 344 | ||||
-rw-r--r-- | src/XrrScreen.c | 246 |
10 files changed, 1510 insertions, 409 deletions
diff --git a/src/.gitignore b/src/.gitignore index a947c47..00409a0 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -2,5 +2,6 @@ .libs libXrandr.la *.lo +*.o Makefile Makefile.in diff --git a/src/Makefile.am b/src/Makefile.am index dce56e4..b884a39 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,14 +2,20 @@ lib_LTLIBRARIES = libXrandr.la libXrandr_la_SOURCES = \ Xrandr.c \ - Xrandrint.h + Xrandrint.h \ + XrrConfig.c \ + XrrCrtc.c \ + XrrMode.c \ + XrrOutput.c \ + XrrProperty.c \ + XrrScreen.c libXrandr_la_LIBADD = @X_LIBS@ @RANDR_LIBS@ AM_CFLAGS = @X_CFLAGS@ @RANDR_CFLAGS@ @MALLOC_ZERO_CFLAGS@ INCLUDES = -I$(top_srcdir)/include/X11/extensions -libXrandr_la_LDFLAGS = -version-number 2:0:0 -no-undefined +libXrandr_la_LDFLAGS = -version-number 2:1:0 -no-undefined libXrandrincludedir = $(includedir)/X11/extensions libXrandrinclude_HEADERS = $(top_srcdir)/include/X11/extensions/Xrandr.h diff --git a/src/Xrandr.c b/src/Xrandr.c index 7f256a7..f8bdf02 100644 --- a/src/Xrandr.c +++ b/src/Xrandr.c @@ -42,8 +42,6 @@ char XRRExtensionName[] = RANDR_NAME; static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire); static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire); -static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy, Window window); - static int XRRCloseDisplay (Display *dpy, XExtCodes *codes); @@ -64,19 +62,16 @@ static /* const */ XExtensionHooks rr_extension_hooks = { static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire) { XExtDisplayInfo *info = XRRFindDisplay(dpy); - XRRScreenChangeNotifyEvent *aevent; - xRRScreenChangeNotifyEvent *awire; RRCheckExtension(dpy, info, False); switch ((wire->u.u.type & 0x7F) - info->codes->first_event) { - case RRScreenChangeNotify: - awire = (xRRScreenChangeNotifyEvent *) wire; - aevent = (XRRScreenChangeNotifyEvent *) event; + case RRScreenChangeNotify: { + XRRScreenChangeNotifyEvent *aevent= (XRRScreenChangeNotifyEvent *) event; + xRRScreenChangeNotifyEvent *awire = (xRRScreenChangeNotifyEvent *) wire; aevent->type = awire->type & 0x7F; - aevent->serial = _XSetLastRequestRead(dpy, - (xGenericReply *) wire); + aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); aevent->send_event = (awire->type & 0x80) != 0; aevent->display = dpy; aevent->window = awire->window; @@ -91,6 +86,53 @@ static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire) aevent->mwidth = awire->widthInMillimeters; aevent->mheight = awire->heightInMillimeters; return True; + } + case RRNotify: { + XRRNotifyEvent *aevent = (XRRNotifyEvent *) event; + xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire; + aevent->type = awire->type & 0x7F; + aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); + aevent->send_event = (awire->type & 0x80) != 0; + aevent->display = dpy; + aevent->window = awire->window; + aevent->subtype = awire->subCode; + switch (aevent->subtype) { + case RRNotify_OutputChange: { + XRROutputChangeNotifyEvent *aevent = (XRROutputChangeNotifyEvent *) event; + xRROutputChangeNotifyEvent *awire = (xRROutputChangeNotifyEvent *) wire; + aevent->output = awire->output; + aevent->crtc = awire->crtc; + aevent->mode = awire->mode; + aevent->rotation = awire->rotation; + aevent->connection = awire->connection; + aevent->subpixel_order = awire->subpixelOrder; + return True; + } + case RRNotify_CrtcChange: { + XRRCrtcChangeNotifyEvent *aevent = (XRRCrtcChangeNotifyEvent *) event; + xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire; + aevent->crtc = awire->crtc; + aevent->mode = awire->mode; + aevent->rotation = awire->rotation; + aevent->x = awire->x; + aevent->y = awire->y; + aevent->width = awire->height; + aevent->height = awire->height; + return True; + } + case RRNotify_OutputProperty: { + XRROutputPropertyNotifyEvent *aevent = (XRROutputPropertyNotifyEvent *) event; + xRROutputPropertyNotifyEvent *awire = (xRROutputPropertyNotifyEvent *) wire; + aevent->output = awire->output; + aevent->property = awire->atom; + aevent->timestamp = awire->timestamp; + aevent->state = awire->state; + return True; + } + + break; + } + } } return False; @@ -99,16 +141,14 @@ static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire) static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire) { XExtDisplayInfo *info = XRRFindDisplay(dpy); - XRRScreenChangeNotifyEvent *aevent; - xRRScreenChangeNotifyEvent *awire; RRCheckExtension(dpy, info, False); switch ((event->type & 0x7F) - info->codes->first_event) { - case RRScreenChangeNotify: - awire = (xRRScreenChangeNotifyEvent *) wire; - aevent = (XRRScreenChangeNotifyEvent *) event; + case RRScreenChangeNotify: { + xRRScreenChangeNotifyEvent *awire = (xRRScreenChangeNotifyEvent *) wire; + XRRScreenChangeNotifyEvent *aevent = (XRRScreenChangeNotifyEvent *) event; awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); awire->rotation = (CARD8) aevent->rotation; awire->sequenceNumber = aevent->serial & 0xFFFF; @@ -123,6 +163,49 @@ static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire) awire->widthInMillimeters = aevent->mwidth; awire->heightInMillimeters = aevent->mheight; return True; + } + case RRNotify: { + xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire; + XRRNotifyEvent *aevent = (XRRNotifyEvent *) event; + awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); + awire->sequenceNumber = aevent->serial & 0xFFFF; + awire->window = aevent->window; + awire->subCode = aevent->subtype; + switch (aevent->subtype) { + case RRNotify_OutputChange: { + xRROutputChangeNotifyEvent *awire = (xRROutputChangeNotifyEvent *) wire; + XRROutputChangeNotifyEvent *aevent = (XRROutputChangeNotifyEvent *) event; + awire->output = aevent->output; + awire->crtc = aevent->crtc; + awire->mode = aevent->mode; + awire->rotation = aevent->rotation; + awire->connection = aevent->connection; + awire->subpixelOrder = aevent->subpixel_order; + return True; + } + case RRNotify_CrtcChange: { + xRRCrtcChangeNotifyEvent *awire = (xRRCrtcChangeNotifyEvent *) wire; + XRRCrtcChangeNotifyEvent *aevent = (XRRCrtcChangeNotifyEvent *) event; + awire->crtc = aevent->crtc; + awire->mode = aevent->mode; + awire->rotation = aevent->rotation; + awire->x = aevent->x; + awire->y = aevent->y; + awire->width = aevent->height; + awire->height = aevent->height; + return True; + } + case RRNotify_OutputProperty: { + xRROutputPropertyNotifyEvent *awire = (xRROutputPropertyNotifyEvent *) wire; + XRROutputPropertyNotifyEvent *aevent = (XRROutputPropertyNotifyEvent *) event; + awire->output = aevent->output; + awire->atom = aevent->property; + awire->timestamp = aevent->timestamp; + awire->state = aevent->state; + return True; + } + } + } } return False; } @@ -178,157 +261,6 @@ XRRCloseDisplay (Display *dpy, XExtCodes *codes) UnlockDisplay(dpy); return XextRemoveDisplay (&XRRExtensionInfo, dpy); } - - -Rotation XRRConfigRotations(XRRScreenConfiguration *config, Rotation *current_rotation) -{ - *current_rotation = config->current_rotation; - return config->rotations; -} - -XRRScreenSize *XRRConfigSizes(XRRScreenConfiguration *config, int *nsizes) -{ - *nsizes = config->nsizes; - return config->sizes; -} - -short *XRRConfigRates (XRRScreenConfiguration *config, int sizeID, int *nrates) -{ - short *r = config->rates; - int nents = config->nrates; - - /* Skip over the intervening rate lists */ - while (sizeID > 0 && nents > 0) - { - int i = (*r + 1); - r += i; - nents -= i; - sizeID--; - } - if (!nents) - { - *nrates = 0; - return 0; - } - *nrates = (int) *r; - return r + 1; -} - -Time XRRConfigTimes (XRRScreenConfiguration *config, Time *config_timestamp) -{ - *config_timestamp = config->config_timestamp; - return config->timestamp; -} - - -SizeID XRRConfigCurrentConfiguration (XRRScreenConfiguration *config, - Rotation *rotation) -{ - *rotation = (Rotation) config->current_rotation; - return (SizeID) config->current_size; -} - -short XRRConfigCurrentRate (XRRScreenConfiguration *config) -{ - return config->current_rate; -} - -/* - * Go get the screen configuration data and salt it away for future use; - * returns NULL if extension not supported - */ -static XRRScreenConfiguration *_XRRValidateCache (Display *dpy, int screen) -{ - XExtDisplayInfo *info = XRRFindDisplay (dpy); - XRRScreenConfiguration **configs; - XRandRInfo *xrri; - - if (XextHasExtension(info)) { - xrri = (XRandRInfo *) info->data; - configs = xrri->config; - - if (configs[screen] == NULL) - configs[screen] = _XRRGetScreenInfo (dpy, RootWindow(dpy, screen)); - return configs[screen]; - } else { - return NULL; - } -} - -/* given a screen, return the information from the (possibly) cached data */ -Rotation XRRRotations(Display *dpy, int screen, Rotation *current_rotation) -{ - XRRScreenConfiguration *config; - Rotation cr; - LockDisplay(dpy); - if ((config = _XRRValidateCache(dpy, screen))) { - *current_rotation = config->current_rotation; - cr = config->rotations; - UnlockDisplay(dpy); - return cr; - } - else { - UnlockDisplay(dpy); - *current_rotation = RR_Rotate_0; - return 0; /* no rotations supported */ - } -} - -/* given a screen, return the information from the (possibly) cached data */ -XRRScreenSize *XRRSizes(Display *dpy, int screen, int *nsizes) -{ - XRRScreenConfiguration *config; - XRRScreenSize *sizes; - - LockDisplay(dpy); - if ((config = _XRRValidateCache(dpy, screen))) { - *nsizes = config->nsizes; - sizes = config->sizes; - UnlockDisplay(dpy); - return sizes; - } - else { - UnlockDisplay(dpy); - *nsizes = 0; - return NULL; - } -} - -short *XRRRates (Display *dpy, int screen, int sizeID, int *nrates) -{ - XRRScreenConfiguration *config; - short *rates; - - LockDisplay(dpy); - if ((config = _XRRValidateCache(dpy, screen))) { - rates = XRRConfigRates (config, sizeID, nrates); - UnlockDisplay(dpy); - return rates; - } - else { - UnlockDisplay(dpy); - *nrates = 0; - return NULL; - } -} - -/* given a screen, return the information from the (possibly) cached data */ -Time XRRTimes (Display *dpy, int screen, Time *config_timestamp) -{ - XRRScreenConfiguration *config; - Time ts; - - LockDisplay(dpy); - if ((config = _XRRValidateCache(dpy, screen))) { - *config_timestamp = config->config_timestamp; - ts = config->timestamp; - UnlockDisplay(dpy); - return ts; - } else { - UnlockDisplay(dpy); - return CurrentTime; - } -} int XRRRootToScreen(Display *dpy, Window root) { @@ -353,7 +285,7 @@ Bool XRRQueryExtension (Display *dpy, int *event_basep, int *error_basep) } } -static Bool +Bool _XRRHasRates (int major, int minor) { return major > 1 || (major == 1 && minor >= 1); @@ -398,14 +330,7 @@ Status XRRQueryVersion (Display *dpy, return 1; } -typedef struct _randrVersionState { - unsigned long version_seq; - Bool error; - int major_version; - int minor_version; -} _XRRVersionState; - -static Bool +Bool _XRRVersionHandler (Display *dpy, xReply *rep, char *buf, @@ -431,167 +356,6 @@ _XRRVersionHandler (Display *dpy, state->minor_version = repl->minorVersion; return True; } -/* need a version that does not hold the display lock */ -static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy, Window window) -{ - XExtDisplayInfo *info = XRRFindDisplay(dpy); - xRRGetScreenInfoReply rep; - xRRGetScreenInfoReq *req; - _XAsyncHandler async; - _XRRVersionState async_state; - int nbytes, nbytesRead, rbytes; - int i; - xScreenSizes size; - struct _XRRScreenConfiguration *scp; - XRRScreenSize *ssp; - short *rates; - xRRQueryVersionReq *vreq; - XRandRInfo *xrri; - Bool getting_version = False; - - RRCheckExtension (dpy, info, 0); - - xrri = (XRandRInfo *) info->data; - - if (xrri->major_version == -1) - { - /* hide a version query in the request */ - GetReq (RRQueryVersion, vreq); - vreq->reqType = info->codes->major_opcode; - vreq->randrReqType = X_RRQueryVersion; - vreq->majorVersion = RANDR_MAJOR; - vreq->minorVersion = RANDR_MINOR; - - async_state.version_seq = dpy->request; - async_state.error = False; - async.next = dpy->async_handlers; - async.handler = _XRRVersionHandler; - async.data = (XPointer) &async_state; - dpy->async_handlers = &async; - - getting_version = True; - } - - GetReq (RRGetScreenInfo, req); - req->reqType = info->codes->major_opcode; - req->randrReqType = X_RRGetScreenInfo; - req->window = window; - - if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) - { - if (getting_version) - DeqAsyncHandler (dpy, &async); - SyncHandle (); - return NULL; - } - if (getting_version) - { - DeqAsyncHandler (dpy, &async); - if (async_state.error) - { - SyncHandle(); - } - xrri->major_version = async_state.major_version; - xrri->minor_version = async_state.minor_version; - xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version); - } - - /* - * Make the reply compatible with v1.1 - */ - if (!xrri->has_rates) - { - rep.rate = 0; - rep.nrateEnts = 0; - } - - nbytes = (long) rep.length << 2; - - nbytesRead = (long) (rep.nSizes * SIZEOF (xScreenSizes) + - ((rep.nrateEnts + 1)& ~1) * 2 /* SIZEOF (CARD16) */); - - /* - * first we must compute how much space to allocate for - * randr library's use; we'll allocate the structures in a single - * allocation, on cleanlyness grounds. - */ - - rbytes = sizeof (XRRScreenConfiguration) + - (rep.nSizes * sizeof (XRRScreenSize) + - rep.nrateEnts * sizeof (int)); - - scp = (struct _XRRScreenConfiguration *) Xmalloc(rbytes); - if (scp == NULL) { - _XEatData (dpy, (unsigned long) nbytes); - SyncHandle (); - return NULL; - } - - - ssp = (XRRScreenSize *)(scp + 1); - rates = (short *) (ssp + rep.nSizes); - - /* set up the screen configuration structure */ - scp->screen = - ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root)); - - scp->sizes = ssp; - scp->rates = rates; - scp->rotations = rep.setOfRotations; - scp->current_size = rep.sizeID; - scp->current_rate = rep.rate; - scp->current_rotation = rep.rotation; - scp->timestamp = rep.timestamp; - scp->config_timestamp = rep.configTimestamp; - scp->nsizes = rep.nSizes; - scp->nrates = rep.nrateEnts; - - /* - * Time to unpack the data from the server. - */ - - /* - * First the size information - */ - for (i = 0; i < rep.nSizes; i++) { - _XReadPad (dpy, (char *) &size, SIZEOF (xScreenSizes)); - - ssp[i].width = size.widthInPixels; - ssp[i].height = size.heightInPixels; - ssp[i].mwidth = size.widthInMillimeters; - ssp[i].mheight = size.heightInMillimeters; - } - /* - * And the rates - */ - _XRead16Pad (dpy, rates, 2 /* SIZEOF (CARD16) */ * rep.nrateEnts); - - /* - * Skip any extra data - */ - if (nbytes > nbytesRead) - _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); - - return (XRRScreenConfiguration *)(scp); -} - -XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, Window window) -{ - XRRScreenConfiguration *config; - XRRFindDisplay(dpy); - LockDisplay (dpy); - config = _XRRGetScreenInfo(dpy, window); - UnlockDisplay (dpy); - SyncHandle (); - return config; -} - - -void XRRFreeScreenConfigInfo (XRRScreenConfiguration *config) -{ - Xfree (config); -} - /* * in protocol version 0.1, routine added to allow selecting for new events. @@ -616,78 +380,6 @@ void XRRSelectInput (Display *dpy, Window window, int mask) return; } -Status XRRSetScreenConfigAndRate (Display *dpy, - XRRScreenConfiguration *config, - Drawable draw, - int size_index, - Rotation rotation, - short rate, - Time timestamp) -{ - XExtDisplayInfo *info = XRRFindDisplay (dpy); - xRRSetScreenConfigReply rep; - XRandRInfo *xrri; - int major, minor; - - RRCheckExtension (dpy, info, 0); - - /* Make sure has_rates is set */ - if (!XRRQueryVersion (dpy, &major, &minor)) - return 0; - - LockDisplay (dpy); - xrri = (XRandRInfo *) info->data; - if (xrri->has_rates) - { - xRRSetScreenConfigReq *req; - GetReq (RRSetScreenConfig, req); - req->reqType = info->codes->major_opcode; - req->randrReqType = X_RRSetScreenConfig; - req->drawable = draw; - req->sizeID = size_index; - req->rotation = rotation; - req->timestamp = timestamp; - req->configTimestamp = config->config_timestamp; - req->rate = rate; - } - else - { - xRR1_0SetScreenConfigReq *req; - GetReq (RR1_0SetScreenConfig, req); - req->reqType = info->codes->major_opcode; - req->randrReqType = X_RRSetScreenConfig; - req->drawable = draw; - req->sizeID = size_index; - req->rotation = rotation; - req->timestamp = timestamp; - req->configTimestamp = config->config_timestamp; - } - - (void) _XReply (dpy, (xReply *) &rep, 0, xTrue); - - if (rep.status == RRSetConfigSuccess) { - /* if we succeed, set our view of reality to what we set it to */ - config->config_timestamp = rep.newConfigTimestamp; - config->timestamp = rep.newTimestamp; - config->screen = ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root)); - config->current_size = size_index; - config->current_rotation = rotation; - } - UnlockDisplay (dpy); - SyncHandle (); - return(rep.status); -} - -Status XRRSetScreenConfig (Display *dpy, - XRRScreenConfiguration *config, - Drawable draw, - int size_index, - Rotation rotation, Time timestamp) -{ - return XRRSetScreenConfigAndRate (dpy, config, draw, size_index, - rotation, 0, timestamp); -} - int XRRUpdateConfiguration(XEvent *event) { XRRScreenChangeNotifyEvent *scevent; diff --git a/src/Xrandrint.h b/src/Xrandrint.h index 78a8fcf..14675bd 100644 --- a/src/Xrandrint.h +++ b/src/Xrandrint.h @@ -84,4 +84,20 @@ typedef struct _XRandRInfo { Bool has_rates; /* Server supports refresh rates */ } XRandRInfo; +typedef struct _randrVersionState { + unsigned long version_seq; + Bool error; + int major_version; + int minor_version; +} _XRRVersionState; + +extern char XRRExtensionName[]; + +Bool +_XRRVersionHandler (Display *dpy, + xReply *rep, + char *buf, + int len, + XPointer data); + #endif /* _XRANDRINT_H_ */ diff --git a/src/XrrConfig.c b/src/XrrConfig.c new file mode 100644 index 0000000..577ccd6 --- /dev/null +++ b/src/XrrConfig.c @@ -0,0 +1,424 @@ +/* + * Copyright © 2000 Compaq Computer Corporation, Inc. + * Copyright © 2002 Hewlett Packard Company, Inc. + * 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. + * + * Author: Jim Gettys, HP Labs, HP. + * Author: Keith Packard, Intel Corporation + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <X11/Xlib.h> +/* we need to be able to manipulate the Display structure on events */ +#include <X11/Xlibint.h> +#include <X11/extensions/render.h> +#include <X11/extensions/Xrender.h> +#include "Xrandrint.h" + +static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy, Window window); + +Rotation XRRConfigRotations(XRRScreenConfiguration *config, Rotation *current_rotation) +{ + *current_rotation = config->current_rotation; + return config->rotations; +} + +XRRScreenSize *XRRConfigSizes(XRRScreenConfiguration *config, int *nsizes) +{ + *nsizes = config->nsizes; + return config->sizes; +} + +short *XRRConfigRates (XRRScreenConfiguration *config, int sizeID, int *nrates) +{ + short *r = config->rates; + int nents = config->nrates; + + /* Skip over the intervening rate lists */ + while (sizeID > 0 && nents > 0) + { + int i = (*r + 1); + r += i; + nents -= i; + sizeID--; + } + if (!nents) + { + *nrates = 0; + return 0; + } + *nrates = (int) *r; + return r + 1; +} + +Time XRRConfigTimes (XRRScreenConfiguration *config, Time *config_timestamp) +{ + *config_timestamp = config->config_timestamp; + return config->timestamp; +} + + +SizeID XRRConfigCurrentConfiguration (XRRScreenConfiguration *config, + Rotation *rotation) +{ + *rotation = (Rotation) config->current_rotation; + return (SizeID) config->current_size; +} + +short XRRConfigCurrentRate (XRRScreenConfiguration *config) +{ + return config->current_rate; +} + +/* + * Go get the screen configuration data and salt it away for future use; + * returns NULL if extension not supported + */ +static XRRScreenConfiguration *_XRRValidateCache (Display *dpy, int screen) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + XRRScreenConfiguration **configs; + XRandRInfo *xrri; + + if (XextHasExtension(info)) { + xrri = (XRandRInfo *) info->data; + configs = xrri->config; + + if (configs[screen] == NULL) + configs[screen] = _XRRGetScreenInfo (dpy, RootWindow(dpy, screen)); + return configs[screen]; + } else { + return NULL; + } +} + +/* given a screen, return the information from the (possibly) cached data */ +Rotation XRRRotations(Display *dpy, int screen, Rotation *current_rotation) +{ + XRRScreenConfiguration *config; + Rotation cr; + LockDisplay(dpy); + if ((config = _XRRValidateCache(dpy, screen))) { + *current_rotation = config->current_rotation; + cr = config->rotations; + UnlockDisplay(dpy); + return cr; + } + else { + UnlockDisplay(dpy); + *current_rotation = RR_Rotate_0; + return 0; /* no rotations supported */ + } +} + +/* given a screen, return the information from the (possibly) cached data */ +XRRScreenSize *XRRSizes(Display *dpy, int screen, int *nsizes) +{ + XRRScreenConfiguration *config; + XRRScreenSize *sizes; + + LockDisplay(dpy); + if ((config = _XRRValidateCache(dpy, screen))) { + *nsizes = config->nsizes; + sizes = config->sizes; + UnlockDisplay(dpy); + return sizes; + } + else { + UnlockDisplay(dpy); + *nsizes = 0; + return NULL; + } +} + +short *XRRRates (Display *dpy, int screen, int sizeID, int *nrates) +{ + XRRScreenConfiguration *config; + short *rates; + + LockDisplay(dpy); + if ((config = _XRRValidateCache(dpy, screen))) { + rates = XRRConfigRates (config, sizeID, nrates); + UnlockDisplay(dpy); + return rates; + } + else { + UnlockDisplay(dpy); + *nrates = 0; + return NULL; + } +} + +/* given a screen, return the information from the (possibly) cached data */ +Time XRRTimes (Display *dpy, int screen, Time *config_timestamp) +{ + XRRScreenConfiguration *config; + Time ts; + + LockDisplay(dpy); + if ((config = _XRRValidateCache(dpy, screen))) { + *config_timestamp = config->config_timestamp; + ts = config->timestamp; + UnlockDisplay(dpy); + return ts; + } else { + UnlockDisplay(dpy); + return CurrentTime; + } +} + +/* need a version that does not hold the display lock */ +static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy, Window window) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetScreenInfoReply rep; + xRRGetScreenInfoReq *req; + _XAsyncHandler async; + _XRRVersionState async_state; + int nbytes, nbytesRead, rbytes; + int i; + xScreenSizes size; + struct _XRRScreenConfiguration *scp; + XRRScreenSize *ssp; + short *rates; + xRRQueryVersionReq *vreq; + XRandRInfo *xrri; + Bool getting_version = False; + + RRCheckExtension (dpy, info, 0); + + xrri = (XRandRInfo *) info->data; + + if (xrri->major_version == -1) + { + /* hide a version query in the request */ + GetReq (RRQueryVersion, vreq); + vreq->reqType = info->codes->major_opcode; + vreq->randrReqType = X_RRQueryVersion; + vreq->majorVersion = RANDR_MAJOR; + vreq->minorVersion = RANDR_MINOR; + + async_state.version_seq = dpy->request; + async_state.error = False; + async.next = dpy->async_handlers; + async.handler = _XRRVersionHandler; + async.data = (XPointer) &async_state; + dpy->async_handlers = &async; + + getting_version = True; + } + + GetReq (RRGetScreenInfo, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetScreenInfo; + req->window = window; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + if (getting_version) + DeqAsyncHandler (dpy, &async); + SyncHandle (); + return NULL; + } + if (getting_version) + { + DeqAsyncHandler (dpy, &async); + if (async_state.error) + { + UnlockDisplay (dpy); + SyncHandle(); + LockDisplay (dpy); + } + xrri->major_version = async_state.major_version; + xrri->minor_version = async_state.minor_version; + xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version); + } + + /* + * Make the reply compatible with v1.1 + */ + if (!xrri->has_rates) + { + rep.rate = 0; + rep.nrateEnts = 0; + } + + nbytes = (long) rep.length << 2; + + nbytesRead = (long) (rep.nSizes * SIZEOF (xScreenSizes) + + ((rep.nrateEnts + 1)& ~1) * 2 /* SIZEOF (CARD16) */); + + /* + * first we must compute how much space to allocate for + * randr library's use; we'll allocate the structures in a single + * allocation, on cleanlyness grounds. + */ + + rbytes = sizeof (XRRScreenConfiguration) + + (rep.nSizes * sizeof (XRRScreenSize) + + rep.nrateEnts * sizeof (int)); + + scp = (struct _XRRScreenConfiguration *) Xmalloc(rbytes); + if (scp == NULL) { + _XEatData (dpy, (unsigned long) nbytes); + return NULL; + } + + + ssp = (XRRScreenSize *)(scp + 1); + rates = (short *) (ssp + rep.nSizes); + + /* set up the screen configuration structure */ + scp->screen = + ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root)); + + scp->sizes = ssp; + scp->rates = rates; + scp->rotations = rep.setOfRotations; + scp->current_size = rep.sizeID; + scp->current_rate = rep.rate; + scp->current_rotation = rep.rotation; + scp->timestamp = rep.timestamp; + scp->config_timestamp = rep.configTimestamp; + scp->nsizes = rep.nSizes; + scp->nrates = rep.nrateEnts; + + /* + * Time to unpack the data from the server. + */ + + /* + * First the size information + */ + for (i = 0; i < rep.nSizes; i++) { + _XReadPad (dpy, (char *) &size, SIZEOF (xScreenSizes)); + + ssp[i].width = size.widthInPixels; + ssp[i].height = size.heightInPixels; + ssp[i].mwidth = size.widthInMillimeters; + ssp[i].mheight = size.heightInMillimeters; + } + /* + * And the rates + */ + _XRead16Pad (dpy, rates, 2 /* SIZEOF (CARD16) */ * rep.nrateEnts); + + /* + * Skip any extra data + */ + if (nbytes > nbytesRead) + _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); + + return (XRRScreenConfiguration *)(scp); +} + +XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, Window window) +{ + XRRScreenConfiguration *config; + XRRFindDisplay(dpy); + LockDisplay (dpy); + config = _XRRGetScreenInfo(dpy, window); + UnlockDisplay (dpy); + SyncHandle (); + return config; +} + + +void XRRFreeScreenConfigInfo (XRRScreenConfiguration *config) +{ + Xfree (config); +} + +Status XRRSetScreenConfigAndRate (Display *dpy, + XRRScreenConfiguration *config, + Drawable draw, + int size_index, + Rotation rotation, + short rate, + Time timestamp) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + xRRSetScreenConfigReply rep; + XRandRInfo *xrri; + int major, minor; + + RRCheckExtension (dpy, info, 0); + + /* Make sure has_rates is set */ + if (!XRRQueryVersion (dpy, &major, &minor)) + return 0; + + LockDisplay (dpy); + xrri = (XRandRInfo *) info->data; + if (xrri->has_rates) + { + xRRSetScreenConfigReq *req; + GetReq (RRSetScreenConfig, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSetScreenConfig; + req->drawable = draw; + req->sizeID = size_index; + req->rotation = rotation; + req->timestamp = timestamp; + req->configTimestamp = config->config_timestamp; + req->rate = rate; + } + else + { + xRR1_0SetScreenConfigReq *req; + GetReq (RR1_0SetScreenConfig, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSetScreenConfig; + req->drawable = draw; + req->sizeID = size_index; + req->rotation = rotation; + req->timestamp = timestamp; + req->configTimestamp = config->config_timestamp; + } + + (void) _XReply (dpy, (xReply *) &rep, 0, xTrue); + + if (rep.status == RRSetConfigSuccess) { + /* if we succeed, set our view of reality to what we set it to */ + config->config_timestamp = rep.newConfigTimestamp; + config->timestamp = rep.newTimestamp; + config->screen = ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root)); + config->current_size = size_index; + config->current_rotation = rotation; + } + UnlockDisplay (dpy); + SyncHandle (); + return(rep.status); +} + +Status XRRSetScreenConfig (Display *dpy, + XRRScreenConfiguration *config, + Drawable draw, + int size_index, + Rotation rotation, Time timestamp) +{ + return XRRSetScreenConfigAndRate (dpy, config, draw, size_index, + rotation, 0, timestamp); +} diff --git a/src/XrrCrtc.c b/src/XrrCrtc.c new file mode 100644 index 0000000..a1372a1 --- /dev/null +++ b/src/XrrCrtc.c @@ -0,0 +1,178 @@ +/* + * 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 <config.h> +#endif + +#include <stdio.h> +#include <X11/Xlib.h> +/* we need to be able to manipulate the Display structure on events */ +#include <X11/Xlibint.h> +#include <X11/extensions/render.h> +#include <X11/extensions/Xrender.h> +#include "Xrandrint.h" + +XRRCrtcInfo * +XRRGetCrtcInfo (Display *dpy, XRRScreenResources *resources, RRCrtc crtc) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetCrtcInfoReply rep; + xRRGetCrtcInfoReq *req; + int nbytes, nbytesRead, rbytes; + int i; + XRRCrtcInfo *xci; + + RRCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (RRGetCrtcInfo, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetCrtcInfo; + req->crtc = crtc; + req->configTimestamp = resources->configTimestamp; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + nbytes = (long) rep.length << 2; + + nbytesRead = (long) (rep.nOutput * 4 + + rep.nPossibleOutput * 4); + + /* + * first we must compute how much space to allocate for + * randr library's use; we'll allocate the structures in a single + * allocation, on cleanlyness grounds. + */ + + rbytes = (sizeof (XRRCrtcInfo) + + rep.nOutput * sizeof (RROutput) + + rep.nPossibleOutput * sizeof (RROutput)); + + xci = (XRRCrtcInfo *) Xmalloc(rbytes); + if (xci == NULL) { + _XEatData (dpy, (unsigned long) nbytes); + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + xci->timestamp = rep.timestamp; + xci->x = rep.x; + xci->y = rep.y; + xci->width = rep.width; + xci->height = rep.height; + xci->mode = rep.mode; + xci->rotation = rep.rotation; + xci->noutput = rep.nOutput; + xci->outputs = (RROutput *) (xci + 1); + xci->npossible = rep.nPossibleOutput; + xci->possible = (RROutput *) (xci->outputs + rep.nOutput); + + _XRead32 (dpy, xci->outputs, rep.nOutput << 2); + _XRead32 (dpy, xci->possible, rep.nPossibleOutput << 2); + + /* + * Skip any extra data + */ + if (nbytes > nbytesRead) + _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); + + UnlockDisplay (dpy); + SyncHandle (); + return (XRRCrtcInfo *) xci; +} + +void +XRRFreeCrtcInfo (XRRCrtcInfo *crtcInfo) +{ + Xfree (crtcInfo); +} + +Status +XRRSetCrtcConfig (Display *dpy, + XRRScreenResources *resources, + RRCrtc crtc, + Time timestamp, + int x, int y, + RRMode mode, + Rotation rotation, + RROutput *outputs, + int noutputs) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRSetCrtcConfigReply rep; + xRRSetCrtcConfigReq *req; + int i; + + RRCheckExtension (dpy, info, 0); + + LockDisplay(dpy); + GetReq (RRSetCrtcConfig, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSetCrtcConfig; + req->length += noutputs; + req->crtc = crtc; + req->timestamp = timestamp; + req->configTimestamp = resources->configTimestamp; + req->x = x; + req->y = y; + req->mode = mode; + req->rotation = rotation; + Data32 (dpy, outputs, noutputs << 2); + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + rep.status = RRSetConfigFailed; + UnlockDisplay (dpy); + SyncHandle (); + return rep.status; +} + +int +XRRGetCrtcGammaSize (Display *dpy, RRCrtc crtc) +{ +} + +XRRCrtcGamma * +XRRGetCrtcGamma (Display *dpy, RRCrtc crtc) +{ +} + +XRRCrtcGamma * +XRRAllocGamma (int size) +{ +} + +void +XRRSetCrtcGamma (Display *dpy, RRCrtc crtc, XRRCrtcGamma *gamma) +{ +} + +void +XRRFreeGamma (XRRCrtcGamma *gamma) +{ +} diff --git a/src/XrrMode.c b/src/XrrMode.c new file mode 100644 index 0000000..65b60f9 --- /dev/null +++ b/src/XrrMode.c @@ -0,0 +1,63 @@ +/* + * 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 <config.h> +#endif + +#include <stdio.h> +#include <X11/Xlib.h> +/* we need to be able to manipulate the Display structure on events */ +#include <X11/Xlibint.h> +#include <X11/extensions/render.h> +#include <X11/extensions/Xrender.h> +#include "Xrandrint.h" + +XRRModeInfo * +XRRAllocModeInfo (char *name, int nameLength) +{ +} + +RRMode +XRRCreateMode (Display *dpy, Window window, XRRModeInfo *modeInfo) +{ +} + +void +XRRDestroyMode (Display *dpy, RRMode mode) +{ +} + +void +XRRAddOutputMode (Display *dpy, RROutput output, RRMode mode) +{ +} + +void +XRRDeleteOutputMode (Display *dpy, RROutput output, RRMode mode) +{ +} + +void +XRRFreeModeInfo (XRRModeInfo *modeInfo) +{ +} diff --git a/src/XrrOutput.c b/src/XrrOutput.c new file mode 100644 index 0000000..1fe03ae --- /dev/null +++ b/src/XrrOutput.c @@ -0,0 +1,131 @@ +/* + * 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 <config.h> +#endif + +#include <stdio.h> +#include <X11/Xlib.h> +/* we need to be able to manipulate the Display structure on events */ +#include <X11/Xlibint.h> +#include <X11/extensions/render.h> +#include <X11/extensions/Xrender.h> +#include "Xrandrint.h" + +#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) + +XRROutputInfo * +XRRGetOutputInfo (Display *dpy, XRRScreenResources *resources, RROutput output) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetOutputInfoReply rep; + xRRGetOutputInfoReq *req; + int nbytes, nbytesRead, rbytes; + int i; + xRRQueryVersionReq *vreq; + XRROutputInfo *xoi; + + RRCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (RRGetOutputInfo, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetOutputInfo; + req->output = output; + req->configTimestamp = resources->configTimestamp; + + if (!_XReply (dpy, (xReply *) &rep, OutputInfoExtra >> 2, xFalse)) + { + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + nbytes = ((long) (rep.length) << 2) - OutputInfoExtra; + + nbytesRead = (long) (rep.nCrtcs * 4 + + rep.nModes * 4 + + rep.nClones * 4 + + ((rep.nameLength + 3) & ~3)); + + /* + * first we must compute how much space to allocate for + * randr library's use; we'll allocate the structures in a single + * allocation, on cleanlyness grounds. + */ + + rbytes = (sizeof (XRROutputInfo) + + rep.nCrtcs * sizeof (RRCrtc) + + rep.nModes * sizeof (RRMode) + + rep.nClones * sizeof (RROutput) + + rep.nameLength + 1); /* '\0' terminate name */ + + xoi = (XRROutputInfo *) Xmalloc(rbytes); + if (xoi == NULL) { + _XEatData (dpy, (unsigned long) nbytes); + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + xoi->timestamp = rep.timestamp; + xoi->crtc = rep.crtc; + xoi->mm_width = rep.mmWidth; + xoi->mm_height = rep.mmHeight; + xoi->connection = rep.connection; + xoi->subpixel_order = rep.subpixelOrder; + xoi->ncrtc = rep.nCrtcs; + xoi->crtcs = (RRCrtc *) (xoi + 1); + xoi->nmode = rep.nModes; + xoi->npreferred = rep.nPreferred; + xoi->modes = (RRMode *) (xoi->crtcs + rep.nCrtcs); + xoi->nclone = rep.nClones; + xoi->clones = (RROutput *) (xoi->modes + rep.nModes); + xoi->name = (char *) (xoi->clones + rep.nClones); + + _XRead32 (dpy, xoi->crtcs, rep.nCrtcs << 2); + _XRead32 (dpy, xoi->modes, rep.nModes << 2); + _XRead32 (dpy, xoi->clones, rep.nClones << 2); + + /* + * Read name and '\0' terminate + */ + _XReadPad (dpy, xoi->name, rep.nameLength); + xoi->name[rep.nameLength] = '\0'; + + /* + * Skip any extra data + */ + if (nbytes > nbytesRead) + _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); + + UnlockDisplay (dpy); + SyncHandle (); + return (XRROutputInfo *) xoi; +} + +void +XRRFreeOutputInfo (XRROutputInfo *outputInfo) +{ + Xfree (outputInfo); +} 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 <config.h> +#endif + +#include <stdio.h> +#include <X11/Xlib.h> +/* we need to be able to manipulate the Display structure on events */ +#include <X11/Xlibint.h> +#include <X11/extensions/render.h> +#include <X11/extensions/Xrender.h> +#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; +} diff --git a/src/XrrScreen.c b/src/XrrScreen.c new file mode 100644 index 0000000..c9f5204 --- /dev/null +++ b/src/XrrScreen.c @@ -0,0 +1,246 @@ +/* + * 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 <config.h> +#endif + +#include <stdio.h> +#include <X11/Xlib.h> +/* we need to be able to manipulate the Display structure on events */ +#include <X11/Xlibint.h> +#include <X11/extensions/render.h> +#include <X11/extensions/Xrender.h> +#include "Xrandrint.h" + +XRRScreenResources * +XRRGetScreenResources (Display *dpy, Window window) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetScreenResourcesReply rep; + xRRGetScreenResourcesReq *req; + _XAsyncHandler async; + _XRRVersionState async_state; + int nbytes, nbytesRead, rbytes; + int i; + xRRQueryVersionReq *vreq; + XRRScreenResources *xrsr; + char *names; + char *wire_names, *wire_name; + Bool getting_version = False; + XRandRInfo *xrri; + + RRCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + xrri = (XRandRInfo *) info->data; + + if (xrri->major_version == -1) + { + /* hide a version query in the request */ + GetReq (RRQueryVersion, vreq); + vreq->reqType = info->codes->major_opcode; + vreq->randrReqType = X_RRQueryVersion; + vreq->majorVersion = RANDR_MAJOR; + vreq->minorVersion = RANDR_MINOR; + + async_state.version_seq = dpy->request; + async_state.error = False; + async.next = dpy->async_handlers; + async.handler = _XRRVersionHandler; + async.data = (XPointer) &async_state; + dpy->async_handlers = &async; + + getting_version = True; + } + + GetReq (RRGetScreenResources, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetScreenResources; + req->window = window; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + if (getting_version) + DeqAsyncHandler (dpy, &async); + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + if (getting_version) + { + DeqAsyncHandler (dpy, &async); + if (async_state.error) + { + UnlockDisplay (dpy); + SyncHandle(); + LockDisplay (dpy); + } + xrri->major_version = async_state.major_version; + xrri->minor_version = async_state.minor_version; + xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version); + } + + nbytes = (long) rep.length << 2; + + nbytesRead = (long) (rep.nCrtcs * 4 + + rep.nOutputs * 4 + + rep.nModes * SIZEOF (xRRModeInfo) + + ((rep.nbytesNames + 3) & ~3)); + + /* + * first we must compute how much space to allocate for + * randr library's use; we'll allocate the structures in a single + * allocation, on cleanlyness grounds. + */ + + rbytes = (sizeof (XRRScreenResources) + + rep.nCrtcs * sizeof (RRCrtc) + + rep.nOutputs * sizeof (RROutput) + + rep.nModes * sizeof (XRRModeInfo) + + rep.nbytesNames + rep.nModes); /* '\0' terminate names */ + + xrsr = (XRRScreenResources *) Xmalloc(rbytes); + wire_names = (char *) Xmalloc (rep.nbytesNames); + if (xrsr == NULL || wire_names == NULL) { + if (xrsr) Xfree (xrsr); + if (wire_names) Xfree (wire_names); + _XEatData (dpy, (unsigned long) nbytes); + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + xrsr->timestamp = rep.timestamp; + xrsr->configTimestamp = rep.configTimestamp; + xrsr->ncrtc = rep.nCrtcs; + xrsr->crtcs = (RRCrtc *) (xrsr + 1); + xrsr->noutput = rep.nOutputs; + xrsr->outputs = (RROutput *) (xrsr->crtcs + rep.nCrtcs); + xrsr->nmode = rep.nModes; + xrsr->modes = (XRRModeInfo *) (xrsr->outputs + rep.nOutputs); + names = (char *) (xrsr->modes + rep.nModes); + + _XRead32 (dpy, xrsr->crtcs, rep.nCrtcs << 2); + _XRead32 (dpy, xrsr->outputs, rep.nOutputs << 2); + + for (i = 0; i < rep.nModes; i++) { + xRRModeInfo modeInfo; + + _XReadPad (dpy, (char *) &modeInfo, SIZEOF (xRRModeInfo)); + xrsr->modes[i].id = modeInfo.id; + xrsr->modes[i].width = modeInfo.width; + xrsr->modes[i].height = modeInfo.height; + xrsr->modes[i].dotClock = modeInfo.dotClock; + xrsr->modes[i].hSyncStart = modeInfo.hSyncStart; + xrsr->modes[i].hSyncEnd = modeInfo.hSyncEnd; + xrsr->modes[i].hTotal = modeInfo.hTotal; + xrsr->modes[i].hSkew = modeInfo.hSkew; + xrsr->modes[i].vSyncStart = modeInfo.vSyncStart; + xrsr->modes[i].vSyncEnd = modeInfo.vSyncEnd; + xrsr->modes[i].vTotal = modeInfo.vTotal; + xrsr->modes[i].nameLength = modeInfo.nameLength; + xrsr->modes[i].modeFlags = modeInfo.modeFlags; + } + + /* + * Read names and '\0' pad each one + */ + _XReadPad (dpy, wire_names, rep.nbytesNames); + wire_name = wire_names; + for (i = 0; i < rep.nModes; i++) { + xrsr->modes[i].name = names; + memcpy (names, wire_name, xrsr->modes[i].nameLength); + names[xrsr->modes[i].nameLength] = '\0'; + names += xrsr->modes[i].nameLength + 1; + wire_name += xrsr->modes[i].nameLength; + } + Xfree (wire_names); + + /* + * Skip any extra data + */ + if (nbytes > nbytesRead) + _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); + + UnlockDisplay (dpy); + SyncHandle(); + return (XRRScreenResources *) xrsr; +} + +void +XRRFreeScreenResources (XRRScreenResources *resources) +{ + Xfree (resources); +} + +Status +XRRGetScreenSizeRange (Display *dpy, Window window, + int *minWidth, int *minHeight, + int *maxWidth, int *maxHeight) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetScreenSizeRangeReq *req; + xRRGetScreenSizeRangeReply rep; + + RRCheckExtension (dpy, info, 0); + LockDisplay (dpy); + GetReq (RRGetScreenSizeRange, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetScreenSizeRange; + req->window = window; + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + UnlockDisplay (dpy); + SyncHandle (); + *minWidth = rep.minWidth; + *minHeight = rep.minHeight; + *maxWidth = rep.maxWidth; + *maxHeight = rep.maxHeight; + return True; +} + +void +XRRSetScreenSize (Display *dpy, Window window, + int width, int height, + int mmWidth, int mmHeight) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRSetScreenSizeReq *req; + + RRSimpleCheckExtension (dpy, info); + LockDisplay (dpy); + GetReq (RRSetScreenSize, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSetScreenSize; + req->window = window; + req->width = width; + req->height = height; + req->widthInMillimeters = mmWidth; + req->heightInMillimeters = mmHeight; + UnlockDisplay (dpy); + SyncHandle (); +} |