upload tizen1.0 source
[framework/uifw/xorg/lib/libxrandr.git] / src / XrrScreen.c
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  */
39 static XRRScreenResources *
40 doGetScreenResources (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         _XEatData (dpy, (unsigned long) nbytes);
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, xrsr->crtcs, rep.nCrtcs << 2);
149     _XRead32 (dpy, 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
195 XRRScreenResources *
196 XRRGetScreenResources(Display *dpy, Window window)
197 {
198     return doGetScreenResources(dpy, window, 1);
199 }
200
201 XRRScreenResources *
202 XRRGetScreenResourcesCurrent(Display *dpy, Window window)
203 {
204     return doGetScreenResources(dpy, window, 0);
205 }
206
207 void
208 XRRFreeScreenResources (XRRScreenResources *resources)
209 {
210     Xfree (resources);
211 }
212
213 Status
214 XRRGetScreenSizeRange (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
243 void
244 XRRSetScreenSize (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 }