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