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