update for beta release
[framework/uifw/e17.git] / src / modules / conf_keybindings / e_int_config_mousebindings.c
1 #include "e.h"
2
3 #define TEXT_NO_PARAMS _("<None>")
4 #define EXAMPLE_STRING "example : "
5 #define E_BINDING_CONTEXT_NUMBER  10
6
7 #define TEXT_PRESS_MOUSE_BINIDING_SEQUENCE _("Please hold any modifier you want<br>" \
8                                              "and press any button on your mouse,<br> or roll a" \
9                                              " wheel, to assign mouse binding." \
10                                              "<br>Press <hilight>Escape</highlight> to abort.")
11
12 static void *_create_data(E_Config_Dialog *cfd);
13 static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
14 static int _basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
15 static Evas_Object *_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
16
17 static void _fill_data(E_Config_Dialog_Data *cfdata);
18 static void _fill_actions_list(E_Config_Dialog_Data *cfdata);
19
20 /******************* Callbacks *************/
21 static void _binding_change_cb(void *data);
22 static void _action_change_cb(void *data);
23 static void _delete_mouse_binding_cb(void *data, void *data2);
24 static void _delete_all_mouse_binding_cb(void *data, void *data2);
25 static void _restore_mouse_binding_defaults_cb(void *data, void *data2);
26 static void _add_mouse_binding_cb(void *data, void *data2);
27 static void _modify_mouse_binding_cb(void *data, void *data2);
28
29 /******************* Updates *****************/
30 static void _update_action_list(E_Config_Dialog_Data *cfdata);
31 static void _update_action_params(E_Config_Dialog_Data *cfdata);
32 static void _update_mouse_binding_list(E_Config_Dialog_Data *cfdata);
33 static void _update_buttons(E_Config_Dialog_Data *cfdata);
34 static void _update_binding_context(E_Config_Dialog_Data *cfdata);
35
36 /****************** Helper *****************/
37 static void _find_key_binding_action(const char *action, const char *params, int *g, int *a, int *n);
38 static char *_helper_button_name_get(E_Config_Binding_Mouse *eb);
39 static char *_helper_wheel_name_get(E_Config_Binding_Wheel *bw);
40 static char *_helper_modifier_name_get(int mod);
41 static void _auto_apply_changes(E_Config_Dialog_Data *cfdata);
42
43 /********* Sorting ***************/
44 static int _mouse_binding_sort_cb(const void *d1, const void *d2);
45 static int _wheel_binding_sort_cb(const void *d1, const void *d2);
46
47 /********* grab window **********/
48 static void _grab_wnd_show(E_Config_Dialog_Data *cfdata);
49 static void _grab_wnd_hide(E_Config_Dialog_Data *cfdata);
50 static Eina_Bool _grab_mouse_down_cb(void *data, int type, void *event);
51 static Eina_Bool _grab_mouse_wheel_cb(void *data, int type, void *event);
52 static Eina_Bool _grab_key_down_cb(void *data, int type, void *event);
53
54 struct _E_Config_Dialog_Data
55 {
56   E_Config_Dialog *cfd;
57
58   Evas *evas;
59
60   struct
61     {
62        Eina_List *mouse;
63        Eina_List *wheel;
64     } binding;
65
66   struct
67     {
68        const char *binding;
69        const char *action;
70        char *params;
71        int context;
72
73        const char *cur;
74        int add; /*just to distinguesh among two buttons add/modify */
75
76        E_Dialog *dia;
77        Ecore_X_Window bind_win;
78        Eina_List *handlers;
79     } locals;
80
81   struct 
82     { 
83        Evas_Object *o_binding_list;
84        Evas_Object *o_action_list;
85        Evas_Object *o_params;
86        Evas_Object *o_del;
87        Evas_Object *o_mod;
88        Evas_Object *o_del_all;
89        struct {
90          Evas_Object *o_any, *o_border, *o_menu, *o_winlist, *o_popup, *o_zone,
91                      *o_container, *o_manager, *o_none;
92        } context;
93     } gui;
94 };
95
96 E_Config_Dialog *
97 e_int_config_mousebindings(E_Container *con, const char *params __UNUSED__)
98 {
99    E_Config_Dialog *cfd;
100    E_Config_Dialog_View *v;
101    
102    if (e_config_dialog_find("E", "keyboard_and_mouse/mouse_bindings")) return NULL;
103    v = E_NEW(E_Config_Dialog_View, 1);
104    
105    v->create_cfdata = _create_data;
106    v->free_cfdata = _free_data;
107    v->basic.apply_cfdata = _basic_apply_data;
108    v->basic.create_widgets = _basic_create_widgets;
109    v->override_auto_apply = 0;
110    
111    cfd = e_config_dialog_new(con,
112                              _("Mouse Bindings Settings"),
113                              "E", "keyboard_and_mouse/mouse_bindings",
114                              "preferences-desktop-mouse", 0, v, NULL);
115    return cfd;
116 }
117
118 static void
119 _fill_data(E_Config_Dialog_Data *cfdata)
120 {
121    Eina_List *l;
122    E_Config_Binding_Mouse *eb, *eb2;
123    E_Config_Binding_Wheel *bw, *bw2;
124
125    cfdata->locals.binding = eina_stringshare_add("");
126    cfdata->locals.action = eina_stringshare_add("");
127    cfdata->locals.params = strdup("");
128    cfdata->locals.context = E_BINDING_CONTEXT_ANY;
129    cfdata->binding.mouse = NULL;
130    cfdata->binding.wheel = NULL;
131    cfdata->locals.bind_win = 0;
132    cfdata->locals.handlers =  NULL;
133    cfdata->locals.dia = NULL;
134
135    EINA_LIST_FOREACH(e_config->mouse_bindings, l, eb)
136      {
137         eb2 = E_NEW(E_Config_Binding_Mouse, 1);
138         eb2->context = eb->context;
139         eb2->button = eb->button;
140         eb2->modifiers = eb->modifiers;
141         eb2->any_mod = eb->any_mod;
142         eb2->action = !eb->action ? NULL : eina_stringshare_add(eb->action);
143         eb2->params = !eb->params ? NULL : eina_stringshare_add(eb->params);
144
145         cfdata->binding.mouse = eina_list_append(cfdata->binding.mouse, eb2);
146      }
147
148    EINA_LIST_FOREACH(e_config->wheel_bindings, l, bw)
149      {
150         bw2 = E_NEW(E_Config_Binding_Wheel, 1);
151         bw2->context = bw->context;
152         bw2->direction = bw->direction;
153         bw2->z = bw->z;
154         bw2->modifiers = bw->modifiers;
155         bw2->any_mod = bw->any_mod;
156         bw2->action = !bw->action ? NULL : eina_stringshare_add(bw->action);
157         bw2->params = !bw->params ? NULL : eina_stringshare_add(bw->params);
158
159         cfdata->binding.wheel = eina_list_append(cfdata->binding.wheel, bw2);
160      }
161 }
162
163 static void *
164 _create_data(E_Config_Dialog *cfd)
165 {
166    E_Config_Dialog_Data *cfdata;
167    
168    cfdata = E_NEW(E_Config_Dialog_Data, 1);
169    
170    _fill_data(cfdata);
171    cfdata->cfd = cfd;
172    return cfdata;
173 }
174
175 static void
176 _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
177 {
178    E_Config_Binding_Mouse *eb;
179    E_Config_Binding_Wheel *bw;
180
181    EINA_LIST_FREE(cfdata->binding.mouse, eb)
182      {
183         eina_stringshare_del(eb->action);
184         eina_stringshare_del(eb->params);
185         E_FREE(eb);
186      }
187
188    EINA_LIST_FREE(cfdata->binding.wheel, bw)
189      {
190         eina_stringshare_del(bw->action);
191         eina_stringshare_del(bw->params);
192         E_FREE(bw);
193      }
194
195    eina_stringshare_del(cfdata->locals.binding);
196    eina_stringshare_del(cfdata->locals.action);
197    eina_stringshare_del(cfdata->locals.cur);
198
199    if (cfdata->locals.params) free(cfdata->locals.params);
200    E_FREE(cfdata);
201 }
202
203 static int
204 _basic_apply_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
205
206    Eina_List *l;
207    E_Config_Binding_Mouse *eb, *eb2;
208    E_Config_Binding_Wheel *bw, *bw2;
209
210    _auto_apply_changes(cfdata);
211
212    e_border_button_bindings_ungrab_all();
213    EINA_LIST_FREE(e_config->mouse_bindings, eb)
214      {
215         e_bindings_mouse_del(eb->context, eb->button, eb->modifiers, eb->any_mod,
216                              eb->action, eb->params);
217         eina_stringshare_del(eb->action);
218         eina_stringshare_del(eb->params);
219         E_FREE(eb);
220      }
221
222    EINA_LIST_FOREACH(cfdata->binding.mouse, l, eb)
223      {
224         eb2 = E_NEW(E_Config_Binding_Mouse, 1);
225         eb2->context = eb->context;
226         eb2->button = eb->button;
227         eb2->modifiers = eb->modifiers;
228         eb2->any_mod = eb->any_mod;
229         eb2->action = !eb->action ? NULL : eina_stringshare_add(eb->action);
230         eb2->params = !eb->params ? NULL : eina_stringshare_add(eb->params);
231
232         e_config->mouse_bindings = eina_list_append(e_config->mouse_bindings, eb2);
233         e_bindings_mouse_add(eb2->context, eb2->button, eb2->modifiers, eb2->any_mod,
234                              eb2->action, eb2->params);
235      }
236
237    EINA_LIST_FREE(e_config->wheel_bindings, bw)
238      {
239         e_bindings_wheel_del(bw->context, bw->direction, bw->z, bw->modifiers, bw->any_mod,
240                              bw->action, bw->params);
241         eina_stringshare_del(bw->action);
242         eina_stringshare_del(bw->params);
243         E_FREE(bw);
244      }
245
246    EINA_LIST_FOREACH(cfdata->binding.wheel, l, bw)
247      {
248         bw2 = E_NEW(E_Config_Binding_Wheel, 1);
249         bw2->context = bw->context;
250         bw2->direction = bw->direction;
251         bw2->z = bw->z;
252         bw2->modifiers = bw->modifiers;
253         bw2->any_mod = bw->any_mod;
254         bw2->action = !bw->action ? NULL : eina_stringshare_add(bw->action);
255         bw2->params = !bw->params ? NULL : eina_stringshare_add(bw->params);
256
257         e_config->wheel_bindings = eina_list_append(e_config->wheel_bindings, bw2);
258         e_bindings_wheel_add(bw2->context, bw2->direction, bw2->z, bw2->modifiers,
259                              bw2->any_mod, bw2->action, bw2->params);
260      }
261    e_border_button_bindings_grab_all();
262
263    e_config_save_queue();
264    return 1;
265 }
266
267 static Evas_Object *
268 _basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
269 {
270    Evas_Object *o, *of, *ot, *ob;
271    E_Radio_Group *rg;
272    
273    cfdata->evas = evas;
274    o = e_widget_list_add(evas, 0, 1);
275    ot = e_widget_frametable_add(evas, _("Mouse Bindings"), 0);
276    ob = e_widget_ilist_add(evas, 32, 32, &(cfdata->locals.binding));
277    cfdata->gui.o_binding_list = ob;
278    e_widget_size_min_set(ob, 200, 200);
279    e_widget_frametable_object_append(ot, ob, 0, 0, 2, 1, 1, 1, 1, 1);
280
281    ob = e_widget_button_add(evas, _("Add Binding"), NULL, _add_mouse_binding_cb, cfdata, NULL);
282    e_widget_frametable_object_append(ot, ob, 0, 1, 1, 1, 1, 0, 1, 0);
283    ob = e_widget_button_add(evas, _("Delete Binding"), NULL, _delete_mouse_binding_cb, cfdata, NULL);
284    cfdata->gui.o_del = ob;
285    e_widget_disabled_set(ob, 1);
286    e_widget_frametable_object_append(ot, ob, 1, 1, 1, 1, 1, 0, 1, 0);
287    ob = e_widget_button_add(evas, _("Modify Binding"), NULL, _modify_mouse_binding_cb, cfdata, NULL);
288    cfdata->gui.o_mod = ob;
289    e_widget_disabled_set(ob, 1);
290    e_widget_frametable_object_append(ot, ob, 0, 2, 1, 1, 1, 0, 1, 0);
291    ob = e_widget_button_add(evas, _("Delete All"), NULL, _delete_all_mouse_binding_cb, cfdata, NULL);
292    cfdata->gui.o_del_all = ob;
293    e_widget_disabled_set(ob, 1);
294    e_widget_frametable_object_append(ot, ob, 1, 2, 1, 1, 1, 0, 1, 0);
295    ob = e_widget_button_add(evas, _("Restore Default Bindings"), "enlightenment",
296                             _restore_mouse_binding_defaults_cb, cfdata, NULL);
297    e_widget_frametable_object_append(ot, ob, 0, 3, 2, 1, 1, 0, 1, 0);
298    e_widget_list_object_append(o, ot, 1, 1, 0.5);
299
300    ot = e_widget_table_add(evas, 0);
301    of = e_widget_framelist_add(evas, _("Action"), 0);
302    ob = e_widget_ilist_add(evas, 24, 24, &(cfdata->locals.action));
303    cfdata->gui.o_action_list = ob;
304    e_widget_size_min_set(ob, 200, 200);
305    e_widget_framelist_object_append(of, ob);
306    e_widget_table_object_append(ot, of, 0, 0, 3, 1, 1, 1, 1, 1);
307    
308    of = e_widget_framelist_add(evas, _("Action Params"), 0);
309    ob = e_widget_entry_add(evas, &(cfdata->locals.params), NULL, NULL, NULL);
310    e_widget_disabled_set(ob, 1);
311    cfdata->gui.o_params = ob;
312    e_widget_framelist_object_append(of, ob);
313    e_widget_table_object_append(ot, of, 0, 1, 3, 1, 1, 1, 1, 0);
314
315    of = e_widget_frametable_add(evas, _("Action Context"), 1);
316    rg = e_widget_radio_group_new(&(cfdata->locals.context));
317    ob = e_widget_radio_add(evas, _("Any"), E_BINDING_CONTEXT_ANY, rg);
318    cfdata->gui.context.o_any = ob;
319    e_widget_disabled_set(ob, 1);
320    e_widget_frametable_object_append(of, ob, 0, 0, 1, 1, 1, 1, 1, 1);
321    ob = e_widget_radio_add(evas, _("Border"), E_BINDING_CONTEXT_BORDER, rg);
322    cfdata->gui.context.o_border = ob;
323    e_widget_disabled_set(ob, 1);
324    e_widget_frametable_object_append(of, ob, 0, 1, 1, 1, 1, 1, 1, 1);
325    ob = e_widget_radio_add(evas, _("Menu"), E_BINDING_CONTEXT_MENU, rg);
326    cfdata->gui.context.o_menu = ob;
327    e_widget_disabled_set(ob, 1);
328    e_widget_frametable_object_append(of, ob, 0, 2, 1, 1, 1, 1, 1, 1);
329    ob = e_widget_radio_add(evas, _("Win List"), E_BINDING_CONTEXT_WINLIST, rg);
330    cfdata->gui.context.o_winlist = ob;
331    e_widget_disabled_set(ob, 1);
332    e_widget_frametable_object_append(of, ob, 1, 0, 1, 1, 1, 1, 1, 1);
333    ob = e_widget_radio_add(evas, _("Popup"), E_BINDING_CONTEXT_POPUP, rg);
334    cfdata->gui.context.o_popup = ob;
335    e_widget_disabled_set(ob, 1);
336    e_widget_frametable_object_append(of, ob, 1, 1, 1, 1, 1, 1, 1, 1);
337    ob = e_widget_radio_add(evas, _("Zone"), E_BINDING_CONTEXT_ZONE, rg);
338    cfdata->gui.context.o_zone = ob;
339    e_widget_disabled_set(ob, 1);
340    e_widget_frametable_object_append(of, ob, 1, 2, 1, 1, 1, 1, 1, 1);
341    ob = e_widget_radio_add(evas, _("Container"), E_BINDING_CONTEXT_CONTAINER, rg);
342    cfdata->gui.context.o_container = ob;
343    e_widget_disabled_set(ob, 1);
344    e_widget_frametable_object_append(of, ob, 2, 0, 1, 1, 1, 1, 1, 1);
345    ob = e_widget_radio_add(evas, _("Manager"), E_BINDING_CONTEXT_MANAGER, rg);
346    cfdata->gui.context.o_manager = ob;
347    e_widget_disabled_set(ob, 1);
348    e_widget_frametable_object_append(of, ob, 2, 1, 1, 1, 1, 1, 1, 1);
349    ob = e_widget_radio_add(evas, _("None"), E_BINDING_CONTEXT_NONE, rg);
350    cfdata->gui.context.o_none = ob;
351    e_widget_disabled_set(ob, 1);
352    e_widget_frametable_object_append(of, ob, 2, 2, 1, 1, 1, 1, 1, 1);
353    e_widget_table_object_append(ot, of, 0, 2, 3, 1, 1, 1, 1, 0);
354    e_widget_list_object_append(o, ot, 1, 1, 0.5);
355    
356    _update_mouse_binding_list(cfdata);
357    _fill_actions_list(cfdata);
358    
359    e_dialog_resizable_set(cfd->dia, 1);
360    return o;
361 }
362
363 static void
364 _fill_actions_list(E_Config_Dialog_Data *cfdata)
365 {
366    char buf[1024];
367    Eina_List *l, *l2;
368    E_Action_Group *actg;
369    E_Action_Description *actd;
370    int g, a;
371
372    evas_event_freeze(evas_object_evas_get(cfdata->gui.o_action_list));
373    edje_freeze();
374    e_widget_ilist_freeze(cfdata->gui.o_action_list);
375    
376    e_widget_ilist_clear(cfdata->gui.o_action_list);
377    for (l = e_action_groups_get(), g = 0; l; l = l->next, g++)
378      {
379         actg = l->data;
380
381         if (!actg->acts) continue;
382
383         e_widget_ilist_header_append(cfdata->gui.o_action_list, NULL, _(actg->act_grp));
384
385         for (l2 = actg->acts, a = 0; l2; l2 = l2->next, a++)
386           {
387              actd = l2->data;
388
389              snprintf(buf, sizeof(buf), "%d %d", g, a);
390              e_widget_ilist_append(cfdata->gui.o_action_list, NULL, _(actd->act_name),
391                                    _action_change_cb, cfdata, buf);
392           }
393      }
394    e_widget_ilist_go(cfdata->gui.o_action_list);
395    e_widget_ilist_thaw(cfdata->gui.o_action_list);
396    edje_thaw();
397    evas_event_thaw(evas_object_evas_get(cfdata->gui.o_action_list));
398 }
399
400 /******************* Callbacks *************/
401 static void
402 _add_mouse_binding_cb(void *data, void *data2 __UNUSED__)
403 {
404    E_Config_Dialog_Data *cfdata;
405
406    cfdata = data;
407    _auto_apply_changes(cfdata);
408
409    cfdata->locals.add = 1;
410    _grab_wnd_show(cfdata);
411 }
412
413 static void
414 _modify_mouse_binding_cb(void *data, void *data2 __UNUSED__)
415 {
416    E_Config_Dialog_Data *cfdata;
417
418    cfdata = data;
419    _auto_apply_changes(cfdata);
420
421    cfdata->locals.add = 0;
422    _grab_wnd_show(cfdata);
423 }
424
425 static void
426 _action_change_cb(void *data)
427 {
428    E_Config_Dialog_Data *cfdata;
429
430    cfdata = data;
431    _update_action_params(cfdata);
432 }
433
434 static void
435 _binding_change_cb(void *data)
436 {
437    E_Config_Dialog_Data *cfdata;
438
439    cfdata = data;
440
441    _auto_apply_changes(cfdata);
442
443    eina_stringshare_del(cfdata->locals.cur);
444    cfdata->locals.cur = NULL;
445
446    if (cfdata->locals.binding[0]) 
447      cfdata->locals.cur = eina_stringshare_ref(cfdata->locals.binding);
448
449    _update_buttons(cfdata);
450    _update_action_list(cfdata);
451    _update_binding_context(cfdata);
452 }
453
454 static void
455 _delete_all_mouse_binding_cb(void *data, void *data2 __UNUSED__)
456 {
457    E_Config_Dialog_Data *cfdata;
458    E_Config_Binding_Mouse *eb;
459    E_Config_Binding_Wheel *bw;
460
461    cfdata = data;
462
463    /* FIXME: need confirmation dialog */
464    EINA_LIST_FREE(cfdata->binding.mouse, eb)
465      {
466         eina_stringshare_del(eb->action);
467         eina_stringshare_del(eb->params);
468         E_FREE(eb);
469      }
470
471    EINA_LIST_FREE(cfdata->binding.wheel, bw)
472      {
473         eina_stringshare_del(bw->action);
474         eina_stringshare_del(bw->params);
475         E_FREE(bw);
476      }
477
478    eina_stringshare_del(cfdata->locals.cur);
479    cfdata->locals.cur = NULL;
480
481    e_widget_ilist_clear(cfdata->gui.o_binding_list);
482    e_widget_ilist_go(cfdata->gui.o_binding_list);
483    e_widget_ilist_unselect(cfdata->gui.o_action_list);
484    e_widget_entry_clear(cfdata->gui.o_params);
485    e_widget_disabled_set(cfdata->gui.o_params, 1);
486
487    _update_buttons(cfdata);
488    _update_binding_context(cfdata);
489 }
490
491 static void
492 _delete_mouse_binding_cb(void *data, void *data2 __UNUSED__)
493 {
494    Eina_List *l;
495    int sel, n;
496    E_Config_Dialog_Data *cfdata;
497    E_Config_Binding_Mouse *eb;
498    E_Config_Binding_Wheel *bw;
499
500    cfdata = data;
501
502    sel = e_widget_ilist_selected_get(cfdata->gui.o_binding_list);
503    if (cfdata->locals.binding[0] == 'm')
504      {
505         sscanf(cfdata->locals.binding, "m%d", &n);
506         l = eina_list_nth_list(cfdata->binding.mouse, n);
507         if (l)
508           {
509              eb = eina_list_data_get(l);
510              eina_stringshare_del(eb->action);
511              eina_stringshare_del(eb->params);
512              E_FREE(eb);
513
514              cfdata->binding.mouse = eina_list_remove_list(cfdata->binding.mouse, l);
515           }
516      }
517    else if (cfdata->locals.binding[0] == 'w')
518      {
519         sscanf(cfdata->locals.binding, "w%d", &n);
520         l = eina_list_nth_list(cfdata->binding.wheel, n);
521         if (l)
522           {
523              bw = eina_list_data_get(l);
524              eina_stringshare_del(bw->action);
525              eina_stringshare_del(bw->params);
526              E_FREE(bw);
527
528              cfdata->binding.wheel = eina_list_remove_list(cfdata->binding.wheel, l);
529           }
530      }
531    else
532      return;
533
534    _update_mouse_binding_list(cfdata);
535    if (sel >= e_widget_ilist_count(cfdata->gui.o_binding_list))
536      sel = e_widget_ilist_count(cfdata->gui.o_binding_list) - 1;
537
538    eina_stringshare_del(cfdata->locals.cur);
539    cfdata->locals.cur = NULL;
540
541    if (!e_widget_ilist_count(cfdata->gui.o_binding_list))
542      {
543         _update_binding_context(cfdata);
544         _update_buttons(cfdata); 
545         
546         e_widget_ilist_unselect(cfdata->gui.o_action_list);
547         e_widget_entry_clear(cfdata->gui.o_params);
548         e_widget_disabled_set(cfdata->gui.o_params, 1);
549      }
550    else 
551      { 
552         if (e_widget_ilist_nth_is_header(cfdata->gui.o_binding_list, sel)) sel++;
553         e_widget_ilist_selected_set(cfdata->gui.o_binding_list, sel);
554         e_widget_ilist_nth_show(cfdata->gui.o_binding_list, sel, 0);
555      }
556 }
557
558 static void
559 _restore_mouse_binding_defaults_cb(void *data, void *data2 __UNUSED__)
560 {
561    E_Config_Binding_Mouse *eb;
562    E_Config_Binding_Wheel *bw;
563    E_Config_Dialog_Data *cfdata;
564
565    cfdata = data;
566
567    EINA_LIST_FREE(cfdata->binding.mouse, eb)
568      {
569         eina_stringshare_del(eb->action);
570         eina_stringshare_del(eb->params);
571         E_FREE(eb);
572      }
573
574    EINA_LIST_FREE(cfdata->binding.wheel, bw)
575      {
576         if (bw->action) eina_stringshare_del(bw->action);
577         if (bw->params) eina_stringshare_del(bw->params);
578         E_FREE(bw);
579      }
580 #define CFG_MOUSEBIND_DFLT(_context, _button, _modifiers, _anymod, _action, _params) \
581    eb = E_NEW(E_Config_Binding_Mouse, 1); \
582    eb->context = _context; \
583    eb->button = _button; \
584    eb->modifiers = _modifiers; \
585    eb->any_mod = _anymod; \
586    eb->action = _action == NULL ? NULL : eina_stringshare_add(_action); \
587    eb->params = _params == NULL ? NULL : eina_stringshare_add(_params); \
588    cfdata->binding.mouse = eina_list_append(cfdata->binding.mouse, eb) 
589    
590    CFG_MOUSEBIND_DFLT(E_BINDING_CONTEXT_BORDER, 1, E_BINDING_MODIFIER_ALT, 0, "window_move", NULL); 
591    CFG_MOUSEBIND_DFLT(E_BINDING_CONTEXT_BORDER, 2, E_BINDING_MODIFIER_ALT, 0, "window_resize", NULL); 
592    CFG_MOUSEBIND_DFLT(E_BINDING_CONTEXT_BORDER, 3, E_BINDING_MODIFIER_ALT, 0, "window_menu", NULL); 
593    CFG_MOUSEBIND_DFLT(E_BINDING_CONTEXT_ZONE, 1, 0, 0, "menu_show", "main"); 
594    CFG_MOUSEBIND_DFLT(E_BINDING_CONTEXT_ZONE, 2, 0, 0, "menu_show", "clients"); 
595    CFG_MOUSEBIND_DFLT(E_BINDING_CONTEXT_ZONE, 3, 0, 0, "menu_show", "favorites");
596
597 #define CFG_WHEELBIND_DFLT(_context, _direction, _z, _modifiers, _anymod, _action, _params) \
598    bw = E_NEW(E_Config_Binding_Wheel, 1); \
599    bw->context = _context; \
600    bw->direction = _direction; \
601    bw->z = _z; \
602    bw->modifiers = _modifiers; \
603    bw->any_mod = _anymod; \
604    bw->action = _action == NULL ? NULL : eina_stringshare_add(_action); \
605    bw->params = _params == NULL ? NULL : eina_stringshare_add(_params); \
606    cfdata->binding.wheel = eina_list_append(cfdata->binding.wheel, bw) 
607    
608    CFG_WHEELBIND_DFLT(E_BINDING_CONTEXT_CONTAINER, 0, -1, E_BINDING_MODIFIER_ALT, 0, 
609          "desk_linear_flip_by", "-1"); 
610    CFG_WHEELBIND_DFLT(E_BINDING_CONTEXT_CONTAINER, 1, -1, E_BINDING_MODIFIER_ALT, 0, 
611          "desk_linear_flip_by", "-1"); 
612    CFG_WHEELBIND_DFLT(E_BINDING_CONTEXT_CONTAINER, 0, 1, E_BINDING_MODIFIER_ALT, 0, 
613          "desk_linear_flip_by", "1"); 
614    CFG_WHEELBIND_DFLT(E_BINDING_CONTEXT_CONTAINER, 1, 1, E_BINDING_MODIFIER_ALT, 0, 
615          "desk_linear_flip_by", "1"); 
616    CFG_WHEELBIND_DFLT(E_BINDING_CONTEXT_BORDER, 0, -1, E_BINDING_MODIFIER_ALT, 0, 
617          "desk_linear_flip_by", "-1"); 
618    CFG_WHEELBIND_DFLT(E_BINDING_CONTEXT_BORDER, 1, -1, E_BINDING_MODIFIER_ALT, 0, 
619          "desk_linear_flip_by", "-1"); 
620    CFG_WHEELBIND_DFLT(E_BINDING_CONTEXT_BORDER, 0, 1, E_BINDING_MODIFIER_ALT, 0, 
621          "desk_linear_flip_by", "1"); 
622    CFG_WHEELBIND_DFLT(E_BINDING_CONTEXT_BORDER, 1, 1, E_BINDING_MODIFIER_ALT, 0, 
623          "desk_linear_flip_by", "1");
624
625    eina_stringshare_del(cfdata->locals.cur);
626    cfdata->locals.cur = NULL;
627
628    _update_mouse_binding_list(cfdata);
629    _update_buttons(cfdata);
630    _update_binding_context(cfdata);
631
632    e_widget_ilist_unselect(cfdata->gui.o_action_list);
633    e_widget_entry_clear(cfdata->gui.o_params);
634    e_widget_disabled_set(cfdata->gui.o_params, 1);
635 }
636
637 /******************* Updates *****************/
638 static void
639 _update_action_list(E_Config_Dialog_Data *cfdata)
640 {
641    E_Config_Binding_Mouse *eb;
642    E_Config_Binding_Wheel *bw;
643    const char *action, *params;
644    int j = -1, i, n;
645
646    if (!cfdata->locals.cur) return;
647
648    if (cfdata->locals.cur[0] == 'm')
649      {
650         sscanf(cfdata->locals.cur, "m%d", &n);
651         eb = eina_list_nth(cfdata->binding.mouse, n);
652         if (!eb)
653           {
654              e_widget_ilist_unselect(cfdata->gui.o_action_list);
655              e_widget_entry_clear(cfdata->gui.o_params);
656              e_widget_disabled_set(cfdata->gui.o_params, 1);
657              return;
658           }
659         action = eb->action;
660         params = eb->params;
661      }
662    else if (cfdata->locals.cur[0] == 'w')
663      {
664         sscanf(cfdata->locals.cur, "w%d", &n);
665         bw = eina_list_nth(cfdata->binding.wheel, n);
666         if (!bw)
667           {
668              e_widget_ilist_unselect(cfdata->gui.o_action_list);
669              e_widget_entry_clear(cfdata->gui.o_params);
670              e_widget_disabled_set(cfdata->gui.o_params, 1);
671              return;
672           }
673         action = bw->action;
674         params = bw->params;
675      }
676    else
677      return;
678
679    _find_key_binding_action(action, params, NULL, NULL, &j);
680    if (j >= 0)
681      {
682         for (i = 0; i < e_widget_ilist_count(cfdata->gui.o_action_list); i++)
683           {
684              if (i > j) break;
685              if (e_widget_ilist_nth_is_header(cfdata->gui.o_action_list, i)) j++;
686           }
687      }
688
689    if (j >= 0)
690      {
691         if (j == e_widget_ilist_selected_get(cfdata->gui.o_action_list))
692           _update_action_params(cfdata);
693         else
694           e_widget_ilist_selected_set(cfdata->gui.o_action_list, j);
695      }
696    else
697      {
698         e_widget_ilist_unselect(cfdata->gui.o_action_list);
699         eina_stringshare_del(cfdata->locals.action);
700         cfdata->locals.action = eina_stringshare_add("");
701         e_widget_entry_clear(cfdata->gui.o_params);
702      }
703 }
704
705 static void
706 _update_mouse_binding_list(E_Config_Dialog_Data *cfdata)
707 {
708    char *icon = NULL, *button, *mods;
709    char label[1024], val[10];
710    int i = 0;
711    Eina_List *l;
712    E_Config_Binding_Mouse *eb;
713    E_Config_Binding_Wheel *bw;
714
715    evas_event_freeze(evas_object_evas_get(cfdata->gui.o_binding_list));
716    edje_freeze();
717    e_widget_ilist_freeze(cfdata->gui.o_binding_list);
718    
719    e_widget_ilist_clear(cfdata->gui.o_binding_list);
720
721    if (cfdata->binding.mouse) 
722      { 
723         cfdata->binding.mouse = eina_list_sort(cfdata->binding.mouse, 
724               eina_list_count(cfdata->binding.mouse), _mouse_binding_sort_cb);
725         
726         e_widget_ilist_header_append(cfdata->gui.o_binding_list, NULL, "Mouse Buttons");
727      }
728
729    EINA_LIST_FOREACH(cfdata->binding.mouse, l, eb)
730      {
731         Evas_Object *ic;
732
733         button = _helper_button_name_get(eb);
734         mods = _helper_modifier_name_get(eb->modifiers);
735
736         if (mods && mods[0])
737           snprintf(label, sizeof(label), "%s + %s", button ? button : "", mods);
738         else
739           snprintf(label, sizeof(label), "%s", button ? button : "");
740         if (button) free(button);
741         if (mods) free(mods);
742
743         switch (eb->button)
744           {
745            case 1:
746               icon = "preferences-desktop-mouse-left";
747               break;
748            case 2:
749               icon = "preferences-desktop-mouse-middle";
750               break;
751            case 3:
752               icon = "preferences-desktop-mouse-right";
753               break;
754            default:
755               icon = "preferences-desktop-mouse-extra";
756           }
757
758         snprintf(val, sizeof(val), "m%d", i);
759
760         ic = e_icon_add(cfdata->evas);
761         e_util_icon_theme_set(ic, icon);
762         e_widget_ilist_append(cfdata->gui.o_binding_list, ic, label, _binding_change_cb,
763                               cfdata, val);
764
765         i++;
766      }
767
768    if (cfdata->binding.wheel) 
769      {
770         cfdata->binding.wheel = eina_list_sort(cfdata->binding.wheel, 
771               eina_list_count(cfdata->binding.wheel), _wheel_binding_sort_cb); 
772         
773         e_widget_ilist_header_append(cfdata->gui.o_binding_list, NULL, "Mouse Wheels");
774      }
775
776    i = 0;
777    EINA_LIST_FOREACH(cfdata->binding.wheel, l, bw)
778      {
779         Evas_Object *ic;
780
781         button = _helper_wheel_name_get(bw);
782         mods = _helper_modifier_name_get(bw->modifiers);
783
784         if (mods && mods[0])
785           snprintf(label, sizeof(label), "%s + %s", button ? button : "", mods);
786         else
787           snprintf(label, sizeof(label), "%s", button ? button : "");
788         if (button) free(button);
789         if (mods) free(mods);
790
791         snprintf(val, sizeof(val), "w%d", i);
792
793         ic = e_icon_add(cfdata->evas);
794         e_util_icon_theme_set(ic, "preferences-desktop-mouse-wheel");
795         e_widget_ilist_append(cfdata->gui.o_binding_list, ic, label, _binding_change_cb,
796                               cfdata, val);
797
798         i++;
799      }
800
801    e_widget_ilist_go(cfdata->gui.o_binding_list);
802    e_widget_ilist_thaw(cfdata->gui.o_binding_list);
803    edje_thaw();
804    evas_event_thaw(evas_object_evas_get(cfdata->gui.o_binding_list));
805
806    if (eina_list_count(cfdata->binding.mouse) + eina_list_count(cfdata->binding.wheel))
807      e_widget_disabled_set(cfdata->gui.o_del_all, 0);
808    else
809      e_widget_disabled_set(cfdata->gui.o_del_all, 1);
810 }
811
812 static void
813 _update_action_params(E_Config_Dialog_Data *cfdata)
814 {
815    int g, a, b;
816    E_Action_Group *actg;
817    E_Action_Description *actd;
818    E_Config_Binding_Mouse *eb;
819    E_Config_Binding_Wheel *bw;
820    const char *action, *params;
821
822 #define MB_EXAMPLE_PARAMS \
823    if ((!actd->param_example) || (!actd->param_example[0])) \
824      e_widget_entry_text_set(cfdata->gui.o_params, TEXT_NO_PARAMS); \
825    else \
826      e_widget_entry_text_set(cfdata->gui.o_params, actd->param_example)
827
828    if ((!cfdata->locals.action) || (!cfdata->locals.action[0]))
829      {
830         e_widget_disabled_set(cfdata->gui.o_params, 1);
831         e_widget_entry_clear(cfdata->gui.o_params);
832      }
833    sscanf(cfdata->locals.action, "%d %d", &g, &a);
834
835    actg = eina_list_nth(e_action_groups_get(), g);
836    if (!actg) return;
837    actd = eina_list_nth(actg->acts, a);
838    if (!actd) return;
839
840    if (actd->act_params)
841      {
842         e_widget_disabled_set(cfdata->gui.o_params, 1);
843         e_widget_entry_text_set(cfdata->gui.o_params, actd->act_params);
844         return;
845      }
846
847    if ((!cfdata->locals.cur) || (!cfdata->locals.cur[0]))
848      {
849         e_widget_disabled_set(cfdata->gui.o_params, 1);
850         MB_EXAMPLE_PARAMS;
851         return;
852      }
853
854    if (!actd->editable)
855      e_widget_disabled_set(cfdata->gui.o_params, 1);
856    else
857      e_widget_disabled_set(cfdata->gui.o_params, 0);
858
859    if (cfdata->locals.cur[0] == 'm')
860      {
861         sscanf(cfdata->locals.cur, "m%d", &b);
862         eb = eina_list_nth(cfdata->binding.mouse, b);
863         if (!eb)
864           {
865              e_widget_disabled_set(cfdata->gui.o_params, 1);
866              MB_EXAMPLE_PARAMS;
867              return;
868           }
869         action = eb->action;
870         params = eb->params;
871      }
872    else if (cfdata->locals.cur[0] == 'w')
873      {
874         sscanf(cfdata->locals.cur, "w%d", &b);
875         bw = eina_list_nth(cfdata->binding.wheel, b);
876         if (!bw)
877           {
878              e_widget_disabled_set(cfdata->gui.o_params, 1);
879              MB_EXAMPLE_PARAMS;
880              return;
881           }
882         action = bw->action;
883         params = bw->params;
884      }
885    else
886      { 
887         e_widget_disabled_set(cfdata->gui.o_params, 1);
888         MB_EXAMPLE_PARAMS;
889         return;
890      }
891
892    if (action)
893      {
894         if (!strcmp(action, actd->act_cmd))
895           {
896              if ((!params) || (!params[0]))
897                MB_EXAMPLE_PARAMS;
898              else
899                e_widget_entry_text_set(cfdata->gui.o_params, params);
900           }
901         else
902           MB_EXAMPLE_PARAMS;
903      }
904    else
905      MB_EXAMPLE_PARAMS;
906 }
907
908 static void
909 _update_buttons(E_Config_Dialog_Data *cfdata)
910 {
911    if (e_widget_ilist_count(cfdata->gui.o_binding_list))
912      e_widget_disabled_set(cfdata->gui.o_del_all, 0);
913    else
914      e_widget_disabled_set(cfdata->gui.o_del_all, 1);
915
916    if (!cfdata->locals.cur)
917      { 
918         e_widget_disabled_set(cfdata->gui.o_mod, 1); 
919         e_widget_disabled_set(cfdata->gui.o_del, 1);
920         return;
921      }
922
923    e_widget_disabled_set(cfdata->gui.o_mod, 0);
924    e_widget_disabled_set(cfdata->gui.o_del, 0);
925 }
926
927 static void
928 _update_binding_context(E_Config_Dialog_Data *cfdata)
929 {
930    int n;
931    E_Config_Binding_Mouse *eb;
932    E_Config_Binding_Wheel *bw;
933    E_Binding_Context ctxt;
934
935    /* disable all the radios. */
936    e_widget_radio_toggle_set(cfdata->gui.context.o_any, 1);
937    e_widget_disabled_set(cfdata->gui.context.o_any, 1);
938    e_widget_disabled_set(cfdata->gui.context.o_border, 1);
939    e_widget_disabled_set(cfdata->gui.context.o_menu, 1);
940    e_widget_disabled_set(cfdata->gui.context.o_winlist, 1);
941    e_widget_disabled_set(cfdata->gui.context.o_popup, 1);
942    e_widget_disabled_set(cfdata->gui.context.o_zone, 1);
943    e_widget_disabled_set(cfdata->gui.context.o_container, 1);
944    e_widget_disabled_set(cfdata->gui.context.o_manager, 1);
945    e_widget_disabled_set(cfdata->gui.context.o_none, 1);
946
947    if (!cfdata->locals.cur) return;
948
949    if (cfdata->locals.cur[0] == 'm')
950      {
951         sscanf(cfdata->locals.cur, "m%d", &n);
952         eb = eina_list_nth(cfdata->binding.mouse, n);
953         if (!eb) return;
954         ctxt = eb->context;
955      }
956    else if (cfdata->locals.cur[0] == 'w')
957      {
958         sscanf(cfdata->locals.cur, "w%d", &n);
959         bw = eina_list_nth(cfdata->binding.wheel, n);
960         if (!bw) return;
961         ctxt = bw->context;
962      }
963    else
964      return;
965
966    e_widget_disabled_set(cfdata->gui.context.o_any, 0);
967    e_widget_disabled_set(cfdata->gui.context.o_border, 0);
968    e_widget_disabled_set(cfdata->gui.context.o_menu, 0);
969    e_widget_disabled_set(cfdata->gui.context.o_winlist, 0);
970    e_widget_disabled_set(cfdata->gui.context.o_popup, 0);
971    e_widget_disabled_set(cfdata->gui.context.o_zone, 0);
972    e_widget_disabled_set(cfdata->gui.context.o_container, 0);
973    e_widget_disabled_set(cfdata->gui.context.o_manager, 0);
974    e_widget_disabled_set(cfdata->gui.context.o_none, 0);
975
976    if (ctxt == E_BINDING_CONTEXT_ANY) 
977      e_widget_radio_toggle_set(cfdata->gui.context.o_any, 1);
978    else if (ctxt == E_BINDING_CONTEXT_BORDER)
979      e_widget_radio_toggle_set(cfdata->gui.context.o_border, 1);
980    else if (ctxt == E_BINDING_CONTEXT_MENU)
981      e_widget_radio_toggle_set(cfdata->gui.context.o_menu, 1);
982    else if (ctxt == E_BINDING_CONTEXT_WINLIST)
983      e_widget_radio_toggle_set(cfdata->gui.context.o_winlist, 1);
984    else if (ctxt == E_BINDING_CONTEXT_POPUP)
985      e_widget_radio_toggle_set(cfdata->gui.context.o_popup, 1);
986    else if (ctxt == E_BINDING_CONTEXT_ZONE)
987      e_widget_radio_toggle_set(cfdata->gui.context.o_zone, 1);
988    else if (ctxt == E_BINDING_CONTEXT_CONTAINER)
989      e_widget_radio_toggle_set(cfdata->gui.context.o_container, 1);
990    else if (ctxt == E_BINDING_CONTEXT_MANAGER)
991      e_widget_radio_toggle_set(cfdata->gui.context.o_manager, 1);
992    else if (ctxt == E_BINDING_CONTEXT_NONE)
993      e_widget_radio_toggle_set(cfdata->gui.context.o_none, 1);
994 }
995
996 /****************** Helper *****************/
997 static void
998 _auto_apply_changes(E_Config_Dialog_Data *cfdata)
999 {
1000    int n, g, a;
1001    E_Config_Binding_Mouse *eb = NULL;
1002    E_Config_Binding_Wheel *bw = NULL;
1003
1004    E_Action_Group *actg;
1005    E_Action_Description *actd;
1006    const char **action = NULL, **params = NULL;
1007
1008    if ((!cfdata->locals.cur) || (!cfdata->locals.cur[0])) return;
1009
1010    if (cfdata->locals.cur[0] == 'm')
1011      {
1012         sscanf(cfdata->locals.cur, "m%d", &n);
1013         eb = eina_list_nth(cfdata->binding.mouse, n);
1014         if (!eb) return;
1015
1016         eb->context = cfdata->locals.context;
1017         action = &(eb->action);
1018         params = &(eb->params);
1019      }
1020    else if (cfdata->locals.cur[0] == 'w')
1021      {
1022         sscanf(cfdata->locals.cur, "w%d", &n);
1023         bw = eina_list_nth(cfdata->binding.wheel, n);
1024         if (!bw) return;
1025
1026         bw->context = cfdata->locals.context;
1027         action = &(bw->action);
1028         params = &(bw->params);
1029      } 
1030    else return;
1031    
1032    if (action && *action) eina_stringshare_del(*action); 
1033    if (params && *params) eina_stringshare_del(*params); 
1034    if (action) *action = NULL; 
1035    if (params) *params = NULL;
1036
1037    if ((!cfdata->locals.action) || (!cfdata->locals.action[0])) return;
1038
1039    sscanf(cfdata->locals.action, "%d %d", &g, &a);
1040
1041    actg = eina_list_nth(e_action_groups_get(), g);
1042    if (!actg) return;
1043    actd = eina_list_nth(actg->acts, a);
1044    if (!actd) return;
1045
1046    if (actd->act_cmd) *action = eina_stringshare_add(actd->act_cmd);
1047    if (actd->act_params) 
1048      *params = eina_stringshare_add(actd->act_params);
1049    else
1050      {
1051         int ok = 1;
1052         if (cfdata->locals.params)
1053           {
1054              if (!strcmp(cfdata->locals.params, TEXT_NO_PARAMS)) ok = 0;
1055
1056              if ((actd->param_example) && (!strcmp(cfdata->locals.params, actd->param_example)))
1057                ok = 0;
1058           }
1059         else
1060           ok = 0;
1061
1062         if (ok)
1063           *params = eina_stringshare_add(cfdata->locals.params);
1064      }
1065 }
1066
1067 static void
1068 _find_key_binding_action(const char *action, const char *params, int *g, int *a, int *n)
1069 {
1070    Eina_List *l, *l2;
1071    int gg = -1, aa = -1, nn = -1, found;
1072    E_Action_Group *actg;
1073    E_Action_Description *actd;
1074
1075    if (g) *g = -1;
1076    if (a) *a = -1;
1077    if (n) *n = -1;
1078
1079    found = 0;
1080    for (l = e_action_groups_get(), gg = 0, nn = 0; l; l = l->next, gg++)
1081      {
1082         actg = l->data;
1083
1084         for (l2 = actg->acts, aa = 0; l2; l2 = l2->next, aa++)
1085           {
1086              actd = l2->data;
1087
1088              if (!strcmp((!action ? "" : action), (!actd->act_cmd ? "" : actd->act_cmd)))
1089                {
1090                   if (!params || !params[0])
1091                     {
1092                        if ((!actd->act_params) || (!actd->act_params[0]))
1093                          {
1094                             if (g) *g = gg;
1095                             if (a) *a = aa;
1096                             if (n) *n = nn;
1097                             return;
1098                          }
1099                        else
1100                          continue;
1101                     }
1102                   else
1103                     {
1104                        if ((!actd->act_params) || (!actd->act_params[0]))
1105                          {
1106                             if (g) *g = gg;
1107                             if (a) *a = aa;
1108                             if (n) *n = nn;
1109                             found = 1;
1110                          }
1111                        else
1112                          {
1113                             if (!strcmp(params, actd->act_params))
1114                               {
1115                                  if (g) *g = gg;
1116                                  if (a) *a = aa;
1117                                  if (n) *n = nn;
1118                                  return;
1119                               }
1120                          }
1121                     }
1122                }
1123              nn++;
1124           }
1125         if (found) break;
1126      }
1127
1128    if (!found)
1129      {
1130         if (g) *g = -1;
1131         if (a) *a = -1;
1132         if (n) *n = -1;
1133      }
1134 }
1135
1136 static char *
1137 _helper_button_name_get(E_Config_Binding_Mouse *eb)
1138 {
1139    char *name = NULL;
1140    char buf[1024]="";
1141
1142    switch (eb->button)
1143      { 
1144       case 1:
1145          name = strdup("Left Button");
1146          break;
1147       case 2:
1148          name = strdup("Middle Button");
1149          break;
1150       case 3: 
1151          name = strdup("Right Button");
1152          break;
1153       case 4:
1154       case 5:
1155       case 6:
1156       case 7:
1157          break;
1158       default:
1159          snprintf(buf, sizeof(buf), "Extra Button (%d)", eb->button);
1160          name = strdup(buf);
1161      }
1162    return name;
1163 }
1164
1165 static char *
1166 _helper_wheel_name_get(E_Config_Binding_Wheel *bw)
1167 {
1168    char *name = NULL;
1169    char buf[1024] = "";
1170
1171    switch (bw->direction)
1172      {
1173       case 0:
1174          if (bw->z >= 0) 
1175            name = strdup("Mouse Wheel Up");
1176          else
1177            name = strdup("Mouse Wheel Down");
1178          break;
1179       default:
1180          if (bw->z >= 0) 
1181            snprintf(buf, sizeof(buf), "Extra Wheel (%d) Up", bw->direction);
1182          else
1183            snprintf(buf, sizeof(buf), "Extra Wheel (%d) Down", bw->direction);
1184          name = strdup(buf);
1185      }
1186    return name;
1187 }
1188
1189 static char *
1190 _helper_modifier_name_get(int mod)
1191 {
1192    char mods[1024] = "";
1193
1194    if (mod & E_BINDING_MODIFIER_SHIFT)
1195      snprintf(mods, sizeof(mods), "SHIFT");
1196
1197    if (mod & E_BINDING_MODIFIER_CTRL)
1198      {
1199         if (mods[0]) strcat(mods, " + ");
1200         strcat(mods, "CTRL");
1201      }
1202
1203    if (mod & E_BINDING_MODIFIER_ALT)
1204      {
1205         if (mods[0]) strcat(mods, " + ");
1206         strcat(mods, "ALT");
1207      }
1208
1209    if (mod & E_BINDING_MODIFIER_WIN)
1210      {
1211         if (mods[0]) strcat(mods, " + ");
1212         strcat(mods, "WIN");
1213      }
1214
1215    return strdup(mods);
1216 }
1217
1218 /********* Sorting ***************/
1219 static int
1220 _mouse_binding_sort_cb(const void *d1, const void *d2)
1221 {
1222    const E_Config_Binding_Mouse *eb, *eb2;
1223
1224    eb = d1;
1225    eb2 = d2;
1226
1227    if (eb->button < eb2->button) return -1;
1228    else if (eb->button > eb2->button) return 1;
1229    else
1230      {
1231         if (eb->modifiers < eb2->modifiers) return -1;
1232         else if (eb->modifiers > eb2->modifiers) return 1;
1233      }
1234    return 0;
1235 }
1236
1237 static int
1238 _wheel_binding_sort_cb(const void *d1, const void *d2)
1239 {
1240    const E_Config_Binding_Wheel *bw, *bw2;
1241
1242    bw = d1;
1243    bw2 = d2;
1244
1245    if (bw->direction < bw2->direction) return -1;
1246    else if (bw->direction > bw2->direction) return 1;
1247    else
1248      {
1249         if ((bw->z < 0) && (bw2->z > 0)) return 1;
1250         else if ((bw->z > 0) && (bw2->z < 0)) return -1;
1251         else if (((bw->z < 0) && (bw2->z < 0)) ||
1252                  ((bw->z > 0) && (bw2->z > 0)))
1253           {
1254              if (bw->modifiers < bw2->modifiers) return -1;
1255              else if (bw->modifiers > bw2->modifiers) return 1;
1256           }
1257      }
1258    return 0;
1259 }
1260
1261 static void
1262 _grab_wnd_show(E_Config_Dialog_Data *cfdata)
1263 {
1264    E_Manager *man;
1265
1266    if (cfdata->locals.bind_win != 0) return;
1267
1268    man = e_manager_current_get();
1269
1270    cfdata->locals.dia = e_dialog_new(e_container_current_get(man), 
1271                                      "E", "_mousebind_getmouse_dialog");
1272    if (!cfdata->locals.dia) return;
1273    e_dialog_title_set(cfdata->locals.dia, _("Mouse Binding Sequence"));
1274    e_dialog_icon_set(cfdata->locals.dia, "preferences-desktop-mouse", 48);
1275    e_dialog_text_set(cfdata->locals.dia, TEXT_PRESS_MOUSE_BINIDING_SEQUENCE);
1276    e_win_centered_set(cfdata->locals.dia->win, 1);
1277    e_win_borderless_set(cfdata->locals.dia->win, 1);
1278
1279    cfdata->locals.bind_win = ecore_x_window_input_new(man->root, 0, 0,
1280                                                       man->w, man->h);
1281    ecore_x_window_show(cfdata->locals.bind_win);
1282    e_grabinput_get(cfdata->locals.bind_win, 0, cfdata->locals.bind_win);
1283
1284    cfdata->locals.handlers = eina_list_append(cfdata->locals.handlers,
1285                               ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
1286                                  _grab_key_down_cb, cfdata));
1287
1288    cfdata->locals.handlers = eina_list_append(cfdata->locals.handlers,
1289                               ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
1290                                  _grab_mouse_down_cb, cfdata));
1291
1292    cfdata->locals.handlers = eina_list_append(cfdata->locals.handlers,
1293                               ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
1294                                  _grab_mouse_wheel_cb, cfdata));
1295
1296    e_dialog_show(cfdata->locals.dia);
1297    ecore_x_icccm_transient_for_set(cfdata->locals.dia->win->evas_win, cfdata->cfd->dia->win->evas_win);
1298 }
1299
1300 static void
1301 _grab_wnd_hide(E_Config_Dialog_Data *cfdata)
1302 {
1303    while (cfdata->locals.handlers)
1304      {
1305         ecore_event_handler_del(cfdata->locals.handlers->data);
1306         cfdata->locals.handlers = 
1307            eina_list_remove_list(cfdata->locals.handlers, cfdata->locals.handlers);
1308      }
1309    cfdata->locals.handlers = NULL;
1310    e_grabinput_release(cfdata->locals.bind_win, cfdata->locals.bind_win);
1311    ecore_x_window_free(cfdata->locals.bind_win);
1312    cfdata->locals.bind_win = 0;
1313
1314    e_object_del(E_OBJECT(cfdata->locals.dia));
1315    cfdata->locals.dia = NULL;
1316 }
1317
1318 static Eina_Bool
1319 _grab_mouse_down_cb(void *data, __UNUSED__ int type, void *event)
1320 {
1321    Eina_List *l;
1322    E_Config_Dialog_Data *cfdata;
1323    E_Config_Binding_Mouse *eb = NULL;
1324    E_Config_Binding_Wheel *bw;
1325    int mod = E_BINDING_MODIFIER_NONE, n;
1326
1327    Ecore_Event_Mouse_Button *ev;
1328    
1329    ev = event;
1330    cfdata = data;
1331
1332    if (ev->window != cfdata->locals.bind_win) return ECORE_CALLBACK_PASS_ON;
1333
1334    if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
1335      mod |= E_BINDING_MODIFIER_SHIFT;
1336    if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
1337      mod |= E_BINDING_MODIFIER_CTRL;
1338    if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
1339      mod |= E_BINDING_MODIFIER_ALT;
1340    if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
1341      mod |= E_BINDING_MODIFIER_WIN; 
1342       
1343    if (cfdata->locals.add) 
1344      { 
1345         eb = E_NEW(E_Config_Binding_Mouse, 1); 
1346         eb->context = E_BINDING_CONTEXT_ANY; 
1347         eb->button = ev->buttons; 
1348         eb->modifiers = mod; 
1349         eb->any_mod = 0; 
1350         eb->action = NULL; 
1351         eb->params = NULL; 
1352         
1353         cfdata->binding.mouse = eina_list_append(cfdata->binding.mouse, eb);
1354      }
1355    else
1356      {
1357         if (cfdata->locals.cur[0] == 'm')
1358           { 
1359              sscanf(cfdata->locals.cur, "m%d", &n); 
1360              eb = eina_list_nth(cfdata->binding.mouse, n); 
1361              if (eb) 
1362                { 
1363                   eb->button = ev->buttons; 
1364                   eb->modifiers = mod; 
1365                }
1366           }
1367         else if (cfdata->locals.cur[0] == 'w')
1368           {
1369              sscanf(cfdata->locals.cur, "w%d", &n);
1370              l = eina_list_nth_list(cfdata->binding.wheel, n);
1371              bw = eina_list_data_get(l);
1372
1373              eb = E_NEW(E_Config_Binding_Mouse, 1); 
1374              eb->context = bw->context;
1375              eb->button = ev->buttons; 
1376              eb->modifiers = mod; 
1377              eb->any_mod = 0; 
1378              eb->action = bw->action; 
1379              eb->params = bw->params; 
1380
1381              cfdata->binding.mouse = eina_list_append(cfdata->binding.mouse, eb);
1382
1383              bw->action = NULL;
1384              bw->params = NULL;
1385              E_FREE(bw);
1386              cfdata->binding.wheel = eina_list_remove_list(cfdata->binding.wheel, l);
1387           }
1388      } 
1389    _update_mouse_binding_list(cfdata); 
1390
1391    if (cfdata->locals.add)
1392      { 
1393         for (l = cfdata->binding.mouse, n = 0; l; l = l->next, n++)
1394           if (l->data == eb) break;
1395
1396         e_widget_ilist_selected_set(cfdata->gui.o_binding_list, n + 1); 
1397
1398         eina_stringshare_del(cfdata->locals.action);
1399         cfdata->locals.action = eina_stringshare_add("");
1400         e_widget_ilist_unselect(cfdata->gui.o_action_list);
1401         e_widget_entry_clear(cfdata->gui.o_params);
1402         e_widget_disabled_set(cfdata->gui.o_params, 1);
1403      }
1404    else
1405      { 
1406         for (l = cfdata->binding.mouse, n = 0; l; l = l->next, n++) 
1407           if (l->data == eb) break; 
1408
1409         eina_stringshare_del(cfdata->locals.cur);
1410         cfdata->locals.cur = NULL;
1411
1412         e_widget_ilist_selected_set(cfdata->gui.o_binding_list, n + 1);
1413      }
1414    _update_buttons(cfdata);
1415    _grab_wnd_hide(cfdata);
1416
1417    return ECORE_CALLBACK_PASS_ON;
1418 }
1419
1420 static Eina_Bool
1421 _grab_mouse_wheel_cb(void *data, __UNUSED__ int type, void *event)
1422 {
1423    Eina_List *l;
1424    E_Config_Binding_Wheel *bw = NULL;
1425    E_Config_Binding_Mouse *eb = NULL;
1426    E_Config_Dialog_Data *cfdata;
1427    Ecore_Event_Mouse_Wheel *ev; 
1428    int mod = E_BINDING_MODIFIER_NONE, n;
1429
1430    ev = event;
1431    cfdata = data;
1432
1433    if (ev->window != cfdata->locals.bind_win) return ECORE_CALLBACK_PASS_ON;
1434
1435    if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
1436      mod |= E_BINDING_MODIFIER_SHIFT;
1437    if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
1438      mod |= E_BINDING_MODIFIER_CTRL;
1439    if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
1440      mod |= E_BINDING_MODIFIER_ALT;
1441    if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
1442      mod |= E_BINDING_MODIFIER_WIN; 
1443    
1444    
1445    if (cfdata->locals.add)
1446      {
1447         bw = E_NEW(E_Config_Binding_Wheel, 1);
1448         bw->context = E_BINDING_CONTEXT_ANY;
1449         bw->direction = ev->direction;
1450         bw->z = ev->z;
1451         bw->modifiers = mod;
1452         bw->any_mod = 0;
1453         bw->action = NULL;
1454         bw->params = NULL; 
1455         
1456         cfdata->binding.wheel = eina_list_append(cfdata->binding.wheel, bw);
1457      }
1458    else 
1459      {
1460         if (cfdata->locals.cur[0] == 'm')
1461           {
1462              sscanf(cfdata->locals.cur, "m%d", &n);
1463              l = eina_list_nth_list(cfdata->binding.mouse, n);
1464              eb = eina_list_data_get(l);
1465              
1466              bw = E_NEW(E_Config_Binding_Wheel, 1);
1467              bw->context = eb->context;
1468              bw->direction = ev->direction;
1469              bw->z = ev->z;
1470              bw->modifiers = mod;
1471              bw->any_mod = 0;
1472              bw->action = eb->action;
1473              bw->params = eb->params; 
1474
1475              cfdata->binding.wheel = eina_list_append(cfdata->binding.wheel, bw);
1476
1477              E_FREE(eb);
1478              cfdata->binding.mouse = eina_list_remove_list(cfdata->binding.mouse, l);
1479           }
1480         else if (cfdata->locals.cur[0] == 'w')
1481           {
1482              sscanf(cfdata->locals.cur, "w%d", &n);
1483              bw = eina_list_nth(cfdata->binding.wheel, n);
1484              if (bw)
1485                {
1486                   bw->direction = ev->direction;
1487                   bw->z = ev->z;
1488                   bw->modifiers = mod;
1489                }
1490           }
1491      } 
1492    _update_mouse_binding_list(cfdata); 
1493
1494    if (cfdata->locals.add)
1495      { 
1496         for (l = cfdata->binding.wheel, n = 0; l; l = l->next, n++)
1497           if (l->data == bw) break;
1498
1499         if (eina_list_count(cfdata->binding.mouse))
1500           { 
1501              n += eina_list_count(cfdata->binding.mouse) + 2;
1502              e_widget_ilist_selected_set(cfdata->gui.o_binding_list, n); 
1503           }
1504         else 
1505           e_widget_ilist_selected_set(cfdata->gui.o_binding_list, n + 1); 
1506
1507         e_widget_ilist_unselect(cfdata->gui.o_action_list);
1508         eina_stringshare_del(cfdata->locals.action);
1509         cfdata->locals.action = eina_stringshare_add("");
1510         e_widget_entry_clear(cfdata->gui.o_params);
1511         e_widget_disabled_set(cfdata->gui.o_params, 1);
1512      }
1513    else
1514      {
1515         for (l = cfdata->binding.wheel, n = 0; l; l = l->next, n++)
1516           if (l->data == bw) break;
1517
1518         eina_stringshare_del(cfdata->locals.cur);
1519         cfdata->locals.cur = NULL;
1520
1521         if (eina_list_count(cfdata->binding.mouse)) 
1522           { 
1523              n += eina_list_count(cfdata->binding.mouse) + 2;
1524              e_widget_ilist_selected_set(cfdata->gui.o_binding_list, n);
1525           }
1526         else
1527           e_widget_ilist_selected_set(cfdata->gui.o_binding_list, n + 1);
1528      }
1529    _update_buttons(cfdata);
1530
1531    _grab_wnd_hide(cfdata);
1532    return ECORE_CALLBACK_PASS_ON;
1533 }
1534
1535 static Eina_Bool
1536 _grab_key_down_cb(void *data, __UNUSED__ int type, void *event)
1537 {
1538    E_Config_Dialog_Data *cfdata;
1539    Ecore_Event_Key *ev = event;
1540
1541    cfdata = data;
1542
1543    if (ev->window != cfdata->locals.bind_win) return ECORE_CALLBACK_PASS_ON;
1544
1545    if (!strcmp(ev->keyname, "Escape") &&
1546        !(ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) &&
1547        !(ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
1548        !(ev->modifiers & ECORE_EVENT_MODIFIER_ALT) &&
1549        !(ev->modifiers & ECORE_EVENT_MODIFIER_WIN))
1550      { 
1551         _grab_wnd_hide(cfdata);
1552      }
1553    return ECORE_CALLBACK_PASS_ON;
1554 }