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