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