3 #include "e_int_config_randr.h"
7 * - ethumb sometimes returns garbage objects leading to a segv
10 * - write 1.2 per monitor configuration
11 * - write Smart object, so crtcs representations can be properly freed (events,
15 * See comments starting with 'IMPROVABLE'
17 #ifndef ECORE_X_RANDR_1_2
18 #define ECORE_X_RANDR_1_2 ((1 << 16) | 2)
20 #ifndef ECORE_X_RANDR_1_3
21 #define ECORE_X_RANDR_1_3 ((1 << 16) | 3)
24 #ifdef Ecore_X_Randr_None
25 #undef Ecore_X_Randr_None
26 #define Ecore_X_Randr_None 0
28 #define Ecore_X_Randr_None 0
30 #ifdef Ecore_X_Randr_Unset
31 #undef Ecore_X_Randr_Unset
32 #define Ecore_X_Randr_Unset -1
34 #define Ecore_X_Randr_Unset -1
37 #define THEME_FILENAME "/e-module-conf_randr.edj"
38 #define TOOLBAR_ICONSIZE 16
39 #define E_RANDR_12 (e_randr_screen_info.rrvd_info.randr_info_12)
41 static void *create_data(E_Config_Dialog *cfd);
42 static void free_cfdata(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
43 static int basic_check_changed(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
44 static int basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
45 static Evas_Object *basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
46 static Eina_Bool _deferred_noxrandr_error(void *data);
47 static void _e_conf_randr_confirmation_dialog_discard_cb(void *data, E_Dialog *dia);
49 /* actual module specifics */
50 E_Config_Dialog_Data *e_config_runtime_info = NULL;
51 extern E_Module *conf_randr_module;
52 char _theme_file_path[PATH_MAX];
54 E_Config_Randr_Dialog_Output_Dialog_Data *
55 _dialog_output_dialog_data_new(E_Randr_Crtc_Info *crtc_info, E_Randr_Output_Info *output_info)
57 E_Config_Randr_Dialog_Output_Dialog_Data *dialog_data;
59 EINA_SAFETY_ON_NULL_RETURN_VAL(output_info, NULL);
61 dialog_data = E_NEW(E_Config_Randr_Dialog_Output_Dialog_Data, 1);
63 fprintf(stderr, "CONF_RANDR: Added output data struct for Output %d/CRTC %d.\n", output_info->xid, (output_info->crtc ? output_info->crtc->xid : Ecore_X_Randr_None));
66 //already enabled screen, output info is already available in crtc
68 dialog_data->crtc = crtc_info;
73 dialog_data->output = output_info;
79 create_data(E_Config_Dialog *cfd)
82 E_Randr_Output_Info *output_info;
83 E_Config_Randr_Dialog_Output_Dialog_Data *odd;
85 // Prove we got all things to get going
86 EINA_SAFETY_ON_TRUE_RETURN_VAL(!E_RANDR_12, NULL);
87 //e_randr_screen_info_refresh();
88 e_config_runtime_info = E_NEW(E_Config_Dialog_Data, 1);
90 e_config_runtime_info->cfd = cfd;
92 //Compose theme's file path and name
93 snprintf(_theme_file_path, sizeof(_theme_file_path), "%s%s", conf_randr_module->dir, THEME_FILENAME);
95 e_config_runtime_info->manager = e_manager_current_get();
96 e_config_runtime_info->output_dialog_data_list = NULL;
97 EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output_info)
101 fprintf(stderr, "CONF_RANDR: WWWWWWWWWWWWOOOOOOOOOOOOOTTTT an output_info of the central struct is NULL!\n");
104 if ((odd = _dialog_output_dialog_data_new(output_info->crtc, output_info)))
105 e_config_runtime_info->output_dialog_data_list = eina_list_append(e_config_runtime_info->output_dialog_data_list, odd);
107 //FIXME: Properly (stack-like) free data when creation fails
108 EINA_SAFETY_ON_FALSE_GOTO(resolution_widget_create_data(e_config_runtime_info), _e_conf_randr_create_data_failed_free_data);
109 EINA_SAFETY_ON_FALSE_GOTO(arrangement_widget_create_data(e_config_runtime_info), _e_conf_randr_create_data_failed_free_data);
110 EINA_SAFETY_ON_FALSE_GOTO(policy_widget_create_data(e_config_runtime_info), _e_conf_randr_create_data_failed_free_data);
111 EINA_SAFETY_ON_FALSE_GOTO(orientation_widget_create_data(e_config_runtime_info), _e_conf_randr_create_data_failed_free_data);
113 return e_config_runtime_info;
115 _e_conf_randr_create_data_failed_free_data:
116 free(e_config_runtime_info);
121 free_cfdata(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
123 E_Config_Randr_Dialog_Output_Dialog_Data *dialog_data;
125 EINA_SAFETY_ON_TRUE_RETURN(!E_RANDR_12);
127 arrangement_widget_free_cfdata(cfd, cfdata);
128 policy_widget_free_cfdata(cfd, cfdata);
129 resolution_widget_free_cfdata(cfd, cfdata);
130 orientation_widget_free_cfdata(cfd, cfdata);
133 evas_object_del(cfdata->gui.widgets.arrangement.widget);
134 evas_object_del(cfdata->gui.widgets.policy.widget);
135 evas_object_del(cfdata->gui.widgets.resolution.widget);
136 evas_object_del(cfdata->gui.widgets.orientation.widget);
139 EINA_LIST_FREE(cfdata->output_dialog_data_list, dialog_data)
143 cfdata->output_dialog_data_list = NULL;
149 _e_conf_randr_confirmation_dialog_timer_cb(void *data)
151 E_Config_Randr_Dialog_Confirmation_Dialog_Data *cdd = (E_Config_Randr_Dialog_Confirmation_Dialog_Data *)data;
154 if (!cdd) return ECORE_CALLBACK_CANCEL;
158 if (cdd->countdown > 0)
160 snprintf(buf, sizeof(buf),
161 _("Does this look OK? Click <hilight>Keep</hilight> if it does, or Restore if not.<ps>"
162 "If you do not press a button, the previous settings will be<ps>"
163 "restored in %d seconds."), cdd->countdown);
167 snprintf(buf, sizeof(buf),
168 _("Does this look OK? Click <hilight>Keep</hilight> if it does, or Restore if not.<ps>"
169 "If you do not press a button, the previous settings will be<ps>"
170 "restored <highlight>IMMEDIATELY</highlight>."));
173 e_dialog_text_set(cdd->dialog, buf);
175 if (cdd->countdown == 0)
177 _e_conf_randr_confirmation_dialog_discard_cb(cdd, cdd->dialog);
178 return ECORE_CALLBACK_CANCEL;
180 return ECORE_CALLBACK_RENEW;
184 _e_conf_randr_confirmation_dialog_delete_cb(E_Win *win)
187 E_Config_Randr_Dialog_Confirmation_Dialog_Data *cd;
188 E_Config_Dialog *cfd;
192 cd->cfdata->gui.confirmation_dialog = NULL;
193 cfd = cd->cfdata->cfd;
194 if (cd->timer) ecore_timer_del(cd->timer);
197 e_object_del(E_OBJECT(dia));
198 e_object_unref(E_OBJECT(cfd));
202 _e_conf_randr_confirmation_dialog_keep_cb(void *data, E_Dialog *dia)
204 E_Config_Randr_Dialog_Confirmation_Dialog_Data *cdd = (E_Config_Randr_Dialog_Confirmation_Dialog_Data *)data;
208 //ordinary "keep" functionality
209 arrangement_widget_keep_changes(cdd->cfdata);
210 orientation_widget_keep_changes(cdd->cfdata);
211 policy_widget_keep_changes(cdd->cfdata);
212 resolution_widget_keep_changes(cdd->cfdata);
215 _e_conf_randr_confirmation_dialog_delete_cb(dia->win);
219 _e_conf_randr_confirmation_dialog_discard_cb(void *data, E_Dialog *dia)
221 E_Config_Randr_Dialog_Confirmation_Dialog_Data *cdd = (E_Config_Randr_Dialog_Confirmation_Dialog_Data *)data;
225 arrangement_widget_discard_changes(cdd->cfdata);
226 orientation_widget_discard_changes(cdd->cfdata);
227 policy_widget_discard_changes(cdd->cfdata);
228 resolution_widget_discard_changes(cdd->cfdata);
229 _e_conf_randr_confirmation_dialog_delete_cb(dia->win);
233 _e_conf_randr_confirmation_dialog_store_cb(void *data, E_Dialog *dia)
235 E_Config_Randr_Dialog_Confirmation_Dialog_Data *cdd = (E_Config_Randr_Dialog_Confirmation_Dialog_Data *)data;
236 E_Randr_Configuration_Store_Modifier modifier = 0;
241 if (policy_widget_basic_check_changed(NULL, e_config_runtime_info))
242 modifier |= E_RANDR_CONFIGURATION_STORE_POLICIES;
244 if (resolution_widget_basic_check_changed(NULL, e_config_runtime_info))
245 modifier |= E_RANDR_CONFIGURATION_STORE_RESOLUTIONS;
247 if (arrangement_widget_basic_check_changed(NULL, e_config_runtime_info))
248 modifier |= E_RANDR_CONFIGURATION_STORE_ARRANGEMENT;
250 if (orientation_widget_basic_check_changed(NULL, e_config_runtime_info))
251 modifier |= E_RANDR_CONFIGURATION_STORE_ORIENTATIONS;
253 _e_conf_randr_confirmation_dialog_keep_cb(data, dia);
255 //but actually trigger saving the stuff
256 e_randr_store_configuration(modifier);
261 _e_conf_randr_confirmation_dialog_new(E_Config_Dialog *cfd)
263 E_Config_Randr_Dialog_Confirmation_Dialog_Data *cd = E_NEW(E_Config_Randr_Dialog_Confirmation_Dialog_Data, 1);
271 if ((cd->dialog = e_dialog_new(cfd->con, "E", "e_randr_confirmation_dialog")))
273 e_dialog_title_set(cd->dialog, _("New settings confirmation"));
274 cd->cfdata = cfd->cfdata;
275 cd->timer = ecore_timer_add(1.0, _e_conf_randr_confirmation_dialog_timer_cb, cd);
277 cd->dialog->data = cd;
278 e_dialog_icon_set(cd->dialog, "preferences-system-screen-resolution", 48);
279 e_win_delete_callback_set(cd->dialog->win, _e_conf_randr_confirmation_dialog_delete_cb);
280 snprintf(buf, sizeof(buf),
281 _("Does this look OK? Click <hilight>Keep</hilight> if it does, or Restore if not.<ps>"
282 "If you do not press a button, the previous settings will be<ps>"
283 "restored in %d seconds."), cd->countdown);
284 e_dialog_text_set(cd->dialog, buf);
285 e_dialog_button_add(cd->dialog, _("Keep"), NULL, _e_conf_randr_confirmation_dialog_keep_cb, cd);
286 e_dialog_button_add(cd->dialog, _("Store Permanently"), NULL, _e_conf_randr_confirmation_dialog_store_cb, cd);
287 e_dialog_button_add(cd->dialog, _("Restore"), NULL, _e_conf_randr_confirmation_dialog_discard_cb, cd);
288 e_dialog_button_focus_num(cd->dialog, 1);
289 e_win_centered_set(cd->dialog->win, 1);
290 e_win_borderless_set(cd->dialog->win, 1);
291 e_win_layer_set(cd->dialog->win, 6);
292 e_win_sticky_set(cd->dialog->win, 1);
293 e_dialog_show(cd->dialog);
294 e_object_ref(E_OBJECT(cfd));
299 basic_create_widgets(E_Config_Dialog *cfd, Evas *canvas, E_Config_Dialog_Data *cfdata)
301 Evas_Object *table = NULL, *wl = NULL;
303 EINA_SAFETY_ON_TRUE_RETURN_VAL (!E_RANDR_12 || (e_randr_screen_info.randr_version < ECORE_X_RANDR_1_2), NULL);
304 EINA_SAFETY_ON_TRUE_RETURN_VAL((!canvas || !cfdata), NULL);
306 e_config_runtime_info->gui.canvas = canvas;
308 if (!(cfdata->gui.widgets.arrangement.widget = arrangement_widget_basic_create_widgets(canvas))) goto _dialog_create_widget_arrangement_fail;
309 if (!(cfdata->gui.widgets.policy.widget = policy_widget_basic_create_widgets(canvas))) goto _dialog_create_widget_policies_fail;
310 if (!(cfdata->gui.widgets.resolution.widget = resolution_widget_basic_create_widgets(canvas))) goto _dialog_create_widget_resolutions_fail;
311 if (!(cfdata->gui.widgets.orientation.widget = orientation_widget_basic_create_widgets(canvas))) goto _dialog_create_widget_orientation_fail;
313 EINA_SAFETY_ON_FALSE_GOTO((table = e_widget_table_add(canvas, EINA_FALSE)), _dialog_create_widgets_fail);
314 EINA_SAFETY_ON_FALSE_GOTO((wl = e_widget_list_add(canvas, EINA_FALSE, EINA_TRUE)), _dialog_create_widget_list_fail);
316 //e_widget_table_object_append(Evas_Object *obj, Evas_Object *sobj, int col, int row, int colspan, int rowspan, int fill_w, int fill_h, int expand_w, int expand_h);
317 e_widget_table_object_append(table, cfdata->gui.widgets.arrangement.widget, 1, 1, 1, 1, 1, 1, 1, 1);
319 e_widget_table_object_append(table, cfdata->gui.widgets.policy.widget, 1, 2, 1, 1, 0, 0, 0, 0);
320 e_widget_table_object_append(table, cfdata->gui.widgets.orientation.widget, 2, 2, 1, 1, 0, 0, 0, 0);
321 e_widget_table_object_append(table, cfdata->gui.widgets.resolution.widget, 3, 2, 1, 1, EVAS_HINT_FILL, EVAS_HINT_FILL, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
323 //e_widget_list_object_append(Evas_Object *obj, Evas_Object *sobj, int fill, int expand, double align);
324 e_widget_list_object_append(wl, cfdata->gui.widgets.policy.widget, 0, 0, 0.0);
325 e_widget_list_object_append(wl, cfdata->gui.widgets.orientation.widget, 0, 0, 0.0);
326 e_widget_list_object_append(wl, cfdata->gui.widgets.resolution.widget, EVAS_HINT_FILL, EVAS_HINT_EXPAND, 1.0);
327 e_widget_table_object_append(table, wl, 1, 2, 1, 1, EVAS_HINT_FILL, EVAS_HINT_FILL, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
328 cfdata->gui.widget_list = wl;
330 cfdata->gui.dialog = table;
332 e_dialog_resizable_set(cfd->dia, EINA_TRUE);
334 return cfdata->gui.dialog;
336 _dialog_create_widget_list_fail:
337 evas_object_del(table);
338 _dialog_create_widgets_fail:
339 evas_object_del(cfdata->gui.widgets.orientation.widget);
340 _dialog_create_widget_orientation_fail:
341 evas_object_del(cfdata->gui.widgets.resolution.widget);
342 _dialog_create_widget_resolutions_fail:
343 evas_object_del(cfdata->gui.widgets.policy.widget);
344 _dialog_create_widget_policies_fail:
345 evas_object_del(cfdata->gui.widgets.arrangement.widget);
346 _dialog_create_widget_arrangement_fail:
352 (E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
354 Eina_Bool ret = EINA_TRUE;
356 fprintf(stderr, "CONF_RANDR: New configuration is beeing applied.\n");
357 //this is a special case, where the function is called, before the
358 //configuration data is created.
359 if (!cfdata) return EINA_FALSE;
361 //the order matters except for policies!
362 if (policy_widget_basic_check_changed(cfd, cfdata))
364 ret &= policy_widget_basic_apply_data(cfd, cfdata);
365 if (!ret) return EINA_FALSE;
368 if (resolution_widget_basic_check_changed(cfd, cfdata))
370 ret &= resolution_widget_basic_apply_data(cfd, cfdata);
371 if (!ret) return EINA_FALSE;
374 if (arrangement_widget_basic_check_changed(cfd, cfdata))
376 ret &= arrangement_widget_basic_apply_data(cfd, cfdata);
377 if (!ret) return EINA_FALSE;
380 if (orientation_widget_basic_check_changed(cfd, cfdata))
381 ret &= orientation_widget_basic_apply_data(cfd, cfdata);
383 _e_conf_randr_confirmation_dialog_new(cfd);
389 e_int_config_randr(E_Container *con, const char *params __UNUSED__){
390 E_Config_Dialog *cfd;
391 E_Config_Dialog_View *v;
393 if (!E_RANDR_12 || (e_randr_screen_info.randr_version < ECORE_X_RANDR_1_2))
395 ecore_timer_add(0.5, _deferred_noxrandr_error, NULL);
396 fprintf(stderr, "CONF_RANDR: XRandR version >= 1.2 necessary to work.\n");
400 //Dialog already opened?
401 if (e_config_dialog_find("E", "screen/screen_setup")) return NULL;
403 v = E_NEW(E_Config_Dialog_View, 1);
404 v->create_cfdata = create_data;
405 v->free_cfdata = free_cfdata;
406 v->basic.apply_cfdata = basic_apply_data;
407 v->basic.create_widgets = basic_create_widgets;
408 v->basic.check_changed = basic_check_changed;
409 //v->override_auto_apply = 0;
411 cfd = e_config_dialog_new(con, _("Screen Setup"),
412 "E", "screen/screen_setup",
413 "preferences-system-screen-setup", 0, v, NULL);
418 _deferred_noxrandr_error(void *data __UNUSED__)
420 e_util_dialog_show(_("Missing Features"),
421 _("Your X Display Server is missing support for<ps>"
422 "the <hilight>XRandR</hilight> (X Resize and Rotate) extension version 1.2 or above.<ps>"
423 "You cannot change screen resolutions without<ps>"
424 "the support of this extension. It could also be<ps>"
425 "that at the time <hilight>ecore</hilight> was built, there<ps>"
426 "was no XRandR support detected."));
427 return ECORE_CALLBACK_CANCEL;
431 basic_check_changed(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
436 return (arrangement_widget_basic_check_changed(cfd, cfdata)
437 || policy_widget_basic_check_changed(cfd, cfdata)
438 || orientation_widget_basic_check_changed(cfd, cfdata)
439 || resolution_widget_basic_check_changed(cfd, cfdata));