create rotation job and EAPI e_border_rotation_set
[platform/core/uifw/e17.git] / src / bin / e_bindings.c
1 #include "e.h"
2
3 /* local subsystem functions */
4 static Eina_Bool _e_bindings_mapping_change_event_cb(void *data, int type, void *event);
5
6 static void _e_bindings_mouse_free(E_Binding_Mouse *bind);
7 static void _e_bindings_key_free(E_Binding_Key *bind);
8 static void _e_bindings_edge_free(E_Binding_Edge *bind);
9 static void _e_bindings_signal_free(E_Binding_Signal *bind);
10 static void _e_bindings_wheel_free(E_Binding_Wheel *bind);
11 static void _e_bindings_acpi_free(E_Binding_Acpi *bind);
12 static int _e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt);
13 static E_Binding_Modifier _e_bindings_modifiers(unsigned int modifiers);
14 static int _e_ecore_modifiers(E_Binding_Modifier modifiers);
15 static Eina_Bool _e_bindings_edge_cb_timer(void *data);
16
17 /* local subsystem globals */
18
19 static Ecore_Event_Handler *mapping_handler = NULL;
20
21 static Eina_List *mouse_bindings = NULL;
22 static Eina_List *key_bindings = NULL;
23 static Eina_List *edge_bindings = NULL;
24 static Eina_List *signal_bindings = NULL;
25 static Eina_List *wheel_bindings = NULL;
26 static Eina_List *acpi_bindings = NULL;
27 static int _e_bindings_mapping_change_enabled = 1;
28
29 typedef struct _E_Binding_Edge_Data E_Binding_Edge_Data;
30
31 struct _E_Binding_Edge_Data
32 {
33    E_Binding_Edge    *bind;
34    E_Event_Zone_Edge *ev;
35    E_Action          *act;
36    E_Object          *obj;
37 };
38
39 /* externally accessible functions */
40
41 EINTERN int
42 e_bindings_init(void)
43 {
44    E_Config_Binding_Signal *ebs;
45    E_Config_Binding_Mouse *ebm;
46    E_Config_Binding_Wheel *ebw;
47    E_Config_Binding_Edge *ebe;
48    E_Config_Binding_Key *ebk;
49    E_Config_Binding_Acpi *eba;
50    Eina_List *l;
51
52    mapping_handler = ecore_event_handler_add
53       (ECORE_X_EVENT_MAPPING_CHANGE, _e_bindings_mapping_change_event_cb, NULL);
54
55    EINA_LIST_FOREACH(e_config->mouse_bindings, l, ebm)
56      e_bindings_mouse_add(ebm->context, ebm->button, ebm->modifiers,
57                           ebm->any_mod, ebm->action, ebm->params);
58
59    EINA_LIST_FOREACH(e_config->key_bindings, l, ebk)
60      e_bindings_key_add(ebk->context, ebk->key, ebk->modifiers,
61                         ebk->any_mod, ebk->action, ebk->params);
62
63    EINA_LIST_FOREACH(e_config->edge_bindings, l, ebe)
64      e_bindings_edge_add(ebe->context, ebe->edge, ebe->modifiers,
65                          ebe->any_mod, ebe->action, ebe->params, ebe->delay);
66
67    EINA_LIST_FOREACH(e_config->signal_bindings, l, ebs)
68      {
69         e_bindings_signal_add(ebs->context, ebs->signal, ebs->source, ebs->modifiers,
70                               ebs->any_mod, ebs->action, ebs->params);
71         /* FIXME: Can this be solved in a generic way? */
72         /* FIXME: Only change cursor if action is allowed! */
73         if ((ebs->action) && (ebs->signal) && (ebs->source) &&
74             (!strcmp(ebs->action, "window_resize")) &&
75             (!strncmp(ebs->signal, "mouse,down,", 11)) &&
76             (!strncmp(ebs->source, "e.event.resize.", 15)))
77           {
78              char params[32];
79
80              snprintf(params, sizeof(params), "resize_%s", ebs->params);
81              e_bindings_signal_add(ebs->context, "mouse,in", ebs->source, ebs->modifiers,
82                                    ebs->any_mod, "pointer_resize_push", params);
83              e_bindings_signal_add(ebs->context, "mouse,out", ebs->source, ebs->modifiers,
84                                    ebs->any_mod, "pointer_resize_pop", params);
85           }
86      }
87
88    EINA_LIST_FOREACH(e_config->wheel_bindings, l, ebw)
89      e_bindings_wheel_add(ebw->context, ebw->direction, ebw->z, ebw->modifiers,
90                           ebw->any_mod, ebw->action, ebw->params);
91
92    EINA_LIST_FOREACH(e_config->acpi_bindings, l, eba)
93      e_bindings_acpi_add(eba->context, eba->type, eba->status,
94                          eba->action, eba->params);
95
96    return 1;
97 }
98
99 EINTERN int
100 e_bindings_shutdown(void)
101 {
102    E_FREE_LIST(mouse_bindings, _e_bindings_mouse_free);
103    E_FREE_LIST(key_bindings, _e_bindings_key_free);
104    E_FREE_LIST(edge_bindings, _e_bindings_edge_free);
105    E_FREE_LIST(signal_bindings, _e_bindings_signal_free);
106    E_FREE_LIST(wheel_bindings, _e_bindings_wheel_free);
107    E_FREE_LIST(acpi_bindings, _e_bindings_acpi_free);
108
109    if (mapping_handler)
110       {
111          ecore_event_handler_del(mapping_handler);
112          mapping_handler = NULL;
113       }
114
115    return 1;
116 }
117
118 EAPI void
119 e_bindings_signal_reset(void)
120 {
121    E_Config_Binding_Signal *ebs;
122    Eina_List *l;
123    E_FREE_LIST(signal_bindings, _e_bindings_signal_free);
124
125    EINA_LIST_FOREACH(e_config->signal_bindings, l, ebs)
126      {
127         e_bindings_signal_add(ebs->context, ebs->signal, ebs->source, ebs->modifiers,
128                               ebs->any_mod, ebs->action, ebs->params);
129         /* FIXME: Can this be solved in a generic way? */
130         /* FIXME: Only change cursor if action is allowed! */
131         if ((ebs->action) && (ebs->signal) && (ebs->source) &&
132             (!strcmp(ebs->action, "window_resize")) &&
133             (!strncmp(ebs->signal, "mouse,down,", 11)) &&
134             (!strncmp(ebs->source, "e.event.resize.", 15)))
135           {
136              char params[32];
137
138              snprintf(params, sizeof(params), "resize_%s", ebs->params);
139              e_bindings_signal_add(ebs->context, "mouse,in", ebs->source, ebs->modifiers,
140                                    ebs->any_mod, "pointer_resize_push", params);
141              e_bindings_signal_add(ebs->context, "mouse,out", ebs->source, ebs->modifiers,
142                                    ebs->any_mod, "pointer_resize_pop", params);
143           }
144      }
145 }
146
147 EAPI void
148 e_bindings_acpi_reset(void)
149 {
150    E_Config_Binding_Acpi *eba;
151    Eina_List *l;
152
153    E_FREE_LIST(acpi_bindings, _e_bindings_acpi_free);
154
155    EINA_LIST_FOREACH(e_config->acpi_bindings, l, eba)
156      e_bindings_acpi_add(eba->context, eba->type, eba->status,
157                          eba->action, eba->params);
158 }
159
160 EAPI void
161 e_bindings_wheel_reset(void)
162 {
163    E_Config_Binding_Wheel *ebw;
164    Eina_List *l;
165
166    E_FREE_LIST(wheel_bindings, _e_bindings_wheel_free);
167
168    EINA_LIST_FOREACH(e_config->wheel_bindings, l, ebw)
169      e_bindings_wheel_add(ebw->context, ebw->direction, ebw->z, ebw->modifiers,
170                           ebw->any_mod, ebw->action, ebw->params);
171 }
172
173 EAPI void
174 e_bindings_edge_reset(void)
175 {
176    E_Config_Binding_Edge *ebe;
177    Eina_List *l;
178    
179    E_FREE_LIST(edge_bindings, _e_bindings_edge_free);
180    
181    EINA_LIST_FOREACH(e_config->edge_bindings, l, ebe)
182      e_bindings_edge_add(ebe->context, ebe->edge, ebe->modifiers,
183                          ebe->any_mod, ebe->action, ebe->params, ebe->delay);
184 }
185
186 EAPI void
187 e_bindings_mouse_reset(void)
188 {
189    E_Config_Binding_Mouse *ebm;
190    Eina_List *l;
191
192    E_FREE_LIST(mouse_bindings, _e_bindings_mouse_free);
193
194    EINA_LIST_FOREACH(e_config->mouse_bindings, l, ebm)
195      e_bindings_mouse_add(ebm->context, ebm->button, ebm->modifiers,
196                           ebm->any_mod, ebm->action, ebm->params);
197
198 }
199
200 EAPI void
201 e_bindings_key_reset(void)
202 {
203    E_Config_Binding_Key *ebk;
204    Eina_List *l;
205
206    e_managers_keys_ungrab();
207    E_FREE_LIST(key_bindings, _e_bindings_key_free);
208
209    EINA_LIST_FOREACH(e_config->key_bindings, l, ebk)
210      e_bindings_key_add(ebk->context, ebk->key, ebk->modifiers,
211                         ebk->any_mod, ebk->action, ebk->params);
212    e_managers_keys_grab();
213 }
214
215 EAPI void
216 e_bindings_reset(void)
217 {
218    e_bindings_signal_reset();
219    e_bindings_mouse_reset();
220    e_bindings_wheel_reset();
221    e_bindings_edge_reset();
222    e_bindings_key_reset();
223 }
224
225 EAPI void
226 e_bindings_mouse_add(E_Binding_Context ctxt, int button, E_Binding_Modifier mod, int any_mod, const char *action, const char *params)
227 {
228    E_Binding_Mouse *binding;
229
230    binding = calloc(1, sizeof(E_Binding_Mouse));
231    binding->ctxt = ctxt;
232    binding->button = button;
233    binding->mod = mod;
234    binding->any_mod = any_mod;
235    if (action) binding->action = eina_stringshare_add(action);
236    if (params) binding->params = eina_stringshare_add(params);
237    mouse_bindings = eina_list_append(mouse_bindings, binding);
238 }
239
240 EAPI void
241 e_bindings_mouse_del(E_Binding_Context ctxt, int button, E_Binding_Modifier mod, int any_mod, const char *action, const char *params)
242 {
243    E_Binding_Mouse *binding;
244    Eina_List *l;
245
246    EINA_LIST_FOREACH(mouse_bindings, l, binding)
247      {
248         if ((binding->ctxt == ctxt) &&
249             (binding->button == button) &&
250             (binding->mod == mod) &&
251             (binding->any_mod == any_mod) &&
252             (((binding->action) && (action) && (!strcmp(binding->action, action))) ||
253              ((!binding->action) && (!action))) &&
254             (((binding->params) && (params) && (!strcmp(binding->params, params))) ||
255              ((!binding->params) && (!params))))
256           {
257              _e_bindings_mouse_free(binding);
258              mouse_bindings = eina_list_remove_list(mouse_bindings, l);
259              break;
260           }
261      }
262 }
263
264 EAPI void
265 e_bindings_mouse_grab(E_Binding_Context ctxt, Ecore_X_Window win)
266 {
267    E_Binding_Mouse *binding;
268    Eina_List *l;
269
270    EINA_LIST_FOREACH(mouse_bindings, l, binding)
271      {
272         if (_e_bindings_context_match(binding->ctxt, ctxt))
273           {
274              ecore_x_window_button_grab(win, binding->button,
275                                         ECORE_X_EVENT_MASK_MOUSE_DOWN |
276                                         ECORE_X_EVENT_MASK_MOUSE_UP |
277                                         ECORE_X_EVENT_MASK_MOUSE_MOVE,
278                                         _e_ecore_modifiers(binding->mod),
279                                         binding->any_mod);
280           }
281      }
282 }
283
284 EAPI void
285 e_bindings_mouse_ungrab(E_Binding_Context ctxt, Ecore_X_Window win)
286 {
287    E_Binding_Mouse *binding;
288    Eina_List *l;
289
290    EINA_LIST_FOREACH(mouse_bindings, l, binding)
291      {
292         if (_e_bindings_context_match(binding->ctxt, ctxt))
293           {
294              ecore_x_window_button_ungrab(win, binding->button,
295                                           _e_ecore_modifiers(binding->mod), binding->any_mod);
296           }
297      }
298 }
299
300 EAPI E_Action *
301 e_bindings_mouse_down_find(E_Binding_Context ctxt, E_Object *obj __UNUSED__, Ecore_Event_Mouse_Button *ev, E_Binding_Mouse **bind_ret)
302 {
303    E_Binding_Modifier mod = 0;
304    E_Binding_Mouse *binding;
305    Eina_List *l;
306
307    mod = _e_bindings_modifiers(ev->modifiers);
308    EINA_LIST_FOREACH(mouse_bindings, l, binding)
309      {
310         if ((binding->button == (int) ev->buttons) &&
311             ((binding->any_mod) || (binding->mod == mod)))
312           {
313              if (_e_bindings_context_match(binding->ctxt, ctxt))
314                {
315                   E_Action *act;
316
317                   act = e_action_find(binding->action);
318                   if (bind_ret) *bind_ret = binding;
319                   return act;
320                }
321           }
322      }
323    return NULL;
324 }
325
326 EAPI E_Action *
327 e_bindings_mouse_down_event_handle(E_Binding_Context ctxt, E_Object *obj, Ecore_Event_Mouse_Button *ev)
328 {
329    E_Action *act;
330    E_Binding_Mouse *binding;
331
332    act = e_bindings_mouse_down_find(ctxt, obj, ev, &binding);
333    if (act)
334      {
335         if (act->func.go_mouse)
336           act->func.go_mouse(obj, binding->params, ev);
337         else if (act->func.go)
338           act->func.go(obj, binding->params);
339         return act;
340      }
341    return act;
342 }
343
344 EAPI E_Action *
345 e_bindings_mouse_up_find(E_Binding_Context ctxt, E_Object *obj __UNUSED__, Ecore_Event_Mouse_Button *ev, E_Binding_Mouse **bind_ret)
346 {
347    E_Binding_Modifier mod = 0;
348    E_Binding_Mouse *binding;
349    Eina_List *l;
350
351    mod = _e_bindings_modifiers(ev->modifiers);
352    EINA_LIST_FOREACH(mouse_bindings, l, binding)
353      {
354         if ((binding->button == (int) ev->buttons) &&
355             ((binding->any_mod) || (binding->mod == mod)))
356           {
357              if (_e_bindings_context_match(binding->ctxt, ctxt))
358                {
359                   E_Action *act;
360
361                   act = e_action_find(binding->action);
362                   if (bind_ret) *bind_ret = binding;
363                   return act;
364                }
365           }
366      }
367    return NULL;
368 }
369
370 EAPI E_Action *
371 e_bindings_mouse_up_event_handle(E_Binding_Context ctxt, E_Object *obj, Ecore_Event_Mouse_Button *ev)
372 {
373    E_Action *act;
374    E_Binding_Mouse *binding;
375
376    act = e_bindings_mouse_up_find(ctxt, obj, ev, &binding);
377    if (act)
378      {
379         if (act->func.end_mouse)
380           act->func.end_mouse(obj, binding->params, ev);
381         else if (act->func.end)
382           act->func.end(obj, binding->params);
383         return act;
384      }
385    return act;
386 }
387
388 EAPI void
389 e_bindings_key_add(E_Binding_Context ctxt, const char *key, E_Binding_Modifier mod, int any_mod, const char *action, const char *params)
390 {
391    E_Binding_Key *binding;
392
393    binding = calloc(1, sizeof(E_Binding_Key));
394    binding->ctxt = ctxt;
395    binding->key = eina_stringshare_add(key);
396    binding->mod = mod;
397    binding->any_mod = any_mod;
398    if (action) binding->action = eina_stringshare_add(action);
399    if (params) binding->params = eina_stringshare_add(params);
400    key_bindings = eina_list_append(key_bindings, binding);
401 }
402
403 EAPI E_Binding_Key *
404 e_bindings_key_get(const char *action)
405 {
406    E_Binding_Key *binding;
407    Eina_List *l;
408
409    EINA_LIST_FOREACH(key_bindings, l, binding)
410      {
411         if (binding->action && action && !strcmp(action, binding->action))
412           return binding;
413      }
414    return NULL;
415 }
416
417 EAPI E_Binding_Key *
418 e_bindings_key_find(const char *key, E_Binding_Modifier mod, int any_mod)
419 {
420    E_Binding_Key *binding;
421    Eina_List *l;
422
423    if (!key) return NULL;
424
425    EINA_LIST_FOREACH(key_bindings, l, binding)
426      {
427         if ((binding->key) && (!strcmp(key, binding->key)) &&
428             (binding->mod == mod) && (binding->any_mod == any_mod))
429           return binding;
430      }
431
432    return NULL;
433 }
434
435 EAPI void
436 e_bindings_key_del(E_Binding_Context ctxt, const char *key, E_Binding_Modifier mod, int any_mod, const char *action, const char *params)
437 {
438    E_Binding_Key *binding;
439    Eina_List *l;
440
441    EINA_LIST_FOREACH(key_bindings, l, binding)
442      {
443         if ((binding->ctxt == ctxt) &&
444             (key) && (binding->key) && (!strcmp(binding->key, key)) &&
445             (binding->mod == mod) &&
446             (binding->any_mod == any_mod) &&
447             (((binding->action) && (action) && (!strcmp(binding->action, action))) ||
448              ((!binding->action) && (!action))) &&
449             (((binding->params) && (params) && (!strcmp(binding->params, params))) ||
450              ((!binding->params) && (!params))))
451           {
452              _e_bindings_key_free(binding);
453              key_bindings = eina_list_remove_list(key_bindings, l);
454              break;
455           }
456      }
457 }
458
459 EAPI void
460 e_bindings_key_grab(E_Binding_Context ctxt, Ecore_X_Window win)
461 {
462    E_Binding_Key *binding;
463    Eina_List *l;
464
465    EINA_LIST_FOREACH(key_bindings, l, binding)
466      {
467         if (_e_bindings_context_match(binding->ctxt, ctxt))
468           {
469              ecore_x_window_key_grab(win, binding->key,
470                                      _e_ecore_modifiers(binding->mod), binding->any_mod);
471           }
472      }
473 }
474
475 EAPI void
476 e_bindings_key_ungrab(E_Binding_Context ctxt, Ecore_X_Window win)
477 {
478    E_Binding_Key *binding;
479    Eina_List *l;
480
481    EINA_LIST_FOREACH(key_bindings, l, binding)
482      {
483         if (_e_bindings_context_match(binding->ctxt, ctxt))
484           {
485              ecore_x_window_key_ungrab(win, binding->key,
486                                        _e_ecore_modifiers(binding->mod), binding->any_mod);
487           }
488      }
489 }
490
491 EAPI E_Action *
492 e_bindings_key_down_event_handle(E_Binding_Context ctxt, E_Object *obj, Ecore_Event_Key *ev)
493 {
494    E_Binding_Modifier mod = 0;
495    E_Binding_Key *binding;
496    Eina_List *l;
497
498    mod = _e_bindings_modifiers(ev->modifiers);
499    EINA_LIST_FOREACH(key_bindings, l, binding)
500      {
501         if ((binding->key) && (!strcmp(binding->key, ev->keyname)) &&
502             ((binding->any_mod) || (binding->mod == mod)))
503           {
504              if (_e_bindings_context_match(binding->ctxt, ctxt))
505                {
506                   E_Action *act;
507
508                   act = e_action_find(binding->action);
509                   if (act)
510                     {
511                        if (act->func.go_key)
512                          act->func.go_key(obj, binding->params, ev);
513                        else if (act->func.go)
514                          act->func.go(obj, binding->params);
515                        return act;
516                     }
517                   return NULL;
518                }
519           }
520      }
521    return NULL;
522 }
523
524 EAPI E_Action *
525 e_bindings_key_up_event_handle(E_Binding_Context ctxt, E_Object *obj, Ecore_Event_Key *ev)
526 {
527    E_Binding_Modifier mod = 0;
528    E_Binding_Key *binding;
529    Eina_List *l;
530
531    mod = _e_bindings_modifiers(ev->modifiers);
532    EINA_LIST_FOREACH(key_bindings, l, binding)
533      {
534         if ((binding->key) && (!strcmp(binding->key, ev->keyname)) &&
535             ((binding->any_mod) || (binding->mod == mod)))
536           {
537              if (_e_bindings_context_match(binding->ctxt, ctxt))
538                {
539                   E_Action *act;
540
541                   act = e_action_find(binding->action);
542                   if (act)
543                     {
544                        if (act->func.end_key)
545                          act->func.end_key(obj, binding->params, ev);
546                        else if (act->func.end)
547                          act->func.end(obj, binding->params);
548                        return act;
549                     }
550                   return NULL;
551                }
552           }
553      }
554    return NULL;
555 }
556
557 EAPI E_Action *
558 e_bindings_key_down_event_find(E_Binding_Context ctxt, Ecore_Event_Key *ev)
559 {
560    E_Binding_Modifier mod = 0;
561    E_Binding_Key *binding;
562    Eina_List *l;
563
564    mod = _e_bindings_modifiers(ev->modifiers);
565    EINA_LIST_FOREACH(key_bindings, l, binding)
566      {
567         if ((binding->key) && (!strcmp(binding->key, ev->keyname)) &&
568             ((binding->any_mod) || (binding->mod == mod)))
569           {
570              if (_e_bindings_context_match(binding->ctxt, ctxt))
571                {
572                   E_Action *act;
573
574                   act = e_action_find(binding->action);
575                   return act;
576                }
577           }
578      }
579    return NULL;
580 }
581
582 EAPI E_Action *
583 e_bindings_key_up_event_find(E_Binding_Context ctxt, Ecore_Event_Key *ev)
584 {
585    E_Binding_Modifier mod = 0;
586    E_Binding_Key *binding;
587    Eina_List *l;
588
589    mod = _e_bindings_modifiers(ev->modifiers);
590    EINA_LIST_FOREACH(key_bindings, l, binding)
591      {
592         if ((binding->key) && (!strcmp(binding->key, ev->keyname)) &&
593             ((binding->any_mod) || (binding->mod == mod)))
594           {
595              if (_e_bindings_context_match(binding->ctxt, ctxt))
596                {
597                   E_Action *act;
598
599                   act = e_action_find(binding->action);
600                   return act;
601                }
602           }
603      }
604    return NULL;
605 }
606
607 EAPI void
608 e_bindings_edge_add(E_Binding_Context ctxt, E_Zone_Edge edge, E_Binding_Modifier mod, int any_mod, const char *action, const char *params, float delay)
609 {
610    E_Binding_Edge *binding;
611
612    binding = calloc(1, sizeof(E_Binding_Edge));
613    binding->ctxt = ctxt;
614    binding->edge = edge;
615    binding->mod = mod;
616    binding->any_mod = any_mod;
617    binding->delay = delay;
618    if (action) binding->action = eina_stringshare_add(action);
619    if (params) binding->params = eina_stringshare_add(params);
620    edge_bindings = eina_list_append(edge_bindings, binding);
621
622    e_zone_edge_new(edge);
623 }
624
625 EAPI Eina_Bool
626 e_bindings_edge_flippable_get(E_Zone_Edge edge)
627 {
628    E_Binding_Edge *binding;
629    Eina_List *l;
630
631    EINA_LIST_FOREACH(edge_bindings, l, binding)
632      {
633         if ((binding->edge == edge) && (binding->action))
634           {
635              if ((!strcmp(binding->action, "desk_flip_in_direction")) ||
636                  (!strcmp(binding->action, "desk_flip_by")))
637                 return EINA_TRUE;
638           }
639      }
640    return EINA_FALSE;
641 }
642
643 EAPI Eina_Bool
644 e_bindings_edge_non_flippable_get(E_Zone_Edge edge)
645 {
646    E_Binding_Edge *binding;
647    Eina_List *l;
648
649    EINA_LIST_FOREACH(edge_bindings, l, binding)
650      {
651         if ((binding->edge == edge) && (binding->action))
652           {
653              if ((!strcmp(binding->action, "desk_flip_in_direction")) ||
654                  (!strcmp(binding->action, "desk_flip_by")))
655                 continue;
656              return EINA_TRUE;
657           }
658      }
659    return EINA_FALSE;
660 }
661
662 EAPI E_Binding_Edge *
663 e_bindings_edge_get(const char *action, E_Zone_Edge edge, int click)
664 {
665    E_Binding_Edge *binding;
666    Eina_List *l;
667
668    EINA_LIST_FOREACH(edge_bindings, l, binding)
669      {
670         if ((binding->edge == edge) &&
671             ((click && (binding->delay == -1.0 * click))
672              || (!click && (binding->delay >= 0.0))) &&
673             (binding->action) && (action) &&
674             (!strcmp(action, binding->action)))
675           return binding;
676      }
677    return NULL;
678 }
679
680 EAPI void
681 e_bindings_edge_del(E_Binding_Context ctxt, E_Zone_Edge edge, E_Binding_Modifier mod, int any_mod, const char *action, const char *params, float delay)
682 {
683    E_Binding_Edge *binding;
684    Eina_List *l;
685    int ref_count = 0;
686
687    EINA_LIST_FOREACH(edge_bindings, l, binding)
688      {
689         if (binding->edge == edge)
690           {
691              if ((binding->ctxt == ctxt) &&
692                  (binding->mod == mod) &&
693                  ((binding->delay * 1000) == (delay * 1000)) &&
694                  (binding->any_mod == any_mod) &&
695                  (((binding->action) && (action) && (!strcmp(binding->action, action))) ||
696                   ((!binding->action) && (!action))) &&
697                  (((binding->params) && (params) && (!strcmp(binding->params, params))) ||
698                   ((!binding->params) && (!params))))
699                {
700                   _e_bindings_edge_free(binding);
701                   edge_bindings = eina_list_remove_list(edge_bindings, l);
702                }
703              else ref_count++;
704           }
705      }
706
707    if (!ref_count)
708      e_zone_edge_free(edge);
709 }
710
711 EAPI E_Action *
712 e_bindings_edge_in_event_handle(E_Binding_Context ctxt, E_Object *obj, E_Event_Zone_Edge *ev)
713 {
714    E_Binding_Modifier mod = 0;
715    E_Binding_Edge *binding;
716    E_Desk *current = NULL;
717    E_Action *act = NULL;
718    Eina_List *l;
719
720    current = e_desk_at_xy_get(ev->zone, ev->zone->desk_x_current, ev->zone->desk_y_current);
721    if (current->fullscreen_borders && (!e_config->fullscreen_flip)) return NULL;
722
723    if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) mod |= E_BINDING_MODIFIER_SHIFT;
724    if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) mod |= E_BINDING_MODIFIER_CTRL;
725    if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT) mod |= E_BINDING_MODIFIER_ALT;
726    if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN) mod |= E_BINDING_MODIFIER_WIN;
727    EINA_LIST_FOREACH(edge_bindings, l, binding)
728      {
729         /* A value of <= -1.0 for the delay indicates it as a mouse-click binding on that edge */
730         if (((binding->edge == ev->edge)) && (binding->delay >= 0.0) &&
731             ((binding->any_mod) || (binding->mod == mod)))
732           {
733              if (_e_bindings_context_match(binding->ctxt, ctxt))
734                {
735                   act = e_action_find(binding->action);
736                   if (act)
737                     {
738                        E_Binding_Edge_Data *ed = E_NEW(E_Binding_Edge_Data, 1);
739                        E_Event_Zone_Edge *ev2 = E_NEW(E_Event_Zone_Edge, 1);
740
741                        /* The original event will be freed before it can be
742                         * used again */
743                        ev2->zone  = ev->zone;
744                        ev2->edge  = ev->edge;
745                        ev2->x     = ev->x;
746                        ev2->y     = ev->y;
747
748                        ed->bind = binding;
749                        ed->obj  = obj;
750                        ed->act  = act;
751                        ed->ev   = ev2;
752                        binding->timer = ecore_timer_add(((double) binding->delay), _e_bindings_edge_cb_timer, ed);
753                     }
754                }
755           }
756      }
757    return act;
758 }
759
760 EAPI E_Action *
761 e_bindings_edge_out_event_handle(E_Binding_Context ctxt, E_Object *obj, E_Event_Zone_Edge *ev)
762 {
763    E_Binding_Modifier mod = 0;
764    E_Binding_Edge *binding;
765    E_Action *act = NULL;
766    Eina_List *l;
767
768    if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) mod |= E_BINDING_MODIFIER_SHIFT;
769    if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) mod |= E_BINDING_MODIFIER_CTRL;
770    if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT) mod |= E_BINDING_MODIFIER_ALT;
771    if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN) mod |= E_BINDING_MODIFIER_WIN;
772    EINA_LIST_FOREACH(edge_bindings, l, binding)
773      {
774         /* A value of <= -1.0 for the delay indicates it as a mouse-click binding on that edge */
775         if ((binding->edge == ev->edge) && (binding->delay >= 0.0) &&
776             ((binding->any_mod) || (binding->mod == mod)))
777           {
778              if (_e_bindings_context_match(binding->ctxt, ctxt))
779                {
780                   if (binding->timer)
781                     {
782                        E_Binding_Edge_Data *ed;
783
784                        ed = ecore_timer_del(binding->timer);
785                        if (ed)
786                          {
787                             E_FREE(ed->ev);
788                             E_FREE(ed);
789                          }
790                     }
791                   binding->timer = NULL;
792
793                   act = e_action_find(binding->action);
794                   if (act && act->func.end)
795                     act->func.end(obj, binding->params);
796                }
797           }
798      }
799    return act;
800 }
801
802 EAPI E_Action *
803 e_bindings_edge_down_event_handle(E_Binding_Context ctxt, E_Object *obj, E_Event_Zone_Edge *ev)
804 {
805    E_Binding_Modifier mod = 0;
806    E_Binding_Edge *binding;
807    E_Desk *current = NULL;
808    E_Action *act = NULL;
809    Eina_List *l;
810
811    current = e_desk_at_xy_get(ev->zone, ev->zone->desk_x_current, ev->zone->desk_y_current);
812    if (current->fullscreen_borders && (!e_config->fullscreen_flip)) return NULL;
813
814    if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) mod |= E_BINDING_MODIFIER_SHIFT;
815    if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) mod |= E_BINDING_MODIFIER_CTRL;
816    if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT) mod |= E_BINDING_MODIFIER_ALT;
817    if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN) mod |= E_BINDING_MODIFIER_WIN;
818    EINA_LIST_FOREACH(edge_bindings, l, binding)
819      {
820         if (((binding->edge == ev->edge)) && (binding->delay == -1.0 * ev->button) &&
821             ((binding->any_mod) || (binding->mod == mod)))
822           {
823              if (_e_bindings_context_match(binding->ctxt, ctxt))
824                {
825                   act = e_action_find(binding->action);
826                   if (act)
827                     {
828                        if (act->func.go_edge)
829                          act->func.go_edge(obj, binding->params, ev);
830                        else if (act->func.go)
831                          act->func.go(obj, binding->params);
832                     }
833                }
834           }
835      }
836    return act;
837 }
838
839 EAPI E_Action *
840 e_bindings_edge_up_event_handle(E_Binding_Context ctxt, E_Object *obj, E_Event_Zone_Edge *ev)
841 {
842    E_Binding_Modifier mod = 0;
843    E_Binding_Edge *binding;
844    E_Action *act = NULL;
845    Eina_List *l;
846
847    if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) mod |= E_BINDING_MODIFIER_SHIFT;
848    if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) mod |= E_BINDING_MODIFIER_CTRL;
849    if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT) mod |= E_BINDING_MODIFIER_ALT;
850    if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN) mod |= E_BINDING_MODIFIER_WIN;
851    EINA_LIST_FOREACH(edge_bindings, l, binding)
852      {
853         if (((binding->edge == ev->edge)) && (binding->delay == -1.0 * ev->button) &&
854             ((binding->any_mod) || (binding->mod == mod)))
855           {
856              if (_e_bindings_context_match(binding->ctxt, ctxt))
857                {
858                   act = e_action_find(binding->action);
859                   if (act && act->func.end)
860                     act->func.end(obj, binding->params);
861                }
862           }
863      }
864    return act;
865 }
866
867 EAPI void
868 e_bindings_signal_add(E_Binding_Context ctxt, const char *sig, const char *src, E_Binding_Modifier mod, int any_mod, const char *action, const char *params)
869 {
870    E_Binding_Signal *binding;
871
872    binding = calloc(1, sizeof(E_Binding_Signal));
873    binding->ctxt = ctxt;
874    if (sig) binding->sig = eina_stringshare_add(sig);
875    if (src) binding->src = eina_stringshare_add(src);
876    binding->mod = mod;
877    binding->any_mod = any_mod;
878    if (action) binding->action = eina_stringshare_add(action);
879    if (params) binding->params = eina_stringshare_add(params);
880    signal_bindings = eina_list_append(signal_bindings, binding);
881 }
882
883 EAPI void
884 e_bindings_signal_del(E_Binding_Context ctxt, const char *sig, const char *src, E_Binding_Modifier mod, int any_mod, const char *action, const char *params)
885 {
886    E_Binding_Signal *binding;
887    Eina_List *l;
888
889    EINA_LIST_FOREACH(signal_bindings, l, binding)
890      {
891         if ((binding->ctxt == ctxt) &&
892             (((binding->sig) && (sig) && (!strcmp(binding->sig, sig))) ||
893              ((!binding->sig) && (!sig))) &&
894             (((binding->src) && (src) && (!strcmp(binding->src, src))) ||
895              ((!binding->src) && (!src))) &&
896             (binding->mod == mod) &&
897             (binding->any_mod == any_mod) &&
898             (((binding->action) && (action) && (!strcmp(binding->action, action))) ||
899              ((!binding->action) && (!action))) &&
900             (((binding->params) && (params) && (!strcmp(binding->params, params))) ||
901              ((!binding->params) && (!params))))
902           {
903              _e_bindings_signal_free(binding);
904              signal_bindings = eina_list_remove_list(signal_bindings, l);
905              break;
906           }
907      }
908 }
909
910 EAPI E_Action  *
911 e_bindings_signal_find(E_Binding_Context ctxt, E_Object *obj __UNUSED__, const char *sig, const char *src, E_Binding_Signal **bind_ret)
912 {
913    E_Binding_Modifier mod = 0;
914    E_Binding_Signal *binding;
915    Eina_List *l;
916
917    if (strstr(sig, "MOD:Shift")) mod |= E_BINDING_MODIFIER_SHIFT;
918    if (strstr(sig, "MOD:Control")) mod |= E_BINDING_MODIFIER_CTRL;
919    if (strstr(sig, "MOD:Alt")) mod |= E_BINDING_MODIFIER_ALT;
920    if (strstr(sig, "MOD:Super")) mod |= E_BINDING_MODIFIER_WIN;
921    EINA_LIST_FOREACH(signal_bindings, l, binding)
922      {
923         if ((e_util_glob_match(sig, binding->sig)) &&
924             (e_util_glob_match(src, binding->src)) &&
925             ((binding->any_mod) || (binding->mod == mod)))
926           {
927              if (_e_bindings_context_match(binding->ctxt, ctxt))
928                {
929                   E_Action *act;
930
931                   act = e_action_find(binding->action);
932                   if (bind_ret) *bind_ret = binding;
933                   return act;
934                }
935           }
936      }
937    return NULL;
938 }
939
940 EAPI E_Action *
941 e_bindings_signal_handle(E_Binding_Context ctxt, E_Object *obj, const char *sig, const char *src)
942 {
943    E_Action *act;
944    E_Binding_Signal *binding;
945
946    if (sig[0] == 0) sig = NULL;
947    if (src[0] == 0) src = NULL;
948    act = e_bindings_signal_find(ctxt, obj, sig, src, &binding);
949    if (act)
950      {
951         if (act->func.go_signal)
952           act->func.go_signal(obj, binding->params, sig, src);
953         else if (act->func.go)
954           act->func.go(obj, binding->params);
955         return act;
956      }
957    return act;
958 }
959
960 EAPI void
961 e_bindings_wheel_add(E_Binding_Context ctxt, int direction, int z, E_Binding_Modifier mod, int any_mod, const char *action, const char *params)
962 {
963    E_Binding_Wheel *binding;
964
965    binding = calloc(1, sizeof(E_Binding_Wheel));
966    binding->ctxt = ctxt;
967    binding->direction = direction;
968    binding->z = z;
969    binding->mod = mod;
970    binding->any_mod = any_mod;
971    if (action) binding->action = eina_stringshare_add(action);
972    if (params) binding->params = eina_stringshare_add(params);
973    wheel_bindings = eina_list_append(wheel_bindings, binding);
974 }
975
976 EAPI void
977 e_bindings_wheel_del(E_Binding_Context ctxt, int direction, int z, E_Binding_Modifier mod, int any_mod, const char *action, const char *params)
978 {
979    E_Binding_Wheel *binding;
980    Eina_List *l;
981
982    EINA_LIST_FOREACH(wheel_bindings, l, binding)
983      {
984         if ((binding->ctxt == ctxt) &&
985             (binding->direction == direction) &&
986             (binding->z == z) &&
987             (binding->mod == mod) &&
988             (binding->any_mod == any_mod) &&
989             (((binding->action) && (action) && (!strcmp(binding->action, action))) ||
990              ((!binding->action) && (!action))) &&
991             (((binding->params) && (params) && (!strcmp(binding->params, params))) ||
992              ((!binding->params) && (!params))))
993           {
994              _e_bindings_wheel_free(binding);
995              wheel_bindings = eina_list_remove_list(wheel_bindings, l);
996              break;
997           }
998      }
999 }
1000
1001 EAPI void
1002 e_bindings_wheel_grab(E_Binding_Context ctxt, Ecore_X_Window win)
1003 {
1004    E_Binding_Wheel *binding;
1005    Eina_List *l;
1006
1007    EINA_LIST_FOREACH(wheel_bindings, l, binding)
1008      {
1009         if (_e_bindings_context_match(binding->ctxt, ctxt))
1010           {
1011              int button = 0;
1012
1013              if (binding->direction == 0)
1014                {
1015                   if (binding->z < 0) button = 4;
1016                   else if (binding->z > 0) button = 5;
1017                }
1018              else if (binding->direction == 1)
1019                {
1020                   if (binding->z < 0) button = 6;
1021                   else if (binding->z > 0) button = 7;
1022                }
1023              if (button != 0)
1024                ecore_x_window_button_grab(win, button,
1025                                           ECORE_X_EVENT_MASK_MOUSE_DOWN,
1026                                           _e_ecore_modifiers(binding->mod), binding->any_mod);
1027           }
1028      }
1029 }
1030
1031 EAPI void
1032 e_bindings_wheel_ungrab(E_Binding_Context ctxt, Ecore_X_Window win)
1033 {
1034    E_Binding_Wheel *binding;
1035    Eina_List *l;
1036
1037    EINA_LIST_FOREACH(wheel_bindings, l, binding)
1038      {
1039         if (_e_bindings_context_match(binding->ctxt, ctxt))
1040           {
1041              int button = 0;
1042
1043              if (binding->direction == 0)
1044                {
1045                   if (binding->z < 0) button = 4;
1046                   else if (binding->z > 0) button = 5;
1047                }
1048              else if (binding->direction == 1)
1049                {
1050                   if (binding->z < 0) button = 6;
1051                   else if (binding->z > 0) button = 7;
1052                }
1053              if (button != 0)
1054                ecore_x_window_button_ungrab(win, button,
1055                                             _e_ecore_modifiers(binding->mod), binding->any_mod);
1056           }
1057      }
1058 }
1059
1060 EAPI E_Action *
1061 e_bindings_wheel_find(E_Binding_Context ctxt, E_Object *obj __UNUSED__, Ecore_Event_Mouse_Wheel *ev, E_Binding_Wheel **bind_ret)
1062 {
1063    E_Binding_Modifier mod = 0;
1064    E_Binding_Wheel *binding;
1065    Eina_List *l;
1066
1067    mod = _e_bindings_modifiers(ev->modifiers);
1068    EINA_LIST_FOREACH(wheel_bindings, l, binding)
1069      {
1070         if ((binding->direction == ev->direction) &&
1071             (((binding->z < 0) && (ev->z < 0)) || ((binding->z > 0) && (ev->z > 0))) &&
1072             ((binding->any_mod) || (binding->mod == mod)))
1073           {
1074              if (_e_bindings_context_match(binding->ctxt, ctxt))
1075                {
1076                   E_Action *act;
1077
1078                   act = e_action_find(binding->action);
1079                   if (bind_ret) *bind_ret = binding;
1080                   return act;
1081                }
1082           }
1083      }
1084    return NULL;
1085 }
1086
1087 EAPI E_Action *
1088 e_bindings_wheel_event_handle(E_Binding_Context ctxt, E_Object *obj, Ecore_Event_Mouse_Wheel *ev)
1089 {
1090    E_Action *act;
1091    E_Binding_Wheel *binding;
1092
1093    act = e_bindings_wheel_find(ctxt, obj, ev, &binding);
1094    if (act)
1095      {
1096         if (act->func.go_wheel)
1097           act->func.go_wheel(obj, binding->params, ev);
1098         else if (act->func.go)
1099           act->func.go(obj, binding->params);
1100         return act;
1101      }
1102    return act;
1103 }
1104
1105 EAPI void
1106 e_bindings_acpi_add(E_Binding_Context ctxt, int type, int status, const char *action, const char *params)
1107 {
1108    E_Binding_Acpi *binding;
1109
1110    binding = E_NEW(E_Binding_Acpi, 1);
1111    binding->ctxt = ctxt;
1112    binding->type = type;
1113    binding->status = status;
1114    if (action) binding->action = eina_stringshare_add(action);
1115    if (params) binding->params = eina_stringshare_add(params);
1116    acpi_bindings = eina_list_append(acpi_bindings, binding);
1117 }
1118
1119 EAPI void
1120 e_bindings_acpi_del(E_Binding_Context ctxt, int type, int status, const char *action, const char *params)
1121 {
1122    E_Binding_Acpi *binding;
1123    Eina_List *l;
1124
1125    EINA_LIST_FOREACH(acpi_bindings, l, binding)
1126      {
1127         if ((binding->ctxt == ctxt) &&
1128             (binding->type == type) && (binding->status == status) &&
1129             (((binding->action) && (action) && (!strcmp(binding->action, action))) ||
1130              ((!binding->action) && (!action))) &&
1131             (((binding->params) && (params) && (!strcmp(binding->params, params))) ||
1132              ((!binding->params) && (!params))))
1133           {
1134              _e_bindings_acpi_free(binding);
1135              acpi_bindings = eina_list_remove_list(acpi_bindings, l);
1136              break;
1137           }
1138      }
1139 }
1140
1141 EAPI E_Action *
1142 e_bindings_acpi_find(E_Binding_Context ctxt, E_Object *obj __UNUSED__, E_Event_Acpi *ev, E_Binding_Acpi **bind_ret)
1143 {
1144    E_Binding_Acpi *binding;
1145    Eina_List *l;
1146
1147    EINA_LIST_FOREACH(acpi_bindings, l, binding)
1148      {
1149         if (binding->type == ev->type)
1150           {
1151              /* if binding status is -1, then we don't compare event status */
1152              if (binding->status != -1)
1153                {
1154                   /* binding status is set to something, compare event status */
1155                   if (binding->status != ev->status) continue;
1156                }
1157              if (_e_bindings_context_match(binding->ctxt, ctxt))
1158                {
1159                   E_Action *act;
1160
1161                   act = e_action_find(binding->action);
1162                   if (bind_ret) *bind_ret = binding;
1163                   return act;
1164                }
1165           }
1166      }
1167    return NULL;
1168 }
1169
1170 EAPI E_Action *
1171 e_bindings_acpi_event_handle(E_Binding_Context ctxt, E_Object *obj, E_Event_Acpi *ev)
1172 {
1173    E_Action *act;
1174    E_Binding_Acpi *binding;
1175
1176    act = e_bindings_acpi_find(ctxt, obj, ev, &binding);
1177    if (act)
1178      {
1179         if (act->func.go_acpi)
1180           act->func.go_acpi(obj, binding->params, ev);
1181         else if (act->func.go)
1182           act->func.go(obj, binding->params);
1183         return act;
1184      }
1185    return act;
1186 }
1187
1188 EAPI void
1189 e_bindings_mapping_change_enable(Eina_Bool enable)
1190 {
1191    if (enable)
1192      _e_bindings_mapping_change_enabled++;
1193    else
1194      _e_bindings_mapping_change_enabled--;
1195    if (_e_bindings_mapping_change_enabled < 0)
1196      _e_bindings_mapping_change_enabled = 0;
1197 }
1198
1199 /* local subsystem functions */
1200 static Eina_Bool
1201 _e_bindings_mapping_change_event_cb(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
1202 {
1203   if (!_e_bindings_mapping_change_enabled) return ECORE_CALLBACK_RENEW;
1204   e_managers_keys_ungrab();
1205   e_border_button_bindings_ungrab_all();
1206   e_border_button_bindings_grab_all();
1207   e_managers_keys_grab();
1208   return ECORE_CALLBACK_PASS_ON;
1209 }
1210
1211 static void
1212 _e_bindings_mouse_free(E_Binding_Mouse *binding)
1213 {
1214    if (binding->action) eina_stringshare_del(binding->action);
1215    if (binding->params) eina_stringshare_del(binding->params);
1216    free(binding);
1217 }
1218
1219 static void
1220 _e_bindings_key_free(E_Binding_Key *binding)
1221 {
1222    if (binding->key) eina_stringshare_del(binding->key);
1223    if (binding->action) eina_stringshare_del(binding->action);
1224    if (binding->params) eina_stringshare_del(binding->params);
1225    free(binding);
1226 }
1227
1228 static void
1229 _e_bindings_edge_free(E_Binding_Edge *binding)
1230 {
1231    if (binding->action) eina_stringshare_del(binding->action);
1232    if (binding->params) eina_stringshare_del(binding->params);
1233    if (binding->timer)
1234      {
1235         E_Binding_Edge_Data *ed;
1236
1237         ed = ecore_timer_del(binding->timer);
1238         E_FREE(ed);
1239      }
1240    free(binding);
1241 }
1242
1243 static void
1244 _e_bindings_signal_free(E_Binding_Signal *binding)
1245 {
1246    if (binding->sig) eina_stringshare_del(binding->sig);
1247    if (binding->src) eina_stringshare_del(binding->src);
1248    if (binding->action) eina_stringshare_del(binding->action);
1249    if (binding->params) eina_stringshare_del(binding->params);
1250    free(binding);
1251 }
1252
1253 static void
1254 _e_bindings_wheel_free(E_Binding_Wheel *binding)
1255 {
1256    if (binding->action) eina_stringshare_del(binding->action);
1257    if (binding->params) eina_stringshare_del(binding->params);
1258    free(binding);
1259 }
1260
1261 static void
1262 _e_bindings_acpi_free(E_Binding_Acpi *binding)
1263 {
1264    if (binding->action) eina_stringshare_del(binding->action);
1265    if (binding->params) eina_stringshare_del(binding->params);
1266    E_FREE(binding);
1267 }
1268
1269 static int
1270 _e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt)
1271 {
1272    if (bctxt == E_BINDING_CONTEXT_ANY &&
1273        !(ctxt == E_BINDING_CONTEXT_ZONE)) return 1;
1274    if (ctxt == E_BINDING_CONTEXT_UNKNOWN) return 0;
1275    if (bctxt == ctxt) return 1;
1276    return 0;
1277 }
1278
1279 static E_Binding_Modifier
1280 _e_bindings_modifiers(unsigned int modifiers)
1281 {
1282    E_Binding_Modifier mod = 0;
1283
1284    if (modifiers & ECORE_EVENT_MODIFIER_SHIFT) mod |= E_BINDING_MODIFIER_SHIFT;
1285    if (modifiers & ECORE_EVENT_MODIFIER_CTRL) mod |= E_BINDING_MODIFIER_CTRL;
1286    if (modifiers & ECORE_EVENT_MODIFIER_ALT) mod |= E_BINDING_MODIFIER_ALT;
1287    if (modifiers & ECORE_EVENT_MODIFIER_WIN) mod |= E_BINDING_MODIFIER_WIN;
1288    /* FIXME: there is a good reason numlock was ignored. sometimes people
1289     * have it on, sometimes they don't, and often they have no idea. waaaay
1290     * back in E 0.1->0.13 or so days this caused issues thus numlock,
1291     * scrollock and capslock are not usable modifiers.
1292     *
1293     * if we REALLY want to be able to use numlock we need to add more binding
1294     * flags and config that says "REALLY pay attention to numlock for this
1295     * binding" field in the binding (like there is a "any_mod" flag - we need a
1296     * "num_lock_respect" field)
1297     *
1298     * also it should be an E_BINDING_MODIFIER_LOCK_NUM as the ecore lock flag
1299     * may vary from system to system as different xservers may have differing
1300     * modifier masks for numlock (it is queried at startup).
1301     *
1302    if (ev->modifiers & ECORE_X_LOCK_NUM) mod |= ECORE_X_LOCK_NUM;
1303     */
1304
1305    return mod;
1306 }
1307
1308 static int
1309 _e_ecore_modifiers(E_Binding_Modifier modifiers)
1310 {
1311    int mod = 0;
1312
1313    if (modifiers & E_BINDING_MODIFIER_SHIFT) mod |= ECORE_EVENT_MODIFIER_SHIFT;
1314    if (modifiers & E_BINDING_MODIFIER_CTRL) mod |= ECORE_EVENT_MODIFIER_CTRL;
1315    if (modifiers & E_BINDING_MODIFIER_ALT) mod |= ECORE_EVENT_MODIFIER_ALT;
1316    if (modifiers & E_BINDING_MODIFIER_WIN) mod |= ECORE_EVENT_MODIFIER_WIN;
1317    /* see comment in e_bindings on numlock
1318       if (modifiers & ECORE_X_LOCK_NUM) mod |= ECORE_X_LOCK_NUM;
1319    */
1320
1321    return mod;
1322 }
1323
1324 static Eina_Bool
1325 _e_bindings_edge_cb_timer(void *data)
1326 {
1327    E_Binding_Edge_Data *ed;
1328    E_Event_Zone_Edge *ev;
1329    E_Binding_Edge *binding;
1330    E_Action *act;
1331    E_Object *obj;
1332
1333    ed = data;
1334    binding = ed->bind;
1335    act = ed->act;
1336    obj = ed->obj;
1337    ev = ed->ev;
1338
1339    E_FREE(ed);
1340
1341    if (act->func.go_edge)
1342      act->func.go_edge(obj, binding->params, ev);
1343    else if (act->func.go)
1344      act->func.go(obj, binding->params);
1345
1346    binding->timer = NULL;
1347
1348    /* Duplicate event */
1349    E_FREE(ev);
1350
1351    return ECORE_CALLBACK_CANCEL;
1352 }