1 #include "e_int_config_randr.h"
5 #ifndef ECORE_X_RANDR_1_2
6 #define ECORE_X_RANDR_1_2 ((1 << 16) | 2)
8 #ifndef ECORE_X_RANDR_1_3
9 #define ECORE_X_RANDR_1_3 ((1 << 16) | 3)
12 #ifndef Ecore_X_Randr_Unset
13 #define Ecore_X_Randr_Unset -1
16 #define DOUBLECLICK_TIMEOUT 0.2
17 #define CRTC_THUMB_SIZE_W 300
18 #define CRTC_THUMB_SIZE_H 300
20 Eina_Bool dialog_subdialog_arrangement_create_data(E_Config_Dialog_Data *e_config_runtime_info);
21 Evas_Object *dialog_subdialog_arrangement_basic_create_widgets(Evas *canvas);
22 Eina_Bool dialog_subdialog_arrangement_basic_check_changed(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
23 Eina_Bool dialog_subdialog_arrangement_basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
24 void dialog_subdialog_arrangement_free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
25 static inline Eina_List *_dialog_subdialog_arrangement_neighbors_get(Evas_Object *obj);
26 static void _dialog_subdialog_arrangement_determine_positions_recursive(Evas_Object *obj);
28 //static inline E_Config_Randr_Dialog_Output_Dialog_Data *_dialog_subdialog_arrangement_output_dialog_data_new (E_Randr_Crtc_Info *crtc_info, E_Randr_Output_Info *output_info);
29 static inline void _dialog_subdialog_arrangement_suggestion_add(Evas *evas);
30 static inline void _dialog_subdialog_arrangement_make_suggestion(Evas_Object *obj);
31 static void _dialog_subdialog_arrangement_smart_class_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
32 static Evas_Object *_dialog_subdialog_arrangement_output_add(Evas *canvas, E_Config_Randr_Dialog_Output_Dialog_Data *output_dialog_data);
33 static void _dialog_subdialog_arrangement_output_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
34 static void _dialog_subdialog_arrangement_output_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
35 static void _dialog_subdialog_arrangement_output_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
37 // Function for the resolutions subdialog interaction
38 extern void dialog_subdialog_resolutions_update_list(Evas_Object *crtc);
39 // Function for the orientation subdialog interaction
40 extern void dialog_subdialog_orientation_update_radio_buttons(Evas_Object *crtc);
41 extern void dialog_subdialog_orientation_update_edje(Evas_Object *crtc);
42 // Functions for the orientation subdialog interaction
43 extern void dialog_subdialog_policies_update_radio_buttons(Evas_Object *crtc);
45 static Evas_Smart_Class screen_setup_smart_class = EVAS_SMART_CLASS_INIT_NAME_VERSION("EvasObjectSmartScreenSetup");
46 static Evas_Smart *screen_setup_smart = NULL;
48 extern E_Config_Dialog_Data *e_config_runtime_info;
49 extern char _theme_file_path[];
52 _dialog_subdialog_arrangement_output_dialog_data_fill(E_Config_Randr_Dialog_Output_Dialog_Data *odd)
58 //already enabled screen
59 odd->previous_pos.x = odd->crtc->geometry.x;
60 odd->previous_pos.y = odd->crtc->geometry.y;
61 odd->previous_mode = odd->crtc->current_mode;
66 //try to get a mode from the preferred list, else use default list
67 if (!(odd->preferred_mode = (Ecore_X_Randr_Mode_Info *)eina_list_data_get(eina_list_last(odd->output->preferred_modes))))
69 if (odd->output->modes)
70 odd->preferred_mode = (Ecore_X_Randr_Mode_Info *)eina_list_data_get(eina_list_last(odd->output->modes));
72 odd->preferred_mode = NULL;
75 odd->previous_pos.x = Ecore_X_Randr_Unset;
76 odd->previous_pos.y = Ecore_X_Randr_Unset;
79 odd->new_pos.x = Ecore_X_Randr_Unset;
80 odd->new_pos.y = Ecore_X_Randr_Unset;
84 dialog_subdialog_arrangement_create_data(E_Config_Dialog_Data *data)
87 E_Config_Randr_Dialog_Output_Dialog_Data *dialog_data;
88 char *disabled_output_width, *disabled_output_height;
91 EINA_LIST_FOREACH(data->output_dialog_data_list, iter, dialog_data)
93 _dialog_subdialog_arrangement_output_dialog_data_fill(dialog_data);
96 if(!(disabled_output_width = edje_file_data_get(_theme_file_path, "disabled_output_width")))
97 disabled_output_width = "1024";
98 if(!(disabled_output_height = edje_file_data_get(_theme_file_path, "disabled_output_height")))
99 disabled_output_height = "768";
101 data->gui.subdialogs.arrangement.disabled_output_size.w = atoi(disabled_output_width);
102 data->gui.subdialogs.arrangement.disabled_output_size.h = atoi(disabled_output_height);
107 //IMPROVABLE: Clean up properly if instances can't be created
109 dialog_subdialog_arrangement_basic_create_widgets(Evas *canvas)
111 Evas_Object *subdialog, *crtc;
112 E_Config_Randr_Dialog_Output_Dialog_Data *output_dialog_data;
115 if (!canvas || !e_config_runtime_info || !e_config_runtime_info->output_dialog_data_list) return NULL;
117 //initialize smart object
118 evas_object_smart_clipped_smart_set(&screen_setup_smart_class);
119 screen_setup_smart_class.resize = _dialog_subdialog_arrangement_smart_class_resize;
120 screen_setup_smart = evas_smart_class_new(&screen_setup_smart_class);
122 subdialog = evas_object_smart_add(canvas, screen_setup_smart);
123 e_config_runtime_info->gui.subdialogs.arrangement.clipper = evas_object_smart_clipped_clipper_get(subdialog);
124 fprintf(stderr, "CONF_RANDR: Arrangement subdialog added (%p).\n", subdialog);
126 //only use information we can restore.
127 EINA_LIST_FOREACH(e_config_runtime_info->output_dialog_data_list, iter, output_dialog_data)
129 if ((!output_dialog_data->crtc && !output_dialog_data->output))
131 crtc = _dialog_subdialog_arrangement_output_add(canvas, output_dialog_data);
134 evas_object_show(crtc);
136 evas_object_event_callback_add (crtc, EVAS_CALLBACK_MOUSE_DOWN, _dialog_subdialog_arrangement_output_mouse_down_cb, NULL);
137 evas_object_event_callback_add (crtc, EVAS_CALLBACK_MOUSE_MOVE, _dialog_subdialog_arrangement_output_mouse_move_cb, NULL);
138 evas_object_event_callback_add (crtc, EVAS_CALLBACK_MOUSE_UP, _dialog_subdialog_arrangement_output_mouse_up_cb, NULL);
140 evas_object_smart_member_add(crtc, subdialog);
141 fprintf(stderr, "CONF_RANDR: CRTC representation (%p) added to arrangement subdialog (%p).\n", crtc, subdialog);
144 e_config_runtime_info->gui.subdialogs.arrangement.smart_parent = subdialog;
150 _dialog_subdialog_arrangement_output_add(Evas *canvas, E_Config_Randr_Dialog_Output_Dialog_Data *output_dialog_data)
152 E_Randr_Output_Info *output_info;
154 const char *output_name = NULL;
156 if (!canvas || !output_dialog_data || !e_config_runtime_info) return NULL;
158 output = edje_object_add(canvas);
160 //set instance data for output
161 evas_object_data_set(output, "output_info", output_dialog_data);
163 //set theme for monitor representation
164 EINA_SAFETY_ON_FALSE_GOTO(edje_object_file_set(output, _theme_file_path, "e/conf/randr/dialog/subdialog/arrangement/output"), _dialog_subdialog_arrangement_output_add_edje_set_fail);
165 //indicate monitor state
166 if (!output_dialog_data->crtc || (output_dialog_data->crtc && !output_dialog_data->previous_mode))
167 edje_object_signal_emit(output, "disabled", "e");
169 edje_object_signal_emit(output, "enabled", "e");
170 //for now use deskpreview widget as background of output, maybe change this to
171 //live image from comp module
172 output_dialog_data->bg = e_widget_deskpreview_add(canvas, 1, 1);
173 edje_object_part_swallow(output, "e.swallow.content", output_dialog_data->bg);
175 //Try to get the name of the monitor connected to the output's last output via edid
176 //else use the output's name
177 if (output_dialog_data->crtc)
178 output_info = (E_Randr_Output_Info *)eina_list_data_get(eina_list_last(output_dialog_data->crtc->outputs));
180 output_info = output_dialog_data->output;
183 if (ecore_x_randr_edid_has_valid_header(output_info->edid, output_info->edid_length))
184 output_name = ecore_x_randr_edid_display_name_get(output_info->edid, output_info->edid_length);
185 else if (output_info->name)
186 output_name = output_info->name;
189 edje_object_part_text_set(output, "output_txt", output_name);
191 //set output orientation
192 dialog_subdialog_orientation_update_edje(output);
195 _dialog_subdialog_arrangement_output_add_edje_set_fail:
196 evas_object_del(output);
201 _dialog_subdialog_arrangement_smart_class_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
204 Evas_Coord real_sum_w = 0, real_sum_h = 0;
205 Eina_Rectangle parent_geo, new_geo;
206 Evas_Coord_Point offset = {.x = 0, .y = 0};
207 Evas_Coord offset_x_max = 0;
208 float scaling_factor = 0.1;
209 Eina_List *lst, *itr;
210 const E_Config_Randr_Dialog_Output_Dialog_Data *output_dialog_data;
212 evas_object_geometry_get(obj, &parent_geo.x, &parent_geo.y, &parent_geo.w, &parent_geo.h);
213 fprintf(stderr, "CONF_RANDR: Arrangement dialog shall be resized to %d x %d\n", w, h);
214 fprintf(stderr, "CONF_RANDR: Arrangement dialog Smart object geo: %d x %d, %d x %d\n", parent_geo.x, parent_geo.y, parent_geo.w, parent_geo.h);
215 if ((w < 1) || (h < 1)) return;
217 lst = evas_object_smart_members_get(obj);
218 //Calc average aspect ratio from all available monitors
219 EINA_LIST_FOREACH(lst, itr, output)
221 if (output == e_config_runtime_info->gui.subdialogs.arrangement.clipper) continue;
222 output_dialog_data = evas_object_data_get(output, "output_info");
223 if (!output_dialog_data) continue;
224 if ((!output_dialog_data->previous_mode) && (!output_dialog_data->preferred_mode)) continue;
225 if (output_dialog_data->previous_mode)
227 real_sum_w += output_dialog_data->previous_mode->width;
228 real_sum_h += output_dialog_data->previous_mode->height;
230 else if (output_dialog_data->preferred_mode)
232 real_sum_w += output_dialog_data->preferred_mode->width;
233 real_sum_h += output_dialog_data->preferred_mode->height;
237 real_sum_w += e_config_runtime_info->gui.subdialogs.arrangement.disabled_output_size.w;
238 real_sum_h += e_config_runtime_info->gui.subdialogs.arrangement.disabled_output_size.h;
242 scaling_factor = (((float)parent_geo.w / (float)real_sum_w) < ((float)parent_geo.h / (float)real_sum_h)) ? ((float)parent_geo.w / (float)real_sum_w) : ((float)parent_geo.h / (float)real_sum_h);
243 scaling_factor *= e_scale;
245 EINA_LIST_FOREACH(lst, itr, output)
247 //Skip elements that are either the clipped smart object or falsely added
248 //to the list of outputs (which should not happen)
249 if (output == e_config_runtime_info->gui.subdialogs.arrangement.clipper) continue;
250 output_dialog_data = evas_object_data_get(output, "output_info");
251 if (!output_dialog_data) continue;
252 if (output_dialog_data->previous_mode)
254 new_geo.w = (int)((float)output_dialog_data->previous_mode->width * scaling_factor);
255 new_geo.h = (int)((float)output_dialog_data->previous_mode->height * scaling_factor);
257 else if (output_dialog_data->preferred_mode)
259 new_geo.w = (int)((float)output_dialog_data->preferred_mode->width * scaling_factor);
260 new_geo.h = (int)((float)output_dialog_data->preferred_mode->height * scaling_factor);
264 new_geo.w = (int)((float)e_config_runtime_info->gui.subdialogs.arrangement.disabled_output_size.w * scaling_factor);
265 new_geo.h = (int)((float)e_config_runtime_info->gui.subdialogs.arrangement.disabled_output_size.h * scaling_factor);
266 fprintf(stderr, "CONF_RANDR: Neither mode nor preferred mode are avavailable for %x. Using %dx%d.\n", (output_dialog_data->crtc ? output_dialog_data->crtc->xid : output_dialog_data->output->xid), e_config_runtime_info->gui.subdialogs.arrangement.disabled_output_size.w, e_config_runtime_info->gui.subdialogs.arrangement.disabled_output_size.h);
268 if ((new_geo.w <= 0) || (new_geo.h <= 0))
270 //this is an effect, occuring during dialog closing.
271 //If we don't return here, e_thumb will segfault!
274 if ((output_dialog_data->previous_pos.x == Ecore_X_Randr_Unset) || (output_dialog_data->previous_pos.y == Ecore_X_Randr_Unset))
276 //this is a non enabled monitor
277 new_geo.x = parent_geo.x + parent_geo.w - new_geo.w - offset.x;
278 new_geo.y = parent_geo.y + offset.y;
279 offset.y = new_geo.y + new_geo.h;
280 if (offset_x_max < new_geo.w)
282 //adopt new max value for x
283 offset_x_max = new_geo.w;
285 if ((offset.y + new_geo.h) > (parent_geo.y + parent_geo.h))
287 //reset offset.y and adjust offset.x
289 offset.x += offset_x_max;
294 new_geo.x = ((int)((float)output_dialog_data->previous_pos.x * scaling_factor)) + parent_geo.x;
295 new_geo.y = ((int)((float)output_dialog_data->previous_pos.y * scaling_factor)) + parent_geo.y;
297 //resize edje element
298 evas_object_resize(output, new_geo.w, new_geo.h);
300 e_thumb_icon_size_set(output_dialog_data->bg, new_geo.w, new_geo.h); //need to clarify the usage of e_thumb. Usable without e_thumb_icon_file_set??!!
301 evas_object_move(output, new_geo.x, new_geo.y);
302 fprintf(stderr, "CONF_RANDR: output representation %p was resized to %d x %d\n", output, new_geo.w, new_geo.h);
303 fprintf(stderr, "CONF_RANDR: output representation %p was moved to %d x %d\n", output, new_geo.x, new_geo.y);
308 _dialog_subdialog_arrangement_output_mouse_down_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
310 Evas_Object *element = NULL;
312 Eina_Bool crtc_selected = EINA_FALSE;
314 EINA_LIST_FOREACH(evas_object_smart_members_get(evas_object_smart_parent_get(obj)), iter, element)
316 if (e_config_runtime_info->gui.subdialogs.arrangement.clipper == obj) continue;
318 edje_object_signal_emit(element, "deselect", "e");
321 edje_object_signal_emit(element, "select", "e");
322 //update data for other dialogs
323 e_config_runtime_info->gui.selected_eo = obj;
325 //update resolutions list
326 dialog_subdialog_resolutions_update_list(obj);
328 //update orientation radio buttons
329 dialog_subdialog_orientation_update_radio_buttons(obj);
331 //update policy radio buttons
332 dialog_subdialog_policies_update_radio_buttons(obj);
334 crtc_selected = EINA_TRUE;
339 //update data for other dialogs
340 e_config_runtime_info->gui.selected_eo = NULL;
342 //update resolutions list
343 dialog_subdialog_resolutions_update_list(NULL);
345 //update orientation radio buttons
346 dialog_subdialog_orientation_update_radio_buttons(NULL);
348 //update policy radio buttons
349 dialog_subdialog_policies_update_radio_buttons(NULL);
352 evas_object_geometry_get(obj, &e_config_runtime_info->gui.subdialogs.arrangement.previous_pos.x, &e_config_runtime_info->gui.subdialogs.arrangement.previous_pos.y, NULL, NULL);
356 _dialog_subdialog_arrangement_output_mouse_move_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
358 Evas_Event_Mouse_Move *ev = event_info;
359 Eina_Rectangle geo, parent;
360 Evas_Coord_Point delta, new;
362 if (ev->buttons != 1) return;
363 evas_object_geometry_get (obj, &geo.x, &geo.y, &geo.w, &geo.h);
364 evas_object_geometry_get (evas_object_smart_parent_get(obj), &parent.x, &parent.y, &parent.w, &parent.h);
365 delta.x = ev->cur.canvas.x - ev->prev.canvas.x;
366 delta.y = ev->cur.canvas.y - ev->prev.canvas.y;
368 new.x = geo.x + delta.x;
369 new.y = geo.y + delta.y;
370 //respect container borders
371 if (new.x < parent.x + 1)
372 new.x = parent.x + 1;
373 else if (new.x > parent.x + parent.w - geo.w)
374 new.x = parent.x + parent.w - geo.w;
375 if (new.y < parent.y + 1)
376 new.y = parent.y + 1;
377 else if (new.y > parent.y + parent.h - geo.h)
378 new.y = parent.y + parent.h - geo.h;
379 //only take action if position changed
380 if ((geo.x != new.x) || (geo.y != new.y))
382 evas_object_move(obj, new.x, new.y);
383 _dialog_subdialog_arrangement_make_suggestion(obj);
388 _dialog_subdialog_arrangement_output_mouse_up_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
390 Evas_Coord_Point coords;
392 if (evas_object_visible_get(e_config_runtime_info->gui.subdialogs.arrangement.suggestion))
394 edje_object_signal_emit(e_config_runtime_info->gui.subdialogs.arrangement.suggestion, "hide", "e");
395 evas_object_geometry_get(e_config_runtime_info->gui.subdialogs.arrangement.suggestion, &coords.x, &coords.y, NULL, NULL);
396 evas_object_move(obj, coords.x, coords.y);
400 evas_object_move(obj, e_config_runtime_info->gui.subdialogs.arrangement.previous_pos.x, e_config_runtime_info->gui.subdialogs.arrangement.previous_pos.y);
405 _dialog_subdialog_arrangement_suggestion_add(Evas *evas)
407 const char *theme_data_item = NULL;
409 e_config_runtime_info->gui.subdialogs.arrangement.suggestion = edje_object_add(evas);
410 edje_object_file_set(e_config_runtime_info->gui.subdialogs.arrangement.suggestion, _theme_file_path, "e/conf/randr/dialog/subdialog/arrangement/suggestion");
411 if ((theme_data_item = edje_object_data_get(e_config_runtime_info->gui.subdialogs.arrangement.suggestion, "distance_min")))
412 e_config_runtime_info->gui.subdialogs.arrangement.suggestion_dist_min = MIN(MAX(atoi(theme_data_item), 0), 100);
414 e_config_runtime_info->gui.subdialogs.arrangement.suggestion_dist_min = 20;
418 _dialog_subdialog_arrangement_make_suggestion(Evas_Object *obj)
420 Eina_List *li, *crtcs = evas_object_smart_members_get(evas_object_smart_parent_get(obj));
421 Evas_Object *crtc = NULL;
422 Eina_Rectangle p_geo, geo, crtc_geo, s_geo;
423 int dxa = 10000, dya = 10000, tmp, min_dist;
427 if (!e_config_runtime_info->gui.subdialogs.arrangement.suggestion)
429 _dialog_subdialog_arrangement_suggestion_add(evas_object_evas_get(obj));
430 evas_object_show(e_config_runtime_info->gui.subdialogs.arrangement.suggestion);
433 min_dist = e_config_runtime_info->gui.subdialogs.arrangement.suggestion_dist_min;
435 evas_object_geometry_get(evas_object_smart_parent_get(obj), &p_geo.x, &p_geo.y, &p_geo.w, &p_geo.h);
436 evas_object_geometry_get(obj, &geo.x, &geo.y, &geo.w, &geo.h);
443 //compare possible positions
444 //aritifical (relative) 0x0 element
446 if ((tmp < dxa) && (tmp < min_dist))
452 if ((tmp < dya) && (tmp < min_dist))
458 EINA_LIST_FOREACH(crtcs, li, crtc)
460 if ((crtc == obj) || (crtc == e_config_runtime_info->gui.subdialogs.arrangement.clipper)) continue;
461 evas_object_geometry_get(crtc, &crtc_geo.x, &crtc_geo.y, &crtc_geo.w, &crtc_geo.h);
463 tmp = abs(s_geo.x - crtc_geo.x);
464 if ((tmp < dxa) && (tmp < min_dist))
466 s_geo.x = crtc_geo.x;
467 dxa = abs(s_geo.x - crtc_geo.x);
470 tmp = abs(s_geo.x - (crtc_geo.x + crtc_geo.w));
471 if ((tmp < dxa) && (tmp < min_dist))
473 s_geo.x = (crtc_geo.x + crtc_geo.w);
477 tmp = abs((s_geo.x + s_geo.w) - (crtc_geo.x - 1));
478 if ((tmp < dxa) && (tmp < min_dist))
480 s_geo.x = (crtc_geo.x - s_geo.w);
484 tmp = abs((s_geo.x + s_geo.w) - (crtc_geo.x + crtc_geo.w));
485 if ((tmp < dxa) && (tmp < min_dist))
487 s_geo.x = (crtc_geo.x + crtc_geo.w - s_geo.w);
492 tmp = abs(s_geo.y - crtc_geo.y);
493 if ((tmp < dya) && (tmp < min_dist))
495 s_geo.y = crtc_geo.y;
496 dya = abs(s_geo.y - crtc_geo.y);
499 tmp = abs(s_geo.y - (crtc_geo.y + crtc_geo.h));
500 if ((tmp < dya) && (tmp < min_dist))
502 s_geo.y = (crtc_geo.y + crtc_geo.h);
506 tmp = abs((s_geo.y + s_geo.h) - (crtc_geo.y - 1));
507 if ((tmp < dya) && (tmp < min_dist))
509 s_geo.y = (crtc_geo.y - s_geo.h);
513 tmp = abs((s_geo.y + s_geo.h) - (crtc_geo.y + crtc_geo.h));
514 if ((tmp < dya) && (tmp < min_dist))
516 s_geo.y = (crtc_geo.y + crtc_geo.h - s_geo.h);
521 if ((s_geo.x != geo.x) && (s_geo.y != geo.y))
523 if (s_geo.x < p_geo.x) s_geo.x = p_geo.x;
524 if ((s_geo.x + s_geo.w) > (p_geo.x + p_geo.w)) s_geo.x = ((p_geo.x + p_geo.w) - s_geo.w);
525 if (s_geo.y < p_geo.y) s_geo.y = p_geo.y;
526 if ((s_geo.y + s_geo.h) > (p_geo.y + p_geo.h)) s_geo.y = ((p_geo.y + p_geo.h) - s_geo.h);
528 if (!evas_object_visible_get(e_config_runtime_info->gui.subdialogs.arrangement.suggestion))
530 evas_object_show(e_config_runtime_info->gui.subdialogs.arrangement.suggestion);
531 edje_object_signal_emit(e_config_runtime_info->gui.subdialogs.arrangement.suggestion, "show", "e");
534 evas_object_resize(e_config_runtime_info->gui.subdialogs.arrangement.suggestion, s_geo.w, s_geo.h);
535 evas_object_move(e_config_runtime_info->gui.subdialogs.arrangement.suggestion, s_geo.x, s_geo.y);
539 edje_object_signal_emit(e_config_runtime_info->gui.subdialogs.arrangement.suggestion, "hide", "e");
540 evas_object_hide(e_config_runtime_info->gui.subdialogs.arrangement.suggestion);
545 dialog_subdialog_arrangement_free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
547 E_Config_Randr_Dialog_Output_Dialog_Data *dialog_data;
549 EINA_SAFETY_ON_NULL_RETURN(cfdata);
551 EINA_LIST_FREE(cfdata->output_dialog_data_list, dialog_data)
553 if (!dialog_data) continue;
556 evas_object_del(dialog_data->bg);
557 dialog_data->bg = NULL;
564 _dialog_subdialog_arrangement_neighbors_get(Evas_Object *obj)
566 Evas_Object *smart_parent, *crtc;
567 Eina_List *crtcs, *iter, *neighbors = NULL;
568 Eina_Rectangle geo, neighbor_geo;
569 E_Config_Randr_Dialog_Output_Dialog_Data *dialog_data, *neighbor_info;
571 smart_parent = evas_object_smart_parent_get(obj);
572 crtcs = evas_object_smart_members_get(smart_parent);
574 EINA_SAFETY_ON_FALSE_RETURN_VAL((dialog_data = evas_object_data_get(obj, "output_info")), NULL);
575 evas_object_geometry_get(obj, &geo.x, &geo.y, &geo.w, &geo.h);
576 EINA_LIST_FOREACH(crtcs, iter, crtc)
579 || (crtc == e_config_runtime_info->gui.subdialogs.arrangement.clipper)) continue;
580 evas_object_geometry_get(crtc, &neighbor_geo.x, &neighbor_geo.y, &neighbor_geo.w, &neighbor_geo.h);
581 if (!(neighbor_info = evas_object_data_get(crtc, "output_info"))) continue;
582 if (!neighbor_info->previous_mode) continue;
584 if (((geo.x + geo.w) == neighbor_geo.x)
585 || (geo.x == (neighbor_geo.x + neighbor_geo.w))
586 || (geo.x == neighbor_geo.x)
587 || ((geo.x + geo.w) == (neighbor_geo.x + neighbor_geo.w))
588 || ((geo.y + geo.h) == neighbor_geo.y)
589 || (geo.y == (neighbor_geo.y + neighbor_geo.h))
590 || (geo.y == neighbor_geo.y)
591 || ((geo.y + geo.h) == (neighbor_geo.y + neighbor_geo.h)))
593 neighbors = eina_list_append(neighbors, crtc);
601 _dialog_subdialog_arrangement_determine_positions_recursive(Evas_Object *obj)
603 Eina_List *neighbors, *iter;
604 Evas_Object *smart_parent, *crtc;
605 E_Config_Randr_Dialog_Output_Dialog_Data *dialog_data, *neighbor_info;
606 Eina_Rectangle geo, neighbor_geo, smart_geo;
608 // Each object is seen as a tree. All its edges are compared to their
609 // neighbors and wandered recusively.
610 EINA_SAFETY_ON_NULL_RETURN(obj);
612 smart_parent = e_config_runtime_info->gui.subdialogs.arrangement.smart_parent;
613 evas_object_geometry_get(smart_parent, &smart_geo.x, &smart_geo.y, &smart_geo.w, &smart_geo.h);
614 //fprintf(stderr, "CONF_RANDR: Smart Parent is at %dx%d\n", smart_geo.x, smart_geo.y);
615 neighbors = _dialog_subdialog_arrangement_neighbors_get(obj);
617 EINA_SAFETY_ON_FALSE_RETURN((dialog_data = evas_object_data_get(obj, "output_info")));
618 evas_object_geometry_get(obj, &geo.x, &geo.y, &geo.w, &geo.h);
620 //fprintf(stderr, "CONF_RANDR: Traversed element (%p) is at %dx%d\n", obj, geo.x, geo.y);
621 if (geo.x == e_config_runtime_info->gui.subdialogs.arrangement.relative_zero.x) dialog_data->new_pos.x = 0;
622 if (geo.y == e_config_runtime_info->gui.subdialogs.arrangement.relative_zero.y) dialog_data->new_pos.y = 0;
624 if ((dialog_data->new_pos.x != 0) || (dialog_data->new_pos.y != 0))
626 // Find neighbor object we can calculate our own coordinates from
627 EINA_LIST_FOREACH(neighbors, iter, crtc)
629 evas_object_geometry_get(crtc, &neighbor_geo.x, &neighbor_geo.y, &neighbor_geo.w, &neighbor_geo.h);
630 if (!(neighbor_info = evas_object_data_get(crtc, "output_info"))) continue;
632 evas_object_geometry_get(crtc, &neighbor_geo.x, &neighbor_geo.y, &neighbor_geo.w, &neighbor_geo.h);
634 if ((dialog_data->new_pos.x == Ecore_X_Randr_Unset) && (neighbor_info->new_pos.x != Ecore_X_Randr_Unset))
636 if ((geo.x + geo.w) == neighbor_geo.x)
638 dialog_data->new_pos.x = neighbor_info->new_pos.x - dialog_data->previous_mode->width;
641 if (geo.x == (neighbor_geo.x + neighbor_geo.w))
643 dialog_data->new_pos.x = neighbor_info->new_pos.x + neighbor_info->previous_mode->width;
646 if (geo.x == neighbor_geo.x)
648 dialog_data->new_pos.x = neighbor_info->new_pos.x;
651 if ((geo.x + geo.w) == (neighbor_geo.x + neighbor_geo.w))
653 dialog_data->new_pos.x = (neighbor_info->new_pos.x + neighbor_info->previous_mode->width) - dialog_data->previous_mode->width;
657 if ((dialog_data->new_pos.y == Ecore_X_Randr_Unset) && (neighbor_info->new_pos.y != Ecore_X_Randr_Unset))
659 if ((geo.y + geo.h) == neighbor_geo.y)
661 dialog_data->new_pos.y = neighbor_info->new_pos.y - dialog_data->previous_mode->height;
664 if (geo.y == (neighbor_geo.y + neighbor_geo.h))
666 dialog_data->new_pos.y = neighbor_info->new_pos.y + neighbor_info->previous_mode->height;
669 if (geo.y == neighbor_geo.y)
671 dialog_data->new_pos.y = neighbor_info->new_pos.y;
674 if ((geo.y + geo.h) == (neighbor_geo.y + neighbor_geo.h))
676 dialog_data->new_pos.y = (neighbor_info->new_pos.y + neighbor_info->previous_mode->height) - dialog_data->previous_mode->height;
679 if ((dialog_data->new_pos.x != Ecore_X_Randr_Unset)
680 && (dialog_data->new_pos.y != Ecore_X_Randr_Unset))
682 //fprintf(stderr, "CONF_RANDR: Determined position for %p: %dx%d\n", obj, dialog_data->new_pos.x, dialog_data->new_pos.y);
687 if ((dialog_data->new_pos.x != Ecore_X_Randr_Unset) || (dialog_data->new_pos.y != Ecore_X_Randr_Unset))
689 //Only wander all neighbors recursively, if they can use the current
690 //element as reference for their position
691 EINA_LIST_FOREACH(neighbors, iter, crtc)
693 neighbor_info = evas_object_data_get(crtc, "output_info");
694 if ((neighbor_info->new_pos.x == Ecore_X_Randr_Unset)
695 || (neighbor_info->new_pos.y == Ecore_X_Randr_Unset))
697 //fprintf(stderr, "CONF_RANDR: Now going to travel %p.\n", crtc);
698 _dialog_subdialog_arrangement_determine_positions_recursive(crtc);
702 eina_list_free(neighbors);
706 dialog_subdialog_arrangement_basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata __UNUSED__)
708 Eina_List *crtcs, *iter;
709 Evas_Object *smart_parent, *crtc, *top_left = NULL;
710 Eina_Rectangle geo, smart_geo;
711 E_Config_Randr_Dialog_Output_Dialog_Data *odd;
712 Evas_Coord_Point relz = { .x = 10000, .y = 10000};
713 Eina_Bool arrangement_failed = EINA_FALSE;
715 smart_parent = e_config_runtime_info->gui.subdialogs.arrangement.smart_parent;
716 evas_object_geometry_get(smart_parent, &smart_geo.x, &smart_geo.y, &smart_geo.w, &smart_geo.h);
717 crtcs = evas_object_smart_members_get(smart_parent);
719 //Create virtual borders around the displayed representations by finding
720 //relative x and y as virtual 0x0
721 EINA_LIST_FOREACH(crtcs, iter, crtc)
723 if (crtc == e_config_runtime_info->gui.subdialogs.arrangement.clipper) continue;
724 //Already reset values for upcoming calculation
725 if (!(odd = evas_object_data_get(crtc, "output_info"))) continue;
726 odd->new_pos.x = Ecore_X_Randr_Unset;
727 odd->new_pos.y = Ecore_X_Randr_Unset;
730 //See whether this element is closer to 0x0 than any before
731 evas_object_geometry_get(crtc, &geo.x, &geo.y, &geo.w, &geo.h);
743 e_config_runtime_info->gui.subdialogs.arrangement.relative_zero.x = relz.x;
744 e_config_runtime_info->gui.subdialogs.arrangement.relative_zero.y = relz.y;
745 if (top_left) _dialog_subdialog_arrangement_determine_positions_recursive(top_left);
747 EINA_LIST_FOREACH(crtcs, iter, crtc)
749 if ((crtc == e_config_runtime_info->gui.subdialogs.arrangement.clipper) || !(odd = evas_object_data_get(crtc, "output_info")) || !odd->crtc
750 || ((odd->new_pos.x == Ecore_X_Randr_Unset) || (odd->new_pos.y == Ecore_X_Randr_Unset))) continue;
751 if ((odd->previous_pos.x != odd->new_pos.x) || (odd->previous_pos.y != odd->new_pos.y))
753 fprintf(stderr, "CONF_RANDR: CRTC %x is moved to %dx%d\n", odd->crtc->xid, odd->new_pos.x, odd->new_pos.y);
754 if (!ecore_x_randr_crtc_pos_set(cfd->con->manager->root, odd->crtc->xid, odd->new_pos.x, odd->new_pos.y))
756 arrangement_failed = EINA_TRUE;
761 if (arrangement_failed)
765 ecore_x_randr_screen_reset(cfd->con->manager->root);
771 dialog_subdialog_arrangement_basic_check_changed(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
774 E_Config_Randr_Dialog_Output_Dialog_Data *output_dialog_data;
776 EINA_LIST_FOREACH(cfdata->output_dialog_data_list, iter, output_dialog_data)
778 if ((output_dialog_data->previous_pos.x != output_dialog_data->new_pos.x)
779 || (output_dialog_data->previous_pos.y != output_dialog_data->new_pos.y)
786 dialog_subdialog_arrangement_keep_changes(E_Config_Dialog_Data *cfdata)
788 E_Config_Randr_Dialog_Output_Dialog_Data *odd;
793 EINA_LIST_FOREACH(cfdata->output_dialog_data_list, iter, odd)
795 if (!odd->crtc || ((odd->new_pos.x == Ecore_X_Randr_Unset) || (odd->new_pos.y == Ecore_X_Randr_Unset))) continue;
796 odd->previous_pos.x = odd->new_pos.x;
797 odd->previous_pos.y = odd->new_pos.y;
798 odd->new_pos.x = Ecore_X_Randr_Unset;
799 odd->new_pos.y = Ecore_X_Randr_Unset;
804 dialog_subdialog_arrangement_discard_changes(E_Config_Dialog_Data *cfdata)
806 E_Config_Randr_Dialog_Output_Dialog_Data *odd;
811 EINA_LIST_FOREACH(cfdata->output_dialog_data_list, iter, odd)
813 if (!odd->crtc || ((odd->previous_pos.x == Ecore_X_Randr_Unset) || (odd->previous_pos.y == Ecore_X_Randr_Unset))) continue;
814 if (ecore_x_randr_crtc_pos_set(cfdata->manager->root, odd->crtc->xid, odd->previous_pos.x, odd->previous_pos.y))
816 odd->new_pos.x = odd->previous_pos.x;
817 odd->new_pos.y = odd->previous_pos.y;
818 odd->previous_pos.x = Ecore_X_Randr_Unset;
819 odd->previous_pos.y = Ecore_X_Randr_Unset;
820 ecore_x_randr_screen_reset(cfdata->manager->root);