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