2 * Copyright © 2006 Keith Packard
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.
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
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"
36 * this is cheating on the knowledge that the two requests are identical
37 * but for the request number.
39 static XRRScreenResources *
40 doGetScreenResources (Display *dpy, Window window, int poll)
42 XExtDisplayInfo *info = XRRFindDisplay(dpy);
43 xRRGetScreenResourcesReply rep;
44 xRRGetScreenResourcesReq *req;
46 _XRRVersionState async_state;
47 int nbytes, nbytesRead, rbytes;
49 xRRQueryVersionReq *vreq;
50 XRRScreenResources *xrsr;
52 char *wire_names, *wire_name;
53 Bool getting_version = False;
56 RRCheckExtension (dpy, info, NULL);
59 xrri = (XRandRInfo *) info->data;
61 if (xrri->major_version == -1)
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;
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;
77 getting_version = True;
80 GetReq (RRGetScreenResources, req);
81 req->reqType = info->codes->major_opcode;
82 req->randrReqType = poll ? X_RRGetScreenResources
83 : X_RRGetScreenResourcesCurrent;
86 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
89 DeqAsyncHandler (dpy, &async);
96 DeqAsyncHandler (dpy, &async);
97 if (async_state.error)
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);
108 nbytes = (long) rep.length << 2;
110 nbytesRead = (long) (rep.nCrtcs * 4 +
112 rep.nModes * SIZEOF (xRRModeInfo) +
113 ((rep.nbytesNames + 3) & ~3));
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.
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 */
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 _XEatData (dpy, (unsigned long) nbytes);
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);
148 _XRead32 (dpy, xrsr->crtcs, rep.nCrtcs << 2);
149 _XRead32 (dpy, xrsr->outputs, rep.nOutputs << 2);
151 for (i = 0; i < rep.nModes; i++) {
152 xRRModeInfo modeInfo;
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;
171 * Read names and '\0' pad each one
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;
185 * Skip any extra data
187 if (nbytes > nbytesRead)
188 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
192 return (XRRScreenResources *) xrsr;
196 XRRGetScreenResources(Display *dpy, Window window)
198 return doGetScreenResources(dpy, window, 1);
202 XRRGetScreenResourcesCurrent(Display *dpy, Window window)
204 return doGetScreenResources(dpy, window, 0);
208 XRRFreeScreenResources (XRRScreenResources *resources)
214 XRRGetScreenSizeRange (Display *dpy, Window window,
215 int *minWidth, int *minHeight,
216 int *maxWidth, int *maxHeight)
218 XExtDisplayInfo *info = XRRFindDisplay(dpy);
219 xRRGetScreenSizeRangeReq *req;
220 xRRGetScreenSizeRangeReply rep;
222 RRCheckExtension (dpy, info, 0);
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))
236 *minWidth = rep.minWidth;
237 *minHeight = rep.minHeight;
238 *maxWidth = rep.maxWidth;
239 *maxHeight = rep.maxHeight;
244 XRRSetScreenSize (Display *dpy, Window window,
245 int width, int height,
246 int mmWidth, int mmHeight)
248 XExtDisplayInfo *info = XRRFindDisplay(dpy);
249 xRRSetScreenSizeReq *req;
251 RRSimpleCheckExtension (dpy, info);
253 GetReq (RRSetScreenSize, req);
254 req->reqType = info->codes->major_opcode;
255 req->randrReqType = X_RRSetScreenSize;
256 req->window = window;
258 req->height = height;
259 req->widthInMillimeters = mmWidth;
260 req->heightInMillimeters = mmHeight;