2 * vim:ts=8:sw=3:sts=8:expandtab:cino=>5n-3f0^-2{2
6 #define ECORE_X_RANDR_1_1 ((1 << 16) | 1)
7 #define ECORE_X_RANDR_1_2 ((1 << 16) | 2)
8 #define ECORE_X_RANDR_1_3 ((1 << 16) | 3)
10 #define Ecore_X_Randr_None 0
11 #define Ecore_X_Randr_Unset -1
15 * -fix output policies above and left
18 //following macro namescheme follows cardinal relation
20 #define E_RANDR_NO_SCREEN_RET(ret) if (!e_randr_screen_info) return ret
21 #define E_RANDR_NO_11_RET(ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_1) || !e_randr_screen_info->rrvd_info.randr_info_11) return ret
22 #define E_RANDR_NO_12_RET(ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12) return ret
23 #define E_RANDR_NO_CRTCS_RET(ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->crtcs) return ret
24 #define E_RANDR_NO_OUTPUTS_RET(ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->outputs) return ret
25 #define E_RANDR_NO_CRTC_RET(crtc, ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->crtcs || !crtc) return ret
26 #define E_RANDR_NO_OUTPUT_RET(output, ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->outputs || !output) return ret
27 #define E_RANDR_NO_MODE_RET(mode, ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->modes || !mode) return ret
28 #define E_RANDR_NO_CRTC_OUTPUT_RET(crtc, output, ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->crtcs || !crtc || !e_randr_screen_info->rrvd_info.randr_info_12->outputs || !output) return ret
29 #define E_RANDR_NO_CRTC_OUTPUT_MODE_RET(crtc, output, mode, ret) if (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->crtcs || !crtc || !e_randr_screen_info->rrvd_info.randr_info_12->outputs || !output || !e_randr_screen_info->rrvd_info.randr_info_12->modes || !mode) return ret
31 #define E_RANDR_NO_11 (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_1) || !e_randr_screen_info->rrvd_info.randr_info_11)
32 #define E_RANDR_NO_12 (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12)
33 #define E_RANDR_NO_CRTCS (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->crtcs)
34 #define E_RANDR_NO_OUTPUTS (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->outputs)
35 #define E_RANDR_NO_MODES (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->modes)
36 #define E_RANDR_NO_CRTC(crtc) (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->crtcs || !crtc)
37 #define E_RANDR_NO_OUTPUT(output) (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->outputs || !output)
38 #define E_RANDR_NO_CRTC_OUTPUT(crtc, output) (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->crtcs || !crtc || !e_randr_screen_info->rrvd_info.randr_info_12->outputs || !output)
39 #define E_RANDR_NO_CRTC_OUTPUT_MODE(crtc, output, mode) (!e_randr_screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info->rrvd_info.randr_info_12 || !e_randr_screen_info->rrvd_info.randr_info_12->crtcs || !crtc || !e_randr_screen_info->rrvd_info.randr_info_12->outputs || !output || !e_randr_screen_info->rrvd_info.randr_info_12->modes || !mode)
41 static Eina_Bool _e_randr_init(void);
42 static void _e_randr_shutdown(void);
43 static void _e_randr_event_listeners_add(void);
44 static void _e_randr_event_listeners_remove(void);
45 static Eina_Bool _e_randr_event_cb(void *data, int type, void *e);
46 static E_Randr_Screen_Info *_e_randr_screen_info_new(void);
47 static void _e_randr_screen_info_free(E_Randr_Screen_Info *screen_info);
48 static E_Randr_Screen_Info_11 *_e_randr_screen_info_11_new(void);
49 static Eina_Bool _e_randr_screen_info_11_set(void);
50 static void _e_randr_screen_info_11_free(E_Randr_Screen_Info_11 *screen_info_11);
51 static E_Randr_Screen_Info_12 *_e_randr_screen_info_12_new(void);
52 static Eina_Bool _e_randr_screen_info_12_set(E_Randr_Screen_Info_12 *screen_info_12);
53 static void _e_randr_screen_info_12_free(E_Randr_Screen_Info_12 *screen_info_12);
54 static E_Randr_Output_Info *_e_randr_output_info_new(int nrequested);
55 static void _e_randr_output_info_free(E_Randr_Output_Info *output_info);
56 static E_Randr_Crtc_Info *_e_randr_crtc_info_new(int nrequested);
57 static void _e_randr_crtc_info_free(E_Randr_Crtc_Info *crtc_info);
58 static Eina_Bool _e_randr_screen_outputs_init(void);
59 static Eina_Bool _e_randr_screen_crtcs_init(void);
60 static Eina_Bool _e_randr_output_modes_add(E_Randr_Output_Info *output_info);
61 static void _e_randr_notify_crtc_mode_change(E_Randr_Crtc_Info *crtc_info);
62 static void _e_randr_notify_output_change(E_Randr_Output_Info *output_info);
63 static Ecore_X_Randr_Mode_Info *_e_randr_mode_info_get(Ecore_X_Randr_Mode mode);
64 static E_Randr_Crtc_Info *_e_randr_crtc_info_get(Ecore_X_Randr_Crtc crtc);
65 static E_Randr_Output_Info *_e_randr_output_info_get(Ecore_X_Randr_Output output);
66 static void _e_randr_output_info_set(E_Randr_Output_Info *output_info);
67 static void _e_randr_crtc_info_set(E_Randr_Crtc_Info *crtc_info);
68 static const E_Randr_Crtc_Info *_e_randr_policy_crtc_get(E_Randr_Crtc_Info* but, E_Randr_Crtc_Info *hint, Ecore_X_Randr_Output_Policy policy);
69 //static Eina_Bool _e_randr_outputs_connected(Eina_List *outputs_info);
70 static Ecore_X_Randr_Output *_e_randr_outputs_to_array(Eina_List *outputs_info);
71 //static int _e_randr_config_find_suiting_config_11(E_Randr_Screen_Restore_Info_11** restore_info);
72 static E_Randr_Screen_Restore_Info_12 * _e_randr_config_find_suiting_config_12(void);
73 //static Eina_Bool _e_randr_config_enable_11(int size_index, Ecore_X_Randr_Refresh_Rate refresh_rate, Ecore_X_Randr_Orientation orientation);
74 //static Eina_Bool _e_randr_config_enable_12(const E_Randr_Screen_Restore_Info_12 *restore_info);
75 static Eina_Bool _e_randr_try_enable_output(E_Randr_Output_Info *output_info, Eina_Bool force);
76 static void _e_randr_crtcs_possible_output_update(E_Randr_Output_Info *output_info);
77 static void _e_randr_crtc_outputs_refs_update(E_Randr_Crtc_Info *crtc_info);
78 static Eina_Bool _e_randr_crtc_move_policy(E_Randr_Crtc_Info *new_crtc);
79 //static int _crtcs_size_sort_cb(const void *d1, const void *d2);
80 static int _outputs_size_sort_cb(const void *d1, const void *d2);
81 static int _modes_size_sort_cb(const void *d1, const void *d2);
82 static Eina_List *_e_randr_outputs_common_modes_get(Eina_List *outputs, Ecore_X_Randr_Mode_Info *max_size_mode);
83 static Ecore_X_Randr_Mode_Info *_e_randr_outputs_common_mode_max_get(Eina_List *outputs, Ecore_X_Randr_Mode_Info *max_size_mode);
84 static Ecore_X_Randr_Mode_Info *_e_randr_mode_geo_identical_find(Eina_List *modes, Ecore_X_Randr_Mode_Info *mode);
85 static Eina_Bool _e_randr_crtc_mode_intersects_crtcs(E_Randr_Crtc_Info *crtc_info, Ecore_X_Randr_Mode_Info *mode);
86 static Eina_Bool _e_randr_crtc_outputs_mode_max_set(E_Randr_Crtc_Info *crtc_info);
87 static Eina_Bool _e_randr_crtcs_clone_crtc_removed(E_Randr_Crtc_Info *former_clone);
88 static void _e_randr_screen_primary_output_assign(E_Randr_Output_Info *removed);
89 static void _e_randr_output_info_hw_info_set(E_Randr_Output_Info *output_info);
90 static void _e_randr_output_hw_info_free(E_Randr_Output_Info *output_info);
91 static Eina_Bool _e_randr_outputs_are_clones(E_Randr_Output_Info *output_info, Eina_List *outputs);
93 E_Randr_Screen_Info *e_randr_screen_info = NULL;
94 static Eina_List *_e_randr_event_handlers = NULL;
99 return _e_randr_init();
103 e_randr_shutdown(void)
113 Ecore_X_Window *roots;
116 if(!(roots = ecore_x_window_root_list(&n))) return EINA_FALSE;
117 /* first (and only) root window */
121 if (!ecore_x_randr_query() || !(e_randr_screen_info = _e_randr_screen_info_new()))
122 goto ecore_x_randr_init_fail_free_screen;
124 if ((e_randr_screen_info->randr_version = ecore_x_randr_version_get()))
125 e_randr_screen_info->root = root;
126 if (e_randr_screen_info->randr_version == ECORE_X_RANDR_1_1)
128 if (!(e_randr_screen_info->rrvd_info.randr_info_11 = _e_randr_screen_info_11_new()))
129 goto ecore_x_randr_init_fail_free_screen;
130 _e_randr_screen_info_11_set();
131 //_e_randr_config_find_and_enable();
134 else if (e_randr_screen_info->randr_version >= ECORE_X_RANDR_1_2)
136 if (!(e_randr_screen_info->rrvd_info.randr_info_12 = _e_randr_screen_info_12_new()))
137 goto ecore_x_randr_init_fail_free_screen;
138 _e_randr_screen_info_12_set(e_randr_screen_info->rrvd_info.randr_info_12);
139 _e_randr_event_listeners_add();
140 if (!_e_randr_screen_outputs_init())
141 goto ecore_x_randr_init_fail_free_screen;
142 if (!_e_randr_screen_crtcs_init())
143 goto ecore_x_randr_init_fail_free_screen;
144 _e_randr_screen_primary_output_assign(NULL);
148 //FILO free stack in case we fail to allocate something/can't get hold of
149 //necessary information
150 ecore_x_randr_init_fail_free_screen:
151 if (e_randr_screen_info)
152 _e_randr_screen_info_free(e_randr_screen_info);
158 _e_randr_shutdown(void)
160 _e_randr_screen_info_free(e_randr_screen_info);
165 * @return Instance of E_Randr_Screen_Info or if memory couldn't be
168 static E_Randr_Screen_Info *
169 _e_randr_screen_info_new(void)
171 E_Randr_Screen_Info *ret = NULL;
172 E_Randr_Screen_Info default_info =
174 .root = Ecore_X_Randr_Unset,
175 .randr_version = Ecore_X_Randr_None,
176 .rrvd_info.randr_info_11 = NULL
179 if (!(ret = malloc(sizeof(E_Randr_Screen_Info)))) return NULL;
181 memcpy(ret, &default_info, sizeof(default_info));
187 * @param screen_info the screen info to free.
190 _e_randr_screen_info_free(E_Randr_Screen_Info *screen_info)
192 if ((!screen_info) || !(screen_info->rrvd_info.randr_info_11)) return;
193 switch (e_randr_screen_info->randr_version)
195 case ECORE_X_RANDR_1_1:
196 _e_randr_screen_info_11_free(screen_info->rrvd_info.randr_info_11);
198 case ECORE_X_RANDR_1_2:
199 case ECORE_X_RANDR_1_3:
200 _e_randr_screen_info_12_free(screen_info->rrvd_info.randr_info_12);
208 * @return array of E_Randr_Screen_Info_11 elements, or in case not all could
209 * be created or parameter 'nrequested'==0, NULL
211 static E_Randr_Screen_Info_11 *
212 _e_randr_screen_info_11_new(void)
214 E_Randr_Screen_Info_11 *ret = NULL;
215 static const E_Randr_Screen_Info_11 default_info =
218 .csize_index = Ecore_X_Randr_Unset,
219 .corientation = Ecore_X_Randr_Unset,
220 .orientations = Ecore_X_Randr_Unset,
222 .current_rate = Ecore_X_Randr_Unset
225 if (!(ret = malloc(sizeof(E_Randr_Screen_Info_11)))) return NULL;
227 ret = memcpy(ret, &default_info, sizeof(default_info));
233 * @param screen_info the screen info to be freed.
236 _e_randr_screen_info_11_free(E_Randr_Screen_Info_11 *screen_info)
238 if (!screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_1))
241 if (screen_info->sizes)
243 free(eina_list_nth(screen_info->sizes, 0));
244 eina_list_free(screen_info->sizes);
246 if (screen_info->rates)
248 /* this may be leaking, but at least it will be valid */
249 eina_list_free(eina_list_nth(screen_info->rates, 0));
250 eina_list_free(screen_info->rates);
257 * @return array of E_Randr_Screen_Info_12 elements, or in case not all could
258 * be created or parameter 'nrequested'==0, NULL
260 static E_Randr_Screen_Info_12 *
261 _e_randr_screen_info_12_new(void)
263 E_Randr_Screen_Info_12 *ret = NULL;
264 static const E_Randr_Screen_Info_12 default_info =
266 .min_size = {Ecore_X_Randr_Unset, Ecore_X_Randr_Unset},
267 .max_size = {Ecore_X_Randr_Unset, Ecore_X_Randr_Unset},
268 .current_size = {Ecore_X_Randr_Unset, Ecore_X_Randr_Unset},
271 .primary_output = NULL,
272 .output_policy = ECORE_X_RANDR_OUTPUT_POLICY_NONE,
273 .alignment = ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE
276 if (!(ret = malloc(sizeof(E_Randr_Screen_Info_12)))) return NULL;
277 ret = memcpy(ret, &default_info, sizeof(default_info));
283 _e_randr_screen_info_12_set(E_Randr_Screen_Info_12 *screen_info)
285 E_RANDR_NO_12_RET(EINA_FALSE);
287 ecore_x_randr_screen_size_range_get(e_randr_screen_info->root,
288 &screen_info->min_size.width,
289 &screen_info->min_size.height,
290 &screen_info->max_size.width ,
291 &screen_info->max_size.height);
292 ecore_x_randr_screen_current_size_get(e_randr_screen_info->root,
293 &screen_info->current_size.width ,
294 &screen_info->current_size.height ,
301 _e_randr_screen_info_11_set(void)
303 E_RANDR_NO_11_RET(EINA_FALSE);
305 E_Randr_Screen_Info_11 *screen_info_11 = e_randr_screen_info->rrvd_info.randr_info_11;
306 Ecore_X_Randr_Screen_Size_MM *sizes = NULL;
307 Ecore_X_Randr_Refresh_Rate *rates = NULL;
308 Eina_List *rates_list;
309 int i, j, nsizes, nrates;
311 if (!(sizes = ecore_x_randr_screen_primary_output_sizes_get(e_randr_screen_info->root, &nsizes)))
313 for (i = 0; i < nsizes; i++)
314 if (!(screen_info_11->sizes = eina_list_append(screen_info_11->sizes, &sizes[i])))
315 goto _e_randr_screen_info_11_fill_fail_sizes;
316 ecore_x_randr_screen_primary_output_current_size_get(e_randr_screen_info->root, NULL, NULL, NULL, NULL, &(screen_info_11->csize_index));
317 screen_info_11->corientation = ecore_x_randr_screen_primary_output_orientation_get(e_randr_screen_info->root);
318 screen_info_11->orientations = ecore_x_randr_screen_primary_output_orientations_get(e_randr_screen_info->root);
319 for (i = 0; i < nsizes; i++)
322 if (!(rates = ecore_x_randr_screen_primary_output_refresh_rates_get(e_randr_screen_info->root, i, &nrates)))
324 for (j = 0; j < nrates; j++)
325 if (!(rates_list = eina_list_append(rates_list, &rates[j])))
326 goto _e_randr_screen_info_11_fill_fail_rates_list;
327 if (!(screen_info_11->rates = eina_list_append(screen_info_11->rates, rates_list)))
328 goto _e_randr_screen_info_11_fill_fail_rates;
330 screen_info_11->current_rate = ecore_x_randr_screen_primary_output_current_refresh_rate_get(e_randr_screen_info->root);
334 _e_randr_screen_info_11_fill_fail_rates_list:
335 eina_list_free(rates_list);
336 _e_randr_screen_info_11_fill_fail_rates:
338 _e_randr_screen_info_11_fill_fail_sizes:
340 free(screen_info_11);
345 * @param screen_info the screen info to be freed.
348 _e_randr_screen_info_12_free(E_Randr_Screen_Info_12 *screen_info)
350 Ecore_X_Randr_Mode_Info *mode_info;
351 E_Randr_Crtc_Info *crtc_info;
352 E_Randr_Output_Info *output_info;
354 if (!screen_info || (e_randr_screen_info->randr_version < ECORE_X_RANDR_1_2)) return;
356 if (e_randr_screen_info->randr_version >= ECORE_X_RANDR_1_2 && screen_info->crtcs)
358 EINA_LIST_FREE(screen_info->crtcs, crtc_info)
359 _e_randr_crtc_info_free(crtc_info);
360 free(eina_list_nth(screen_info->crtcs, 0));
363 if (e_randr_screen_info->randr_version >= ECORE_X_RANDR_1_2 && screen_info->outputs)
365 EINA_LIST_FREE(screen_info->outputs, output_info)
366 _e_randr_output_info_free(output_info);
367 free(eina_list_nth(screen_info->outputs, 0));
370 if (e_randr_screen_info->randr_version >= ECORE_X_RANDR_1_2 && screen_info->modes)
372 EINA_LIST_FREE(screen_info->modes, mode_info)
373 ecore_x_randr_mode_info_free(mode_info);
376 _e_randr_event_listeners_remove();
383 * @brief allocates structs with and fills them with default values. The
384 * returned pointer is allocated as one chunk of data since it won't change.
385 * @param nrequested number of E_Randr_Crtc_Info to be created
386 * @return array of E_Randr_Crtc_Info elements, or in case not all could
387 * be created or parameter 'nrequested'==0, NULL
389 static E_Randr_Crtc_Info *
390 _e_randr_crtc_info_new(int nrequested)
392 E_Randr_Crtc_Info *ret = NULL;
393 static E_Randr_Crtc_Info default_info =
395 .xid = Ecore_X_Randr_Unset,
396 .geometry = {Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, Ecore_X_Randr_Unset},
397 .panning = {Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, Ecore_X_Randr_Unset},
398 .tracking = {Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, Ecore_X_Randr_Unset},
399 .border = {Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, Ecore_X_Randr_Unset},
400 .current_orientation = ECORE_X_RANDR_ORIENTATION_ROT_0,
401 .orientations = Ecore_X_Randr_Unset,
403 .gamma_ramp_size = Ecore_X_Randr_Unset,
405 .possible_outputs = NULL
408 if (!(ret = malloc(sizeof(E_Randr_Crtc_Info) * nrequested))) return NULL;
410 while (nrequested > 0)
412 memcpy(&ret[--nrequested], &default_info, sizeof(default_info));
419 * @param crtc_info the crtc info to be freed.
422 _e_randr_crtc_info_free(E_Randr_Crtc_Info *crtc_info)
424 if (!crtc_info) return;
426 if (crtc_info->gamma_ramps) free(crtc_info->gamma_ramps);
427 if (crtc_info->outputs) eina_list_free(crtc_info->outputs);
428 if (crtc_info->possible_outputs) eina_list_free(crtc_info->possible_outputs);
432 * @brief allocates structs with and fills them with default values. The
433 * returned pointer is allocated as one chunk of data since it won't change.
434 * @param nrequested number of E_Randr_Output_Info to be created
435 * @return E_Randr_Output_Info element, or it could not be
438 static E_Randr_Output_Info *
439 _e_randr_output_info_new(int nrequested)
441 E_Randr_Output_Info *ret = NULL;
442 static E_Randr_Output_Info default_info =
444 .xid = Ecore_X_Randr_Unset,
447 .possible_crtcs = NULL,
448 .preferred_modes = NULL,
449 .max_backlight = Ecore_X_Randr_Unset,
450 .backlight_level = 0.0,
453 .size_mm = {Ecore_X_Randr_Unset, Ecore_X_Randr_Unset},
454 .wired_clones = NULL,
455 .signalformats = Ecore_X_Randr_Unset,
456 .signalformat = Ecore_X_Randr_Unset,
457 .connector_number = Ecore_X_Randr_Unset,
458 .connector_type = Ecore_X_Randr_Unset,
459 .connection_status = ECORE_X_RANDR_CONNECTION_STATUS_DISCONNECTED,
460 .subpixel_order= Ecore_X_Randr_Unset,
461 .compatible_outputs = NULL
464 if (!(ret = malloc(sizeof(E_Randr_Output_Info) * nrequested))) return NULL;
466 while (nrequested > 0)
468 memcpy(&ret[--nrequested], &default_info, sizeof(default_info));
475 * removes all traces of an output within the data.
476 * @param output_info the output info to be freed.
479 _e_randr_output_info_free(E_Randr_Output_Info *output_info)
482 E_Randr_Crtc_Info *crtc_info;
484 if (!output_info) return;
485 if (output_info->name)
487 free(output_info->name);
488 output_info->name = NULL;
490 _e_randr_output_hw_info_free(output_info);
492 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
494 crtc_info->outputs = eina_list_remove(crtc_info->outputs, output_info);
499 _e_randr_output_info_set(E_Randr_Output_Info *output_info)
501 if (E_RANDR_NO_12 || !output_info) return;
503 output_info->name = ecore_x_randr_output_name_get(e_randr_screen_info->root, output_info->xid, &output_info->name_length);
504 output_info->connection_status = ecore_x_randr_output_connection_status_get(e_randr_screen_info->root, output_info->xid);
508 * fills a given crtc_info using its xid with
509 * - geometry data (x,y,w,h)
510 * - used outputs structs
511 * - possible outputs structs
513 * - connection status
517 _e_randr_crtc_info_set(E_Randr_Crtc_Info *crtc_info)
519 Ecore_X_Randr_Mode mode = 0;
520 fprintf(stderr, "Fillng CRTC %d (%p)\n", crtc_info->xid, crtc_info);
521 if (E_RANDR_NO_12 || !crtc_info) return;
523 //get references to used and possible E_Randr_Output_Info structs
524 _e_randr_crtc_outputs_refs_update(crtc_info);
526 ecore_x_randr_crtc_geometry_get(e_randr_screen_info->root, crtc_info->xid, &crtc_info->geometry.x, &crtc_info->geometry.y, &crtc_info->geometry.w, &crtc_info->geometry.h);
527 mode = ecore_x_randr_crtc_mode_get(e_randr_screen_info->root, crtc_info->xid);
528 crtc_info->current_mode = _e_randr_mode_info_get(mode);
529 fprintf(stderr, "CRTC %d apparently is in mode %d, trying to find it in the list of modes..\n", crtc_info->xid, mode);
530 if (crtc_info->current_mode)
531 fprintf(stderr, "found CRTC %d in mode %d\n", crtc_info->xid, crtc_info->current_mode->xid);
532 crtc_info->current_orientation = ecore_x_randr_crtc_orientation_get(e_randr_screen_info->root, crtc_info->xid);
533 crtc_info->outputs_common_modes = _e_randr_outputs_common_modes_get(crtc_info->outputs, NULL);
537 * looks up modes supported by an output and adds them - if they are not already
538 * known by - to the screen's information struct ant the output_info itself
541 _e_randr_output_modes_add(E_Randr_Output_Info *output_info)
543 Ecore_X_Randr_Mode *modes;
544 Ecore_X_Randr_Mode_Info *mode_info;
545 int nmodes, npreferred;
547 Eina_Bool added_yet = EINA_FALSE;
549 if (E_RANDR_NO_12 || !(modes = ecore_x_randr_output_modes_get(e_randr_screen_info->root, output_info->xid, &nmodes, &npreferred))) return EINA_FALSE;
551 //In case the monitor does not have any preferred mode at all
552 if (nmodes > 0 && npreferred == 0) npreferred = 1;
554 while (--nmodes >= 0)
556 added_yet = EINA_FALSE;
557 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->modes, iter, mode_info)
559 if (mode_info && mode_info->xid == modes[nmodes])
561 added_yet = EINA_TRUE;
567 mode_info = ecore_x_randr_mode_info_get(e_randr_screen_info->root, modes[nmodes]);
568 e_randr_screen_info->rrvd_info.randr_info_12->modes = eina_list_prepend(e_randr_screen_info->rrvd_info.randr_info_12->modes, mode_info);
570 output_info->modes = eina_list_prepend(output_info->modes, mode_info);
571 if (nmodes < npreferred) output_info->preferred_modes = eina_list_prepend(output_info->preferred_modes, mode_info);
580 _e_randr_screen_crtcs_init(void)
582 Ecore_X_Randr_Crtc *crtcs = NULL;
583 E_Randr_Crtc_Info *crtcs_info = NULL, *crtc = NULL;
586 if (E_RANDR_NO_12 || !(crtcs = ecore_x_randr_crtcs_get(e_randr_screen_info->root, &ncrtcs))) return EINA_FALSE;
588 if (!(crtcs_info = _e_randr_crtc_info_new(ncrtcs))) goto ecore_x_randr_screen_crtcs_init_fail_free_crtcs;
589 for (i = 0; i < ncrtcs; i++)
591 fprintf (stderr, "E_RANDR: filling %d/%d (%d)\n", (i + 1), ncrtcs, crtcs[i]);
592 crtcs_info[i].xid = crtcs[i];
593 _e_randr_crtc_info_set(&crtcs_info[i]);
594 if(!(e_randr_screen_info->rrvd_info.randr_info_12->crtcs = eina_list_append(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, &crtcs_info[i]))) break;
598 //successfully initialized crtcs!
602 EINA_LIST_FREE(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, crtc)
603 _e_randr_crtc_info_free(crtc);
604 if (e_randr_screen_info->rrvd_info.randr_info_12->crtcs)
606 free(eina_list_nth(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, 0));
609 ecore_x_randr_screen_crtcs_init_fail_free_crtcs:
615 _e_randr_screen_outputs_init(void)
617 Ecore_X_Randr_Output *outputs;
618 E_Randr_Output_Info *outputs_info = NULL, *output_info = NULL;
620 if (E_RANDR_NO_12 || !(outputs = ecore_x_randr_outputs_get(e_randr_screen_info->root, &noutputs))) return EINA_FALSE;
622 if (!(outputs_info = _e_randr_output_info_new(noutputs))) goto _e_randr_screen_outputs_init_fail_free_outputs;
623 while (--noutputs >= 0)
625 outputs_info[noutputs].xid = outputs[noutputs];
626 _e_randr_output_info_set(&outputs_info[noutputs]);
627 outputs_info[noutputs].connection_status = ecore_x_randr_output_connection_status_get(e_randr_screen_info->root, outputs_info[noutputs].xid);
628 if (outputs_info[noutputs].connection_status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
629 _e_randr_output_info_hw_info_set(&outputs_info[noutputs]);
631 if (!(e_randr_screen_info->rrvd_info.randr_info_12->outputs = eina_list_append(e_randr_screen_info->rrvd_info.randr_info_12->outputs, &outputs_info[noutputs]))) goto _e_randr_screen_outputs_init_fail_free_outputs_list;
637 _e_randr_screen_outputs_init_fail_free_outputs_list:
638 if (e_randr_screen_info->rrvd_info.randr_info_12->outputs)
640 EINA_LIST_FREE(e_randr_screen_info->rrvd_info.randr_info_12->outputs, output_info)
643 _e_randr_screen_outputs_init_fail_free_outputs:
648 static Ecore_X_Randr_Mode_Info*
649 _e_randr_mode_info_get(Ecore_X_Randr_Mode mode)
652 Ecore_X_Randr_Mode_Info* mode_info;
654 E_RANDR_NO_MODE_RET(mode, NULL);
655 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->modes, iter, mode_info)
657 if (mode_info && mode_info->xid == mode) return mode_info;
662 static E_Randr_Output_Info*
663 _e_randr_output_info_get(Ecore_X_Randr_Output output)
666 E_Randr_Output_Info* output_info;
668 E_RANDR_NO_OUTPUTS_RET(NULL);
669 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->outputs, iter, output_info)
671 if (output_info && output_info->xid == output) return output_info;
676 static E_Randr_Crtc_Info*
677 _e_randr_crtc_info_get(Ecore_X_Randr_Crtc crtc)
680 E_Randr_Crtc_Info* crtc_info;
682 E_RANDR_NO_CRTCS_RET(NULL);
683 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
685 if (crtc_info && crtc_info->xid == crtc) return crtc_info;
691 _e_randr_event_cb(void *data __UNUSED__, int type, void *ev)
693 E_Randr_Crtc_Info *crtc_info;
696 if (!e_randr_screen_info) return ECORE_CALLBACK_RENEW;
697 if (type == ECORE_X_EVENT_RANDR_CRTC_CHANGE)
699 Ecore_X_Event_Randr_Crtc_Change *event = (Ecore_X_Event_Randr_Crtc_Change*) ev;
700 /* available information:
701 struct _Ecore_X_Event_Randr_Crtc_Change
704 Ecore_X_Randr_Crtc crtc;
705 Ecore_X_Randr_Mode mode;
706 Ecore_X_Randr_Orientation orientation;
713 crtc_info = _e_randr_crtc_info_get(event->crtc);
714 if (!crtc_info) goto on_exit;
716 if (event->mode != Ecore_X_Randr_None)
719 if ((crtc_info->current_mode != _e_randr_mode_info_get(event->mode)))
721 crtc_info->current_mode = _e_randr_mode_info_get(event->mode);
722 _e_randr_notify_crtc_mode_change(crtc_info);
725 crtc_info->current_mode = _e_randr_mode_info_get(event->mode);
726 crtc_info->current_orientation = event->orientation;
727 crtc_info->geometry.x = event->geo.x;
728 crtc_info->geometry.y = event->geo.y;
729 crtc_info->geometry.w = event->geo.w;
730 crtc_info->geometry.h = event->geo.h;
731 //update screensize if necessary
732 e_randr_screen_info->rrvd_info.randr_info_12->current_size.width = MAX((event->geo.x + event->geo.w), e_randr_screen_info->rrvd_info.randr_info_12->current_size.width);
733 e_randr_screen_info->rrvd_info.randr_info_12->current_size.height = MAX((event->geo.y + event->geo.h), e_randr_screen_info->rrvd_info.randr_info_12->current_size.height);
737 //set the max mode common amongst outputs
738 _e_randr_crtcs_clone_crtc_removed(crtc_info);
741 crtc_info->current_orientation = event->orientation;
742 crtc_info->geometry.x = 0;
743 crtc_info->geometry.y = 0;
744 crtc_info->geometry.w = 0;
745 crtc_info->geometry.h = 0;
746 crtc_info->current_mode = NULL;
747 if (crtc_info->outputs) eina_list_free(crtc_info->outputs);
748 crtc_info->outputs = NULL;
750 //update screensize of necessary
751 ecore_x_randr_screen_reset(e_randr_screen_info->root);
752 ecore_x_randr_screen_current_size_get(e_randr_screen_info->root, &e_randr_screen_info->rrvd_info.randr_info_12->current_size.width, &e_randr_screen_info->rrvd_info.randr_info_12->current_size.height, NULL, NULL);
755 else if (type == ECORE_X_EVENT_RANDR_OUTPUT_CHANGE)
757 Ecore_X_Event_Randr_Output_Change *event = ev;
758 const E_Randr_Screen_Restore_Info_12 *restore_info;
759 E_Randr_Output_Info* output_info = NULL;
760 /* available information:
761 struct _Ecore_X_Event_Randr_Output_Change
764 Ecore_X_Randr_Output output;
765 Ecore_X_Randr_Crtc crtc;
766 Ecore_X_Randr_Mode mode;
767 Ecore_X_Randr_Orientation orientation;
768 Ecore_X_Randr_Connection_Status connection;
769 Ecore_X_Render_Subpixel_Order subpixel_order;
772 fprintf(stderr, "E_RANDR: Output connected!: \n \
773 E_RANDR: relative to win: %d\n \
774 E_RANDR: relative to output: %d\n \
775 E_RANDR: relative to crtc: %d\n \
776 E_RANDR: relative to mode: %d\n \
777 E_RANDR: relative to orientation: %d\n \
778 E_RANDR: relative to connction: %d (connected = %d, disconnected = %d, unknown %d)\n \
779 E_RANDR: relative to subpixel_order: %d\n",
780 event->win, event->output, event->crtc, event->mode, event->orientation, event->connection, ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED, ECORE_X_RANDR_CONNECTION_STATUS_DISCONNECTED, ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN, event->subpixel_order);
782 output_info = _e_randr_output_info_get(event->output);
783 if (!output_info) goto on_exit;
785 if ((output_info->crtc = _e_randr_crtc_info_get(event->crtc)))
787 if (!eina_list_data_find(output_info->crtc->outputs, output_info))
788 output_info->crtc->outputs = eina_list_append(output_info->crtc->outputs, output_info);
791 output_info->connection_status = event->connection;
792 output_info->subpixel_order = event->subpixel_order;
794 if (event->connection == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
797 output_info->crtc = _e_randr_crtc_info_get(event->crtc);
799 if (output_info && !output_info->crtc && !event->crtc && !event->mode)
801 //Monitor was attached!
802 _e_randr_output_info_hw_info_set(output_info);
803 //make the crtcs aware of their possibly new output
804 _e_randr_crtcs_possible_output_update(output_info);
805 if ((restore_info = _e_randr_config_find_suiting_config_12()))
806 //maybe we have a suiting configuration
807 //_e_randr_config_enable_12(restore_info);
810 enabled = _e_randr_try_enable_output(output_info, EINA_FALSE); //maybe give a success message?
812 _e_randr_notify_output_change(output_info);
814 else if (event->connection == ECORE_X_RANDR_CONNECTION_STATUS_DISCONNECTED)
816 if (output_info->crtc)
818 //remove output from CRTC
819 output_info->crtc->outputs = eina_list_remove(output_info->crtc->outputs, output_info);
820 if (output_info->crtc->current_mode)
822 //in case this output was enabled on some CRTC
823 if (eina_list_count(output_info->crtc->outputs) == 0)
825 //in case it was the only output running on this CRTC, disable
827 ecore_x_randr_crtc_mode_set(e_randr_screen_info->root, output_info->crtc->xid, NULL, Ecore_X_Randr_None, Ecore_X_Randr_None);
828 //crop the screen of course.
829 ecore_x_randr_screen_reset(e_randr_screen_info->root);
832 _e_randr_crtc_outputs_mode_max_set(output_info->crtc);
835 if (e_randr_screen_info->rrvd_info.randr_info_12->primary_output && (output_info == e_randr_screen_info->rrvd_info.randr_info_12->primary_output))
836 _e_randr_screen_primary_output_assign(output_info);
837 //let's try to get a proper config for the new setup and crop the
839 if ((restore_info = _e_randr_config_find_suiting_config_12()))
841 //in case we didn't have, init it anyway...
842 //_e_randr_config_enable_12(restore_info);
845 _e_randr_notify_output_change(output_info);
846 _e_randr_output_hw_info_free(output_info);
849 else if (type == ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY)
851 //Ecore_X_Event_Randr_Output_Property_Notify *event = (Ecore_X_Event_Randr_Output_Property_Notify*) ev;
852 /* available information:
853 struct _Ecore_X_Event_Randr_Output_Property_Notify
856 Ecore_X_Randr_Output output;
857 Ecore_X_Atom property;
859 Ecore_X_Randr_Property_Change state;
864 return ECORE_CALLBACK_RENEW;
868 _e_randr_event_listeners_add(void)
870 if (E_RANDR_NO_12) return;
871 ecore_x_randr_events_select(e_randr_screen_info->root, EINA_TRUE);
872 _e_randr_event_handlers= eina_list_append(_e_randr_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_CRTC_CHANGE, _e_randr_event_cb, NULL));
873 _e_randr_event_handlers= eina_list_append(_e_randr_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, _e_randr_event_cb, NULL));
874 _e_randr_event_handlers= eina_list_append(_e_randr_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, _e_randr_event_cb, NULL));
878 _e_randr_event_listeners_remove(void)
880 Ecore_Event_Handler *_event_handler = NULL;
881 EINA_LIST_FREE(_e_randr_event_handlers, _event_handler)
882 ecore_event_handler_del(_event_handler);
886 _e_randr_notify_crtc_mode_change(E_Randr_Crtc_Info *crtc_info)
888 // E_Notification *n;
891 if (crtc_info->current_mode)
893 // snprintf(buff, 200, "New resolution is %dx%d. Click here for further information.", crtc_info->current_mode->width, crtc_info->current_mode->height);
894 // n = e_notification_full_new("RandRR", crtc_info->xid, NULL, "Resolution changed", buff, -1);
895 // //n = e_notification_full_new("RandRR", id, icon, function, body, timeout);
896 // e_notification_send(n, NULL, NULL);
897 // e_notification_unref(n);
901 _e_randr_notify_output_change(E_Randr_Output_Info *output_info)
903 // E_Notification *n;
905 if (output_info->connection_status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
907 // snprintf(buff, 100, "Output %s connected", output_info->name);
908 // n = e_notification_full_new("RandRR", output_info->xid, NULL, buff, "Click here for further information.", -1);
912 // snprintf(buff, 100, "Output %s disconnected", output_info->name);
913 // n = e_notification_full_new("RandRR", output_info->xid, NULL, buff, "Click here to adjust screen setup.", -1);
916 // //n = e_notification_full_new("RandRR", id, icon, function, body, timeout);
917 // e_notification_send(n, NULL, NULL);
918 // e_notification_unref(n);
922 * this retrieves a CRTC depending on a policy.
923 * Note that this is enlightenment specific! Enlightenment doesn't 'allow' zones
924 * to overlap. Thus we always use the output with the most extreme position
925 * instead of trying to fill gaps like tetris. Though this could be done by
926 * simply implementing another policy.
928 static const E_Randr_Crtc_Info*
929 _e_randr_policy_crtc_get(E_Randr_Crtc_Info *but, E_Randr_Crtc_Info *hint __UNUSED__, Ecore_X_Randr_Output_Policy policy)
932 E_Randr_Crtc_Info *crtc_info, *ret = NULL;
934 E_RANDR_NO_CRTCS_RET(NULL);
936 //get any crtc that besides 'but' to start with
937 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
939 if (crtc_info != but)
945 if (!ret && (policy != ECORE_X_RANDR_OUTPUT_POLICY_CLONE)) return NULL;
949 case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
950 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
952 if (crtc_info && (crtc_info != but) && (crtc_info->geometry.y <= ret->geometry.y))
958 case ECORE_X_RANDR_OUTPUT_POLICY_RIGHT:
959 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
961 if (crtc_info && (crtc_info != but) && ((crtc_info->geometry.x + crtc_info->geometry.w) >= (ret->geometry.x + ret->geometry.w)))
968 case ECORE_X_RANDR_OUTPUT_POLICY_BELOW:
969 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
971 if (crtc_info && (crtc_info != but) && ((crtc_info->geometry.y + crtc_info->geometry.h) >= (ret->geometry.y + ret->geometry.h)))
978 case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
979 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
981 if (crtc_info && (crtc_info != but) && (crtc_info->geometry.x <= ret->geometry.x))
988 case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
989 ret = (e_randr_screen_info->rrvd_info.randr_info_12->primary_output) ? e_randr_screen_info->rrvd_info.randr_info_12->primary_output->crtc : NULL;
1000 _e_randr_outputs_connected(Eina_List *outputs_info)
1003 E_Randr_Output_Info *output_info;
1005 EINA_LIST_FOREACH(outputs_info, iter, output_info)
1006 if (output_info->connection_status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) return EINA_TRUE;
1011 _e_randr_config_enable_11(int size_index, Ecore_X_Randr_Refresh_Rate refresh_rate, Ecore_X_Randr_Orientation orientation)
1013 E_Randr_Screen_Info_11 *current_info_11;
1015 if (E_RANDR_NO_11 || (size_index < 0) || (refresh_rate < 0) ||
1016 (orientation < 0)) return EINA_FALSE;
1018 if (!ecore_x_randr_screen_primary_output_size_set(e_randr_screen_info->root, size_index)
1019 || !ecore_x_randr_screen_primary_output_orientation_set(e_randr_screen_info->root, orientation)
1020 || !ecore_x_randr_screen_primary_output_refresh_rate_set(e_randr_screen_info->root, size_index, refresh_rate)) return EINA_FALSE;
1022 //TODO: move this to the screen event later.
1023 current_info_11 = e_randr_screen_info->rrvd_info.randr_info_11;
1025 current_info_11->csize_index = size_index;
1026 current_info_11->corientation = orientation;
1027 current_info_11->current_rate = refresh_rate;
1033 _e_randr_config_enable_12(const E_Randr_Screen_Restore_Info_12 *restore_info __UNUSED__)
1035 if (E_RANDR_NO_12 || !restore_info) return EINA_FALSE;
1036 E_Randr_Screen_Info_12 *current_info_12;
1037 E_Randr_Screen_Restore_Info_12 *restore_info_12 = NULL;
1038 E_Randr_Crtc_Restore_Info *crtc_restore_info = NULL;
1039 E_Randr_Crtc_Info *crtc_info;
1040 E_Randr_Output_Info *output_info;
1041 Eina_List *crtc_restore_iter;
1043 current_info_12 = (e_randr_screen_info->rrvd_info).randr_info_12;
1044 EINA_LIST_FOREACH(restore_info_12->crtcs, crtc_restore_iter, crtc_restore_info)
1048 current_info_12->alignment = restore_info_12->alignment;
1049 current_info_12->output_policy = restore_info_12->output_policy;
1055 _e_randr_config_find_suiting_config_11(E_Randr_Screen_Restore_Info_11 **restore_info)
1057 E_RANDR_NO_11_RET(Ecore_X_Randr_None);
1058 Eina_List *cfg_screen_restore_info_iter;
1059 E_Randr_Screen_Restore_Info *screen_restore_info;
1061 E_Randr_Screen_Restore_Info_11 *restore_info_11;
1062 Ecore_X_Randr_Screen_Size_MM *sizes;
1063 Ecore_X_Randr_Refresh_Rate *rates = NULL;
1064 int i = 0, j = 0, nsizes = 0, nrates = 0;
1066 EINA_LIST_FOREACH(e_config->screen_info, cfg_screen_restore_info_iter, screen_restore_info)
1068 // 'screen_restore_info' should _never_ be NULL, since this functions shouldn't be called due to randr init failing.
1069 if (!screen_restore_info) continue;
1070 if (screen_restore_info->randr_version != ECORE_X_RANDR_1_1) continue;
1071 restore_info_11 = screen_restore_info->rrvd_restore_info.restore_info_11;
1072 if((sizes = ecore_x_randr_screen_primary_output_sizes_get(e_randr_screen_info->root, &nsizes)))
1074 for (i = 0; i < nsizes; i++)
1076 if ((restore_info_11->size.width == sizes[i].width)
1077 && (restore_info_11->size.height == sizes[i].height))
1079 if ((rates = ecore_x_randr_screen_primary_output_refresh_rates_get(e_randr_screen_info->root, i, &nrates)))
1081 for (j = 0; j < nrates; j++)
1082 if (rates[j] == restore_info_11->refresh_rate)
1084 if (restore_info) *restore_info = restore_info_11;
1093 if (sizes) free(sizes);
1096 return Ecore_X_Randr_Unset;
1101 * @Brief find configuration with the most hardware currently available
1103 static E_Randr_Screen_Restore_Info_12 *
1104 _e_randr_config_find_suiting_config_12(void)
1106 //TODO: write geometry based loading
1108 Eina_List *cfg_screen_restore_info_iter;
1109 E_Randr_Screen_Restore_Info *screen_restore_info;
1111 E_Randr_Screen_Info_12 *current_info_12;
1112 E_Randr_Screen_Restore_Info_12 *restore_info_12, *most_matches = NULL;
1113 E_Randr_Output_Info *output_info;
1114 E_Randr_Crtc_Restore_Info *crtc_restore_info;
1115 Ecore_X_Randr_Output *outputs_xids;
1116 Ecore_X_Randr_Crtc *crtcs_xids;
1117 Eina_List *restore_info_12_iter, *output_iter, *restore_crtcs_iter;
1119 if (e_randr_screen_info && e_config && e_config->screen_info)
1122 EINA_LIST_FOREACH(e_config->screen_info, cfg_screen_restore_info_iter, screen_restore_info)
1124 if (screen_restore_info->randr_version < ECORE_X_RANDR_1_2) continue;
1126 //HINT: use eina_list_clone and a sort callback to find proper
1129 //current_info_12 = e_randr_screen_info->rrvd_info.randr_info_12;
1137 static Ecore_X_Randr_Output *
1138 _e_randr_outputs_to_array(Eina_List *outputs_info)
1140 Ecore_X_Randr_Output *ret = NULL;
1141 E_Randr_Output_Info *output_info;
1142 Eina_List *output_iter;
1145 if (!outputs_info || !(ret = malloc(sizeof(Ecore_X_Randr_Output) * eina_list_count(outputs_info)))) return NULL;
1146 EINA_LIST_FOREACH(outputs_info, output_iter, output_info)
1147 /* output_info == NULL should _not_ be possible! */
1148 ret[i++] = output_info ? output_info->xid : Ecore_X_Randr_None;
1153 * Try to enable this output on an unoccupied CRTC. 'Force' in this context
1154 * means, that if there are only occupied CRTCs, we disable another output to
1155 * enable this one. If not forced we will - if we don't find an unoccupied CRTC
1156 * - try to share the output of a CRTC with other outputs already using it
1160 _e_randr_try_enable_output(E_Randr_Output_Info *output_info, Eina_Bool force)
1162 if (!output_info) return EINA_FALSE;
1163 else if (output_info->crtc && output_info->crtc->current_mode) return EINA_TRUE;
1165 Eina_List *iter, *outputs_list = NULL;
1166 E_Randr_Crtc_Info *crtc_info, *usable_crtc = NULL;
1167 E_Randr_Output_Info *primary_output;
1168 Ecore_X_Randr_Output *outputs;
1169 Ecore_X_Randr_Mode_Info *mode_info;
1170 Eina_Bool ret = EINA_FALSE;
1173 * Try to find a usable crtc for this output. Either unused or forced.
1175 EINA_LIST_FOREACH(output_info->possible_crtcs, iter, crtc_info)
1177 if (crtc_info && (!crtc_info->current_mode || force))
1179 usable_crtc = crtc_info;
1185 * apparently we don't have a CRTC to make use of the device
1187 if (!usable_crtc) return EINA_FALSE;
1189 //get the CRTC we will refer to, dependend on policy
1190 switch (e_randr_screen_info->rrvd_info.randr_info_12->output_policy)
1192 case ECORE_X_RANDR_OUTPUT_POLICY_NONE:
1194 case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
1196 * Order of approaches to enable a clone (of the primary output):
1198 * 0. Get Primary output from Server
1199 * 1. Try to add new Output to primary output's CRTC, using the mode used
1200 * by the primary output
1201 * 2. Try to enable clone in the same
1202 * 2a. exact mode or a
1203 * 2b. geometrically identical mode
1204 * 3. Find a most high resolution mode in common to enable on primary output's CRTC and the new
1208 if ((primary_output = e_randr_screen_info->rrvd_info.randr_info_12->primary_output))
1210 if (primary_output->crtc && primary_output->crtc->current_mode && eina_list_data_find(output_info->modes, primary_output->crtc->current_mode))
1213 * mode currently used by primary output's CRTC is also supported by the new output
1215 if (_e_randr_outputs_are_clones(output_info, primary_output->crtc->outputs))
1218 * 1. Try to add new Output to primary output's CRTC, using the mode used
1219 * by the primary output
1220 * TODO: check with compatibility list in RandRR >= 1.3
1223 * The new output is also usable by the primary output's
1224 * CRTC. Try to enable this output together with the already
1225 * enabled outputs on the CRTC in already used mode.
1227 outputs_list = eina_list_clone(primary_output->crtc->outputs);
1228 outputs_list = eina_list_append(outputs_list, output_info);
1229 outputs = _e_randr_outputs_to_array(outputs_list);
1230 ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info->root, primary_output->crtc->xid, outputs, eina_list_count(outputs_list), primary_output->crtc->current_mode->xid);
1232 eina_list_free(outputs_list);
1238 * 2. Try to enable clone in the same
1244 ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info->root, usable_crtc->xid, &output_info->xid, 1, primary_output->crtc->current_mode->xid);
1245 return (ret && ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info->root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info->rrvd_info.randr_info_12->alignment));
1252 * 2b. geometrically identical mode
1254 if (primary_output->crtc && (mode_info = _e_randr_mode_geo_identical_find(output_info->modes, primary_output->crtc->current_mode)))
1256 ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info->root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid);
1257 return (ret && ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info->root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info->rrvd_info.randr_info_12->alignment));
1260 * 3. Find the highest resolution mode common to enable on primary output's CRTC and the new one.
1262 if (((outputs_list = eina_list_append(outputs_list, primary_output)) && (outputs_list = eina_list_append(outputs_list, output_info))))
1264 if (primary_output->crtc)
1266 if((mode_info = _e_randr_outputs_common_mode_max_get(outputs_list, primary_output->crtc->current_mode)))
1268 fprintf(stderr, "Will try to set mode: %dx%d for primary and clone.\n", mode_info->width, mode_info->height);
1269 ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info->root, primary_output->crtc->xid, ((Ecore_X_Randr_Output*)Ecore_X_Randr_Unset), Ecore_X_Randr_Unset, mode_info->xid);
1270 ret = (ret && ecore_x_randr_crtc_mode_set(e_randr_screen_info->root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid));
1271 ret = (ret && ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info->root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info->rrvd_info.randr_info_12->alignment));
1274 eina_list_free(outputs_list);
1280 fprintf(stderr, "Couldn't get primary output!\n");
1287 if ((usable_crtc && (!usable_crtc->current_mode)) || force)
1289 //enable and position according to used policies
1290 if(!(mode_info = ((Ecore_X_Randr_Mode_Info*)eina_list_nth(output_info->preferred_modes, 0))))
1292 fprintf(stderr, "E_RANDR: Could not enable output(%d), as it has no preferred (and there for none at all) modes.!\n", output_info->xid);
1296 if((ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info->root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid)))
1298 usable_crtc->geometry.w = mode_info->width;
1299 usable_crtc->geometry.h = mode_info->height;
1300 usable_crtc->geometry.x = 0;
1301 usable_crtc->geometry.y = 0;
1303 ret &= _e_randr_crtc_move_policy(usable_crtc);
1307 ecore_x_randr_screen_reset(e_randr_screen_info->root);
1312 * updates all crtcs information regarding a new output
1315 _e_randr_crtcs_possible_output_update(E_Randr_Output_Info *output_info)
1318 E_Randr_Crtc_Info *crtc_info;
1319 Ecore_X_Randr_Output *outputs = NULL;
1322 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
1324 if (!eina_list_data_find(crtc_info->possible_outputs, output_info))
1326 if ((outputs = ecore_x_randr_crtc_possible_outputs_get(e_randr_screen_info->root, crtc_info->xid, &noutputs)))
1328 while (--noutputs >= 0)
1330 if (outputs[noutputs] == output_info->xid)
1332 crtc_info->possible_outputs = eina_list_append(crtc_info->possible_outputs, output_info);
1343 * setup a crtc's current (possible) outputs references
1346 _e_randr_crtc_outputs_refs_update(E_Randr_Crtc_Info *crtc_info)
1348 Ecore_X_Randr_Output *outputs;
1349 E_Randr_Output_Info *output_info;
1352 //get references to output_info structs which are related to this CRTC
1353 if (e_randr_screen_info->rrvd_info.randr_info_12->outputs && (outputs = ecore_x_randr_crtc_outputs_get(e_randr_screen_info->root, crtc_info->xid, &noutputs)))
1355 for(i = 0; i < noutputs; i++)
1357 if (!(output_info = _e_randr_output_info_get(outputs[i])) || eina_list_data_find(crtc_info->outputs, output_info) || (ecore_x_randr_output_crtc_get(e_randr_screen_info->root, outputs[i]) != crtc_info->xid)) continue;
1358 if(!(crtc_info->outputs = eina_list_append(crtc_info->outputs, output_info))) fprintf(stderr, "E_RANDR: could not add output(%d) to CRTC's(%d) output list!\n", output_info->xid, crtc_info->xid);
1359 output_info->crtc = crtc_info;
1363 //get references to possible output_info structs which are related to this CRTC
1364 if (e_randr_screen_info->rrvd_info.randr_info_12->outputs && (outputs = ecore_x_randr_crtc_possible_outputs_get(e_randr_screen_info->root, crtc_info->xid, &noutputs)))
1366 for(i = 0; i < noutputs; i++)
1368 if (!(output_info = _e_randr_output_info_get(outputs[i])) || eina_list_data_find(crtc_info->possible_outputs, output_info)) continue;
1369 if(!(crtc_info->possible_outputs = eina_list_append(crtc_info->possible_outputs, output_info))) fprintf(stderr, "E_RANDR: could not add output(%d) to CRTC's(%d) possible output list!\n", output_info->xid, crtc_info->xid);
1376 * reconfigure screen setup according to policy. This is only required if all
1377 * CRTCs' positions might be affected by the another screens' movement. This includes 'virtual' moves,
1378 * which means that e.g. when a crtc should be placed at a position < 0, all
1379 * other crtcs are accordingly moved instead, so the result is the same.
1382 _e_randr_crtc_move_policy(E_Randr_Crtc_Info *new_crtc)
1384 const E_Randr_Crtc_Info *crtc_rel;
1385 int dx = Ecore_X_Randr_None, dy = Ecore_X_Randr_None;
1386 Eina_Bool ret = EINA_TRUE;
1388 //get the crtc we will place our's relative to. If it's NULL, this is the
1389 //only output attached, work done.
1390 if(!(crtc_rel = _e_randr_policy_crtc_get(new_crtc, NULL, e_randr_screen_info->rrvd_info.randr_info_12->output_policy))) return EINA_TRUE;
1392 //following is policy dependend.
1393 switch (e_randr_screen_info->rrvd_info.randr_info_12->output_policy)
1395 case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
1396 dy = (crtc_rel->geometry.y - new_crtc->geometry.h);
1399 //virtual move (move other CRTCs as nessesary)
1401 ret = ecore_x_randr_move_all_crtcs_but(e_randr_screen_info->root,
1408 case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
1409 dx = (crtc_rel->geometry.x - new_crtc->geometry.w);
1412 //virtual move (move other CRTCs as nessesary)
1414 ret = ecore_x_randr_move_all_crtcs_but(e_randr_screen_info->root,
1424 ret &= ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info->root, new_crtc->xid, crtc_rel->xid, e_randr_screen_info->rrvd_info.randr_info_12->output_policy, e_randr_screen_info->rrvd_info.randr_info_12->alignment);
1429 * returns the highest resolution mode common ammongst the given outputs,
1430 * optionally limited by max_size_mode. If none is found, NULL is returned.
1432 static Ecore_X_Randr_Mode_Info *
1433 _e_randr_outputs_common_mode_max_get(Eina_List *outputs, Ecore_X_Randr_Mode_Info *max_size_mode)
1435 Eina_List *all_modes = NULL, *iter, *output_iter, *right;
1436 E_Randr_Output_Info *output_info;
1437 Ecore_X_Randr_Mode_Info *mode_info;
1438 int outputs_mode_found;
1440 //create a list of all available modes
1441 EINA_LIST_FOREACH(outputs, iter, output_info)
1443 right = eina_list_clone(output_info->modes);
1444 all_modes = eina_list_merge(all_modes, right);
1449 //remove all modes that are larger than max_size_mode
1450 EINA_LIST_FOREACH(all_modes, iter, mode_info)
1452 if (_modes_size_sort_cb((void*)max_size_mode, (void*)mode_info) < 0)
1453 all_modes = eina_list_remove(all_modes, mode_info);
1457 //sort modes by their sizes
1458 all_modes = eina_list_sort(all_modes, eina_list_count(all_modes), _modes_size_sort_cb);
1459 EINA_LIST_REVERSE_FOREACH(all_modes, iter, mode_info)
1461 outputs_mode_found = 0;
1462 EINA_LIST_FOREACH(outputs, output_iter, output_info)
1464 if (eina_list_data_find(output_info->modes, mode_info))
1465 outputs_mode_found++;
1467 if (outputs_mode_found == (int)eina_list_count(outputs))
1476 _crtcs_size_sort_cb(const void *d1, const void *d2)
1478 E_Randr_Crtc_Info *crtc1 = ((E_Randr_Crtc_Info*)d1), *crtc2 = ((E_Randr_Crtc_Info*)d2);
1480 return ((crtc1->geometry.w * crtc1->geometry.h) - (crtc2->geometry.w * crtc2->geometry.h));
1485 _outputs_size_sort_cb(const void *d1, const void *d2)
1487 E_Randr_Output_Info *output1 = ((E_Randr_Output_Info*)d1), *output2 = ((E_Randr_Output_Info*)d2);
1489 return (output1 && output1->crtc && output1->crtc->current_mode && output2 && output2->crtc && output2->crtc->current_mode) ? ((output1->crtc->current_mode->width * output1->crtc->current_mode->height) - (output2->crtc->current_mode->width * output2->crtc->current_mode->height)) : 0;
1493 _modes_size_sort_cb(const void *d1, const void *d2)
1495 Ecore_X_Randr_Mode_Info *mode1 = ((Ecore_X_Randr_Mode_Info*)d1), *mode2 = ((Ecore_X_Randr_Mode_Info*)d2);
1497 return ((mode1->width * mode1->height) - (mode2->width * mode2->height));
1501 * returns a mode within a given list of modes that is gemetrically identical.
1502 * If none is found, NULL is returned.
1504 static Ecore_X_Randr_Mode_Info *
1505 _e_randr_mode_geo_identical_find(Eina_List *modes, Ecore_X_Randr_Mode_Info *mode)
1508 Ecore_X_Randr_Mode_Info *mode_info;
1510 EINA_LIST_FOREACH(modes, iter, mode_info)
1512 if ((mode_info->width == mode->width) && (mode_info->height == mode->height))
1519 * reconfigures a CRTC enabling the highest resolution amongst its outputs,
1520 * without touching any other CRTC currently activated
1523 _e_randr_crtc_outputs_mode_max_set(E_Randr_Crtc_Info *crtc_info)
1525 Ecore_X_Randr_Mode_Info *mode_info;
1527 Eina_Bool ret = EINA_TRUE;
1528 Ecore_X_Randr_Output *outputs;
1530 if (!crtc_info || !crtc_info->outputs || !crtc_info->outputs_common_modes) return EINA_FALSE;
1532 EINA_LIST_REVERSE_FOREACH(crtc_info->outputs_common_modes, iter, mode_info)
1534 if (!_e_randr_crtc_mode_intersects_crtcs(crtc_info, mode_info))
1539 eina_list_free(crtc_info->outputs_common_modes);
1542 if ((outputs = _e_randr_outputs_to_array(crtc_info->outputs)))
1544 ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info->root, crtc_info->xid, outputs, eina_list_count(crtc_info->outputs), mode_info->xid);
1547 eina_list_free(crtc_info->outputs_common_modes);
1549 ecore_x_randr_screen_reset(e_randr_screen_info->root);
1555 * returns EINA_TRUE if given CRTC would intersect with other CRTCs if set to
1559 _e_randr_crtc_mode_intersects_crtcs(E_Randr_Crtc_Info *crtc_info, Ecore_X_Randr_Mode_Info *mode)
1562 E_Randr_Crtc_Info *tmp;
1564 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, tmp)
1566 if ((tmp == crtc_info) ||
1567 ((tmp->geometry.w <= 0) || (tmp->geometry.h <= 0)))
1569 if (E_INTERSECTS(crtc_info->geometry.x, crtc_info->geometry.y,
1570 mode->width, mode->height, tmp->geometry.x,
1571 tmp->geometry.y, tmp->geometry.w, tmp->geometry.h)
1572 && ((crtc_info->geometry.x != tmp->geometry.x) &&
1573 (crtc_info->geometry.y != tmp->geometry.y)))
1580 * returns a list of modes common ammongst the given outputs,
1581 * optionally limited by max_size_mode. If none are found, NULL is returned.
1584 _e_randr_outputs_common_modes_get(Eina_List *outputs, Ecore_X_Randr_Mode_Info *max_size_mode)
1586 Eina_List *common_modes = NULL, *iter, *output_iter, *right;
1587 E_Randr_Output_Info *output_info;
1588 Ecore_X_Randr_Mode_Info *mode_info;
1589 int outputs_mode_found;
1591 if (!outputs) return NULL;
1593 //create a list of all available modes
1594 EINA_LIST_FOREACH(outputs, iter, output_info)
1596 right = eina_list_clone(output_info->modes);
1597 common_modes = eina_list_merge(common_modes, right);
1602 //remove all modes that are larger than max_size_mode
1603 EINA_LIST_FOREACH(common_modes, iter, mode_info)
1605 if (_modes_size_sort_cb((void*)max_size_mode, (void*)mode_info) < 0)
1606 common_modes = eina_list_remove(common_modes, mode_info);
1610 //sort modes desc. by their sizes
1611 EINA_LIST_REVERSE_FOREACH(common_modes, iter, mode_info)
1613 outputs_mode_found = 0;
1614 EINA_LIST_FOREACH(outputs, output_iter, output_info)
1616 if (eina_list_data_find(output_info->modes, mode_info))
1617 outputs_mode_found++;
1619 if (outputs_mode_found != (int)eina_list_count(outputs))
1620 common_modes = eina_list_remove(common_modes, mode_info);
1622 return common_modes;
1626 * reconfigure all CRTCs that had a given CRTC as a clone
1629 _e_randr_crtcs_clone_crtc_removed(E_Randr_Crtc_Info *former_clone)
1632 E_Randr_Crtc_Info *crtc_info;
1634 if (!former_clone) return EINA_FALSE;
1636 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
1638 if ((crtc_info == former_clone) || ((crtc_info->geometry.w <= 0) || (crtc_info->geometry.h <= 0))) continue;
1639 if ((former_clone->geometry.x == crtc_info->geometry.x) && (former_clone->geometry.y == crtc_info->geometry.y) && (former_clone->geometry.w == crtc_info->geometry.w) && (former_clone->geometry.h == crtc_info->geometry.h))
1641 if (!_e_randr_crtc_outputs_mode_max_set(crtc_info)) return EINA_FALSE;
1650 _e_randr_screen_primary_output_assign(E_Randr_Output_Info *removed)
1653 E_Randr_Output_Info *primary_output = NULL, *output_info;
1655 E_RANDR_NO_OUTPUTS_RET();
1657 if (e_randr_screen_info->rrvd_info.randr_info_12->primary_output && (removed != e_randr_screen_info->rrvd_info.randr_info_12->primary_output)) return;
1658 if (!(primary_output = _e_randr_output_info_get(ecore_x_randr_primary_output_get(e_randr_screen_info->root))))
1660 primary_output = eina_list_data_get(eina_list_last(e_randr_screen_info->rrvd_info.randr_info_12->outputs));
1662 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->outputs, iter, output_info)
1664 if (output_info->connection_status == ECORE_X_RANDR_CONNECTION_STATUS_DISCONNECTED || !output_info->crtc || !output_info->crtc->current_mode) continue;
1665 if ((!primary_output->crtc || !primary_output->crtc->current_mode) || _outputs_size_sort_cb(output_info, primary_output) > 0) primary_output = output_info;
1667 if (!primary_output->crtc || !primary_output->crtc->current_mode) primary_output = NULL;
1669 e_randr_screen_info->rrvd_info.randr_info_12->primary_output = primary_output;
1673 _e_randr_output_info_hw_info_set(E_Randr_Output_Info *output_info)
1675 Ecore_X_Randr_Output *outputs;
1676 Ecore_X_Randr_Crtc *crtcs;
1677 E_Randr_Output_Info *output;
1678 E_Randr_Crtc_Info *crtc;
1681 _e_randr_output_modes_add(output_info);
1682 output_info->edid = ecore_x_randr_output_edid_get(e_randr_screen_info->root, output_info->xid, &output_info->edid_length);
1683 //get the outputs we can use on the same CRTC alongside this one.
1684 if ((outputs = ecore_x_randr_output_clones_get(e_randr_screen_info->root, output_info->xid, &num)))
1686 for (i = 0; i < num; i++)
1688 if ((output = _e_randr_output_info_get(outputs[i])))
1689 output_info->clones = eina_list_append(output_info->clones, output);
1694 //get the CRTCs which are usable with this output.
1695 if ((crtcs = ecore_x_randr_output_possible_crtcs_get(e_randr_screen_info->root, output_info->xid, &num)))
1697 for (i = 0; i < num; i++)
1699 fprintf(stderr, "E_RANDR: possible CRTC: %d\n", crtcs[i]);
1700 if ((crtc = _e_randr_crtc_info_get(crtcs[i])))
1702 fprintf(stderr, "E_RANDR: \tfound the suiting struct at %p\n", crtc);
1703 output_info->possible_crtcs = eina_list_append(output_info->possible_crtcs, crtc);
1711 * free the hardware specifig parts of the information
1712 * removes all traces of an output within the data.
1713 * @param output_info the output info to be freed.
1716 _e_randr_output_hw_info_free(E_Randr_Output_Info *output_info)
1718 E_Randr_Crtc_Info *crtc_info;
1720 if (!output_info) return;
1722 if (output_info->modes)
1724 eina_list_free(output_info->modes);
1725 output_info->modes = NULL;
1727 if (output_info->preferred_modes)
1729 eina_list_free(output_info->preferred_modes);
1730 output_info->preferred_modes = NULL;
1732 if (output_info->edid)
1734 free(output_info->edid);
1735 output_info->edid = NULL;
1737 if (output_info->wired_clones)
1739 eina_list_free(output_info->wired_clones);
1740 output_info->wired_clones = NULL;
1742 if (output_info->compatible_outputs)
1744 eina_list_free(output_info->compatible_outputs);
1745 output_info->compatible_outputs = NULL;
1747 if (output_info->possible_crtcs)
1749 eina_list_free(output_info->possible_crtcs);
1750 output_info->possible_crtcs = NULL;
1752 if (output_info->clones)
1754 eina_list_free(output_info->clones);
1755 output_info->clones = NULL;
1758 EINA_LIST_FOREACH(e_randr_screen_info->rrvd_info.randr_info_12->crtcs, iter, crtc_info)
1760 crtc_info->possible_outputs = eina_list_remove(crtc_info->possible_outputs, output_info);
1765 * checks whether a given output is a common clone of the given list's outputs
1768 _e_randr_outputs_are_clones(E_Randr_Output_Info *output_info, Eina_List *outputs)
1770 E_Randr_Output_Info *output;
1773 if (!outputs || !output_info) return EINA_FALSE;
1775 EINA_LIST_FOREACH(output_info->clones, iter, output)
1777 if (!eina_list_data_find(output_info->clones, output))