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