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