82fa6b7396befe3a04fd95e7014d254712efd9dd
[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      }
1502    if ((x_n == r1_geo.x) && (y_n == r1_geo.x))
1503      return EINA_TRUE;
1504
1505    //out of possible bounds?
1506    if (((y_n + r1_geo.h) > h_max) || ((x_n + r1_geo.w) > w_max))
1507      return EINA_FALSE;
1508
1509    return ecore_x_randr_crtc_pos_set(root, crtc_r1, x_n, y_n);
1510 #else
1511    return EINA_FALSE;
1512 #endif
1513 }
1514
1515 /*
1516  * @brief Add given mode to given output.
1517  *
1518  * @param output The output the mode is added to.
1519  * @param mode The mode added to the output.
1520  * @return @c EINA_FALSE if output or mode equal Ecore_X_Randr_None, else
1521  * @c EINA_TRUE.
1522  * Additionally, if xcb backend is used, the success of the addition is
1523  * reported back directly.
1524  * @since 1.2.0
1525  */
1526 EAPI Eina_Bool
1527 ecore_x_randr_output_mode_add(Ecore_X_Randr_Output output,
1528                               Ecore_X_Randr_Mode mode)
1529 {
1530 #ifdef ECORE_XRANDR
1531    RANDR_CHECK_1_2_RET(EINA_FALSE);
1532
1533    if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None))
1534      return EINA_FALSE;
1535
1536    XRRAddOutputMode(_ecore_x_disp, output, mode);
1537    return EINA_TRUE;
1538 #else
1539    return EINA_FALSE;
1540 #endif
1541 }
1542
1543 /*
1544  * @brief delete given mode from given output
1545  * @param output the output the mode is removed from
1546  * @param mode the mode removed from the output
1547  * @since 1.2.0
1548  */
1549 EAPI void
1550 ecore_x_randr_output_mode_del(Ecore_X_Randr_Output output,
1551                               Ecore_X_Randr_Mode mode)
1552 {
1553 #ifdef ECORE_XRANDR
1554    RANDR_CHECK_1_2_RET();
1555
1556    if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None))
1557      return;
1558
1559    XRRDeleteOutputMode(_ecore_x_disp, output, mode);
1560 #else
1561    return;
1562 #endif
1563 }
1564
1565 EAPI Ecore_X_Randr_Mode *
1566 ecore_x_randr_output_modes_get(Ecore_X_Window root,
1567                                Ecore_X_Randr_Output output,
1568                                int *num,
1569                                int *npreferred)
1570 {
1571 #ifdef ECORE_XRANDR
1572    RANDR_CHECK_1_2_RET(NULL);
1573    XRRScreenResources *res = NULL;
1574    XRROutputInfo *output_info = NULL;
1575    Ecore_X_Randr_Mode *modes = NULL;
1576
1577    if ((output != Ecore_X_Randr_None)
1578        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1579        && (output_info =
1580              XRRGetOutputInfo(_ecore_x_disp, res, (RROutput)output)))
1581      {
1582         if ((modes = malloc(sizeof(Ecore_X_Randr_Mode) * output_info->nmode)))
1583           {
1584              memcpy(modes, output_info->modes,
1585                     (sizeof(Ecore_X_Randr_Mode) * output_info->nmode));
1586              if (num)
1587                *num = output_info->nmode;
1588
1589              if (npreferred)
1590                *npreferred = output_info->npreferred;
1591           }
1592      }
1593
1594    if (output_info)
1595      XRRFreeOutputInfo(output_info);
1596
1597    if (res)
1598      XRRFreeScreenResources(res);
1599
1600    return modes;
1601 #else
1602    return NULL;
1603 #endif
1604 }
1605
1606 EAPI Ecore_X_Randr_Crtc *
1607 ecore_x_randr_output_possible_crtcs_get(Ecore_X_Window root,
1608                                         Ecore_X_Randr_Output output,
1609                                         int *num)
1610 {
1611 #ifdef ECORE_XRANDR
1612    RANDR_CHECK_1_2_RET(NULL);
1613    XRRScreenResources *res = NULL;
1614    XRROutputInfo *output_info = NULL;
1615    Ecore_X_Randr_Crtc *crtcs = NULL;
1616
1617    if ((output != Ecore_X_Randr_None))
1618      {
1619         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1620           {
1621              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1622                {
1623                   if ((crtcs = malloc(sizeof(Ecore_X_Randr_Crtc) * output_info->ncrtc)))
1624                     {
1625                        memcpy(crtcs, output_info->crtcs, (sizeof(Ecore_X_Randr_Crtc) * output_info->ncrtc));
1626                        if (num) *num = output_info->ncrtc;
1627                     }
1628                   XRRFreeOutputInfo(output_info);
1629                }
1630              XRRFreeScreenResources(res);
1631           }
1632      }
1633    return crtcs;
1634 #else
1635    return Ecore_X_Randr_None;
1636 #endif
1637 }
1638
1639 /**
1640  * @brief gets the the outputs which might be used simultenously on the same
1641  * CRTC.
1642  * @param root window that this information should be queried for.
1643  * @param output the output which's clones we concern
1644  * @param num number of possible clones
1645  */
1646 EAPI Ecore_X_Randr_Output *
1647 ecore_x_randr_output_clones_get(Ecore_X_Window root,
1648                                 Ecore_X_Randr_Output output,
1649                                 int *num)
1650 {
1651 #ifdef ECORE_XRANDR
1652    RANDR_CHECK_1_2_RET(NULL);
1653    XRRScreenResources *res = NULL;
1654    XRROutputInfo *output_info = NULL;
1655    Ecore_X_Randr_Output *outputs = NULL;
1656
1657    if ((output != Ecore_X_Randr_None))
1658      {
1659         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1660           {
1661              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1662                {
1663                   if ((outputs = malloc(sizeof(Ecore_X_Randr_Output) * output_info->nclone)))
1664                     {
1665                        memcpy(outputs, output_info->clones, (sizeof(Ecore_X_Randr_Output) * output_info->nclone));
1666                        if (num) *num = output_info->nclone;
1667                     }
1668                   XRRFreeOutputInfo(output_info);
1669                }
1670              XRRFreeScreenResources(res);
1671           }
1672      }
1673    return outputs;
1674 #else
1675    return Ecore_X_Randr_None;
1676 #endif
1677 }
1678
1679 EAPI Ecore_X_Randr_Crtc
1680 ecore_x_randr_output_crtc_get(Ecore_X_Window root,
1681                               Ecore_X_Randr_Output output)
1682 {
1683 #ifdef ECORE_XRANDR
1684    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
1685    XRRScreenResources *res = NULL;
1686    XRROutputInfo *output_info = NULL;
1687    Ecore_X_Randr_Crtc ret = Ecore_X_Randr_None;
1688
1689    if ((output != Ecore_X_Randr_None))
1690      {
1691         if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1692           {
1693              if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1694                {
1695                   ret = output_info->crtc;
1696                   XRRFreeOutputInfo(output_info);
1697                }
1698              XRRFreeScreenResources(res);
1699           }
1700      }
1701
1702    return ret;
1703 #else
1704    return Ecore_X_Randr_None;
1705 #endif
1706 }
1707
1708 /**
1709  * @brief gets the given output's name as reported by X
1710  * @param root the window which's screen will be queried
1711  * @param output The output for which the name will be reported.
1712  * @param len length of returned c-string.
1713  * @return name of the output as reported by X
1714  */
1715 EAPI char *
1716 ecore_x_randr_output_name_get(Ecore_X_Window root,
1717                               Ecore_X_Randr_Output output,
1718                               int *len)
1719 {
1720 #ifdef ECORE_XRANDR
1721    RANDR_CHECK_1_2_RET(NULL);
1722    XRRScreenResources *res = NULL;
1723    XRROutputInfo *output_info = NULL;
1724    char *ret = NULL;
1725
1726    if ((output != Ecore_X_Randr_None)
1727        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1728        && (output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1729      {
1730         /*
1731          * Actually the below command is correct, but due to a bug in libXrandr
1732          * it doesn't work. Therefore we stick with strlen().
1733          * Replace the line below with the following once this bug is
1734          * fixed within libXrandr.
1735          *
1736          *    *len = output_info->nameLen;
1737          *
1738          */
1739         if ((ret = strdup(output_info->name)) && len)
1740           *len = strlen(ret);
1741
1742         XRRFreeOutputInfo(output_info);
1743      }
1744
1745    if (res)
1746      XRRFreeScreenResources(res);
1747
1748    return ret;
1749 #else
1750    return NULL;
1751 #endif
1752 }
1753
1754 /**
1755  * @brief gets the width and hight of a given mode
1756  * @param mode the mode which's size is to be looked up
1757  * @param w width of given mode in px
1758  * @param h height of given mode in px
1759  */
1760 EAPI void
1761 ecore_x_randr_mode_size_get(Ecore_X_Window root,
1762                             Ecore_X_Randr_Mode mode,
1763                             int *w,
1764                             int *h)
1765 {
1766 #ifdef ECORE_XRANDR
1767    RANDR_CHECK_1_2_RET();
1768    XRRScreenResources *res = NULL;
1769    int i;
1770
1771    if ((mode != Ecore_X_Randr_None)
1772        && (w || h)
1773        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1774      {
1775         for (i = 0; i < res->nmode; i++)
1776           {
1777              if (res->modes[i].id == mode)
1778                {
1779                   if (w)
1780                     *w = res->modes[i].width;
1781
1782                   if (h)
1783                     *h = res->modes[i].height;
1784
1785                   break;
1786                }
1787           }
1788      }
1789
1790    if (res)
1791      XRRFreeScreenResources(res);
1792
1793 #endif
1794 }
1795
1796 /**
1797  * @brief gets the EDID information of an attached output if available.
1798  * Note that this information is not to be compared using ordinary string
1799  * comparison functions, since it includes 0-bytes.
1800  * @param root window this information should be queried from
1801  * @param output the XID of the output
1802  * @param length length of the byte-array. If NULL, request will fail.
1803  */
1804 EAPI unsigned char *
1805 ecore_x_randr_output_edid_get(Ecore_X_Window root,
1806                               Ecore_X_Randr_Output output,
1807                               unsigned long *length)
1808 {
1809 #ifdef ECORE_XRANDR
1810    RANDR_CHECK_1_2_RET(NULL);
1811    Atom name = XInternAtom (_ecore_x_disp, RANDR_PROPERTY_EDID, False);
1812    unsigned char *prop_data, *ret = NULL;
1813    int actual_format;
1814    unsigned long nitems, bytes_after;
1815    Atom actual_type;
1816
1817    if (!length || !_ecore_x_randr_output_validate(root, output))
1818      return NULL;
1819
1820    if (XRRGetOutputProperty (_ecore_x_disp, output, name,
1821                              0, 100, False, False,
1822                              AnyPropertyType,
1823                              &actual_type, &actual_format,
1824                              &nitems, &bytes_after, &prop_data) == Success)
1825      {
1826         if (actual_type == XA_INTEGER && actual_format == 8)
1827           {
1828              if ((ret = malloc(nitems * sizeof(unsigned char))))
1829                {
1830                   if (length &&
1831                       (memcpy(ret, prop_data, (nitems * sizeof(unsigned char)))))
1832                     *length = nitems;
1833
1834                   return ret;
1835                }
1836           }
1837      }
1838
1839    return NULL;
1840 #else
1841    return NULL;
1842 #endif
1843 }
1844
1845 EAPI Ecore_X_Randr_Connection_Status
1846 ecore_x_randr_output_connection_status_get(Ecore_X_Window root,
1847                                            Ecore_X_Randr_Output output)
1848 {
1849 #ifdef ECORE_XRANDR
1850    RANDR_CHECK_1_2_RET(ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN);
1851    XRRScreenResources *res = NULL;
1852    XRROutputInfo *output_info = NULL;
1853    Ecore_X_Randr_Connection_Status ret =
1854      ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
1855
1856    if ((output != Ecore_X_Randr_None)
1857        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
1858        && (output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
1859      {
1860         ret = output_info->connection;
1861      }
1862
1863    if (output_info)
1864      XRRFreeOutputInfo(output_info);
1865
1866    if (res)
1867      XRRFreeScreenResources(res);
1868
1869    return ret;
1870 #else
1871    return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
1872 #endif
1873 }
1874
1875 EAPI void
1876 ecore_x_randr_output_size_mm_get(Ecore_X_Window root,
1877                                  Ecore_X_Randr_Output output,
1878                                  int *w_mm,
1879                                  int *h_mm)
1880 {
1881 #ifdef ECORE_XRANDR
1882    RANDR_CHECK_1_2_RET();
1883    XRRScreenResources *res = NULL;
1884    XRROutputInfo *output_info = NULL;
1885
1886    if ((output != Ecore_X_Randr_None)
1887        && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
1888      {
1889         if ((output_info =
1890                XRRGetOutputInfo(_ecore_x_disp, res, (RROutput)output)))
1891           {
1892              if (w_mm)
1893                *w_mm = output_info->mm_width;
1894
1895              if (h_mm)
1896                *h_mm = output_info->mm_height;
1897
1898              XRRFreeOutputInfo(output_info);
1899           }
1900
1901         XRRFreeScreenResources(res);
1902      }
1903
1904 #endif
1905 }
1906
1907 EAPI Eina_Bool
1908 ecore_x_randr_move_all_crtcs_but(Ecore_X_Window root,
1909                                  const Ecore_X_Randr_Crtc *not_moved,
1910                                  int nnot_moved,
1911                                  int dx,
1912                                  int dy)
1913 {
1914 #ifdef ECORE_XRANDR
1915    Ecore_X_Randr_Crtc *crtcs_to_be_moved = NULL;
1916    XRRScreenResources *res = NULL;
1917    int i, j, k, n;
1918    Eina_Bool ret;
1919
1920    if ((nnot_moved <= 0) || (!not_moved)
1921        || !_ecore_x_randr_root_validate(root)
1922        || !(res =
1923               _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
1924      return EINA_FALSE;
1925
1926    n = (res->ncrtc - nnot_moved);
1927    if ((crtcs_to_be_moved = malloc(sizeof(Ecore_X_Randr_Crtc) * n)))
1928      {
1929         for (i = 0, k = 0; (i < res->ncrtc) && (k < n); i++)
1930           {
1931              for (j = 0; j < nnot_moved; j++)
1932                {
1933                   if (res->crtcs[i] == not_moved[j])
1934                     break;
1935                }
1936              if (j == nnot_moved)
1937                //crtcs[i] is not in the 'not to move'-list
1938                crtcs_to_be_moved[k++] = res->crtcs[i];
1939           }
1940      }
1941
1942    XRRFreeScreenResources(res);
1943    ret = ecore_x_randr_move_crtcs(root, crtcs_to_be_moved, n, dx, dy);
1944    free(crtcs_to_be_moved);
1945    return ret;
1946 #else
1947    return EINA_FALSE;
1948 #endif
1949 }
1950
1951 /*
1952  * @brief Move given CRTCs belonging to the given root window's screen dx/dy
1953  * pixels relative to their current position. The screen size will be
1954  * automatically adjusted if necessary and possible.
1955  *
1956  * @param root Window which's screen's resources are used.
1957  * @param crtcs List of CRTCs to be moved.
1958  * @param ncrtc Number of CRTCs in array.
1959  * @param dx Amount of pixels the CRTCs should be moved in x direction.
1960  * @param dy Amount of pixels the CRTCs should be moved in y direction.
1961  * @return @c EINA_TRUE if all crtcs could be moved successfully.
1962  */
1963 EAPI Eina_Bool
1964 ecore_x_randr_move_crtcs(Ecore_X_Window root,
1965                          const Ecore_X_Randr_Crtc *crtcs,
1966                          int ncrtc,
1967                          int dx,
1968                          int dy)
1969 {
1970 #ifdef ECORE_XRANDR
1971    RANDR_CHECK_1_2_RET(EINA_FALSE);
1972    XRRScreenResources *res = NULL;
1973    XRRCrtcInfo **crtc_info = NULL;
1974    Eina_Bool ret = EINA_TRUE;
1975    int i, cw, ch, w_max, h_max, nw, nh;
1976
1977    crtc_info = alloca(sizeof(XRRCrtcInfo *) * ncrtc);
1978    memset(crtc_info, 0, sizeof(XRRCrtcInfo *) * ncrtc);
1979    if (_ecore_x_randr_root_validate(root)
1980        && (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
1981      {
1982         ecore_x_randr_screen_size_range_get(root, NULL, NULL, &w_max, &h_max);
1983         ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
1984         nw = cw;
1985         nh = ch;
1986
1987         for (i = 0;
1988              (i < ncrtc) &&
1989              (crtc_info[i] = XRRGetCrtcInfo(_ecore_x_disp, res, crtcs[i]));
1990              i++)
1991           {
1992              if (((crtc_info[i]->x + dx) < 0) ||
1993                  ((int)(crtc_info[i]->x + crtc_info[i]->width + dx) > w_max)
1994                  || ((crtc_info[i]->y + dy) < 0) ||
1995                  ((int)(crtc_info[i]->y + crtc_info[i]->height + dy) > h_max)
1996                  )
1997                goto _ecore_x_randr_move_crtcs_fail_free_crtc_info;
1998
1999              nw = MAX((int)(crtc_info[i]->x + crtc_info[i]->width + dx), nw);
2000              nh = MAX((int)(crtc_info[i]->y + crtc_info[i]->height + dy), nh);
2001           }
2002         //not out of bounds
2003
2004         //resize if necessary
2005         if (!(((nw > cw) ||
2006                (nh > ch)) ||
2007               ecore_x_randr_screen_current_size_set(root, nw, nh,
2008                                                     Ecore_X_Randr_Unset,
2009                                                     Ecore_X_Randr_Unset)))
2010           goto _ecore_x_randr_move_crtcs_fail_free_crtc_info;
2011
2012         //actually move all the crtcs, keep their rotation and mode.
2013         for (i = 0; (i < ncrtc) && crtc_info[i]; i++)
2014           {
2015              if ((crtc_info[i]) &&
2016                  (!ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL,
2017                                                    Ecore_X_Randr_Unset,
2018                                                    (crtc_info[i]->x + dx),
2019                                                    (crtc_info[i]->y + dy),
2020                                                    crtc_info[i]->mode,
2021                                                    crtc_info[i]->rotation)))
2022                {
2023                   ret = EINA_FALSE;
2024                   break;
2025                }
2026           }
2027         if (i < ncrtc)
2028           {
2029              //something went wrong, let's try to move the already moved crtcs
2030              //back.
2031              while ((i--) >= 0)
2032                {
2033                   if (crtc_info[i])
2034                     ecore_x_randr_crtc_settings_set(root,
2035                                                     crtcs[i],
2036                                                     NULL,
2037                                                     Ecore_X_Randr_Unset,
2038                                                     (crtc_info[i]->x - dx),
2039                                                     (crtc_info[i]->y - dy),
2040                                                     crtc_info[i]->mode,
2041                                                     crtc_info[i]->rotation);
2042                }
2043           }
2044
2045         for (i = 0; i < ncrtc; i++)
2046           {
2047              if (crtc_info[i]) XRRFreeCrtcInfo(crtc_info[i]);
2048           }
2049      }
2050
2051    XRRFreeScreenResources(res);
2052
2053    return ret;
2054 _ecore_x_randr_move_crtcs_fail_free_crtc_info:
2055    while (i-- > 0)
2056      XRRFreeCrtcInfo(crtc_info[i]);
2057    XRRFreeScreenResources(res);
2058    return EINA_FALSE;
2059 #else
2060    return EINA_FALSE;
2061 #endif
2062 }
2063
2064 /**
2065  * @brief removes unused screen space. The most upper left CRTC is set to 0x0
2066  * and all other CRTCs dx,dy respectively.
2067  * @param root the window's screen which will be reset.
2068  */
2069 EAPI void
2070 ecore_x_randr_screen_reset(Ecore_X_Window root)
2071 {
2072 #ifdef ECORE_XRANDR
2073    XRRCrtcInfo *crtc_info = NULL;
2074    XRRScreenResources *res = NULL;
2075    //the 100000 are just a random huge number.
2076    int i, dx_min = 100000, dy_min = 100000, w_n = 0, h_n = 0, nenabled_crtcs = 0;
2077
2078    if (!_ecore_x_randr_root_validate(root) ||
2079        !(res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
2080      return;
2081
2082    Ecore_X_Randr_Crtc enabled_crtcs[res->ncrtc];
2083
2084    for (i = 0; i < res->ncrtc; i++)
2085      {
2086         if (!(crtc_info =
2087                 XRRGetCrtcInfo(_ecore_x_disp, res,
2088                                res->crtcs[i])) ||
2089             (crtc_info->mode == Ecore_X_Randr_None) ||
2090             (crtc_info->mode == Ecore_X_Randr_Unset)
2091             || ((crtc_info->noutput == 0)))
2092           continue;
2093
2094         enabled_crtcs[nenabled_crtcs++] = res->crtcs[i];
2095
2096         if ((int)(crtc_info->x + crtc_info->width) > w_n)
2097           w_n = (crtc_info->x + crtc_info->width);
2098
2099         if ((int)(crtc_info->y + crtc_info->height) > h_n)
2100           h_n = (crtc_info->y + crtc_info->height);
2101
2102         if (crtc_info->x < dx_min)
2103           dx_min = crtc_info->x;
2104         if (crtc_info->y < dy_min)
2105           dy_min = crtc_info->y;
2106
2107         XRRFreeCrtcInfo(crtc_info);
2108      }
2109    if ((dx_min > 0) || (dy_min > 0))
2110      {
2111         if (ecore_x_randr_move_crtcs(root, enabled_crtcs, nenabled_crtcs, -dx_min, -dy_min))
2112           {
2113              w_n -= dx_min;
2114              h_n -= dy_min;
2115           }
2116      }
2117    ecore_x_randr_screen_current_size_set(root,
2118                                          w_n,
2119                                          h_n,
2120                                          Ecore_X_Randr_Unset,
2121                                          Ecore_X_Randr_Unset);
2122 #endif
2123 }
2124
2125 /**
2126  * @brief Set up the backlight level to the given level.
2127  *
2128  * @param root The window's screen which will be set.
2129  * @param level Of the backlight between @c 0 and @c 1.
2130  */
2131
2132 EAPI void
2133 ecore_x_randr_screen_backlight_level_set(Ecore_X_Window root,
2134                                          double level)
2135 {
2136 #ifdef ECORE_XRANDR
2137    RANDR_CHECK_1_2_RET();
2138    Atom _backlight;
2139    XRRScreenResources *resources = NULL;
2140    Ecore_X_Randr_Output output;
2141    int o;
2142
2143    if ((level < 0) || (level > 1))
2144      {
2145         ERR("Wrong value for the backlight level. It should be between 0 and 1.");
2146         return;
2147      }
2148
2149    /*
2150     * To make sure that the _backlight atomic property still exists.
2151     */
2152    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2153    if (_backlight == None)
2154      {
2155         WRN("Backlight setting is not supported on this server or driver");
2156         return;
2157      }
2158
2159    /* get the ressources */
2160    resources = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root);
2161    if (!resources) return;
2162
2163    for (o = 0; o < resources->noutput; o++)
2164      {
2165         output = resources->outputs[o];
2166         if (ecore_x_randr_output_backlight_level_get(root, output) >= 0)
2167           {
2168              ecore_x_randr_output_backlight_level_set(root, output, level);
2169           }
2170      }
2171    XRRFreeScreenResources(resources);
2172 #endif
2173 }
2174
2175 /*
2176  * @brief Check if a backlight is available.
2177  * @return Whether a backlight is available.
2178  */
2179
2180 EAPI Eina_Bool
2181 ecore_x_randr_output_backlight_available(void)
2182 {
2183 #ifdef ECORE_XRANDR
2184    RANDR_CHECK_1_2_RET(-1);
2185    Atom _backlight;
2186
2187    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2188
2189    return (_backlight == None) ? EINA_FALSE : EINA_TRUE;
2190
2191 #endif
2192    return EINA_FALSE;
2193 }
2194
2195 /*
2196  * @brief Get the backlight level of the given output.
2197  *
2198  * @param root Window which's screen should be queried.
2199  * @param output From which the backlight level should be retrieved.
2200  * @return The backlight level.
2201  */
2202
2203 EAPI double
2204 ecore_x_randr_output_backlight_level_get(Ecore_X_Window root,
2205                                          Ecore_X_Randr_Output output)
2206 {
2207 #ifdef ECORE_XRANDR
2208    RANDR_CHECK_1_2_RET(-1);
2209    Atom actual_type;
2210    Atom _backlight;
2211    XRRPropertyInfo *info = NULL;
2212    double dvalue;
2213    int actual_format;
2214    long value, max, min;
2215    unsigned long nitems;
2216    unsigned long bytes_after;
2217    unsigned char *prop = NULL;
2218
2219    /* set backlight variable if not already done */
2220
2221    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2222    if (_backlight == None)
2223      {
2224         ERR("Backlight property is not suppported on this server or driver");
2225         return -1;
2226      }
2227
2228    if (!_ecore_x_randr_output_validate(root, output))
2229      {
2230         ERR("Invalid output");
2231         return -1;
2232      }
2233
2234    if (XRRGetOutputProperty(_ecore_x_disp, output, _backlight,
2235                             0, 4, False, False, None,
2236                             &actual_type, &actual_format,
2237                             &nitems, &bytes_after, &prop) != Success)
2238      {
2239         WRN("Backlight not supported on this output");
2240         return -1;
2241      }
2242
2243    if ((actual_type != XA_INTEGER) || (nitems != 1) || (actual_format != 32)) return -1;
2244
2245    value = *((long *)prop);
2246    free (prop);
2247
2248    /* I have the current value of the backlight */
2249    /* Now retrieve the min and max intensities of the output */
2250    info = XRRQueryOutputProperty(_ecore_x_disp, output, _backlight);
2251    if (info)
2252      {
2253         dvalue = -1;
2254         if ((info->range) && (info->num_values == 2))
2255           {
2256              /* finally convert the current value in the interval [0..1] */
2257              min = info->values[0];
2258              max = info->values[1];
2259              dvalue = ((double)(value - min)) / ((double)(max - min));
2260           }
2261         free(info);
2262         return dvalue;
2263      }
2264 #endif
2265    return -1;
2266 }
2267
2268 /*
2269  * @brief Set the backlight level of a given output.
2270  *
2271  * @param root Window which's screen should be queried.
2272  * @param output That should be set.
2273  * @param level For which the backlight should be set.
2274  * @return @c EINA_TRUE in case of success.
2275  */
2276
2277 EAPI Eina_Bool
2278 ecore_x_randr_output_backlight_level_set(Ecore_X_Window root,
2279                                          Ecore_X_Randr_Output output,
2280                                          double level)
2281 {
2282 #ifdef ECORE_XRANDR
2283    RANDR_CHECK_1_2_RET(EINA_FALSE);
2284    Atom _backlight;
2285    XRRPropertyInfo *info = NULL;
2286    double min, max, tmp;
2287    long new;
2288
2289    if ((level < 0) || (level > 1))
2290      {
2291         ERR("Backlight level should be between 0 and 1");
2292         return EINA_FALSE;
2293      }
2294
2295    if (!_ecore_x_randr_output_validate(root, output))
2296      {
2297         ERR("Wrong output value");
2298         return EINA_FALSE;
2299      }
2300
2301    _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True);
2302    if (_backlight == None)
2303      {
2304         WRN("Backlight property is not suppported on this server or driver");
2305         return EINA_FALSE;
2306      }
2307
2308    info = XRRQueryOutputProperty(_ecore_x_disp, output, _backlight);
2309    if (info)
2310      {
2311         if ((info->range) && (info->num_values == 2))
2312           {
2313              min = info->values[0];
2314              max = info->values[1];
2315              tmp = (level * (max - min)) + min;
2316              new = tmp;
2317              if (new > max) new = max;
2318              if (new < min) new = min;
2319              XRRChangeOutputProperty(_ecore_x_disp, output, _backlight, XA_INTEGER, 32,
2320                                      PropModeReplace, (unsigned char *)&new, 1);
2321              XFlush(_ecore_x_disp);
2322           }
2323         free(info);
2324         return EINA_TRUE;
2325      }
2326 #endif
2327    return EINA_FALSE;
2328 }
2329
2330 /*
2331  * @brief Get the outputs, which display a certain window.
2332  *
2333  * @param window Window the displaying outputs shall be found for
2334  * @param num The number of outputs displaying the window
2335  * @return Array of outputs that display a certain window. @c NULL if no
2336  * outputs was found that displays the specified window.
2337  */
2338
2339 EAPI Ecore_X_Randr_Output *
2340 ecore_x_randr_window_outputs_get(Ecore_X_Window window,
2341                                  int *num)
2342 {
2343 #ifdef ECORE_XRANDR
2344    Ecore_X_Window root;
2345    Ecore_X_Randr_Crtc *crtcs;
2346    Ecore_X_Randr_Output *outputs, *ret = NULL, *tret;
2347    int ncrtcs, noutputs, i, nret = 0;
2348
2349    if (_randr_version < RANDR_1_2) goto _ecore_x_randr_current_output_get_fail;
2350
2351    root = ecore_x_window_root_get(window);
2352    if (!(crtcs = ecore_x_randr_window_crtcs_get(window, &ncrtcs)))
2353      goto _ecore_x_randr_current_output_get_fail;
2354    
2355    for (i = 0, nret = 0; i < ncrtcs; i++)
2356      {
2357
2358         outputs = ecore_x_randr_crtc_outputs_get(root, crtcs[i],
2359                                                  &noutputs);
2360         if (!outputs)
2361           goto _ecore_x_randr_current_output_get_fail_free;
2362         tret = realloc(ret, ((nret + noutputs) * sizeof(Ecore_X_Randr_Output)));
2363         if (!tret) goto _ecore_x_randr_current_output_get_fail_free;
2364         ret = tret;
2365         memcpy(&ret[nret], outputs, (noutputs * sizeof(Ecore_X_Randr_Output)));
2366         nret += noutputs;
2367         free(outputs);
2368         outputs = NULL;
2369      }
2370    free(crtcs);
2371
2372    if (num)
2373      *num = nret;
2374
2375    return ret;
2376
2377 _ecore_x_randr_current_output_get_fail_free:
2378    free(outputs);
2379    free(crtcs);
2380    free(ret);
2381 _ecore_x_randr_current_output_get_fail:
2382 #endif
2383    if (num) *num = 0;
2384    return NULL;
2385 }
2386
2387 /*
2388  * @deprecated bad naming. Use ecore_x_randr_window_outputs_get instead.
2389  * @brief Get the outputs, which display a certain window.
2390  *
2391  * @param window Window the displaying outputs shall be found for.
2392  * @param num The number of outputs displaying the window.
2393  * @return Array of outputs that display a certain window. @c NULL if no
2394  * outputs was found that displays the specified window.
2395  */
2396
2397 EAPI Ecore_X_Randr_Output *
2398 ecore_x_randr_current_output_get(Ecore_X_Window window,
2399                                  int *num)
2400 {
2401    return ecore_x_randr_window_outputs_get(window, num);
2402 }
2403