eolian: rename is_ref API to is_ptr to match syntax
[platform/upstream/efl.git] / src / lib / ecore_x / xcb / ecore_xcb_randr.c
1 /* TODO: List of missing functions
2  *
3  * ecore_x_randr_edid_display_aspect_ratio_preferred_get
4  * ecore_x_randr_edid_display_aspect_ratios_get
5  * ecore_x_randr_edid_display_colorscheme_get
6  * ecore_x_randr_edid_display_type_digital_get
7  * ecore_x_randr_edid_display_interface_type_get
8  * ecore_x_randr_output_subpixel_order_get
9  * ecore_x_randr_output_wired_clones_get
10  * ecore_x_randr_output_compatibility_list_get
11  * ecore_x_randr_output_signal_formats_get
12  * ecore_x_randr_output_signal_format_set
13  * ecore_x_randr_output_signal_properties_get
14  * ecore_x_randr_output_connector_number_get
15  * ecore_x_randr_output_connector_type_get
16  * ecore_x_randr_crtc_panning_area_get
17  * ecore_x_randr_crtc_panning_area_set
18  * ecore_x_randr_crtc_tracking_area_get
19  * ecore_x_randr_crtc_tracking_area_set
20  * ecore_x_randr_crtc_border_area_get
21  * ecore_x_randr_crtc_border_area_set
22  */
23
24 #include "ecore_xcb_private.h"
25 # ifdef ECORE_XCB_RANDR
26 #  include <xcb/randr.h>
27 # endif
28
29 #define Ecore_X_Randr_None  0
30 #define Ecore_X_Randr_Unset -1
31
32 #define RANDR_1_1           ((1 << 16) | 1)
33 #define RANDR_1_2           ((1 << 16) | 2)
34 #define RANDR_1_3           ((1 << 16) | 3)
35 #define RANDR_1_4           ((1 << 16) | 4)
36
37 #define RANDR_CHECK_1_1_RET(ret) if (_randr_version < RANDR_1_1) return ret
38 #define RANDR_CHECK_1_2_RET(ret) if (_randr_version < RANDR_1_2) return ret
39 #define RANDR_CHECK_1_3_RET(ret) if (_randr_version < RANDR_1_3) return ret
40 #define RANDR_CHECK_1_4_RET(ret) if (_randr_version < RANDR_1_4) return ret
41
42 #define ECORE_X_RANDR_EDID_VERSION_13 ((1 << 8) | 3)
43 #define _ECORE_X_RANDR_EDID_OFFSET_VERSION_MAJOR 0x12
44 #define _ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR 0x13
45 #define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK 0x36
46 #define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE 3
47 #define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT 5
48 #define _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX 13
49 #define _ECORE_X_RANDR_EDID_MANUFACTURER 0x08
50
51 #define _ECORE_X_RANDR_EDID_FOR_EACH_DESCRIPTOR_BLOCK(edid, block) \
52   for (block = edid + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK; block <= (edid + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK + (3 * 18)); block += 18)
53
54 #define _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) \
55   _ECORE_X_RANDR_EDID_FOR_EACH_DESCRIPTOR_BLOCK(edid, block)                 \
56   if ((block[0] == 0) && (block[1] == 0))
57
58 #ifdef ECORE_XCB_RANDR
59 # define RANDR_VALIDATE_ROOT(screen, root) \
60   ((screen = _ecore_xcb_randr_root_to_screen(root)) != -1)
61 #endif
62
63 /* local function prototypes */
64 static Eina_Bool                                       _ecore_xcb_randr_output_validate(Ecore_X_Window       root,
65                                                                                         Ecore_X_Randr_Output output);
66 static Eina_Bool                                       _ecore_xcb_randr_crtc_validate(Ecore_X_Window     root,
67                                                                                       Ecore_X_Randr_Crtc crtc);
68 static Eina_Bool                                       _ecore_xcb_randr_root_validate(Ecore_X_Window root);
69 static int                                             _ecore_xcb_randr_root_to_screen(Ecore_X_Window root);
70 #ifdef ECORE_XCB_RANDR
71 static xcb_randr_get_screen_resources_reply_t         *_ecore_xcb_randr_12_get_resources(Ecore_X_Window win);
72 static xcb_randr_get_screen_resources_current_reply_t *_ecore_xcb_randr_13_get_resources(Ecore_X_Window win);
73 #endif
74 static xcb_timestamp_t                                 _ecore_xcb_randr_12_get_resource_timestamp(Ecore_X_Window win);
75 static xcb_timestamp_t                                 _ecore_xcb_randr_13_get_resource_timestamp(Ecore_X_Window win);
76
77 static Ecore_X_Randr_Mode                             *_ecore_xcb_randr_12_output_modes_get(Ecore_X_Window       root,
78                                                                                             Ecore_X_Randr_Output output,
79                                                                                             int                 *num,
80                                                                                             int                 *npreferred);
81 static Ecore_X_Randr_Mode *_ecore_xcb_randr_13_output_modes_get(Ecore_X_Window       root,
82                                                                 Ecore_X_Randr_Output output,
83                                                                 int                 *num,
84                                                                 int                 *npreferred);
85 static Ecore_X_Randr_Mode_Info  *_ecore_xcb_randr_12_mode_info_get(Ecore_X_Window     root,
86                                                                    Ecore_X_Randr_Mode mode);
87 static Ecore_X_Randr_Mode_Info  *_ecore_xcb_randr_13_mode_info_get(Ecore_X_Window     root,
88                                                                    Ecore_X_Randr_Mode mode);
89 static Ecore_X_Randr_Mode_Info **_ecore_xcb_randr_12_modes_info_get(Ecore_X_Window root,
90                                                                     int           *num);
91 static Ecore_X_Randr_Mode_Info **_ecore_xcb_randr_13_modes_info_get(Ecore_X_Window root,
92                                                                     int           *num);
93 static void                      _ecore_xcb_randr_12_mode_size_get(Ecore_X_Window     root,
94                                                                    Ecore_X_Randr_Mode mode,
95                                                                    int               *w,
96                                                                    int               *h);
97 static void _ecore_xcb_randr_13_mode_size_get(Ecore_X_Window     root,
98                                               Ecore_X_Randr_Mode mode,
99                                               int               *w,
100                                               int               *h);
101 static Ecore_X_Randr_Output *_ecore_xcb_randr_12_output_clones_get(Ecore_X_Window       root,
102                                                                    Ecore_X_Randr_Output output,
103                                                                    int                 *num);
104 static Ecore_X_Randr_Output *_ecore_xcb_randr_13_output_clones_get(Ecore_X_Window       root,
105                                                                    Ecore_X_Randr_Output output,
106                                                                    int                 *num);
107 static Ecore_X_Randr_Crtc *_ecore_xcb_randr_12_output_possible_crtcs_get(Ecore_X_Window       root,
108                                                                          Ecore_X_Randr_Output output,
109                                                                          int                 *num);
110 static Ecore_X_Randr_Crtc *_ecore_xcb_randr_13_output_possible_crtcs_get(Ecore_X_Window       root,
111                                                                          Ecore_X_Randr_Output output,
112                                                                          int                 *num);
113 static char *_ecore_xcb_randr_12_output_name_get(Ecore_X_Window       root,
114                                                  Ecore_X_Randr_Output output,
115                                                  int                 *len);
116 static char *_ecore_xcb_randr_13_output_name_get(Ecore_X_Window       root,
117                                                  Ecore_X_Randr_Output output,
118                                                  int                 *len);
119 static Ecore_X_Randr_Connection_Status _ecore_xcb_randr_12_output_connection_status_get(Ecore_X_Window       root,
120                                                                                         Ecore_X_Randr_Output output);
121 static Ecore_X_Randr_Connection_Status _ecore_xcb_randr_13_output_connection_status_get(Ecore_X_Window       root,
122                                                                                         Ecore_X_Randr_Output output);
123 static Ecore_X_Randr_Output           *_ecore_xcb_randr_12_outputs_get(Ecore_X_Window root,
124                                                                        int           *num);
125 static Ecore_X_Randr_Output           *_ecore_xcb_randr_13_outputs_get(Ecore_X_Window root,
126                                                                        int           *num);
127 static Ecore_X_Randr_Crtc              _ecore_xcb_randr_12_output_crtc_get(Ecore_X_Window       root,
128                                                                            Ecore_X_Randr_Output output);
129 static Ecore_X_Randr_Crtc              _ecore_xcb_randr_13_output_crtc_get(Ecore_X_Window       root,
130                                                                            Ecore_X_Randr_Output output);
131
132 /* local variables */
133 static Eina_Bool _randr_avail = EINA_FALSE;
134 static int _randr_version = -1;
135
136 /* external variables */
137 int _ecore_xcb_event_randr = -1;
138
139 void
140 _ecore_xcb_randr_init(void)
141 {
142    LOGFN(__FILE__, __LINE__, __FUNCTION__);
143
144 #ifdef ECORE_XCB_RANDR
145    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_randr_id);
146 #endif
147 }
148
149 void
150 _ecore_xcb_randr_finalize(void)
151 {
152 #ifdef ECORE_XCB_RANDR
153    const xcb_query_extension_reply_t *ext_reply;
154 #endif
155
156    LOGFN(__FILE__, __LINE__, __FUNCTION__);
157
158 #ifdef ECORE_XCB_RANDR
159    ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_randr_id);
160    if ((ext_reply) && (ext_reply->present))
161      {
162         xcb_randr_query_version_cookie_t cookie;
163         xcb_randr_query_version_reply_t *reply;
164
165         cookie =
166           xcb_randr_query_version_unchecked(_ecore_xcb_conn,
167                                             XCB_RANDR_MAJOR_VERSION,
168                                             XCB_RANDR_MINOR_VERSION);
169         reply = xcb_randr_query_version_reply(_ecore_xcb_conn, cookie, NULL);
170         if (reply)
171           {
172              if ((reply->major_version >= XCB_RANDR_MAJOR_VERSION) &&
173                  (reply->minor_version >= XCB_RANDR_MINOR_VERSION))
174                _randr_avail = EINA_TRUE;
175
176              _randr_version =
177                ((reply->major_version << 16) | reply->minor_version);
178
179              free(reply);
180           }
181
182         if (_randr_avail)
183           _ecore_xcb_event_randr = ext_reply->first_event;
184      }
185 #endif
186 }
187
188 static Eina_Bool
189 #ifdef ECORE_XCB_RANDR
190 _ecore_xcb_randr_root_validate(Ecore_X_Window root)
191 #else
192 _ecore_xcb_randr_root_validate(Ecore_X_Window root EINA_UNUSED)
193 #endif
194 {
195 #ifdef ECORE_XCB_RANDR
196    Ecore_X_Randr_Screen scr = -1;
197 #endif
198
199    LOGFN(__FILE__, __LINE__, __FUNCTION__);
200
201 #ifdef ECORE_XCB_RANDR
202    if ((root) && RANDR_VALIDATE_ROOT(scr, root))
203      return EINA_TRUE;
204 #endif
205
206    return EINA_FALSE;
207 }
208
209 static int
210 _ecore_xcb_randr_root_to_screen(Ecore_X_Window root)
211 {
212    int count = 0, num = 0;
213
214    CHECK_XCB_CONN;
215
216    count = xcb_setup_roots_length(xcb_get_setup(_ecore_xcb_conn));
217    for (num = 0; num < count; num++)
218      if (_ecore_xcb_window_root_of_screen_get(num) == root)
219        return num;
220
221    return -1;
222 }
223
224 /* public functions */
225
226 /*
227  * @brief Query whether RandR is available or not.
228  *
229  * @return @c EINA_TRUE if extension is available, @c EINA_FALSE otherwise.
230  */
231 EAPI Eina_Bool
232 ecore_x_randr_query(void)
233 {
234    return _randr_avail;
235 }
236
237 /*
238  * @return version of the RandRR extension supported by the server or,
239  * in case RandRR extension is not available, Ecore_X_Randr_Unset (=-1).
240  * bit version information: 31   MAJOR   16 | 15   MINOR   0
241  */
242 EAPI int
243 ecore_x_randr_version_get(void)
244 {
245    return _randr_version;
246 }
247
248 /**
249  * @brief This function returns the current config timestamp from 
250  * XRRScreenConfiguration.
251  * 
252  * @param root root window to query screen configuration from
253  * 
254  * @returns The screen configuration timestamp
255  * 
256  * @since 1.8
257  */
258 EAPI Ecore_X_Time 
259 ecore_x_randr_config_timestamp_get(Ecore_X_Window root)
260 {
261    Ecore_X_Time timestamp = 0;
262
263 #ifdef ECORE_XCB_RANDR
264    xcb_randr_get_screen_info_cookie_t cookie;
265    xcb_randr_get_screen_info_reply_t *reply;
266 #endif
267
268    LOGFN(__FILE__, __LINE__, __FUNCTION__);
269    CHECK_XCB_CONN;
270
271 #ifdef ECORE_XCB_RANDR
272    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
273    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
274    if (reply)
275      {
276         timestamp = (Ecore_X_Time)reply->config_timestamp;
277         free(reply);
278      }
279 #endif
280
281    return timestamp;
282 }
283
284 /*
285  * @param root window which's primary output will be queried
286  */
287 EAPI Ecore_X_Randr_Orientation
288 ecore_x_randr_screen_primary_output_orientations_get(Ecore_X_Window root)
289 {
290    int ret = Ecore_X_Randr_None;
291 #ifdef ECORE_XCB_RANDR
292    xcb_randr_get_screen_info_cookie_t cookie;
293    xcb_randr_get_screen_info_reply_t *reply;
294 #endif
295
296    LOGFN(__FILE__, __LINE__, __FUNCTION__);
297    CHECK_XCB_CONN;
298
299 #ifdef ECORE_XCB_RANDR
300    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
301    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
302    if (reply)
303      {
304         ret = reply->rotations;
305         free(reply);
306      }
307 #endif
308
309    return ret;
310 }
311
312 /*
313  * @param root window which's primary output will be queried
314  * @return the current orientation of the root window's screen primary output
315  */
316 EAPI Ecore_X_Randr_Orientation
317 ecore_x_randr_screen_primary_output_orientation_get(Ecore_X_Window root)
318 {
319    int ret = Ecore_X_Randr_None;
320 #ifdef ECORE_XCB_RANDR
321    xcb_randr_get_screen_info_cookie_t cookie;
322    xcb_randr_get_screen_info_reply_t *reply;
323 #endif
324
325    LOGFN(__FILE__, __LINE__, __FUNCTION__);
326    CHECK_XCB_CONN;
327
328 #ifdef ECORE_XCB_RANDR
329    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
330    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
331    if (reply)
332      {
333         ret = reply->rotation;
334         free(reply);
335      }
336 #endif
337
338    return ret;
339 }
340
341 /*
342  * @brief Sets a given screen's primary output's orientation.
343  *
344  * @param root Window which's screen's primary output will be queried.
345  * @param orientation Orientation which should be set for the root window's
346  * screen primary output.
347  * @return @c EINA_TRUE if the primary output's orientation could be
348  * successfully altered.
349  */
350 EAPI Eina_Bool
351 ecore_x_randr_screen_primary_output_orientation_set(Ecore_X_Window            root,
352                                                     Ecore_X_Randr_Orientation orientation)
353 {
354    int ret = EINA_FALSE;
355 #ifdef ECORE_XCB_RANDR
356    xcb_randr_get_screen_info_cookie_t cookie;
357    xcb_randr_get_screen_info_reply_t *reply;
358 #endif
359
360    LOGFN(__FILE__, __LINE__, __FUNCTION__);
361    CHECK_XCB_CONN;
362
363 #ifdef ECORE_XCB_RANDR
364    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
365    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
366    if (reply)
367      {
368         xcb_randr_set_screen_config_cookie_t scookie;
369         xcb_randr_set_screen_config_reply_t *sreply;
370
371         scookie =
372           xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root,
373                                                 XCB_CURRENT_TIME,
374                                                 reply->config_timestamp,
375                                                 reply->sizeID, orientation,
376                                                 reply->rate);
377         sreply =
378           xcb_randr_set_screen_config_reply(_ecore_xcb_conn, scookie, NULL);
379         if (!sreply)
380           ret = EINA_FALSE;
381         else
382           {
383              ret = (sreply->status == XCB_RANDR_SET_CONFIG_SUCCESS) ?
384                EINA_TRUE : EINA_FALSE;
385              free(sreply);
386           }
387         free(reply);
388      }
389 #endif
390
391    return ret;
392 }
393
394 /*
395  * @brief gets a screen's primary output's possible sizes
396  * @param root window which's primary output will be queried
397  * @param num number of sizes reported as supported by the screen's primary output
398  * @return an array of sizes reported as supported by the screen's primary output or - if query failed - NULL
399  */
400 EAPI Ecore_X_Randr_Screen_Size_MM *
401 ecore_x_randr_screen_primary_output_sizes_get(Ecore_X_Window root,
402                                               int           *num)
403 {
404 #ifdef ECORE_XCB_RANDR
405    xcb_randr_get_screen_info_cookie_t cookie;
406    xcb_randr_get_screen_info_reply_t *reply;
407    Ecore_X_Randr_Screen_Size_MM *ret = NULL;
408 #endif
409
410    LOGFN(__FILE__, __LINE__, __FUNCTION__);
411    CHECK_XCB_CONN;
412
413 #ifdef ECORE_XCB_RANDR
414    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
415    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
416    if (reply)
417      {
418         int len = 0, i = 0;
419         xcb_randr_screen_size_t *sizes;
420
421         len = xcb_randr_get_screen_info_sizes_length(reply);
422         sizes = xcb_randr_get_screen_info_sizes(reply);
423         if ((!sizes) || (len <= 0))
424           {
425              free(reply);
426              return NULL;
427           }
428         if (num) *num = len;
429         ret = calloc(len, sizeof(Ecore_X_Randr_Screen_Size_MM));
430         if (!ret)
431           {
432              free(reply);
433              return NULL;
434           }
435         for (i = 0; i < len; i++)
436           {
437              ret[i].width = sizes[i].width;
438              ret[i].height = sizes[i].height;
439              ret[i].width_mm = sizes[i].mwidth;
440              ret[i].height_mm = sizes[i].mheight;
441           }
442
443         free(reply);
444      }
445
446    return ret;
447 #else
448    return NULL;
449 #endif
450 }
451
452 /*
453  * @brief get the current set size of a given screen's primary output
454  * @param root window which's primary output will be queried
455  * @param w the current size's width
456  * @param h the current size's height
457  * @param w_mm the current size's width in mm
458  * @param h_mm the current size's height in mm
459  * @param size_index of current set size to be used with ecore_x_randr_primary_output_size_set()
460  */
461 EAPI void
462 ecore_x_randr_screen_primary_output_current_size_get(Ecore_X_Window root,
463                                                      int           *w,
464                                                      int           *h,
465                                                      int           *w_mm,
466                                                      int           *h_mm,
467                                                      int           *size_index)
468 {
469 #ifdef ECORE_XCB_RANDR
470    xcb_randr_get_screen_info_cookie_t cookie;
471    xcb_randr_get_screen_info_reply_t *reply;
472 #endif
473
474    LOGFN(__FILE__, __LINE__, __FUNCTION__);
475    CHECK_XCB_CONN;
476
477 #ifdef ECORE_XCB_RANDR
478    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
479    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
480    if (reply)
481      {
482         int len = 0, idx = 0;
483         xcb_randr_screen_size_t *sizes;
484
485         len = xcb_randr_get_screen_info_sizes_length(reply);
486         sizes = xcb_randr_get_screen_info_sizes(reply);
487         if ((!sizes) || (len <= 0))
488           {
489              free(reply);
490              return;
491           }
492         idx = reply->sizeID;
493         if ((idx < len) && (idx >= 0))
494           {
495              if (w) *w = sizes[idx].width;
496              if (h) *h = sizes[idx].height;
497              if (w_mm) *w_mm = sizes[idx].mwidth;
498              if (h_mm) *h_mm = sizes[idx].mheight;
499              if (size_index) *size_index = idx;
500           }
501
502         free(reply);
503      }
504 #endif
505 }
506
507 /*
508  * @brief Sets a given screen's primary output size, but disables all other
509  * outputs at the same time.
510  *
511  * @param root Window which's primary output will be queried.
512  * @param size_index Within the list of sizes reported as supported by the root
513  * window's screen primary output.
514  * @return @c EINA_TRUE on success, @c EINA_FALSE on failure due to e.g.
515  * invalid times.
516  */
517 EAPI Eina_Bool
518 ecore_x_randr_screen_primary_output_size_set(Ecore_X_Window root,
519                                              int            size_index)
520 {
521    Eina_Bool ret = EINA_FALSE;
522 #ifdef ECORE_XCB_RANDR
523    xcb_randr_get_screen_info_cookie_t cookie;
524    xcb_randr_get_screen_info_reply_t *reply;
525 #endif
526
527    LOGFN(__FILE__, __LINE__, __FUNCTION__);
528    CHECK_XCB_CONN;
529
530 #ifdef ECORE_XCB_RANDR
531    if (!((size_index >= 0) && (_ecore_xcb_randr_root_validate(root))))
532      return EINA_FALSE;
533
534    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
535    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
536    if (reply)
537      {
538         int len = 0;
539
540         len = xcb_randr_get_screen_info_sizes_length(reply);
541         if (len <= 0)
542           {
543              free(reply);
544              return EINA_FALSE;
545           }
546         if ((size_index < len) && (size_index >= 0))
547           {
548              xcb_randr_set_screen_config_cookie_t scookie;
549              xcb_randr_set_screen_config_reply_t *sreply;
550
551              scookie =
552                xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root,
553                                                      XCB_CURRENT_TIME,
554                                                      reply->config_timestamp,
555                                                      size_index,
556                                                      reply->rotation,
557                                                      reply->rate);
558              sreply =
559                xcb_randr_set_screen_config_reply(_ecore_xcb_conn,
560                                                  scookie, NULL);
561              if (!sreply)
562                ret = EINA_FALSE;
563              else
564                {
565                   ret = (sreply->status == XCB_RANDR_SET_CONFIG_SUCCESS) ?
566                     EINA_TRUE : EINA_FALSE;
567                   free(sreply);
568                }
569           }
570
571         free(reply);
572      }
573 #endif
574    return ret;
575 }
576
577 /*
578  * @param root window which's primary output will be queried
579  * @return currently used refresh rate or - if request failed or RandRR is not available - 0.0
580  */
581 EAPI Ecore_X_Randr_Refresh_Rate
582 ecore_x_randr_screen_primary_output_current_refresh_rate_get(Ecore_X_Window root)
583 {
584 #ifdef ECORE_XCB_RANDR
585    xcb_randr_get_screen_info_cookie_t cookie;
586    xcb_randr_get_screen_info_reply_t *reply;
587    Ecore_X_Randr_Refresh_Rate ret = 0.0;
588 #endif
589
590    LOGFN(__FILE__, __LINE__, __FUNCTION__);
591    CHECK_XCB_CONN;
592
593 #ifdef ECORE_XCB_RANDR
594    if (!_ecore_xcb_randr_root_validate(root)) return ret;
595
596    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
597    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
598    if (reply)
599      {
600         ret = reply->rate;
601         free(reply);
602      }
603
604    return ret;
605 #else
606    return 0.0;
607 #endif
608 }
609
610 /*
611  * @param root window which's primary output will be queried
612  * @param size_index referencing the size to query valid refresh rates for
613  * @return currently used refresh rate or - if request failed or RandRR is not available - NULL
614  */
615 EAPI Ecore_X_Randr_Refresh_Rate *
616 ecore_x_randr_screen_primary_output_refresh_rates_get(Ecore_X_Window root,
617                                                       int            size_index,
618                                                       int           *num)
619 {
620 #ifdef ECORE_XCB_RANDR
621    xcb_randr_get_screen_info_cookie_t cookie;
622    xcb_randr_get_screen_info_reply_t *reply;
623    Ecore_X_Randr_Refresh_Rate *ret = NULL;
624 #endif
625
626    LOGFN(__FILE__, __LINE__, __FUNCTION__);
627    CHECK_XCB_CONN;
628
629 #ifdef ECORE_XCB_RANDR
630    if (!_ecore_xcb_randr_root_validate(root)) return ret;
631
632    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
633    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
634    if (reply)
635      {
636         int len = 0;
637
638         len = xcb_randr_get_screen_info_rates_length(reply);
639         if (num) *num = len;
640
641         ret = malloc(sizeof(Ecore_X_Randr_Refresh_Rate) * len);
642         if (ret)
643           {
644              xcb_randr_refresh_rates_iterator_t iter;
645              int i = 0;
646
647              iter = xcb_randr_get_screen_info_rates_iterator(reply);
648              while (i++ < size_index)
649                xcb_randr_refresh_rates_next(&iter);
650
651              memcpy(ret, xcb_randr_refresh_rates_rates(iter.data),
652                     sizeof(Ecore_X_Randr_Refresh_Rate) * len);
653           }
654         free(reply);
655      }
656
657    return ret;
658 #else
659    return NULL;
660 #endif
661 }
662
663 /*
664  * @brief Sets the current primary output's refresh rate.
665  *
666  * @param root Window which's primary output will be queried.
667  * @param size_index Referencing the size to be set.
668  * @param rate The refresh rate to be set.
669  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
670  */
671 EAPI Eina_Bool
672 ecore_x_randr_screen_primary_output_refresh_rate_set(Ecore_X_Window             root,
673                                                      int                        size_index,
674                                                      Ecore_X_Randr_Refresh_Rate rate)
675 {
676    Eina_Bool ret = EINA_FALSE;
677 #ifdef ECORE_XCB_RANDR
678    xcb_randr_get_screen_info_cookie_t cookie;
679    xcb_randr_get_screen_info_reply_t *reply;
680 #endif
681
682    LOGFN(__FILE__, __LINE__, __FUNCTION__);
683    CHECK_XCB_CONN;
684
685 #ifdef ECORE_XCB_RANDR
686    if (_randr_version < RANDR_1_1) return EINA_FALSE;
687
688    cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root);
689    reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
690    if (reply)
691      {
692         xcb_randr_set_screen_config_cookie_t scookie;
693         xcb_randr_set_screen_config_reply_t *sreply;
694
695         scookie =
696           xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root,
697                                                 XCB_CURRENT_TIME,
698                                                 reply->config_timestamp,
699                                                 size_index,
700                                                 reply->rotation, rate);
701         sreply =
702           xcb_randr_set_screen_config_reply(_ecore_xcb_conn,
703                                             scookie, NULL);
704         if (!sreply)
705           ret = EINA_FALSE;
706         else
707           {
708              ret = (sreply->status == XCB_RANDR_SET_CONFIG_SUCCESS) ?
709                EINA_TRUE : EINA_FALSE;
710              free(sreply);
711           }
712         free(reply);
713      }
714 #endif
715
716    return ret;
717 }
718
719 /*
720  * @brief Free detailed mode information. The pointer handed in will be set to
721  * @c NULL after freeing the memory.
722  *
723  * @param mode_info The mode information that should be freed.
724  */
725 EAPI void
726 ecore_x_randr_mode_info_free(Ecore_X_Randr_Mode_Info *mode_info)
727 {
728    LOGFN(__FILE__, __LINE__, __FUNCTION__);
729    CHECK_XCB_CONN;
730
731    RANDR_CHECK_1_2_RET();
732
733    if (!mode_info) return;
734
735    if (mode_info->name) free(mode_info->name);
736    free(mode_info);
737 }
738
739 /*
740  * @param root window which's screen should be queried
741  * @return Ecore_X_Randr_Ouptut_Id or - if query failed or none is set - Ecore_X_Randr_None
742  */
743 EAPI Ecore_X_Randr_Output
744 ecore_x_randr_primary_output_get(Ecore_X_Window root)
745 {
746    Ecore_X_Randr_Output ret = Ecore_X_Randr_None;
747 #ifdef ECORE_XCB_RANDR
748    xcb_randr_get_output_primary_cookie_t cookie;
749    xcb_randr_get_output_primary_reply_t *reply;
750 #endif
751
752    LOGFN(__FILE__, __LINE__, __FUNCTION__);
753    CHECK_XCB_CONN;
754
755 #ifdef ECORE_XCB_RANDR
756    RANDR_CHECK_1_3_RET(Ecore_X_Randr_None);
757
758    if (!_ecore_xcb_randr_root_validate(root))
759      return Ecore_X_Randr_None;
760
761    cookie = xcb_randr_get_output_primary_unchecked(_ecore_xcb_conn, root);
762    reply = xcb_randr_get_output_primary_reply(_ecore_xcb_conn, cookie, NULL);
763    if (reply)
764      {
765         ret = reply->output;
766         free(reply);
767      }
768 #endif
769    return ret;
770 }
771
772 /*
773  * @param root window which's screen should be queried
774  * @param output that should be set as given root window's screen primary output
775  */
776 EAPI void
777 ecore_x_randr_primary_output_set(Ecore_X_Window       root,
778                                  Ecore_X_Randr_Output output)
779 {
780    LOGFN(__FILE__, __LINE__, __FUNCTION__);
781    CHECK_XCB_CONN;
782
783 #ifdef ECORE_XCB_RANDR
784    RANDR_CHECK_1_3_RET();
785
786    if ((output) && (_ecore_xcb_randr_root_validate(root)))
787      xcb_randr_set_output_primary(_ecore_xcb_conn, root, output);
788 #endif
789 }
790
791 EAPI Ecore_X_Randr_Mode *
792 ecore_x_randr_output_modes_get(Ecore_X_Window       root,
793                                Ecore_X_Randr_Output output,
794                                int                 *num,
795                                int                 *npreferred)
796 {
797    Ecore_X_Randr_Mode *modes = NULL;
798
799    LOGFN(__FILE__, __LINE__, __FUNCTION__);
800    CHECK_XCB_CONN;
801
802 #ifdef ECORE_XCB_RANDR
803    RANDR_CHECK_1_2_RET(NULL);
804
805    if (_randr_version >= RANDR_1_3)
806      {
807         modes =
808           _ecore_xcb_randr_13_output_modes_get(root, output, num, npreferred);
809      }
810    else if (_randr_version == RANDR_1_2)
811      {
812         modes =
813           _ecore_xcb_randr_12_output_modes_get(root, output, num, npreferred);
814      }
815 #endif
816
817    return modes;
818 }
819
820 EAPI Eina_Bool 
821 ecore_x_randr_output_mode_add(Ecore_X_Randr_Output output, Ecore_X_Randr_Mode mode)
822 {
823    LOGFN(__FILE__, __LINE__, __FUNCTION__);
824    CHECK_XCB_CONN;
825
826 #ifdef ECORE_XCB_RANDR
827    RANDR_CHECK_1_2_RET(EINA_FALSE);
828
829    if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None))
830      return EINA_FALSE;
831
832    xcb_randr_add_output_mode(_ecore_xcb_conn, output, mode);
833    return EINA_TRUE;
834 #endif
835    return EINA_FALSE;
836 }
837
838 /*
839  * @brief get detailed information for a given mode id
840  * @param root window which's screen's ressources are queried
841  * @param mode the XID which identifies the mode of interest
842  * @return mode's detailed information
843  */
844 EAPI Ecore_X_Randr_Mode_Info *
845 ecore_x_randr_mode_info_get(Ecore_X_Window     root,
846                             Ecore_X_Randr_Mode mode)
847 {
848    Ecore_X_Randr_Mode_Info *ret = NULL;
849
850    LOGFN(__FILE__, __LINE__, __FUNCTION__);
851    CHECK_XCB_CONN;
852
853 #ifdef ECORE_XCB_RANDR
854    RANDR_CHECK_1_2_RET(NULL);
855
856    if (!_ecore_xcb_randr_root_validate(root)) return NULL;
857
858    if (_randr_version >= RANDR_1_3)
859      ret = _ecore_xcb_randr_13_mode_info_get(root, mode);
860    else if (_randr_version == RANDR_1_2)
861      ret = _ecore_xcb_randr_12_mode_info_get(root, mode);
862 #endif
863    return ret;
864 }
865
866 /*
867  * @brief add a mode to a display
868  * @param root window to which's screen's ressources are added
869  * @param mode_info
870  * @return Ecore_X_Randr_Mode of the added mode. Ecore_X_Randr_None if mode
871  * adding failed.
872  * @since 1.2.0
873  */
874 EAPI Ecore_X_Randr_Mode 
875 ecore_x_randr_mode_info_add(Ecore_X_Window root, Ecore_X_Randr_Mode_Info *mode_info)
876 {
877    Ecore_X_Randr_Mode mode = Ecore_X_Randr_None;
878 #ifdef ECORE_XCB_RANDR
879    xcb_randr_create_mode_cookie_t cookie;
880    xcb_randr_create_mode_reply_t *reply;
881    xcb_randr_mode_info_t info;
882    int namelen = 0;
883 #endif
884
885    LOGFN(__FILE__, __LINE__, __FUNCTION__);
886    CHECK_XCB_CONN;
887
888 #ifdef ECORE_XCB_RANDR
889    RANDR_CHECK_1_2_RET(EINA_FALSE);
890
891    if (!mode_info) return Ecore_X_Randr_None;
892    if (!_ecore_xcb_randr_root_validate(root)) return Ecore_X_Randr_None;
893
894    namelen = strlen(mode_info->name);
895
896    memset(&info, 0, sizeof(info));
897    info.width = mode_info->width;
898    info.height = mode_info->height;
899    info.dot_clock = mode_info->dotClock;
900    info.hsync_start = mode_info->hSyncStart;
901    info.hsync_end = mode_info->hSyncEnd;
902    info.htotal = mode_info->hTotal;
903    info.hskew = mode_info->hSkew;
904    info.vsync_start = mode_info->vSyncStart;
905    info.vsync_end = mode_info->vSyncEnd;
906    info.vtotal = mode_info->vTotal;
907    info.mode_flags = mode_info->modeFlags;
908    info.name_len = namelen;
909
910    cookie = 
911      xcb_randr_create_mode_unchecked(_ecore_xcb_conn, root, info, 
912                                      namelen, mode_info->name);
913    reply = xcb_randr_create_mode_reply(_ecore_xcb_conn, cookie, NULL);
914    if (reply)
915      {
916         mode = mode_info->xid;
917         free(reply);
918      }
919 #endif
920    return mode;
921 }
922
923 /*
924  * @brief get detailed information for all modes related to a root window's screen
925  * @param root window which's screen's ressources are queried
926  * @param num number of modes returned
927  * @return modes' information
928  */
929 EAPI Ecore_X_Randr_Mode_Info **
930 ecore_x_randr_modes_info_get(Ecore_X_Window root,
931                              int           *num)
932 {
933    Ecore_X_Randr_Mode_Info **ret = NULL;
934
935    LOGFN(__FILE__, __LINE__, __FUNCTION__);
936    CHECK_XCB_CONN;
937
938    if (num) *num = 0;
939
940 #ifdef ECORE_XCB_RANDR
941    RANDR_CHECK_1_2_RET(NULL);
942
943    if (!_ecore_xcb_randr_root_validate(root)) return NULL;
944
945    if (_randr_version >= RANDR_1_3)
946      ret = _ecore_xcb_randr_13_modes_info_get(root, num);
947    else if (_randr_version == RANDR_1_2)
948      ret = _ecore_xcb_randr_12_modes_info_get(root, num);
949 #endif
950    return ret;
951 }
952
953 /**
954  * @brief Gets the width and hight of a given mode.
955  *
956  * @param root Window which's screen's ressources are queried.
957  * @param mode The mode which's size is to be looked up.
958  * @param w Width of given mode in px.
959  * @param h Height of given mode in px.
960  */
961 EAPI void
962 ecore_x_randr_mode_size_get(Ecore_X_Window     root,
963                             Ecore_X_Randr_Mode mode,
964                             int               *w,
965                             int               *h)
966 {
967    LOGFN(__FILE__, __LINE__, __FUNCTION__);
968    CHECK_XCB_CONN;
969
970 #ifdef ECORE_XCB_RANDR
971    RANDR_CHECK_1_2_RET();
972
973    if (mode == Ecore_X_Randr_None) return;
974
975    if (_randr_version >= RANDR_1_3)
976      _ecore_xcb_randr_13_mode_size_get(root, mode, w, h);
977    else if (_randr_version == RANDR_1_2)
978      _ecore_xcb_randr_12_mode_size_get(root, mode, w, h);
979 #endif
980 }
981
982 /**
983  * @brief Gets the EDID information of an attached output if available.
984  * Note that this information is not to be compared using ordinary string
985  * comparison functions, since it includes 0-bytes.
986  *
987  * @param root Window this information should be queried from.
988  * @param output The XID of the output.
989  * @param length Length of the byte-array. If @c NULL, request will fail.
990  * @return EDID information of the output.
991  */
992 EAPI unsigned char *
993 ecore_x_randr_output_edid_get(Ecore_X_Window       root,
994                               Ecore_X_Randr_Output output,
995                               unsigned long       *length)
996 {
997    unsigned char *ret = NULL;
998 #ifdef ECORE_XCB_RANDR
999    xcb_randr_get_output_property_cookie_t cookie;
1000    xcb_randr_get_output_property_reply_t *reply;
1001    Ecore_X_Atom atom;
1002 #endif
1003
1004    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1005    CHECK_XCB_CONN;
1006
1007 #ifdef ECORE_XCB_RANDR
1008    RANDR_CHECK_1_2_RET(NULL);
1009
1010    if ((!length) || (!_ecore_xcb_randr_output_validate(root, output)))
1011      return NULL;
1012
1013    atom = ecore_x_atom_get("EDID");
1014    cookie =
1015      xcb_randr_get_output_property_unchecked(_ecore_xcb_conn, output, atom,
1016                                              XCB_GET_PROPERTY_TYPE_ANY,
1017                                              0, 100, 0, 0);
1018    reply =
1019      xcb_randr_get_output_property_reply(_ecore_xcb_conn, cookie, NULL);
1020    if (reply)
1021      {
1022         if ((reply->type == XCB_ATOM_INTEGER) && (reply->format == 8))
1023           {
1024              if (length) *length = reply->num_items;
1025              if ((ret = malloc(reply->num_items * sizeof(unsigned char))))
1026                {
1027                   memcpy(ret, xcb_randr_get_output_property_data(reply),
1028                          (reply->num_items * sizeof(unsigned char)));
1029                }
1030           }
1031         free(reply);
1032      }
1033 #endif
1034    return ret;
1035 }
1036
1037 /**
1038  * @brief Gets the outputs which might be used simultaneously on the same CRTC.
1039  *
1040  * @param root Window that this information should be queried for.
1041  * @param output The output which's clones we concern.
1042  * @param num Number of possible clones.
1043  * @return The existing outputs, @c NULL otherwise.
1044  */
1045 EAPI Ecore_X_Randr_Output *
1046 ecore_x_randr_output_clones_get(Ecore_X_Window       root,
1047                                 Ecore_X_Randr_Output output,
1048                                 int                 *num)
1049 {
1050    Ecore_X_Randr_Output *outputs = NULL;
1051
1052    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1053    CHECK_XCB_CONN;
1054
1055 #ifdef ECORE_XCB_RANDR
1056    RANDR_CHECK_1_2_RET(NULL);
1057
1058    if (output == Ecore_X_Randr_None) return NULL;
1059
1060    if (_randr_version >= RANDR_1_3)
1061      outputs = _ecore_xcb_randr_13_output_clones_get(root, output, num);
1062    else if (_randr_version == RANDR_1_2)
1063      outputs = _ecore_xcb_randr_12_output_clones_get(root, output, num);
1064 #endif
1065    return outputs;
1066 }
1067
1068 EAPI Ecore_X_Randr_Crtc *
1069 ecore_x_randr_output_possible_crtcs_get(Ecore_X_Window       root,
1070                                         Ecore_X_Randr_Output output,
1071                                         int                 *num)
1072 {
1073    Ecore_X_Randr_Crtc *crtcs = NULL;
1074
1075    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1076    CHECK_XCB_CONN;
1077
1078 #ifdef ECORE_XCB_RANDR
1079    RANDR_CHECK_1_2_RET(NULL);
1080
1081    if (output == Ecore_X_Randr_None) return NULL;
1082
1083    if (_randr_version >= RANDR_1_3)
1084      crtcs = _ecore_xcb_randr_13_output_possible_crtcs_get(root, output, num);
1085    else if (_randr_version == RANDR_1_2)
1086      crtcs = _ecore_xcb_randr_12_output_possible_crtcs_get(root, output, num);
1087 #endif
1088    return crtcs;
1089 }
1090
1091 /**
1092  * @brief gets the given output's name as reported by X
1093  * @param root the window which's screen will be queried
1094  * @param output The output name given to be reported.
1095  * @param len length of returned c-string.
1096  * @return name of the output as reported by X
1097  */
1098 EAPI char *
1099 ecore_x_randr_output_name_get(Ecore_X_Window       root,
1100                               Ecore_X_Randr_Output output,
1101                               int                 *len)
1102 {
1103    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1104    CHECK_XCB_CONN;
1105
1106 #ifdef ECORE_XCB_RANDR
1107    RANDR_CHECK_1_2_RET(NULL);
1108
1109    if (output == Ecore_X_Randr_None) return NULL;
1110
1111    if (_randr_version >= RANDR_1_3)
1112      return _ecore_xcb_randr_13_output_name_get(root, output, len);
1113    else if (_randr_version == RANDR_1_2)
1114      return _ecore_xcb_randr_12_output_name_get(root, output, len);
1115 #endif
1116
1117    return NULL;
1118 }
1119
1120 EAPI Ecore_X_Randr_Connection_Status
1121 ecore_x_randr_output_connection_status_get(Ecore_X_Window       root,
1122                                            Ecore_X_Randr_Output output)
1123 {
1124    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1125    CHECK_XCB_CONN;
1126
1127 #ifdef ECORE_XCB_RANDR
1128    RANDR_CHECK_1_2_RET(ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN);
1129
1130    if (output == Ecore_X_Randr_None)
1131      return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
1132
1133    if (_randr_version >= RANDR_1_3)
1134      return _ecore_xcb_randr_13_output_connection_status_get(root, output);
1135    else if (_randr_version == RANDR_1_2)
1136      return _ecore_xcb_randr_12_output_connection_status_get(root, output);
1137 #endif
1138
1139    return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
1140 }
1141
1142 EAPI Ecore_X_Randr_Output *
1143 ecore_x_randr_outputs_get(Ecore_X_Window root,
1144                           int           *num)
1145 {
1146    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1147    CHECK_XCB_CONN;
1148
1149 #ifdef ECORE_XCB_RANDR
1150    RANDR_CHECK_1_2_RET(NULL);
1151
1152    if (_randr_version >= RANDR_1_3)
1153      return _ecore_xcb_randr_13_outputs_get(root, num);
1154    else if (_randr_version == RANDR_1_2)
1155      return _ecore_xcb_randr_12_outputs_get(root, num);
1156 #endif
1157
1158    return NULL;
1159 }
1160
1161 EAPI Ecore_X_Randr_Crtc
1162 ecore_x_randr_output_crtc_get(Ecore_X_Window       root,
1163                               Ecore_X_Randr_Output output)
1164 {
1165    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1166    CHECK_XCB_CONN;
1167
1168 #ifdef ECORE_XCB_RANDR
1169    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
1170
1171    if (output == Ecore_X_Randr_None) return Ecore_X_Randr_None;
1172
1173    if (_randr_version >= RANDR_1_3)
1174      return _ecore_xcb_randr_13_output_crtc_get(root, output);
1175    else if (_randr_version == RANDR_1_2)
1176      return _ecore_xcb_randr_12_output_crtc_get(root, output);
1177 #endif
1178
1179    return Ecore_X_Randr_None;
1180 }
1181
1182 EAPI Eina_Bool
1183 ecore_x_randr_output_crtc_set(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Output output EINA_UNUSED, const Ecore_X_Randr_Crtc crtc EINA_UNUSED)
1184 {
1185    /* TODO */
1186    return EINA_FALSE;
1187 }
1188
1189 EAPI void 
1190 ecore_x_randr_output_size_mm_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *w_mm, int *h_mm)
1191 {
1192 #ifdef ECORE_XCB_RANDR
1193    xcb_randr_get_output_info_cookie_t ocookie;
1194    xcb_randr_get_output_info_reply_t *oreply;
1195    xcb_timestamp_t timestamp = 0;
1196 #endif
1197
1198    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1199    CHECK_XCB_CONN;
1200
1201    if (w_mm) *w_mm = 0;
1202    if (h_mm) *h_mm = 0;
1203
1204 #ifdef ECORE_XCB_RANDR
1205    RANDR_CHECK_1_2_RET();
1206
1207    if ((output != Ecore_X_Randr_None) && (_randr_version >= RANDR_1_3))
1208      {
1209         xcb_randr_get_screen_resources_current_reply_t *reply;
1210
1211         reply = _ecore_xcb_randr_13_get_resources(root);
1212         timestamp = reply->config_timestamp;
1213         free(reply);
1214      }
1215    else if ((output != Ecore_X_Randr_None) && (_randr_version == RANDR_1_2))
1216      {
1217         xcb_randr_get_screen_resources_reply_t *reply;
1218
1219         reply = _ecore_xcb_randr_12_get_resources(root);
1220         timestamp = reply->config_timestamp;
1221         free(reply);
1222      }
1223
1224    ocookie =
1225      xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, timestamp);
1226    oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, ocookie, NULL);
1227    if (oreply)
1228      {
1229         if (w_mm) *w_mm = oreply->mm_width;
1230         if (h_mm) *h_mm = oreply->mm_height;
1231         free(oreply);
1232      }
1233 #endif
1234 }
1235
1236 /**
1237  * @brief Sets the demanded parameters for a given CRTC. Note that the CRTC is
1238  * auto enabled in it's preferred mode, when it was disabled before.
1239  *
1240  * @param root The root window which's default display will be queried.
1241  * @param crtc The CRTC which's configuration should be altered.
1242  * @param outputs An array of outputs, that should display this CRTC's content.
1243  * @param noutputs Number of outputs in the array of outputs. If set to
1244  * Ecore_X_Randr_Unset, current outputs and number of outputs will be used. If
1245  * set to Ecore_X_Randr_None, CRTC will be disabled.
1246  * @param x New x coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current x
1247  * coordinate will be assumed.
1248  * @param y New y coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current y
1249  * coordinate will be assumed.
1250  * @param mode The new mode to be set. If Ecore_X_Randr_None is passed, the
1251  * CRTC will be disabled. If Ecore_X_Randr_Unset is passed, the current mode is
1252  * assumed.
1253  * @param orientation The new orientation to be set. If Ecore_X_Randr_Unset is
1254  * used, the current mode is assumed.
1255  * @return @c EINA_TRUE if the configuration alteration was successful,
1256  * @c EINA_FALSE otherwise.
1257  */
1258 EAPI Eina_Bool
1259 ecore_x_randr_crtc_settings_set(Ecore_X_Window            root,
1260                                 Ecore_X_Randr_Crtc        crtc,
1261                                 Ecore_X_Randr_Output     *outputs,
1262                                 int                       noutputs,
1263                                 int                       x,
1264                                 int                       y,
1265                                 Ecore_X_Randr_Mode        mode,
1266                                 Ecore_X_Randr_Orientation orientation)
1267 {
1268    Eina_Bool ret = EINA_FALSE;
1269 #ifdef ECORE_XCB_RANDR
1270    xcb_timestamp_t stamp = 0;
1271    xcb_randr_get_crtc_info_cookie_t ccookie;
1272    xcb_randr_get_crtc_info_reply_t *creply;
1273 #endif
1274
1275    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1276    CHECK_XCB_CONN;
1277
1278 #ifdef ECORE_XCB_RANDR
1279    RANDR_CHECK_1_2_RET(EINA_FALSE);
1280
1281    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret;
1282
1283    if (_randr_version >= RANDR_1_3)
1284      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
1285    else if (_randr_version == RANDR_1_2)
1286      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
1287
1288    ccookie =
1289      xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp);
1290    creply =
1291      xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ccookie, NULL);
1292    if (creply)
1293      {
1294         xcb_randr_set_crtc_config_cookie_t scookie;
1295         xcb_randr_set_crtc_config_reply_t *sreply;
1296
1297         if ((mode == Ecore_X_Randr_None) ||
1298             (noutputs == Ecore_X_Randr_None))
1299           {
1300              outputs = NULL;
1301              noutputs = 0;
1302           }
1303         else if (noutputs == (int)Ecore_X_Randr_Unset)
1304           {
1305              outputs = xcb_randr_get_crtc_info_outputs(creply);
1306              noutputs = creply->num_outputs;
1307           }
1308         if ((int)mode == Ecore_X_Randr_Unset) mode = creply->mode;
1309         if (x < 0) x = creply->x;
1310         if (y < 0) y = creply->y;
1311         if ((int)orientation == Ecore_X_Randr_Unset)
1312           orientation = creply->rotation;
1313
1314         scookie =
1315           xcb_randr_set_crtc_config_unchecked(_ecore_xcb_conn,
1316                                               crtc, XCB_CURRENT_TIME, stamp,
1317                                               x, y, mode, orientation,
1318                                               noutputs, outputs);
1319         sreply =
1320           xcb_randr_set_crtc_config_reply(_ecore_xcb_conn, scookie, NULL);
1321         if (sreply)
1322           {
1323              ret = (sreply->status == XCB_RANDR_SET_CONFIG_SUCCESS) ?
1324                EINA_TRUE : EINA_FALSE;
1325              free(sreply);
1326           }
1327         free(creply);
1328      }
1329 #endif
1330
1331    return ret;
1332 }
1333
1334 /**
1335  * @brief Sets a mode for a CRTC and the outputs attached to it.
1336  *
1337  * @param root The window's screen to be queried
1338  * @param crtc The CRTC which shall be set
1339  * @param outputs Array of outputs which have to be compatible with the mode. If
1340  * @c NULL CRTC will be disabled.
1341  * @param noutputs Number of outputs in array to be used. Use
1342  * Ecore_X_Randr_Unset (or @c -1) to use currently used outputs.
1343  * @param mode XID of the mode to be set. If set to @c 0 the CRTC will be
1344  * disabled. If set to @c -1 the call will fail.
1345  * @return @c EINA_TRUE if mode setting was successful, @c EINA_FALSE
1346  * otherwise.
1347  */
1348 EAPI Eina_Bool
1349 ecore_x_randr_crtc_mode_set(Ecore_X_Window        root,
1350                             Ecore_X_Randr_Crtc    crtc,
1351                             Ecore_X_Randr_Output *outputs,
1352                             int                   noutputs,
1353                             Ecore_X_Randr_Mode    mode)
1354 {
1355    Eina_Bool ret = EINA_FALSE;
1356
1357    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1358    CHECK_XCB_CONN;
1359
1360 #ifdef ECORE_XCB_RANDR
1361    RANDR_CHECK_1_2_RET(EINA_FALSE);
1362
1363    if ((int)mode == Ecore_X_Randr_Unset) return ret;
1364    ret =
1365      ecore_x_randr_crtc_settings_set(root, crtc, outputs, noutputs,
1366                                      Ecore_X_Randr_Unset, Ecore_X_Randr_Unset,
1367                                      mode, Ecore_X_Randr_Unset);
1368 #endif
1369
1370    return ret;
1371 }
1372
1373 /**
1374  * @brief Get the current set mode of a given CRTC
1375  * @param root the window's screen to be queried
1376  * @param crtc the CRTC which's should be queried
1377  * @return currently set mode or - in case parameters are invalid -
1378  * Ecore_X_Randr_Unset
1379  */
1380 EAPI Ecore_X_Randr_Mode
1381 ecore_x_randr_crtc_mode_get(Ecore_X_Window     root,
1382                             Ecore_X_Randr_Crtc crtc)
1383 {
1384    Ecore_X_Randr_Mode ret = Ecore_X_Randr_Unset;
1385 #ifdef ECORE_XCB_RANDR
1386    xcb_timestamp_t stamp = 0;
1387    xcb_randr_get_crtc_info_cookie_t ocookie;
1388    xcb_randr_get_crtc_info_reply_t *oreply;
1389 #endif
1390
1391    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1392    CHECK_XCB_CONN;
1393
1394 #ifdef ECORE_XCB_RANDR
1395    RANDR_CHECK_1_2_RET(Ecore_X_Randr_Unset);
1396
1397    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret;
1398
1399    if (_randr_version >= RANDR_1_3)
1400      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
1401    else if (_randr_version == RANDR_1_2)
1402      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
1403
1404    ocookie =
1405      xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp);
1406    oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL);
1407    if (oreply)
1408      {
1409         ret = oreply->mode;
1410         free(oreply);
1411      }
1412 #endif
1413
1414    return ret;
1415 }
1416
1417 EAPI Ecore_X_Randr_Orientation
1418 ecore_x_randr_crtc_orientation_get(Ecore_X_Window     root,
1419                                    Ecore_X_Randr_Crtc crtc)
1420 {
1421    Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None;
1422 #ifdef ECORE_XCB_RANDR
1423    xcb_timestamp_t stamp = 0;
1424    xcb_randr_get_crtc_info_cookie_t ocookie;
1425    xcb_randr_get_crtc_info_reply_t *oreply;
1426 #endif
1427
1428    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1429    CHECK_XCB_CONN;
1430
1431 #ifdef ECORE_XCB_RANDR
1432    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
1433
1434    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret;
1435
1436    if (_randr_version >= RANDR_1_3)
1437      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
1438    else if (_randr_version == RANDR_1_2)
1439      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
1440
1441    ocookie =
1442      xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp);
1443    oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL);
1444    if (oreply)
1445      {
1446         ret = oreply->rotation;
1447         free(oreply);
1448      }
1449 #endif
1450
1451    return ret;
1452 }
1453
1454 EAPI Eina_Bool
1455 ecore_x_randr_crtc_orientation_set(Ecore_X_Window            root,
1456                                    Ecore_X_Randr_Crtc        crtc,
1457                                    Ecore_X_Randr_Orientation orientation)
1458 {
1459    Eina_Bool ret = EINA_FALSE;
1460
1461    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1462    CHECK_XCB_CONN;
1463
1464 #ifdef ECORE_XCB_RANDR
1465    RANDR_CHECK_1_2_RET(EINA_FALSE);
1466
1467    if (orientation != Ecore_X_Randr_None)
1468      {
1469         ret =
1470           ecore_x_randr_crtc_settings_set(root, crtc, NULL,
1471                                           Ecore_X_Randr_Unset, Ecore_X_Randr_Unset,
1472                                           Ecore_X_Randr_Unset, Ecore_X_Randr_Unset,
1473                                           orientation);
1474      }
1475 #endif
1476    return ret;
1477 }
1478
1479 EAPI Ecore_X_Randr_Orientation
1480 ecore_x_randr_crtc_orientations_get(Ecore_X_Window     root,
1481                                     Ecore_X_Randr_Crtc crtc)
1482 {
1483    Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None;
1484 #ifdef ECORE_XCB_RANDR
1485    xcb_timestamp_t stamp = 0;
1486    xcb_randr_get_crtc_info_cookie_t ocookie;
1487    xcb_randr_get_crtc_info_reply_t *oreply;
1488 #endif
1489
1490    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1491    CHECK_XCB_CONN;
1492
1493 #ifdef ECORE_XCB_RANDR
1494    RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
1495
1496    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret;
1497
1498    if (_randr_version >= RANDR_1_3)
1499      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
1500    else if (_randr_version == RANDR_1_2)
1501      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
1502
1503    ocookie =
1504      xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp);
1505    oreply =
1506      xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL);
1507    if (oreply)
1508      {
1509         ret = oreply->rotations;
1510         free(oreply);
1511      }
1512 #endif
1513
1514    return ret;
1515 }
1516
1517 /*
1518  * @brief get a CRTC's possible outputs.
1519  * @param root the root window which's screen will be queried
1520  * @param num number of possible outputs referenced by given CRTC
1521  */
1522 EAPI Ecore_X_Randr_Output *
1523 ecore_x_randr_crtc_possible_outputs_get(Ecore_X_Window     root,
1524                                         Ecore_X_Randr_Crtc crtc,
1525                                         int               *num)
1526 {
1527    Ecore_X_Randr_Output *ret = NULL;
1528 #ifdef ECORE_XCB_RANDR
1529    xcb_timestamp_t stamp = 0;
1530    xcb_randr_get_crtc_info_cookie_t ocookie;
1531    xcb_randr_get_crtc_info_reply_t *oreply;
1532 #endif
1533
1534    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1535    CHECK_XCB_CONN;
1536
1537 #ifdef ECORE_XCB_RANDR
1538    RANDR_CHECK_1_2_RET(NULL);
1539
1540    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret;
1541
1542    if (_randr_version >= RANDR_1_3)
1543      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
1544    else if (_randr_version == RANDR_1_2)
1545      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
1546
1547    ocookie =
1548      xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp);
1549    oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL);
1550    if (oreply)
1551      {
1552         if (num) *num = oreply->num_possible_outputs;
1553         ret = malloc(sizeof(Ecore_X_Randr_Output) *
1554                      oreply->num_possible_outputs);
1555         if (ret)
1556           {
1557              memcpy(ret, xcb_randr_get_crtc_info_possible(oreply),
1558                     sizeof(Ecore_X_Randr_Output) *
1559                     oreply->num_possible_outputs);
1560           }
1561         free(oreply);
1562      }
1563 #endif
1564
1565    return ret;
1566 }
1567
1568 /*
1569  * @brief get all known CRTCs related to a root window's screen
1570  * @param root window which's screen's ressources are queried
1571  * @param num number of CRTCs returned
1572  * @return CRTC IDs
1573  */
1574 EAPI Ecore_X_Randr_Crtc *
1575 ecore_x_randr_crtcs_get(Ecore_X_Window root,
1576                         int           *num)
1577 {
1578    Ecore_X_Randr_Crtc *ret = NULL;
1579
1580    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1581    CHECK_XCB_CONN;
1582
1583 #ifdef ECORE_XCB_RANDR
1584    RANDR_CHECK_1_2_RET(NULL);
1585
1586    if (_randr_version >= RANDR_1_3)
1587      {
1588         xcb_randr_get_screen_resources_current_reply_t *reply;
1589
1590         reply = _ecore_xcb_randr_13_get_resources(root);
1591         if (reply)
1592           {
1593              if (num) *num = reply->num_crtcs;
1594              ret = malloc(sizeof(Ecore_X_Randr_Crtc) * reply->num_crtcs);
1595              if (ret)
1596                memcpy(ret, xcb_randr_get_screen_resources_current_crtcs(reply),
1597                       sizeof(Ecore_X_Randr_Crtc) * reply->num_crtcs);
1598              free(reply);
1599           }
1600      }
1601    else if (_randr_version == RANDR_1_2)
1602      {
1603         xcb_randr_get_screen_resources_reply_t *reply;
1604
1605         reply = _ecore_xcb_randr_12_get_resources(root);
1606         if (reply)
1607           {
1608              if (num) *num = reply->num_crtcs;
1609              ret = malloc(sizeof(Ecore_X_Randr_Crtc) * reply->num_crtcs);
1610              if (ret)
1611                memcpy(ret, xcb_randr_get_screen_resources_crtcs(reply),
1612                       sizeof(Ecore_X_Randr_Crtc) * reply->num_crtcs);
1613              free(reply);
1614           }
1615      }
1616 #endif
1617
1618    return ret;
1619 }
1620
1621 /*
1622  * @deprecated bad naming. Use ecore_x_randr_window_crtcs_get instead.
1623  * @brief Get the CRTCs, which display a certain window.
1624  *
1625  * @param window Window the displaying CRTCs shall be found for.
1626  * @param num The number of CRTCs displaying the window.
1627  * @return Array of CRTCs that display a certain window. @c NULL if no CRTCs
1628  * was found that displays the specified window.
1629  */
1630 EAPI Ecore_X_Randr_Crtc *
1631 ecore_x_randr_current_crtc_get(Ecore_X_Window window,
1632                                  int           *num)
1633 {
1634    return ecore_x_randr_window_crtcs_get(window, num);
1635 }
1636
1637 /*
1638  * @brief Get the CRTCs, which display a certain window.
1639  *
1640  * @param window Window the displaying crtcs shall be found for.
1641  * @param num The number of crtcs displaying the window.
1642  * @return Array of crtcs that display a certain window. @c NULL if no crtcs
1643  * was found that displays the specified window.
1644  * @since 1.2.0
1645  */
1646 EAPI Ecore_X_Randr_Crtc *
1647 ecore_x_randr_window_crtcs_get(Ecore_X_Window window,
1648                                int *num)
1649 {
1650 #ifdef ECORE_XCB_RANDR
1651    Ecore_X_Window root;
1652    Eina_Rectangle w_geo, c_geo;
1653    Ecore_X_Randr_Crtc *crtcs, *ret = NULL;
1654    Ecore_X_Randr_Mode mode;
1655    int ncrtcs, i, nret = 0;
1656    xcb_translate_coordinates_cookie_t cookie;
1657    xcb_translate_coordinates_reply_t *trans;
1658 #endif
1659
1660    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1661    CHECK_XCB_CONN;
1662
1663 #ifdef ECORE_XCB_RANDR
1664    RANDR_CHECK_1_2_RET(NULL);
1665
1666    ecore_x_window_geometry_get(window, &w_geo.x, &w_geo.y, &w_geo.w, &w_geo.h);
1667
1668    root = ecore_x_window_root_get(window);
1669    crtcs = ecore_x_randr_crtcs_get(root, &ncrtcs);
1670    if (!crtcs) goto _ecore_x_randr_window_crtcs_get_fail;
1671
1672    /* now get window RELATIVE to root window - thats what matters. */
1673    cookie = xcb_translate_coordinates(_ecore_xcb_conn, window, root, 0, 0);
1674    trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL);
1675    w_geo.x = trans->dst_x;
1676    w_geo.y = trans->dst_y;
1677    free(trans);
1678
1679    ret = calloc(1, ncrtcs * sizeof(Ecore_X_Randr_Crtc));
1680    if (!ret)
1681      {
1682         free(crtcs);
1683         goto _ecore_x_randr_window_crtcs_get_fail;
1684      }
1685    for (i = 0, nret = 0; i < ncrtcs; i++)
1686      {
1687         /* if crtc is not enabled, don't bother about it any further */
1688          mode = ecore_x_randr_crtc_mode_get(root, crtcs[i]);
1689          if (mode == Ecore_X_Randr_None) continue;
1690
1691          ecore_x_randr_crtc_geometry_get(root, crtcs[i], &c_geo.x, &c_geo.y,
1692                                          &c_geo.w, &c_geo.h);
1693          if (eina_rectangles_intersect(&w_geo, &c_geo))
1694            {
1695               ret[nret] = crtcs[i];
1696               nret++;
1697            }
1698      }
1699    free(crtcs);
1700
1701    if (num) *num = nret;
1702    return ret;
1703
1704 _ecore_x_randr_window_crtcs_get_fail:
1705 #endif
1706    if (num) *num = 0;
1707    return NULL;
1708 }
1709
1710 /*
1711  * @brief get a CRTC's outputs.
1712  * @param root the root window which's screen will be queried
1713  * @param num number of outputs referenced by given CRTC
1714  */
1715 EAPI Ecore_X_Randr_Output *
1716 ecore_x_randr_crtc_outputs_get(Ecore_X_Window     root,
1717                                Ecore_X_Randr_Crtc crtc,
1718                                int               *num)
1719 {
1720    Ecore_X_Randr_Output *ret = NULL;
1721 #ifdef ECORE_XCB_RANDR
1722    xcb_timestamp_t stamp = 0;
1723    xcb_randr_get_crtc_info_cookie_t ocookie;
1724    xcb_randr_get_crtc_info_reply_t *oreply;
1725 #endif
1726
1727    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1728    CHECK_XCB_CONN;
1729
1730 #ifdef ECORE_XCB_RANDR
1731    RANDR_CHECK_1_2_RET(NULL);
1732
1733    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret;
1734
1735    if (_randr_version >= RANDR_1_3)
1736      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
1737    else if (_randr_version == RANDR_1_2)
1738      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
1739
1740    ocookie =
1741      xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp);
1742    oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL);
1743    if (oreply)
1744      {
1745         if (num) *num = oreply->num_outputs;
1746         ret = malloc(sizeof(Ecore_X_Randr_Output) * oreply->num_outputs);
1747         if (ret)
1748           memcpy(ret, xcb_randr_get_crtc_info_outputs(oreply),
1749                  sizeof(Ecore_X_Randr_Output) * oreply->num_outputs);
1750         free(oreply);
1751      }
1752 #endif
1753
1754    return ret;
1755 }
1756
1757 EAPI void
1758 ecore_x_randr_crtc_geometry_get(Ecore_X_Window     root,
1759                                 Ecore_X_Randr_Crtc crtc,
1760                                 int               *x,
1761                                 int               *y,
1762                                 int               *w,
1763                                 int               *h)
1764 {
1765 #ifdef ECORE_XCB_RANDR
1766    xcb_timestamp_t stamp = 0;
1767    xcb_randr_get_crtc_info_cookie_t ocookie;
1768    xcb_randr_get_crtc_info_reply_t *oreply;
1769 #endif
1770
1771    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1772    CHECK_XCB_CONN;
1773
1774 #ifdef ECORE_XCB_RANDR
1775    RANDR_CHECK_1_2_RET();
1776
1777    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return;
1778
1779    if (_randr_version >= RANDR_1_3)
1780      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
1781    else if (_randr_version == RANDR_1_2)
1782      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
1783
1784    ocookie =
1785      xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp);
1786    oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL);
1787    if (oreply)
1788      {
1789         if (x) *x = oreply->x;
1790         if (y) *y = oreply->y;
1791         if (w) *w = oreply->width;
1792         if (h) *h = oreply->height;
1793         free(oreply);
1794      }
1795 #endif
1796 }
1797
1798 /**
1799  * @brief Sets a CRTC relative to another one.
1800  *
1801  * @param root The window on which CRTC's position will be set.
1802  * @param crtc_r1 The CRTC to be positioned.
1803  * @param crtc_r2 The CRTC the position should be relative to.
1804  * @param policy The relation between the crtcs.
1805  * @param alignment In case CRTCs size differ, aligns CRTC1 accordingly at
1806  * CRTC2's borders.
1807  * @return @c EINA_TRUE if crtc could be successfully positioned, @c EINA_FALSE
1808  * if repositioning failed or if position of new crtc would be out of given
1809  * screen's min/max bounds.
1810  */
1811 EAPI Eina_Bool
1812 ecore_x_randr_crtc_pos_relative_set(Ecore_X_Window                   root,
1813                                     Ecore_X_Randr_Crtc               crtc_r1,
1814                                     Ecore_X_Randr_Crtc               crtc_r2,
1815                                     Ecore_X_Randr_Output_Policy      policy,
1816                                     Ecore_X_Randr_Relative_Alignment alignment)
1817 {
1818 #ifdef ECORE_XCB_RANDR
1819    Eina_Rectangle r1, r2;
1820    int w_max = 0, h_max = 0, cw = 0, ch = 0, xn = -1, yn = -1;
1821 #endif
1822
1823    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1824    CHECK_XCB_CONN;
1825
1826 #ifdef ECORE_XCB_RANDR
1827    RANDR_CHECK_1_2_RET(EINA_FALSE);
1828
1829    if ((ecore_x_randr_crtc_mode_get(root, crtc_r1) == 0) ||
1830        (ecore_x_randr_crtc_mode_get(root, crtc_r2) == 0))
1831      return EINA_FALSE;
1832
1833    if ((!_ecore_xcb_randr_crtc_validate(root, crtc_r1) ||
1834         (!(crtc_r1 != crtc_r2) && (!_ecore_xcb_randr_crtc_validate(root, crtc_r2)))))
1835      return EINA_FALSE;
1836
1837    ecore_x_randr_crtc_geometry_get(root, crtc_r1, &r1.x, &r1.y, &r1.w, &r1.h);
1838    ecore_x_randr_crtc_geometry_get(root, crtc_r2, &r2.x, &r2.y, &r2.w, &r2.h);
1839    ecore_x_randr_screen_size_range_get(root, NULL, NULL, &w_max, &h_max);
1840    ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
1841
1842    switch (policy)
1843      {
1844       case ECORE_X_RANDR_OUTPUT_POLICY_RIGHT:
1845         xn = (r2.x + r2.w);
1846         if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE)
1847           yn = -1;
1848         else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL)
1849           yn = ((int)(((double)r2.h / 2.0) + (double)r2.y - ((double)r1.h / 2.0)));
1850         else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR)
1851           yn = ((int)((double)ch / 2.0) - ((double)r1.h / 2.0));
1852         break;
1853
1854       case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
1855         xn = (r2.x - r1.w);
1856         if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE)
1857           yn = -1;
1858         else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL)
1859           yn = ((int)(((double)r2.h / 2.0) + (double)r2.y - ((double)r1.h / 2.0)));
1860         else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR)
1861           yn = ((int)((double)ch / 2.0) - ((double)r1.h / 2.0));
1862         break;
1863
1864       case ECORE_X_RANDR_OUTPUT_POLICY_BELOW:
1865         yn = (r2.y + r2.h);
1866         if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE)
1867           xn = -1;
1868         else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL)
1869           xn = ((int)((((double)r2.x + (double)r2.w) / 2.0) - ((double)r1.w / 2.0)));
1870         else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR)
1871           xn = ((int)((double)cw / 2.0));
1872         break;
1873
1874       case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
1875         yn = (r2.y - r1.h);
1876         if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE)
1877           xn = -1;
1878         else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL)
1879           xn = ((int)((((double)r2.x + (double)r2.w) / 2.0) - ((double)r1.w / 2.0)));
1880         else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR)
1881           xn = ((int)((double)cw / 2.0));
1882         break;
1883
1884       case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
1885         return ecore_x_randr_crtc_pos_set(root, crtc_r1, r2.x, r2.y);
1886         break;
1887
1888       case ECORE_X_RANDR_OUTPUT_POLICY_NONE:
1889         break;
1890       default:
1891         return EINA_FALSE;
1892      }
1893
1894    if ((xn == r1.x) && (yn == r1.x)) return EINA_TRUE;
1895    if (((yn + r1.h) > h_max) || ((xn + r1.w) > w_max))
1896      return EINA_FALSE;
1897
1898    return ecore_x_randr_crtc_pos_set(root, crtc_r1, xn, yn);
1899 #endif
1900
1901    return EINA_FALSE;
1902 }
1903
1904 EAPI Eina_Bool
1905 ecore_x_randr_move_all_crtcs_but(Ecore_X_Window            root,
1906                                  const Ecore_X_Randr_Crtc *not_moved,
1907                                  int                       num,
1908                                  int                       dx,
1909                                  int                       dy)
1910 {
1911    Eina_Bool ret = EINA_FALSE;
1912 #ifdef ECORE_XCB_RANDR
1913    Ecore_X_Randr_Crtc *crtcs = NULL, *move = NULL;
1914    int i = 0, j = 0, k = 0, n = 0, total = 0;
1915 #endif
1916
1917    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1918    CHECK_XCB_CONN;
1919
1920 #ifdef ECORE_XCB_RANDR
1921    if ((num <= 0) || (!not_moved) || (!_ecore_xcb_randr_root_validate(root)))
1922      return EINA_FALSE;
1923
1924    crtcs = ecore_x_randr_crtcs_get(root, &total);
1925    n = (total - num);
1926    move = malloc(sizeof(Ecore_X_Randr_Crtc) * n);
1927    if (move)
1928      {
1929         for (i = 0, k = 0; (i < total) && (k < n); i++)
1930           {
1931              for (j = 0; j < num; j++)
1932                if (crtcs[i] == not_moved[j]) break;
1933              if (j == num)
1934                move[k++] = crtcs[i];
1935           }
1936         ret = ecore_x_randr_move_crtcs(root, move, n, dx, dy);
1937         free(move);
1938         free(crtcs);
1939      }
1940 #endif
1941
1942    return ret;
1943 }
1944
1945 EAPI void
1946 ecore_x_randr_crtc_pos_get(Ecore_X_Window     root,
1947                            Ecore_X_Randr_Crtc crtc,
1948                            int               *x,
1949                            int               *y)
1950 {
1951    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1952    CHECK_XCB_CONN;
1953
1954 #ifdef ECORE_XCB_RANDR
1955    RANDR_CHECK_1_2_RET();
1956
1957    ecore_x_randr_crtc_geometry_get(root, crtc, x, y, NULL, NULL);
1958 #endif
1959 }
1960
1961 /*
1962  * @brief Sets the position of given CRTC within root window's screen.
1963  *
1964  * @param root The window's screen to be queried.
1965  * @param crtc The CRTC which's position within the mentioned screen is to be
1966  * altered.
1967  * @param x Position on the x-axis (0 == left) of the screen. if x < 0 current
1968  * value will be kept.
1969  * @param y Position on the y-ayis (0 == top) of the screen. if y < 0, current
1970  * value will be kept.
1971  * @return @c EINA_TRUE if position could be successfully be altered.
1972  */
1973 EAPI Eina_Bool
1974 ecore_x_randr_crtc_pos_set(Ecore_X_Window     root,
1975                            Ecore_X_Randr_Crtc crtc,
1976                            int                x,
1977                            int                y)
1978 {
1979    Eina_Bool ret = EINA_FALSE;
1980 #ifdef ECORE_XCB_RANDR
1981    int w = 0, h = 0, nw = 0, nh = 0;
1982    Eina_Rectangle rect;
1983 #endif
1984
1985    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1986    CHECK_XCB_CONN;
1987
1988 #ifdef ECORE_XCB_RANDR
1989    RANDR_CHECK_1_2_RET(EINA_FALSE);
1990
1991    ecore_x_randr_crtc_geometry_get(root, crtc,
1992                                    &rect.x, &rect.y, &rect.w, &rect.h);
1993    ecore_x_randr_screen_current_size_get(root, &w, &h, NULL, NULL);
1994    if (x < 0) x = rect.x;
1995    if (y < 0) y = rect.y;
1996    if ((x + rect.w) > w)
1997      nw = (x + rect.w);
1998    if ((y + rect.h) > h)
1999      nh = (y + rect.h);
2000
2001    if ((nw != 0) || (nh != 0))
2002      {
2003         if (!ecore_x_randr_screen_current_size_set(root, nw, nh, 0, 0))
2004           return EINA_FALSE;
2005      }
2006
2007    ret = ecore_x_randr_crtc_settings_set(root, crtc, NULL, -1, x, y, -1, -1);
2008 #endif
2009
2010    return ret;
2011 }
2012
2013 EAPI Eina_Bool
2014 ecore_x_randr_crtc_panning_area_set(Ecore_X_Window root EINA_UNUSED, Ecore_X_Randr_Crtc crtc, const int x, const int y, const int w, const int h)
2015 {
2016    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2017    CHECK_XCB_CONN;
2018
2019 #ifdef ECORE_XCB_RANDR
2020    RANDR_CHECK_1_4_RET(EINA_FALSE);
2021
2022    Eina_Bool ret = EINA_FALSE;
2023    xcb_randr_get_panning_cookie_t get_cookie;
2024    xcb_randr_get_panning_reply_t *get_reply;
2025
2026    get_cookie = xcb_randr_get_panning_unchecked(_ecore_xcb_conn, crtc);
2027    get_reply = xcb_randr_get_panning_reply(_ecore_xcb_conn, get_cookie, NULL);
2028    if (get_reply)
2029      {
2030         xcb_randr_set_panning_cookie_t set_cookie;
2031         xcb_randr_set_panning_reply_t *set_reply;
2032
2033         set_cookie =
2034           xcb_randr_set_panning_unchecked(_ecore_xcb_conn, crtc,
2035                                           XCB_CURRENT_TIME,
2036                                           x, y, w, h,
2037                                           get_reply->track_left,
2038                                           get_reply->track_top,
2039                                           get_reply->track_width,
2040                                           get_reply->track_height,
2041                                           get_reply->border_left,
2042                                           get_reply->border_top,
2043                                           get_reply->border_right,
2044                                           get_reply->border_bottom);
2045         set_reply =
2046           xcb_randr_set_panning_reply(_ecore_xcb_conn, set_cookie, NULL);
2047         if (!set_reply)
2048           ret = EINA_FALSE;
2049         else
2050           {
2051              if (set_reply->status == XCB_RANDR_SET_CONFIG_SUCCESS)
2052                ret = EINA_TRUE;
2053
2054              free(set_reply);
2055           }
2056
2057         free(get_reply);
2058      }
2059
2060    return ret;
2061 #endif
2062    return EINA_FALSE;
2063 }
2064
2065 EAPI void
2066 ecore_x_randr_crtc_size_get(Ecore_X_Window     root,
2067                             Ecore_X_Randr_Crtc crtc,
2068                             int               *w,
2069                             int               *h)
2070 {
2071    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2072    CHECK_XCB_CONN;
2073
2074 #ifdef ECORE_XCB_RANDR
2075    RANDR_CHECK_1_2_RET();
2076    ecore_x_randr_crtc_geometry_get(root, crtc, NULL, NULL, w, h);
2077 #endif
2078 }
2079
2080 EAPI Eina_Bool 
2081 ecore_x_randr_crtc_clone_set(Ecore_X_Window root, Ecore_X_Randr_Crtc original, Ecore_X_Randr_Crtc cln)
2082 {
2083    Eina_Bool ret = EINA_FALSE;
2084
2085    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2086    CHECK_XCB_CONN;
2087
2088 #ifdef ECORE_XCB_RANDR
2089    RANDR_CHECK_1_2_RET(EINA_FALSE);
2090
2091    if (_randr_version >= RANDR_1_3)
2092      {
2093         xcb_randr_get_screen_resources_current_reply_t *reply;
2094         xcb_timestamp_t stamp = 0;
2095
2096         reply = _ecore_xcb_randr_13_get_resources(root);
2097         if (reply)
2098           {
2099              xcb_randr_get_crtc_info_cookie_t rcookie;
2100              xcb_randr_get_crtc_info_reply_t *rreply;
2101
2102              if (_randr_version >= RANDR_1_3)
2103                stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
2104              else if (_randr_version == RANDR_1_2)
2105                stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
2106
2107              rcookie =
2108                xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, original,
2109                                                  stamp);
2110
2111              rreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn,
2112                                                     rcookie, NULL);
2113              if (rreply)
2114                {
2115                   int ox = 0, oy = 0;
2116                   Ecore_X_Randr_Orientation orient = 0;
2117                   Ecore_X_Randr_Mode mode = -1;
2118
2119                   ox = rreply->x;
2120                   oy = rreply->y;
2121                   orient = rreply->rotation;
2122                   mode = rreply->mode;
2123
2124                   free(rreply);
2125
2126                   ret = ecore_x_randr_crtc_settings_set(root, cln, NULL, -1, 
2127                                                         ox, oy, mode, orient);
2128                }
2129
2130              free(reply);
2131           }
2132      }
2133 #endif
2134
2135    return ret;
2136 }
2137
2138 EAPI Ecore_X_Randr_Crtc_Info *
2139 ecore_x_randr_crtc_info_get(Ecore_X_Window root, const Ecore_X_Randr_Crtc crtc)
2140 {
2141    Ecore_X_Randr_Crtc_Info *ret = NULL;
2142
2143    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2144    CHECK_XCB_CONN;
2145
2146 #ifdef ECORE_XCB_RANDR
2147    RANDR_CHECK_1_2_RET(NULL);
2148
2149    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return NULL;
2150
2151    if (_randr_version >= RANDR_1_3)
2152      {
2153         xcb_randr_get_screen_resources_current_reply_t *reply;
2154         xcb_timestamp_t stamp = 0;
2155
2156         reply = _ecore_xcb_randr_13_get_resources(root);
2157         if (reply)
2158           {
2159              xcb_randr_get_crtc_info_cookie_t rcookie;
2160              xcb_randr_get_crtc_info_reply_t *rreply;
2161
2162              if (_randr_version >= RANDR_1_3)
2163                stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
2164              else if (_randr_version == RANDR_1_2)
2165                stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
2166
2167              rcookie =
2168                xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc,
2169                                                  stamp);
2170
2171              rreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn,
2172                                                     rcookie, NULL);
2173              if (rreply)
2174                {
2175                   if ((ret = malloc(sizeof(Ecore_X_Randr_Crtc_Info))))
2176                     {
2177                        ret->timestamp = rreply->timestamp;
2178                        ret->x = rreply->x;
2179                        ret->y = rreply->y;
2180                        ret->width = rreply->width;
2181                        ret->height = rreply->height;
2182                        ret->mode = rreply->mode;
2183                        ret->rotation = rreply->rotation;
2184                        ret->noutput = 
2185                          xcb_randr_get_crtc_info_outputs_length(rreply);
2186                        ret->npossible = 
2187                          xcb_randr_get_crtc_info_possible_length(rreply);
2188
2189                        if ((ret->outputs = 
2190                             malloc(ret->noutput * sizeof(Ecore_X_Randr_Output))))
2191                          {
2192                             xcb_randr_output_t *outs;
2193                             int i = 0;
2194
2195                             outs = xcb_randr_get_crtc_info_outputs(rreply);
2196                             for (i = 0; i < ret->noutput; i++)
2197                               ret->outputs[i] = outs[i];
2198                          }
2199
2200                        if ((ret->possible = 
2201                             malloc(ret->npossible * sizeof(Ecore_X_Randr_Output))))
2202                          {
2203                             xcb_randr_output_t *outs;
2204                             int i = 0;
2205
2206                             outs = xcb_randr_get_crtc_info_possible(rreply);
2207                             for (i = 0; i < ret->npossible; i++)
2208                               ret->possible[i] = outs[i];
2209                          }
2210                     }
2211                   free(rreply);
2212                }
2213
2214              free(reply);
2215           }
2216      }
2217 #endif
2218
2219    return ret;
2220 }
2221
2222 EAPI void 
2223 ecore_x_randr_crtc_info_free(Ecore_X_Randr_Crtc_Info *info)
2224 {
2225 #ifdef ECORE_XCB_RANDR
2226    if (_randr_version >= RANDR_1_2)
2227      {
2228         if (info)
2229           {
2230              if (info->outputs) free(info->outputs);
2231              if (info->possible) free(info->possible);
2232              free(info);
2233           }
2234      }
2235 #endif
2236 }
2237
2238 EAPI Ecore_X_Randr_Refresh_Rate
2239 ecore_x_randr_crtc_refresh_rate_get(Ecore_X_Window     root,
2240                                     Ecore_X_Randr_Crtc crtc,
2241                                     Ecore_X_Randr_Mode mode)
2242 {
2243    Ecore_X_Randr_Refresh_Rate ret = 0.0;
2244
2245    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2246    CHECK_XCB_CONN;
2247
2248 #ifdef ECORE_XCB_RANDR
2249    RANDR_CHECK_1_2_RET(0.0);
2250
2251    if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return 0.0;
2252
2253    if (_randr_version >= RANDR_1_3)
2254      {
2255         xcb_randr_get_screen_resources_current_reply_t *reply;
2256
2257         reply = _ecore_xcb_randr_13_get_resources(root);
2258         if (reply)
2259           {
2260              xcb_randr_mode_info_iterator_t miter;
2261
2262              miter =
2263                xcb_randr_get_screen_resources_current_modes_iterator(reply);
2264              while (miter.rem)
2265                {
2266                   xcb_randr_mode_info_t *minfo;
2267
2268                   minfo = miter.data;
2269                   if (minfo->id == mode)
2270                     {
2271                        if ((minfo->htotal) && (minfo->vtotal))
2272                          {
2273                             ret = ((double)minfo->dot_clock /
2274                                    ((double)minfo->htotal *
2275                                     (double)minfo->vtotal));
2276                          }
2277                        break;
2278                     }
2279                   xcb_randr_mode_info_next(&miter);
2280                }
2281              free(reply);
2282           }
2283      }
2284    else if (_randr_version == RANDR_1_2)
2285      {
2286         xcb_randr_get_screen_resources_reply_t *reply;
2287
2288         reply = _ecore_xcb_randr_12_get_resources(root);
2289         if (reply)
2290           {
2291              xcb_randr_mode_info_iterator_t miter;
2292
2293              miter = xcb_randr_get_screen_resources_modes_iterator(reply);
2294              while (miter.rem)
2295                {
2296                   xcb_randr_mode_info_t *minfo;
2297
2298                   minfo = miter.data;
2299                   if (minfo->id == mode)
2300                     {
2301                        if ((minfo->htotal) && (minfo->vtotal))
2302                          {
2303                             ret = ((double)minfo->dot_clock /
2304                                    ((double)minfo->htotal *
2305                                     (double)minfo->vtotal));
2306                          }
2307                        break;
2308                     }
2309                   xcb_randr_mode_info_next(&miter);
2310                }
2311              free(reply);
2312           }
2313      }
2314 #endif
2315    return ret;
2316 }
2317
2318 /*
2319  * @brief Move given CRTCs belonging to the given root window's screen dx/dy
2320  * pixels relative to their current position. The screen size will be
2321  * automatically adjusted if necessary and possible.
2322  *
2323  * @param root Window which's screen's resources are used.
2324  * @param crtcs List of CRTCs to be moved.
2325  * @param ncrtc Number of CRTCs in array.
2326  * @param dx Amount of pixels the CRTCs should be moved in x direction.
2327  * @param dy Amount of pixels the CRTCs should be moved in y direction.
2328  * @return @c EINA_TRUE if all crtcs could be moved successfully.
2329  */
2330 EAPI Eina_Bool
2331 ecore_x_randr_move_crtcs(Ecore_X_Window            root,
2332                          const Ecore_X_Randr_Crtc *crtcs,
2333                          int                       num,
2334                          int                       dx,
2335                          int                       dy)
2336 {
2337    Eina_Bool ret = EINA_TRUE;
2338 #ifdef ECORE_XCB_RANDR
2339    xcb_timestamp_t stamp = 0;
2340    xcb_randr_get_crtc_info_reply_t *oreply[num];
2341    int i = 0, cw = 0, ch = 0;
2342    int mw = 0, mh = 0, nw = 0, nh = 0;
2343 #endif
2344
2345    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2346    CHECK_XCB_CONN;
2347
2348 #ifdef ECORE_XCB_RANDR
2349    RANDR_CHECK_1_2_RET(EINA_FALSE);
2350
2351    if (!_ecore_xcb_randr_root_validate(root)) return EINA_FALSE;
2352
2353    if (_randr_version >= RANDR_1_3)
2354      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
2355    else if (_randr_version == RANDR_1_2)
2356      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
2357
2358    ecore_x_randr_screen_size_range_get(root, NULL, NULL, &mw, &mh);
2359    ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
2360    nw = cw;
2361    nh = ch;
2362
2363    for (i = 0; i < num; i++)
2364      {
2365         xcb_randr_get_crtc_info_cookie_t ocookie;
2366
2367         ocookie =
2368           xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtcs[i],
2369                                             stamp);
2370         oreply[i] = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn,
2371                                                   ocookie, NULL);
2372         if (oreply[i])
2373           {
2374              if (((oreply[i]->x + dx) < 0) ||
2375                  ((oreply[i]->y + dy) < 0) ||
2376                  ((oreply[i]->x + oreply[i]->width + dx) > mw) ||
2377                  ((oreply[i]->y + oreply[i]->height + dy) > mh))
2378                {
2379                   continue;
2380                }
2381              nw = MAX((int)(oreply[i]->x + oreply[i]->width + dx), nw);
2382              nh = MAX((int)(oreply[i]->y + oreply[i]->height + dy), nh);
2383           }
2384      }
2385
2386    if ((nw > cw) || (nh > ch))
2387      {
2388         if (!ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1))
2389           {
2390              for (i = 0; i < num; i++)
2391                if (oreply[i]) free(oreply[i]);
2392
2393              return EINA_FALSE;
2394           }
2395      }
2396
2397    for (i = 0; ((i < num) && (oreply[i])); i++)
2398      {
2399         if (!oreply[i]) continue;
2400         if (!ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL, -1,
2401                                              (oreply[i]->x + dx),
2402                                              (oreply[i]->y + dy),
2403                                              oreply[i]->mode,
2404                                              oreply[i]->rotation))
2405           {
2406              ret = EINA_FALSE;
2407              break;
2408           }
2409      }
2410
2411    if (i < num)
2412      {
2413         while (i-- >= 0)
2414           {
2415              if (oreply[i])
2416                ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL, -1,
2417                                                (oreply[i]->x - dx),
2418                                                (oreply[i]->y - dy),
2419                                                oreply[i]->mode,
2420                                                oreply[i]->rotation);
2421           }
2422      }
2423
2424    for (i = 0; i < num; i++)
2425      if (oreply[i]) free(oreply[i]);
2426 #endif
2427
2428    return ret;
2429 }
2430
2431 /**
2432  * @brief enable event selection. This enables basic interaction with
2433  * output/crtc events and requires RRandR >= 1.2.
2434  * @param win select this window's properties for RandRR events
2435  * @param on enable/disable selecting
2436  */
2437 EAPI void
2438 ecore_x_randr_events_select(Ecore_X_Window win,
2439                             Eina_Bool      on)
2440 {
2441 #ifdef ECORE_XCB_RANDR
2442    uint16_t mask = 0;
2443 #endif
2444
2445    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2446    CHECK_XCB_CONN;
2447
2448 #ifdef ECORE_XCB_RANDR
2449    if (on)
2450      {
2451         mask = XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE;
2452         if (_randr_version >= ((1 << 16) | 2))
2453           {
2454              mask |= (XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
2455                       XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
2456                       XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
2457           }
2458      }
2459
2460    xcb_randr_select_input(_ecore_xcb_conn, win, mask);
2461 #endif
2462 }
2463
2464 /**
2465  * @brief removes unused screen space. The most upper left CRTC is set to 0x0
2466  * and all other CRTCs dx,dy respectively.
2467  * @param root the window's screen which will be reset.
2468  */
2469 EAPI void
2470 ecore_x_randr_screen_reset(Ecore_X_Window root)
2471 {
2472 #ifdef ECORE_XCB_RANDR
2473    xcb_timestamp_t stamp = 0;
2474    Ecore_X_Randr_Crtc *crtcs = NULL;
2475    int total = 0, i = 0, w = 0, h = 0;
2476    int dx = 100000, dy = 100000, num = 0;
2477 #endif
2478
2479    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2480    CHECK_XCB_CONN;
2481
2482 #ifdef ECORE_XCB_RANDR
2483    if (!_ecore_xcb_randr_root_validate(root)) return;
2484    crtcs = ecore_x_randr_crtcs_get(root, &total);
2485
2486    if (_randr_version >= RANDR_1_3)
2487      stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
2488    else if (_randr_version == RANDR_1_2)
2489      stamp = _ecore_xcb_randr_12_get_resource_timestamp(root);
2490
2491    /* I hate declaring variables inside code like this, but we need the
2492     * value of 'total' before we can */
2493    Ecore_X_Randr_Crtc enabled[total];
2494
2495    for (i = 0; i < total; i++)
2496      {
2497         xcb_randr_get_crtc_info_cookie_t ocookie;
2498         xcb_randr_get_crtc_info_reply_t *oreply;
2499
2500         ocookie =
2501           xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtcs[i], stamp);
2502         oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn,
2503                                                ocookie, NULL);
2504         if (!oreply) continue;
2505         if ((oreply->mode <= 0) || (oreply->num_outputs == 0))
2506           {
2507              free(oreply);
2508              continue;
2509           }
2510
2511         enabled[num++] = crtcs[i];
2512         if ((int)(oreply->x + oreply->width) > w)
2513           w = (oreply->x + oreply->width);
2514         if ((int)(oreply->y + oreply->height) > h)
2515           h = (oreply->y + oreply->height);
2516
2517         if (oreply->x < dx) dx = oreply->x;
2518         if (oreply->y < dy) dy = oreply->y;
2519
2520         free(oreply);
2521      }
2522    free(crtcs);
2523
2524    if ((dx > 0) || (dy > 0))
2525      {
2526         if (ecore_x_randr_move_crtcs(root, enabled, num, -dx, -dy))
2527           {
2528              w -= dx;
2529              h -= dy;
2530           }
2531      }
2532
2533    ecore_x_randr_screen_current_size_set(root, w, h, -1, -1);
2534 #endif
2535 }
2536
2537 /*
2538  * @param root window which's screen will be queried
2539  * @param wmin minimum width the screen can be set to
2540  * @param hmin minimum height the screen can be set to
2541  * @param wmax maximum width the screen can be set to
2542  * @param hmax maximum height the screen can be set to
2543  */
2544 EAPI void
2545 ecore_x_randr_screen_size_range_get(Ecore_X_Window root,
2546                                     int           *minw,
2547                                     int           *minh,
2548                                     int           *maxw,
2549                                     int           *maxh)
2550 {
2551 #ifdef ECORE_XCB_RANDR
2552    xcb_randr_get_screen_size_range_cookie_t cookie;
2553    xcb_randr_get_screen_size_range_reply_t *reply;
2554 #endif
2555
2556    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2557    CHECK_XCB_CONN;
2558
2559 #ifdef ECORE_XCB_RANDR
2560    RANDR_CHECK_1_2_RET();
2561
2562    cookie = xcb_randr_get_screen_size_range_unchecked(_ecore_xcb_conn, root);
2563    reply = xcb_randr_get_screen_size_range_reply(_ecore_xcb_conn, cookie, NULL);
2564    if (reply)
2565      {
2566         if (minw) *minw = reply->min_width;
2567         if (minh) *minh = reply->min_height;
2568         if (maxw) *maxw = reply->max_width;
2569         if (maxh) *maxh = reply->max_height;
2570         free(reply);
2571      }
2572 #endif
2573 }
2574
2575 EAPI void
2576 ecore_x_randr_screen_backlight_level_set(Ecore_X_Window root, double level)
2577 {
2578    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2579    CHECK_XCB_CONN;
2580
2581 #ifdef ECORE_XCB_RANDR
2582    Ecore_X_Randr_Output *outputs;
2583    int i = 0, ret = 0;
2584
2585    RANDR_CHECK_1_3_RET();
2586
2587    outputs = _ecore_xcb_randr_13_outputs_get(root, &ret);
2588    for (i = 0; i < ret; i++)
2589      ecore_x_randr_output_backlight_level_set(root, outputs[i], level);
2590 #endif
2591 }
2592
2593 /*
2594  * @param w width of screen in px
2595  * @param h height of screen in px
2596  */
2597 EAPI void
2598 ecore_x_randr_screen_current_size_get(Ecore_X_Window root,
2599                                       int           *w,
2600                                       int           *h,
2601                                       int           *w_mm,
2602                                       int           *h_mm)
2603 {
2604 #ifdef ECORE_XCB_RANDR
2605    Ecore_X_Randr_Screen scr = 0;
2606    xcb_screen_t *s;
2607 #endif
2608
2609    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2610    CHECK_XCB_CONN;
2611
2612 #ifdef ECORE_XCB_RANDR
2613    RANDR_CHECK_1_2_RET();
2614
2615    if (!RANDR_VALIDATE_ROOT(scr, root)) return;
2616
2617    s = ecore_x_screen_get(scr);
2618    if (w) *w = s->width_in_pixels;
2619    if (h) *h = s->height_in_pixels;
2620    if (w_mm) *w_mm = s->width_in_millimeters;
2621    if (h_mm) *h_mm = s->height_in_millimeters;
2622 #endif
2623 }
2624
2625 /*
2626  * @param root Window which's screen's size should be set. If invalid (e.g. 
2627  * @c NULL) no action is taken.
2628  * @param w Width in px the screen should be set to. If out of valid
2629  * boundaries, current value is assumed.
2630  * @param h Height in px the screen should be set to. If out of valid
2631  * boundaries, current value is assumed.
2632  * @param w_mm Width in mm the screen should be set to. If @c 0, current
2633  * aspect is assumed.
2634  * @param h_mm Height in mm the screen should be set to. If @c 0, current
2635  * aspect is assumed.
2636  * @return @c EINA_TRUE if request was successfully sent or screen is already
2637  * in requested size, @c EINA_FALSE if parameters are invalid.
2638  */
2639 EAPI Eina_Bool
2640 ecore_x_randr_screen_current_size_set(Ecore_X_Window root,
2641                                       int            w,
2642                                       int            h,
2643                                       int            w_mm,
2644                                       int            h_mm)
2645 {
2646    Eina_Bool ret = EINA_TRUE;
2647 #ifdef ECORE_XCB_RANDR
2648    Ecore_X_Randr_Screen scr;
2649    int wc = 0, hc = 0, w_mm_c = 0, h_mm_c = 0;
2650    int mw = 0, mh = 0, xw = 0, xh = 0;
2651 #endif
2652
2653    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2654    CHECK_XCB_CONN;
2655
2656 #ifdef ECORE_XCB_RANDR
2657    RANDR_CHECK_1_2_RET(EINA_FALSE);
2658
2659    if (!RANDR_VALIDATE_ROOT(scr, root)) return EINA_FALSE;
2660    ecore_x_randr_screen_current_size_get(root, &wc, &hc, &w_mm_c, &h_mm_c);
2661    if ((w == wc) && (h == hc) && (w_mm == w_mm_c) && (h_mm == h_mm_c))
2662      return EINA_TRUE;
2663    ecore_x_randr_screen_size_range_get(root, &mw, &mh, &xw, &xh);
2664    if (((w != 1) && ((w < mw) || (w > xw))) ||
2665        ((h != -1) && ((h < mh) || (h > xh)))) return EINA_FALSE;
2666
2667    if (w <= 0)
2668      w = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels;
2669    if (h <= 0)
2670      h = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_pixels;
2671
2672    /* NB: Hmmmm, xlib version divides w_mm by width ... that seems wrong */
2673    if (w_mm <= 0)
2674      w_mm = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_millimeters;
2675    if (h_mm <= 0)
2676      h_mm = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_millimeters;
2677
2678    xcb_randr_set_screen_size(_ecore_xcb_conn, root, w, h, w_mm, h_mm);
2679 #endif
2680
2681    return ret;
2682 }
2683
2684 /*
2685  * @deprecated bad naming. Use ecore_x_randr_window_outputs_get instead.
2686  * @brief Get the outputs, which display a certain window.
2687  *
2688  * @param window Window the displaying outputs shall be found for.
2689  * @param num The number of outputs displaying the window.
2690  * @return Array of outputs that display a certain window. @c NULL if no
2691  * outputs was found that displays the specified window.
2692  */
2693
2694 Ecore_X_Randr_Output *
2695 ecore_x_randr_current_output_get(Ecore_X_Window window,
2696                                  int *num)
2697 {
2698    return ecore_x_randr_window_outputs_get(window, num);
2699 }
2700
2701 /*
2702  * @brief Get the outputs, which display a certain window.
2703  *
2704  * @param window Window the displaying outputs shall be found for.
2705  * @param num The number of outputs displaying the window.
2706  * @return Array of outputs that display a certain window. @c NULL if no
2707  * outputs was found that displays the specified window.
2708  */
2709 EAPI Ecore_X_Randr_Output *
2710 ecore_x_randr_window_outputs_get(Ecore_X_Window window,
2711                                  int           *num)
2712 {
2713 #ifdef ECORE_XCB_RANDR
2714    Ecore_X_Window root;
2715    Ecore_X_Randr_Crtc *crtcs;
2716    Ecore_X_Randr_Output *outputs, *ret = NULL, *tret;
2717    int ncrtcs, noutputs, i, nret = 0;
2718 #endif
2719
2720    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2721    CHECK_XCB_CONN;
2722
2723    if (num) *num = 0;
2724
2725 #ifdef ECORE_XCB_RANDR
2726    if (_randr_version < RANDR_1_2) goto _ecore_x_randr_current_output_get_fail;
2727
2728    root = ecore_x_window_root_get(window);
2729    if (!(crtcs = ecore_x_randr_window_crtcs_get(window, &ncrtcs)))
2730      goto _ecore_x_randr_current_output_get_fail;
2731
2732    for (i = 0, nret = 0; i < ncrtcs; i++)
2733      {
2734
2735         outputs = ecore_x_randr_crtc_outputs_get(root, crtcs[i],
2736               &noutputs);
2737         if (outputs)
2738           {
2739              if (noutputs > 0)
2740                {
2741                   tret = realloc(ret, ((nret + noutputs) * sizeof(Ecore_X_Randr_Output)));
2742                   if (!tret) goto _ecore_x_randr_current_output_get_fail_free;
2743                   ret = tret;
2744                   memcpy(&ret[nret], outputs, (noutputs * sizeof(Ecore_X_Randr_Output)));
2745                   nret += noutputs;
2746                }
2747              free(outputs);
2748              outputs = NULL;
2749           }
2750      }
2751    free(crtcs);
2752
2753    if (num)
2754      *num = nret;
2755
2756    return ret;
2757
2758 _ecore_x_randr_current_output_get_fail_free:
2759    free(outputs);
2760    free(crtcs);
2761    free(ret);
2762 _ecore_x_randr_current_output_get_fail:
2763 #endif
2764    if (num) *num = 0;
2765    return NULL;
2766 }
2767
2768 /*
2769  * @brief get the backlight level of the given output
2770  * @param root window which's screen should be queried
2771  * @param output from which the backlight level should be retrieved
2772  * @return the backlight level
2773  */
2774 EAPI double
2775 ecore_x_randr_output_backlight_level_get(Ecore_X_Window       root,
2776                                          Ecore_X_Randr_Output output)
2777 {
2778 #ifdef ECORE_XCB_RANDR
2779    Ecore_X_Atom _backlight;
2780    xcb_intern_atom_cookie_t acookie;
2781    xcb_intern_atom_reply_t *areply;
2782    xcb_randr_get_output_property_cookie_t cookie;
2783    xcb_randr_get_output_property_reply_t *reply;
2784    xcb_randr_query_output_property_cookie_t qcookie;
2785    xcb_randr_query_output_property_reply_t *qreply;
2786    double dvalue;
2787    long value, max, min;
2788 #endif
2789
2790    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2791    CHECK_XCB_CONN;
2792
2793 #ifdef ECORE_XCB_RANDR
2794    RANDR_CHECK_1_2_RET(-1);
2795
2796    acookie =
2797      xcb_intern_atom_unchecked(_ecore_xcb_conn, 1,
2798                                strlen("Backlight"), "Backlight");
2799    areply = xcb_intern_atom_reply(_ecore_xcb_conn, acookie, NULL);
2800
2801    if (!areply)
2802      {
2803         ERR("Backlight property is not suppported on this server or driver");
2804         return -1;
2805      }
2806    else
2807      {
2808         _backlight = areply->atom;
2809         free(areply);
2810      }
2811
2812    if (!_ecore_xcb_randr_output_validate(root, output))
2813      {
2814         ERR("Invalid output");
2815         return -1;
2816      }
2817
2818    cookie =
2819      xcb_randr_get_output_property_unchecked(_ecore_xcb_conn,
2820                                              output, _backlight,
2821                                              XCB_ATOM_NONE, 0, 4, 0, 0);
2822    reply =
2823      xcb_randr_get_output_property_reply(_ecore_xcb_conn, cookie, NULL);
2824    if (!reply)
2825      {
2826         WRN("Backlight not supported on this output");
2827         return -1;
2828      }
2829
2830    if ((reply->format != 32) || (reply->num_items != 1) ||
2831        (reply->type != XCB_ATOM_INTEGER))
2832      {
2833         free(reply);
2834         return -1;
2835      }
2836
2837    value = *((long *)xcb_randr_get_output_property_data(reply));
2838    free (reply);
2839
2840    /* I have the current value of the backlight */
2841    /* Now retrieve the min and max intensities of the output */
2842    qcookie =
2843      xcb_randr_query_output_property_unchecked(_ecore_xcb_conn,
2844                                                output, _backlight);
2845    qreply =
2846      xcb_randr_query_output_property_reply(_ecore_xcb_conn, qcookie, NULL);
2847    if (qreply)
2848      {
2849         dvalue = -1;
2850         if ((qreply->range) &&
2851             (xcb_randr_query_output_property_valid_values_length(qreply) == 2))
2852           {
2853              int32_t *vals;
2854
2855              vals = xcb_randr_query_output_property_valid_values(qreply);
2856              /* finally convert the current value in the interval [0..1] */
2857              min = vals[0];
2858              max = vals[1];
2859              dvalue = ((double)(value - min)) / ((double)(max - min));
2860           }
2861         free(qreply);
2862         return dvalue;
2863      }
2864 #endif
2865    return -1;
2866 }
2867
2868 /*
2869  * @brief Set the backlight level of a given output.
2870  *
2871  * @param root Window which's screen should be queried.
2872  * @param output That should be set.
2873  * @param level For which the backlight should be set.
2874  * @return @c EINA_TRUE in case of success.
2875  */
2876 EAPI Eina_Bool
2877 ecore_x_randr_output_backlight_level_set(Ecore_X_Window       root,
2878                                          Ecore_X_Randr_Output output,
2879                                          double               level)
2880 {
2881 #ifdef ECORE_XCB_RANDR
2882    Ecore_X_Atom _backlight;
2883    xcb_intern_atom_cookie_t acookie;
2884    xcb_intern_atom_reply_t *areply;
2885    xcb_randr_query_output_property_cookie_t qcookie;
2886    xcb_randr_query_output_property_reply_t *qreply;
2887 #endif
2888
2889    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2890    CHECK_XCB_CONN;
2891
2892 #ifdef ECORE_XCB_RANDR
2893    RANDR_CHECK_1_2_RET(EINA_FALSE);
2894
2895    if ((level < 0) || (level > 1))
2896      {
2897         ERR("Backlight level should be between 0 and 1");
2898         return EINA_FALSE;
2899      }
2900
2901    if (!_ecore_xcb_randr_output_validate(root, output))
2902      {
2903         ERR("Wrong output value");
2904         return EINA_FALSE;
2905      }
2906
2907    acookie =
2908      xcb_intern_atom_unchecked(_ecore_xcb_conn, 1,
2909                                strlen("Backlight"), "Backlight");
2910    areply = xcb_intern_atom_reply(_ecore_xcb_conn, acookie, NULL);
2911    if (!areply)
2912      {
2913         WRN("Backlight property is not suppported on this server or driver");
2914         return EINA_FALSE;
2915      }
2916    else
2917      {
2918         _backlight = areply->atom;
2919         free(areply);
2920      }
2921
2922    qcookie =
2923      xcb_randr_query_output_property_unchecked(_ecore_xcb_conn,
2924                                                output, _backlight);
2925    qreply =
2926      xcb_randr_query_output_property_reply(_ecore_xcb_conn, qcookie, NULL);
2927    if (qreply)
2928      {
2929         if ((qreply->range) && (qreply->length == 2))
2930           {
2931              int32_t *vals;
2932              double min, max, tmp;
2933              long n;
2934
2935              vals = xcb_randr_query_output_property_valid_values(qreply);
2936              min = vals[0];
2937              max = vals[1];
2938              tmp = (level * (max - min)) + min;
2939              n = tmp;
2940              if (n > max) n = max;
2941              if (n < min) n = min;
2942              xcb_randr_change_output_property(_ecore_xcb_conn, output,
2943                                               _backlight, XCB_ATOM_INTEGER,
2944                                               32, XCB_PROP_MODE_REPLACE,
2945                                               1, (unsigned char *)&n);
2946              ecore_x_flush(); // needed
2947           }
2948
2949         free(qreply);
2950         return EINA_TRUE;
2951      }
2952 #endif
2953    return EINA_FALSE;
2954 }
2955
2956 /*
2957  * @brief Check if a backlight is available.
2958  *
2959  * @return Whether a backlight is available.
2960  */
2961 EAPI Eina_Bool 
2962 ecore_x_randr_output_backlight_available(void) 
2963 {
2964 #ifdef ECORE_XCB_RANDR
2965    xcb_intern_atom_cookie_t acookie;
2966    xcb_intern_atom_reply_t *areply;
2967 #endif
2968
2969    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2970    CHECK_XCB_CONN;
2971
2972 #ifdef ECORE_XCB_RANDR
2973    RANDR_CHECK_1_2_RET(EINA_FALSE);
2974
2975    acookie =
2976      xcb_intern_atom_unchecked(_ecore_xcb_conn, 1,
2977                                strlen("Backlight"), "Backlight");
2978    areply = xcb_intern_atom_reply(_ecore_xcb_conn, acookie, NULL);
2979
2980    if (!areply)
2981      {
2982         ERR("Backlight property is not suppported on this server or driver");
2983         return EINA_FALSE;
2984      }
2985    else
2986      {
2987         free(areply);
2988         return EINA_TRUE;
2989      }
2990 #endif
2991    return EINA_FALSE;
2992 }
2993
2994 EAPI int
2995 ecore_x_randr_edid_version_get(unsigned char *edid, unsigned long edid_length)
2996 {
2997    if ((edid_length > _ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR) &&
2998        (ecore_x_randr_edid_has_valid_header(edid, edid_length)))
2999      return (edid[_ECORE_X_RANDR_EDID_OFFSET_VERSION_MAJOR] << 8) |
3000             edid[_ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR];
3001    return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3002 }
3003
3004 EAPI char *
3005 ecore_x_randr_edid_display_name_get(unsigned char *edid, unsigned long edid_length) 
3006 {
3007    unsigned char *block = NULL;
3008    int version = 0;
3009
3010    version = ecore_x_randr_edid_version_get(edid, edid_length);
3011    if (version < ECORE_X_RANDR_EDID_VERSION_13) return NULL;
3012
3013    _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block)
3014      {
3015         if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xfc)
3016           {
3017              char *name, *p;
3018              const char *edid_name;
3019
3020              edid_name = (const char *)block + 
3021                _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT;
3022              name = 
3023                malloc(_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX + 1);
3024              if (!name) return NULL;
3025
3026              strncpy(name, edid_name, 
3027                      _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX);
3028              name[_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX] = 0;
3029              for (p = name; *p; p++)
3030                if ((*p < ' ') || (*p > '~')) *p = 0;
3031
3032              return name;
3033           }
3034      }
3035    return NULL;
3036 }
3037
3038 EAPI char *
3039 ecore_x_randr_edid_display_ascii_get(unsigned char *edid, unsigned long edid_length) 
3040 {
3041 #ifdef ECORE_XCB_RANDR
3042    unsigned char *block = NULL;
3043    int version = 0;
3044
3045    version = ecore_x_randr_edid_version_get(edid, edid_length);
3046    if (version < ECORE_X_RANDR_EDID_VERSION_13) return NULL;
3047
3048    _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block)
3049      {
3050         if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xfe)
3051           {
3052              char *ascii = NULL, *p = NULL;
3053              const char *edid_ascii;
3054
3055              edid_ascii = (const char *)block + 5;
3056
3057              if (!(ascii = malloc(14))) return NULL;
3058              strncpy(ascii, edid_ascii, 13);
3059              ascii[13] = 0;
3060              for (p = ascii; *p; p++)
3061                if ((*p < ' ') || (*p > '~')) *p = 0;
3062
3063              return ascii;
3064           }
3065      }
3066 #endif
3067    return NULL;
3068 }
3069
3070 EAPI char *
3071 ecore_x_randr_edid_display_serial_get(unsigned char *edid, unsigned long edid_length) 
3072 {
3073 #ifdef ECORE_XCB_RANDR
3074    unsigned char *block = NULL;
3075    int version = 0;
3076
3077    version = ecore_x_randr_edid_version_get(edid, edid_length);
3078    if (version < ECORE_X_RANDR_EDID_VERSION_13) return NULL;
3079
3080    _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block)
3081      {
3082         if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xff)
3083           {
3084              char *serial = NULL, *p = NULL;
3085              const char *edid_serial;
3086
3087              edid_serial = (const char *)block + 5;
3088
3089              if (!(serial = malloc(14))) return NULL;
3090              strncpy(serial, edid_serial, 13);
3091              serial[13] = 0;
3092              for (p = serial; *p; p++)
3093                if ((*p < ' ') || (*p > '~')) *p = 0;
3094
3095              return serial;
3096           }
3097      }
3098 #endif
3099    return NULL;
3100 }
3101
3102 EAPI Ecore_X_Randr_Edid_Display_Interface_Type
3103 ecore_x_randr_edid_display_interface_type_get(unsigned char *edid, unsigned long edid_length)
3104 {
3105 #ifdef ECORE_XCB_RANDR
3106    Ecore_X_Randr_Edid_Display_Interface_Type type;
3107    int version = 0;
3108
3109    type = ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3110
3111    version = ecore_x_randr_edid_version_get(edid, edid_length);
3112    if (version < ECORE_X_RANDR_EDID_VERSION_13) return type;
3113
3114    type = (edid[0x14] & 0x0f);
3115    if (type > ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DISPLAY_PORT)
3116      type = ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3117
3118    return type;
3119 #endif
3120    return 0;
3121 }
3122
3123 EAPI Eina_Bool
3124 ecore_x_randr_edid_has_valid_header(unsigned char *edid, unsigned long edid_length)
3125 {
3126    const unsigned char header[] =
3127      { 
3128         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 
3129      };
3130
3131    if ((!edid) || (edid_length < 8)) return EINA_FALSE;
3132    if (!memcmp(edid, header, 8)) return EINA_TRUE;
3133    return EINA_FALSE;
3134 }
3135
3136 EAPI Eina_Bool
3137 ecore_x_randr_edid_info_has_valid_checksum(unsigned char *edid, unsigned long edid_length)
3138 {
3139    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3140    CHECK_XCB_CONN;
3141
3142 #ifdef ECORE_XCB_RANDR
3143    unsigned char *iter = NULL;
3144    char sum = 0;
3145    int i = 0, version = 0;
3146
3147    if (edid_length < 128) return EINA_FALSE;
3148
3149    version = ecore_x_randr_edid_version_get(edid, edid_length);
3150    if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE;
3151
3152    for (i = 0; i < 128; i++)
3153      sum += edid[i];
3154
3155    if (sum) return EINA_FALSE;
3156
3157    for (iter = edid; iter < (edid + edid_length); iter += 128)
3158      {
3159         if (iter[0] == 0x02)
3160           {
3161              for (i = 0, sum = 0; i < 128; i++)
3162                sum += iter[i];
3163           }
3164      }
3165
3166    if (sum) return EINA_FALSE;
3167    return EINA_TRUE;
3168 #else
3169    return EINA_FALSE;
3170 #endif
3171 }
3172
3173 EAPI char *
3174 ecore_x_randr_edid_manufacturer_name_get(unsigned char *edid, unsigned long edid_length)
3175 {
3176    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3177    CHECK_XCB_CONN;
3178
3179 #ifdef ECORE_XCB_RANDR
3180    if ((edid_length > _ECORE_X_RANDR_EDID_MANUFACTURER + 1) &&
3181        (ecore_x_randr_edid_has_valid_header(edid, edid_length)))
3182      {
3183         unsigned char *x;
3184         char *name;
3185
3186         name = malloc(sizeof(char) * 4);
3187         if (!name) return NULL;
3188
3189         x = (edid + _ECORE_X_RANDR_EDID_MANUFACTURER);
3190         name[0] = ((x[0] & 0x7c) >> 2) + '@';
3191         name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xe0) >> 5) + '@';
3192         name[2] = (x[1] & 0x1f) + '@';
3193         name[3] = 0;
3194
3195         return name;
3196      }
3197 #endif
3198    return NULL;
3199 }
3200
3201 EAPI int
3202 ecore_x_randr_edid_manufacturer_model_get(unsigned char *edid, unsigned long edid_length)
3203 {
3204    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3205    CHECK_XCB_CONN;
3206
3207 #ifdef ECORE_XCB_RANDR
3208    if ((edid_length > _ECORE_X_RANDR_EDID_MANUFACTURER + 1) &&
3209        (ecore_x_randr_edid_has_valid_header(edid, edid_length)))
3210      return (int)(edid[0x0a] + (edid[0x0b] << 8));
3211 #endif
3212    return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3213 }
3214
3215 EAPI int
3216 ecore_x_randr_edid_model_get(unsigned char *edid, unsigned long edid_length)
3217 {
3218    return ecore_x_randr_edid_manufacturer_model_get(edid, edid_length);
3219 }
3220
3221 EAPI int 
3222 ecore_x_randr_edid_manufacturer_serial_number_get(unsigned char *edid, unsigned long edid_length)
3223 {
3224    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3225    CHECK_XCB_CONN;
3226
3227 #ifdef ECORE_XCB_RANDR
3228    if ((edid_length > _ECORE_X_RANDR_EDID_MANUFACTURER + 1) &&
3229        (ecore_x_randr_edid_has_valid_header(edid, edid_length)))
3230      return (int)(edid[0x0c] + (edid[0x0d] << 8) + 
3231                   (edid[0x0e] << 16) + (edid[0x0f] << 24));
3232 #endif
3233    return ECORE_X_RANDR_EDID_UNKNOWN_VALUE;
3234 }
3235
3236 EAPI Eina_Bool 
3237 ecore_x_randr_edid_dpms_available_get(unsigned char *edid, unsigned long edid_length)
3238 {
3239    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3240    CHECK_XCB_CONN;
3241
3242 #ifdef ECORE_XCB_RANDR
3243    int version = 0;
3244
3245    version = ecore_x_randr_edid_version_get(edid, edid_length);
3246    if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE;
3247
3248    return !!(edid[0x18] & 0xE0);
3249 #else
3250    return EINA_FALSE;
3251 #endif
3252 }
3253
3254 EAPI Eina_Bool 
3255 ecore_x_randr_edid_dpms_standby_available_get(unsigned char *edid, unsigned long edid_length)
3256 {
3257    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3258    CHECK_XCB_CONN;
3259
3260 #ifdef ECORE_XCB_RANDR
3261    int version = 0;
3262
3263    version = ecore_x_randr_edid_version_get(edid, edid_length);
3264    if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE;
3265
3266    if (edid[0x18] & 0xE0) return !!(edid[0x18] & 0x80);
3267 #endif
3268    return EINA_FALSE;
3269 }
3270
3271 EAPI Eina_Bool 
3272 ecore_x_randr_edid_dpms_suspend_available_get(unsigned char *edid, unsigned long edid_length)
3273 {
3274    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3275    CHECK_XCB_CONN;
3276
3277 #ifdef ECORE_XCB_RANDR
3278    int version = 0;
3279
3280    version = ecore_x_randr_edid_version_get(edid, edid_length);
3281    if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE;
3282
3283    if (edid[0x18] & 0xE0) return !!(edid[0x18] & 0x40);
3284 #endif
3285    return EINA_FALSE;
3286 }
3287
3288 EAPI Eina_Bool 
3289 ecore_x_randr_edid_dpms_off_available_get(unsigned char *edid, unsigned long edid_length)
3290 {
3291    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3292    CHECK_XCB_CONN;
3293
3294 #ifdef ECORE_XCB_RANDR
3295    int version = 0;
3296
3297    version = ecore_x_randr_edid_version_get(edid, edid_length);
3298    if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE;
3299
3300    if (edid[0x18] & 0xE0) return !!(edid[0x18] & 0x20);
3301 #endif
3302    return EINA_FALSE;
3303 }
3304
3305 /* local functions */
3306 static Eina_Bool
3307 _ecore_xcb_randr_output_validate(Ecore_X_Window       root,
3308                                  Ecore_X_Randr_Output output)
3309 {
3310    Eina_Bool ret = EINA_FALSE;
3311
3312    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3313    CHECK_XCB_CONN;
3314
3315 #ifdef ECORE_XCB_RANDR
3316    RANDR_CHECK_1_2_RET(EINA_FALSE);
3317
3318    if ((output) && (_ecore_xcb_randr_root_validate(root)))
3319      {
3320         if (_randr_version >= RANDR_1_3)
3321           {
3322              xcb_randr_get_screen_resources_current_reply_t *reply;
3323
3324              reply = _ecore_xcb_randr_13_get_resources(root);
3325              if (reply)
3326                {
3327                   int len = 0, i = 0;
3328                   xcb_randr_output_t *outputs;
3329
3330                   len =
3331                     xcb_randr_get_screen_resources_current_outputs_length(reply);
3332                   outputs =
3333                     xcb_randr_get_screen_resources_current_outputs(reply);
3334                   for (i = 0; i < len; i++)
3335                     {
3336                        if (outputs[i] == output)
3337                          {
3338                             ret = EINA_TRUE;
3339                             break;
3340                          }
3341                     }
3342                   free(reply);
3343                }
3344           }
3345         else if (_randr_version == RANDR_1_2)
3346           {
3347              xcb_randr_get_screen_resources_reply_t *reply;
3348
3349              reply = _ecore_xcb_randr_12_get_resources(root);
3350              if (reply)
3351                {
3352                   int len = 0, i = 0;
3353                   xcb_randr_output_t *outputs;
3354
3355                   len = xcb_randr_get_screen_resources_outputs_length(reply);
3356                   outputs = xcb_randr_get_screen_resources_outputs(reply);
3357                   for (i = 0; i < len; i++)
3358                     {
3359                        if (outputs[i] == output)
3360                          {
3361                             ret = EINA_TRUE;
3362                             break;
3363                          }
3364                     }
3365                   free(reply);
3366                }
3367           }
3368      }
3369 #endif
3370    return ret;
3371 }
3372
3373 /**
3374  * @brief Validates a CRTC for a given root window's screen.
3375  *
3376  * @param root The window which's default display will be queried.
3377  * @param crtc The CRTC to be validated.
3378  * @return In case it is found @c EINA_TRUE will be returned, else
3379  * @c EINA_FALSE is returned.
3380  */
3381 static Eina_Bool
3382 _ecore_xcb_randr_crtc_validate(Ecore_X_Window     root,
3383                                Ecore_X_Randr_Crtc crtc)
3384 {
3385    Eina_Bool ret = EINA_FALSE;
3386
3387    LOGFN(__FILE__, __LINE__, __FUNCTION__);
3388    CHECK_XCB_CONN;
3389
3390 #ifdef ECORE_XCB_RANDR
3391    RANDR_CHECK_1_2_RET(EINA_FALSE);
3392
3393    if (((int)crtc == Ecore_X_Randr_None) || ((int)crtc == Ecore_X_Randr_Unset))
3394      return ret;
3395
3396    if ((crtc) && (_ecore_xcb_randr_root_validate(root)))
3397      {
3398         if (_randr_version >= RANDR_1_3)
3399           {
3400              xcb_randr_get_screen_resources_current_reply_t *reply;
3401
3402              reply = _ecore_xcb_randr_13_get_resources(root);
3403              if (reply)
3404                {
3405                   int i = 0;
3406                   xcb_randr_crtc_t *crtcs;
3407
3408                   crtcs = xcb_randr_get_screen_resources_current_crtcs(reply);
3409                   for (i = 0; i < reply->num_crtcs; i++)
3410                     {
3411                        if (crtcs[i] == crtc)
3412                          {
3413                             ret = EINA_TRUE;
3414                             break;
3415                          }
3416                     }
3417                   free(reply);
3418                }
3419           }
3420         else if (_randr_version == RANDR_1_2)
3421           {
3422              xcb_randr_get_screen_resources_reply_t *reply;
3423
3424              reply = _ecore_xcb_randr_12_get_resources(root);
3425              if (reply)
3426                {
3427                   int i = 0;
3428                   xcb_randr_crtc_t *crtcs;
3429
3430                   crtcs = xcb_randr_get_screen_resources_crtcs(reply);
3431                   for (i = 0; i < reply->num_crtcs; i++)
3432                     {
3433                        if (crtcs[i] == crtc)
3434                          {
3435                             ret = EINA_TRUE;
3436                             break;
3437                          }
3438                     }
3439                   free(reply);
3440                }
3441           }
3442      }
3443 #endif
3444
3445    return ret;
3446 }
3447
3448 static Ecore_X_Randr_Mode *
3449 _ecore_xcb_randr_12_output_modes_get(Ecore_X_Window       root,
3450                                      Ecore_X_Randr_Output output,
3451                                      int                 *num,
3452                                      int                 *npreferred)
3453 {
3454    Ecore_X_Randr_Mode *modes = NULL;
3455 #ifdef ECORE_XCB_RANDR
3456    xcb_randr_get_screen_resources_reply_t *reply;
3457
3458    reply = _ecore_xcb_randr_12_get_resources(root);
3459    if (reply)
3460      {
3461         xcb_randr_get_output_info_cookie_t ocookie;
3462         xcb_randr_get_output_info_reply_t *oreply;
3463
3464         ocookie =
3465           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
3466                                               reply->config_timestamp);
3467         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
3468                                                  ocookie, NULL);
3469         if (oreply)
3470           {
3471              if (num) *num = oreply->num_modes;
3472              if (npreferred) *npreferred = oreply->num_preferred;
3473
3474              modes = malloc(sizeof(Ecore_X_Randr_Mode) *
3475                             oreply->num_modes);
3476              if (modes)
3477                {
3478                   xcb_randr_mode_t *rmodes;
3479                   int len = 0;
3480
3481                   len = xcb_randr_get_output_info_modes_length(oreply);
3482                   rmodes = xcb_randr_get_output_info_modes(oreply);
3483                   memcpy(modes, rmodes, sizeof(Ecore_X_Randr_Mode) * len);
3484                }
3485              free(oreply);
3486           }
3487         free(reply);
3488      }
3489 #endif
3490    return modes;
3491 }
3492
3493 static Ecore_X_Randr_Mode *
3494 _ecore_xcb_randr_13_output_modes_get(Ecore_X_Window       root,
3495                                      Ecore_X_Randr_Output output,
3496                                      int                 *num,
3497                                      int                 *npreferred)
3498 {
3499    Ecore_X_Randr_Mode *modes = NULL;
3500 #ifdef ECORE_XCB_RANDR
3501    xcb_timestamp_t stamp = 0;
3502    xcb_randr_get_output_info_cookie_t ocookie;
3503    xcb_randr_get_output_info_reply_t *oreply;
3504
3505    stamp = _ecore_xcb_randr_13_get_resource_timestamp(root);
3506
3507    ocookie =
3508      xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, stamp);
3509    oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, ocookie, NULL);
3510    if (oreply)
3511      {
3512         if (num) *num = oreply->num_modes;
3513         if (npreferred) *npreferred = oreply->num_preferred;
3514
3515         modes = malloc(sizeof(Ecore_X_Randr_Mode) * oreply->num_modes);
3516         if (modes)
3517           {
3518              xcb_randr_mode_t *rmodes;
3519              int len = 0;
3520
3521              len = xcb_randr_get_output_info_modes_length(oreply);
3522              rmodes = xcb_randr_get_output_info_modes(oreply);
3523              memcpy(modes, rmodes, sizeof(Ecore_X_Randr_Mode) * len);
3524           }
3525         free(oreply);
3526      }
3527 #endif
3528    return modes;
3529 }
3530
3531 static Ecore_X_Randr_Mode_Info *
3532 _ecore_xcb_randr_12_mode_info_get(Ecore_X_Window     root,
3533                                   Ecore_X_Randr_Mode mode)
3534 {
3535    Ecore_X_Randr_Mode_Info *ret = NULL;
3536 #ifdef ECORE_XCB_RANDR
3537    xcb_randr_get_screen_resources_reply_t *reply;
3538
3539    reply = _ecore_xcb_randr_12_get_resources(root);
3540    if (reply)
3541      {
3542         if ((ret = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
3543           {
3544              uint8_t *nbuf;
3545              xcb_randr_mode_info_iterator_t miter;
3546
3547              nbuf = xcb_randr_get_screen_resources_names(reply);
3548              miter = xcb_randr_get_screen_resources_modes_iterator(reply);
3549              while (miter.rem)
3550                {
3551                   xcb_randr_mode_info_t *minfo;
3552
3553                   minfo = miter.data;
3554                   nbuf += minfo->name_len;
3555
3556                   if (minfo->id == mode)
3557                     {
3558                        ret->xid = minfo->id;
3559                        ret->width = minfo->width;
3560                        ret->height = minfo->height;
3561                        ret->dotClock = minfo->dot_clock;
3562                        ret->hSyncStart = minfo->hsync_start;
3563                        ret->hSyncEnd = minfo->hsync_end;
3564                        ret->hTotal = minfo->htotal;
3565                        ret->vSyncStart = minfo->vsync_start;
3566                        ret->vSyncEnd = minfo->vsync_end;
3567                        ret->vTotal = minfo->vtotal;
3568                        ret->modeFlags = minfo->mode_flags;
3569
3570                        ret->name = NULL;
3571                        ret->nameLength = minfo->name_len;
3572                        if (ret->nameLength > 0)
3573                          {
3574                             ret->name = malloc(ret->nameLength + 1);
3575                             if (ret->name)
3576                               memcpy(ret->name, nbuf, ret->nameLength + 1);
3577                          }
3578
3579                        break;
3580                     }
3581                   xcb_randr_mode_info_next(&miter);
3582                }
3583           }
3584
3585         free(reply);
3586      }
3587 #endif
3588    return ret;
3589 }
3590
3591 static Ecore_X_Randr_Mode_Info *
3592 _ecore_xcb_randr_13_mode_info_get(Ecore_X_Window     root,
3593                                   Ecore_X_Randr_Mode mode)
3594 {
3595    Ecore_X_Randr_Mode_Info *ret = NULL;
3596 #ifdef ECORE_XCB_RANDR
3597    xcb_randr_get_screen_resources_current_reply_t *reply;
3598
3599    reply = _ecore_xcb_randr_13_get_resources(root);
3600    if (reply)
3601      {
3602         if ((ret = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
3603           {
3604              uint8_t *nbuf;
3605              xcb_randr_mode_info_iterator_t miter;
3606
3607              nbuf = xcb_randr_get_screen_resources_current_names(reply);
3608              miter =
3609                xcb_randr_get_screen_resources_current_modes_iterator(reply);
3610              while (miter.rem)
3611                {
3612                   xcb_randr_mode_info_t *minfo;
3613
3614                   minfo = miter.data;
3615                   nbuf += minfo->name_len;
3616
3617                   if (minfo->id == mode)
3618                     {
3619                        ret->xid = minfo->id;
3620                        ret->width = minfo->width;
3621                        ret->height = minfo->height;
3622                        ret->dotClock = minfo->dot_clock;
3623                        ret->hSyncStart = minfo->hsync_start;
3624                        ret->hSyncEnd = minfo->hsync_end;
3625                        ret->hTotal = minfo->htotal;
3626                        ret->vSyncStart = minfo->vsync_start;
3627                        ret->vSyncEnd = minfo->vsync_end;
3628                        ret->vTotal = minfo->vtotal;
3629                        ret->modeFlags = minfo->mode_flags;
3630
3631                        ret->name = NULL;
3632                        ret->nameLength = minfo->name_len;
3633                        if (ret->nameLength > 0)
3634                          {
3635                             ret->name = malloc(ret->nameLength + 1);
3636                             if (ret->name)
3637                               memcpy(ret->name, nbuf, ret->nameLength + 1);
3638                          }
3639
3640                        break;
3641                     }
3642                   xcb_randr_mode_info_next(&miter);
3643                }
3644           }
3645
3646         free(reply);
3647      }
3648 #endif
3649    return ret;
3650 }
3651
3652 static Ecore_X_Randr_Mode_Info **
3653 _ecore_xcb_randr_12_modes_info_get(Ecore_X_Window root,
3654                                    int           *num)
3655 {
3656    Ecore_X_Randr_Mode_Info **ret = NULL;
3657 #ifdef ECORE_XCB_RANDR
3658    xcb_randr_get_screen_resources_reply_t *reply;
3659
3660    reply = _ecore_xcb_randr_12_get_resources(root);
3661    if (reply)
3662      {
3663         if (num) *num = reply->num_modes;
3664         ret = malloc(sizeof(Ecore_X_Randr_Mode_Info *) * reply->num_modes);
3665         if (ret)
3666           {
3667              xcb_randr_mode_info_iterator_t miter;
3668              int i = 0;
3669              uint8_t *nbuf;
3670
3671              nbuf = xcb_randr_get_screen_resources_names(reply);
3672              miter = xcb_randr_get_screen_resources_modes_iterator(reply);
3673              while (miter.rem)
3674                {
3675                   xcb_randr_mode_info_t *minfo;
3676
3677                   minfo = miter.data;
3678                   nbuf += minfo->name_len;
3679                   if ((ret[i] = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
3680                     {
3681                        ret[i]->xid = minfo->id;
3682                        ret[i]->width = minfo->width;
3683                        ret[i]->height = minfo->height;
3684                        ret[i]->dotClock = minfo->dot_clock;
3685                        ret[i]->hSyncStart = minfo->hsync_start;
3686                        ret[i]->hSyncEnd = minfo->hsync_end;
3687                        ret[i]->hTotal = minfo->htotal;
3688                        ret[i]->vSyncStart = minfo->vsync_start;
3689                        ret[i]->vSyncEnd = minfo->vsync_end;
3690                        ret[i]->vTotal = minfo->vtotal;
3691                        ret[i]->modeFlags = minfo->mode_flags;
3692
3693                        ret[i]->name = NULL;
3694                        ret[i]->nameLength = minfo->name_len;
3695                        if (ret[i]->nameLength > 0)
3696                          {
3697                             ret[i]->name = malloc(ret[i]->nameLength + 1);
3698                             if (ret[i]->name)
3699                               memcpy(ret[i]->name, nbuf,
3700                                      ret[i]->nameLength + 1);
3701                          }
3702                     }
3703                   else
3704                     {
3705                        while (i > 0)
3706                          free(ret[--i]);
3707                        free(ret);
3708                        ret = NULL;
3709                        break;
3710                     }
3711                   i++;
3712                   xcb_randr_mode_info_next(&miter);
3713                }
3714           }
3715         free(reply);
3716      }
3717 #endif
3718    return ret;
3719 }
3720
3721 static Ecore_X_Randr_Mode_Info **
3722 _ecore_xcb_randr_13_modes_info_get(Ecore_X_Window root,
3723                                    int           *num)
3724 {
3725    Ecore_X_Randr_Mode_Info **ret = NULL;
3726 #ifdef ECORE_XCB_RANDR
3727    xcb_randr_get_screen_resources_current_reply_t *reply;
3728
3729    reply = _ecore_xcb_randr_13_get_resources(root);
3730    if (reply)
3731      {
3732         if (num) *num = reply->num_modes;
3733         ret = malloc(sizeof(Ecore_X_Randr_Mode_Info *) * reply->num_modes);
3734         if (ret)
3735           {
3736              xcb_randr_mode_info_iterator_t miter;
3737              int i = 0;
3738              uint8_t *nbuf;
3739
3740              nbuf = xcb_randr_get_screen_resources_current_names(reply);
3741              miter =
3742                xcb_randr_get_screen_resources_current_modes_iterator(reply);
3743              while (miter.rem)
3744                {
3745                   xcb_randr_mode_info_t *minfo;
3746
3747                   minfo = miter.data;
3748                   nbuf += minfo->name_len;
3749                   if ((ret[i] = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
3750                     {
3751                        ret[i]->xid = minfo->id;
3752                        ret[i]->width = minfo->width;
3753                        ret[i]->height = minfo->height;
3754                        ret[i]->dotClock = minfo->dot_clock;
3755                        ret[i]->hSyncStart = minfo->hsync_start;
3756                        ret[i]->hSyncEnd = minfo->hsync_end;
3757                        ret[i]->hTotal = minfo->htotal;
3758                        ret[i]->vSyncStart = minfo->vsync_start;
3759                        ret[i]->vSyncEnd = minfo->vsync_end;
3760                        ret[i]->vTotal = minfo->vtotal;
3761                        ret[i]->modeFlags = minfo->mode_flags;
3762
3763                        ret[i]->name = NULL;
3764                        ret[i]->nameLength = minfo->name_len;
3765                        if (ret[i]->nameLength > 0)
3766                          {
3767                             ret[i]->name = malloc(ret[i]->nameLength + 1);
3768                             if (ret[i]->name)
3769                               memcpy(ret[i]->name, nbuf,
3770                                      ret[i]->nameLength + 1);
3771                          }
3772                     }
3773                   else
3774                     {
3775                        while (i > 0)
3776                          free(ret[--i]);
3777                        free(ret);
3778                        ret = NULL;
3779                        break;
3780                     }
3781                   i++;
3782                   xcb_randr_mode_info_next(&miter);
3783                }
3784           }
3785         free(reply);
3786      }
3787 #endif
3788    return ret;
3789 }
3790
3791 static void
3792 _ecore_xcb_randr_12_mode_size_get(Ecore_X_Window     root,
3793                                   Ecore_X_Randr_Mode mode,
3794                                   int               *w,
3795                                   int               *h)
3796 {
3797    if (w) *w = 0;
3798    if (h) *h = 0;
3799
3800 #ifdef ECORE_XCB_RANDR
3801    xcb_randr_get_screen_resources_reply_t *reply;
3802
3803    reply = _ecore_xcb_randr_12_get_resources(root);
3804    if (reply)
3805      {
3806         xcb_randr_mode_info_iterator_t miter;
3807
3808         miter = xcb_randr_get_screen_resources_modes_iterator(reply);
3809         while (miter.rem)
3810           {
3811              xcb_randr_mode_info_t *minfo;
3812
3813              minfo = miter.data;
3814              if (minfo->id == mode)
3815                {
3816                   if (w) *w = minfo->width;
3817                   if (h) *h = minfo->height;
3818                   break;
3819                }
3820              xcb_randr_mode_info_next(&miter);
3821           }
3822         free(reply);
3823      }
3824 #endif
3825 }
3826
3827 static void
3828 _ecore_xcb_randr_13_mode_size_get(Ecore_X_Window     root,
3829                                   Ecore_X_Randr_Mode mode,
3830                                   int               *w,
3831                                   int               *h)
3832 {
3833    if (w) *w = 0;
3834    if (h) *h = 0;
3835
3836 #ifdef ECORE_XCB_RANDR
3837    xcb_randr_get_screen_resources_current_reply_t *reply;
3838
3839    reply = _ecore_xcb_randr_13_get_resources(root);
3840    if (reply)
3841      {
3842         xcb_randr_mode_info_iterator_t miter;
3843
3844         miter = xcb_randr_get_screen_resources_current_modes_iterator(reply);
3845         while (miter.rem)
3846           {
3847              xcb_randr_mode_info_t *minfo;
3848
3849              minfo = miter.data;
3850              if (minfo->id == mode)
3851                {
3852                   if (w) *w = minfo->width;
3853                   if (h) *h = minfo->height;
3854                   break;
3855                }
3856              xcb_randr_mode_info_next(&miter);
3857           }
3858         free(reply);
3859      }
3860 #endif
3861 }
3862
3863 static Ecore_X_Randr_Output *
3864 _ecore_xcb_randr_12_output_clones_get(Ecore_X_Window       root,
3865                                       Ecore_X_Randr_Output output,
3866                                       int                 *num)
3867 {
3868    Ecore_X_Randr_Output *outputs = NULL;
3869 #ifdef ECORE_XCB_RANDR
3870    xcb_randr_get_screen_resources_reply_t *reply;
3871
3872    reply = _ecore_xcb_randr_12_get_resources(root);
3873    if (reply)
3874      {
3875         xcb_randr_get_output_info_cookie_t ocookie;
3876         xcb_randr_get_output_info_reply_t *oreply;
3877
3878         ocookie =
3879           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
3880                                               reply->config_timestamp);
3881         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
3882                                                  ocookie, NULL);
3883         if (oreply)
3884           {
3885              if (num) *num = oreply->num_clones;
3886
3887              outputs =
3888                malloc(sizeof(Ecore_X_Randr_Output) * oreply->num_clones);
3889              if (outputs)
3890                {
3891                   memcpy(outputs, xcb_randr_get_output_info_clones(oreply),
3892                          sizeof(Ecore_X_Randr_Output) * oreply->num_clones);
3893                }
3894              free(oreply);
3895           }
3896         free(reply);
3897      }
3898 #endif
3899    return outputs;
3900 }
3901
3902 static Ecore_X_Randr_Output *
3903 _ecore_xcb_randr_13_output_clones_get(Ecore_X_Window       root,
3904                                       Ecore_X_Randr_Output output,
3905                                       int                 *num)
3906 {
3907    Ecore_X_Randr_Output *outputs = NULL;
3908 #ifdef ECORE_XCB_RANDR
3909    xcb_randr_get_screen_resources_current_reply_t *reply;
3910
3911    reply = _ecore_xcb_randr_13_get_resources(root);
3912    if (reply)
3913      {
3914         xcb_randr_get_output_info_cookie_t ocookie;
3915         xcb_randr_get_output_info_reply_t *oreply;
3916
3917         ocookie =
3918           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
3919                                               reply->config_timestamp);
3920         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
3921                                                  ocookie, NULL);
3922         if (oreply)
3923           {
3924              if (num) *num = oreply->num_clones;
3925
3926              outputs =
3927                malloc(sizeof(Ecore_X_Randr_Output) * oreply->num_clones);
3928              if (outputs)
3929                {
3930                   memcpy(outputs, xcb_randr_get_output_info_clones(oreply),
3931                          sizeof(Ecore_X_Randr_Output) * oreply->num_clones);
3932                }
3933              free(oreply);
3934           }
3935         free(reply);
3936      }
3937 #endif
3938    return outputs;
3939 }
3940
3941 static Ecore_X_Randr_Crtc *
3942 _ecore_xcb_randr_12_output_possible_crtcs_get(Ecore_X_Window       root,
3943                                               Ecore_X_Randr_Output output,
3944                                               int                 *num)
3945 {
3946    Ecore_X_Randr_Crtc *crtcs = NULL;
3947 #ifdef ECORE_XCB_RANDR
3948    xcb_randr_get_screen_resources_reply_t *reply;
3949
3950    reply = _ecore_xcb_randr_12_get_resources(root);
3951    if (reply)
3952      {
3953         xcb_randr_get_output_info_cookie_t ocookie;
3954         xcb_randr_get_output_info_reply_t *oreply;
3955
3956         ocookie =
3957           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
3958                                               reply->config_timestamp);
3959         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
3960                                                  ocookie, NULL);
3961         if (oreply)
3962           {
3963              if (num) *num = oreply->num_crtcs;
3964
3965              crtcs = malloc(sizeof(Ecore_X_Randr_Crtc) * oreply->num_crtcs);
3966              if (crtcs)
3967                {
3968                   memcpy(crtcs, xcb_randr_get_output_info_crtcs(oreply),
3969                          sizeof(Ecore_X_Randr_Crtc) * oreply->num_crtcs);
3970                }
3971              free(oreply);
3972           }
3973         free(reply);
3974      }
3975 #endif
3976    return crtcs;
3977 }
3978
3979 static Ecore_X_Randr_Crtc *
3980 _ecore_xcb_randr_13_output_possible_crtcs_get(Ecore_X_Window       root,
3981                                               Ecore_X_Randr_Output output,
3982                                               int                 *num)
3983 {
3984    Ecore_X_Randr_Crtc *crtcs = NULL;
3985 #ifdef ECORE_XCB_RANDR
3986    xcb_randr_get_screen_resources_current_reply_t *reply;
3987
3988    reply = _ecore_xcb_randr_13_get_resources(root);
3989    if (reply)
3990      {
3991         xcb_randr_get_output_info_cookie_t ocookie;
3992         xcb_randr_get_output_info_reply_t *oreply;
3993
3994         ocookie =
3995           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
3996                                               reply->config_timestamp);
3997         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
3998                                                  ocookie, NULL);
3999         if (oreply)
4000           {
4001              if (num) *num = oreply->num_crtcs;
4002
4003              crtcs = malloc(sizeof(Ecore_X_Randr_Crtc) * oreply->num_crtcs);
4004              if (crtcs)
4005                {
4006                   memcpy(crtcs, xcb_randr_get_output_info_crtcs(oreply),
4007                          sizeof(Ecore_X_Randr_Crtc) * oreply->num_crtcs);
4008                }
4009              free(oreply);
4010           }
4011         free(reply);
4012      }
4013 #endif
4014    return crtcs;
4015 }
4016
4017 static char *
4018 _ecore_xcb_randr_12_output_name_get(Ecore_X_Window       root,
4019                                     Ecore_X_Randr_Output output,
4020                                     int                 *len)
4021 {
4022    char *ret = NULL;
4023 #ifdef ECORE_XCB_RANDR
4024    xcb_randr_get_screen_resources_reply_t *reply;
4025
4026    reply = _ecore_xcb_randr_12_get_resources(root);
4027    if (reply)
4028      {
4029         xcb_randr_get_output_info_cookie_t ocookie;
4030         xcb_randr_get_output_info_reply_t *oreply;
4031
4032         ocookie =
4033           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
4034                                               reply->config_timestamp);
4035         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
4036                                                  ocookie, NULL);
4037         if (oreply)
4038           {
4039              uint8_t *nbuf;
4040
4041              nbuf = xcb_randr_get_output_info_name(oreply);
4042
4043              if (len) *len = oreply->name_len;
4044              if (oreply->name_len > 0)
4045                {
4046                   ret = malloc(oreply->name_len + 1);
4047                   if (ret)
4048                     {
4049                        memcpy(ret, nbuf, oreply->name_len + 1);
4050                        ret[oreply->name_len] = '\0';
4051                     }
4052                }
4053
4054              free(oreply);
4055           }
4056         free(reply);
4057      }
4058 #endif
4059    return ret;
4060 }
4061
4062 static char *
4063 _ecore_xcb_randr_13_output_name_get(Ecore_X_Window       root,
4064                                     Ecore_X_Randr_Output output,
4065                                     int                 *len)
4066 {
4067    char *ret = NULL;
4068 #ifdef ECORE_XCB_RANDR
4069    xcb_randr_get_screen_resources_current_reply_t *reply;
4070
4071    reply = _ecore_xcb_randr_13_get_resources(root);
4072    if (reply)
4073      {
4074         xcb_randr_get_output_info_cookie_t ocookie;
4075         xcb_randr_get_output_info_reply_t *oreply;
4076
4077         ocookie =
4078           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
4079                                               reply->config_timestamp);
4080         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
4081                                                  ocookie, NULL);
4082         if (oreply)
4083           {
4084              uint8_t *nbuf;
4085
4086              nbuf = xcb_randr_get_output_info_name(oreply);
4087
4088              if (len) *len = oreply->name_len;
4089              if (oreply->name_len > 0)
4090                {
4091                   ret = malloc(oreply->name_len + 1);
4092                   if (ret)
4093                     {
4094                        memcpy(ret, nbuf, oreply->name_len + 1);
4095                        ret[oreply->name_len] = '\0';
4096                     }
4097                }
4098
4099              free(oreply);
4100           }
4101         free(reply);
4102      }
4103 #endif
4104    return ret;
4105 }
4106
4107 static Ecore_X_Randr_Connection_Status
4108 _ecore_xcb_randr_12_output_connection_status_get(Ecore_X_Window       root,
4109                                                  Ecore_X_Randr_Output output)
4110 {
4111    Ecore_X_Randr_Connection_Status ret = ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
4112 #ifdef ECORE_XCB_RANDR
4113    xcb_randr_get_screen_resources_reply_t *reply;
4114
4115    reply = _ecore_xcb_randr_12_get_resources(root);
4116    if (reply)
4117      {
4118         xcb_randr_get_output_info_cookie_t ocookie;
4119         xcb_randr_get_output_info_reply_t *oreply;
4120
4121         ocookie =
4122           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
4123                                               reply->config_timestamp);
4124         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
4125                                                  ocookie, NULL);
4126         if (oreply)
4127           {
4128              ret = oreply->connection;
4129              free(oreply);
4130           }
4131         free(reply);
4132      }
4133 #endif
4134    return ret;
4135 }
4136
4137 static Ecore_X_Randr_Connection_Status
4138 _ecore_xcb_randr_13_output_connection_status_get(Ecore_X_Window       root,
4139                                                  Ecore_X_Randr_Output output)
4140 {
4141    Ecore_X_Randr_Connection_Status ret = ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
4142 #ifdef ECORE_XCB_RANDR
4143    xcb_randr_get_screen_resources_current_reply_t *reply;
4144
4145    reply = _ecore_xcb_randr_13_get_resources(root);
4146    if (reply)
4147      {
4148         xcb_randr_get_output_info_cookie_t ocookie;
4149         xcb_randr_get_output_info_reply_t *oreply;
4150
4151         ocookie =
4152           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
4153                                               reply->config_timestamp);
4154         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
4155                                                  ocookie, NULL);
4156         if (oreply)
4157           {
4158              ret = oreply->connection;
4159              free(oreply);
4160           }
4161         free(reply);
4162      }
4163 #endif
4164    return ret;
4165 }
4166
4167 static Ecore_X_Randr_Output *
4168 _ecore_xcb_randr_12_outputs_get(Ecore_X_Window root,
4169                                 int           *num)
4170 {
4171    Ecore_X_Randr_Output *ret = NULL;
4172 #ifdef ECORE_XCB_RANDR
4173    xcb_randr_get_screen_resources_reply_t *reply;
4174
4175    reply = _ecore_xcb_randr_12_get_resources(root);
4176    if (reply)
4177      {
4178         if (num) *num = reply->num_outputs;
4179         ret = malloc(sizeof(Ecore_X_Randr_Output) * reply->num_outputs);
4180         if (ret)
4181           memcpy(ret, xcb_randr_get_screen_resources_outputs(reply),
4182                  sizeof(Ecore_X_Randr_Output) * reply->num_outputs);
4183         free(reply);
4184      }
4185 #endif
4186    return ret;
4187 }
4188
4189 static Ecore_X_Randr_Output *
4190 _ecore_xcb_randr_13_outputs_get(Ecore_X_Window root,
4191                                 int           *num)
4192 {
4193    Ecore_X_Randr_Output *ret = NULL;
4194 #ifdef ECORE_XCB_RANDR
4195    xcb_randr_get_screen_resources_current_reply_t *reply;
4196
4197    reply = _ecore_xcb_randr_13_get_resources(root);
4198    if (reply)
4199      {
4200         if (num) *num = reply->num_outputs;
4201         ret = malloc(sizeof(Ecore_X_Randr_Output) * reply->num_outputs);
4202         if (ret)
4203           memcpy(ret, xcb_randr_get_screen_resources_current_outputs(reply),
4204                  sizeof(Ecore_X_Randr_Output) * reply->num_outputs);
4205         free(reply);
4206      }
4207 #endif
4208    return ret;
4209 }
4210
4211 static Ecore_X_Randr_Crtc
4212 _ecore_xcb_randr_12_output_crtc_get(Ecore_X_Window       root,
4213                                     Ecore_X_Randr_Output output)
4214 {
4215    Ecore_X_Randr_Crtc ret = Ecore_X_Randr_None;
4216 #ifdef ECORE_XCB_RANDR
4217    xcb_randr_get_screen_resources_reply_t *reply;
4218
4219    reply = _ecore_xcb_randr_12_get_resources(root);
4220    if (reply)
4221      {
4222         xcb_randr_get_output_info_cookie_t ocookie;
4223         xcb_randr_get_output_info_reply_t *oreply;
4224
4225         ocookie =
4226           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
4227                                               reply->config_timestamp);
4228         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
4229                                                  ocookie, NULL);
4230         if (oreply)
4231           {
4232              ret = oreply->crtc;
4233              free(oreply);
4234           }
4235         free(reply);
4236      }
4237 #endif
4238    return ret;
4239 }
4240
4241 static Ecore_X_Randr_Crtc
4242 _ecore_xcb_randr_13_output_crtc_get(Ecore_X_Window       root,
4243                                     Ecore_X_Randr_Output output)
4244 {
4245    Ecore_X_Randr_Crtc ret = Ecore_X_Randr_None;
4246 #ifdef ECORE_XCB_RANDR
4247    xcb_randr_get_screen_resources_current_reply_t *reply;
4248
4249    reply = _ecore_xcb_randr_13_get_resources(root);
4250    if (reply)
4251      {
4252         xcb_randr_get_output_info_cookie_t ocookie;
4253         xcb_randr_get_output_info_reply_t *oreply;
4254
4255         ocookie =
4256           xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output,
4257                                               reply->config_timestamp);
4258         oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn,
4259                                                  ocookie, NULL);
4260         if (oreply)
4261           {
4262              ret = oreply->crtc;
4263              free(oreply);
4264           }
4265         free(reply);
4266      }
4267 #endif
4268    return ret;
4269 }
4270
4271 static xcb_randr_get_screen_resources_reply_t *
4272 _ecore_xcb_randr_12_get_resources(Ecore_X_Window win)
4273 {
4274    xcb_randr_get_screen_resources_cookie_t cookie;
4275    xcb_randr_get_screen_resources_reply_t *reply;
4276
4277    cookie = xcb_randr_get_screen_resources_unchecked(_ecore_xcb_conn, win);
4278    reply = xcb_randr_get_screen_resources_reply(_ecore_xcb_conn, cookie, NULL);
4279    return reply;
4280 }
4281
4282 static xcb_randr_get_screen_resources_current_reply_t *
4283 _ecore_xcb_randr_13_get_resources(Ecore_X_Window win)
4284 {
4285    xcb_randr_get_screen_resources_current_cookie_t cookie;
4286    xcb_randr_get_screen_resources_current_reply_t *reply;
4287
4288    cookie =
4289      xcb_randr_get_screen_resources_current_unchecked(_ecore_xcb_conn, win);
4290    reply =
4291      xcb_randr_get_screen_resources_current_reply(_ecore_xcb_conn,
4292                                                   cookie, NULL);
4293    return reply;
4294 }
4295
4296 static xcb_timestamp_t
4297 _ecore_xcb_randr_12_get_resource_timestamp(Ecore_X_Window win)
4298 {
4299    xcb_timestamp_t stamp = 0;
4300 #ifdef ECORE_XCB_RANDR
4301    xcb_randr_get_screen_resources_reply_t *reply;
4302
4303    reply = _ecore_xcb_randr_12_get_resources(win);
4304    stamp = reply->config_timestamp;
4305    free(reply);
4306 #endif
4307    return stamp;
4308 }
4309
4310 static xcb_timestamp_t
4311 _ecore_xcb_randr_13_get_resource_timestamp(Ecore_X_Window win)
4312 {
4313    xcb_timestamp_t stamp = 0;
4314 #ifdef ECORE_XCB_RANDR
4315    xcb_randr_get_screen_resources_current_reply_t *reply;
4316
4317    reply = _ecore_xcb_randr_13_get_resources(win);
4318    stamp = reply->config_timestamp;
4319    free(reply);
4320 #endif
4321    return stamp;
4322 }
4323