XrrScreen.c revision 67594505
1/* 2 * Copyright © 2006 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include <config.h> 25#endif 26 27#include <stdio.h> 28#include <X11/Xlib.h> 29/* we need to be able to manipulate the Display structure on events */ 30#include <X11/Xlibint.h> 31#include <X11/extensions/render.h> 32#include <X11/extensions/Xrender.h> 33#include "Xrandrint.h" 34 35/* 36 * this is cheating on the knowledge that the two requests are identical 37 * but for the request number. 38 */ 39static XRRScreenResources * 40doGetScreenResources (Display *dpy, Window window, int poll) 41{ 42 XExtDisplayInfo *info = XRRFindDisplay(dpy); 43 xRRGetScreenResourcesReply rep; 44 xRRGetScreenResourcesReq *req; 45 _XAsyncHandler async; 46 _XRRVersionState async_state; 47 int nbytes, nbytesRead, rbytes; 48 int i; 49 xRRQueryVersionReq *vreq; 50 XRRScreenResources *xrsr; 51 char *names; 52 char *wire_names, *wire_name; 53 Bool getting_version = False; 54 XRandRInfo *xrri; 55 56 RRCheckExtension (dpy, info, NULL); 57 58 LockDisplay (dpy); 59 xrri = (XRandRInfo *) info->data; 60 61 if (xrri->major_version == -1) 62 { 63 /* hide a version query in the request */ 64 GetReq (RRQueryVersion, vreq); 65 vreq->reqType = info->codes->major_opcode; 66 vreq->randrReqType = X_RRQueryVersion; 67 vreq->majorVersion = RANDR_MAJOR; 68 vreq->minorVersion = RANDR_MINOR; 69 70 async_state.version_seq = dpy->request; 71 async_state.error = False; 72 async.next = dpy->async_handlers; 73 async.handler = _XRRVersionHandler; 74 async.data = (XPointer) &async_state; 75 dpy->async_handlers = &async; 76 77 getting_version = True; 78 } 79 80 GetReq (RRGetScreenResources, req); 81 req->reqType = info->codes->major_opcode; 82 req->randrReqType = poll ? X_RRGetScreenResources 83 : X_RRGetScreenResourcesCurrent; 84 req->window = window; 85 86 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 87 { 88 if (getting_version) 89 DeqAsyncHandler (dpy, &async); 90 UnlockDisplay (dpy); 91 SyncHandle (); 92 return NULL; 93 } 94 if (getting_version) 95 { 96 DeqAsyncHandler (dpy, &async); 97 if (async_state.error) 98 { 99 UnlockDisplay (dpy); 100 SyncHandle(); 101 LockDisplay (dpy); 102 } 103 xrri->major_version = async_state.major_version; 104 xrri->minor_version = async_state.minor_version; 105 xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version); 106 } 107 108 nbytes = (long) rep.length << 2; 109 110 nbytesRead = (long) (rep.nCrtcs * 4 + 111 rep.nOutputs * 4 + 112 rep.nModes * SIZEOF (xRRModeInfo) + 113 ((rep.nbytesNames + 3) & ~3)); 114 115 /* 116 * first we must compute how much space to allocate for 117 * randr library's use; we'll allocate the structures in a single 118 * allocation, on cleanlyness grounds. 119 */ 120 121 rbytes = (sizeof (XRRScreenResources) + 122 rep.nCrtcs * sizeof (RRCrtc) + 123 rep.nOutputs * sizeof (RROutput) + 124 rep.nModes * sizeof (XRRModeInfo) + 125 rep.nbytesNames + rep.nModes); /* '\0' terminate names */ 126 127 xrsr = (XRRScreenResources *) Xmalloc(rbytes); 128 wire_names = (char *) Xmalloc (rep.nbytesNames); 129 if (xrsr == NULL || wire_names == NULL) { 130 if (xrsr) Xfree (xrsr); 131 if (wire_names) Xfree (wire_names); 132 _XEatDataWords (dpy, rep.length); 133 UnlockDisplay (dpy); 134 SyncHandle (); 135 return NULL; 136 } 137 138 xrsr->timestamp = rep.timestamp; 139 xrsr->configTimestamp = rep.configTimestamp; 140 xrsr->ncrtc = rep.nCrtcs; 141 xrsr->crtcs = (RRCrtc *) (xrsr + 1); 142 xrsr->noutput = rep.nOutputs; 143 xrsr->outputs = (RROutput *) (xrsr->crtcs + rep.nCrtcs); 144 xrsr->nmode = rep.nModes; 145 xrsr->modes = (XRRModeInfo *) (xrsr->outputs + rep.nOutputs); 146 names = (char *) (xrsr->modes + rep.nModes); 147 148 _XRead32 (dpy, (long *) xrsr->crtcs, rep.nCrtcs << 2); 149 _XRead32 (dpy, (long *) xrsr->outputs, rep.nOutputs << 2); 150 151 for (i = 0; i < rep.nModes; i++) { 152 xRRModeInfo modeInfo; 153 154 _XReadPad (dpy, (char *) &modeInfo, SIZEOF (xRRModeInfo)); 155 xrsr->modes[i].id = modeInfo.id; 156 xrsr->modes[i].width = modeInfo.width; 157 xrsr->modes[i].height = modeInfo.height; 158 xrsr->modes[i].dotClock = modeInfo.dotClock; 159 xrsr->modes[i].hSyncStart = modeInfo.hSyncStart; 160 xrsr->modes[i].hSyncEnd = modeInfo.hSyncEnd; 161 xrsr->modes[i].hTotal = modeInfo.hTotal; 162 xrsr->modes[i].hSkew = modeInfo.hSkew; 163 xrsr->modes[i].vSyncStart = modeInfo.vSyncStart; 164 xrsr->modes[i].vSyncEnd = modeInfo.vSyncEnd; 165 xrsr->modes[i].vTotal = modeInfo.vTotal; 166 xrsr->modes[i].nameLength = modeInfo.nameLength; 167 xrsr->modes[i].modeFlags = modeInfo.modeFlags; 168 } 169 170 /* 171 * Read names and '\0' pad each one 172 */ 173 _XReadPad (dpy, wire_names, rep.nbytesNames); 174 wire_name = wire_names; 175 for (i = 0; i < rep.nModes; i++) { 176 xrsr->modes[i].name = names; 177 memcpy (names, wire_name, xrsr->modes[i].nameLength); 178 names[xrsr->modes[i].nameLength] = '\0'; 179 names += xrsr->modes[i].nameLength + 1; 180 wire_name += xrsr->modes[i].nameLength; 181 } 182 Xfree (wire_names); 183 184 /* 185 * Skip any extra data 186 */ 187 if (nbytes > nbytesRead) 188 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 189 190 UnlockDisplay (dpy); 191 SyncHandle(); 192 return (XRRScreenResources *) xrsr; 193} 194 195XRRScreenResources * 196XRRGetScreenResources(Display *dpy, Window window) 197{ 198 return doGetScreenResources(dpy, window, 1); 199} 200 201XRRScreenResources * 202XRRGetScreenResourcesCurrent(Display *dpy, Window window) 203{ 204 return doGetScreenResources(dpy, window, 0); 205} 206 207void 208XRRFreeScreenResources (XRRScreenResources *resources) 209{ 210 Xfree (resources); 211} 212 213Status 214XRRGetScreenSizeRange (Display *dpy, Window window, 215 int *minWidth, int *minHeight, 216 int *maxWidth, int *maxHeight) 217{ 218 XExtDisplayInfo *info = XRRFindDisplay(dpy); 219 xRRGetScreenSizeRangeReq *req; 220 xRRGetScreenSizeRangeReply rep; 221 222 RRCheckExtension (dpy, info, 0); 223 LockDisplay (dpy); 224 GetReq (RRGetScreenSizeRange, req); 225 req->reqType = info->codes->major_opcode; 226 req->randrReqType = X_RRGetScreenSizeRange; 227 req->window = window; 228 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 229 { 230 UnlockDisplay (dpy); 231 SyncHandle (); 232 return False; 233 } 234 UnlockDisplay (dpy); 235 SyncHandle (); 236 *minWidth = rep.minWidth; 237 *minHeight = rep.minHeight; 238 *maxWidth = rep.maxWidth; 239 *maxHeight = rep.maxHeight; 240 return True; 241} 242 243void 244XRRSetScreenSize (Display *dpy, Window window, 245 int width, int height, 246 int mmWidth, int mmHeight) 247{ 248 XExtDisplayInfo *info = XRRFindDisplay(dpy); 249 xRRSetScreenSizeReq *req; 250 251 RRSimpleCheckExtension (dpy, info); 252 LockDisplay (dpy); 253 GetReq (RRSetScreenSize, req); 254 req->reqType = info->codes->major_opcode; 255 req->randrReqType = X_RRSetScreenSize; 256 req->window = window; 257 req->width = width; 258 req->height = height; 259 req->widthInMillimeters = mmWidth; 260 req->heightInMillimeters = mmHeight; 261 UnlockDisplay (dpy); 262 SyncHandle (); 263} 264