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