Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / conf_randr / e_int_config_randr.c
1 #include "e.h"
2 #include "e_randr.h"
3 #include "e_int_config_randr.h"
4
5 /*
6  * BUGS:
7  * - ethumb sometimes returns garbage objects leading to a segv
8  *
9  * TODO:
10  * - write 1.2 per monitor configuration
11  * - write Smart object, so crtcs representations can be properly freed (events,
12  *   etc.)
13  *
14  * IMPROVABLE:
15  *  See comments starting with 'IMPROVABLE'
16  */
17 #ifndef  ECORE_X_RANDR_1_2
18 #define ECORE_X_RANDR_1_2 ((1 << 16) | 2)
19 #endif
20 #ifndef  ECORE_X_RANDR_1_3
21 #define ECORE_X_RANDR_1_3 ((1 << 16) | 3)
22 #endif
23
24 #ifdef  Ecore_X_Randr_None
25 #undef  Ecore_X_Randr_None
26 #define Ecore_X_Randr_None  0
27 #else
28 #define Ecore_X_Randr_None  0
29 #endif
30 #ifdef  Ecore_X_Randr_Unset
31 #undef  Ecore_X_Randr_Unset
32 #define Ecore_X_Randr_Unset -1
33 #else
34 #define Ecore_X_Randr_Unset -1
35 #endif
36
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)
40
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);
48
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];
53
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)
56 {
57    E_Config_Randr_Dialog_Output_Dialog_Data *dialog_data;
58
59    EINA_SAFETY_ON_NULL_RETURN_VAL(output_info, NULL);
60
61    dialog_data = E_NEW(E_Config_Randr_Dialog_Output_Dialog_Data, 1);
62
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));
64    if (crtc_info)
65      {
66         //already enabled screen, output info is already available in crtc
67         //struct
68         dialog_data->crtc = crtc_info;
69      }
70    else
71      {
72         //disabled monitor
73         dialog_data->output = output_info;
74      }
75    return dialog_data;
76 }
77
78 static void *
79 create_data(E_Config_Dialog *cfd)
80 {
81    Eina_List *iter;
82    E_Randr_Output_Info *output_info;
83    E_Config_Randr_Dialog_Output_Dialog_Data *odd;
84
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);
89
90    e_config_runtime_info->cfd = cfd;
91
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);
94
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)
98      {
99         if (!output_info)
100           {
101              fprintf(stderr, "CONF_RANDR: WWWWWWWWWWWWOOOOOOOOOOOOOTTTT an output_info of the central struct is NULL!\n");
102              continue;
103           }
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);
106      }
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);
112
113    return e_config_runtime_info;
114
115 _e_conf_randr_create_data_failed_free_data:
116    free(e_config_runtime_info);
117    return NULL;
118 }
119
120 static void
121 free_cfdata(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
122 {
123    E_Config_Randr_Dialog_Output_Dialog_Data *dialog_data;
124
125    EINA_SAFETY_ON_TRUE_RETURN(!E_RANDR_12);
126
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);
131
132    /*
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);
137    */
138
139    EINA_LIST_FREE(cfdata->output_dialog_data_list, dialog_data)
140      {
141         free(dialog_data);
142      }
143    cfdata->output_dialog_data_list = NULL;
144
145    free(cfdata);
146 }
147
148 static Eina_Bool
149 _e_conf_randr_confirmation_dialog_timer_cb(void *data)
150 {
151    E_Config_Randr_Dialog_Confirmation_Dialog_Data *cdd = (E_Config_Randr_Dialog_Confirmation_Dialog_Data *)data;
152    char buf[4096];
153
154    if (!cdd) return ECORE_CALLBACK_CANCEL;
155
156    --cdd->countdown;
157
158    if (cdd->countdown > 0)
159      {
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);
164      }
165    else
166      {
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>."));
171      }
172
173    e_dialog_text_set(cdd->dialog, buf);
174
175    if (cdd->countdown == 0)
176       {
177          _e_conf_randr_confirmation_dialog_discard_cb(cdd, cdd->dialog);
178          return ECORE_CALLBACK_CANCEL;
179       }
180    return ECORE_CALLBACK_RENEW;
181 }
182
183 static void
184 _e_conf_randr_confirmation_dialog_delete_cb(E_Win *win)
185 {
186    E_Dialog *dia;
187    E_Config_Randr_Dialog_Confirmation_Dialog_Data *cd;
188    E_Config_Dialog *cfd;
189
190    dia = win->data;
191    cd = dia->data;
192    cd->cfdata->gui.confirmation_dialog = NULL;
193    cfd = cd->cfdata->cfd;
194    if (cd->timer) ecore_timer_del(cd->timer);
195    cd->timer = NULL;
196    free(cd);
197    e_object_del(E_OBJECT(dia));
198    e_object_unref(E_OBJECT(cfd));
199 }
200
201 static void
202 _e_conf_randr_confirmation_dialog_keep_cb(void *data, E_Dialog *dia)
203 {
204    E_Config_Randr_Dialog_Confirmation_Dialog_Data *cdd = (E_Config_Randr_Dialog_Confirmation_Dialog_Data *)data;
205
206    if (!cdd) return;
207
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);
213
214    //cleanup dialog
215    _e_conf_randr_confirmation_dialog_delete_cb(dia->win);
216 }
217
218 static void
219 _e_conf_randr_confirmation_dialog_discard_cb(void *data, E_Dialog *dia)
220 {
221    E_Config_Randr_Dialog_Confirmation_Dialog_Data *cdd = (E_Config_Randr_Dialog_Confirmation_Dialog_Data *)data;
222
223    if (!cdd) return;
224
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);
230 }
231
232 static void
233 _e_conf_randr_confirmation_dialog_store_cb(void *data, E_Dialog *dia)
234 {
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;
237
238    if (!cdd) return;
239
240    //Create modifier
241    if (policy_widget_basic_check_changed(NULL, e_config_runtime_info))
242      modifier |= E_RANDR_CONFIGURATION_STORE_POLICIES;
243
244    if (resolution_widget_basic_check_changed(NULL, e_config_runtime_info))
245      modifier |= E_RANDR_CONFIGURATION_STORE_RESOLUTIONS;
246
247    if (arrangement_widget_basic_check_changed(NULL, e_config_runtime_info))
248      modifier |= E_RANDR_CONFIGURATION_STORE_ARRANGEMENT;
249
250    if (orientation_widget_basic_check_changed(NULL, e_config_runtime_info))
251      modifier |= E_RANDR_CONFIGURATION_STORE_ORIENTATIONS;
252
253    _e_conf_randr_confirmation_dialog_keep_cb(data, dia);
254
255    //but actually trigger saving the stuff
256    e_randr_store_configuration(modifier);
257
258 }
259
260 static void
261 _e_conf_randr_confirmation_dialog_new(E_Config_Dialog *cfd)
262 {
263    E_Config_Randr_Dialog_Confirmation_Dialog_Data *cd = E_NEW(E_Config_Randr_Dialog_Confirmation_Dialog_Data, 1);
264
265    char buf[4096];
266
267    if (!cd) return;
268
269    cd->cfd = cfd;
270
271    if ((cd->dialog = e_dialog_new(cfd->con, "E", "e_randr_confirmation_dialog")))
272      {
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);
276         cd->countdown = 15;
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));
295      }
296 }
297
298 static Evas_Object *
299 basic_create_widgets(E_Config_Dialog *cfd, Evas *canvas, E_Config_Dialog_Data *cfdata)
300 {
301    Evas_Object *table = NULL, *wl = NULL;
302
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);
305
306    e_config_runtime_info->gui.canvas = canvas;
307
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;
312
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);
315
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);
318    /*
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);
322     */
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;
329
330    cfdata->gui.dialog = table;
331
332    e_dialog_resizable_set(cfd->dia, EINA_TRUE);
333
334    return cfdata->gui.dialog;
335
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:
347    return NULL;
348 }
349
350 static int
351 basic_apply_data
352   (E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
353 {
354    Eina_Bool ret = EINA_TRUE;
355
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;
360
361    //the order matters except for policies!
362    if (policy_widget_basic_check_changed(cfd, cfdata))
363      {
364         ret &= policy_widget_basic_apply_data(cfd, cfdata);
365         if (!ret) return EINA_FALSE;
366      }
367
368    if (resolution_widget_basic_check_changed(cfd, cfdata))
369      {
370         ret &= resolution_widget_basic_apply_data(cfd, cfdata);
371         if (!ret) return EINA_FALSE;
372      }
373
374    if (arrangement_widget_basic_check_changed(cfd, cfdata))
375      {
376         ret &= arrangement_widget_basic_apply_data(cfd, cfdata);
377         if (!ret) return EINA_FALSE;
378      }
379
380    if (orientation_widget_basic_check_changed(cfd, cfdata))
381      ret &= orientation_widget_basic_apply_data(cfd, cfdata);
382
383    _e_conf_randr_confirmation_dialog_new(cfd);
384
385    return ret;
386 }
387
388 E_Config_Dialog *
389 e_int_config_randr(E_Container *con, const char *params __UNUSED__){
390    E_Config_Dialog *cfd;
391    E_Config_Dialog_View *v;
392
393    if (!E_RANDR_12 || (e_randr_screen_info.randr_version < ECORE_X_RANDR_1_2))
394      {
395         ecore_timer_add(0.5, _deferred_noxrandr_error, NULL);
396         fprintf(stderr, "CONF_RANDR: XRandR version >= 1.2 necessary to work.\n");
397         return NULL;
398      }
399
400    //Dialog already opened?
401    if (e_config_dialog_find("E", "screen/screen_setup")) return NULL;
402
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;
410
411    cfd = e_config_dialog_new(con, _("Screen Setup"),
412                              "E", "screen/screen_setup",
413                              "preferences-system-screen-setup", 0, v, NULL);
414    return cfd;
415 }
416
417 static Eina_Bool
418 _deferred_noxrandr_error(void *data __UNUSED__)
419 {
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;
428 }
429
430 static int
431 basic_check_changed(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
432 {
433    if (!cfdata)
434      return EINA_FALSE;
435
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));
440 }
441