EFL core migration @74576
[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 (num && 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              memcpy(ret, res->crtcs, (sizeof(Ecore_X_Randr_Crtc) * res->ncrtc));
536              *num = res->ncrtc;
537           }
538
539         XRRFreeScreenResources(res);
540      }
541
542    return ret;
543 #else
544    return NULL;
545 #endif
546 }
547
548 /*
549  * @deprecated bad naming. Use ecore_x_randr_window_crtcs_get instead.
550  * @brief get the CRTCs, which display a certain window
551  * @param window window the displaying crtcs shall be found for
552  * @param num the number of crtcs displaying the window
553  * @return Array of crtcs that display a certain window. @c NULL if no crtcs
554  * was found that displays the specified window.
555  */
556 EAPI Ecore_X_Randr_Crtc *
557 ecore_x_randr_current_crtc_get(Ecore_X_Window window,
558                                int *num)
559 {
560    return ecore_x_randr_window_crtcs_get(window, num);
561 }
562
563 /*
564  * @brief get the CRTCs, which display a certain window
565  * @param window window the displaying crtcs shall be found for
566  * @param num the number of crtcs displaying the window
567  * @return Array of crtcs that display a certain window. @c NULL if no crtcs
568  * was found that displays the specified window.
569  * @since 1.2.0
570  */
571 EAPI Ecore_X_Randr_Crtc *
572 ecore_x_randr_window_crtcs_get(Ecore_X_Window window,
573                                int *num)
574 {
575 #ifdef ECORE_XRANDR
576    Ecore_X_Window root;
577    Eina_Rectangle w_geo, c_geo;
578    Ecore_X_Randr_Crtc *crtcs;
579    Ecore_X_Randr_Mode mode;
580    Ecore_X_Randr_Output *ret = NULL;
581    Window tw;
582    int ncrtcs, i, nret = 0, rx = 0, ry = 0;
583
584    if (_randr_version < RANDR_1_2) goto _ecore_x_randr_window_crtcs_get_fail;
585
586    ecore_x_window_geometry_get(window,
587                                &w_geo.x, &w_geo.y,
588                                &w_geo.w, &w_geo.h);
589
590    root = ecore_x_window_root_get(window);
591    crtcs = ecore_x_randr_crtcs_get(root, &ncrtcs);
592    if (!crtcs) goto _ecore_x_randr_window_crtcs_get_fail;
593
594    /* now get window RELATIVE to root window - thats what matters. */
595    XTranslateCoordinates(_ecore_x_disp, window, root, 0, 0, &rx, &ry, &tw);
596    w_geo.x = rx;
597    w_geo.y = ry;
598
599    ret = calloc(1, ncrtcs * sizeof(Ecore_X_Randr_Crtc));
600    if (!ret)
601      {
602         free(crtcs);
603         goto _ecore_x_randr_window_crtcs_get_fail;
604      }
605    for (i = 0, nret = 0; i < ncrtcs; i++)
606      {
607         /* if crtc is not enabled, don't bother about it any further */
608         mode = ecore_x_randr_crtc_mode_get(root, crtcs[i]);
609         if (mode == Ecore_X_Randr_None) continue;
610
611         ecore_x_randr_crtc_geometry_get(root, crtcs[i],
612                                         &c_geo.x, &c_geo.y,
613                                         &c_geo.w, &c_geo.h);
614         if (eina_rectangles_intersect(&w_geo, &c_geo))
615           {
616              ret[nret] = crtcs[i];
617              nret++;
618           }
619      }
620    free(crtcs);
621
622    if (num) *num = nret;
623    return ret;
624
625 _ecore_x_randr_window_crtcs_get_fail:
626 #endif
627    if (num) *num = 0;
628    return NULL;
629 }
630
631 EAPI Ecore_X_Randr_Output *
632 ecore_x_randr_outputs_get(Ecore_X_Window root,
633                           int *num)
634 {
635 #ifdef ECORE_XRANDR
636    RANDR_CHECK_1_2_RET(NULL);
637    XRRScreenResources *res = NULL;
638    Ecore_X_Randr_Output *ret = NULL;
639
640    if (num && root &&
641        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
642      {
643         if ((ret = malloc(sizeof(Ecore_X_Randr_Output) * res->noutput)))
644           {
645              memcpy(ret, res->outputs,
646                     (sizeof(Ecore_X_Randr_Output) * res->noutput));
647              if (num)
648                *num = res->noutput;
649           }
650
651         if (res)
652           XRRFreeScreenResources(res);
653      }
654
655    return ret;
656 #else
657    return NULL;
658 #endif
659 }
660
661 //Per Crtc
662 /*
663  * @brief get a CRTC's outputs.
664  * @param root the root window which's screen will be queried
665  * @param num number of outputs referenced by given CRTC
666  */
667 EAPI Ecore_X_Randr_Output *
668 ecore_x_randr_crtc_outputs_get(Ecore_X_Window root,
669                                Ecore_X_Randr_Crtc crtc,
670                                int *num)
671 {
672 #ifdef ECORE_XRANDR
673    RANDR_CHECK_1_2_RET(NULL);
674    XRRScreenResources *res = NULL;
675    Ecore_X_Randr_Output *ret = NULL;
676    XRRCrtcInfo *crtc_info = NULL;
677
678    if (_ecore_x_randr_crtc_validate(root,
679                                     crtc) &&
680        (res =
681           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
682                                                root)) &&
683        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
684      {
685         if ((ret = malloc(sizeof(Ecore_X_Randr_Output) * crtc_info->noutput)))
686           {
687              memcpy(ret, crtc_info->outputs,
688                     (sizeof(Ecore_X_Randr_Output) * crtc_info->noutput));
689              if (num)
690                *num = crtc_info->noutput;
691           }
692
693         if (crtc_info)
694           XRRFreeCrtcInfo(crtc_info);
695
696         if (res)
697           XRRFreeScreenResources(res);
698      }
699
700    return ret;
701 #else
702    return NULL;
703 #endif
704 }
705
706 /*
707  * @brief get a CRTC's possible outputs.
708  * @param root the root window which's screen will be queried
709  * @param num number of possible outputs referenced by given CRTC
710  */
711 EAPI Ecore_X_Randr_Output *
712 ecore_x_randr_crtc_possible_outputs_get(Ecore_X_Window root,
713                                         Ecore_X_Randr_Crtc crtc,
714                                         int *num)
715 {
716 #ifdef ECORE_XRANDR
717    RANDR_CHECK_1_2_RET(NULL);
718    XRRScreenResources *res = NULL;
719    Ecore_X_Randr_Output *ret = NULL;
720    XRRCrtcInfo *crtc_info = NULL;
721
722    if (_ecore_x_randr_crtc_validate(root,
723                                     crtc) &&
724        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
725      {
726         if ((crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
727           {
728              if ((ret =
729                     malloc(sizeof(Ecore_X_Randr_Output) * crtc_info->npossible)))
730                {
731                   memcpy(ret, crtc_info->possible,
732                          (sizeof(Ecore_X_Randr_Output) * crtc_info->npossible));
733                   if (num)
734                     *num = res->ncrtc;
735                }
736
737              XRRFreeCrtcInfo(crtc_info);
738           }
739
740         XRRFreeScreenResources(res);
741      }
742
743    return ret;
744 #else
745    return NULL;
746 #endif
747 }
748
749 EAPI void
750 ecore_x_randr_crtc_geometry_get(Ecore_X_Window root,
751                                 Ecore_X_Randr_Crtc crtc,
752                                 int *x,
753                                 int *y,
754                                 int *w,
755                                 int *h)
756 {
757 #ifdef ECORE_XRANDR
758    RANDR_CHECK_1_2_RET();
759    XRRScreenResources *res = NULL;
760    XRRCrtcInfo *crtc_info = NULL;
761
762    if (_ecore_x_randr_crtc_validate(root,
763                                     crtc) &&
764        (res =
765           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
766                                                root)) &&
767        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
768      {
769         if (x)
770           *x = crtc_info->x;
771
772         if (y)
773           *y = crtc_info->y;
774
775         if (w)
776           *w = crtc_info->width;
777
778         if (h)
779           *h = crtc_info->height;
780
781         XRRFreeCrtcInfo(crtc_info);
782         XRRFreeScreenResources(res);
783      }
784
785 #endif
786 }
787
788 /*
789  * @brief Sets the position of given CRTC within root window's screen.
790  *
791  * @param root The window's screen to be queried.
792  * @param crtc The CRTC which's position within the mentioned screen is to be
793  * altered.
794  * @param x Position on the x-axis (0 == left) of the screen. if x < 0 current
795  * value will be kept.
796  * @param y Position on the y-ayis (0 == top) of the screen. if y < 0, current
797  * value will be kept.
798  * @return @c EINA_TRUE if position could successfully be altered.
799  */
800 EAPI Eina_Bool
801 ecore_x_randr_crtc_pos_set(Ecore_X_Window root,
802                            Ecore_X_Randr_Crtc crtc,
803                            int x,
804                            int y)
805 {
806 #ifdef ECORE_XRANDR
807    RANDR_CHECK_1_2_RET(EINA_FALSE);
808    int w_c, h_c, w_new = 0, h_new = 0;
809    Eina_Rectangle crtc_geo;
810
811    ecore_x_randr_crtc_geometry_get(root,
812                                    crtc,
813                                    &crtc_geo.x,
814                                    &crtc_geo.y,
815                                    &crtc_geo.w,
816                                    &crtc_geo.h);
817    ecore_x_randr_screen_current_size_get(root, &w_c, &h_c, NULL, NULL);
818    if (x < 0)
819      x = crtc_geo.x;
820
821    if (y < 0)
822      y = crtc_geo.y;
823
824    if ((x + crtc_geo.w) > w_c)
825      w_new = x + crtc_geo.w;
826
827    if ((y + crtc_geo.h) > h_c)
828      h_new = y + crtc_geo.h;
829
830    if ((w_new != 0) || (h_new != 0))
831      if (!ecore_x_randr_screen_current_size_set(root, w_new, h_new, 0, 0))
832        return EINA_FALSE;
833
834    return ecore_x_randr_crtc_settings_set(root,
835                                           crtc,
836                                           NULL,
837                                           Ecore_X_Randr_Unset,
838                                           x,
839                                           y,
840                                           Ecore_X_Randr_Unset,
841                                           Ecore_X_Randr_Unset);
842 #else
843    return EINA_FALSE;
844 #endif
845 }
846
847 /**
848  * @brief Get the current set mode of a given CRTC
849  * @param root the window's screen to be queried
850  * @param crtc the CRTC which's should be queried
851  * @return currently set mode or - in case parameters are invalid -
852  * Ecore_X_Randr_Unset
853  */
854 EAPI Ecore_X_Randr_Mode
855 ecore_x_randr_crtc_mode_get(Ecore_X_Window root,
856                             Ecore_X_Randr_Crtc crtc)
857 {
858 #ifdef ECORE_XRANDR
859    RANDR_CHECK_1_2_RET(Ecore_X_Randr_Unset);
860    XRRScreenResources *res = NULL;
861    XRRCrtcInfo *crtc_info = NULL;
862    Ecore_X_Randr_Mode ret = Ecore_X_Randr_Unset;
863    if (_ecore_x_randr_root_validate(root) &&
864        _ecore_x_randr_crtc_validate(root,
865                                     crtc) &&
866        (res =
867           _ecore_x_randr_get_screen_resources(_ecore_x_disp,
868                                               root)) &&
869        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
870      {
871         ret = crtc_info->mode;
872         XRRFreeCrtcInfo(crtc_info);
873         XRRFreeScreenResources(res);
874      }
875
876    return ret;
877 #else
878    return Ecore_X_Randr_Unset;
879 #endif
880 }
881
882 /**
883  * @brief Sets a mode for a CRTC and the outputs attached to it.
884  *
885  * @param root The window's screen to be queried.
886  * @param crtc The CRTC which shall be set.
887  * @param outputs Array of outputs which have to be compatible with the mode.
888  * If @c NULL, CRTC will be disabled.
889  * @param noutputs Number of outputs in array to be used. Use
890  * Ecore_X_Randr_Unset (or @c -1) to use currently used outputs.
891  * @param mode XID of the mode to be set. If set to @c 0 the CRTC will be
892  * disabled. If set to @c -1 the call will fail.
893  * @return @c EINA_TRUE if mode setting was successful, @c EINA_FALSE
894  * otherwise.
895  */
896 EAPI Eina_Bool
897 ecore_x_randr_crtc_mode_set(Ecore_X_Window root,
898                             Ecore_X_Randr_Crtc crtc,
899                             Ecore_X_Randr_Output *outputs,
900                             int noutputs,
901                             Ecore_X_Randr_Mode mode)
902 {
903 #ifdef ECORE_XRANDR
904    RANDR_CHECK_1_2_RET(EINA_FALSE);
905
906    if (mode == Ecore_X_Randr_Unset)
907      return EINA_FALSE;
908
909    return ecore_x_randr_crtc_settings_set(root,
910                                           crtc,
911                                           outputs,
912                                           noutputs,
913                                           Ecore_X_Randr_Unset,
914                                           Ecore_X_Randr_Unset,
915                                           mode,
916                                           Ecore_X_Randr_Unset);
917 #else
918    return EINA_FALSE;
919 #endif
920 }
921
922 EAPI void
923 ecore_x_randr_crtc_size_get(Ecore_X_Window root,
924                             Ecore_X_Randr_Crtc crtc,
925                             int *w,
926                             int *h)
927 {
928 #ifdef ECORE_XRANDR
929    RANDR_CHECK_1_2_RET();
930    ecore_x_randr_crtc_geometry_get(root, crtc, NULL, NULL, w, h);
931 #endif
932 }
933
934 EAPI Ecore_X_Randr_Refresh_Rate
935 ecore_x_randr_crtc_refresh_rate_get(Ecore_X_Window root,
936                                     Ecore_X_Randr_Crtc crtc,
937                                     Ecore_X_Randr_Mode mode)
938 {
939 #ifdef ECORE_XRANDR
940    RANDR_CHECK_1_2_RET(0.0);
941    XRRScreenResources *res = NULL;
942    XRRCrtcInfo *crtc_info = NULL;
943    Ecore_X_Randr_Refresh_Rate ret = 0.0;
944    int i;
945
946    if (_ecore_x_randr_crtc_validate(root,
947                                     crtc) &&
948        (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
949      {
950         for (i = 0; i < res->nmode; i++)
951           if (res->modes[i].id == mode)
952             {
953                if (res->modes[i].hTotal && res->modes[i].vTotal)
954                  ret = ((double)res->modes[i].dotClock /
955                         ((double)res->modes[i].hTotal *
956                          (double)res->modes[i].vTotal));
957
958                break;
959             }
960      }
961
962    if (crtc_info)
963      XRRFreeCrtcInfo(crtc_info);
964
965    if (res)
966      XRRFreeScreenResources(res);
967
968    return ret;
969 #else
970    return 0.0;
971 #endif
972 }
973
974 EAPI Ecore_X_Randr_Orientation
975 ecore_x_randr_crtc_orientations_get(Ecore_X_Window root,
976                                     Ecore_X_Randr_Crtc crtc)
977 {
978 #ifdef ECORE_XRANDR
979    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
980    XRRCrtcInfo *crtc_info = NULL;
981    XRRScreenResources *res = NULL;
982    Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None;
983
984    if (_ecore_x_randr_crtc_validate(root,
985                                     crtc) &&
986        (res =
987           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
988                                                root)) &&
989        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
990      {
991         ret = crtc_info->rotations;
992      }
993    if (crtc_info)
994      XRRFreeCrtcInfo(crtc_info);
995
996    if (res)
997      XRRFreeScreenResources(res);
998
999    return ret;
1000 #else
1001    return Ecore_X_Randr_None;
1002 #endif
1003 }
1004
1005 EAPI Ecore_X_Randr_Orientation
1006 ecore_x_randr_crtc_orientation_get(Ecore_X_Window root,
1007                                    Ecore_X_Randr_Crtc crtc)
1008 {
1009 #ifdef ECORE_XRANDR
1010    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
1011    XRRCrtcInfo *crtc_info = NULL;
1012    XRRScreenResources *res = NULL;
1013    Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None;
1014
1015    if (_ecore_x_randr_crtc_validate(root,
1016                                     crtc) &&
1017        (res =
1018           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
1019                                                root)) &&
1020        (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1021      {
1022         ret = crtc_info->rotation;
1023      }
1024    if (crtc_info)
1025      XRRFreeCrtcInfo(crtc_info);
1026
1027    if (res)
1028      XRRFreeScreenResources(res);
1029
1030    return ret;
1031 #else
1032    return Ecore_X_Randr_None;
1033 #endif
1034 }
1035
1036 EAPI Eina_Bool
1037 ecore_x_randr_crtc_orientation_set(Ecore_X_Window root,
1038                                    Ecore_X_Randr_Crtc crtc,
1039                                    Ecore_X_Randr_Orientation orientation)
1040 {
1041 #ifdef ECORE_XRANDR
1042    RANDR_CHECK_1_2_RET(EINA_FALSE);
1043    Eina_Bool ret = EINA_FALSE;
1044
1045    if (orientation != Ecore_X_Randr_None)
1046      {
1047         ret = ecore_x_randr_crtc_settings_set(root,
1048                                               crtc,
1049                                               NULL,
1050                                               Ecore_X_Randr_Unset,
1051                                               Ecore_X_Randr_Unset,
1052                                               Ecore_X_Randr_Unset,
1053                                               Ecore_X_Randr_Unset,
1054                                               orientation);
1055      }
1056
1057    return ret;
1058 #else
1059    return EINA_FALSE;
1060 #endif
1061 }
1062
1063 EAPI void
1064 ecore_x_randr_crtc_pos_get(Ecore_X_Window root,
1065                            Ecore_X_Randr_Crtc crtc,
1066                            int *x,
1067                            int *y)
1068 {
1069 #ifdef ECORE_XRANDR
1070    RANDR_CHECK_1_2_RET();
1071
1072    ecore_x_randr_crtc_geometry_get(root, crtc, x, y, NULL, NULL);
1073 #endif
1074 }
1075
1076 EAPI Eina_Bool
1077 ecore_x_randr_crtc_clone_set(Ecore_X_Window root,
1078                              Ecore_X_Randr_Crtc original,
1079                              Ecore_X_Randr_Crtc clon)
1080 {
1081 #ifdef ECORE_XRANDR
1082    RANDR_CHECK_1_2_RET(EINA_FALSE);
1083
1084    XRRScreenResources *res = NULL;
1085    XRRCrtcInfo *clone_crtc_info = NULL;
1086    Ecore_X_Randr_Mode original_mode = Ecore_X_Randr_None;
1087    Ecore_X_Randr_Orientation original_orientation = Ecore_X_Randr_None;
1088    Eina_Bool ret = EINA_FALSE;
1089    int x, y;
1090
1091    if (_ecore_x_randr_root_validate(root) &&
1092        _ecore_x_randr_crtc_validate(root,
1093                                     original) &&
1094        _ecore_x_randr_crtc_validate(root,
1095                                     clon) &&
1096        (res =
1097           _ecore_x_randr_get_screen_resources (_ecore_x_disp,
1098                                                root)) &&
1099        (clone_crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, clon)))
1100      {
1101         ecore_x_randr_crtc_geometry_get(root, original, &x, &y, NULL, NULL);
1102         original_mode = ecore_x_randr_crtc_mode_get(root, original);
1103         original_orientation = ecore_x_randr_crtc_orientation_get(root,
1104                                                                   original);
1105         ret = ecore_x_randr_crtc_settings_set(root,
1106                                               clon,
1107                                               NULL,
1108                                               Ecore_X_Randr_Unset,
1109                                               x,
1110                                               y,
1111                                               original_mode,
1112                                               original_orientation);
1113         XRRFreeCrtcInfo(clone_crtc_info);
1114         XRRFreeScreenResources(res);
1115      }
1116
1117    return ret;
1118 #else
1119    return EINA_FALSE;
1120 #endif
1121 }
1122
1123 /**
1124  * @brief Sets the demanded parameters for a given CRTC. Note that the CRTC is
1125  * auto enabled in it's preferred mode, when it was disabled before.
1126  *
1127  * @param root The root window which's default display will be queried.
1128  * @param crtc The CRTC which's configuration should be altered.
1129  * @param outputs An array of outputs, that should display this CRTC's content.
1130  * @param noutputs Number of outputs in the array of outputs. If set to
1131  * Ecore_X_Randr_Unset, current outputs and number of outputs will be used.
1132  * If set to Ecore_X_Randr_None, CRTC will be disabled.
1133  * @param x New x coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current x
1134  * corrdinate will be assumed.
1135  * @param y New y coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current y
1136  * corrdinate will be assumed.
1137  * @param mode The new mode to be set. If Ecore_X_Randr_None is passed, the
1138  * CRTC will be disabled. If Ecore_X_Randr_Unset is passed, the current mode is
1139  * assumed.
1140  * @param orientation The new orientation to be set. If Ecore_X_Randr_Unset is
1141  * used, the current mode is assumed.
1142  * @return @c EINA_TRUE if the configuration alteration was successful,
1143  * @c EINA_FALSE otherwise.
1144  */
1145 EAPI Eina_Bool
1146 ecore_x_randr_crtc_settings_set(Ecore_X_Window root,
1147                                 Ecore_X_Randr_Crtc crtc,
1148                                 Ecore_X_Randr_Output *outputs,
1149                                 int noutputs,
1150                                 int x,
1151                                 int y,
1152                                 Ecore_X_Randr_Mode mode,
1153                                 Ecore_X_Randr_Orientation orientation)
1154 {
1155 #ifdef ECORE_XRANDR
1156    RANDR_CHECK_1_2_RET(EINA_FALSE);
1157    XRRScreenResources *res = NULL;
1158    XRRCrtcInfo *crtc_info = NULL;
1159    Eina_Bool ret = EINA_FALSE;
1160
1161    if (_ecore_x_randr_crtc_validate(root,
1162                                     crtc) &&
1163        (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1164      {
1165         if ((crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
1166           {
1167              if ((mode == Ecore_X_Randr_None) ||
1168                  (noutputs == Ecore_X_Randr_None))
1169                {
1170                   outputs = NULL;
1171                   noutputs = 0;
1172                }
1173              else if (noutputs == (int)Ecore_X_Randr_Unset)
1174                {
1175                   outputs = (Ecore_X_Randr_Output *)crtc_info->outputs;
1176                   noutputs = crtc_info->noutput;
1177                }
1178
1179              if (mode == Ecore_X_Randr_Unset)
1180                mode = crtc_info->mode;
1181
1182              if (x < 0)
1183                x = crtc_info->x;
1184
1185              if (y < 0)
1186                y = crtc_info->y;
1187
1188              if (orientation == Ecore_X_Randr_Unset)
1189                orientation = crtc_info->rotation;
1190
1191              if (!XRRSetCrtcConfig(_ecore_x_disp, res, crtc, CurrentTime,
1192                                    x, y, mode, orientation, (RROutput *)outputs,
1193                                    noutputs))
1194                ret = EINA_TRUE;
1195
1196              XRRFreeCrtcInfo(crtc_info);
1197           }
1198
1199         XRRFreeScreenResources(res);
1200      }
1201
1202    return ret;
1203 #else
1204    return EINA_FALSE;
1205 #endif
1206 }
1207
1208 /**
1209  * @brief Sets a CRTC relative to another one.
1210  *
1211  * @param root The root window which's default display will be set.
1212  * @param crtc_r1 The CRTC to be positioned.
1213  * @param crtc_r2 The CRTC the position should be relative to.
1214  * @param policy The relation between the crtcs.
1215  * @param alignment In case CRTCs size differ, aligns CRTC1 accordingly at
1216  * CRTC2's borders.
1217  * @return @c EINA_TRUE if crtc could be successfully positioned, @c EINA_FALSE
1218  * if repositioning failed or if position of new crtc would be out of given
1219  * screen's min/max bounds.
1220  */
1221 EAPI Eina_Bool
1222 ecore_x_randr_crtc_pos_relative_set(Ecore_X_Window root,
1223                                     Ecore_X_Randr_Crtc crtc_r1,
1224                                     Ecore_X_Randr_Crtc crtc_r2,
1225                                     Ecore_X_Randr_Output_Policy policy,
1226                                     Ecore_X_Randr_Relative_Alignment alignment)
1227 {
1228 #ifdef ECORE_XRANDR
1229    RANDR_CHECK_1_2_RET(EINA_FALSE);
1230
1231    Eina_Rectangle r1_geo, r2_geo;
1232    int w_max, h_max, cw, ch, x_n = Ecore_X_Randr_Unset, y_n =
1233      Ecore_X_Randr_Unset;
1234    /*
1235       int r1_noutputs, r2_noutputs, r1_nmodes, i, j, outputs_mode_found, mode_w, mode_h;
1236       Ecore_X_Randr_Output *r1_outputs, *r2_outputs, *r2_r1_outputs;
1237       Ecore_X_Randr_Mode *r1_modes, r2_mode, r1_mode;
1238       Eina_Bool ret;
1239     */
1240
1241    if ((ecore_x_randr_crtc_mode_get(root, crtc_r1) == Ecore_X_Randr_None)
1242        || (ecore_x_randr_crtc_mode_get(root, crtc_r2) == Ecore_X_Randr_None))
1243      return EINA_FALSE;
1244
1245    if (!_ecore_x_randr_crtc_validate(root, crtc_r1) ||
1246        (!(crtc_r1 != crtc_r2) &&
1247         !_ecore_x_randr_crtc_validate(root, crtc_r2)))
1248      return EINA_FALSE;
1249
1250    ecore_x_randr_crtc_geometry_get(root,
1251                                    crtc_r1,
1252                                    &r1_geo.x,
1253                                    &r1_geo.y,
1254                                    &r1_geo.w,
1255                                    &r1_geo.h);
1256    ecore_x_randr_crtc_geometry_get(root,
1257                                    crtc_r2,
1258                                    &r2_geo.x,
1259                                    &r2_geo.y,
1260                                    &r2_geo.w,
1261                                    &r2_geo.h);
1262    ecore_x_randr_screen_size_range_get(root, NULL, NULL, &w_max, &h_max);
1263    ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
1264
1265    switch (policy)
1266      {
1267       case ECORE_X_RANDR_OUTPUT_POLICY_RIGHT:
1268         //set r1 right of r2
1269         x_n = r2_geo.x + r2_geo.w;
1270
1271         switch (alignment)
1272           {
1273            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1274              y_n = Ecore_X_Randr_Unset;
1275              break;
1276
1277            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1278              y_n =
1279                ((int)(((double)r2_geo.h /
1280                        2.0) + (double)r2_geo.y - ((double)r1_geo.h / 2.0)));
1281              break;
1282
1283            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1284              y_n = ((int)((double)ch / 2.0) - ((double)r1_geo.h / 2.0));
1285              break;
1286           }
1287         break;
1288
1289       case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
1290         //set r1 left of r2
1291         x_n = r2_geo.x - r1_geo.w;
1292
1293         switch (alignment)
1294           {
1295            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1296              y_n = Ecore_X_Randr_Unset;
1297              break;
1298
1299            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1300              y_n =
1301                ((int)(((double)r2_geo.h /
1302                        2.0) + r2_geo.y - ((double)r1_geo.h / 2.0)));
1303              break;
1304
1305            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1306              y_n = ((int)(((double)ch / 2.0) - ((double)r1_geo.h / 2.0)));
1307              break;
1308           }
1309         break;
1310
1311       case ECORE_X_RANDR_OUTPUT_POLICY_BELOW:
1312         //set r1 below r2
1313         y_n = r2_geo.y + r2_geo.h;
1314
1315         switch (alignment)
1316           {
1317            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1318              x_n = Ecore_X_Randr_Unset;
1319              break;
1320
1321            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1322              x_n =
1323                ((int)((((double)r2_geo.x +
1324                         (double)r2_geo.w) / 2.0) - ((double)r1_geo.w / 2.0)));
1325              break;
1326
1327            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1328              x_n = ((int)((double)cw / 2.0));
1329              break;
1330           }
1331         break;
1332
1333       case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
1334         y_n = r2_geo.y - r1_geo.h;
1335
1336         //set r1 above r2
1337         switch (alignment)
1338           {
1339            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
1340              x_n = Ecore_X_Randr_Unset;
1341              break;
1342
1343            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
1344              x_n =
1345                ((int)((((double)r2_geo.x +
1346                         (double)r2_geo.w) / 2.0) - ((double)r1_geo.w / 2.0)));
1347              break;
1348
1349            case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
1350              x_n = ((int)((double)cw / 2.0));
1351              break;
1352           }
1353         break;
1354
1355       case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
1356         return ecore_x_randr_crtc_pos_set(root, crtc_r1, r2_geo.x, r2_geo.y);
1357
1358       /* entire cloning (including modesetting)
1359          //all outputs of crtc1 capable of crtc2's current mode?
1360          r2_mode = ecore_x_randr_crtc_mode_get(root, crtc_r2);
1361          if (!(r1_outputs =
1362                ecore_x_randr_crtc_outputs_get(root, crtc_r1,
1363                                               &r1_noutputs)) ||
1364           (r1_noutputs == 0))
1365          return EINA_FALSE;
1366
1367          for (i = 0, outputs_mode_found = 0; i < r1_noutputs; i++)
1368          {
1369            if (!(r1_modes =
1370                     ecore_x_randr_output_modes_get(root, r1_outputs[i],
1371                                                    &r1_nmodes, NULL)))
1372              {
1373                 free(r1_outputs);
1374                 return EINA_FALSE;
1375              }
1376
1377            for (j = 0; j < r1_nmodes; j++)
1378              {
1379                 ecore_x_randr_mode_size_get(root,
1380                                             r1_modes[j],
1381                                             &mode_w,
1382                                             &mode_h);
1383                 if ((mode_w == r2_geo.w) && (mode_h == r2_geo.h))
1384                   {
1385                      r1_mode = r1_modes[j];
1386          ++outputs_mode_found;
1387                      free(r1_modes);
1388                      r1_modes = NULL;
1389                      break;
1390                   }
1391              }
1392            if (r1_modes)
1393                      free(r1_modes);
1394
1395            if (outputs_mode_found <= i)
1396              {
1397                 //an output doesn't support the set mode, cancel!
1398                      free(r1_outputs);
1399                 return EINA_FALSE;
1400              }
1401          }
1402                      free (r1_outputs);
1403          //CRTC 1's outputs support a mode of same geometry as CRTC 2.
1404          ret =
1405          (ecore_x_randr_crtc_mode_set(root, crtc_r1, Ecore_X_Randr_None,
1406                                       Ecore_X_Randr_None,
1407                                       r1_mode) &&
1408           ecore_x_randr_crtc_pos_set(root, crtc_r1, r2_geo.x, r2_geo.y));
1409          return ret;
1410        */
1411
1412       /* entire cloning on same CRTC
1413          //all outputs of crtc1 capable of crtc2's current mode?
1414          r2_mode = ecore_x_randr_crtc_mode_get(root, crtc_r2);
1415          if (!(r1_outputs =
1416                ecore_x_randr_crtc_outputs_get(root, crtc_r1,
1417                                               &r1_noutputs)) ||
1418           (r1_noutputs == 0))
1419          return EINA_FALSE;
1420
1421          for (i = 0, outputs_mode_found = 0; i < r1_noutputs; i++)
1422          {
1423            if (!(r1_modes =
1424                     ecore_x_randr_output_modes_get(root, r1_outputs[i],
1425                                                    &r1_nmodes, NULL)))
1426              {
1427                      free(r1_outputs);
1428                 return EINA_FALSE;
1429              }
1430
1431            for (j = 0; j < r1_nmodes; j++)
1432              {
1433                 if (r1_modes[j] == r2_mode)
1434                   {
1435          ++outputs_mode_found;
1436                      free(r1_modes);
1437                      r1_modes = NULL;
1438                      break;
1439                   }
1440              }
1441            if (r1_modes)
1442                      free(r1_modes);
1443
1444            if (outputs_mode_found <= i)
1445              {
1446                 //an output doesn't support the set mode, cancel!
1447                      free(r1_outputs);
1448                 return EINA_FALSE;
1449              }
1450          }
1451          //check whether crtc r2 can use all outputs of r1.
1452          if (!(r2_outputs =
1453                ecore_x_randr_crtc_possible_outputs_get(root, crtc_r2,
1454                                                        &r2_noutputs)) ||
1455           (r2_noutputs == 0))
1456          {
1457                 free(r1_outputs);
1458            return EINA_FALSE;
1459          }
1460
1461          for (i = 0; i < r1_noutputs; i++)
1462          {
1463            for (j = 0; j < r2_noutputs; )
1464              {
1465                 if (r1_outputs[i] == r2_outputs[j])
1466                    break;
1467
1468                 j++;
1469              }
1470            if (j == r2_noutputs)
1471              {
1472                 //didn't find the output!
1473                 free (r1_outputs);
1474                 free (r2_outputs);
1475                 return EINA_FALSE;
1476              }
1477          }
1478
1479          //apparently crtc2 supports all outputs of r1
1480          //TODO: check with the compatible list of outputs (property in RR1.3)
1481          r2_r1_outputs =
1482          malloc(sizeof(Ecore_X_Randr_Output) * (r1_noutputs + r2_noutputs));
1483          for (i = 0; i < r1_noutputs; i++)
1484          {
1485            r2_r1_outputs[i] = r1_outputs[i];
1486          }
1487          free(r1_outputs);
1488          for (; i < r2_noutputs; i++)
1489          {
1490            r2_r1_outputs[i] = r2_outputs[i];
1491          }
1492          free(r2_outputs);
1493          ret =
1494          ecore_x_randr_crtc_mode_set(root, crtc_r2, r2_r1_outputs,
1495                                      (r1_noutputs + r1_noutputs), r2_mode);
1496          free (r2_r1_outputs);
1497          return ret;
1498        */
1499       case ECORE_X_RANDR_OUTPUT_POLICY_NONE:
1500         break;
1501       default:
1502         return EINA_FALSE;
1503      }
1504    if ((x_n == r1_geo.x) && (y_n == r1_geo.x))
1505      return EINA_TRUE;
1506
1507    //out of possible bounds?
1508    if (((y_n + r1_geo.h) > h_max) || ((x_n + r1_geo.w) > w_max))
1509      return EINA_FALSE;
1510
1511    return ecore_x_randr_crtc_pos_set(root, crtc_r1, x_n, y_n);
1512 #else
1513    return EINA_FALSE;
1514 #endif
1515 }
1516
1517 /*
1518  * @brief Add given mode to given output.
1519  *
1520  * @param output The output the mode is added to.
1521  * @param mode The mode added to the output.
1522  * @return @c EINA_FALSE if output or mode equal Ecore_X_Randr_None, else
1523  * @c EINA_TRUE.
1524  * Additionally, if xcb backend is used, the success of the addition is
1525  * reported back directly.
1526  * @since 1.2.0
1527  */
1528 EAPI Eina_Bool
1529 ecore_x_randr_output_mode_add(Ecore_X_Randr_Output output,
1530                               Ecore_X_Randr_Mode mode)
1531 {
1532 #ifdef ECORE_XRANDR
1533    RANDR_CHECK_1_2_RET(EINA_FALSE);
1534
1535    if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None))
1536      return EINA_FALSE;
1537
1538    XRRAddOutputMode(_ecore_x_disp, output, mode);
1539    return EINA_TRUE;
1540 #else
1541    return EINA_FALSE;
1542 #endif
1543 }
1544
1545 /*
1546  * @brief delete given mode from given output
1547  * @param output the output the mode is removed from
1548  * @param mode the mode removed from the output
1549  * @since 1.2.0
1550  */
1551 EAPI void
1552 ecore_x_randr_output_mode_del(Ecore_X_Randr_Output output,
1553                               Ecore_X_Randr_Mode mode)
1554 {
1555 #ifdef ECORE_XRANDR
1556    RANDR_CHECK_1_2_RET();
1557
1558    if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None))
1559      return;
1560
1561    XRRDeleteOutputMode(_ecore_x_disp, output, mode);
1562 #else
1563    return;
1564 #endif
1565 }
1566
1567 EAPI Ecore_X_Randr_Mode *
1568 ecore_x_randr_output_modes_get(Ecore_X_Window root,
1569                                Ecore_X_Randr_Output output,
1570                                int *num,
1571                                int *npreferred)
1572 {
1573 #ifdef ECORE_XRANDR
1574    RANDR_CHECK_1_2_RET(NULL);
1575    XRRScreenResources *res = NULL;
1576    XRROutputInfo *output_info = NULL;
1577    Ecore_X_Randr_Mode *modes = NULL;
1578
1579    if ((output != Ecore_X_Randr_None)
1580        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1581        && (output_info =
1582              XRRGetOutputInfo(_ecore_x_disp, res, (RROutput)output)))
1583      {
1584         if ((modes = malloc(sizeof(Ecore_X_Randr_Mode) * output_info->nmode)))
1585           {
1586              memcpy(modes, output_info->modes,
1587                     (sizeof(Ecore_X_Randr_Mode) * output_info->nmode));
1588              if (num)
1589                *num = output_info->nmode;
1590
1591              if (npreferred)
1592                *npreferred = output_info->npreferred;
1593           }
1594      }
1595
1596    if (output_info)
1597      XRRFreeOutputInfo(output_info);
1598
1599    if (res)
1600      XRRFreeScreenResources(res);
1601
1602    return modes;
1603 #else
1604    return NULL;
1605 #endif
1606 }
1607
1608 EAPI Ecore_X_Randr_Crtc *
1609 ecore_x_randr_output_possible_crtcs_get(Ecore_X_Window root,
1610                                         Ecore_X_Randr_Output output,
1611                                         int *num)
1612 {
1613 #ifdef ECORE_XRANDR
1614    RANDR_CHECK_1_2_RET(NULL);
1615    XRRScreenResources *res = NULL;
1616    XRROutputInfo *output_info = NULL;
1617    Ecore_X_Randr_Crtc *crtcs = NULL;
1618
1619    if ((output != Ecore_X_Randr_None))
1620      {
1621         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1622           {
1623              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1624                {
1625                   if ((crtcs = malloc(sizeof(Ecore_X_Randr_Crtc) * output_info->ncrtc)))
1626                     {
1627                        memcpy(crtcs, output_info->crtcs, (sizeof(Ecore_X_Randr_Crtc) * output_info->ncrtc));
1628                        if (num) *num = output_info->ncrtc;
1629                     }
1630                   XRRFreeOutputInfo(output_info);
1631                }
1632              XRRFreeScreenResources(res);
1633           }
1634      }
1635    return crtcs;
1636 #else
1637    return Ecore_X_Randr_None;
1638 #endif
1639 }
1640
1641 /**
1642  * @brief gets the the outputs which might be used simultenously on the same
1643  * CRTC.
1644  * @param root window that this information should be queried for.
1645  * @param output the output which's clones we concern
1646  * @param num number of possible clones
1647  */
1648 EAPI Ecore_X_Randr_Output *
1649 ecore_x_randr_output_clones_get(Ecore_X_Window root,
1650                                 Ecore_X_Randr_Output output,
1651                                 int *num)
1652 {
1653 #ifdef ECORE_XRANDR
1654    RANDR_CHECK_1_2_RET(NULL);
1655    XRRScreenResources *res = NULL;
1656    XRROutputInfo *output_info = NULL;
1657    Ecore_X_Randr_Output *outputs = NULL;
1658
1659    if ((output != Ecore_X_Randr_None))
1660      {
1661         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1662           {
1663              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1664                {
1665                   if ((outputs = malloc(sizeof(Ecore_X_Randr_Output) * output_info->nclone)))
1666                     {
1667                        memcpy(outputs, output_info->clones, (sizeof(Ecore_X_Randr_Output) * output_info->nclone));
1668                        if (num) *num = output_info->nclone;
1669                     }
1670                   XRRFreeOutputInfo(output_info);
1671                }
1672              XRRFreeScreenResources(res);
1673           }
1674      }
1675    return outputs;
1676 #else
1677    return Ecore_X_Randr_None;
1678 #endif
1679 }
1680
1681 EAPI Ecore_X_Randr_Crtc
1682 ecore_x_randr_output_crtc_get(Ecore_X_Window root,
1683                               Ecore_X_Randr_Output output)
1684 {
1685 #ifdef ECORE_XRANDR
1686    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
1687    XRRScreenResources *res = NULL;
1688    XRROutputInfo *output_info = NULL;
1689    Ecore_X_Randr_Crtc ret = Ecore_X_Randr_None;
1690
1691    if ((output != Ecore_X_Randr_None))
1692      {
1693         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1694           {
1695              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1696                {
1697                   ret = output_info->crtc;
1698                   XRRFreeOutputInfo(output_info);
1699                }
1700              XRRFreeScreenResources(res);
1701           }
1702      }
1703
1704    return ret;
1705 #else
1706    return Ecore_X_Randr_None;
1707 #endif
1708 }
1709
1710 /**
1711  * @brief gets the given output's name as reported by X
1712  * @param root the window which's screen will be queried
1713  * @param output The output for which the name will be reported.
1714  * @param len length of returned c-string.
1715  * @return name of the output as reported by X
1716  */
1717 EAPI char *
1718 ecore_x_randr_output_name_get(Ecore_X_Window root,
1719                               Ecore_X_Randr_Output output,
1720                               int *len)
1721 {
1722 #ifdef ECORE_XRANDR
1723    RANDR_CHECK_1_2_RET(NULL);
1724    XRRScreenResources *res = NULL;
1725    XRROutputInfo *output_info = NULL;
1726    char *ret = NULL;
1727
1728    if ((output != Ecore_X_Randr_None)
1729        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1730        && (output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1731      {
1732         /*
1733          * Actually the below command is correct, but due to a bug in libXrandr
1734          * it doesn't work. Therefore we stick with strlen().
1735          * Replace the line below with the following once this bug is
1736          * fixed within libXrandr.
1737          *
1738          *    *len = output_info->nameLen;
1739          *
1740          */
1741         if ((ret = strdup(output_info->name)) && len)
1742           *len = strlen(ret);
1743
1744         XRRFreeOutputInfo(output_info);
1745      }
1746
1747    if (res)
1748      XRRFreeScreenResources(res);
1749
1750    return ret;
1751 #else
1752    return NULL;
1753 #endif
1754 }
1755
1756 /**
1757  * @brief gets the width and hight of a given mode
1758  * @param mode the mode which's size is to be looked up
1759  * @param w width of given mode in px
1760  * @param h height of given mode in px
1761  */
1762 EAPI void
1763 ecore_x_randr_mode_size_get(Ecore_X_Window root,
1764                             Ecore_X_Randr_Mode mode,
1765                             int *w,
1766                             int *h)
1767 {
1768 #ifdef ECORE_XRANDR
1769    RANDR_CHECK_1_2_RET();
1770    XRRScreenResources *res = NULL;
1771    int i;
1772
1773    if ((mode != Ecore_X_Randr_None)
1774        && (w || h)
1775        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1776      {
1777         for (i = 0; i < res->nmode; i++)
1778           {
1779              if (res->modes[i].id == mode)
1780                {
1781                   if (w)
1782                     *w = res->modes[i].width;
1783
1784                   if (h)
1785                     *h = res->modes[i].height;
1786
1787                   break;
1788                }
1789           }
1790      }
1791
1792    if (res)
1793      XRRFreeScreenResources(res);
1794
1795 #endif
1796 }
1797
1798 /**
1799  * @brief gets the EDID information of an attached output if available.
1800  * Note that this information is not to be compared using ordinary string
1801  * comparison functions, since it includes 0-bytes.
1802  * @param root window this information should be queried from
1803  * @param output the XID of the output
1804  * @param length length of the byte-array. If NULL, request will fail.
1805  */
1806 EAPI unsigned char *
1807 ecore_x_randr_output_edid_get(Ecore_X_Window root,
1808                               Ecore_X_Randr_Output output,
1809                               unsigned long *length)
1810 {
1811 #ifdef ECORE_XRANDR
1812    RANDR_CHECK_1_2_RET(NULL);
1813    Atom name = XInternAtom (_ecore_x_disp, RANDR_PROPERTY_EDID, False);
1814    unsigned char *prop_data, *ret = NULL;
1815    int actual_format;
1816    unsigned long nitems, bytes_after;
1817    Atom actual_type;
1818
1819    if (!length || !_ecore_x_randr_output_validate(root, output))
1820      return NULL;
1821
1822    if (XRRGetOutputProperty (_ecore_x_disp, output, name,
1823                              0, 100, False, False,
1824                              AnyPropertyType,
1825                              &actual_type, &actual_format,
1826                              &nitems, &bytes_after, &prop_data) == Success)
1827      {
1828         if (actual_type == XA_INTEGER && actual_format == 8)
1829           {
1830              if ((ret = malloc(nitems * sizeof(unsigned char))))
1831                {
1832                   if (length &&
1833                       (memcpy(ret, prop_data, (nitems * sizeof(unsigned char)))))
1834                     *length = nitems;
1835
1836                   return ret;
1837                }
1838           }
1839      }
1840
1841    return NULL;
1842 #else
1843    return NULL;
1844 #endif
1845 }
1846
1847 EAPI Ecore_X_Randr_Connection_Status
1848 ecore_x_randr_output_connection_status_get(Ecore_X_Window root,
1849                                            Ecore_X_Randr_Output output)
1850 {
1851 #ifdef ECORE_XRANDR
1852    RANDR_CHECK_1_2_RET(ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN);
1853    XRRScreenResources *res = NULL;
1854    XRROutputInfo *output_info = NULL;
1855    Ecore_X_Randr_Connection_Status ret =
1856      ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
1857
1858    if ((output != Ecore_X_Randr_None)
1859        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1860        && (output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1861      {
1862         ret = output_info->connection;
1863      }
1864
1865    if (output_info)
1866      XRRFreeOutputInfo(output_info);
1867
1868    if (res)
1869      XRRFreeScreenResources(res);
1870
1871    return ret;
1872 #else
1873    return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
1874 #endif
1875 }
1876
1877 EAPI void
1878 ecore_x_randr_output_size_mm_get(Ecore_X_Window root,
1879                                  Ecore_X_Randr_Output output,
1880                                  int *w_mm,
1881                                  int *h_mm)
1882 {
1883 #ifdef ECORE_XRANDR
1884    RANDR_CHECK_1_2_RET();
1885    XRRScreenResources *res = NULL;
1886    XRROutputInfo *output_info = NULL;
1887
1888    if ((output != Ecore_X_Randr_None)
1889        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1890      {
1891         if ((output_info =
1892                XRRGetOutputInfo(_ecore_x_disp, res, (RROutput)output)))
1893           {
1894              if (w_mm)
1895                *w_mm = output_info->mm_width;
1896
1897              if (h_mm)
1898                *h_mm = output_info->mm_height;
1899
1900              XRRFreeOutputInfo(output_info);
1901           }
1902
1903         XRRFreeScreenResources(res);
1904      }
1905
1906 #endif
1907 }
1908
1909 EAPI Eina_Bool
1910 ecore_x_randr_move_all_crtcs_but(Ecore_X_Window root,
1911                                  const Ecore_X_Randr_Crtc *not_moved,
1912                                  int nnot_moved,
1913                                  int dx,
1914                                  int dy)
1915 {
1916 #ifdef ECORE_XRANDR
1917    Ecore_X_Randr_Crtc *crtcs_to_be_moved = NULL;
1918    XRRScreenResources *res = NULL;
1919    int i, j, k, n;
1920    Eina_Bool ret;
1921
1922    if ((nnot_moved <= 0) || (!not_moved)
1923        || !_ecore_x_randr_root_validate(root)
1924        || !(res =
1925               _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
1926      return EINA_FALSE;
1927
1928    n = (res->ncrtc - nnot_moved);
1929    if ((crtcs_to_be_moved = malloc(sizeof(Ecore_X_Randr_Crtc) * n)))
1930      {
1931         for (i = 0, k = 0; (i < res->ncrtc) && (k < n); i++)
1932           {
1933              for (j = 0; j < nnot_moved; j++)
1934                {
1935                   if (res->crtcs[i] == not_moved[j])
1936                     break;
1937                }
1938              if (j == nnot_moved)
1939                //crtcs[i] is not in the 'not to move'-list
1940                crtcs_to_be_moved[k++] = res->crtcs[i];
1941           }
1942      }
1943
1944    XRRFreeScreenResources(res);
1945    ret = ecore_x_randr_move_crtcs(root, crtcs_to_be_moved, n, dx, dy);
1946    free(crtcs_to_be_moved);
1947    return ret;
1948 #else
1949    return EINA_FALSE;
1950 #endif
1951 }
1952
1953 /*
1954  * @brief Move given CRTCs belonging to the given root window's screen dx/dy
1955  * pixels relative to their current position. The screen size will be
1956  * automatically adjusted if necessary and possible.
1957  *
1958  * @param root Window which's screen's resources are used.
1959  * @param crtcs List of CRTCs to be moved.
1960  * @param ncrtc Number of CRTCs in array.
1961  * @param dx Amount of pixels the CRTCs should be moved in x direction.
1962  * @param dy Amount of pixels the CRTCs should be moved in y direction.
1963  * @return @c EINA_TRUE if all crtcs could be moved successfully.
1964  */
1965 EAPI Eina_Bool
1966 ecore_x_randr_move_crtcs(Ecore_X_Window root,
1967                          const Ecore_X_Randr_Crtc *crtcs,
1968                          int ncrtc,
1969                          int dx,
1970                          int dy)
1971 {
1972 #ifdef ECORE_XRANDR
1973    RANDR_CHECK_1_2_RET(EINA_FALSE);
1974    XRRScreenResources *res = NULL;
1975    XRRCrtcInfo **crtc_info = NULL;
1976    Eina_Bool ret = EINA_TRUE;
1977    int i, cw, ch, w_max, h_max, nw, nh;
1978
1979    crtc_info = alloca(sizeof(XRRCrtcInfo *) * ncrtc);
1980    memset(crtc_info, 0, sizeof(XRRCrtcInfo *) * ncrtc);
1981    if (_ecore_x_randr_root_validate(root)
1982        && (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
1983      {
1984         ecore_x_randr_screen_size_range_get(root, NULL, NULL, &w_max, &h_max);
1985         ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
1986         nw = cw;
1987         nh = ch;
1988
1989         for (i = 0;
1990              (i < ncrtc) &&
1991              (crtc_info[i] = XRRGetCrtcInfo(_ecore_x_disp, res, crtcs[i]));
1992              i++)
1993           {
1994              if (((crtc_info[i]->x + dx) < 0) ||
1995                  ((int)(crtc_info[i]->x + crtc_info[i]->width + dx) > w_max)
1996                  || ((crtc_info[i]->y + dy) < 0) ||
1997                  ((int)(crtc_info[i]->y + crtc_info[i]->height + dy) > h_max)
1998                  )
1999                goto _ecore_x_randr_move_crtcs_fail_free_crtc_info;
2000
2001              nw = MAX((int)(crtc_info[i]->x + crtc_info[i]->width + dx), nw);
2002              nh = MAX((int)(crtc_info[i]->y + crtc_info[i]->height + dy), nh);
2003           }
2004         //not out of bounds
2005
2006         //resize if necessary
2007         if (!(((nw > cw) ||
2008                (nh > ch)) ||
2009               ecore_x_randr_screen_current_size_set(root, nw, nh,
2010                                                     Ecore_X_Randr_Unset,
2011                                                     Ecore_X_Randr_Unset)))
2012           goto _ecore_x_randr_move_crtcs_fail_free_crtc_info;
2013
2014         //actually move all the crtcs, keep their rotation and mode.
2015         for (i = 0; (i < ncrtc) && crtc_info[i]; i++)
2016           {
2017              if ((crtc_info[i]) &&
2018                  (!ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL,
2019                                                    Ecore_X_Randr_Unset,
2020                                                    (crtc_info[i]->x + dx),
2021                                                    (crtc_info[i]->y + dy),
2022                                                    crtc_info[i]->mode,
2023                                                    crtc_info[i]->rotation)))
2024                {
2025                   ret = EINA_FALSE;
2026                   break;
2027                }
2028           }
2029         if (i < ncrtc)
2030           {
2031              //something went wrong, let's try to move the already moved crtcs
2032              //back.
2033              while ((i--) >= 0)
2034                {
2035                   if (crtc_info[i])
2036                     ecore_x_randr_crtc_settings_set(root,
2037                                                     crtcs[i],
2038                                                     NULL,
2039                                                     Ecore_X_Randr_Unset,
2040                                                     (crtc_info[i]->x - dx),
2041                                                     (crtc_info[i]->y - dy),
2042                                                     crtc_info[i]->mode,
2043                                                     crtc_info[i]->rotation);
2044                }
2045           }
2046
2047         for (i = 0; i < ncrtc; i++)
2048           {
2049              if (crtc_info[i]) XRRFreeCrtcInfo(crtc_info[i]);
2050           }
2051      }
2052
2053    XRRFreeScreenResources(res);
2054
2055    return ret;
2056 _ecore_x_randr_move_crtcs_fail_free_crtc_info:
2057    while (i-- > 0)
2058      XRRFreeCrtcInfo(crtc_info[i]);
2059    XRRFreeScreenResources(res);
2060    return EINA_FALSE;
2061 #else
2062    return EINA_FALSE;
2063 #endif
2064 }
2065
2066 /**
2067  * @brief removes unused screen space. The most upper left CRTC is set to 0x0
2068  * and all other CRTCs dx,dy respectively.
2069  * @param root the window's screen which will be reset.
2070  */
2071 EAPI void
2072 ecore_x_randr_screen_reset(Ecore_X_Window root)
2073 {
2074 #ifdef ECORE_XRANDR
2075    XRRCrtcInfo *crtc_info = NULL;
2076    XRRScreenResources *res = NULL;
2077    //the 100000 are just a random huge number.
2078    int i, dx_min = 100000, dy_min = 100000, w_n = 0, h_n = 0, nenabled_crtcs = 0;
2079
2080    if (!_ecore_x_randr_root_validate(root) ||
2081        !(res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
2082      return;
2083
2084    Ecore_X_Randr_Crtc enabled_crtcs[res->ncrtc];
2085
2086    for (i = 0; i < res->ncrtc; i++)
2087      {
2088         if (!(crtc_info =
2089                 XRRGetCrtcInfo(_ecore_x_disp, res,
2090                                res->crtcs[i])) ||
2091             (crtc_info->mode == Ecore_X_Randr_None) ||
2092             (crtc_info->mode == Ecore_X_Randr_Unset)
2093             || ((crtc_info->noutput == 0)))
2094           continue;
2095
2096         enabled_crtcs[nenabled_crtcs++] = res->crtcs[i];
2097
2098         if ((int)(crtc_info->x + crtc_info->width) > w_n)
2099           w_n = (crtc_info->x + crtc_info->width);
2100
2101         if ((int)(crtc_info->y + crtc_info->height) > h_n)
2102           h_n = (crtc_info->y + crtc_info->height);
2103
2104         if (crtc_info->x < dx_min)
2105           dx_min = crtc_info->x;
2106         if (crtc_info->y < dy_min)
2107           dy_min = crtc_info->y;
2108
2109         XRRFreeCrtcInfo(crtc_info);
2110      }
2111    if ((dx_min > 0) || (dy_min > 0))
2112      {
2113         if (ecore_x_randr_move_crtcs(root, enabled_crtcs, nenabled_crtcs, -dx_min, -dy_min))
2114           {
2115              w_n -= dx_min;
2116              h_n -= dy_min;
2117           }
2118      }
2119    ecore_x_randr_screen_current_size_set(root,
2120                                          w_n,
2121                                          h_n,
2122                                          Ecore_X_Randr_Unset,
2123                                          Ecore_X_Randr_Unset);
2124 #endif
2125 }
2126
2127 /**
2128  * @brief Set up the backlight level to the given level.
2129  *
2130  * @param root The window's screen which will be set.
2131  * @param level Of the backlight between @c 0 and @c 1.
2132  */
2133
2134 EAPI void
2135 ecore_x_randr_screen_backlight_level_set(Ecore_X_Window root,
2136                                          double level)
2137 {
2138 #ifdef ECORE_XRANDR
2139    RANDR_CHECK_1_2_RET();
2140    Atom _backlight;
2141    XRRScreenResources *resources = NULL;
2142    Ecore_X_Randr_Output output;
2143    int o;
2144
2145    if ((level < 0) || (level > 1))
2146      {
2147         ERR("Wrong value for the backlight level. It should be between 0 and 1.");
2148         return;
2149      }
2150
2151    /*
2152     * To make sure that the _backlight atomic property still exists.
2153     */
2154    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2155    if (_backlight == None)
2156      {
2157         WRN("Backlight setting is not supported on this server or driver");
2158         return;
2159      }
2160
2161    /* get the ressources */
2162    resources = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root);
2163    if (!resources) return;
2164
2165    for (o = 0; o < resources->noutput; o++)
2166      {
2167         output = resources->outputs[o];
2168         if (ecore_x_randr_output_backlight_level_get(root, output) >= 0)
2169           {
2170              ecore_x_randr_output_backlight_level_set(root, output, level);
2171           }
2172      }
2173    XRRFreeScreenResources(resources);
2174 #endif
2175 }
2176
2177 /*
2178  * @brief Check if a backlight is available.
2179  * @return Whether a backlight is available.
2180  */
2181
2182 EAPI Eina_Bool
2183 ecore_x_randr_output_backlight_available(void)
2184 {
2185 #ifdef ECORE_XRANDR
2186    RANDR_CHECK_1_2_RET(-1);
2187    Atom _backlight;
2188
2189    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2190
2191    return (_backlight == None) ? EINA_FALSE : EINA_TRUE;
2192
2193 #endif
2194    return EINA_FALSE;
2195 }
2196
2197 /*
2198  * @brief Get the backlight level of the given output.
2199  *
2200  * @param root Window which's screen should be queried.
2201  * @param output From which the backlight level should be retrieved.
2202  * @return The backlight level.
2203  */
2204
2205 EAPI double
2206 ecore_x_randr_output_backlight_level_get(Ecore_X_Window root,
2207                                          Ecore_X_Randr_Output output)
2208 {
2209 #ifdef ECORE_XRANDR
2210    RANDR_CHECK_1_2_RET(-1);
2211    Atom actual_type;
2212    Atom _backlight;
2213    XRRPropertyInfo *info = NULL;
2214    double dvalue;
2215    int actual_format;
2216    long value, max, min;
2217    unsigned long nitems;
2218    unsigned long bytes_after;
2219    unsigned char *prop = NULL;
2220
2221    /* set backlight variable if not already done */
2222
2223    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2224    if (_backlight == None)
2225      {
2226         ERR("Backlight property is not suppported on this server or driver");
2227         return -1;
2228      }
2229
2230    if (!_ecore_x_randr_output_validate(root, output))
2231      {
2232         ERR("Invalid output");
2233         return -1;
2234      }
2235
2236    if (XRRGetOutputProperty(_ecore_x_disp, output, _backlight,
2237                             0, 4, False, False, None,
2238                             &actual_type, &actual_format,
2239                             &nitems, &bytes_after, &prop) != Success)
2240      {
2241         WRN("Backlight not supported on this output");
2242         return -1;
2243      }
2244
2245    if ((actual_type != XA_INTEGER) || (nitems != 1) || (actual_format != 32)) return -1;
2246
2247    value = *((long *)prop);
2248    free (prop);
2249
2250    /* I have the current value of the backlight */
2251    /* Now retrieve the min and max intensities of the output */
2252    info = XRRQueryOutputProperty(_ecore_x_disp, output, _backlight);
2253    if (info)
2254      {
2255         dvalue = -1;
2256         if ((info->range) && (info->num_values == 2))
2257           {
2258              /* finally convert the current value in the interval [0..1] */
2259              min = info->values[0];
2260              max = info->values[1];
2261              dvalue = ((double)(value - min)) / ((double)(max - min));
2262           }
2263         free(info);
2264         return dvalue;
2265      }
2266 #endif
2267    return -1;
2268 }
2269
2270 /*
2271  * @brief Set the backlight level of a given output.
2272  *
2273  * @param root Window which's screen should be queried.
2274  * @param output That should be set.
2275  * @param level For which the backlight should be set.
2276  * @return @c EINA_TRUE in case of success.
2277  */
2278
2279 EAPI Eina_Bool
2280 ecore_x_randr_output_backlight_level_set(Ecore_X_Window root,
2281                                          Ecore_X_Randr_Output output,
2282                                          double level)
2283 {
2284 #ifdef ECORE_XRANDR
2285    RANDR_CHECK_1_2_RET(EINA_FALSE);
2286    Atom _backlight;
2287    XRRPropertyInfo *info = NULL;
2288    double min, max, tmp;
2289    long new;
2290
2291    if ((level < 0) || (level > 1))
2292      {
2293         ERR("Backlight level should be between 0 and 1");
2294         return EINA_FALSE;
2295      }
2296
2297    if (!_ecore_x_randr_output_validate(root, output))
2298      {
2299         ERR("Wrong output value");
2300         return EINA_FALSE;
2301      }
2302
2303    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2304    if (_backlight == None)
2305      {
2306         WRN("Backlight property is not suppported on this server or driver");
2307         return EINA_FALSE;
2308      }
2309
2310    info = XRRQueryOutputProperty(_ecore_x_disp, output, _backlight);
2311    if (info)
2312      {
2313         if ((info->range) && (info->num_values == 2))
2314           {
2315              min = info->values[0];
2316              max = info->values[1];
2317              tmp = (level * (max - min)) + min;
2318              new = tmp;
2319              if (new > max) new = max;
2320              if (new < min) new = min;
2321              XRRChangeOutputProperty(_ecore_x_disp, output, _backlight, XA_INTEGER, 32,
2322                                      PropModeReplace, (unsigned char *)&new, 1);
2323              XFlush(_ecore_x_disp);
2324           }
2325         free(info);
2326         return EINA_TRUE;
2327      }
2328 #endif
2329    return EINA_FALSE;
2330 }
2331
2332 /*
2333  * @brief Get the outputs, which display a certain window.
2334  *
2335  * @param window Window the displaying outputs shall be found for
2336  * @param num The number of outputs displaying the window
2337  * @return Array of outputs that display a certain window. @c NULL if no
2338  * outputs was found that displays the specified window.
2339  */
2340
2341 EAPI Ecore_X_Randr_Output *
2342 ecore_x_randr_window_outputs_get(Ecore_X_Window window,
2343                                  int *num)
2344 {
2345 #ifdef ECORE_XRANDR
2346    Ecore_X_Window root;
2347    Ecore_X_Randr_Crtc *crtcs;
2348    Ecore_X_Randr_Output *outputs, *ret = NULL, *tret;
2349    int ncrtcs, noutputs, i, nret = 0;
2350
2351    if (_randr_version < RANDR_1_2) goto _ecore_x_randr_current_output_get_fail;
2352
2353    root = ecore_x_window_root_get(window);
2354    if (!(crtcs = ecore_x_randr_window_crtcs_get(window, &ncrtcs)))
2355      goto _ecore_x_randr_current_output_get_fail;
2356    
2357    for (i = 0, nret = 0; i < ncrtcs; i++)
2358      {
2359
2360         outputs = ecore_x_randr_crtc_outputs_get(root, crtcs[i],
2361                                                  &noutputs);
2362         if (!outputs)
2363           goto _ecore_x_randr_current_output_get_fail_free;
2364         tret = realloc(ret, ((nret + noutputs) * sizeof(Ecore_X_Randr_Output)));
2365         if (!tret) goto _ecore_x_randr_current_output_get_fail_free;
2366         ret = tret;
2367         memcpy(&ret[nret], outputs, (noutputs * sizeof(Ecore_X_Randr_Output)));
2368         nret += noutputs;
2369         free(outputs);
2370         outputs = NULL;
2371      }
2372    free(crtcs);
2373
2374    if (num)
2375      *num = nret;
2376
2377    return ret;
2378
2379 _ecore_x_randr_current_output_get_fail_free:
2380    free(outputs);
2381    free(crtcs);
2382    free(ret);
2383 _ecore_x_randr_current_output_get_fail:
2384 #endif
2385    if (num) *num = 0;
2386    return NULL;
2387 }
2388
2389 /*
2390  * @deprecated bad naming. Use ecore_x_randr_window_outputs_get instead.
2391  * @brief Get the outputs, which display a certain window.
2392  *
2393  * @param window Window the displaying outputs shall be found for.
2394  * @param num The number of outputs displaying the window.
2395  * @return Array of outputs that display a certain window. @c NULL if no
2396  * outputs was found that displays the specified window.
2397  */
2398
2399 EAPI Ecore_X_Randr_Output *
2400 ecore_x_randr_current_output_get(Ecore_X_Window window,
2401                                  int *num)
2402 {
2403    return ecore_x_randr_window_outputs_get(window, num);
2404 }
2405