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