XrrScreen.c revision b042e37f
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 35XRRScreenResources * 36XRRGetScreenResources (Display *dpy, Window window) 37{ 38 XExtDisplayInfo *info = XRRFindDisplay(dpy); 39 xRRGetScreenResourcesReply rep; 40 xRRGetScreenResourcesReq *req; 41 _XAsyncHandler async; 42 _XRRVersionState async_state; 43 int nbytes, nbytesRead, rbytes; 44 int i; 45 xRRQueryVersionReq *vreq; 46 XRRScreenResources *xrsr; 47 char *names; 48 char *wire_names, *wire_name; 49 Bool getting_version = False; 50 XRandRInfo *xrri; 51 52 RRCheckExtension (dpy, info, 0); 53 54 LockDisplay (dpy); 55 xrri = (XRandRInfo *) info->data; 56 57 if (xrri->major_version == -1) 58 { 59 /* hide a version query in the request */ 60 GetReq (RRQueryVersion, vreq); 61 vreq->reqType = info->codes->major_opcode; 62 vreq->randrReqType = X_RRQueryVersion; 63 vreq->majorVersion = RANDR_MAJOR; 64 vreq->minorVersion = RANDR_MINOR; 65 66 async_state.version_seq = dpy->request; 67 async_state.error = False; 68 async.next = dpy->async_handlers; 69 async.handler = _XRRVersionHandler; 70 async.data = (XPointer) &async_state; 71 dpy->async_handlers = &async; 72 73 getting_version = True; 74 } 75 76 GetReq (RRGetScreenResources, req); 77 req->reqType = info->codes->major_opcode; 78 req->randrReqType = X_RRGetScreenResources; 79 req->window = window; 80 81 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 82 { 83 if (getting_version) 84 DeqAsyncHandler (dpy, &async); 85 UnlockDisplay (dpy); 86 SyncHandle (); 87 return NULL; 88 } 89 if (getting_version) 90 { 91 DeqAsyncHandler (dpy, &async); 92 if (async_state.error) 93 { 94 UnlockDisplay (dpy); 95 SyncHandle(); 96 LockDisplay (dpy); 97 } 98 xrri->major_version = async_state.major_version; 99 xrri->minor_version = async_state.minor_version; 100 xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version); 101 } 102 103 nbytes = (long) rep.length << 2; 104 105 nbytesRead = (long) (rep.nCrtcs * 4 + 106 rep.nOutputs * 4 + 107 rep.nModes * SIZEOF (xRRModeInfo) + 108 ((rep.nbytesNames + 3) & ~3)); 109 110 /* 111 * first we must compute how much space to allocate for 112 * randr library's use; we'll allocate the structures in a single 113 * allocation, on cleanlyness grounds. 114 */ 115 116 rbytes = (sizeof (XRRScreenResources) + 117 rep.nCrtcs * sizeof (RRCrtc) + 118 rep.nOutputs * sizeof (RROutput) + 119 rep.nModes * sizeof (XRRModeInfo) + 120 rep.nbytesNames + rep.nModes); /* '\0' terminate names */ 121 122 xrsr = (XRRScreenResources *) Xmalloc(rbytes); 123 wire_names = (char *) Xmalloc (rep.nbytesNames); 124 if (xrsr == NULL || wire_names == NULL) { 125 if (xrsr) Xfree (xrsr); 126 if (wire_names) Xfree (wire_names); 127 _XEatData (dpy, (unsigned long) nbytes); 128 UnlockDisplay (dpy); 129 SyncHandle (); 130 return NULL; 131 } 132 133 xrsr->timestamp = rep.timestamp; 134 xrsr->configTimestamp = rep.configTimestamp; 135 xrsr->ncrtc = rep.nCrtcs; 136 xrsr->crtcs = (RRCrtc *) (xrsr + 1); 137 xrsr->noutput = rep.nOutputs; 138 xrsr->outputs = (RROutput *) (xrsr->crtcs + rep.nCrtcs); 139 xrsr->nmode = rep.nModes; 140 xrsr->modes = (XRRModeInfo *) (xrsr->outputs + rep.nOutputs); 141 names = (char *) (xrsr->modes + rep.nModes); 142 143 _XRead32 (dpy, xrsr->crtcs, rep.nCrtcs << 2); 144 _XRead32 (dpy, xrsr->outputs, rep.nOutputs << 2); 145 146 for (i = 0; i < rep.nModes; i++) { 147 xRRModeInfo modeInfo; 148 149 _XReadPad (dpy, (char *) &modeInfo, SIZEOF (xRRModeInfo)); 150 xrsr->modes[i].id = modeInfo.id; 151 xrsr->modes[i].width = modeInfo.width; 152 xrsr->modes[i].height = modeInfo.height; 153 xrsr->modes[i].dotClock = modeInfo.dotClock; 154 xrsr->modes[i].hSyncStart = modeInfo.hSyncStart; 155 xrsr->modes[i].hSyncEnd = modeInfo.hSyncEnd; 156 xrsr->modes[i].hTotal = modeInfo.hTotal; 157 xrsr->modes[i].hSkew = modeInfo.hSkew; 158 xrsr->modes[i].vSyncStart = modeInfo.vSyncStart; 159 xrsr->modes[i].vSyncEnd = modeInfo.vSyncEnd; 160 xrsr->modes[i].vTotal = modeInfo.vTotal; 161 xrsr->modes[i].nameLength = modeInfo.nameLength; 162 xrsr->modes[i].modeFlags = modeInfo.modeFlags; 163 } 164 165 /* 166 * Read names and '\0' pad each one 167 */ 168 _XReadPad (dpy, wire_names, rep.nbytesNames); 169 wire_name = wire_names; 170 for (i = 0; i < rep.nModes; i++) { 171 xrsr->modes[i].name = names; 172 memcpy (names, wire_name, xrsr->modes[i].nameLength); 173 names[xrsr->modes[i].nameLength] = '\0'; 174 names += xrsr->modes[i].nameLength + 1; 175 wire_name += xrsr->modes[i].nameLength; 176 } 177 Xfree (wire_names); 178 179 /* 180 * Skip any extra data 181 */ 182 if (nbytes > nbytesRead) 183 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 184 185 UnlockDisplay (dpy); 186 SyncHandle(); 187 return (XRRScreenResources *) xrsr; 188} 189 190void 191XRRFreeScreenResources (XRRScreenResources *resources) 192{ 193 Xfree (resources); 194} 195 196Status 197XRRGetScreenSizeRange (Display *dpy, Window window, 198 int *minWidth, int *minHeight, 199 int *maxWidth, int *maxHeight) 200{ 201 XExtDisplayInfo *info = XRRFindDisplay(dpy); 202 xRRGetScreenSizeRangeReq *req; 203 xRRGetScreenSizeRangeReply rep; 204 205 RRCheckExtension (dpy, info, 0); 206 LockDisplay (dpy); 207 GetReq (RRGetScreenSizeRange, req); 208 req->reqType = info->codes->major_opcode; 209 req->randrReqType = X_RRGetScreenSizeRange; 210 req->window = window; 211 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 212 { 213 UnlockDisplay (dpy); 214 SyncHandle (); 215 return False; 216 } 217 UnlockDisplay (dpy); 218 SyncHandle (); 219 *minWidth = rep.minWidth; 220 *minHeight = rep.minHeight; 221 *maxWidth = rep.maxWidth; 222 *maxHeight = rep.maxHeight; 223 return True; 224} 225 226void 227XRRSetScreenSize (Display *dpy, Window window, 228 int width, int height, 229 int mmWidth, int mmHeight) 230{ 231 XExtDisplayInfo *info = XRRFindDisplay(dpy); 232 xRRSetScreenSizeReq *req; 233 234 RRSimpleCheckExtension (dpy, info); 235 LockDisplay (dpy); 236 GetReq (RRSetScreenSize, req); 237 req->reqType = info->codes->major_opcode; 238 req->randrReqType = X_RRSetScreenSize; 239 req->window = window; 240 req->width = width; 241 req->height = height; 242 req->widthInMillimeters = mmWidth; 243 req->heightInMillimeters = mmHeight; 244 UnlockDisplay (dpy); 245 SyncHandle (); 246} 247