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