Imported Upstream version 1.7.8
[platform/upstream/ecore.git] / src / lib / ecore_x / xlib / ecore_x_randr.c
1  #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include "Ecore.h"
6 #include "ecore_x_private.h"
7 #include "Ecore_X.h"
8
9 /* NB: FIXME:
10  * 
11  * A lot of this code uses XRRGetScreenInfo and then calls 
12  * XRRFreeScreenConfigInfo. Typically this is not an Unheard of thing to do, 
13  * however this process of getting config and freeing config does force a 
14  * round-trip to the X server */
15
16 /* local variables */
17 static Eina_Bool _randr_avail = EINA_FALSE;
18
19 #ifdef ECORE_XRANDR
20
21 # define RANDR_VERSION_1_1 ((1 << 16) | 1)
22 # define RANDR_VERSION_1_2 ((1 << 16) | 2)
23 # define RANDR_VERSION_1_3 ((1 << 16) | 3)
24 # define RANDR_VERSION_1_4 ((1 << 16) | 4)
25
26 # define RANDR_EDID_VERSION_1_3 ((1 << 8) | 3)
27 # define RANDR_EDID_VERSION_MAJOR 0x12
28 # define RANDR_EDID_VERSION_MINOR 0x13
29
30 # define RANDR_EDID_MANUFACTURER 0x08
31 # define RANDR_EDID_BLOCK 0x36
32
33 typedef enum _Ecore_X_Randr_Edid_Aspect_Ratio_Preferred 
34 {
35    RANDR_EDID_ASPECT_RATIO_PREFERRED_4_3 = 0x00,
36      RANDR_EDID_ASPECT_RATIO_PREFERRED_16_9 = 0x01,
37      RANDR_EDID_ASPECT_RATIO_PREFERRED_16_10 = 0x02,
38      RANDR_EDID_ASPECT_RATIO_PREFERRED_5_4 = 0x03,
39      RANDR_EDID_ASPECT_RATIO_PREFERRED_15_9 = 0x04
40 } Ecore_X_Randr_Edid_Aspect_Ratio_Preferred;
41
42 static int _randr_major, _randr_minor, _randr_version;
43
44 XRRScreenResources *(*_ecore_x_randr_screen_resources_get)(Display *disp, Window win);
45
46 #endif
47
48 /* local functions */
49 void 
50 _ecore_x_randr_init(void)
51 {
52 #ifdef ECORE_XRANDR
53    _randr_major = 1;
54    _randr_minor = 4;
55    _randr_version = 0;
56
57    /* try to query the randr extenstion version */
58    if (XRRQueryVersion(_ecore_x_disp, &_randr_major, &_randr_minor))
59      {
60         _randr_version = (_randr_major << 16) | _randr_minor;
61
62         if (_randr_version >= RANDR_VERSION_1_3)
63           _ecore_x_randr_screen_resources_get = XRRGetScreenResourcesCurrent;
64         else if (_randr_version == RANDR_VERSION_1_2)
65           _ecore_x_randr_screen_resources_get = XRRGetScreenResources;
66
67         _randr_avail = EINA_TRUE;
68      }
69 #endif
70 }
71
72 /* public functions */
73 EAPI int 
74 ecore_x_randr_version_get(void)
75 {
76 #ifdef ECORE_XRANDR
77    if (_randr_avail) return _randr_version;
78 #endif
79    return -1;
80 }
81
82 EAPI Eina_Bool 
83 ecore_x_randr_query(void)
84 {
85    return _randr_avail;
86 }
87
88 /**
89  * @brief This function returns the current config timestamp from 
90  * XRRScreenConfiguration.
91  * 
92  * @params root root window to query screen configuration from
93  * 
94  * @returns The screen configuration timestamp
95  * 
96  * @since 1.8
97  */
98 EAPI Ecore_X_Time 
99 ecore_x_randr_config_timestamp_get(Ecore_X_Window root)
100 {
101    Ecore_X_Time timestamp = 0;
102
103 #ifdef ECORE_XRANDR
104    XRRScreenConfiguration *cfg;
105
106    /* try to get the screen configuration from Xrandr */
107    if ((cfg = XRRGetScreenInfo(_ecore_x_disp, root)))
108      {
109         Time tm;
110
111         XRRConfigTimes(cfg, &tm);
112
113         timestamp = (Ecore_X_Time)tm;
114
115         /* free any returned screen config */
116         if (cfg) XRRFreeScreenConfigInfo(cfg);
117      }
118 #endif
119
120    return timestamp;
121 }
122
123 /***************************************
124  * API Functions for RandR version 1.1 *
125  ***************************************/
126
127 /*
128  * @param root window which's primary output will be queried
129  */
130 EAPI Ecore_X_Randr_Orientation 
131 ecore_x_randr_screen_primary_output_orientations_get(Ecore_X_Window root)
132 {
133 #ifdef ECORE_XRANDR
134    Rotation ret = 0, crot = 0;
135
136    /* get the rotations available from XRandr */
137    ret = XRRRotations(_ecore_x_disp, 
138                       XRRRootToScreen(_ecore_x_disp, root), &crot);
139
140    return ret;
141 #else
142    return 0;
143 #endif
144 }
145
146 /*
147  * @param root window which's primary output will be queried
148  * @return the current orientation of the root window's screen primary output
149  */
150 EAPI Ecore_X_Randr_Orientation 
151 ecore_x_randr_screen_primary_output_orientation_get(Ecore_X_Window root)
152 {
153 #ifdef ECORE_XRANDR
154    Rotation ret = 0;
155
156    /* get the current rotation available from XRandr */
157    XRRRotations(_ecore_x_disp, 
158                 XRRRootToScreen(_ecore_x_disp, root), &ret);
159
160    return ret;
161 #else
162    return 0;
163 #endif
164 }
165
166 /*
167  * @brief Sets a given screen's primary output's orientation.
168  *
169  * @param root Window which's screen's primary output will be queried.
170  * @param orientation orientation which should be set for the root window's
171  * screen primary output.
172  * @return @c EINA_TRUE if the primary output's orientation could be
173  * successfully altered.
174  */
175 EAPI Eina_Bool 
176 ecore_x_randr_screen_primary_output_orientation_set(Ecore_X_Window root, Ecore_X_Randr_Orientation orient)
177 {
178 #ifdef ECORE_XRANDR
179    Eina_Bool ret = EINA_FALSE;
180    Rotation crot = 0;
181    XRRScreenConfiguration *cfg = NULL;
182    int id = 0;
183
184    /* try to get the screen config from XRandr */
185    if (!(cfg = XRRGetScreenInfo(_ecore_x_disp, root)))
186      return EINA_FALSE;
187
188    /* get the screen's current size id */
189    id = XRRConfigCurrentConfiguration(cfg, &crot);
190
191    /* attempt to set the new orientation */
192    if (!XRRSetScreenConfig(_ecore_x_disp, cfg, root, id, orient, CurrentTime))
193      ret = EINA_TRUE;
194
195    /* free any returned screen config */
196    if (cfg) XRRFreeScreenConfigInfo(cfg);
197
198    return ret;
199 #else
200    return EINA_FALSE;
201 #endif
202 }
203
204 /*
205  * @brief gets a screen's primary output's possible sizes
206  * @param root window which's primary output will be queried
207  * @param num number of sizes reported as supported by the screen's primary output
208  * @return an array of sizes reported as supported by the screen's primary output or - if query failed - NULL
209  */
210 EAPI Ecore_X_Randr_Screen_Size_MM *
211 ecore_x_randr_screen_primary_output_sizes_get(Ecore_X_Window root, int *num)
212 {
213    if (num) *num = 0;
214 #ifdef ECORE_XRANDR
215    Ecore_X_Randr_Screen_Size_MM *ret = NULL;
216    XRRScreenSize *sizes;
217    int n = 0, i = 0;
218
219    /* retrieve the number of sizes from X, and the sizes themselves.
220     * 
221     * NB: don't have to free the returned sizes */
222    sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
223    if (!sizes) return NULL;
224    if (n <= 0) return NULL;
225
226    /* try to allocate our structure for these sizes */
227    if (!(ret = calloc(n, sizeof(Ecore_X_Randr_Screen_Size_MM))))
228      return NULL;
229
230    if (num) *num = n;
231
232    /* fill in our allocated structure with the screen sizes */
233    for (i = 0; i < n; i++)
234      {
235         ret[i].width = sizes[i].width;
236         ret[i].height = sizes[i].height;
237         ret[i].width_mm = sizes[i].mwidth;
238         ret[i].height_mm = sizes[i].mheight;
239      }
240
241    return ret;
242 #else
243    return NULL;
244 #endif
245 }
246
247 EAPI void 
248 ecore_x_randr_screen_primary_output_current_size_get(Ecore_X_Window root, int *w, int *h, int *w_mm, int *h_mm, int *size_index)
249 {
250 #ifdef ECORE_XRANDR
251    XRRScreenConfiguration *cfg = NULL;
252
253    /* try to get the screen config from XRandr */
254    if ((cfg = XRRGetScreenInfo(_ecore_x_disp, root)))
255      {
256         XRRScreenSize *sizes;
257         Rotation crot = 0;
258         int n = 0;
259
260         /* retrieve the number of sizes from X, and the sizes themselves.
261          * 
262          * NB: don't have to free the returned sizes */
263         sizes = 
264           XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
265         if ((sizes) && (n > 0))
266           {
267              int idx = 0;
268
269              /* get the index of the current configuration */
270              idx = XRRConfigCurrentConfiguration(cfg, &crot);
271
272              /* if the index is valid, then fill in the return variables with 
273               * the size information for this index */
274              if ((idx < n) && (idx >= 0))
275                {
276                   if (w) *w = sizes[idx].width;
277                   if (h) *h = sizes[idx].height;
278                   if (w_mm) *w_mm = sizes[idx].mwidth;
279                   if (h_mm) *h_mm = sizes[idx].mheight;
280                   if (size_index) *size_index = idx;
281                }
282           }
283
284         /* free the returned screen config */
285         XRRFreeScreenConfigInfo(cfg);
286      }
287 #endif
288 }
289
290 /*
291  * @brief Sets a given screen's primary output size, but disables all other
292  * outputs at the same time.
293  *
294  * @param root Window which's primary output will be queried.
295  * @param size_index Within the list of sizes reported as supported by the root
296  * window's screen primary output.
297  * @return @c EINA_TRUE on success, @c EINA_FALSE on failure due to e.g.
298  * invalid times.
299  */
300 EAPI Eina_Bool 
301 ecore_x_randr_screen_primary_output_size_set(Ecore_X_Window root, int size_index)
302 {
303 #ifdef ECORE_XRANDR
304    Eina_Bool ret = EINA_FALSE;
305    int n = 0;
306
307    /* check for valid size index first */
308    if (size_index < 0) return EINA_FALSE;
309
310    /* get the number of sizes from XRandr */
311    XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
312
313    /* make sure the requested index is below the number returned from randr */
314    if (size_index < n)
315      {
316         XRRScreenConfiguration *cfg = NULL;
317
318         /* try to get the screen config from XRandr */
319         if ((cfg = XRRGetScreenInfo(_ecore_x_disp, root)))
320           {
321              /* try to set the new screen config
322               * 
323               * NB: Returns Success (0) if it works */
324              if (!XRRSetScreenConfig(_ecore_x_disp, cfg, root, size_index, 
325                                       ECORE_X_RANDR_ORIENTATION_ROT_0, 
326                                       CurrentTime))
327                {
328                   ret = EINA_TRUE;
329                }
330
331              /* free the returned screen config */
332              XRRFreeScreenConfigInfo(cfg);
333           }
334      }
335
336    return ret;
337 #else
338    return EINA_FALSE;
339 #endif
340 }
341
342 /*
343  * @param root window which's primary output will be queried
344  * @return currently used refresh rate or - if request failed or RandRR is not available - 0.0
345  */
346 EAPI Ecore_X_Randr_Refresh_Rate 
347 ecore_x_randr_screen_primary_output_current_refresh_rate_get(Ecore_X_Window root)
348 {
349 #ifdef ECORE_XRANDR
350    XRRScreenConfiguration *cfg = NULL;
351
352    /* try to get the screen config from XRandr */
353    if ((cfg = XRRGetScreenInfo(_ecore_x_disp, root)))
354      {
355         Ecore_X_Randr_Refresh_Rate ret = 0.0;
356
357         /* try to get the current refresh rate */
358         ret = XRRConfigCurrentRate(cfg);
359
360         /* free the returned screen config */
361         XRRFreeScreenConfigInfo(cfg);
362
363         return ret;
364      }
365 #endif
366    return 0.0;
367 }
368
369 /*
370  * @param root window which's primary output will be queried
371  * @param size_index referencing the size to query valid refresh rates for
372  * @return currently used refresh rate or - if request failed or RandRR is not available - NULL
373  */
374 EAPI Ecore_X_Randr_Refresh_Rate *
375 ecore_x_randr_screen_primary_output_refresh_rates_get(Ecore_X_Window root, int size_index, int *num)
376 {
377 #ifdef ECORE_XRANDR
378    Ecore_X_Randr_Refresh_Rate *rates = NULL;
379    int n = 0;
380
381    /* try to get the refresh rates for this screen */
382    if ((rates = XRRRates(_ecore_x_disp, 
383                          XRRRootToScreen(_ecore_x_disp, root), size_index, &n)))
384      {
385         Ecore_X_Randr_Refresh_Rate *ret = NULL;
386
387         if (n == 0) return NULL;
388
389         /* try to allocate space for the return */
390         if ((ret = malloc(n * sizeof(Ecore_X_Randr_Refresh_Rate))))
391           {
392              int i = 0;
393
394              /* fill in our return values */
395              for (i = 0; i < n; i++)
396                ret[i] = rates[i];
397
398              if (num) *num = n;
399
400              return ret;
401           }
402      }
403 #endif
404    return NULL;
405 }
406
407 /*
408  * @brief Sets the current primary output's refresh rate.
409  *
410  * @param root Window which's primary output will be queried.
411  * @param size_index Referencing the size to be set.
412  * @param rate The refresh rate to be set.
413  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
414  */
415 EAPI Eina_Bool 
416 ecore_x_randr_screen_primary_output_refresh_rate_set(Ecore_X_Window root, int size_index, Ecore_X_Randr_Refresh_Rate rate)
417 {
418 #ifdef ECORE_XRANDR
419    if (_randr_version >= RANDR_VERSION_1_1)
420      {
421         XRRScreenConfiguration *cfg = NULL;
422
423         /* try to get the screen config from XRandr */
424         if ((cfg = XRRGetScreenInfo(_ecore_x_disp, root)))
425           {
426              Eina_Bool ret = EINA_FALSE;
427              Rotation rot = 0;
428
429              /* get the current rotation */
430              XRRConfigRotations(cfg, &rot);
431  
432              /* try to set the new screen config
433               * 
434               * NB: Returns Success (0) if it works */
435              if (!XRRSetScreenConfigAndRate(_ecore_x_disp, cfg, root, 
436                                             size_index, rot, rate, CurrentTime))
437                {
438                   ret = EINA_TRUE;
439                }
440
441              /* free the returned screen config */
442              XRRFreeScreenConfigInfo(cfg);
443
444              return ret;
445           }
446      }
447 #endif
448    return EINA_FALSE;
449 }
450
451 /***************************************
452  * API Functions for RandR version 1.2 *
453  ***************************************/
454
455 /**
456  * @brief Enable event selection. This enables basic interaction with
457  * output/crtc events and requires RandR >= 1.2.
458  *
459  * @param win Select this window's properties for RandR events.
460  * @param on Enable/disable selecting.
461  */
462 EAPI void 
463 ecore_x_randr_events_select(Ecore_X_Window win, Eina_Bool on)
464 {
465 #ifdef ECORE_XRANDR
466    int mask = 0;
467
468    if (on)
469      {
470         mask = RRScreenChangeNotifyMask;
471         if (_randr_version >= RANDR_VERSION_1_2)
472           mask |= (RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | 
473                    RROutputPropertyNotifyMask);
474      }
475
476    /* tell randr what events we want to listen to for this window */
477    XRRSelectInput(_ecore_x_disp, win, mask);
478 #endif
479 }
480
481 /*
482  * @param w width of screen in px
483  * @param h height of screen in px
484  */
485 EAPI void 
486 ecore_x_randr_screen_current_size_get(Ecore_X_Window root, int *w, int *h, int *w_mm, int *h_mm)
487 {
488 #ifdef ECORE_XRANDR
489    if (_randr_version >= RANDR_VERSION_1_2)
490      {
491         int scr = 0;
492
493         /* get the screen number */
494         scr = XRRRootToScreen(_ecore_x_disp, root);
495
496         if (w) *w = DisplayWidth(_ecore_x_disp, scr);
497         if (h) *h = DisplayHeight(_ecore_x_disp, scr);
498         if (w_mm) *w_mm = DisplayWidthMM(_ecore_x_disp, scr);
499         if (h_mm) *h_mm = DisplayHeightMM(_ecore_x_disp, scr);
500      }
501 #endif
502 }
503
504 /*
505  * @param root window which's screen will be queried
506  * @param wmin minimum width the screen can be set to
507  * @param hmin minimum height the screen can be set to
508  * @param wmax maximum width the screen can be set to
509  * @param hmax maximum height the screen can be set to
510  */
511 EAPI void 
512 ecore_x_randr_screen_size_range_get(Ecore_X_Window root, int *wmin, int *hmin, int *wmax, int *hmax)
513 {
514 #ifdef ECORE_XRANDR
515    if (_randr_version >= RANDR_VERSION_1_2)
516      {
517         int swmin = 0, shmin = 0, swmax = 0, shmax = 0;
518
519         /* try to get the screen size range from XRandr
520          * 
521          * NB: returns 1 on success */
522         if ((XRRGetScreenSizeRange(_ecore_x_disp, root, &swmin, &shmin, 
523                                    &swmax, &shmax)))
524           {
525              /* fill in the return variables */
526              if (wmin) *wmin = swmin;
527              if (hmin) *hmin = shmin;
528              if (wmax) *wmax = swmax;
529              if (hmax) *hmax = shmax;
530           }
531      }
532 #endif
533 }
534
535 /**
536  * @brief removes unused screen space. The most upper left CRTC is set to 0x0
537  * and all other CRTCs dx,dy respectively.
538  * @param root the window's screen which will be reset.
539  */
540 EAPI void 
541 ecore_x_randr_screen_reset(Ecore_X_Window root)
542 {
543 #ifdef ECORE_XRANDR
544    XRRScreenResources *res = NULL;
545
546    if (_randr_version < RANDR_VERSION_1_2) return;
547
548    /* try to get the screen resources from Xrandr */
549    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
550      {
551         if (res->ncrtc > 0)
552           {
553              Ecore_X_Randr_Crtc crtcs[res->ncrtc];
554              int i = 0, nenabled = 0;
555              int nw = 0, nh = 0;
556              int dx = 100000, dy = 100000;
557
558              for (i = 0; i < res->ncrtc; i++)
559                {
560                   XRRCrtcInfo *info = NULL;
561
562                   /* try to get the crtc info from Xrandr */
563                   if (!(info = XRRGetCrtcInfo(_ecore_x_disp, res, res->crtcs[i])))
564                     continue;
565
566                   /* safety check */
567                   if ((info->mode <= 0) || (info->noutput == 0))
568                     {
569                        /* free the crtc info */
570                        XRRFreeCrtcInfo(info);
571
572                        continue;
573                     }
574
575                   crtcs[nenabled++] = res->crtcs[i];
576
577                   if ((int)(info->x + info->width) > nw)
578                     nw = (info->x + info->width);
579
580                   if ((int)(info->y + info->height) > nh)
581                     nh = (info->y + info->height);
582
583                   if (info->x < dx) dx = info->x;
584                   if (info->y < dy) dy = info->y;
585
586                   /* free the crtc info */
587                   XRRFreeCrtcInfo(info);
588                }
589
590              /* free the resources */
591              XRRFreeScreenResources(res);
592
593              if ((dx > 0) || (dy > 0))
594                {
595                   if (ecore_x_randr_move_crtcs(root, crtcs, nenabled, -dx, -dy))
596                     {
597                        nw -= dx;
598                        nh -= dy;
599                     }
600                }
601
602              ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1);
603           }
604      }
605 #endif
606 }
607
608 /*
609  * @param root Window which's screen's size should be set. If invalid (e.g. 
610  * @c NULL) no action is taken.
611  * @param w Width in px the screen should be set to. If out of valid
612  * boundaries, current value is assumed.
613  * @param h Height in px the screen should be set to. If out of valid
614  * boundaries, current value is assumed.
615  * @param w_mm Width in mm the screen should be set to. If @c 0, current
616  * aspect is assumed.
617  * @param h_mm Height in mm the screen should be set to. If @c 0, current
618  * aspect is assumed.
619  * @return @c EINA_TRUE if request was successfully sent or screen is already
620  * in requested size, @c EINA_FALSE if parameters are invalid.
621  */
622 EAPI Eina_Bool 
623 ecore_x_randr_screen_current_size_set(Ecore_X_Window root, int w, int h, int w_mm, int h_mm)
624 {
625 #ifdef ECORE_XRANDR
626    if (_randr_version >= RANDR_VERSION_1_2)
627      {
628         int cw = 0, ch = 0, cwmm = 0, chmm = 0;
629         int wmin = 0, hmin = 0, wmax = 0, hmax = 0;
630
631         /* get the current screen size */
632         ecore_x_randr_screen_current_size_get(root, &cw, &ch, &cwmm, &chmm);
633
634         /* compare to the values passed in. if there are no changes, get out */
635         if ((w == cw) && (h == ch) && (w_mm == cwmm) && (h_mm == chmm))
636           return EINA_TRUE;
637
638         /* get the current size range */
639         ecore_x_randr_screen_size_range_get(root, &wmin, &hmin, &wmax, &hmax);
640
641         /* compare to the values passed in. make sure they are within range */
642         if ((w != 0) && ((w < wmin) || (w > wmax))) return EINA_FALSE;
643         if ((h != 0) && ((h < hmin) || (h > hmax))) return EINA_FALSE;
644
645         /* safety check some values */
646         if (w <= 0) w = cw;
647         if (h <= 0) h = ch;
648         if (w_mm <= 0)
649           w_mm = (int)(((double)(cwmm / (double)cw)) * (double)w);
650         if (h_mm <= 0)
651           h_mm = (int)(((double)(chmm / (double)ch)) * (double)h);
652
653         /* tell XRandr to set screen size */
654         XRRSetScreenSize(_ecore_x_disp, root, w, h, w_mm, h_mm);
655
656         return EINA_TRUE;
657      }
658 #endif
659    return EINA_FALSE;
660 }
661
662 /*
663  * @brief get detailed information for all modes related to a root window's screen
664  * @param root window which's screen's ressources are queried
665  * @param num number of modes returned
666  * @return modes' information
667  */
668 EAPI Ecore_X_Randr_Mode_Info **
669 ecore_x_randr_modes_info_get(Ecore_X_Window root, int *num)
670 {
671    if (num) *num = 0;
672 #ifdef ECORE_XRANDR
673    XRRScreenResources *res = NULL;
674
675    if (_randr_version < RANDR_VERSION_1_2) return NULL;
676
677    /* try to get the screen resources from Xrandr */
678    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
679      {
680         Ecore_X_Randr_Mode_Info **ret = NULL;
681
682         /* set the returned number of modes */
683         if (num) *num = res->nmode;
684
685         /* if we did not get any modes from X, then cleanup and return */
686         if (res->nmode == 0)
687           {
688              /* free the resources */
689              XRRFreeScreenResources(res);
690
691              return NULL;
692           }
693
694         /* try to allocate space for our return variable */
695         if ((ret = (Ecore_X_Randr_Mode_Info **)
696              malloc(res->nmode * sizeof(Ecore_X_Randr_Mode_Info *))))
697           {
698              int i = 0;
699
700              /* loop through all the modes and assign to our return var */
701              for (i = 0; i < res->nmode; i++)
702                {
703                   if ((ret[i] = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
704                     {
705                        ret[i]->xid = res->modes[i].id;
706                        ret[i]->width = res->modes[i].width;
707                        ret[i]->height = res->modes[i].height;
708                        ret[i]->dotClock = res->modes[i].dotClock;
709                        ret[i]->hSyncStart = res->modes[i].hSyncStart;
710                        ret[i]->hSyncEnd = res->modes[i].hSyncEnd;
711                        ret[i]->hTotal = res->modes[i].hTotal;
712                        ret[i]->hSkew = res->modes[i].hSkew;
713                        ret[i]->vSyncStart = res->modes[i].vSyncStart;
714                        ret[i]->vSyncEnd = res->modes[i].vSyncEnd;
715                        ret[i]->vTotal = res->modes[i].vTotal;
716                        if (res->modes[i].nameLength > 0)
717                          {
718                             if ((ret[i]->name = 
719                                  (malloc(res->modes[i].nameLength + 1))))
720                               strncpy(ret[i]->name, res->modes[i].name,
721                                       (res->modes[i].nameLength + 1));
722                             else
723                               ret[i]->name = NULL;
724                          }
725                        else
726                          ret[i]->name = NULL;
727
728                        ret[i]->nameLength = res->modes[i].nameLength;
729                        ret[i]->modeFlags = res->modes[i].modeFlags;
730                     }
731                   else
732                     {
733                        while (i > 0)
734                          free(ret[--i]);
735                        free(ret);
736                        ret = NULL;
737                        break;
738                     }
739                }
740           }
741
742         /* free the resources */
743         XRRFreeScreenResources(res);
744
745         return ret;
746      }
747 #endif
748    return NULL;
749 }
750
751 /*
752  * @brief Add a mode to a display.
753  *
754  * @param root Window to which's screen's ressources are added.
755  * @param mode_info
756  * @return Ecore_X_Randr_Mode of the added mode. Ecore_X_Randr_None if mode
757  * adding failed.
758  * @since 1.2.0
759  */
760 EAPI Ecore_X_Randr_Mode 
761 ecore_x_randr_mode_info_add(Ecore_X_Window root, Ecore_X_Randr_Mode_Info *mode_info)
762 {
763 #ifdef ECORE_XRANDR
764    if (_randr_version >= RANDR_VERSION_1_2)
765      {
766         Ecore_X_Randr_Mode mode = 0;
767
768         /* if we have valid mode_info from the user, then ask XRandr to 
769          * create the new mode using that as base */
770         if (mode_info)
771           mode = XRRCreateMode(_ecore_x_disp, root, (XRRModeInfo *)mode_info);
772
773         return mode;
774      }
775 #endif
776    return 0;
777 }
778
779 /*
780  * @brief Delete a mode from the display.
781  *
782  * @param mode_info
783  * @since 1.2.0
784  */
785 EAPI void 
786 ecore_x_randr_mode_del(Ecore_X_Randr_Mode mode)
787 {
788 #ifdef ECORE_XRANDR
789    if (_randr_version >= RANDR_VERSION_1_2)
790      XRRDestroyMode(_ecore_x_disp, mode);
791 #endif
792 }
793
794 /*
795  * @brief get detailed information for a given mode id
796  * @param root window which's screen's ressources are queried
797  * @param mode the XID which identifies the mode of interest
798  * @return mode's detailed information
799  */
800 EAPI Ecore_X_Randr_Mode_Info *
801 ecore_x_randr_mode_info_get(Ecore_X_Window root, Ecore_X_Randr_Mode mode)
802 {
803 #ifdef ECORE_XRANDR
804    XRRScreenResources *res = NULL;
805
806    if (_randr_version < RANDR_VERSION_1_2) return NULL;
807
808    /* try to get the screen resources from Xrandr */
809    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
810      {
811         Ecore_X_Randr_Mode_Info *ret = NULL;
812         int i = 0;
813
814         if (res->nmode == 0)
815           {
816              /* free the resources */
817              XRRFreeScreenResources(res);
818
819              return NULL;
820           }
821
822         /* loop the mode informations and find the one we want */
823         for (i = 0; i < res->nmode; i++)
824           {
825              /* compare mode ids */
826              if (res->modes[i].id != mode) continue;
827
828              /* try to allocate our return mode information structure */
829              if (!(ret = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
830                break;
831
832              /* copy the mode information into our return structure */
833              ret->xid = res->modes[i].id;
834              ret->width = res->modes[i].width;
835              ret->height = res->modes[i].height;
836              ret->dotClock = res->modes[i].dotClock;
837              ret->hSyncStart = res->modes[i].hSyncStart;
838              ret->hSyncEnd = res->modes[i].hSyncEnd;
839              ret->hTotal = res->modes[i].hTotal;
840              ret->hSkew = res->modes[i].hSkew;
841              ret->vSyncStart = res->modes[i].vSyncStart;
842              ret->vSyncEnd = res->modes[i].vSyncEnd;
843              ret->vTotal = res->modes[i].vTotal;
844              ret->modeFlags = res->modes[i].modeFlags;
845              ret->name = NULL;
846              ret->nameLength = 0;
847              if (res->modes[i].nameLength > 0)
848                {
849                   ret->nameLength = res->modes[i].nameLength;
850                   if ((ret->name = malloc(res->modes[i].nameLength + 1)))
851                     strncpy(ret->name, res->modes[i].name,
852                             (res->modes[i].nameLength + 1));
853                }
854              break;
855           }
856
857         /* free the resources */
858         XRRFreeScreenResources(res);
859
860         return ret;
861      }
862 #endif
863    return NULL;
864 }
865
866 /*
867  * @brief Free detailed mode information. The pointer handed in will be set to
868  * @c NULL after freeing the memory.
869  *
870  * @param mode_info The mode information that should be freed.
871  */
872 EAPI void 
873 ecore_x_randr_mode_info_free(Ecore_X_Randr_Mode_Info *mode_info)
874 {
875 #ifdef ECORE_XRANDR
876    if (_randr_version >= RANDR_VERSION_1_2)
877      {
878         if (mode_info)
879           {
880              if (mode_info->name) free(mode_info->name);
881              free(mode_info);
882              mode_info = NULL;
883           }
884      }
885 #endif
886 }
887
888 /*
889  * @brief Get all known CRTCs related to a root window's screen.
890  *
891  * @param root Window which's screen's ressources are queried.
892  * @param num Number of CRTCs returned.
893  * @return CRTC IDs.
894  */
895 EAPI Ecore_X_Randr_Crtc *
896 ecore_x_randr_crtcs_get(Ecore_X_Window root, int *num)
897 {
898    if (num) *num = 0;
899 #ifdef ECORE_XRANDR
900    XRRScreenResources *res = NULL;
901
902    if (_randr_version < RANDR_VERSION_1_2) return NULL;
903
904    /* try to get the screen resources from Xrandr */
905    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
906      {
907         Ecore_X_Randr_Crtc *ret = NULL;
908
909         if (res->ncrtc == 0)
910           {
911              /* free the resources */
912              XRRFreeScreenResources(res);
913
914              return NULL;
915           }
916
917         /* try to allocate space for our return variable */
918         if ((ret = malloc(res->ncrtc * sizeof(Ecore_X_Randr_Crtc))))
919           {
920              int i = 0;
921
922              if (num) *num = res->ncrtc;
923
924              /* copy the crtc information into our return variable */
925              for (i = 0; i < res->ncrtc; i++)
926                ret[i] = res->crtcs[i];
927           }
928
929         /* free the resources */
930         XRRFreeScreenResources(res);
931
932         return ret;
933      }
934 #endif
935    return NULL;
936 }
937
938 EAPI Ecore_X_Randr_Output *
939 ecore_x_randr_outputs_get(Ecore_X_Window root, int *num)
940 {
941    if (num) *num = 0;
942 #ifdef ECORE_XRANDR
943    XRRScreenResources *res = NULL;
944
945    if (_randr_version < RANDR_VERSION_1_2) return NULL;
946
947    /* try to get the screen resources from Xrandr */
948    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
949      {
950         Ecore_X_Randr_Output *ret = NULL;
951
952         if (res->noutput == 0)
953           {
954              /* free the resources */
955              XRRFreeScreenResources(res);
956
957              return NULL;
958           }
959
960         /* try to allocate space for our return variable */
961         if ((ret = malloc(res->noutput * sizeof(Ecore_X_Randr_Output))))
962           {
963              int i = 0;
964
965              if (num) *num = res->noutput;
966
967              /* copy the output information into our return variable */
968              for (i = 0; i < res->noutput; i++)
969                ret[i] = res->outputs[i];
970           }
971
972         /* free the resources */
973         XRRFreeScreenResources(res);
974
975         return ret;
976      }
977 #endif
978    return NULL;
979 }
980
981 /*
982  * @brief Get the outputs, which display a certain window.
983  *
984  * @param window Window the displaying outputs shall be found for
985  * @param num The number of outputs displaying the window
986  * @return Array of outputs that display a certain window. @c NULL if no
987  * outputs was found that displays the specified window.
988  */
989 EAPI Ecore_X_Randr_Output *
990 ecore_x_randr_window_outputs_get(Ecore_X_Window window, int *num)
991 {
992    if (num) *num = 0;
993 #ifdef ECORE_XRANDR
994    Ecore_X_Window root;
995    Ecore_X_Randr_Crtc *crtcs = NULL;
996    int ncrtcs = 0;
997
998    if (_randr_version < RANDR_VERSION_1_2) return NULL;
999
1000    /* grab this windows root window */
1001    root = ecore_x_window_root_get(window);
1002
1003    /* get the crtcs from xrandr */
1004    if ((crtcs = ecore_x_randr_crtcs_get(root, &ncrtcs)))
1005      {
1006         XRRScreenResources *res = NULL;
1007         Ecore_X_Randr_Output *ret = NULL;
1008
1009         /* try to get the screen resources from Xrandr
1010          * 
1011          * NB: We do this ONCE here as we reuse it for every crtc.
1012          * NB: The old code used to loop and fetch the screen resources on 
1013          *     every crtc */
1014         if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1015           {
1016              Ecore_X_Randr_Output *tret = NULL;
1017              int i = 0, nret = 0;
1018
1019              /* for each crtc, get it's outputs */
1020              for (i = 0, nret = 0; i < ncrtcs; i++)
1021                {
1022                   XRRCrtcInfo *crtc = NULL;
1023
1024                   /* try to get the crtc info for this crtc */
1025                   if (!(crtc = XRRGetCrtcInfo(_ecore_x_disp, res, crtcs[i])))
1026                     continue;
1027
1028                   /* try to reallocate our return variable */
1029                   if ((tret = realloc(ret, ((nret + crtc->noutput) * 
1030                                             sizeof(Ecore_X_Randr_Output)))))
1031                     {
1032                        ret = tret;
1033                        memcpy(&ret[nret], crtc->outputs, 
1034                               (crtc->noutput * sizeof(Ecore_X_Randr_Output)));
1035                        nret += crtc->noutput;
1036                     }
1037
1038                   /* free the crtc info */
1039                   XRRFreeCrtcInfo(crtc);
1040                }
1041
1042              if (num) *num = nret;
1043
1044              /* free the resources */
1045              XRRFreeScreenResources(res);
1046           }
1047
1048         /* free any allocated crtcs from the get function */
1049         free(crtcs);
1050
1051         return ret;
1052      }
1053 #endif
1054    return NULL;
1055 }
1056
1057 /*
1058  * @deprecated bad naming. Use ecore_x_randr_window_outputs_get instead.
1059  * @brief Get the outputs, which display a certain window.
1060  *
1061  * @param window Window the displaying outputs shall be found for.
1062  * @param num The number of outputs displaying the window.
1063  * @return Array of outputs that display a certain window. @c NULL if no
1064  * outputs was found that displays the specified window.
1065  */
1066 EAPI Ecore_X_Randr_Output *
1067 ecore_x_randr_current_output_get(Ecore_X_Window window, int *num)
1068 {
1069    return ecore_x_randr_window_outputs_get(window, num);
1070 }
1071
1072 /*
1073  * @brief get the CRTCs, which display a certain window
1074  * @param window window the displaying crtcs shall be found for
1075  * @param num the number of crtcs displaying the window
1076  * @return Array of crtcs that display a certain window. @c NULL if no crtcs
1077  * was found that displays the specified window.
1078  * @since 1.2.0
1079  */
1080 EAPI Ecore_X_Randr_Crtc *
1081 ecore_x_randr_window_crtcs_get(Ecore_X_Window window, int *num)
1082 {
1083    if (num) *num = 0;
1084 #ifdef ECORE_XRANDR
1085    Ecore_X_Window root;
1086    Ecore_X_Randr_Crtc *crtcs = NULL;
1087    int ncrtcs = 0;
1088
1089    if (_randr_version < RANDR_VERSION_1_2) return NULL;
1090
1091    /* grab this windows root window */
1092    root = ecore_x_window_root_get(window);
1093
1094    /* get the crtcs from xrandr */
1095    if ((crtcs = ecore_x_randr_crtcs_get(root, &ncrtcs)))
1096      {
1097         XRRScreenResources *res = NULL;
1098         Ecore_X_Randr_Crtc *ret = NULL;
1099
1100         /* make sure we can allocate our return variable */
1101         if (!(ret = calloc(1, ncrtcs * sizeof(Ecore_X_Randr_Crtc))))
1102           {
1103              free(crtcs);
1104              return NULL;
1105           }
1106
1107         /* try to get the screen resources from Xrandr
1108          * 
1109          * NB: We do this ONCE here as we reuse it for every crtc.
1110          * NB: The old code used to loop and fetch the screen resources on 
1111          *     every crtc */
1112         if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1113           {
1114              Window tw;
1115              Eina_Rectangle wrect, crect;
1116              int i = 0, nret = 0;
1117
1118              /* get the geometry of this window */
1119              ecore_x_window_geometry_get(window, &wrect.x, &wrect.y, 
1120                                          &wrect.w, &wrect.h);
1121
1122              /* translate coordinates relative to root window */
1123              XTranslateCoordinates(_ecore_x_disp, window, root, 
1124                                    0, 0, &wrect.x, &wrect.y, &tw);
1125
1126              for (i = 0; i < ncrtcs; i++)
1127                {
1128                   XRRCrtcInfo *info = NULL;
1129
1130                   /* try to get crtc info */
1131                   if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, crtcs[i])))
1132                     {
1133                        /* check if crtc is enabled */
1134                        if (info->mode != 0)
1135                          {
1136                             /* enabled. get geometry */
1137                             crect.x = info->x;
1138                             crect.y = info->y;
1139                             crect.w = info->width;
1140                             crect.h = info->height;
1141
1142                             /* check intersection with window */
1143                             if (eina_rectangles_intersect(&wrect, &crect))
1144                               {
1145                                  /* add if intersect */
1146                                  ret[nret] = crtcs[i];
1147                                  nret++;
1148                               }
1149                          }
1150
1151                        /* free the crtc info */
1152                        XRRFreeCrtcInfo(info);
1153                     }
1154                }
1155
1156              /* free the resources */
1157              XRRFreeScreenResources(res);
1158
1159              if (num) *num = nret;
1160           }
1161
1162         free(crtcs);
1163
1164         return ret;
1165      }
1166 #endif
1167    return NULL;
1168 }
1169
1170 /*
1171  * @deprecated bad naming. Use ecore_x_randr_window_crtcs_get instead.
1172  * @brief get the CRTCs, which display a certain window
1173  * @param window window the displaying crtcs shall be found for
1174  * @param num the number of crtcs displaying the window
1175  * @return Array of crtcs that display a certain window. @c NULL if no crtcs
1176  * was found that displays the specified window.
1177  */
1178 EAPI Ecore_X_Randr_Crtc *
1179 ecore_x_randr_current_crtc_get(Ecore_X_Window window, int *num)
1180 {
1181    return ecore_x_randr_window_crtcs_get(window, num);
1182 }
1183
1184 /*
1185  * @brief get a CRTC's outputs.
1186  * @param root the root window which's screen will be queried
1187  * @param num number of outputs referenced by given CRTC
1188  */
1189 EAPI Ecore_X_Randr_Output *
1190 ecore_x_randr_crtc_outputs_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int *num)
1191 {
1192    if (num) *num = 0;
1193 #ifdef ECORE_XRANDR
1194    XRRScreenResources *res = NULL;
1195
1196    if (_randr_version < RANDR_VERSION_1_2) return NULL;
1197
1198    /* try to get the screen resources from Xrandr */
1199    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1200      {
1201         XRRCrtcInfo *info = NULL;
1202         Ecore_X_Randr_Output *ret = NULL;
1203
1204         /* try to get crtc info */
1205         if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1206           {
1207              /* if we have no outputs, return NULL */
1208              if (info->noutput == 0)
1209                {
1210                   /* free the crtc info */
1211                   XRRFreeCrtcInfo(info);
1212
1213                   /* free the resources */
1214                   XRRFreeScreenResources(res);
1215
1216                   return NULL;
1217                }
1218
1219              /* try to allocate our return struct */
1220              if ((ret = malloc(info->noutput * sizeof(Ecore_X_Randr_Output))))
1221                {
1222                   int i = 0;
1223
1224                   /* loop the outputs on this crtc */
1225                   for (i = 0; i < info->noutput; i++)
1226                     ret[i] = info->outputs[i];
1227
1228                   if (num) *num = info->noutput;
1229                }
1230
1231              /* free the crtc info */
1232              XRRFreeCrtcInfo(info);
1233           }
1234
1235         /* free the resources */
1236         XRRFreeScreenResources(res);
1237
1238         return ret;
1239      }
1240 #endif
1241    return NULL;
1242 }
1243
1244 /*
1245  * @brief get a CRTC's possible outputs.
1246  * @param root the root window which's screen will be queried
1247  * @param num number of possible outputs referenced by given CRTC
1248  */
1249 EAPI Ecore_X_Randr_Output *
1250 ecore_x_randr_crtc_possible_outputs_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int *num)
1251 {
1252    if (num) *num = 0;
1253 #ifdef ECORE_XRANDR
1254    XRRScreenResources *res = NULL;
1255
1256    if (_randr_version < RANDR_VERSION_1_2) return NULL;
1257
1258    /* try to get the screen resources from Xrandr */
1259    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1260      {
1261         XRRCrtcInfo *info = NULL;
1262         Ecore_X_Randr_Output *ret = NULL;
1263
1264         /* try to get crtc info */
1265         if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1266           {
1267              if (info->npossible == 0)
1268                {
1269                   /* free the crtc info */
1270                   XRRFreeCrtcInfo(info);
1271
1272                   /* free the resources */
1273                   XRRFreeScreenResources(res);
1274
1275                   return NULL;
1276                }
1277
1278              /* try to allocate our return struct */
1279              if ((ret = malloc(info->npossible * sizeof(Ecore_X_Randr_Output))))
1280                {
1281                   int i = 0;
1282
1283                   /* loop the outputs on this crtc */
1284                   for (i = 0; i < info->npossible; i++)
1285                     ret[i] = info->possible[i];
1286
1287                   if (num) *num = info->npossible;
1288                }
1289
1290              /* free the crtc info */
1291              XRRFreeCrtcInfo(info);
1292           }
1293
1294         /* free the resources */
1295         XRRFreeScreenResources(res);
1296
1297         return ret;
1298      }
1299 #endif
1300    return NULL;
1301 }
1302
1303 EAPI void 
1304 ecore_x_randr_crtc_geometry_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int *x, int *y, int *w, int *h)
1305 {
1306 #ifdef ECORE_XRANDR
1307    XRRScreenResources *res = NULL;
1308
1309    if (_randr_version < RANDR_VERSION_1_2) return;
1310
1311    /* try to get the screen resources from Xrandr */
1312    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1313      {
1314         XRRCrtcInfo *info = NULL;
1315
1316         /* try to get crtc info */
1317         if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1318           {
1319              if (x) *x = info->x;
1320              if (y) *y = info->y;
1321              if (w) *w = info->width;
1322              if (h) *h = info->height;
1323
1324              /* free the crtc info */
1325              XRRFreeCrtcInfo(info);
1326           }
1327
1328         /* free the resources */
1329         XRRFreeScreenResources(res);
1330      }
1331 #endif
1332 }
1333
1334 EAPI void 
1335 ecore_x_randr_crtc_pos_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int *x, int *y)
1336 {
1337 #ifdef ECORE_XRANDR
1338    if (_randr_version < RANDR_VERSION_1_2) return;
1339
1340    ecore_x_randr_crtc_geometry_get(root, crtc, x, y, NULL, NULL);
1341 #endif
1342 }
1343
1344 /*
1345  * @brief Sets the position of given CRTC within root window's screen.
1346  *
1347  * @param root The window's screen to be queried.
1348  * @param crtc The CRTC which's position within the mentioned screen is to be
1349  * altered.
1350  * @param x Position on the x-axis (0 == left) of the screen. if x < 0 current
1351  * value will be kept.
1352  * @param y Position on the y-ayis (0 == top) of the screen. if y < 0, current
1353  * value will be kept.
1354  * @return @c EINA_TRUE if position could successfully be altered.
1355  */
1356 EAPI Eina_Bool 
1357 ecore_x_randr_crtc_pos_set(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int x, int y)
1358 {
1359 #ifdef ECORE_XRANDR
1360    int cx = 0, cy = 0, cw = 0, ch = 0;
1361    int sw = 0, sh = 0, nw = 0, nh = 0;
1362
1363    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
1364
1365    /* grab the current crtc geometry */
1366    ecore_x_randr_crtc_geometry_get(root, crtc, &cx, &cy, &cw, &ch);
1367
1368    /* grab the current screen geometry */
1369    ecore_x_randr_screen_current_size_get(root, &sw, &sh, NULL, NULL);
1370
1371    /* safety check some values */
1372    if (x < 0) x = cx;
1373    if (y < 0) y = cy;
1374    if ((x + cw) > sw) nw = (x + cw);
1375    if ((y + ch) > sh) nh = (y + ch);
1376
1377    if ((nw > 0) && (nh > 0))
1378      {
1379         /* try to update the current screen geometry */
1380         if (!ecore_x_randr_screen_current_size_set(root, nw, nh, 0, 0))
1381           return EINA_FALSE;
1382      }
1383
1384    /* try to set the new crtc position */
1385    return ecore_x_randr_crtc_settings_set(root, crtc, NULL, -1, x, y, -1, -1);
1386 #endif
1387    return EINA_FALSE;
1388 }
1389
1390 /**
1391  * @brief Get the current set mode of a given CRTC
1392  * @param root the window's screen to be queried
1393  * @param crtc the CRTC which's should be queried
1394  * @return currently set mode or - in case parameters are invalid -
1395  * Ecore_X_Randr_Unset
1396  */
1397 EAPI Ecore_X_Randr_Mode 
1398 ecore_x_randr_crtc_mode_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc)
1399 {
1400 #ifdef ECORE_XRANDR
1401    XRRScreenResources *res = NULL;
1402
1403    if (_randr_version < RANDR_VERSION_1_2) return -1;
1404
1405    /* try to get the screen resources from Xrandr */
1406    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1407      {
1408         XRRCrtcInfo *info = NULL;
1409         Ecore_X_Randr_Mode ret = -1;
1410
1411         /* try to get crtc info */
1412         if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1413           {
1414              /* get the mode */
1415              ret = info->mode;
1416
1417              /* free the crtc info */
1418              XRRFreeCrtcInfo(info);
1419           }
1420
1421         /* free the resources */
1422         XRRFreeScreenResources(res);
1423
1424         return ret;
1425      }
1426 #endif
1427    return -1;
1428 }
1429
1430 /**
1431  * @brief Sets a mode for a CRTC and the outputs attached to it.
1432  *
1433  * @param root The window's screen to be queried.
1434  * @param crtc The CRTC which shall be set.
1435  * @param outputs Array of outputs which have to be compatible with the mode.
1436  * If @c NULL, CRTC will be disabled.
1437  * @param noutputs Number of outputs in array to be used. Use
1438  * Ecore_X_Randr_Unset (or @c -1) to use currently used outputs.
1439  * @param mode XID of the mode to be set. If set to @c 0 the CRTC will be
1440  * disabled. If set to @c -1 the call will fail.
1441  * @return @c EINA_TRUE if mode setting was successful, @c EINA_FALSE
1442  * otherwise.
1443  */
1444 EAPI Eina_Bool 
1445 ecore_x_randr_crtc_mode_set(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, Ecore_X_Randr_Output *outputs, int noutputs, Ecore_X_Randr_Mode mode)
1446 {
1447 #ifdef ECORE_XRANDR
1448    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
1449
1450    return ecore_x_randr_crtc_settings_set(root, crtc, outputs, noutputs, 
1451                                           -1, -1, mode, -1);
1452 #endif
1453    return EINA_FALSE;
1454 }
1455
1456 EAPI void 
1457 ecore_x_randr_crtc_size_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int *w, int *h)
1458 {
1459 #ifdef ECORE_XRANDR
1460    if (_randr_version < RANDR_VERSION_1_2) return;
1461    ecore_x_randr_crtc_geometry_get(root, crtc, NULL, NULL, w, h);
1462 #endif
1463 }
1464
1465 EAPI Ecore_X_Randr_Refresh_Rate 
1466 ecore_x_randr_crtc_refresh_rate_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc EINA_UNUSED, Ecore_X_Randr_Mode mode)
1467 {
1468 #ifdef ECORE_XRANDR
1469    XRRScreenResources *res = NULL;
1470
1471    if (_randr_version < RANDR_VERSION_1_2) return 0.0;
1472
1473    /* try to get the screen resources from Xrandr */
1474    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1475      {
1476         int i = 0;
1477         double ret = 0.0;
1478
1479         for (i = 0; i < res->nmode; i++)
1480           {
1481              if (res->modes[i].id == mode)
1482                {
1483                   if ((res->modes[i].hTotal) && (res->modes[i].vTotal))
1484                     {
1485                        ret = ((double)res->modes[i].dotClock /
1486                               ((double)res->modes[i].hTotal *
1487                                   (double)res->modes[i].vTotal));
1488                     }
1489                   break;
1490                }
1491           }
1492
1493         /* free the resources */
1494         XRRFreeScreenResources(res);
1495
1496         return ret;
1497      }
1498 #endif
1499    return 0.0;
1500 }
1501
1502 EAPI Ecore_X_Randr_Orientation 
1503 ecore_x_randr_crtc_orientations_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc)
1504 {
1505 #ifdef ECORE_XRANDR
1506    XRRScreenResources *res = NULL;
1507
1508    if (_randr_version < RANDR_VERSION_1_2) return 0;
1509
1510    /* try to get the screen resources from Xrandr */
1511    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1512      {
1513         XRRCrtcInfo *info = NULL;
1514         Ecore_X_Randr_Orientation ret = 0;
1515
1516         /* try to get crtc info */
1517         if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1518           {
1519              /* get the mode */
1520              ret = info->rotations;
1521
1522              /* free the crtc info */
1523              XRRFreeCrtcInfo(info);
1524           }
1525
1526         /* free the resources */
1527         XRRFreeScreenResources(res);
1528
1529         return ret;
1530      }
1531 #endif
1532    return 0;
1533 }
1534
1535 EAPI Ecore_X_Randr_Orientation 
1536 ecore_x_randr_crtc_orientation_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc)
1537 {
1538 #ifdef ECORE_XRANDR
1539    XRRScreenResources *res = NULL;
1540
1541    if (_randr_version < RANDR_VERSION_1_2) return 0;
1542
1543    /* try to get the screen resources from Xrandr */
1544    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1545      {
1546         XRRCrtcInfo *info = NULL;
1547         Ecore_X_Randr_Orientation ret = 0;
1548
1549         /* try to get crtc info */
1550         if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1551           {
1552              /* get the mode */
1553              ret = info->rotation;
1554
1555              /* free the crtc info */
1556              XRRFreeCrtcInfo(info);
1557           }
1558
1559         /* free the resources */
1560         XRRFreeScreenResources(res);
1561
1562         return ret;
1563      }
1564 #endif
1565    return 0;
1566 }
1567
1568 EAPI Eina_Bool 
1569 ecore_x_randr_crtc_orientation_set(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, const Ecore_X_Randr_Orientation orientation)
1570 {
1571 #ifdef ECORE_XRANDR
1572    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
1573
1574    if (orientation != 0)
1575      return ecore_x_randr_crtc_settings_set(root, crtc, NULL, 
1576                                             -1, -1, -1, -1, orientation);
1577 #endif
1578    return EINA_FALSE;
1579 }
1580
1581 EAPI Eina_Bool 
1582 ecore_x_randr_crtc_clone_set(Ecore_X_Window root, Ecore_X_Randr_Crtc original, Ecore_X_Randr_Crtc cln)
1583 {
1584 #ifdef ECORE_XRANDR
1585    Eina_Bool ret = EINA_FALSE;
1586    XRRScreenResources *res = NULL;
1587
1588    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
1589
1590    /* try to get the screen resources from Xrandr */
1591    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1592      {
1593         XRRCrtcInfo *info = NULL;
1594         Ecore_X_Randr_Orientation orig_orient = 0;
1595         Ecore_X_Randr_Mode orig_mode = -1;
1596         int ox = 0, oy = 0;
1597
1598         /* try to get crtc info for original crtc */
1599         if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, original)))
1600           {
1601              ox = info->x;
1602              oy = info->y;
1603              orig_orient = info->rotation;
1604              orig_mode = info->mode;
1605
1606              /* free the crtc info */
1607              XRRFreeCrtcInfo(info);
1608           }
1609
1610         ret = ecore_x_randr_crtc_settings_set(root, cln, NULL, -1, ox, oy, 
1611                                               orig_mode, orig_orient);
1612
1613         /* free the resources */
1614         XRRFreeScreenResources(res);
1615
1616         return ret;
1617      }
1618 #endif
1619    return EINA_FALSE;
1620 }
1621
1622 /**
1623  * @brief Sets the demanded parameters for a given CRTC. Note that the CRTC is
1624  * auto enabled in it's preferred mode, when it was disabled before.
1625  *
1626  * @param root The root window which's default display will be queried.
1627  * @param crtc The CRTC which's configuration should be altered.
1628  * @param outputs An array of outputs, that should display this CRTC's content.
1629  * @param noutputs Number of outputs in the array of outputs. If set to
1630  * Ecore_X_Randr_Unset, current outputs and number of outputs will be used.
1631  * If set to Ecore_X_Randr_None, CRTC will be disabled.
1632  * @param x New x coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current x
1633  * corrdinate will be assumed.
1634  * @param y New y coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current y
1635  * corrdinate will be assumed.
1636  * @param mode The new mode to be set. If Ecore_X_Randr_None is passed, the
1637  * CRTC will be disabled. If Ecore_X_Randr_Unset is passed, the current mode is
1638  * assumed.
1639  * @param orientation The new orientation to be set. If Ecore_X_Randr_Unset is
1640  * used, the current mode is assumed.
1641  * @return @c EINA_TRUE if the configuration alteration was successful,
1642  * @c EINA_FALSE otherwise.
1643  */
1644 EAPI Eina_Bool 
1645 ecore_x_randr_crtc_settings_set(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, Ecore_X_Randr_Output *outputs, int noutputs, int x, int y, Ecore_X_Randr_Mode mode, Ecore_X_Randr_Orientation orientation)
1646 {
1647 #ifdef ECORE_XRANDR
1648    Eina_Bool ret = EINA_FALSE;
1649    XRRScreenResources *res = NULL;
1650
1651    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
1652
1653    /* try to get the screen resources from Xrandr */
1654    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1655      {
1656         RRCrtc rcrtc;
1657         RROutput *routputs = NULL;
1658         XRRCrtcInfo *info = NULL;
1659         Eina_Bool need_free = EINA_FALSE;
1660         int i = 0;
1661
1662         rcrtc = (RRCrtc)crtc;
1663
1664         /* try to get crtc info for original crtc */
1665         if (!(info = XRRGetCrtcInfo(_ecore_x_disp, res, rcrtc)))
1666           {
1667              /* free the resources */
1668              XRRFreeScreenResources(res);
1669              return EINA_FALSE;
1670           }
1671
1672         if ((int)mode == -1) mode = info->mode;
1673         if ((int)orientation == -1) orientation = info->rotation;
1674         if (x < 0) x = info->x;
1675         if (y < 0) y = info->y;
1676
1677         if (noutputs < 0)
1678           {
1679              noutputs = info->noutput;
1680              routputs = malloc(noutputs * sizeof(RROutput));
1681              for (i = 0; i < noutputs; i++)
1682                routputs[i] = info->outputs[i];
1683              need_free = EINA_TRUE;
1684           }
1685         else if (noutputs > 0)
1686           {
1687              routputs = malloc(noutputs * sizeof(RROutput));
1688              for (i = 0; i < noutputs; i++)
1689                routputs[i] = (RROutput)outputs[i];
1690              need_free = EINA_TRUE;
1691           }
1692
1693         /* try to set the crtc config */
1694         if (!XRRSetCrtcConfig(_ecore_x_disp, res, rcrtc, CurrentTime, 
1695                               x, y, mode, orientation, 
1696                               routputs, noutputs))
1697           ret = EINA_TRUE;
1698
1699         if (need_free) free(routputs);
1700
1701         /* free the crtc info */
1702         XRRFreeCrtcInfo(info);
1703
1704         /* free the resources */
1705         XRRFreeScreenResources(res);
1706      }
1707
1708    return ret;
1709 #endif
1710    return EINA_FALSE;
1711 }
1712
1713 /**
1714  * @brief Sets a CRTC relative to another one.
1715  *
1716  * @param root The root window which's default display will be set.
1717  * @param crtc_r1 The CRTC to be positioned.
1718  * @param crtc_r2 The CRTC the position should be relative to.
1719  * @param policy The relation between the crtcs.
1720  * @param alignment In case CRTCs size differ, aligns CRTC1 accordingly at
1721  * CRTC2's borders.
1722  * @return @c EINA_TRUE if crtc could be successfully positioned, @c EINA_FALSE
1723  * if repositioning failed or if position of new crtc would be out of given
1724  * screen's min/max bounds.
1725  */
1726 EAPI Eina_Bool 
1727 ecore_x_randr_crtc_pos_relative_set(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc_r1, Ecore_X_Randr_Crtc crtc_r2, Ecore_X_Randr_Output_Policy policy, Ecore_X_Randr_Relative_Alignment alignment)
1728 {
1729 #ifdef ECORE_XRANDR
1730    Eina_Rectangle r1, r2;
1731    int mw = 0, mh = 0, sw = 0, sh = 0;
1732    int nx = 0, ny = 0;
1733
1734    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
1735
1736    /* check each crtc has a valid mode */
1737    if (ecore_x_randr_crtc_mode_get(root, crtc_r1) == 0) return EINA_FALSE;
1738    if (ecore_x_randr_crtc_mode_get(root, crtc_r2) == 0) return EINA_FALSE;
1739
1740    /* get the geometry of each crtc */
1741    ecore_x_randr_crtc_geometry_get(root, crtc_r1, &r1.x, &r1.y, &r1.w, &r1.h);
1742    ecore_x_randr_crtc_geometry_get(root, crtc_r2, &r2.x, &r2.y, &r2.w, &r2.h);
1743
1744    /* get the geometry of the screen */
1745    ecore_x_randr_screen_size_range_get(root, NULL, NULL, &mw, &mh);
1746    ecore_x_randr_screen_current_size_get(root, &sw, &sh, NULL, NULL);
1747
1748    switch (policy)
1749      {
1750       case ECORE_X_RANDR_OUTPUT_POLICY_RIGHT:
1751         nx = (r2.x + r2.w);
1752
1753         switch (alignment)
1754           {
1755            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1756              ny = -1;
1757              break;
1758            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1759              ny = ((int)(((double)r2.h / 2.0) + r2.y - ((double)r1.h / 2.0)));
1760              break;
1761            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1762              ny = ((int)((double)sh / 2.0) - ((double)r1.h / 2.0));
1763              break;
1764           }
1765
1766         break;
1767       case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
1768         nx = (r2.x - r1.w);
1769
1770         switch (alignment)
1771           {
1772            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1773              ny = -1;
1774              break;
1775            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1776              ny = ((int)(((double)r2.h / 2.0) + r2.y - ((double)r1.h / 2.0)));
1777              break;
1778            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1779              ny = ((int)((double)sh / 2.0) - ((double)r1.h / 2.0));
1780              break;
1781           }
1782
1783         break;
1784       case ECORE_X_RANDR_OUTPUT_POLICY_BELOW:
1785         ny = (r2.y + r2.h);
1786
1787         switch (alignment)
1788           {
1789            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1790              nx = -1;
1791              break;
1792            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1793              nx = ((int)((((double)r2.x + (double)r2.w) / 2.0) - 
1794                          ((double)r1.w / 2.0)));
1795              break;
1796            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1797              nx = ((int)((double)sw / 2.0));
1798              break;
1799           }
1800
1801         break;
1802       case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
1803         ny = (r2.y - r1.h);
1804
1805         switch (alignment)
1806           {
1807            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1808              nx = -1;
1809              break;
1810            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1811              nx = ((int)((((double)r2.x + (double)r2.w) / 2.0) - 
1812                          ((double)r1.w / 2.0)));
1813              break;
1814            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1815              nx = ((int)((double)sw / 2.0));
1816              break;
1817           }
1818
1819         break;
1820       case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
1821         return ecore_x_randr_crtc_pos_set(root, crtc_r1, r2.x, r2.y);
1822         break;
1823       case ECORE_X_RANDR_OUTPUT_POLICY_NONE:
1824         break;
1825       default:
1826         return EINA_FALSE;
1827      }
1828
1829    if ((nx == r1.x) && (ny == r1.y)) return EINA_TRUE;
1830    if (((ny + r1.h) > mh) || ((nx + r1.w) > mw)) return EINA_FALSE;
1831
1832    return ecore_x_randr_crtc_pos_set(root, crtc_r1, nx, ny);
1833 #else
1834    return EINA_FALSE;
1835 #endif
1836 }
1837
1838 /*
1839  * @since 1.8
1840  */
1841 EAPI Ecore_X_Randr_Crtc_Info *
1842 ecore_x_randr_crtc_info_get(Ecore_X_Window root, const Ecore_X_Randr_Crtc crtc)
1843 {
1844 #ifdef ECORE_XRANDR
1845    XRRScreenResources *res = NULL;
1846
1847    if (_randr_version < RANDR_VERSION_1_2) return NULL;
1848
1849    /* try to get the screen resources from Xrandr */
1850    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1851      {
1852         XRRCrtcInfo *info = NULL;
1853         Ecore_X_Randr_Crtc_Info *ret = NULL;
1854
1855         /* try to get crtc info */
1856         if ((info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1857           {
1858              if ((ret = malloc(sizeof(Ecore_X_Randr_Crtc_Info))))
1859                {
1860                   /* copy the mode information into our return structure */
1861                   ret->timestamp = info->timestamp;
1862                   ret->x = info->x;
1863                   ret->y = info->y;
1864                   ret->width = info->width;
1865                   ret->height = info->height;
1866                   ret->mode = info->mode;
1867                   ret->rotation = info->rotation;
1868                   ret->rotations = info->rotations;
1869                   ret->noutput = info->noutput;
1870                   ret->npossible = info->npossible;
1871
1872                   if ((ret->outputs = 
1873                        malloc(info->noutput * sizeof(Ecore_X_Randr_Output))))
1874                     {
1875                        int i = 0;
1876
1877                        /* loop the outputs on this crtc */
1878                        for (i = 0; i < info->noutput; i++)
1879                          ret->outputs[i] = info->outputs[i];
1880                     }
1881
1882                   if ((ret->possible = 
1883                        malloc(info->npossible * sizeof(Ecore_X_Randr_Output))))
1884                     {
1885                        int i = 0;
1886
1887                        /* loop the outputs on this crtc */
1888                        for (i = 0; i < info->npossible; i++)
1889                          ret->possible[i] = info->possible[i];
1890                     }
1891                }
1892
1893              /* free the crtc info */
1894              XRRFreeCrtcInfo(info);
1895           }
1896
1897         /* free the resources */
1898         XRRFreeScreenResources(res);
1899
1900         return ret;
1901      }
1902 #endif
1903    return NULL;
1904 }
1905
1906 /*
1907  * @since 1.8
1908  */
1909 EAPI void 
1910 ecore_x_randr_crtc_info_free(Ecore_X_Randr_Crtc_Info *info)
1911 {
1912 #ifdef ECORE_XRANDR
1913    if (_randr_version >= RANDR_VERSION_1_2)
1914      {
1915         if (info)
1916           {
1917              if (info->outputs) free(info->outputs);
1918              if (info->possible) free(info->possible);
1919              free(info);
1920              info = NULL;
1921           }
1922      }
1923 #endif
1924 }
1925
1926 /*
1927  * @brief Add given mode to given output.
1928  *
1929  * @param output The output the mode is added to.
1930  * @param mode The mode added to the output.
1931  * @return @c EINA_FALSE if output or mode equal Ecore_X_Randr_None, else
1932  * @c EINA_TRUE.
1933  * Additionally, if xcb backend is used, the success of the addition is
1934  * reported back directly.
1935  * @since 1.2.0
1936  */
1937 EAPI Eina_Bool 
1938 ecore_x_randr_output_mode_add(Ecore_X_Randr_Output output, Ecore_X_Randr_Mode mode)
1939 {
1940 #ifdef ECORE_XRANDR
1941    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
1942
1943    if ((output) && (mode))
1944      {
1945         /* add this mode to output
1946          * 
1947          * NB: This XRR function returns void so we have to assume it worked */
1948         XRRAddOutputMode(_ecore_x_disp, output, mode);
1949
1950         return EINA_TRUE;
1951      }
1952 #endif
1953    return EINA_FALSE;
1954 }
1955
1956 /*
1957  * @brief delete given mode from given output
1958  * @param output the output the mode is removed from
1959  * @param mode the mode removed from the output
1960  * @since 1.2.0
1961  */
1962 EAPI void 
1963 ecore_x_randr_output_mode_del(Ecore_X_Randr_Output output, Ecore_X_Randr_Mode mode)
1964 {
1965 #ifdef ECORE_XRANDR
1966    if (_randr_version < RANDR_VERSION_1_2) return;
1967
1968    if ((!output) || (!mode)) return;
1969
1970    XRRDeleteOutputMode(_ecore_x_disp, output, mode);
1971 #endif
1972 }
1973
1974 EAPI Ecore_X_Randr_Mode *
1975 ecore_x_randr_output_modes_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *num, int *npreferred)
1976 {
1977 #ifdef ECORE_XRANDR
1978    XRRScreenResources *res = NULL;
1979
1980    if (_randr_version < RANDR_VERSION_1_2) return NULL;
1981
1982    /* try to get the screen resources from Xrandr */
1983    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
1984      {
1985         XRROutputInfo *info = NULL;
1986         Ecore_X_Randr_Mode *modes = NULL;
1987
1988         /* try to get output info */
1989         if ((info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1990           {
1991              if (num) *num = info->nmode;
1992              if (npreferred) *npreferred = info->npreferred;
1993
1994              if (info->nmode > 0)
1995                {
1996                   if ((modes = malloc(info->nmode * sizeof(Ecore_X_Randr_Mode))))
1997                     {
1998                        int i = 0;
1999
2000                        for (i = 0; i < info->nmode; i++)
2001                          modes[i] = info->modes[i];
2002                     }
2003                }
2004
2005              /* free the output info */
2006              XRRFreeOutputInfo(info);
2007           }
2008
2009         /* free the resources */
2010         XRRFreeScreenResources(res);
2011
2012         return modes;
2013      }
2014 #endif
2015    return NULL;
2016 }
2017
2018 /**
2019  * @brief gets the the outputs which might be used simultenously on the same
2020  * CRTC.
2021  * @param root window that this information should be queried for.
2022  * @param output the output which's clones we concern
2023  * @param num number of possible clones
2024  */
2025 EAPI Ecore_X_Randr_Output *
2026 ecore_x_randr_output_clones_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *num)
2027 {
2028 #ifdef ECORE_XRANDR
2029    XRRScreenResources *res = NULL;
2030
2031    if (_randr_version < RANDR_VERSION_1_2) return NULL;
2032
2033    /* try to get the screen resources from Xrandr */
2034    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2035      {
2036         XRROutputInfo *info = NULL;
2037         Ecore_X_Randr_Output *outputs = NULL;
2038
2039         /* try to get output info */
2040         if ((info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
2041           {
2042              if (num) *num = info->nclone;
2043
2044              if (info->nclone > 0)
2045                {
2046                   /* try to allocate space for output return */
2047                   if ((outputs = malloc(info->nclone * sizeof(Ecore_X_Randr_Output))))
2048                     {
2049                        int i = 0;
2050
2051                        for (i = 0; i < info->nclone; i++)
2052                          outputs[i] = info->clones[i];
2053                     }
2054                }
2055
2056              /* free the output info */
2057              XRRFreeOutputInfo(info);
2058           }
2059
2060         /* free the resources */
2061         XRRFreeScreenResources(res);
2062
2063         return outputs;
2064      }
2065 #endif
2066    return NULL;
2067 }
2068
2069 EAPI Ecore_X_Randr_Crtc *
2070 ecore_x_randr_output_possible_crtcs_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *num)
2071 {
2072 #ifdef ECORE_XRANDR
2073    XRRScreenResources *res = NULL;
2074
2075    if (_randr_version < RANDR_VERSION_1_2) return 0;
2076
2077    /* try to get the screen resources from Xrandr */
2078    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2079      {
2080         XRROutputInfo *info = NULL;
2081         Ecore_X_Randr_Crtc *crtcs = NULL;
2082
2083         /* try to get output info */
2084         if ((info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
2085           {
2086              if (num) *num = info->ncrtc;
2087
2088              if (info->ncrtc > 0)
2089                {
2090                   /* try to allocate space for the return crtcs */
2091                   if ((crtcs = malloc(info->ncrtc * sizeof(Ecore_X_Randr_Crtc))))
2092                     {
2093                        int i = 0;
2094
2095                        for (i = 0; i < info->ncrtc; i++)
2096                          crtcs[i] = info->crtcs[i];
2097                     }
2098                }
2099
2100              /* free the output info */
2101              XRRFreeOutputInfo(info);
2102           }
2103
2104         /* free the resources */
2105         XRRFreeScreenResources(res);
2106
2107         return crtcs;
2108      }
2109 #endif
2110    return NULL;
2111 }
2112
2113 EAPI Ecore_X_Randr_Crtc 
2114 ecore_x_randr_output_crtc_get(Ecore_X_Window root, Ecore_X_Randr_Output output)
2115 {
2116 #ifdef ECORE_XRANDR
2117    XRRScreenResources *res = NULL;
2118
2119    if (_randr_version < RANDR_VERSION_1_2) return 0;
2120
2121    /* try to get the screen resources from Xrandr */
2122    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2123      {
2124         XRROutputInfo *info = NULL;
2125         Ecore_X_Randr_Crtc ret = 0;
2126
2127         /* try to get output info */
2128         if ((info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
2129           {
2130              ret = info->crtc;
2131
2132              /* free the output info */
2133              XRRFreeOutputInfo(info);
2134           }
2135
2136         /* free the resources */
2137         XRRFreeScreenResources(res);
2138
2139         return ret;
2140      }
2141 #endif
2142    return 0;
2143 }
2144
2145 /**
2146  * @brief gets the given output's name as reported by X
2147  * @param root the window which's screen will be queried
2148  * @param output The output for which the name will be reported.
2149  * @param len length of returned c-string.
2150  * @return name of the output as reported by X
2151  */
2152 EAPI char *
2153 ecore_x_randr_output_name_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *len)
2154 {
2155 #ifdef ECORE_XRANDR
2156    XRRScreenResources *res = NULL;
2157
2158    if (_randr_version < RANDR_VERSION_1_2) return 0;
2159
2160    /* try to get the screen resources from Xrandr */
2161    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2162      {
2163         XRROutputInfo *info = NULL;
2164         char *ret = NULL;
2165
2166         /* try to get output info */
2167         if ((info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
2168           {
2169              if (info->name)
2170                {
2171                   /* FIXME: TODO: NB:
2172                    * 
2173                    * Old randr code says there is an xrandr bug here with 
2174                    * nameLen. Test This !!!
2175                    * 
2176                    */
2177                   ret = strdup(info->name);
2178                   if (len) *len = info->nameLen;
2179                }
2180
2181              /* free the output info */
2182              XRRFreeOutputInfo(info);
2183           }
2184
2185         /* free the resources */
2186         XRRFreeScreenResources(res);
2187
2188         return ret;
2189      }
2190 #endif
2191    return NULL;
2192 }
2193
2194 /*
2195  * @deprecated use ecore_x_randr_crtc_gamma_size_get()
2196  */
2197 EINA_DEPRECATED EAPI int 
2198 ecore_x_randr_crtc_gamma_ramp_size_get(Ecore_X_Randr_Crtc crtc EINA_UNUSED)
2199 {
2200    return 0;
2201 }
2202
2203 /*
2204  * @deprecated use ecore_x_randr_crtc_gamma_get()
2205  */
2206 EINA_DEPRECATED EAPI Ecore_X_Randr_Crtc_Gamma **
2207 ecore_x_randr_crtc_gamma_ramps_get(Ecore_X_Randr_Crtc crtc EINA_UNUSED)
2208 {
2209    return NULL;
2210 }
2211
2212 /*
2213  * @deprecated use ecore_x_randr_crtc_gamma_set()
2214  */
2215 EINA_DEPRECATED EAPI Eina_Bool 
2216 ecore_x_randr_crtc_gamma_ramps_set(Ecore_X_Randr_Crtc crtc EINA_UNUSED, const Ecore_X_Randr_Crtc_Gamma *red EINA_UNUSED, const Ecore_X_Randr_Crtc_Gamma *green EINA_UNUSED, const Ecore_X_Randr_Crtc_Gamma *blue EINA_UNUSED)
2217 {
2218    return EINA_FALSE;
2219 }
2220
2221 /*
2222  * @since 1.8
2223  */
2224 EAPI int 
2225 ecore_x_randr_crtc_gamma_size_get(Ecore_X_Randr_Crtc crtc)
2226 {
2227 #ifdef ECORE_XRANDR
2228    if (_randr_version < RANDR_VERSION_1_2) return 0;
2229    return XRRGetCrtcGammaSize(_ecore_x_disp, crtc);
2230 #endif
2231    return 0;
2232 }
2233
2234 /*
2235  * @since 1.8
2236  */
2237 EAPI Ecore_X_Randr_Crtc_Gamma_Info *
2238 ecore_x_randr_crtc_gamma_get(Ecore_X_Randr_Crtc crtc)
2239 {
2240 #ifdef ECORE_XRANDR
2241    Ecore_X_Randr_Crtc_Gamma_Info *info = NULL;
2242    XRRCrtcGamma *xgamma = NULL;
2243
2244    if (_randr_version < RANDR_VERSION_1_2) return NULL;
2245
2246    /* try to get the gamma for this crtc from Xrandr */
2247    if (!(xgamma = XRRGetCrtcGamma(_ecore_x_disp, crtc)))
2248      return NULL;
2249
2250    /* try to allocate space for the return struct and copy the results in */
2251    if ((info = malloc(sizeof(Ecore_X_Randr_Crtc_Gamma_Info))))
2252      memcpy(info, xgamma, sizeof(Ecore_X_Randr_Crtc_Gamma_Info));
2253
2254    /* free the returned gamma resource */
2255    XRRFreeGamma(xgamma);
2256
2257    return info;
2258 #endif
2259    return NULL;
2260 }
2261
2262 /*
2263  * @since 1.8
2264  */
2265 EAPI Eina_Bool 
2266 ecore_x_randr_crtc_gamma_set(Ecore_X_Randr_Crtc crtc, const Ecore_X_Randr_Crtc_Gamma_Info *gamma)
2267 {
2268 #ifdef ECORE_XRANDR
2269    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
2270
2271    /* try to set the gamma
2272     * 
2273     * NB: XRRSetCrtcGamma returns void
2274     */
2275    XRRSetCrtcGamma(_ecore_x_disp, crtc, (XRRCrtcGamma *)gamma);
2276    return EINA_TRUE;
2277 #endif
2278    return EINA_FALSE;
2279 }
2280
2281 EAPI Eina_Bool 
2282 ecore_x_randr_move_all_crtcs_but(Ecore_X_Window root, const Ecore_X_Randr_Crtc *not_moved, int nnot_moved, int dx, int dy)
2283 {
2284 #ifdef ECORE_XRANDR
2285    XRRScreenResources *res = NULL;
2286    Eina_Bool ret = EINA_FALSE;
2287
2288    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
2289
2290    if ((nnot_moved <= 0) || (!not_moved)) return EINA_FALSE;
2291
2292    /* try to get the screen resources from Xrandr */
2293    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2294      {
2295         Ecore_X_Randr_Crtc *crtcs = NULL;
2296         int n = 0;
2297
2298         n = (res->ncrtc - nnot_moved);
2299         if (n > 0)
2300           {
2301              /* try to allocate space for a list of crtcs */
2302              if ((crtcs = malloc(n * sizeof(Ecore_X_Randr_Crtc))))
2303                {
2304                   int i = 0, j = 0, k = 0;
2305
2306                   for (i = 0, k = 0; (i < res->ncrtc) && (k < n); i++)
2307                     {
2308                        for (j = 0; j < nnot_moved; j++)
2309                          {
2310                             if (res->crtcs[i] == not_moved[j])
2311                               break;
2312                          }
2313
2314                        if (j == nnot_moved) crtcs[k++] = res->crtcs[i];
2315                     }
2316                }
2317           }
2318
2319         /* free the resources */
2320         XRRFreeScreenResources(res);
2321
2322         /* actually move the crtcs */
2323         if (crtcs)
2324           {
2325              ret = ecore_x_randr_move_crtcs(root, crtcs, n, dx, dy);
2326              free(crtcs);
2327           }
2328
2329         return ret;
2330      }
2331 #endif
2332    return EINA_FALSE;
2333 }
2334
2335 /*
2336  * @brief Move given CRTCs belonging to the given root window's screen dx/dy
2337  * pixels relative to their current position. The screen size will be
2338  * automatically adjusted if necessary and possible.
2339  *
2340  * @param root Window which's screen's resources are used.
2341  * @param crtcs List of CRTCs to be moved.
2342  * @param ncrtc Number of CRTCs in array.
2343  * @param dx Amount of pixels the CRTCs should be moved in x direction.
2344  * @param dy Amount of pixels the CRTCs should be moved in y direction.
2345  * @return @c EINA_TRUE if all crtcs could be moved successfully.
2346  */
2347 EAPI Eina_Bool 
2348 ecore_x_randr_move_crtcs(Ecore_X_Window root, const Ecore_X_Randr_Crtc *crtcs, int ncrtc, int dx, int dy)
2349 {
2350 #ifdef ECORE_XRANDR
2351    XRRScreenResources *res = NULL;
2352    XRRCrtcInfo **info = NULL;
2353    int i = 0;
2354
2355    if (_randr_version < RANDR_VERSION_1_2) return EINA_FALSE;
2356
2357    if (ncrtc < 1) return EINA_FALSE;
2358
2359    /* try to get the screen resources from Xrandr */
2360    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2361      {
2362         Eina_Bool ret = EINA_TRUE;
2363         int mw = 0, mh = 0, sw = 0, sh = 0;
2364         int nw = 0, nh = 0;
2365
2366         info = alloca(ncrtc * sizeof(XRRCrtcInfo *));
2367         memset(info, 0, ncrtc * sizeof(XRRCrtcInfo *));
2368
2369         ecore_x_randr_screen_size_range_get(root, NULL, NULL, &mw, &mh);
2370         ecore_x_randr_screen_current_size_get(root, &sw, &sh, NULL, NULL);
2371         nw = sw;
2372         nh = sh;
2373
2374         for (i = 0; i < ncrtc; i++)
2375           {
2376              /* try to get crtc info for original crtc */
2377              if ((info[i] = XRRGetCrtcInfo(_ecore_x_disp, res, crtcs[i])))
2378                {
2379                   if (((info[i]->x + dx) < 0) || ((info[i]->y + dy < 0)) || 
2380                       ((int)(info[i]->x + info[i]->width) > mw) || 
2381                       ((int)(info[i]->y + info[i]->height) > mh))
2382                     {
2383                        goto err;
2384                     }
2385
2386                   nw = MAX(((int)(info[i]->x + info[i]->width) + dx), nw);
2387                   nh = MAX(((int)(info[i]->y + info[i]->height) + dy), nh);
2388                }
2389           }
2390
2391         /* resize the screen if we need to */
2392         if (!(((nw > sw) || (nh > sh)) || 
2393               ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1)))
2394           goto err;
2395
2396         /* actually move the crtcs */
2397         for (i = 0; ((i < ncrtc) && info[i]); i++)
2398           {
2399              if (!ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL, -1, 
2400                                                   (info[i]->x + dx), 
2401                                                   (info[i]->y + dy), 
2402                                                   info[i]->mode, 
2403                                                   info[i]->rotation))
2404                {
2405                   ret = EINA_FALSE;
2406                   break;
2407                }
2408           }
2409
2410         if (i < ncrtc)
2411           {
2412              /* something went wrong somewhere. move everything back */
2413              while (i-- >= 0)
2414                {
2415                   if (info[i])
2416                     ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL, -1, 
2417                                                     (info[i]->x - dx), 
2418                                                     (info[i]->y - dy), 
2419                                                     info[i]->mode, 
2420                                                     info[i]->rotation);
2421                }
2422           }
2423
2424         /* cleanup */
2425         for (i = 0; i < ncrtc; i++)
2426           if (info[i]) XRRFreeCrtcInfo(info[i]);
2427
2428         /* free the resources */
2429         XRRFreeScreenResources(res);
2430
2431         return ret;
2432      }
2433
2434 err:
2435    while (i-- > 0)
2436      {
2437         /* free the crtc info */
2438         if (info[i]) XRRFreeCrtcInfo(info[i]);
2439      }
2440
2441    /* free the resources */
2442    if (res) XRRFreeScreenResources(res);
2443 #endif
2444    return EINA_FALSE;
2445 }
2446
2447 /**
2448  * @brief gets the width and hight of a given mode
2449  * @param mode the mode which's size is to be looked up
2450  * @param w width of given mode in px
2451  * @param h height of given mode in px
2452  */
2453 EAPI void 
2454 ecore_x_randr_mode_size_get(Ecore_X_Window root, Ecore_X_Randr_Mode mode, int *w, int *h)
2455 {
2456 #ifdef ECORE_XRANDR
2457    if (_randr_version < RANDR_VERSION_1_2) return;
2458
2459    if ((mode != 0) && ((w) || (h)))
2460      {
2461         XRRScreenResources *res = NULL;
2462
2463         /* try to get the screen resources from Xrandr */
2464         if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2465           {
2466              int i = 0;
2467
2468              for (i = 0; i < res->nmode; i++)
2469                {
2470                   if (res->modes[i].id == mode)
2471                     {
2472                        if (w) *w = res->modes[i].width;
2473                        if (h) *h = res->modes[i].height;
2474                        break;
2475                     }
2476                }
2477
2478              /* free the resources */
2479              XRRFreeScreenResources(res);
2480           }
2481      }
2482 #endif
2483 }
2484
2485 EAPI Ecore_X_Randr_Connection_Status 
2486 ecore_x_randr_output_connection_status_get(Ecore_X_Window root, Ecore_X_Randr_Output output)
2487 {
2488 #ifdef ECORE_XRANDR
2489    XRRScreenResources *res = NULL;
2490
2491    if (_randr_version < RANDR_VERSION_1_2) 
2492      return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
2493
2494    /* try to get the screen resources from Xrandr */
2495    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2496      {
2497         XRROutputInfo *info = NULL;
2498         Ecore_X_Randr_Connection_Status ret = 
2499           ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
2500
2501         /* try to get output info */
2502         if ((info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
2503           {
2504              ret = info->connection;
2505
2506              /* free the output info */
2507              XRRFreeOutputInfo(info);
2508           }
2509
2510         /* free the resources */
2511         XRRFreeScreenResources(res);
2512
2513         return ret;
2514      }
2515 #endif
2516    return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
2517 }
2518
2519 EAPI void 
2520 ecore_x_randr_output_size_mm_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *w, int *h)
2521 {
2522 #ifdef ECORE_XRANDR
2523    XRRScreenResources *res = NULL;
2524
2525    if (_randr_version < RANDR_VERSION_1_2) return;
2526
2527    /* try to get the screen resources from Xrandr */
2528    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2529      {
2530         XRROutputInfo *info = NULL;
2531
2532         /* try to get output info */
2533         if ((info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
2534           {
2535              if (w) *w = info->mm_width;
2536              if (h) *h = info->mm_height;
2537
2538              /* free the output info */
2539              XRRFreeOutputInfo(info);
2540           }
2541
2542         /* free the resources */
2543         XRRFreeScreenResources(res);
2544      }
2545 #endif
2546 }
2547
2548 EAPI Eina_Bool 
2549 ecore_x_randr_output_crtc_set(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output EINA_UNUSED, const Ecore_X_Randr_Crtc crtc EINA_UNUSED)
2550 {
2551    /* TODO: !! */
2552    return EINA_FALSE;
2553 }
2554
2555 EAPI Eina_Bool 
2556 ecore_x_randr_output_backlight_available(void)
2557 {
2558 #ifdef ECORE_XRANDR
2559    Atom backlight = None;
2560
2561    /* check for new backlight property */
2562    if ((backlight = XInternAtom(_ecore_x_disp, RR_PROPERTY_BACKLIGHT, True)))
2563      return EINA_TRUE;
2564
2565    /* check for legacy backlight property */
2566    if ((backlight = XInternAtom(_ecore_x_disp, "BACKLIGHT", True)))
2567      return EINA_TRUE;
2568 #endif
2569    return EINA_FALSE;
2570 }
2571
2572 /**
2573  * @brief Set up the backlight level to the given level.
2574  *
2575  * @param root The window's screen which will be set.
2576  * @param level Of the backlight between @c 0 and @c 1.
2577  */
2578 EAPI void 
2579 ecore_x_randr_screen_backlight_level_set(Ecore_X_Window root, double level)
2580 {
2581 #ifdef ECORE_XRANDR
2582    XRRScreenResources *res = NULL;
2583    int i = 0;
2584
2585    if (_randr_version < RANDR_VERSION_1_3) return;
2586
2587    /* try to get the screen resources from Xrandr */
2588    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2589      {
2590         /* set the backlight level on each output */
2591         for (i = 0; i < res->noutput; i++)
2592           ecore_x_randr_output_backlight_level_set(root, res->outputs[i], level);
2593
2594         /* free the resources */
2595         XRRFreeScreenResources(res);
2596      }
2597 #endif
2598 }
2599
2600 EAPI double 
2601 ecore_x_randr_output_backlight_level_get(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output)
2602 {
2603 #ifdef ECORE_XRANDR
2604    XRRPropertyInfo *info = NULL;
2605    Atom backlight = None, type = None;
2606    unsigned long bytes = 0;
2607    unsigned long items = 0;
2608    unsigned char *prop = NULL;
2609    long val = 0;
2610    int format = 0;
2611
2612    /* check if "new" backlight is available */
2613    if (_randr_version >= RANDR_VERSION_1_3)
2614      {
2615         if ((backlight = 
2616              XInternAtom(_ecore_x_disp, RR_PROPERTY_BACKLIGHT, True)))
2617           {
2618              XRRGetOutputProperty(_ecore_x_disp, output, backlight, 0, 4, 
2619                                   False, False, None, &type, &format, 
2620                                   &items, &bytes, &prop);
2621           }
2622      }
2623
2624    if ((!prop) || (items == 0))
2625      {
2626         /* check legacy backlight property
2627          * 
2628          * FIXME: NB: Not sure what randr version we need for the legacy 
2629          * backlight property so skip version check */
2630         if ((backlight = XInternAtom(_ecore_x_disp, "BACKLIGHT", True)))
2631           {
2632              XRRGetOutputProperty(_ecore_x_disp, output, backlight, 0, 4, 
2633                                   False, False, None, &type, &format, 
2634                                   &items, &bytes, &prop);
2635           }
2636      }
2637
2638    /* safety check */
2639    if ((type != XA_INTEGER) || (items != 1) || (format != 32))
2640      {
2641         WRN("Backlight property is not supported on this server or driver");
2642         return -1;
2643      }
2644
2645    val = *((long *)prop);
2646    free(prop);
2647
2648    /* try to get the backlight property value from Xrandr */
2649    if ((info = XRRQueryOutputProperty(_ecore_x_disp, output, backlight)))
2650      {
2651         double ret = -1;
2652
2653         if ((info->range) && (info->num_values == 2))
2654           {
2655              /* convert the current value */
2656              ret = ((double)(val - info->values[0])) / 
2657                ((double)(info->values[1] - info->values[0]));
2658           }
2659
2660         /* free the info */
2661         free(info);
2662
2663         return ret;
2664      }
2665 #endif
2666    return -1;
2667 }
2668
2669 EAPI Eina_Bool 
2670 ecore_x_randr_output_backlight_level_set(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output, double level)
2671 {
2672 #ifdef ECORE_XRANDR
2673    XRRPropertyInfo *info = NULL;
2674    Atom backlight = None;
2675
2676    /* safety check some input values */
2677    if ((level < 0) || (level > 1))
2678      {
2679         ERR("Backlight level should be between 0 and 1");
2680         return EINA_FALSE;
2681      }
2682
2683    /* check if "new" backlight is available */
2684    if (_randr_version >= RANDR_VERSION_1_3)
2685      backlight = XInternAtom(_ecore_x_disp, RR_PROPERTY_BACKLIGHT, True);
2686
2687    if (!backlight)
2688      backlight = XInternAtom(_ecore_x_disp, "BACKLIGHT", True);
2689
2690    if (!backlight)
2691      {
2692         WRN("Backlight property is not supported on this server or driver");
2693         return EINA_FALSE;
2694      }
2695
2696    /* try to get the output property from Xrandr */
2697    if ((info = XRRQueryOutputProperty(_ecore_x_disp, output, backlight)))
2698      {
2699         Eina_Bool ret = EINA_FALSE;
2700
2701         if ((info->range) && (info->num_values == 2))
2702           {
2703              double min = 0.0, max = 0.0;
2704              long val = 0;
2705
2706              min = info->values[0];
2707              max = info->values[1];
2708              val = (level * (max - min)) + min;
2709              if (val > max) val = max;
2710              if (val < min) val = min;
2711
2712              /* tell xrandr to change the backlight value */
2713              XRRChangeOutputProperty(_ecore_x_disp, output, backlight, 
2714                                      XA_INTEGER, 32, PropModeReplace, 
2715                                      (unsigned char *)&val, 1);
2716
2717              /* send changes to X */
2718              ecore_x_flush();
2719
2720              ret = EINA_TRUE;
2721           }
2722
2723         /* free the info */
2724         free(info);
2725
2726         return ret;
2727      }
2728 #endif
2729    return EINA_FALSE;
2730 }
2731
2732 /**
2733  * @brief gets the EDID information of an attached output if available.
2734  * Note that this information is not to be compared using ordinary string
2735  * comparison functions, since it includes 0-bytes.
2736  * @param root window this information should be queried from
2737  * @param output the XID of the output
2738  * @param length length of the byte-array. If NULL, request will fail.
2739  */
2740 EAPI unsigned char *
2741 ecore_x_randr_output_edid_get(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output, unsigned long *length)
2742 {
2743 #ifdef ECORE_XRANDR
2744    Atom edid = None, type = None;
2745    unsigned char *prop;
2746    int format = 0;
2747    unsigned long nitems = 0, bytes = 0;
2748
2749    if (_randr_version < RANDR_VERSION_1_2) return NULL;
2750
2751    /* try to get the edid atom */
2752    if (!(edid = XInternAtom(_ecore_x_disp, RR_PROPERTY_RANDR_EDID, False))) 
2753      return NULL;
2754
2755    /* get the output property
2756     * 
2757     * NB: Returns 0 on success */
2758    if (!XRRGetOutputProperty(_ecore_x_disp, output, edid, 0, 128, False, False,
2759                             AnyPropertyType, &type, &format, &nitems, 
2760                             &bytes, &prop))
2761      {
2762         if ((type == XA_INTEGER) && (nitems >= 1) && (format == 8))
2763           {
2764              unsigned char *ret = NULL;
2765
2766              if ((ret = malloc(nitems * sizeof(unsigned char))))
2767                {
2768                   if (length) *length = nitems;
2769                   memcpy(ret, prop, (nitems * sizeof(unsigned char)));
2770                   return ret;
2771                }
2772           }
2773      }
2774 #endif
2775    return NULL;
2776 }
2777
2778 EAPI Ecore_X_Render_Subpixel_Order 
2779 ecore_x_randr_output_subpixel_order_get(Ecore_X_Window root, Ecore_X_Randr_Output output)
2780 {
2781 #ifdef ECORE_XRANDR
2782    XRRScreenResources *res = NULL;
2783
2784    if (_randr_version < RANDR_VERSION_1_2) 
2785      return ECORE_X_RENDER_SUBPIXEL_ORDER_UNKNOWN;
2786
2787    /* try to get the screen resources from Xrandr */
2788    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
2789      {
2790         XRROutputInfo *info = NULL;
2791         Ecore_X_Render_Subpixel_Order ret = 0;
2792
2793         /* try to get output info */
2794         if ((info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
2795           {
2796              ret = info->subpixel_order;
2797
2798              /* free the output info */
2799              XRRFreeOutputInfo(info);
2800           }
2801
2802         /* free the resources */
2803         XRRFreeScreenResources(res);
2804
2805         return ret;
2806      }
2807 #endif
2808    return ECORE_X_RENDER_SUBPIXEL_ORDER_UNKNOWN;
2809 }
2810
2811 /***************************************
2812  * API Functions for RandR version 1.3 *
2813  ***************************************/
2814
2815 EAPI Ecore_X_Randr_Output *
2816 ecore_x_randr_output_wired_clones_get(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output, int *num)
2817 {
2818 #ifdef ECORE_XRANDR
2819    Atom clones = None, type = None;
2820    unsigned char *prop;
2821    int format = 0;
2822    unsigned long nitems = 0, bytes = 0;
2823
2824    /* NB: FIXME: 
2825     * 
2826     * I am not sure that this code is correct. This needs checking 
2827     */
2828
2829    if (_randr_version < RANDR_VERSION_1_3) return NULL;
2830
2831    /* try to get the edid atom */
2832    if (!(clones = XInternAtom(_ecore_x_disp, RR_PROPERTY_CLONE_LIST, True)))
2833      return NULL;
2834
2835    /* get the output property
2836     * 
2837     * NB: Returns 0 on success */
2838    if (!XRRGetOutputProperty(_ecore_x_disp, output, clones, 0, 100, False, False, 
2839                             AnyPropertyType, &type, &format, &nitems, 
2840                             &bytes, &prop))
2841      {
2842         if ((type == XA_ATOM) && (nitems >= 1) && (format == 32))
2843           {
2844              Ecore_X_Randr_Output *ret = NULL;
2845
2846              if ((ret = malloc(nitems * sizeof(Ecore_X_Randr_Output))))
2847                {
2848                   if (num) *num = nitems;
2849                   memcpy(ret, prop, (nitems * sizeof(Ecore_X_Randr_Output)));
2850                   return ret;
2851                }
2852           }
2853      }
2854 #endif
2855    return NULL;
2856 }
2857
2858 EAPI Ecore_X_Randr_Output **
2859 ecore_x_randr_output_compatibility_list_get(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output EINA_UNUSED, int *num EINA_UNUSED)
2860 {
2861    /* TODO: (1.3) !! */
2862    //RR_PROPERTY_COMPATIBILITY_LIST
2863    return NULL;
2864 }
2865
2866 EAPI Ecore_X_Randr_Signal_Format *
2867 ecore_x_randr_output_signal_formats_get(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output, int *num)
2868 {
2869 #ifdef ECORE_XRANDR
2870    XRRPropertyInfo *info = NULL;
2871    Atom sig, type;
2872    unsigned long bytes = 0;
2873    unsigned long items = 0;
2874    unsigned char *prop = NULL;
2875    int format = 0;
2876
2877    if (_randr_version < RANDR_VERSION_1_3) return NULL;
2878
2879    /* try to get the connector number atom */
2880    if (!(sig = XInternAtom(_ecore_x_disp, RR_PROPERTY_SIGNAL_FORMAT, True)))
2881      return NULL;
2882
2883    /* try to get the output property from Xrandr
2884     * 
2885     * NB: Returns 0 on success */
2886    if (XRRGetOutputProperty(_ecore_x_disp, output, sig, 0, 100, 
2887                             False, False, AnyPropertyType, &type, &format, 
2888                             &items, &bytes, &prop))
2889      {
2890         printf("Signal Format property not supported.\n");
2891         return NULL;
2892      }
2893
2894    free(prop);
2895
2896    /* safety check */
2897    if ((type != XA_ATOM) || (items < 1) || (format != 32))
2898      return NULL;
2899
2900    /* try to get the output property from Xrandr */
2901    if ((info = XRRQueryOutputProperty(_ecore_x_disp, output, sig)))
2902      {
2903         Ecore_X_Randr_Signal_Format *formats = NULL;
2904
2905         if (num) *num = info->num_values;
2906
2907         if (info->num_values > 0)
2908           {
2909              if ((formats = 
2910                   malloc(info->num_values * sizeof(Ecore_X_Randr_Signal_Format))))
2911                {
2912                   memcpy(formats, info->values, 
2913                          (info->num_values * sizeof(Ecore_X_Randr_Signal_Format)));
2914                }
2915           }
2916
2917         /* free the info */
2918         free(info);
2919
2920         return formats;
2921      }
2922 #endif
2923    return NULL;
2924 }
2925
2926 EAPI Eina_Bool 
2927 ecore_x_randr_output_signal_format_set(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output EINA_UNUSED, Ecore_X_Randr_Signal_Format *sig EINA_UNUSED)
2928 {
2929    /* TODO: (1.3) !! */
2930    //RR_PROPERTY_SIGNAL_FORMAT
2931    return EINA_FALSE;
2932 }
2933
2934 EAPI Ecore_X_Randr_Signal_Property *
2935 ecore_x_randr_output_signal_properties_get(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output, int *num)
2936 {
2937 #ifdef ECORE_XRANDR
2938    XRRPropertyInfo *info = NULL;
2939    Atom sig, type;
2940    unsigned long bytes = 0;
2941    unsigned long items = 0;
2942    unsigned char *prop = NULL;
2943    int format = 0;
2944
2945    if (_randr_version < RANDR_VERSION_1_3) return NULL;
2946
2947    /* try to get the connector number atom */
2948    if (!(sig = XInternAtom(_ecore_x_disp, RR_PROPERTY_SIGNAL_PROPERTIES, True)))
2949      return NULL;
2950
2951    /* try to get the output property from Xrandr
2952     * 
2953     * NB: Returns 0 on success */
2954    if (XRRGetOutputProperty(_ecore_x_disp, output, sig, 0, 100, 
2955                             False, False, AnyPropertyType, &type, &format, 
2956                             &items, &bytes, &prop))
2957      {
2958         printf("Signal Properties property not supported.\n");
2959         return NULL;
2960      }
2961
2962    free(prop);
2963
2964    /* safety check */
2965    if ((type != XA_ATOM) || (items < 1) || (format != 32))
2966      return NULL;
2967
2968    /* try to get the output property from Xrandr */
2969    if ((info = XRRQueryOutputProperty(_ecore_x_disp, output, sig)))
2970      {
2971         Ecore_X_Randr_Signal_Property *props = NULL;
2972
2973         if (num) *num = info->num_values;
2974
2975         if (info->num_values > 0)
2976           {
2977              if ((props = 
2978                   malloc(info->num_values * sizeof(Ecore_X_Randr_Signal_Property))))
2979                {
2980                   memcpy(props, info->values, 
2981                          (info->num_values * sizeof(Ecore_X_Randr_Signal_Property)));
2982                }
2983           }
2984
2985         /* free the info */
2986         free(info);
2987
2988         return props;
2989      }
2990 #endif
2991    return NULL;
2992 }
2993
2994 /* TODO NB:
2995  * 
2996  * Document this.
2997  * 
2998  * Returns: 
2999  * 0 == unknown
3000  * 1 == primary
3001  * 2 == secondary
3002  * 3 == (typically) TV Connector but is driver/hardware dependent
3003  * 
3004  */
3005 EAPI int 
3006 ecore_x_randr_output_connector_number_get(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output)
3007 {
3008 #ifdef ECORE_XRANDR
3009    XRRPropertyInfo *info = NULL;
3010    Atom conn, type;
3011    unsigned long bytes = 0;
3012    unsigned long items = 0;
3013    unsigned char *prop = NULL;
3014    int val = 0, format = 0;
3015
3016    if (_randr_version < RANDR_VERSION_1_3) return -1;
3017
3018    /* try to get the connector number atom */
3019    if (!(conn = XInternAtom(_ecore_x_disp, RR_PROPERTY_CONNECTOR_NUMBER, True)))
3020      return -1;
3021
3022    /* try to get the output property from Xrandr
3023     * 
3024     * NB: Returns 0 on success */
3025    if (XRRGetOutputProperty(_ecore_x_disp, output, conn, 0, 100, 
3026                             False, False, AnyPropertyType, &type, &format, 
3027                             &items, &bytes, &prop))
3028      {
3029         printf("ConnectionNumber property not supported.\n");
3030         return -1;
3031      }
3032
3033    /* safety check */
3034    if ((type != XA_INTEGER) || (items != 1) || (format != 32))
3035      return -1;
3036
3037    val = *((int *)prop);
3038    free(prop);
3039
3040    /* try to get the output property from Xrandr */
3041    if ((info = XRRQueryOutputProperty(_ecore_x_disp, output, conn)))
3042      {
3043         int ret = 0;
3044
3045         /* convert the current value */
3046         ret = (int)(val - info->values[0]);
3047
3048         /* free the info */
3049         free(info);
3050
3051         return ret;
3052      }
3053 #endif
3054    return -1;
3055 }
3056
3057 EAPI Ecore_X_Randr_Connector_Type 
3058 ecore_x_randr_output_connector_type_get(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output)
3059 {
3060 #ifdef ECORE_XRANDR
3061    XRRPropertyInfo *info = NULL;
3062    Atom conn, type;
3063    unsigned long bytes = 0;
3064    unsigned long items = 0;
3065    unsigned char *prop = NULL;
3066    int val = 0, format = 0;
3067
3068    if (_randr_version < RANDR_VERSION_1_3) return -1;
3069
3070    /* try to get the connector type atom */
3071    if ((conn = XInternAtom(_ecore_x_disp, RR_PROPERTY_CONNECTOR_NUMBER, True)))
3072      XRRGetOutputProperty(_ecore_x_disp, output, conn, 0, 4, 
3073                           False, False, AnyPropertyType, &type, &format, 
3074                           &items, &bytes, &prop);
3075
3076    if ((!prop) || (items == 0))
3077      {
3078         /* NB: some butthead drivers (*cough* nouveau *cough*) do not 
3079          * implement randr properly. They are not using the connector type 
3080          * property of randr, but rather a "subconnector" property */
3081         if ((conn = XInternAtom(_ecore_x_disp, "subconnector", True)))
3082           XRRGetOutputProperty(_ecore_x_disp, output, conn, 0, 4, 
3083                                False, False, AnyPropertyType, &type, 
3084                                &format, &items, &bytes, &prop);
3085      }
3086
3087    if ((!prop) || (items == 0))
3088      {
3089         WRN("ConnectorType Property not supported.");
3090         return -1;
3091      }
3092
3093    /* safety check */
3094    if ((type != XA_ATOM) || (items != 1) || (format != 32))
3095      return -1;
3096
3097    val = *((int *)prop);
3098    free(prop);
3099
3100    /* try to get the output property from Xrandr */
3101    if ((info = XRRQueryOutputProperty(_ecore_x_disp, output, conn)))
3102      {
3103         int ret = 0;
3104
3105         /* convert the current value */
3106         ret = (int)(val - info->values[0]);
3107
3108         /* printf("\tReturn Value: %d\n", ret); */
3109         /* printf("\t\tActual Name: %s\n",  */
3110         /*        XGetAtomName(_ecore_x_disp, ((Atom)info->values[ret]))); */
3111
3112         /* free the info */
3113         free(info);
3114
3115         return ret;
3116      }
3117 #endif
3118    return -1;
3119 }
3120
3121 EAPI Ecore_X_Randr_Output 
3122 ecore_x_randr_primary_output_get(Ecore_X_Window root)
3123 {
3124 #ifdef ECORE_XRANDR
3125    if (_randr_version < RANDR_VERSION_1_3) return 0;
3126    return XRRGetOutputPrimary(_ecore_x_disp, root);
3127 #else
3128    return 0;
3129 #endif
3130 }
3131
3132 EAPI void 
3133 ecore_x_randr_primary_output_set(Ecore_X_Window root, Ecore_X_Randr_Output output)
3134 {
3135 #ifdef ECORE_XRANDR
3136    if (_randr_version < RANDR_VERSION_1_3) return;
3137    XRRSetOutputPrimary(_ecore_x_disp, root, output);
3138 #endif
3139 }
3140
3141 /***************************************
3142  * API Functions for RandR version 1.4 *
3143  ***************************************/
3144
3145 EAPI void 
3146 ecore_x_randr_crtc_panning_area_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int *x, int *y, int *w, int *h)
3147 {
3148 #ifdef ECORE_XRANDR
3149    XRRScreenResources *res = NULL;
3150
3151    if (_randr_version < RANDR_VERSION_1_4) return;
3152
3153    /* try to get the screen resources from Xrandr */
3154    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
3155      {
3156         XRRPanning *xpan = NULL;
3157
3158         /* get this crtc's panning */
3159         if ((xpan = XRRGetPanning(_ecore_x_disp, res, crtc)))
3160           {
3161              if (x) *x = xpan->left;
3162              if (y) *y = xpan->top;
3163              if (w) *w = xpan->width;
3164              if (h) *h = xpan->height;
3165
3166              /* free the panning resource */
3167              XRRFreePanning(xpan);
3168           }
3169         /* free the resources */
3170         XRRFreeScreenResources(res);
3171      }
3172 #endif
3173 }
3174
3175 EAPI Eina_Bool 
3176 ecore_x_randr_crtc_panning_area_set(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, const int x, const int y, const int w, const int h)
3177 {
3178 #ifdef ECORE_XRANDR
3179    XRRScreenResources *res = NULL;
3180    Eina_Bool ret = EINA_FALSE;
3181
3182    if (_randr_version < RANDR_VERSION_1_4) return EINA_FALSE;
3183
3184    /* try to get the screen resources from Xrandr */
3185    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
3186      {
3187         XRRPanning *xpan = NULL;
3188
3189         /* get this crtc's panning */
3190         if ((xpan = XRRGetPanning(_ecore_x_disp, res, crtc)))
3191           {
3192              xpan->left = x;
3193              xpan->top = y;
3194              xpan->width = w;
3195              xpan->height = h;
3196              xpan->timestamp = CurrentTime;
3197
3198              /* set the panning value */
3199              if (!XRRSetPanning(_ecore_x_disp, res, crtc, xpan))
3200                ret = EINA_TRUE;
3201
3202              /* free the panning resource */
3203              XRRFreePanning(xpan);
3204           }
3205
3206         /* free the resources */
3207         XRRFreeScreenResources(res);
3208      }
3209
3210    return ret;
3211 #else
3212    return EINA_FALSE;
3213 #endif
3214 }
3215
3216 EAPI void 
3217 ecore_x_randr_crtc_tracking_area_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int *x, int *y, int *w, int *h)
3218 {
3219 #ifdef ECORE_XRANDR
3220    XRRScreenResources *res = NULL;
3221
3222    if (_randr_version < RANDR_VERSION_1_4) return;
3223
3224    /* try to get the screen resources from Xrandr */
3225    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
3226      {
3227         XRRPanning *xpan = NULL;
3228
3229         /* get this crtc's panning */
3230         if ((xpan = XRRGetPanning(_ecore_x_disp, res, crtc)))
3231           {
3232              if (x) *x = xpan->track_left;
3233              if (y) *y = xpan->track_top;
3234              if (w) *w = xpan->track_width;
3235              if (h) *h = xpan->track_height;
3236
3237              /* free the panning resource */
3238              XRRFreePanning(xpan);
3239           }
3240         /* free the resources */
3241         XRRFreeScreenResources(res);
3242      }
3243 #endif
3244 }
3245
3246 EAPI Eina_Bool 
3247 ecore_x_randr_crtc_tracking_area_set(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, const int x, const int y, const int w, const int h)
3248 {
3249 #ifdef ECORE_XRANDR
3250    XRRScreenResources *res = NULL;
3251    Eina_Bool ret = EINA_FALSE;
3252
3253    if (_randr_version < RANDR_VERSION_1_4) return EINA_FALSE;
3254
3255    /* try to get the screen resources from Xrandr */
3256    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
3257      {
3258         XRRPanning *xpan = NULL;
3259
3260         /* get this crtc's panning */
3261         if ((xpan = XRRGetPanning(_ecore_x_disp, res, crtc)))
3262           {
3263              xpan->track_left = x;
3264              xpan->track_top = y;
3265              xpan->track_width = w;
3266              xpan->track_height = h;
3267              xpan->timestamp = CurrentTime;
3268
3269              /* set the panning value */
3270              if (!XRRSetPanning(_ecore_x_disp, res, crtc, xpan))
3271                ret = EINA_TRUE;
3272
3273              /* free the panning resource */
3274              XRRFreePanning(xpan);
3275           }
3276
3277         /* free the resources */
3278         XRRFreeScreenResources(res);
3279      }
3280
3281    return ret;
3282 #else
3283    return EINA_FALSE;
3284 #endif
3285 }
3286
3287 EAPI void 
3288 ecore_x_randr_crtc_border_area_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, int *x, int *y, int *w, int *h)
3289 {
3290 #ifdef ECORE_XRANDR
3291    XRRScreenResources *res = NULL;
3292
3293    if (_randr_version < RANDR_VERSION_1_4) return;
3294
3295    /* try to get the screen resources from Xrandr */
3296    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
3297      {
3298         XRRPanning *xpan = NULL;
3299
3300         /* get this crtc's panning */
3301         if ((xpan = XRRGetPanning(_ecore_x_disp, res, crtc)))
3302           {
3303              if (x) *x = xpan->border_left;
3304              if (y) *y = xpan->border_top;
3305              if (w) *w = xpan->border_right;
3306              if (h) *h = xpan->border_bottom;
3307
3308              /* free the panning resource */
3309              XRRFreePanning(xpan);
3310           }
3311         /* free the resources */
3312         XRRFreeScreenResources(res);
3313      }
3314 #endif
3315 }
3316
3317 EAPI Eina_Bool 
3318 ecore_x_randr_crtc_border_area_set(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc, const int left, const int top, const int right, const int bottom)
3319 {
3320 #ifdef ECORE_XRANDR
3321    XRRScreenResources *res = NULL;
3322    Eina_Bool ret = EINA_FALSE;
3323
3324    if (_randr_version < RANDR_VERSION_1_4) return EINA_FALSE;
3325
3326    /* try to get the screen resources from Xrandr */
3327    if ((res = _ecore_x_randr_screen_resources_get(_ecore_x_disp, root)))
3328      {
3329         XRRPanning *xpan = NULL;
3330
3331         /* get this crtc's panning */
3332         if ((xpan = XRRGetPanning(_ecore_x_disp, res, crtc)))
3333           {
3334              xpan->border_left = left;
3335              xpan->border_top = top;
3336              xpan->border_right = right;
3337              xpan->border_bottom = bottom;
3338              xpan->timestamp = CurrentTime;
3339
3340              /* set the panning value */
3341              if (!XRRSetPanning(_ecore_x_disp, res, crtc, xpan))
3342                ret = EINA_TRUE;
3343
3344              /* free the panning resource */
3345              XRRFreePanning(xpan);
3346           }
3347
3348         /* free the resources */
3349         XRRFreeScreenResources(res);
3350      }
3351
3352    return ret;
3353 #else
3354    return EINA_FALSE;
3355 #endif
3356 }
3357
3358 /***************************************
3359  * API Functions for RandR Edid
3360  ***************************************/
3361
3362 EAPI Eina_Bool 
3363 ecore_x_randr_edid_has_valid_header(unsigned char *edid, unsigned long edid_length)
3364 {
3365    const unsigned char header[] =
3366      { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
3367
3368    if (!edid) return EINA_FALSE;
3369    if (edid_length < 8) return EINA_FALSE;
3370    if (!memcmp(edid, header, 8)) return EINA_TRUE;
3371    return EINA_FALSE;
3372 }
3373
3374 EAPI Eina_Bool 
3375 ecore_x_randr_edid_info_has_valid_checksum(unsigned char *edid, unsigned long edid_length)
3376 {
3377 #ifdef ECORE_XRANDR
3378    unsigned char *iter = NULL;
3379    char sum = 0;
3380    int i = 0, version = 0;
3381
3382    if (edid_length < 128) return EINA_FALSE;
3383
3384    version = ecore_x_randr_edid_version_get(edid, edid_length);
3385    if (version < RANDR_EDID_VERSION_1_3) return EINA_FALSE;
3386
3387    for (i = 0; i < 128; i++)
3388      sum += edid[i];
3389
3390    if (sum) return EINA_FALSE;
3391
3392    /* check extension blocks */
3393    for (iter = edid; iter < (edid + edid_length); iter += 128)
3394      {
3395         if (iter[0] == 0x02)
3396           {
3397              for (i = 0, sum = 0; i < 128; i++)
3398                sum += iter[i];
3399           }
3400      }
3401
3402    if (sum) return EINA_FALSE;
3403    return EINA_TRUE;
3404 #else
3405    return EINA_FALSE;
3406 #endif
3407 }
3408
3409 EAPI int 
3410 ecore_x_randr_edid_version_get(unsigned char *edid, unsigned long edid_length)
3411 {
3412 #ifdef ECORE_XRANDR
3413    if ((edid_length > RANDR_EDID_VERSION_MINOR) && 
3414        (ecore_x_randr_edid_has_valid_header(edid, edid_length)))
3415      {
3416         return (edid[RANDR_EDID_VERSION_MAJOR] << 8) | 
3417           edid[RANDR_EDID_VERSION_MINOR];
3418      }
3419
3420    return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3421 #else
3422    return 0;
3423 #endif
3424 }
3425
3426 EAPI char *
3427 ecore_x_randr_edid_manufacturer_name_get(unsigned char *edid, unsigned long edid_length)
3428 {
3429 #ifdef ECORE_XRANDR
3430    if ((edid_length > RANDR_EDID_MANUFACTURER + 1) && 
3431        (ecore_x_randr_edid_has_valid_header(edid, edid_length)))
3432      {
3433         unsigned char *x;
3434         char *name;
3435
3436         if (!(name = malloc(sizeof(char) * 4))) return NULL;
3437
3438         x = (edid + RANDR_EDID_MANUFACTURER);
3439         name[0] = ((x[0] & 0x7c) >> 2) + '@';
3440         name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xe0) >> 5) + '@';
3441         name[2] = (x[1] & 0x1f) + '@';
3442         name[3] = 0;
3443
3444         return name;
3445      }
3446 #endif
3447    return NULL;
3448 }
3449
3450 EAPI char *
3451 ecore_x_randr_edid_display_name_get(unsigned char *edid, unsigned long edid_length)
3452 {
3453 #ifdef ECORE_XRANDR
3454    unsigned char *block = NULL;
3455    int version = 0;
3456
3457    version = ecore_x_randr_edid_version_get(edid, edid_length);
3458    if (version < RANDR_EDID_VERSION_1_3) return NULL;
3459
3460    for (block = (edid + RANDR_EDID_BLOCK); 
3461         block <= (edid + RANDR_EDID_BLOCK + (3 * 18)); block += 18)
3462      {
3463         if ((block[0] == 0) && (block[1] == 0))
3464           {
3465              if (block[3] == 0xfc)
3466                {
3467                   char *name, *p;
3468                   const char *edid_name;
3469
3470                   edid_name = (const char *)block + 5;
3471                   if (!(name = malloc(14))) return NULL;
3472                   strncpy(name, edid_name, 13);
3473                   name[13] = 0;
3474
3475                   for (p = name; *p; p++)
3476                     if ((*p < ' ') || (*p > '~')) *p = 0;
3477
3478                   return name;
3479                }
3480           }
3481      }
3482 #endif
3483    return NULL;
3484 }
3485
3486 EAPI char *
3487 ecore_x_randr_edid_display_ascii_get(unsigned char *edid, unsigned long edid_length)
3488 {
3489 #ifdef ECORE_XRANDR
3490    unsigned char *block = NULL;
3491    int version = 0;
3492
3493    version = ecore_x_randr_edid_version_get(edid, edid_length);
3494    if (version < RANDR_EDID_VERSION_1_3) return NULL;
3495
3496    for (block = (edid + RANDR_EDID_BLOCK); 
3497         block <= (edid + RANDR_EDID_BLOCK + (3 * 18)); block += 18)
3498      {
3499         if ((block[0] == 0) && (block[1] == 0))
3500           {
3501              if (block[3] == 0xfe)
3502                {
3503                   char *ascii = NULL, *p = NULL;
3504                   const char *edid_ascii;
3505
3506                   edid_ascii = (const char *)block + 5;
3507
3508                   if (!(ascii = malloc(14))) return NULL;
3509                   strncpy(ascii, edid_ascii, 13);
3510                   ascii[13] = 0;
3511                   for (p = ascii; *p; p++)
3512                     if ((*p < ' ') || (*p > '~')) *p = 0;
3513
3514                   return ascii;
3515                }
3516           }
3517      }
3518 #endif
3519    return NULL;
3520 }
3521
3522 EAPI char *
3523 ecore_x_randr_edid_display_serial_get(unsigned char *edid, unsigned long edid_length)
3524 {
3525 #ifdef ECORE_XRANDR
3526    unsigned char *block = NULL;
3527    int version = 0;
3528
3529    version = ecore_x_randr_edid_version_get(edid, edid_length);
3530    if (version < RANDR_EDID_VERSION_1_3) return NULL;
3531
3532    for (block = (edid + RANDR_EDID_BLOCK); 
3533         block <= (edid + RANDR_EDID_BLOCK + (3 * 18)); block += 18)
3534      {
3535         if ((block[0] == 0) && (block[1] == 0))
3536           {
3537              if (block[3] == 0xff)
3538                {
3539                   char *serial = NULL, *p = NULL;
3540                   const char *edid_serial;
3541
3542                   edid_serial = (const char *)block + 5;
3543
3544                   if (!(serial = malloc(14))) return NULL;
3545                   strncpy(serial, edid_serial, 13);
3546                   serial[13] = 0;
3547                   for (p = serial; *p; p++)
3548                     if ((*p < ' ') || (*p > '~')) *p = 0;
3549
3550                   return serial;
3551                }
3552           }
3553      }
3554 #endif
3555    return NULL;
3556 }
3557
3558 EAPI int 
3559 ecore_x_randr_edid_model_get(unsigned char *edid, unsigned long edid_length)
3560 {
3561    return ecore_x_randr_edid_manufacturer_model_get(edid, edid_length);
3562 }
3563
3564 EAPI int 
3565 ecore_x_randr_edid_manufacturer_serial_number_get(unsigned char *edid, unsigned long edid_length)
3566 {
3567 #ifdef ECORE_XRANDR
3568    if ((edid_length > RANDR_EDID_MANUFACTURER + 1) && 
3569        (ecore_x_randr_edid_has_valid_header(edid, edid_length)))
3570      return (int)(edid[0x0c] + (edid[0x0d] << 8) + 
3571                   (edid[0x0e] << 16) + (edid[0x0f] << 24));
3572
3573    return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3574 #else
3575    return 0;
3576 #endif
3577 }
3578
3579 EAPI int 
3580 ecore_x_randr_edid_manufacturer_model_get(unsigned char *edid, unsigned long edid_length)
3581 {
3582 #ifdef ECORE_XRANDR
3583    if ((edid_length > RANDR_EDID_MANUFACTURER + 1) && 
3584        (ecore_x_randr_edid_has_valid_header(edid, edid_length)))
3585      return (int)(edid[0x0a] + (edid[0x0b] << 8));
3586 #endif
3587    return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3588 }
3589
3590 EAPI Eina_Bool 
3591 ecore_x_randr_edid_dpms_available_get(unsigned char *edid, unsigned long edid_length)
3592 {
3593 #ifdef ECORE_XRANDR
3594    int version = 0;
3595
3596    version = ecore_x_randr_edid_version_get(edid, edid_length);
3597    if (version < RANDR_EDID_VERSION_1_3) return EINA_FALSE;
3598
3599    return !!(edid[0x18] & 0xE0);
3600 #else
3601    return EINA_FALSE;
3602 #endif
3603 }
3604
3605 EAPI Eina_Bool 
3606 ecore_x_randr_edid_dpms_standby_available_get(unsigned char *edid, unsigned long edid_length)
3607 {
3608 #ifdef ECORE_XRANDR
3609    int version = 0;
3610
3611    version = ecore_x_randr_edid_version_get(edid, edid_length);
3612    if (version < RANDR_EDID_VERSION_1_3) return EINA_FALSE;
3613
3614    if (edid[0x18] & 0xE0) return !!(edid[0x18] & 0x80);
3615 #endif
3616    return EINA_FALSE;
3617 }
3618
3619 EAPI Eina_Bool 
3620 ecore_x_randr_edid_dpms_suspend_available_get(unsigned char *edid, unsigned long edid_length)
3621 {
3622 #ifdef ECORE_XRANDR
3623    int version = 0;
3624
3625    version = ecore_x_randr_edid_version_get(edid, edid_length);
3626    if (version < RANDR_EDID_VERSION_1_3) return EINA_FALSE;
3627
3628    if (edid[0x18] & 0xE0) return !!(edid[0x18] & 0x40);
3629 #endif
3630    return EINA_FALSE;
3631 }
3632
3633 EAPI Eina_Bool 
3634 ecore_x_randr_edid_dpms_off_available_get(unsigned char *edid, unsigned long edid_length)
3635 {
3636 #ifdef ECORE_XRANDR
3637    int version = 0;
3638
3639    version = ecore_x_randr_edid_version_get(edid, edid_length);
3640    if (version < RANDR_EDID_VERSION_1_3) return EINA_FALSE;
3641
3642    if (edid[0x18] & 0xE0) return !!(edid[0x18] & 0x20);
3643 #endif
3644    return EINA_FALSE;
3645 }
3646
3647 EAPI Ecore_X_Randr_Edid_Aspect_Ratio 
3648 ecore_x_randr_edid_display_aspect_ratio_preferred_get(unsigned char *edid, unsigned long edid_length)
3649 {
3650 #ifdef ECORE_XRANDR
3651    unsigned char *block = NULL;
3652    int version = 0;
3653
3654    version = ecore_x_randr_edid_version_get(edid, edid_length);
3655    if (version < RANDR_EDID_VERSION_1_3) 
3656      return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3657
3658    for (block = (edid + RANDR_EDID_BLOCK); 
3659         block <= (edid + RANDR_EDID_BLOCK + (3 * 18)); block += 18)
3660      {
3661         if ((block[0] == 0) && (block[1] == 0))
3662           {
3663              if ((block[3] == 0xfd) && (block[10] == 0x04))
3664                {
3665                   Ecore_X_Randr_Edid_Aspect_Ratio_Preferred ratio = 
3666                     (Ecore_X_Randr_Edid_Aspect_Ratio_Preferred)((block[15] & 0xe0) >> 5);
3667
3668                   switch (ratio)
3669                     {
3670                      case RANDR_EDID_ASPECT_RATIO_PREFERRED_4_3:
3671                        return ECORE_X_RANDR_EDID_ASPECT_RATIO_4_3;
3672                      case RANDR_EDID_ASPECT_RATIO_PREFERRED_16_9:
3673                        return ECORE_X_RANDR_EDID_ASPECT_RATIO_16_9;
3674                      case RANDR_EDID_ASPECT_RATIO_PREFERRED_16_10:
3675                        return ECORE_X_RANDR_EDID_ASPECT_RATIO_16_10;
3676                      case RANDR_EDID_ASPECT_RATIO_PREFERRED_5_4:
3677                        return ECORE_X_RANDR_EDID_ASPECT_RATIO_5_4;
3678                      case RANDR_EDID_ASPECT_RATIO_PREFERRED_15_9:
3679                        return ECORE_X_RANDR_EDID_ASPECT_RATIO_15_9;
3680                      default:
3681                        return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3682                     }
3683                }
3684           }
3685      }
3686
3687    return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3688 #else
3689    return 0;
3690 #endif
3691 }
3692
3693 EAPI Ecore_X_Randr_Edid_Aspect_Ratio 
3694 ecore_x_randr_edid_display_aspect_ratios_get(unsigned char *edid, unsigned long edid_length)
3695 {
3696 #ifdef ECORE_XRANDR
3697    Ecore_X_Randr_Edid_Aspect_Ratio ret;
3698    unsigned char *block = NULL;
3699    int version = 0;
3700
3701    ret = ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3702
3703    version = ecore_x_randr_edid_version_get(edid, edid_length);
3704    if (version < RANDR_EDID_VERSION_1_3) 
3705      return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3706
3707    for (block = (edid + RANDR_EDID_BLOCK); 
3708         block <= (edid + RANDR_EDID_BLOCK + (3 * 18)); block += 18)
3709      {
3710         if ((block[0] == 0) && (block[1] == 0))
3711           {
3712              if ((block[3] == 0xfd) && (block[10] == 0x04))
3713                {
3714                   if (block[14] & 0x80)
3715                     ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_4_3;
3716                   if (block[14] & 0x40)
3717                     ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_16_9;
3718                   if (block[14] & 0x20)
3719                     ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_16_10;
3720                   if (block[14] & 0x10)
3721                     ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_5_4;
3722                   if (block[14] & 0x08)
3723                     ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_15_9;
3724                }
3725           }
3726      }
3727
3728    return ret;
3729 #else
3730    return 0;
3731 #endif
3732 }
3733
3734 EAPI Ecore_X_Randr_Edid_Display_Colorscheme 
3735 ecore_x_randr_edid_display_colorscheme_get(unsigned char *edid, unsigned long edid_length)
3736 {
3737 #ifdef ECORE_XRANDR
3738    Ecore_X_Randr_Edid_Display_Colorscheme ret;
3739    int version = 0;
3740
3741    ret = ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3742
3743    version = ecore_x_randr_edid_version_get(edid, edid_length);
3744    if (version < RANDR_EDID_VERSION_1_3) 
3745      return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3746
3747    if (ecore_x_randr_edid_display_type_digital_get(edid, edid_length))
3748      {
3749         ret = ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_4_4_4;
3750         if (edid[0x18] & 0x10)
3751           ret |= ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_4_4;
3752         if (edid[0x18] & 0x08)
3753           ret |= ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_2_2;
3754      }
3755    else
3756      ret = (edid[0x18] & 0x18);
3757
3758    return ret;
3759 #else
3760    return 0;
3761 #endif
3762 }
3763
3764 EAPI Eina_Bool 
3765 ecore_x_randr_edid_display_type_digital_get(unsigned char *edid, unsigned long edid_length)
3766 {
3767 #ifdef ECORE_XRANDR
3768    int version = 0;
3769
3770    version = ecore_x_randr_edid_version_get(edid, edid_length);
3771    if (version < RANDR_EDID_VERSION_1_3) return EINA_FALSE;
3772
3773    return !!(edid[0x14] & 0x80);
3774 #else
3775    return EINA_FALSE;
3776 #endif
3777 }
3778
3779 EAPI Ecore_X_Randr_Edid_Display_Interface_Type 
3780 ecore_x_randr_edid_display_interface_type_get(unsigned char *edid, unsigned long edid_length)
3781 {
3782 #ifdef ECORE_XRANDR
3783    Ecore_X_Randr_Edid_Display_Interface_Type type;
3784    int version = 0;
3785
3786    type = ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3787
3788    version = ecore_x_randr_edid_version_get(edid, edid_length);
3789    if (version < RANDR_EDID_VERSION_1_3) 
3790      return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3791
3792    type = (edid[0x14] & 0x0f);
3793    if (type > ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DISPLAY_PORT)
3794      type = ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3795
3796    return type;
3797 #else
3798    return 0;
3799 #endif
3800 }