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