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