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