upload tizen1.0 source
[framework/uifw/xorg/lib/libxrandr.git] / src / XrrConfig.c
1 /*
2  * Copyright © 2000 Compaq Computer Corporation, Inc.
3  * Copyright © 2002 Hewlett Packard Company, Inc.
4  * Copyright © 2006 Keith Packard
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that copyright
9  * notice and this permission notice appear in supporting documentation, and
10  * that the name of the copyright holders not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  The copyright holders make no representations
13  * about the suitability of this software for any purpose.  It is provided "as
14  * is" without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22  * OF THIS SOFTWARE.
23  *
24  * Author:  Jim Gettys, HP Labs, HP.
25  * Author:  Keith Packard, Intel Corporation
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <stdio.h>
33 #include <X11/Xlib.h>
34 /* we need to be able to manipulate the Display structure on events */
35 #include <X11/Xlibint.h>
36 #include <X11/extensions/render.h>
37 #include <X11/extensions/Xrender.h>
38 #include "Xrandrint.h"
39
40 static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy,
41                                                   XExtDisplayInfo *info,
42                                                   Window window);
43
44 Rotation XRRConfigRotations(XRRScreenConfiguration *config, Rotation *current_rotation)
45 {
46   *current_rotation = config->current_rotation;
47   return config->rotations;
48 }
49
50 XRRScreenSize *XRRConfigSizes(XRRScreenConfiguration *config, int *nsizes)
51 {
52    *nsizes = config->nsizes;
53   return config->sizes;
54 }
55
56 short *XRRConfigRates (XRRScreenConfiguration *config, int sizeID, int *nrates)
57 {
58     short   *r = config->rates;
59     int     nents = config->nrates;
60
61     /* Skip over the intervening rate lists */
62     while (sizeID > 0 && nents > 0)
63     {
64         int i = (*r + 1);
65         r += i;
66         nents -= i;
67         sizeID--;
68     }
69     if (!nents)
70     {
71         *nrates = 0;
72         return NULL;
73     }
74     *nrates = (int) *r;
75     return r + 1;
76 }
77
78 Time XRRConfigTimes (XRRScreenConfiguration *config, Time *config_timestamp)
79 {
80     *config_timestamp = config->config_timestamp;
81     return config->timestamp;
82 }
83
84
85 SizeID XRRConfigCurrentConfiguration (XRRScreenConfiguration *config, 
86                               Rotation *rotation)
87 {
88     *rotation = (Rotation) config->current_rotation;
89     return (SizeID) config->current_size;
90 }
91
92 short XRRConfigCurrentRate (XRRScreenConfiguration *config)
93 {
94     return config->current_rate;
95 }
96
97 /* 
98  * Go get the screen configuration data and salt it away for future use; 
99  * returns NULL if extension not supported
100  */
101 static XRRScreenConfiguration *_XRRValidateCache (Display *dpy, 
102                                                   XExtDisplayInfo *info,
103                                                   int screen)
104 {
105     XRRScreenConfiguration **configs;
106     XRandRInfo *xrri;
107
108     if ((screen >= 0) && (screen < ScreenCount(dpy)) && XextHasExtension(info)) {
109         xrri = (XRandRInfo *) info->data;
110         configs = xrri->config;
111
112         if (configs[screen] == NULL)
113             configs[screen] = _XRRGetScreenInfo (dpy, info, RootWindow(dpy, screen));
114         return configs[screen];
115     } else {
116         return NULL;
117     }
118 }
119
120 /* given a screen, return the information from the (possibly) cached data */
121 Rotation XRRRotations(Display *dpy, int screen, Rotation *current_rotation)
122 {
123   XRRScreenConfiguration *config;
124   XExtDisplayInfo *info = XRRFindDisplay(dpy);
125   Rotation cr;
126   LockDisplay(dpy);
127   if ((config = _XRRValidateCache(dpy, info, screen))) {
128     *current_rotation = config->current_rotation;
129     cr = config->rotations;
130     UnlockDisplay(dpy);
131     return cr;
132   }
133   else {
134     UnlockDisplay(dpy);
135     *current_rotation = RR_Rotate_0;
136     return 0;   /* no rotations supported */
137   }
138 }
139
140 /* given a screen, return the information from the (possibly) cached data */
141 XRRScreenSize *XRRSizes(Display *dpy, int screen, int *nsizes)
142 {
143   XRRScreenConfiguration *config; 
144   XExtDisplayInfo *info = XRRFindDisplay(dpy);
145   XRRScreenSize *sizes;
146
147   LockDisplay(dpy);
148   if ((config = _XRRValidateCache(dpy, info, screen))) {
149     *nsizes = config->nsizes;
150     sizes = config->sizes;
151     UnlockDisplay(dpy);
152     return sizes;
153     }
154   else {
155     UnlockDisplay(dpy);
156     *nsizes = 0;
157     return NULL;
158   }  
159 }
160
161 short *XRRRates (Display *dpy, int screen, int sizeID, int *nrates)
162 {
163   XRRScreenConfiguration *config; 
164   XExtDisplayInfo *info = XRRFindDisplay(dpy);
165   short *rates;
166
167   LockDisplay(dpy);
168   if ((config = _XRRValidateCache(dpy, info, screen))) {
169     rates = XRRConfigRates (config, sizeID, nrates);
170     UnlockDisplay(dpy);
171     return rates;
172     }
173   else {
174     UnlockDisplay(dpy);
175     *nrates = 0;
176     return NULL;
177   }  
178 }
179
180 /* given a screen, return the information from the (possibly) cached data */
181 Time XRRTimes (Display *dpy, int screen, Time *config_timestamp)
182 {
183   XRRScreenConfiguration *config; 
184   XExtDisplayInfo *info = XRRFindDisplay(dpy);
185   Time ts;
186
187   LockDisplay(dpy);
188   if ((config = _XRRValidateCache(dpy, info, screen))) {
189       *config_timestamp = config->config_timestamp;
190       ts = config->timestamp;
191       UnlockDisplay(dpy);
192       return ts;
193     } else {
194       UnlockDisplay(dpy);
195         return CurrentTime;
196     }
197 }
198
199 /* need a version that does not hold the display lock */
200 static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy,
201                                                   XExtDisplayInfo *info,
202                                                   Window window)
203 {
204     xRRGetScreenInfoReply   rep;
205     xRRGetScreenInfoReq     *req;
206     _XAsyncHandler          async;
207     _XRRVersionState        async_state;
208     int                     nbytes, nbytesRead, rbytes;
209     int                     i;
210     xScreenSizes            size;
211     struct _XRRScreenConfiguration  *scp;
212     XRRScreenSize           *ssp;
213     short                   *rates;
214     xRRQueryVersionReq      *vreq;
215     XRandRInfo              *xrri;
216     Bool                    getting_version = False;
217
218     xrri = (XRandRInfo *) info->data;
219     if (!xrri)
220         return NULL;
221
222     if (xrri->major_version == -1)
223     {
224         /* hide a version query in the request */
225         GetReq (RRQueryVersion, vreq);
226         vreq->reqType = info->codes->major_opcode;
227         vreq->randrReqType = X_RRQueryVersion;
228         vreq->majorVersion = RANDR_MAJOR;
229         vreq->minorVersion = RANDR_MINOR;
230     
231         async_state.version_seq = dpy->request;
232         async_state.error = False;
233         async.next = dpy->async_handlers;
234         async.handler = _XRRVersionHandler;
235         async.data = (XPointer) &async_state;
236         dpy->async_handlers = &async;
237
238         getting_version = True;
239     }
240
241     GetReq (RRGetScreenInfo, req);
242     req->reqType = info->codes->major_opcode;
243     req->randrReqType = X_RRGetScreenInfo;
244     req->window = window;
245
246     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
247     {
248         if (getting_version)
249             DeqAsyncHandler (dpy, &async);
250         SyncHandle ();
251         return NULL;
252     }
253     if (getting_version)
254     {
255         DeqAsyncHandler (dpy, &async);
256         if (async_state.error)
257         {
258             UnlockDisplay (dpy);
259             SyncHandle();
260             LockDisplay (dpy);
261         }
262         xrri->major_version = async_state.major_version;
263         xrri->minor_version = async_state.minor_version;
264         xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version);
265     }
266
267     /*
268      * Make the reply compatible with v1.1
269      */
270     if (!xrri->has_rates)
271     {
272         rep.rate = 0;
273         rep.nrateEnts = 0;
274     }
275     
276     nbytes = (long) rep.length << 2;
277
278     nbytesRead = (long) (rep.nSizes * SIZEOF (xScreenSizes) +
279                          ((rep.nrateEnts + 1)& ~1) * 2 /* SIZEOF (CARD16) */);
280     
281     /* 
282      * first we must compute how much space to allocate for 
283      * randr library's use; we'll allocate the structures in a single
284      * allocation, on cleanlyness grounds.
285      */
286
287     rbytes = sizeof (XRRScreenConfiguration) +
288       (rep.nSizes * sizeof (XRRScreenSize) +
289        rep.nrateEnts * sizeof (int));
290
291     scp = (struct _XRRScreenConfiguration *) Xmalloc(rbytes);
292     if (scp == NULL) {
293         _XEatData (dpy, (unsigned long) nbytes);
294         return NULL;
295     }
296
297
298     ssp = (XRRScreenSize *)(scp + 1);
299     rates = (short *) (ssp + rep.nSizes);
300
301     /* set up the screen configuration structure */
302     scp->screen = 
303       ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root));
304
305     scp->sizes = ssp;
306     scp->rates = rates;
307     scp->rotations = rep.setOfRotations;
308     scp->current_size = rep.sizeID;
309     scp->current_rate = rep.rate;
310     scp->current_rotation = rep.rotation;
311     scp->timestamp = rep.timestamp;
312     scp->config_timestamp = rep.configTimestamp;
313     scp->nsizes = rep.nSizes;
314     scp->nrates = rep.nrateEnts;
315
316     /*
317      * Time to unpack the data from the server.
318      */
319
320     /*
321      * First the size information
322      */
323     for (i = 0; i < rep.nSizes; i++)  {
324         _XReadPad (dpy, (char *) &size, SIZEOF (xScreenSizes));
325         
326         ssp[i].width = size.widthInPixels;
327         ssp[i].height = size.heightInPixels;
328         ssp[i].mwidth = size.widthInMillimeters;
329         ssp[i].mheight = size.heightInMillimeters;
330     }
331     /*
332      * And the rates
333      */
334     _XRead16Pad (dpy, rates, 2 /* SIZEOF (CARD16) */ * rep.nrateEnts);
335     
336     /*
337      * Skip any extra data
338      */
339     if (nbytes > nbytesRead)
340         _XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
341     
342     return (XRRScreenConfiguration *)(scp);
343 }
344
345 XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, Window window)
346 {
347     XRRScreenConfiguration *config;
348     XExtDisplayInfo *info = XRRFindDisplay(dpy);
349     XRRFindDisplay(dpy);
350     LockDisplay (dpy);
351     config = _XRRGetScreenInfo(dpy, info, window);
352     UnlockDisplay (dpy);
353     SyncHandle ();
354     return config;
355 }
356
357     
358 void XRRFreeScreenConfigInfo (XRRScreenConfiguration *config)
359 {
360     Xfree (config);
361 }
362
363 Status XRRSetScreenConfigAndRate (Display *dpy,
364                                   XRRScreenConfiguration *config,
365                                   Drawable draw,
366                                   int size_index,
367                                   Rotation rotation, 
368                                   short rate,
369                                   Time timestamp)
370 {
371     XExtDisplayInfo *info = XRRFindDisplay (dpy);
372     xRRSetScreenConfigReply rep;
373     XRandRInfo *xrri;
374     int major, minor;
375
376     RRCheckExtension (dpy, info, 0);
377
378     /* Make sure has_rates is set */
379     if (!XRRQueryVersion (dpy, &major, &minor))
380         return 0;
381     
382     LockDisplay (dpy);
383     xrri = (XRandRInfo *) info->data;
384     if (xrri->has_rates)
385     {
386         xRRSetScreenConfigReq  *req;
387         GetReq (RRSetScreenConfig, req);
388         req->reqType = info->codes->major_opcode;
389         req->randrReqType = X_RRSetScreenConfig;
390         req->drawable = draw;
391         req->sizeID = size_index;
392         req->rotation = rotation;
393         req->timestamp = timestamp;
394         req->configTimestamp = config->config_timestamp;
395         req->rate = rate;
396     }
397     else
398     {
399         xRR1_0SetScreenConfigReq  *req;
400         GetReq (RR1_0SetScreenConfig, req);
401         req->reqType = info->codes->major_opcode;
402         req->randrReqType = X_RRSetScreenConfig;
403         req->drawable = draw;
404         req->sizeID = size_index;
405         req->rotation = rotation;
406         req->timestamp = timestamp;
407         req->configTimestamp = config->config_timestamp;
408     }
409     
410     (void) _XReply (dpy, (xReply *) &rep, 0, xTrue);
411
412     /* actually .errorCode in struct xError */
413     if (rep.status == RRSetConfigSuccess) {
414       /* if we succeed, set our view of reality to what we set it to */
415       config->config_timestamp = rep.newConfigTimestamp;
416       config->timestamp = rep.newTimestamp;
417       config->screen = ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root));
418       config->current_size = size_index;
419       config->current_rotation = rotation;
420     }
421     UnlockDisplay (dpy);
422     SyncHandle ();
423     return(rep.status);
424 }
425
426 Status XRRSetScreenConfig (Display *dpy,
427                            XRRScreenConfiguration *config,
428                            Drawable draw,
429                            int size_index,
430                            Rotation rotation, Time timestamp)
431 {
432     return XRRSetScreenConfigAndRate (dpy, config, draw, size_index,
433                                       rotation, 0, timestamp);
434 }