Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore_x / xlib / ecore_x_randr_12.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include "ecore_x_private.h"
10 #include "ecore_x_randr.h"
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15
16 #define Ecore_X_Randr_None  (Ecore_X_Randr_Crtc)0
17 #define Ecore_X_Randr_Unset (Ecore_X_Randr_Crtc) - 1
18
19 #ifdef ECORE_XRANDR
20
21 #define RANDR_1_2           ((1 << 16) | 2)
22
23 #define RANDR_VALIDATE_ROOT(screen, root) \
24   ((screen = XRRRootToScreen(_ecore_x_disp, root)) != -1)
25
26 #define RANDR_CHECK_1_2_RET(ret) if (_randr_version < RANDR_1_2) \
27     return ret
28
29 #define RANDR_PROPERTY_EDID               "EDID"
30 #define RANDR_PROPERTY_BACKLIGHT          "Backlight"
31 #define RANDR_PROPERTY_SIGNAL_FORMAT      "SignalFormat"
32 #define RANDR_PROPERTY_SIGNAL_PROPERTIES  "SignalProperties"
33 #define RANDR_PROPERTY_CONNECTOR_TYPE     "ConnectorType"
34 #define RANDR_PROPERTY_CONNECTOR_NUMBER   "ConnectorNumber"
35 #define RANDR_PROPERTY_COMPATIBILITY_LIST "CompatibilityList"
36 #define RANDR_PROPERTY_CLONE_LIST         "CloneList"
37
38 extern XRRScreenResources *(*_ecore_x_randr_get_screen_resources)(Display *
39                                                                   dpy,
40                                                                   Window
41                                                                   window);
42 extern int _randr_version;
43 #endif
44
45 /**
46  * @brief Enable event selection. This enables basic interaction with
47  * output/crtc events and requires RandR >= 1.2.
48  *
49  * @param win Select this window's properties for RandR events.
50  * @param on Enable/disable selecting.
51  */
52 EAPI void
53 ecore_x_randr_events_select(Ecore_X_Window win,
54                             Eina_Bool on)
55 {
56 #ifdef ECORE_XRANDR
57    int mask;
58
59    LOGFN(__FILE__, __LINE__, __FUNCTION__);
60    if (!on)
61      mask = 0;
62    else
63      {
64         mask = RRScreenChangeNotifyMask;
65         if (_randr_version >= RANDR_1_2)
66           mask |= (RRCrtcChangeNotifyMask |
67                    RROutputChangeNotifyMask |
68                    RROutputPropertyNotifyMask);
69      }
70
71    XRRSelectInput(_ecore_x_disp, win, mask);
72 #endif
73 }
74
75 /**
76  * @brief Validates a CRTC for a given root window's screen.
77  *
78  * @param root The window which's default display will be queried.
79  * @param crtc The CRTC to be validated.
80  * @return In case it is found, @c EINA_TRUE will be returned, @c EINA_FALSE
81  * otherwise.
82  */
83 static inline Eina_Bool
84 _ecore_x_randr_crtc_validate(Ecore_X_Window root,
85                              Ecore_X_Randr_Crtc crtc)
86 {
87 #ifdef ECORE_XRANDR
88    RANDR_CHECK_1_2_RET(EINA_FALSE);
89
90    XRRScreenResources *res = NULL;
91    int i;
92    Eina_Bool ret = EINA_FALSE;
93
94    if ((crtc == Ecore_X_Randr_None) ||
95        (crtc == Ecore_X_Randr_Unset))
96      return ret;
97
98    if (_ecore_x_randr_root_validate(root) && crtc &&
99        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
100      {
101         for (i = 0; i < res->ncrtc; i++)
102           {
103              if (res->crtcs[i] == crtc)
104                {
105                   ret = EINA_TRUE;
106                   break;
107                }
108           }
109         XRRFreeScreenResources(res);
110      }
111
112    return ret;
113 #else
114    return EINA_FALSE;
115 #endif
116 }
117
118 Eina_Bool
119 _ecore_x_randr_output_validate(Ecore_X_Window root,
120                                Ecore_X_Randr_Output output)
121 {
122 #ifdef ECORE_XRANDR
123    RANDR_CHECK_1_2_RET(EINA_FALSE);
124
125    Eina_Bool ret = EINA_FALSE;
126    XRRScreenResources *res = NULL;
127    int i;
128
129    if (_ecore_x_randr_root_validate(root) && output &&
130        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
131      {
132         for (i = 0; i < res->noutput; i++)
133           {
134              if (res->outputs[i] == output)
135                {
136                   ret = EINA_TRUE;
137                   break;
138                }
139           }
140         XRRFreeScreenResources(res);
141      }
142
143    return ret;
144 #else
145    return EINA_FALSE;
146 #endif
147 }
148
149 static inline Eina_Bool
150 _ecore_x_randr_mode_validate(Ecore_X_Window root,
151                              Ecore_X_Randr_Mode mode)
152 {
153 #ifdef ECORE_XRANDR
154    RANDR_CHECK_1_2_RET(EINA_FALSE);
155
156    Eina_Bool ret = EINA_FALSE;
157    XRRScreenResources *res = NULL;
158    int i;
159
160    if (_ecore_x_randr_root_validate(root) && mode &&
161        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
162      {
163         for (i = 0; i < res->nmode; i++)
164           {
165              if (res->modes[i].id == mode)
166                {
167                   ret = EINA_TRUE;
168                   break;
169                }
170           }
171         XRRFreeScreenResources(res);
172      }
173
174    return ret;
175 #else
176    return EINA_FALSE;
177 #endif
178 }
179
180 /*
181  * @param w width of screen in px
182  * @param h height of screen in px
183  */
184 EAPI void
185 ecore_x_randr_screen_current_size_get(Ecore_X_Window root,
186                                       int *w,
187                                       int *h,
188                                       int *w_mm,
189                                       int *h_mm)
190 {
191 #ifdef ECORE_XRANDR
192    RANDR_CHECK_1_2_RET();
193    Ecore_X_Randr_Screen scr;
194
195    if (!RANDR_VALIDATE_ROOT(scr, root))
196      return;
197
198    if (w)
199      *w = DisplayWidth(_ecore_x_disp, scr);
200
201    if (h)
202      *h = DisplayHeight(_ecore_x_disp, scr);
203
204    if (w_mm)
205      *w_mm = DisplayWidthMM(_ecore_x_disp, scr);
206
207    if (h_mm)
208      *h_mm = DisplayHeightMM(_ecore_x_disp, scr);
209
210 #endif
211 }
212
213 /*
214  * @param root window which's screen will be queried
215  * @param wmin minimum width the screen can be set to
216  * @param hmin minimum height the screen can be set to
217  * @param wmax maximum width the screen can be set to
218  * @param hmax maximum height the screen can be set to
219  */
220 EAPI void
221 ecore_x_randr_screen_size_range_get(Ecore_X_Window root,
222                                     int *wmin,
223                                     int *hmin,
224                                     int *wmax,
225                                     int *hmax)
226 {
227 #ifdef ECORE_XRANDR
228    RANDR_CHECK_1_2_RET();
229    int twmin, thmin, twmax, thmax;
230    if (XRRGetScreenSizeRange (_ecore_x_disp, root, &twmin, &thmin, &twmax,
231                               &thmax))
232      {
233         if (wmin)
234           *wmin = twmin;
235
236         if (hmin)
237           *hmin = thmin;
238
239         if (wmax)
240           *wmax = twmax;
241
242         if (hmax)
243           *hmax = thmax;
244      }
245
246 #endif
247 }
248
249 /*
250  * @param root Window which's screen's size should be set. If invalid (e.g. 
251  * @c NULL) no action is taken.
252  * @param w Width in px the screen should be set to. If out of valid
253  * boundaries, current value is assumed.
254  * @param h Height in px the screen should be set to. If out of valid
255  * boundaries, current value is assumed.
256  * @param w_mm Width in mm the screen should be set to. If @c 0, current
257  * aspect is assumed.
258  * @param h_mm Height in mm the screen should be set to. If @c 0, current
259  * aspect is assumed.
260  * @return @c EINA_TRUE if request was successfully sent or screen is already
261  * in requested size, @c EINA_FALSE if parameters are invalid.
262  */
263 EAPI Eina_Bool
264 ecore_x_randr_screen_current_size_set(Ecore_X_Window root,
265                                       int w,
266                                       int h,
267                                       int w_mm,
268                                       int h_mm)
269 {
270 #ifdef ECORE_XRANDR
271    RANDR_CHECK_1_2_RET(EINA_FALSE);
272
273    Ecore_X_Randr_Screen scr;
274    int w_c, h_c, w_mm_c, h_mm_c, twmin, thmin, twmax, thmax;
275
276    if (!RANDR_VALIDATE_ROOT(scr, root))
277      return EINA_FALSE;
278
279    ecore_x_randr_screen_current_size_get(root, &w_c, &h_c, &w_mm_c, &h_mm_c);
280    if ((w == w_c) && (h == h_c) && (w_mm_c == w_mm) && (h_mm_c == h_mm))
281      return EINA_TRUE;
282
283    ecore_x_randr_screen_size_range_get(root, &twmin, &thmin, &twmax, &thmax);
284
285    if (((w != Ecore_X_Randr_None) &&
286         ((w < twmin) ||
287          (w > twmax))) ||
288        ((h != Ecore_X_Randr_None) && ((h < thmin) || (h > thmax))))
289      return EINA_FALSE;
290
291    if (w <= 0)
292      w = DisplayWidth(_ecore_x_disp, scr);
293
294    if (h <= 0)
295      h = DisplayHeight(_ecore_x_disp, scr);
296
297    if (w_mm <= 0)
298      w_mm =
299        (int)(((double)(DisplayWidthMM(_ecore_x_disp,
300                                       scr) /
301                        (double)DisplayWidth(_ecore_x_disp,
302                                             scr))) * (double)w);
303
304    if (h_mm <= 0)
305      h_mm =
306        (int)(((double)(DisplayHeightMM(_ecore_x_disp,
307                                        scr) /
308                        (double)DisplayHeight(_ecore_x_disp,
309                                              scr))) * (double)h);
310
311    XRRSetScreenSize (_ecore_x_disp, root, w, h, w_mm, h_mm);
312    return EINA_TRUE;
313 #else
314    return EINA_FALSE;
315 #endif
316 }
317
318 /*
319  * @brief get detailed information for all modes related to a root window's screen
320  * @param root window which's screen's ressources are queried
321  * @param num number of modes returned
322  * @return modes' information
323  */
324 EAPI Ecore_X_Randr_Mode_Info **
325 ecore_x_randr_modes_info_get(Ecore_X_Window root,
326                              int *num)
327 {
328 #ifdef ECORE_XRANDR
329    RANDR_CHECK_1_2_RET(NULL);
330    XRRScreenResources *res = NULL;
331    Ecore_X_Randr_Mode_Info **ret = NULL;
332    int i;
333
334    if (_ecore_x_randr_root_validate(root) &&
335        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
336      {
337         if ((ret =
338                (Ecore_X_Randr_Mode_Info **)malloc(sizeof(
339                                                     Ecore_X_Randr_Mode_Info *)
340                                                   *
341                                                   res->nmode)))
342           {
343              for (i = 0; i < res->nmode; i++)
344                {
345                   if ((ret[i] = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
346                     {
347                        ret[i]->xid = res->modes[i].id;
348                        ret[i]->width = res->modes[i].width;
349                        ret[i]->height = res->modes[i].height;
350                        ret[i]->dotClock = res->modes[i].dotClock;
351                        ret[i]->hSyncStart = res->modes[i].hSyncStart;
352                        ret[i]->hSyncEnd = res->modes[i].hSyncEnd;
353                        ret[i]->hTotal = res->modes[i].hTotal;
354                        ret[i]->hSkew = res->modes[i].hSkew;
355                        ret[i]->vSyncStart = res->modes[i].vSyncStart;
356                        ret[i]->vSyncEnd = res->modes[i].vSyncEnd;
357                        ret[i]->vTotal = res->modes[i].vTotal;
358                        if ((ret[i]->name = (malloc(res->modes[i].nameLength + 1))))
359                          strncpy(ret[i]->name, res->modes[i].name,
360                                  (res->modes[i].nameLength + 1));
361                        else
362                          ret[i]->name = NULL;
363
364                        ret[i]->nameLength = res->modes[i].nameLength;
365                        ret[i]->modeFlags = res->modes[i].modeFlags;
366                     }
367                   else
368                     {
369                        while (i > 0)
370                          free(ret[--i]);
371                        free(ret);
372                        ret = NULL;
373                        break;
374                     }
375                }
376           }
377
378         if (ret && num)
379           *num = res->nmode;
380
381         XRRFreeScreenResources(res);
382      }
383
384    return ret;
385 #else
386    return NULL;
387 #endif
388 }
389
390 /*
391  * @brief Add a mode to a display.
392  *
393  * @param root Window to which's screen's ressources are added.
394  * @param mode_info
395  * @return Ecore_X_Randr_Mode of the added mode. Ecore_X_Randr_None if mode
396  * adding failed.
397  * @since 1.2.0
398  */
399 EAPI Ecore_X_Randr_Mode
400 ecore_x_randr_mode_info_add(Ecore_X_Window root,
401                             Ecore_X_Randr_Mode_Info *mode_info)
402 {
403 #ifdef ECORE_XRANDR
404    RANDR_CHECK_1_2_RET(EINA_FALSE);
405    Ecore_X_Randr_Mode mode = Ecore_X_Randr_None;
406
407    if (_ecore_x_randr_root_validate(root) && mode_info)
408      mode = XRRCreateMode(_ecore_x_disp, root, (XRRModeInfo*)mode_info);
409
410    return mode;
411 #else
412    return Ecore_X_Randr_None;
413 #endif
414 }
415
416 /*
417  * @brief Delete a mode from the display.
418  *
419  * @param mode_info
420  * @since 1.2.0
421  */
422 EAPI void
423 ecore_x_randr_mode_del(Ecore_X_Randr_Mode mode)
424 {
425 #ifdef ECORE_XRANDR
426    RANDR_CHECK_1_2_RET();
427
428    XRRDestroyMode(_ecore_x_disp, mode);
429 #else
430    return;
431 #endif
432 }
433
434 /*
435  * @brief get detailed information for a given mode id
436  * @param root window which's screen's ressources are queried
437  * @param mode the XID which identifies the mode of interest
438  * @return mode's detailed information
439  */
440 EAPI Ecore_X_Randr_Mode_Info *
441 ecore_x_randr_mode_info_get(Ecore_X_Window root,
442                             Ecore_X_Randr_Mode mode)
443 {
444 #ifdef ECORE_XRANDR
445    RANDR_CHECK_1_2_RET(NULL);
446    XRRScreenResources *res = NULL;
447    Ecore_X_Randr_Mode_Info *ret = NULL;
448    int i;
449
450    if (_ecore_x_randr_root_validate(root) &&
451        (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
452      {
453         for (i = 0; i < res->nmode; i++)
454           {
455              if ((res->modes[i].id == mode) &&
456                  (ret = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
457                {
458                   ret->xid = res->modes[i].id;
459                   ret->width = res->modes[i].width;
460                   ret->height = res->modes[i].height;
461                   ret->dotClock = res->modes[i].dotClock;
462                   ret->hSyncStart = res->modes[i].hSyncStart;
463                   ret->hSyncEnd = res->modes[i].hSyncEnd;
464                   ret->hTotal = res->modes[i].hTotal;
465                   ret->hSkew = res->modes[i].hSkew;
466                   ret->vSyncStart = res->modes[i].vSyncStart;
467                   ret->vSyncEnd = res->modes[i].vSyncEnd;
468                   ret->vTotal = res->modes[i].vTotal;
469                   ret->name = NULL;
470                   ret->nameLength = 0;
471                   if (res->modes[i].nameLength > 0)
472                     {
473                        ret->nameLength = res->modes[i].nameLength;
474                        ret->name = malloc(res->modes[i].nameLength + 1);
475                        if (ret->name)
476                          memcpy(ret->name, res->modes[i].name,
477                                 res->modes[i].nameLength + 1);
478                     }
479                   ret->modeFlags = res->modes[i].modeFlags;
480                   break;
481                }
482           }
483         XRRFreeScreenResources(res);
484      }
485
486    return ret;
487 #else
488    return NULL;
489 #endif
490 }
491
492 /*
493  * @brief Free detailed mode information. The pointer handed in will be set to
494  * @c NULL after freeing the memory.
495  *
496  * @param mode_info The mode information that should be freed.
497  */
498 EAPI void
499 ecore_x_randr_mode_info_free(Ecore_X_Randr_Mode_Info *mode_info)
500 {
501 #ifdef ECORE_XRANDR
502    RANDR_CHECK_1_2_RET();
503    if (!mode_info)
504      return;
505
506    if (mode_info->name)
507      free(mode_info->name);
508
509    free(mode_info);
510    mode_info = NULL;
511 #endif
512 }
513
514 /*
515  * @brief Get all known CRTCs related to a root window's screen.
516  *
517  * @param root Window which's screen's ressources are queried.
518  * @param num Number of CRTCs returned.
519  * @return CRTC IDs.
520  */
521 EAPI Ecore_X_Randr_Crtc *
522 ecore_x_randr_crtcs_get(Ecore_X_Window root,
523                         int *num)
524 {
525 #ifdef ECORE_XRANDR
526    RANDR_CHECK_1_2_RET(NULL);
527    XRRScreenResources *res = NULL;
528    Ecore_X_Randr_Crtc *ret = NULL;
529
530    if (root &&
531        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
532      {
533         if ((ret = malloc(sizeof(Ecore_X_Randr_Crtc) * res->ncrtc)))
534           {
535              int i = 0;
536
537              if (num) *num = res->ncrtc;
538
539              for (i = 0; i < res->ncrtc; i++)
540                ret[i] = res->crtcs[i];
541           }
542
543         XRRFreeScreenResources(res);
544      }
545
546    return ret;
547 #else
548    return NULL;
549 #endif
550 }
551
552 /*
553  * @deprecated bad naming. Use ecore_x_randr_window_crtcs_get instead.
554  * @brief get the CRTCs, which display a certain window
555  * @param window window the displaying crtcs shall be found for
556  * @param num the number of crtcs displaying the window
557  * @return Array of crtcs that display a certain window. @c NULL if no crtcs
558  * was found that displays the specified window.
559  */
560 EAPI Ecore_X_Randr_Crtc *
561 ecore_x_randr_current_crtc_get(Ecore_X_Window window,
562                                int *num)
563 {
564    return ecore_x_randr_window_crtcs_get(window, num);
565 }
566
567 /*
568  * @brief get the CRTCs, which display a certain window
569  * @param window window the displaying crtcs shall be found for
570  * @param num the number of crtcs displaying the window
571  * @return Array of crtcs that display a certain window. @c NULL if no crtcs
572  * was found that displays the specified window.
573  * @since 1.2.0
574  */
575 EAPI Ecore_X_Randr_Crtc *
576 ecore_x_randr_window_crtcs_get(Ecore_X_Window window,
577                                int *num)
578 {
579 #ifdef ECORE_XRANDR
580    Ecore_X_Window root;
581    Eina_Rectangle w_geo, c_geo;
582    Ecore_X_Randr_Crtc *crtcs;
583    Ecore_X_Randr_Mode mode;
584    Ecore_X_Randr_Output *ret = NULL;
585    Window tw;
586    int ncrtcs, i, nret = 0, rx = 0, ry = 0;
587
588    if (_randr_version < RANDR_1_2) goto _ecore_x_randr_window_crtcs_get_fail;
589
590    ecore_x_window_geometry_get(window,
591                                &w_geo.x, &w_geo.y,
592                                &w_geo.w, &w_geo.h);
593
594    root = ecore_x_window_root_get(window);
595    crtcs = ecore_x_randr_crtcs_get(root, &ncrtcs);
596    if (!crtcs) goto _ecore_x_randr_window_crtcs_get_fail;
597
598    /* now get window RELATIVE to root window - thats what matters. */
599    XTranslateCoordinates(_ecore_x_disp, window, root, 0, 0, &rx, &ry, &tw);
600    w_geo.x = rx;
601    w_geo.y = ry;
602
603    ret = calloc(1, ncrtcs * sizeof(Ecore_X_Randr_Crtc));
604    if (!ret)
605      {
606         free(crtcs);
607         goto _ecore_x_randr_window_crtcs_get_fail;
608      }
609    for (i = 0, nret = 0; i < ncrtcs; i++)
610      {
611         /* if crtc is not enabled, don't bother about it any further */
612         mode = ecore_x_randr_crtc_mode_get(root, crtcs[i]);
613         if (mode == Ecore_X_Randr_None) continue;
614
615         ecore_x_randr_crtc_geometry_get(root, crtcs[i],
616                                         &c_geo.x, &c_geo.y,
617                                         &c_geo.w, &c_geo.h);
618         if (eina_rectangles_intersect(&w_geo, &c_geo))
619           {
620              ret[nret] = crtcs[i];
621              nret++;
622           }
623      }
624    free(crtcs);
625
626    if (num) *num = nret;
627    return ret;
628
629 _ecore_x_randr_window_crtcs_get_fail:
630 #endif
631    if (num) *num = 0;
632    return NULL;
633 }
634
635 EAPI Ecore_X_Randr_Output *
636 ecore_x_randr_outputs_get(Ecore_X_Window root,
637                           int *num)
638 {
639 #ifdef ECORE_XRANDR
640    RANDR_CHECK_1_2_RET(NULL);
641    XRRScreenResources *res = NULL;
642    Ecore_X_Randr_Output *ret = NULL;
643
644    if (root && 
645        (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
646      {
647         if ((ret = malloc(sizeof(Ecore_X_Randr_Output) * res->noutput)))
648           {
649              int i = 0;
650
651              if (num) *num = res->noutput;
652
653              for (i = 0; i < res->noutput; i++)
654                ret[i] = res->outputs[i];
655           }
656
657         if (res)
658           XRRFreeScreenResources(res);
659      }
660
661    return ret;
662 #else
663    return NULL;
664 #endif
665 }
666
667 //Per Crtc
668 /*
669  * @brief get a CRTC's outputs.
670  * @param root the root window which's screen will be queried
671  * @param num number of outputs referenced by given CRTC
672  */
673 EAPI Ecore_X_Randr_Output *
674 ecore_x_randr_crtc_outputs_get(Ecore_X_Window root,
675                                Ecore_X_Randr_Crtc crtc,
676                                int *num)
677 {
678 #ifdef ECORE_XRANDR
679    RANDR_CHECK_1_2_RET(NULL);
680    XRRScreenResources *res = NULL;
681    Ecore_X_Randr_Output *ret = NULL;
682    XRRCrtcInfo *crtc_info = NULL;
683
684    if (_ecore_x_randr_crtc_validate(root, crtc) &&
685        (res =
686            _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)) &&
687        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
688      {
689         if ((ret = malloc(sizeof(Ecore_X_Randr_Output) * crtc_info->noutput)))
690           {
691              int i = 0;
692
693              if (num) *num = crtc_info->noutput;
694
695              for (i = 0; i < crtc_info->noutput; i++)
696                ret[i] = crtc_info->outputs[i];
697           }
698
699         if (crtc_info)
700           XRRFreeCrtcInfo(crtc_info);
701
702         if (res)
703           XRRFreeScreenResources(res);
704      }
705
706    return ret;
707 #else
708    return NULL;
709 #endif
710 }
711
712 /*
713  * @brief get a CRTC's possible outputs.
714  * @param root the root window which's screen will be queried
715  * @param num number of possible outputs referenced by given CRTC
716  */
717 EAPI Ecore_X_Randr_Output *
718 ecore_x_randr_crtc_possible_outputs_get(Ecore_X_Window root,
719                                         Ecore_X_Randr_Crtc crtc,
720                                         int *num)
721 {
722 #ifdef ECORE_XRANDR
723    RANDR_CHECK_1_2_RET(NULL);
724    XRRScreenResources *res = NULL;
725    Ecore_X_Randr_Output *ret = NULL;
726    XRRCrtcInfo *crtc_info = NULL;
727
728    if (_ecore_x_randr_crtc_validate(root, crtc) &&
729        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
730      {
731         if ((crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
732           {
733              if ((ret =
734                     malloc(sizeof(Ecore_X_Randr_Output) * crtc_info->npossible)))
735                {
736                   int i = 0;
737
738                   if (num) *num = crtc_info->npossible;
739
740                   for (i = 0; i < crtc_info->npossible; i++)
741                     ret[i] = crtc_info->possible[i];
742                }
743
744              XRRFreeCrtcInfo(crtc_info);
745           }
746
747         XRRFreeScreenResources(res);
748      }
749
750    return ret;
751 #else
752    return NULL;
753 #endif
754 }
755
756 EAPI void
757 ecore_x_randr_crtc_geometry_get(Ecore_X_Window root,
758                                 Ecore_X_Randr_Crtc crtc,
759                                 int *x,
760                                 int *y,
761                                 int *w,
762                                 int *h)
763 {
764 #ifdef ECORE_XRANDR
765    RANDR_CHECK_1_2_RET();
766    XRRScreenResources *res = NULL;
767    XRRCrtcInfo *crtc_info = NULL;
768
769    if (_ecore_x_randr_crtc_validate(root,
770                                     crtc) &&
771        (res =
772           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
773                                                root)) &&
774        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
775      {
776         if (x)
777           *x = crtc_info->x;
778
779         if (y)
780           *y = crtc_info->y;
781
782         if (w)
783           *w = crtc_info->width;
784
785         if (h)
786           *h = crtc_info->height;
787
788         XRRFreeCrtcInfo(crtc_info);
789         XRRFreeScreenResources(res);
790      }
791
792 #endif
793 }
794
795 /*
796  * @brief Sets the position of given CRTC within root window's screen.
797  *
798  * @param root The window's screen to be queried.
799  * @param crtc The CRTC which's position within the mentioned screen is to be
800  * altered.
801  * @param x Position on the x-axis (0 == left) of the screen. if x < 0 current
802  * value will be kept.
803  * @param y Position on the y-ayis (0 == top) of the screen. if y < 0, current
804  * value will be kept.
805  * @return @c EINA_TRUE if position could successfully be altered.
806  */
807 EAPI Eina_Bool
808 ecore_x_randr_crtc_pos_set(Ecore_X_Window root,
809                            Ecore_X_Randr_Crtc crtc,
810                            int x,
811                            int y)
812 {
813 #ifdef ECORE_XRANDR
814    RANDR_CHECK_1_2_RET(EINA_FALSE);
815    int w_c, h_c, w_new = 0, h_new = 0;
816    Eina_Rectangle crtc_geo;
817
818    ecore_x_randr_crtc_geometry_get(root,
819                                    crtc,
820                                    &crtc_geo.x,
821                                    &crtc_geo.y,
822                                    &crtc_geo.w,
823                                    &crtc_geo.h);
824    ecore_x_randr_screen_current_size_get(root, &w_c, &h_c, NULL, NULL);
825    if (x < 0)
826      x = crtc_geo.x;
827
828    if (y < 0)
829      y = crtc_geo.y;
830
831    if ((x + crtc_geo.w) > w_c)
832      w_new = x + crtc_geo.w;
833
834    if ((y + crtc_geo.h) > h_c)
835      h_new = y + crtc_geo.h;
836
837    if ((w_new != 0) || (h_new != 0))
838      if (!ecore_x_randr_screen_current_size_set(root, w_new, h_new, 0, 0))
839        return EINA_FALSE;
840
841    return ecore_x_randr_crtc_settings_set(root,
842                                           crtc,
843                                           NULL,
844                                           Ecore_X_Randr_Unset,
845                                           x,
846                                           y,
847                                           Ecore_X_Randr_Unset,
848                                           Ecore_X_Randr_Unset);
849 #else
850    return EINA_FALSE;
851 #endif
852 }
853
854 /**
855  * @brief Get the current set mode of a given CRTC
856  * @param root the window's screen to be queried
857  * @param crtc the CRTC which's should be queried
858  * @return currently set mode or - in case parameters are invalid -
859  * Ecore_X_Randr_Unset
860  */
861 EAPI Ecore_X_Randr_Mode
862 ecore_x_randr_crtc_mode_get(Ecore_X_Window root,
863                             Ecore_X_Randr_Crtc crtc)
864 {
865 #ifdef ECORE_XRANDR
866    RANDR_CHECK_1_2_RET(Ecore_X_Randr_Unset);
867    XRRScreenResources *res = NULL;
868    XRRCrtcInfo *crtc_info = NULL;
869    Ecore_X_Randr_Mode ret = Ecore_X_Randr_Unset;
870    if (_ecore_x_randr_root_validate(root) &&
871        _ecore_x_randr_crtc_validate(root,
872                                     crtc) &&
873        (res =
874           _ecore_x_randr_get_screen_resources(_ecore_x_disp,
875                                               root)) &&
876        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
877      {
878         ret = crtc_info->mode;
879         XRRFreeCrtcInfo(crtc_info);
880         XRRFreeScreenResources(res);
881      }
882
883    return ret;
884 #else
885    return Ecore_X_Randr_Unset;
886 #endif
887 }
888
889 /**
890  * @brief Sets a mode for a CRTC and the outputs attached to it.
891  *
892  * @param root The window's screen to be queried.
893  * @param crtc The CRTC which shall be set.
894  * @param outputs Array of outputs which have to be compatible with the mode.
895  * If @c NULL, CRTC will be disabled.
896  * @param noutputs Number of outputs in array to be used. Use
897  * Ecore_X_Randr_Unset (or @c -1) to use currently used outputs.
898  * @param mode XID of the mode to be set. If set to @c 0 the CRTC will be
899  * disabled. If set to @c -1 the call will fail.
900  * @return @c EINA_TRUE if mode setting was successful, @c EINA_FALSE
901  * otherwise.
902  */
903 EAPI Eina_Bool
904 ecore_x_randr_crtc_mode_set(Ecore_X_Window root,
905                             Ecore_X_Randr_Crtc crtc,
906                             Ecore_X_Randr_Output *outputs,
907                             int noutputs,
908                             Ecore_X_Randr_Mode mode)
909 {
910 #ifdef ECORE_XRANDR
911    RANDR_CHECK_1_2_RET(EINA_FALSE);
912
913    if (mode == Ecore_X_Randr_Unset)
914      return EINA_FALSE;
915
916    return ecore_x_randr_crtc_settings_set(root,
917                                           crtc,
918                                           outputs,
919                                           noutputs,
920                                           Ecore_X_Randr_Unset,
921                                           Ecore_X_Randr_Unset,
922                                           mode,
923                                           Ecore_X_Randr_Unset);
924 #else
925    return EINA_FALSE;
926 #endif
927 }
928
929 EAPI void
930 ecore_x_randr_crtc_size_get(Ecore_X_Window root,
931                             Ecore_X_Randr_Crtc crtc,
932                             int *w,
933                             int *h)
934 {
935 #ifdef ECORE_XRANDR
936    RANDR_CHECK_1_2_RET();
937    ecore_x_randr_crtc_geometry_get(root, crtc, NULL, NULL, w, h);
938 #endif
939 }
940
941 EAPI Ecore_X_Randr_Refresh_Rate
942 ecore_x_randr_crtc_refresh_rate_get(Ecore_X_Window root,
943                                     Ecore_X_Randr_Crtc crtc,
944                                     Ecore_X_Randr_Mode mode)
945 {
946 #ifdef ECORE_XRANDR
947    RANDR_CHECK_1_2_RET(0.0);
948    XRRScreenResources *res = NULL;
949    XRRCrtcInfo *crtc_info = NULL;
950    Ecore_X_Randr_Refresh_Rate ret = 0.0;
951    int i;
952
953    if (_ecore_x_randr_crtc_validate(root,
954                                     crtc) &&
955        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
956      {
957         for (i = 0; i < res->nmode; i++)
958           if (res->modes[i].id == mode)
959             {
960                if (res->modes[i].hTotal && res->modes[i].vTotal)
961                  ret = ((double)res->modes[i].dotClock /
962                         ((double)res->modes[i].hTotal *
963                          (double)res->modes[i].vTotal));
964
965                break;
966             }
967      }
968
969    if (crtc_info)
970      XRRFreeCrtcInfo(crtc_info);
971
972    if (res)
973      XRRFreeScreenResources(res);
974
975    return ret;
976 #else
977    return 0.0;
978 #endif
979 }
980
981 EAPI Ecore_X_Randr_Orientation
982 ecore_x_randr_crtc_orientations_get(Ecore_X_Window root,
983                                     Ecore_X_Randr_Crtc crtc)
984 {
985 #ifdef ECORE_XRANDR
986    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
987    XRRCrtcInfo *crtc_info = NULL;
988    XRRScreenResources *res = NULL;
989    Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None;
990
991    if (_ecore_x_randr_crtc_validate(root,
992                                     crtc) &&
993        (res =
994           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
995                                                root)) &&
996        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
997      {
998         ret = crtc_info->rotations;
999      }
1000    if (crtc_info)
1001      XRRFreeCrtcInfo(crtc_info);
1002
1003    if (res)
1004      XRRFreeScreenResources(res);
1005
1006    return ret;
1007 #else
1008    return Ecore_X_Randr_None;
1009 #endif
1010 }
1011
1012 EAPI Ecore_X_Randr_Orientation
1013 ecore_x_randr_crtc_orientation_get(Ecore_X_Window root,
1014                                    Ecore_X_Randr_Crtc crtc)
1015 {
1016 #ifdef ECORE_XRANDR
1017    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
1018    XRRCrtcInfo *crtc_info = NULL;
1019    XRRScreenResources *res = NULL;
1020    Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None;
1021
1022    if (_ecore_x_randr_crtc_validate(root,
1023                                     crtc) &&
1024        (res =
1025           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
1026                                                root)) &&
1027        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1028      {
1029         ret = crtc_info->rotation;
1030      }
1031    if (crtc_info)
1032      XRRFreeCrtcInfo(crtc_info);
1033
1034    if (res)
1035      XRRFreeScreenResources(res);
1036
1037    return ret;
1038 #else
1039    return Ecore_X_Randr_None;
1040 #endif
1041 }
1042
1043 EAPI Eina_Bool
1044 ecore_x_randr_crtc_orientation_set(Ecore_X_Window root,
1045                                    Ecore_X_Randr_Crtc crtc,
1046                                    Ecore_X_Randr_Orientation orientation)
1047 {
1048 #ifdef ECORE_XRANDR
1049    RANDR_CHECK_1_2_RET(EINA_FALSE);
1050    Eina_Bool ret = EINA_FALSE;
1051
1052    if (orientation != Ecore_X_Randr_None)
1053      {
1054         ret = ecore_x_randr_crtc_settings_set(root,
1055                                               crtc,
1056                                               NULL,
1057                                               Ecore_X_Randr_Unset,
1058                                               Ecore_X_Randr_Unset,
1059                                               Ecore_X_Randr_Unset,
1060                                               Ecore_X_Randr_Unset,
1061                                               orientation);
1062      }
1063
1064    return ret;
1065 #else
1066    return EINA_FALSE;
1067 #endif
1068 }
1069
1070 EAPI void
1071 ecore_x_randr_crtc_pos_get(Ecore_X_Window root,
1072                            Ecore_X_Randr_Crtc crtc,
1073                            int *x,
1074                            int *y)
1075 {
1076 #ifdef ECORE_XRANDR
1077    RANDR_CHECK_1_2_RET();
1078
1079    ecore_x_randr_crtc_geometry_get(root, crtc, x, y, NULL, NULL);
1080 #endif
1081 }
1082
1083 EAPI Eina_Bool
1084 ecore_x_randr_crtc_clone_set(Ecore_X_Window root,
1085                              Ecore_X_Randr_Crtc original,
1086                              Ecore_X_Randr_Crtc clon)
1087 {
1088 #ifdef ECORE_XRANDR
1089    RANDR_CHECK_1_2_RET(EINA_FALSE);
1090
1091    XRRScreenResources *res = NULL;
1092    XRRCrtcInfo *clone_crtc_info = NULL;
1093    Ecore_X_Randr_Mode original_mode = Ecore_X_Randr_None;
1094    Ecore_X_Randr_Orientation original_orientation = Ecore_X_Randr_None;
1095    Eina_Bool ret = EINA_FALSE;
1096    int x, y;
1097
1098    if (_ecore_x_randr_root_validate(root) &&
1099        _ecore_x_randr_crtc_validate(root,
1100                                     original) &&
1101        _ecore_x_randr_crtc_validate(root,
1102                                     clon) &&
1103        (res =
1104           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
1105                                                root)) &&
1106        (clone_crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, clon)))
1107      {
1108         ecore_x_randr_crtc_geometry_get(root, original, &x, &y, NULL, NULL);
1109         original_mode = ecore_x_randr_crtc_mode_get(root, original);
1110         original_orientation = ecore_x_randr_crtc_orientation_get(root,
1111                                                                   original);
1112         ret = ecore_x_randr_crtc_settings_set(root,
1113                                               clon,
1114                                               NULL,
1115                                               Ecore_X_Randr_Unset,
1116                                               x,
1117                                               y,
1118                                               original_mode,
1119                                               original_orientation);
1120         XRRFreeCrtcInfo(clone_crtc_info);
1121         XRRFreeScreenResources(res);
1122      }
1123
1124    return ret;
1125 #else
1126    return EINA_FALSE;
1127 #endif
1128 }
1129
1130 /**
1131  * @brief Sets the demanded parameters for a given CRTC. Note that the CRTC is
1132  * auto enabled in it's preferred mode, when it was disabled before.
1133  *
1134  * @param root The root window which's default display will be queried.
1135  * @param crtc The CRTC which's configuration should be altered.
1136  * @param outputs An array of outputs, that should display this CRTC's content.
1137  * @param noutputs Number of outputs in the array of outputs. If set to
1138  * Ecore_X_Randr_Unset, current outputs and number of outputs will be used.
1139  * If set to Ecore_X_Randr_None, CRTC will be disabled.
1140  * @param x New x coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current x
1141  * corrdinate will be assumed.
1142  * @param y New y coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current y
1143  * corrdinate will be assumed.
1144  * @param mode The new mode to be set. If Ecore_X_Randr_None is passed, the
1145  * CRTC will be disabled. If Ecore_X_Randr_Unset is passed, the current mode is
1146  * assumed.
1147  * @param orientation The new orientation to be set. If Ecore_X_Randr_Unset is
1148  * used, the current mode is assumed.
1149  * @return @c EINA_TRUE if the configuration alteration was successful,
1150  * @c EINA_FALSE otherwise.
1151  */
1152 EAPI Eina_Bool
1153 ecore_x_randr_crtc_settings_set(Ecore_X_Window root,
1154                                 Ecore_X_Randr_Crtc crtc,
1155                                 Ecore_X_Randr_Output *outputs,
1156                                 int noutputs,
1157                                 int x,
1158                                 int y,
1159                                 Ecore_X_Randr_Mode mode,
1160                                 Ecore_X_Randr_Orientation orientation)
1161 {
1162 #ifdef ECORE_XRANDR
1163    RANDR_CHECK_1_2_RET(EINA_FALSE);
1164    XRRScreenResources *res = NULL;
1165    XRRCrtcInfo *crtc_info = NULL;
1166    Eina_Bool ret = EINA_FALSE;
1167
1168    if (_ecore_x_randr_crtc_validate(root,
1169                                     crtc) &&
1170        (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1171      {
1172         if ((crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1173           {
1174              if ((mode == Ecore_X_Randr_None) ||
1175                  (noutputs == Ecore_X_Randr_None))
1176                {
1177                   outputs = NULL;
1178                   noutputs = 0;
1179                }
1180              else if (noutputs == (int)Ecore_X_Randr_Unset)
1181                {
1182                   outputs = (Ecore_X_Randr_Output *)crtc_info->outputs;
1183                   noutputs = crtc_info->noutput;
1184                }
1185
1186              if (mode == Ecore_X_Randr_Unset)
1187                mode = crtc_info->mode;
1188
1189              if (x < 0)
1190                x = crtc_info->x;
1191
1192              if (y < 0)
1193                y = crtc_info->y;
1194
1195              if (orientation == Ecore_X_Randr_Unset)
1196                orientation = crtc_info->rotation;
1197
1198              if (!XRRSetCrtcConfig(_ecore_x_disp, res, crtc, CurrentTime,
1199                                    x, y, mode, orientation, (RROutput *)outputs,
1200                                    noutputs))
1201                ret = EINA_TRUE;
1202
1203              XRRFreeCrtcInfo(crtc_info);
1204           }
1205
1206         XRRFreeScreenResources(res);
1207      }
1208
1209    return ret;
1210 #else
1211    return EINA_FALSE;
1212 #endif
1213 }
1214
1215 /**
1216  * @brief Sets a CRTC relative to another one.
1217  *
1218  * @param root The root window which's default display will be set.
1219  * @param crtc_r1 The CRTC to be positioned.
1220  * @param crtc_r2 The CRTC the position should be relative to.
1221  * @param policy The relation between the crtcs.
1222  * @param alignment In case CRTCs size differ, aligns CRTC1 accordingly at
1223  * CRTC2's borders.
1224  * @return @c EINA_TRUE if crtc could be successfully positioned, @c EINA_FALSE
1225  * if repositioning failed or if position of new crtc would be out of given
1226  * screen's min/max bounds.
1227  */
1228 EAPI Eina_Bool
1229 ecore_x_randr_crtc_pos_relative_set(Ecore_X_Window root,
1230                                     Ecore_X_Randr_Crtc crtc_r1,
1231                                     Ecore_X_Randr_Crtc crtc_r2,
1232                                     Ecore_X_Randr_Output_Policy policy,
1233                                     Ecore_X_Randr_Relative_Alignment alignment)
1234 {
1235 #ifdef ECORE_XRANDR
1236    RANDR_CHECK_1_2_RET(EINA_FALSE);
1237
1238    Eina_Rectangle r1_geo, r2_geo;
1239    int w_max, h_max, cw, ch, x_n = Ecore_X_Randr_Unset, y_n =
1240      Ecore_X_Randr_Unset;
1241    /*
1242       int r1_noutputs, r2_noutputs, r1_nmodes, i, j, outputs_mode_found, mode_w, mode_h;
1243       Ecore_X_Randr_Output *r1_outputs, *r2_outputs, *r2_r1_outputs;
1244       Ecore_X_Randr_Mode *r1_modes, r2_mode, r1_mode;
1245       Eina_Bool ret;
1246     */
1247
1248    if ((ecore_x_randr_crtc_mode_get(root, crtc_r1) == Ecore_X_Randr_None)
1249        || (ecore_x_randr_crtc_mode_get(root, crtc_r2) == Ecore_X_Randr_None))
1250      return EINA_FALSE;
1251
1252    if (!_ecore_x_randr_crtc_validate(root, crtc_r1) ||
1253        (!(crtc_r1 != crtc_r2) &&
1254         !_ecore_x_randr_crtc_validate(root, crtc_r2)))
1255      return EINA_FALSE;
1256
1257    ecore_x_randr_crtc_geometry_get(root,
1258                                    crtc_r1,
1259                                    &r1_geo.x,
1260                                    &r1_geo.y,
1261                                    &r1_geo.w,
1262                                    &r1_geo.h);
1263    ecore_x_randr_crtc_geometry_get(root,
1264                                    crtc_r2,
1265                                    &r2_geo.x,
1266                                    &r2_geo.y,
1267                                    &r2_geo.w,
1268                                    &r2_geo.h);
1269    ecore_x_randr_screen_size_range_get(root, NULL, NULL, &w_max, &h_max);
1270    ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
1271
1272    switch (policy)
1273      {
1274       case ECORE_X_RANDR_OUTPUT_POLICY_RIGHT:
1275         //set r1 right of r2
1276         x_n = r2_geo.x + r2_geo.w;
1277
1278         switch (alignment)
1279           {
1280            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1281              y_n = Ecore_X_Randr_Unset;
1282              break;
1283
1284            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1285              y_n =
1286                ((int)(((double)r2_geo.h /
1287                        2.0) + (double)r2_geo.y - ((double)r1_geo.h / 2.0)));
1288              break;
1289
1290            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1291              y_n = ((int)((double)ch / 2.0) - ((double)r1_geo.h / 2.0));
1292              break;
1293           }
1294         break;
1295
1296       case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
1297         //set r1 left of r2
1298         x_n = r2_geo.x - r1_geo.w;
1299
1300         switch (alignment)
1301           {
1302            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1303              y_n = Ecore_X_Randr_Unset;
1304              break;
1305
1306            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1307              y_n =
1308                ((int)(((double)r2_geo.h /
1309                        2.0) + r2_geo.y - ((double)r1_geo.h / 2.0)));
1310              break;
1311
1312            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1313              y_n = ((int)(((double)ch / 2.0) - ((double)r1_geo.h / 2.0)));
1314              break;
1315           }
1316         break;
1317
1318       case ECORE_X_RANDR_OUTPUT_POLICY_BELOW:
1319         //set r1 below r2
1320         y_n = r2_geo.y + r2_geo.h;
1321
1322         switch (alignment)
1323           {
1324            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1325              x_n = Ecore_X_Randr_Unset;
1326              break;
1327
1328            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1329              x_n =
1330                ((int)((((double)r2_geo.x +
1331                         (double)r2_geo.w) / 2.0) - ((double)r1_geo.w / 2.0)));
1332              break;
1333
1334            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1335              x_n = ((int)((double)cw / 2.0));
1336              break;
1337           }
1338         break;
1339
1340       case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
1341         y_n = r2_geo.y - r1_geo.h;
1342
1343         //set r1 above r2
1344         switch (alignment)
1345           {
1346            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1347              x_n = Ecore_X_Randr_Unset;
1348              break;
1349
1350            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1351              x_n =
1352                ((int)((((double)r2_geo.x +
1353                         (double)r2_geo.w) / 2.0) - ((double)r1_geo.w / 2.0)));
1354              break;
1355
1356            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1357              x_n = ((int)((double)cw / 2.0));
1358              break;
1359           }
1360         break;
1361
1362       case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
1363         return ecore_x_randr_crtc_pos_set(root, crtc_r1, r2_geo.x, r2_geo.y);
1364
1365       /* entire cloning (including modesetting)
1366          //all outputs of crtc1 capable of crtc2's current mode?
1367          r2_mode = ecore_x_randr_crtc_mode_get(root, crtc_r2);
1368          if (!(r1_outputs =
1369                ecore_x_randr_crtc_outputs_get(root, crtc_r1,
1370                                               &r1_noutputs)) ||
1371           (r1_noutputs == 0))
1372          return EINA_FALSE;
1373
1374          for (i = 0, outputs_mode_found = 0; i < r1_noutputs; i++)
1375          {
1376            if (!(r1_modes =
1377                     ecore_x_randr_output_modes_get(root, r1_outputs[i],
1378                                                    &r1_nmodes, NULL)))
1379              {
1380                 free(r1_outputs);
1381                 return EINA_FALSE;
1382              }
1383
1384            for (j = 0; j < r1_nmodes; j++)
1385              {
1386                 ecore_x_randr_mode_size_get(root,
1387                                             r1_modes[j],
1388                                             &mode_w,
1389                                             &mode_h);
1390                 if ((mode_w == r2_geo.w) && (mode_h == r2_geo.h))
1391                   {
1392                      r1_mode = r1_modes[j];
1393          ++outputs_mode_found;
1394                      free(r1_modes);
1395                      r1_modes = NULL;
1396                      break;
1397                   }
1398              }
1399            if (r1_modes)
1400                      free(r1_modes);
1401
1402            if (outputs_mode_found <= i)
1403              {
1404                 //an output doesn't support the set mode, cancel!
1405                      free(r1_outputs);
1406                 return EINA_FALSE;
1407              }
1408          }
1409                      free (r1_outputs);
1410          //CRTC 1's outputs support a mode of same geometry as CRTC 2.
1411          ret =
1412          (ecore_x_randr_crtc_mode_set(root, crtc_r1, Ecore_X_Randr_None,
1413                                       Ecore_X_Randr_None,
1414                                       r1_mode) &&
1415           ecore_x_randr_crtc_pos_set(root, crtc_r1, r2_geo.x, r2_geo.y));
1416          return ret;
1417        */
1418
1419       /* entire cloning on same CRTC
1420          //all outputs of crtc1 capable of crtc2's current mode?
1421          r2_mode = ecore_x_randr_crtc_mode_get(root, crtc_r2);
1422          if (!(r1_outputs =
1423                ecore_x_randr_crtc_outputs_get(root, crtc_r1,
1424                                               &r1_noutputs)) ||
1425           (r1_noutputs == 0))
1426          return EINA_FALSE;
1427
1428          for (i = 0, outputs_mode_found = 0; i < r1_noutputs; i++)
1429          {
1430            if (!(r1_modes =
1431                     ecore_x_randr_output_modes_get(root, r1_outputs[i],
1432                                                    &r1_nmodes, NULL)))
1433              {
1434                      free(r1_outputs);
1435                 return EINA_FALSE;
1436              }
1437
1438            for (j = 0; j < r1_nmodes; j++)
1439              {
1440                 if (r1_modes[j] == r2_mode)
1441                   {
1442          ++outputs_mode_found;
1443                      free(r1_modes);
1444                      r1_modes = NULL;
1445                      break;
1446                   }
1447              }
1448            if (r1_modes)
1449                      free(r1_modes);
1450
1451            if (outputs_mode_found <= i)
1452              {
1453                 //an output doesn't support the set mode, cancel!
1454                      free(r1_outputs);
1455                 return EINA_FALSE;
1456              }
1457          }
1458          //check whether crtc r2 can use all outputs of r1.
1459          if (!(r2_outputs =
1460                ecore_x_randr_crtc_possible_outputs_get(root, crtc_r2,
1461                                                        &r2_noutputs)) ||
1462           (r2_noutputs == 0))
1463          {
1464                 free(r1_outputs);
1465            return EINA_FALSE;
1466          }
1467
1468          for (i = 0; i < r1_noutputs; i++)
1469          {
1470            for (j = 0; j < r2_noutputs; )
1471              {
1472                 if (r1_outputs[i] == r2_outputs[j])
1473                    break;
1474
1475                 j++;
1476              }
1477            if (j == r2_noutputs)
1478              {
1479                 //didn't find the output!
1480                 free (r1_outputs);
1481                 free (r2_outputs);
1482                 return EINA_FALSE;
1483              }
1484          }
1485
1486          //apparently crtc2 supports all outputs of r1
1487          //TODO: check with the compatible list of outputs (property in RR1.3)
1488          r2_r1_outputs =
1489          malloc(sizeof(Ecore_X_Randr_Output) * (r1_noutputs + r2_noutputs));
1490          for (i = 0; i < r1_noutputs; i++)
1491          {
1492            r2_r1_outputs[i] = r1_outputs[i];
1493          }
1494          free(r1_outputs);
1495          for (; i < r2_noutputs; i++)
1496          {
1497            r2_r1_outputs[i] = r2_outputs[i];
1498          }
1499          free(r2_outputs);
1500          ret =
1501          ecore_x_randr_crtc_mode_set(root, crtc_r2, r2_r1_outputs,
1502                                      (r1_noutputs + r1_noutputs), r2_mode);
1503          free (r2_r1_outputs);
1504          return ret;
1505        */
1506       case ECORE_X_RANDR_OUTPUT_POLICY_NONE:
1507         break;
1508       default:
1509         return EINA_FALSE;
1510      }
1511    if ((x_n == r1_geo.x) && (y_n == r1_geo.x))
1512      return EINA_TRUE;
1513
1514    //out of possible bounds?
1515    if (((y_n + r1_geo.h) > h_max) || ((x_n + r1_geo.w) > w_max))
1516      return EINA_FALSE;
1517
1518    return ecore_x_randr_crtc_pos_set(root, crtc_r1, x_n, y_n);
1519 #else
1520    return EINA_FALSE;
1521 #endif
1522 }
1523
1524 /*
1525  * @brief Add given mode to given output.
1526  *
1527  * @param output The output the mode is added to.
1528  * @param mode The mode added to the output.
1529  * @return @c EINA_FALSE if output or mode equal Ecore_X_Randr_None, else
1530  * @c EINA_TRUE.
1531  * Additionally, if xcb backend is used, the success of the addition is
1532  * reported back directly.
1533  * @since 1.2.0
1534  */
1535 EAPI Eina_Bool
1536 ecore_x_randr_output_mode_add(Ecore_X_Randr_Output output,
1537                               Ecore_X_Randr_Mode mode)
1538 {
1539 #ifdef ECORE_XRANDR
1540    RANDR_CHECK_1_2_RET(EINA_FALSE);
1541
1542    if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None))
1543      return EINA_FALSE;
1544
1545    XRRAddOutputMode(_ecore_x_disp, output, mode);
1546    return EINA_TRUE;
1547 #else
1548    return EINA_FALSE;
1549 #endif
1550 }
1551
1552 /*
1553  * @brief delete given mode from given output
1554  * @param output the output the mode is removed from
1555  * @param mode the mode removed from the output
1556  * @since 1.2.0
1557  */
1558 EAPI void
1559 ecore_x_randr_output_mode_del(Ecore_X_Randr_Output output,
1560                               Ecore_X_Randr_Mode mode)
1561 {
1562 #ifdef ECORE_XRANDR
1563    RANDR_CHECK_1_2_RET();
1564
1565    if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None))
1566      return;
1567
1568    XRRDeleteOutputMode(_ecore_x_disp, output, mode);
1569 #else
1570    return;
1571 #endif
1572 }
1573
1574 EAPI Ecore_X_Randr_Mode *
1575 ecore_x_randr_output_modes_get(Ecore_X_Window root,
1576                                Ecore_X_Randr_Output output,
1577                                int *num,
1578                                int *npreferred)
1579 {
1580 #ifdef ECORE_XRANDR
1581    RANDR_CHECK_1_2_RET(NULL);
1582    XRRScreenResources *res = NULL;
1583    XRROutputInfo *output_info = NULL;
1584    Ecore_X_Randr_Mode *modes = NULL;
1585
1586    if ((output != Ecore_X_Randr_None)
1587        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1588        && (output_info =
1589              XRRGetOutputInfo(_ecore_x_disp, res, (RROutput)output)))
1590      {
1591         if ((modes = malloc(sizeof(Ecore_X_Randr_Mode) * output_info->nmode)))
1592           {
1593              int i = 0;
1594
1595              if (num) *num = output_info->nmode;
1596              if (npreferred) *npreferred = output_info->npreferred;
1597
1598              for (i = 0; i < output_info->nmode; i++)
1599                modes[i] = output_info->modes[i];
1600           }
1601      }
1602
1603    if (output_info)
1604      XRRFreeOutputInfo(output_info);
1605
1606    if (res)
1607      XRRFreeScreenResources(res);
1608
1609    return modes;
1610 #else
1611    return NULL;
1612 #endif
1613 }
1614
1615 EAPI Ecore_X_Randr_Crtc *
1616 ecore_x_randr_output_possible_crtcs_get(Ecore_X_Window root,
1617                                         Ecore_X_Randr_Output output,
1618                                         int *num)
1619 {
1620 #ifdef ECORE_XRANDR
1621    RANDR_CHECK_1_2_RET(NULL);
1622    XRRScreenResources *res = NULL;
1623    XRROutputInfo *output_info = NULL;
1624    Ecore_X_Randr_Crtc *crtcs = NULL;
1625
1626    if ((output != Ecore_X_Randr_None))
1627      {
1628         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1629           {
1630              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1631                {
1632                   if ((crtcs = malloc(sizeof(Ecore_X_Randr_Crtc) * output_info->ncrtc)))
1633                     {
1634                        memcpy(crtcs, output_info->crtcs, (sizeof(Ecore_X_Randr_Crtc) * output_info->ncrtc));
1635                        if (num) *num = output_info->ncrtc;
1636                     }
1637                   XRRFreeOutputInfo(output_info);
1638                }
1639              XRRFreeScreenResources(res);
1640           }
1641      }
1642    return crtcs;
1643 #else
1644    return Ecore_X_Randr_None;
1645 #endif
1646 }
1647
1648 /**
1649  * @brief gets the the outputs which might be used simultenously on the same
1650  * CRTC.
1651  * @param root window that this information should be queried for.
1652  * @param output the output which's clones we concern
1653  * @param num number of possible clones
1654  */
1655 EAPI Ecore_X_Randr_Output *
1656 ecore_x_randr_output_clones_get(Ecore_X_Window root,
1657                                 Ecore_X_Randr_Output output,
1658                                 int *num)
1659 {
1660 #ifdef ECORE_XRANDR
1661    RANDR_CHECK_1_2_RET(NULL);
1662    XRRScreenResources *res = NULL;
1663    XRROutputInfo *output_info = NULL;
1664    Ecore_X_Randr_Output *outputs = NULL;
1665
1666    if ((output != Ecore_X_Randr_None))
1667      {
1668         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1669           {
1670              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1671                {
1672                   if ((outputs = malloc(sizeof(Ecore_X_Randr_Output) * output_info->nclone)))
1673                     {
1674                        memcpy(outputs, output_info->clones, (sizeof(Ecore_X_Randr_Output) * output_info->nclone));
1675                        if (num) *num = output_info->nclone;
1676                     }
1677                   XRRFreeOutputInfo(output_info);
1678                }
1679              XRRFreeScreenResources(res);
1680           }
1681      }
1682    return outputs;
1683 #else
1684    return Ecore_X_Randr_None;
1685 #endif
1686 }
1687
1688 EAPI Ecore_X_Randr_Crtc
1689 ecore_x_randr_output_crtc_get(Ecore_X_Window root,
1690                               Ecore_X_Randr_Output output)
1691 {
1692 #ifdef ECORE_XRANDR
1693    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
1694    XRRScreenResources *res = NULL;
1695    XRROutputInfo *output_info = NULL;
1696    Ecore_X_Randr_Crtc ret = Ecore_X_Randr_None;
1697
1698    if ((output != Ecore_X_Randr_None))
1699      {
1700         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1701           {
1702              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1703                {
1704                   ret = output_info->crtc;
1705                   XRRFreeOutputInfo(output_info);
1706                }
1707              XRRFreeScreenResources(res);
1708           }
1709      }
1710
1711    return ret;
1712 #else
1713    return Ecore_X_Randr_None;
1714 #endif
1715 }
1716
1717 /**
1718  * @brief gets the given output's name as reported by X
1719  * @param root the window which's screen will be queried
1720  * @param output The output for which the name will be reported.
1721  * @param len length of returned c-string.
1722  * @return name of the output as reported by X
1723  */
1724 EAPI char *
1725 ecore_x_randr_output_name_get(Ecore_X_Window root,
1726                               Ecore_X_Randr_Output output,
1727                               int *len)
1728 {
1729 #ifdef ECORE_XRANDR
1730    RANDR_CHECK_1_2_RET(NULL);
1731    XRRScreenResources *res = NULL;
1732    XRROutputInfo *output_info = NULL;
1733    char *ret = NULL;
1734
1735    if ((output != Ecore_X_Randr_None)
1736        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1737        && (output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1738      {
1739         /*
1740          * Actually the below command is correct, but due to a bug in libXrandr
1741          * it doesn't work. Therefore we stick with strlen().
1742          * Replace the line below with the following once this bug is
1743          * fixed within libXrandr.
1744          *
1745          *    *len = output_info->nameLen;
1746          *
1747          */
1748         if ((ret = strdup(output_info->name)) && len)
1749           *len = strlen(ret);
1750
1751         XRRFreeOutputInfo(output_info);
1752      }
1753
1754    if (res)
1755      XRRFreeScreenResources(res);
1756
1757    return ret;
1758 #else
1759    return NULL;
1760 #endif
1761 }
1762
1763 /**
1764  * @brief gets the width and hight of a given mode
1765  * @param mode the mode which's size is to be looked up
1766  * @param w width of given mode in px
1767  * @param h height of given mode in px
1768  */
1769 EAPI void
1770 ecore_x_randr_mode_size_get(Ecore_X_Window root,
1771                             Ecore_X_Randr_Mode mode,
1772                             int *w,
1773                             int *h)
1774 {
1775 #ifdef ECORE_XRANDR
1776    RANDR_CHECK_1_2_RET();
1777    XRRScreenResources *res = NULL;
1778    int i;
1779
1780    if ((mode != Ecore_X_Randr_None)
1781        && (w || h)
1782        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1783      {
1784         for (i = 0; i < res->nmode; i++)
1785           {
1786              if (res->modes[i].id == mode)
1787                {
1788                   if (w)
1789                     *w = res->modes[i].width;
1790
1791                   if (h)
1792                     *h = res->modes[i].height;
1793
1794                   break;
1795                }
1796           }
1797      }
1798
1799    if (res)
1800      XRRFreeScreenResources(res);
1801
1802 #endif
1803 }
1804
1805 /**
1806  * @brief gets the EDID information of an attached output if available.
1807  * Note that this information is not to be compared using ordinary string
1808  * comparison functions, since it includes 0-bytes.
1809  * @param root window this information should be queried from
1810  * @param output the XID of the output
1811  * @param length length of the byte-array. If NULL, request will fail.
1812  */
1813 EAPI unsigned char *
1814 ecore_x_randr_output_edid_get(Ecore_X_Window root,
1815                               Ecore_X_Randr_Output output,
1816                               unsigned long *length)
1817 {
1818 #ifdef ECORE_XRANDR
1819    RANDR_CHECK_1_2_RET(NULL);
1820    Atom name = XInternAtom (_ecore_x_disp, RANDR_PROPERTY_EDID, False);
1821    unsigned char *prop_data, *ret = NULL;
1822    int actual_format;
1823    unsigned long nitems, bytes_after;
1824    Atom actual_type;
1825
1826    if (!length || !_ecore_x_randr_output_validate(root, output))
1827      return NULL;
1828
1829    if (XRRGetOutputProperty (_ecore_x_disp, output, name,
1830                              0, 100, False, False,
1831                              AnyPropertyType,
1832                              &actual_type, &actual_format,
1833                              &nitems, &bytes_after, &prop_data) == Success)
1834      {
1835         if (actual_type == XA_INTEGER && actual_format == 8)
1836           {
1837              if ((ret = malloc(nitems * sizeof(unsigned char))))
1838                {
1839                   if (length &&
1840                       (memcpy(ret, prop_data, (nitems * sizeof(unsigned char)))))
1841                     *length = nitems;
1842
1843                   return ret;
1844                }
1845           }
1846      }
1847
1848    return NULL;
1849 #else
1850    return NULL;
1851 #endif
1852 }
1853
1854 EAPI Ecore_X_Randr_Connection_Status
1855 ecore_x_randr_output_connection_status_get(Ecore_X_Window root,
1856                                            Ecore_X_Randr_Output output)
1857 {
1858 #ifdef ECORE_XRANDR
1859    RANDR_CHECK_1_2_RET(ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN);
1860    XRRScreenResources *res = NULL;
1861    XRROutputInfo *output_info = NULL;
1862    Ecore_X_Randr_Connection_Status ret =
1863      ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
1864
1865    if ((output != Ecore_X_Randr_None)
1866        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1867        && (output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1868      {
1869         ret = output_info->connection;
1870      }
1871
1872    if (output_info)
1873      XRRFreeOutputInfo(output_info);
1874
1875    if (res)
1876      XRRFreeScreenResources(res);
1877
1878    return ret;
1879 #else
1880    return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
1881 #endif
1882 }
1883
1884 EAPI void
1885 ecore_x_randr_output_size_mm_get(Ecore_X_Window root,
1886                                  Ecore_X_Randr_Output output,
1887                                  int *w_mm,
1888                                  int *h_mm)
1889 {
1890 #ifdef ECORE_XRANDR
1891    RANDR_CHECK_1_2_RET();
1892    XRRScreenResources *res = NULL;
1893    XRROutputInfo *output_info = NULL;
1894
1895    if ((output != Ecore_X_Randr_None)
1896        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1897      {
1898         if ((output_info =
1899                XRRGetOutputInfo(_ecore_x_disp, res, (RROutput)output)))
1900           {
1901              if (w_mm)
1902                *w_mm = output_info->mm_width;
1903
1904              if (h_mm)
1905                *h_mm = output_info->mm_height;
1906
1907              XRRFreeOutputInfo(output_info);
1908           }
1909
1910         XRRFreeScreenResources(res);
1911      }
1912
1913 #endif
1914 }
1915
1916 EAPI Eina_Bool
1917 ecore_x_randr_move_all_crtcs_but(Ecore_X_Window root,
1918                                  const Ecore_X_Randr_Crtc *not_moved,
1919                                  int nnot_moved,
1920                                  int dx,
1921                                  int dy)
1922 {
1923 #ifdef ECORE_XRANDR
1924    Ecore_X_Randr_Crtc *crtcs_to_be_moved = NULL;
1925    XRRScreenResources *res = NULL;
1926    int i, j, k, n;
1927    Eina_Bool ret;
1928
1929    if ((nnot_moved <= 0) || (!not_moved)
1930        || !_ecore_x_randr_root_validate(root)
1931        || !(res =
1932               _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
1933      return EINA_FALSE;
1934
1935    n = (res->ncrtc - nnot_moved);
1936    if ((crtcs_to_be_moved = malloc(sizeof(Ecore_X_Randr_Crtc) * n)))
1937      {
1938         for (i = 0, k = 0; (i < res->ncrtc) && (k < n); i++)
1939           {
1940              for (j = 0; j < nnot_moved; j++)
1941                {
1942                   if (res->crtcs[i] == not_moved[j])
1943                     break;
1944                }
1945              if (j == nnot_moved)
1946                //crtcs[i] is not in the 'not to move'-list
1947                crtcs_to_be_moved[k++] = res->crtcs[i];
1948           }
1949      }
1950
1951    XRRFreeScreenResources(res);
1952    ret = ecore_x_randr_move_crtcs(root, crtcs_to_be_moved, n, dx, dy);
1953    free(crtcs_to_be_moved);
1954    return ret;
1955 #else
1956    return EINA_FALSE;
1957 #endif
1958 }
1959
1960 /*
1961  * @brief Move given CRTCs belonging to the given root window's screen dx/dy
1962  * pixels relative to their current position. The screen size will be
1963  * automatically adjusted if necessary and possible.
1964  *
1965  * @param root Window which's screen's resources are used.
1966  * @param crtcs List of CRTCs to be moved.
1967  * @param ncrtc Number of CRTCs in array.
1968  * @param dx Amount of pixels the CRTCs should be moved in x direction.
1969  * @param dy Amount of pixels the CRTCs should be moved in y direction.
1970  * @return @c EINA_TRUE if all crtcs could be moved successfully.
1971  */
1972 EAPI Eina_Bool
1973 ecore_x_randr_move_crtcs(Ecore_X_Window root,
1974                          const Ecore_X_Randr_Crtc *crtcs,
1975                          int ncrtc,
1976                          int dx,
1977                          int dy)
1978 {
1979 #ifdef ECORE_XRANDR
1980    RANDR_CHECK_1_2_RET(EINA_FALSE);
1981    XRRScreenResources *res = NULL;
1982    XRRCrtcInfo **crtc_info = NULL;
1983    Eina_Bool ret = EINA_TRUE;
1984    int i, cw, ch, w_max, h_max, nw, nh;
1985
1986    crtc_info = alloca(sizeof(XRRCrtcInfo *) * ncrtc);
1987    memset(crtc_info, 0, sizeof(XRRCrtcInfo *) * ncrtc);
1988    if (_ecore_x_randr_root_validate(root)
1989        && (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
1990      {
1991         ecore_x_randr_screen_size_range_get(root, NULL, NULL, &w_max, &h_max);
1992         ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
1993         nw = cw;
1994         nh = ch;
1995
1996         for (i = 0;
1997              (i < ncrtc) &&
1998              (crtc_info[i] = XRRGetCrtcInfo(_ecore_x_disp, res, crtcs[i]));
1999              i++)
2000           {
2001              if (((crtc_info[i]->x + dx) < 0) ||
2002                  ((int)(crtc_info[i]->x + crtc_info[i]->width + dx) > w_max)
2003                  || ((crtc_info[i]->y + dy) < 0) ||
2004                  ((int)(crtc_info[i]->y + crtc_info[i]->height + dy) > h_max)
2005                  )
2006                goto _ecore_x_randr_move_crtcs_fail_free_crtc_info;
2007
2008              nw = MAX((int)(crtc_info[i]->x + crtc_info[i]->width + dx), nw);
2009              nh = MAX((int)(crtc_info[i]->y + crtc_info[i]->height + dy), nh);
2010           }
2011         //not out of bounds
2012
2013         //resize if necessary
2014         if (!(((nw > cw) ||
2015                (nh > ch)) ||
2016               ecore_x_randr_screen_current_size_set(root, nw, nh,
2017                                                     Ecore_X_Randr_Unset,
2018                                                     Ecore_X_Randr_Unset)))
2019           goto _ecore_x_randr_move_crtcs_fail_free_crtc_info;
2020
2021         //actually move all the crtcs, keep their rotation and mode.
2022         for (i = 0; (i < ncrtc) && crtc_info[i]; i++)
2023           {
2024              if ((crtc_info[i]) &&
2025                  (!ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL,
2026                                                    Ecore_X_Randr_Unset,
2027                                                    (crtc_info[i]->x + dx),
2028                                                    (crtc_info[i]->y + dy),
2029                                                    crtc_info[i]->mode,
2030                                                    crtc_info[i]->rotation)))
2031                {
2032                   ret = EINA_FALSE;
2033                   break;
2034                }
2035           }
2036         if (i < ncrtc)
2037           {
2038              //something went wrong, let's try to move the already moved crtcs
2039              //back.
2040              while ((i--) >= 0)
2041                {
2042                   if (crtc_info[i])
2043                     ecore_x_randr_crtc_settings_set(root,
2044                                                     crtcs[i],
2045                                                     NULL,
2046                                                     Ecore_X_Randr_Unset,
2047                                                     (crtc_info[i]->x - dx),
2048                                                     (crtc_info[i]->y - dy),
2049                                                     crtc_info[i]->mode,
2050                                                     crtc_info[i]->rotation);
2051                }
2052           }
2053
2054         for (i = 0; i < ncrtc; i++)
2055           {
2056              if (crtc_info[i]) XRRFreeCrtcInfo(crtc_info[i]);
2057           }
2058      }
2059
2060    XRRFreeScreenResources(res);
2061
2062    return ret;
2063 _ecore_x_randr_move_crtcs_fail_free_crtc_info:
2064    while (i-- > 0)
2065      XRRFreeCrtcInfo(crtc_info[i]);
2066    XRRFreeScreenResources(res);
2067    return EINA_FALSE;
2068 #else
2069    return EINA_FALSE;
2070 #endif
2071 }
2072
2073 /**
2074  * @brief removes unused screen space. The most upper left CRTC is set to 0x0
2075  * and all other CRTCs dx,dy respectively.
2076  * @param root the window's screen which will be reset.
2077  */
2078 EAPI void
2079 ecore_x_randr_screen_reset(Ecore_X_Window root)
2080 {
2081 #ifdef ECORE_XRANDR
2082    XRRCrtcInfo *crtc_info = NULL;
2083    XRRScreenResources *res = NULL;
2084    //the 100000 are just a random huge number.
2085    int i, dx_min = 100000, dy_min = 100000, w_n = 0, h_n = 0, nenabled_crtcs = 0;
2086
2087    if (!_ecore_x_randr_root_validate(root) ||
2088        !(res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
2089      return;
2090
2091    Ecore_X_Randr_Crtc enabled_crtcs[res->ncrtc];
2092
2093    for (i = 0; i < res->ncrtc; i++)
2094      {
2095         if (!(crtc_info =
2096                 XRRGetCrtcInfo(_ecore_x_disp, res,
2097                                res->crtcs[i])) ||
2098             (crtc_info->mode == Ecore_X_Randr_None) ||
2099             (crtc_info->mode == Ecore_X_Randr_Unset)
2100             || ((crtc_info->noutput == 0)))
2101           continue;
2102
2103         enabled_crtcs[nenabled_crtcs++] = res->crtcs[i];
2104
2105         if ((int)(crtc_info->x + crtc_info->width) > w_n)
2106           w_n = (crtc_info->x + crtc_info->width);
2107
2108         if ((int)(crtc_info->y + crtc_info->height) > h_n)
2109           h_n = (crtc_info->y + crtc_info->height);
2110
2111         if (crtc_info->x < dx_min)
2112           dx_min = crtc_info->x;
2113         if (crtc_info->y < dy_min)
2114           dy_min = crtc_info->y;
2115
2116         XRRFreeCrtcInfo(crtc_info);
2117      }
2118    if ((dx_min > 0) || (dy_min > 0))
2119      {
2120         if (ecore_x_randr_move_crtcs(root, enabled_crtcs, nenabled_crtcs, -dx_min, -dy_min))
2121           {
2122              w_n -= dx_min;
2123              h_n -= dy_min;
2124           }
2125      }
2126    ecore_x_randr_screen_current_size_set(root,
2127                                          w_n,
2128                                          h_n,
2129                                          Ecore_X_Randr_Unset,
2130                                          Ecore_X_Randr_Unset);
2131 #endif
2132 }
2133
2134 /**
2135  * @brief Set up the backlight level to the given level.
2136  *
2137  * @param root The window's screen which will be set.
2138  * @param level Of the backlight between @c 0 and @c 1.
2139  */
2140
2141 EAPI void
2142 ecore_x_randr_screen_backlight_level_set(Ecore_X_Window root,
2143                                          double level)
2144 {
2145 #ifdef ECORE_XRANDR
2146    RANDR_CHECK_1_2_RET();
2147    Atom _backlight;
2148    XRRScreenResources *resources = NULL;
2149    Ecore_X_Randr_Output output;
2150    int o;
2151
2152    if ((level < 0) || (level > 1))
2153      {
2154         ERR("Wrong value for the backlight level. It should be between 0 and 1.");
2155         return;
2156      }
2157
2158    /*
2159     * To make sure that the _backlight atomic property still exists.
2160     */
2161    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2162    if (_backlight == None)
2163      {
2164         WRN("Backlight setting is not supported on this server or driver");
2165         return;
2166      }
2167
2168    /* get the ressources */
2169    resources = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root);
2170    if (!resources) return;
2171
2172    for (o = 0; o < resources->noutput; o++)
2173      {
2174         output = resources->outputs[o];
2175         if (ecore_x_randr_output_backlight_level_get(root, output) >= 0)
2176           {
2177              ecore_x_randr_output_backlight_level_set(root, output, level);
2178           }
2179      }
2180    XRRFreeScreenResources(resources);
2181 #endif
2182 }
2183
2184 /*
2185  * @brief Check if a backlight is available.
2186  * @return Whether a backlight is available.
2187  */
2188
2189 EAPI Eina_Bool
2190 ecore_x_randr_output_backlight_available(void)
2191 {
2192 #ifdef ECORE_XRANDR
2193    RANDR_CHECK_1_2_RET(-1);
2194    Atom _backlight;
2195
2196    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2197
2198    return (_backlight == None) ? EINA_FALSE : EINA_TRUE;
2199
2200 #endif
2201    return EINA_FALSE;
2202 }
2203
2204 /*
2205  * @brief Get the backlight level of the given output.
2206  *
2207  * @param root Window which's screen should be queried.
2208  * @param output From which the backlight level should be retrieved.
2209  * @return The backlight level.
2210  */
2211
2212 EAPI double
2213 ecore_x_randr_output_backlight_level_get(Ecore_X_Window root,
2214                                          Ecore_X_Randr_Output output)
2215 {
2216 #ifdef ECORE_XRANDR
2217    RANDR_CHECK_1_2_RET(-1);
2218    Atom actual_type;
2219    Atom _backlight;
2220    XRRPropertyInfo *info = NULL;
2221    double dvalue;
2222    int actual_format;
2223    long value, max, min;
2224    unsigned long nitems;
2225    unsigned long bytes_after;
2226    unsigned char *prop = NULL;
2227
2228    /* set backlight variable if not already done */
2229
2230    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2231    if (_backlight == None)
2232      {
2233         ERR("Backlight property is not suppported on this server or driver");
2234         return -1;
2235      }
2236
2237    if (!_ecore_x_randr_output_validate(root, output))
2238      {
2239         ERR("Invalid output");
2240         return -1;
2241      }
2242
2243    if (XRRGetOutputProperty(_ecore_x_disp, output, _backlight,
2244                             0, 4, False, False, None,
2245                             &actual_type, &actual_format,
2246                             &nitems, &bytes_after, &prop) != Success)
2247      {
2248         WRN("Backlight not supported on this output");
2249         return -1;
2250      }
2251
2252    if ((actual_type != XA_INTEGER) || (nitems != 1) || (actual_format != 32)) return -1;
2253
2254    value = *((long *)prop);
2255    free (prop);
2256
2257    /* I have the current value of the backlight */
2258    /* Now retrieve the min and max intensities of the output */
2259    info = XRRQueryOutputProperty(_ecore_x_disp, output, _backlight);
2260    if (info)
2261      {
2262         dvalue = -1;
2263         if ((info->range) && (info->num_values == 2))
2264           {
2265              /* finally convert the current value in the interval [0..1] */
2266              min = info->values[0];
2267              max = info->values[1];
2268              dvalue = ((double)(value - min)) / ((double)(max - min));
2269           }
2270         free(info);
2271         return dvalue;
2272      }
2273 #endif
2274    return -1;
2275 }
2276
2277 /*
2278  * @brief Set the backlight level of a given output.
2279  *
2280  * @param root Window which's screen should be queried.
2281  * @param output That should be set.
2282  * @param level For which the backlight should be set.
2283  * @return @c EINA_TRUE in case of success.
2284  */
2285
2286 EAPI Eina_Bool
2287 ecore_x_randr_output_backlight_level_set(Ecore_X_Window root,
2288                                          Ecore_X_Randr_Output output,
2289                                          double level)
2290 {
2291 #ifdef ECORE_XRANDR
2292    RANDR_CHECK_1_2_RET(EINA_FALSE);
2293    Atom _backlight;
2294    XRRPropertyInfo *info = NULL;
2295    double min, max, tmp;
2296    long new;
2297
2298    if ((level < 0) || (level > 1))
2299      {
2300         ERR("Backlight level should be between 0 and 1");
2301         return EINA_FALSE;
2302      }
2303
2304    if (!_ecore_x_randr_output_validate(root, output))
2305      {
2306         ERR("Wrong output value");
2307         return EINA_FALSE;
2308      }
2309
2310    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2311    if (_backlight == None)
2312      {
2313         WRN("Backlight property is not suppported on this server or driver");
2314         return EINA_FALSE;
2315      }
2316
2317    info = XRRQueryOutputProperty(_ecore_x_disp, output, _backlight);
2318    if (info)
2319      {
2320         if ((info->range) && (info->num_values == 2))
2321           {
2322              min = info->values[0];
2323              max = info->values[1];
2324              tmp = (level * (max - min)) + min;
2325              new = tmp;
2326              if (new > max) new = max;
2327              if (new < min) new = min;
2328              XRRChangeOutputProperty(_ecore_x_disp, output, _backlight, XA_INTEGER, 32,
2329                                      PropModeReplace, (unsigned char *)&new, 1);
2330              XFlush(_ecore_x_disp);
2331           }
2332         free(info);
2333         return EINA_TRUE;
2334      }
2335 #endif
2336    return EINA_FALSE;
2337 }
2338
2339 /*
2340  * @brief Get the outputs, which display a certain window.
2341  *
2342  * @param window Window the displaying outputs shall be found for
2343  * @param num The number of outputs displaying the window
2344  * @return Array of outputs that display a certain window. @c NULL if no
2345  * outputs was found that displays the specified window.
2346  */
2347
2348 EAPI Ecore_X_Randr_Output *
2349 ecore_x_randr_window_outputs_get(Ecore_X_Window window,
2350                                  int *num)
2351 {
2352 #ifdef ECORE_XRANDR
2353    Ecore_X_Window root;
2354    Ecore_X_Randr_Crtc *crtcs;
2355    Ecore_X_Randr_Output *outputs, *ret = NULL, *tret;
2356    int ncrtcs, noutputs, i, nret = 0;
2357
2358    if (_randr_version < RANDR_1_2) goto _ecore_x_randr_current_output_get_fail;
2359
2360    root = ecore_x_window_root_get(window);
2361    if (!(crtcs = ecore_x_randr_window_crtcs_get(window, &ncrtcs)))
2362      goto _ecore_x_randr_current_output_get_fail;
2363    
2364    for (i = 0, nret = 0; i < ncrtcs; i++)
2365      {
2366
2367         outputs = ecore_x_randr_crtc_outputs_get(root, crtcs[i],
2368                                                  &noutputs);
2369         if (!outputs)
2370           goto _ecore_x_randr_current_output_get_fail_free;
2371         tret = realloc(ret, ((nret + noutputs) * sizeof(Ecore_X_Randr_Output)));
2372         if (!tret) goto _ecore_x_randr_current_output_get_fail_free;
2373         ret = tret;
2374         memcpy(&ret[nret], outputs, (noutputs * sizeof(Ecore_X_Randr_Output)));
2375         nret += noutputs;
2376         free(outputs);
2377         outputs = NULL;
2378      }
2379    free(crtcs);
2380
2381    if (num)
2382      *num = nret;
2383
2384    return ret;
2385
2386 _ecore_x_randr_current_output_get_fail_free:
2387    free(outputs);
2388    free(crtcs);
2389    free(ret);
2390 _ecore_x_randr_current_output_get_fail:
2391 #endif
2392    if (num) *num = 0;
2393    return NULL;
2394 }
2395
2396 /*
2397  * @deprecated bad naming. Use ecore_x_randr_window_outputs_get instead.
2398  * @brief Get the outputs, which display a certain window.
2399  *
2400  * @param window Window the displaying outputs shall be found for.
2401  * @param num The number of outputs displaying the window.
2402  * @return Array of outputs that display a certain window. @c NULL if no
2403  * outputs was found that displays the specified window.
2404  */
2405
2406 EAPI Ecore_X_Randr_Output *
2407 ecore_x_randr_current_output_get(Ecore_X_Window window,
2408                                  int *num)
2409 {
2410    return ecore_x_randr_window_outputs_get(window, num);
2411 }
2412