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