diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index e37dbf93d8..0aca9abe93 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -437,8 +437,8 @@ extern "C" { Evas_Modifier_Mask evas_key_modifier_mask_get (Evas *e, char *keyname); - int evas_object_key_grab (Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, int exclusive); - void evas_object_key_ungrab (Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers); + int evas_object_key_grab (Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive); + void evas_object_key_ungrab (Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers); void evas_object_pass_events_set (Evas_Object *obj, int pass); int evas_object_pass_events_get (Evas_Object *obj); diff --git a/legacy/evas/src/lib/canvas/Makefile.am b/legacy/evas/src/lib/canvas/Makefile.am index d17cc5ef66..5b3e2df96c 100644 --- a/legacy/evas/src/lib/canvas/Makefile.am +++ b/legacy/evas/src/lib/canvas/Makefile.am @@ -21,6 +21,7 @@ evas_data.c \ evas_events.c \ evas_focus.c \ evas_key.c \ +evas_key_grab.c \ evas_layer.c \ evas_main.c \ evas_name.c \ diff --git a/legacy/evas/src/lib/canvas/evas_events.c b/legacy/evas/src/lib/canvas/evas_events.c index 9a665ad62b..f9a2009323 100644 --- a/legacy/evas/src/lib/canvas/evas_events.c +++ b/legacy/evas/src/lib/canvas/evas_events.c @@ -418,8 +418,6 @@ evas_event_feed_key_down_data(Evas *e, char *keyname, void *data) MAGIC_CHECK_END(); if (!keyname) return; if (e->events_frozen > 0) return; - /* FIXME: handle grabs */ - if (e->focused) { Evas_Event_Key_Down ev; @@ -427,8 +425,27 @@ evas_event_feed_key_down_data(Evas *e, char *keyname, void *data) ev.data = data; ev.modifiers = &(e->modifiers); ev.locks = &(e->locks); - evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev); - } + if (e->grabs) + { + Evas_List *l; + + for (l = e->grabs; l; l= l->next) + { + Evas_Key_Grab *g; + + g = l->data; + if ((e->modifiers.mask & g->modifiers) && + (!(e->modifiers.mask & g->not_modifiers)) && + (!strcmp(keyname, g->keyname))) + { + evas_object_event_callback_call(g->object, EVAS_CALLBACK_KEY_DOWN, &ev); + if (g->exclusive) return; + } + } + } + if (e->focused) + evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev); + } } void @@ -439,9 +456,6 @@ evas_event_feed_key_up_data(Evas *e, char *keyname, void *data) MAGIC_CHECK_END(); if (!keyname) return; if (e->events_frozen > 0) return; - if (!e->focused) return; - /* FIXME: handle grabs */ - if (e->focused) { Evas_Event_Key_Up ev; @@ -449,8 +463,27 @@ evas_event_feed_key_up_data(Evas *e, char *keyname, void *data) ev.data = data; ev.modifiers = &(e->modifiers); ev.locks = &(e->locks); - evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev); - } + if (e->grabs) + { + Evas_List *l; + + for (l = e->grabs; l; l= l->next) + { + Evas_Key_Grab *g; + + g = l->data; + if ((e->modifiers.mask & g->modifiers) && + (!(e->modifiers.mask & g->not_modifiers)) && + (!strcmp(keyname, g->keyname))) + { + evas_object_event_callback_call(g->object, EVAS_CALLBACK_KEY_UP, &ev); + if (g->exclusive) return; + } + } + } + if (e->focused) + evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev); + } } void diff --git a/legacy/evas/src/lib/canvas/evas_key.c b/legacy/evas/src/lib/canvas/evas_key.c index ccc66ffa68..d61d20b633 100644 --- a/legacy/evas/src/lib/canvas/evas_key.c +++ b/legacy/evas/src/lib/canvas/evas_key.c @@ -233,13 +233,3 @@ evas_key_modifier_mask_get(Evas *e, char *keyname) if (num < 0) return 0; return 1 << num; } - -int -evas_object_key_grab(Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, int exclusive) -{ -} - -void -evas_object_key_ungrab(Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers) -{ -} diff --git a/legacy/evas/src/lib/canvas/evas_key_grab.c b/legacy/evas/src/lib/canvas/evas_key_grab.c new file mode 100644 index 0000000000..c002255626 --- /dev/null +++ b/legacy/evas/src/lib/canvas/evas_key_grab.c @@ -0,0 +1,158 @@ +#include "evas_common.h" +#include "evas_private.h" +#include "Evas.h" + +/* private calls */ + +/* FIXME: this is not optimal, but works. i should have a hash of keys per */ +/* Evas and then a linked lists of grabs for that key and what */ +/* modifiers/not_modifers they use */ + +static Evas_Key_Grab *evas_key_grab_new (Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive); +static void evas_key_grab_free (Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers); +static Evas_Key_Grab *evas_key_grab_find (Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers); + +static Evas_Key_Grab * +evas_key_grab_new(Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive) +{ + /* MEM OK */ + Evas_Key_Grab *g; + + g = evas_mem_calloc(sizeof(Evas_Key_Grab)); + if (!g) return; + g->keyname = strdup(keyname); + if (!g->keyname) + { + if (!evas_mem_free(strlen(keyname) + 1)) + { + free(g); + return NULL; + } + g->keyname = strdup(keyname); + if (!g->keyname) + { + free(g); + return NULL; + } + } + g->object->grabs = evas_list_append(g->object->grabs, g); + if (evas_list_alloc_error()) + { + MERR_BAD(); + evas_mem_free(sizeof(Evas_List)); + g->object->grabs = evas_list_append(g->object->grabs, g); + if (evas_list_alloc_error()) + { + MERR_FATAL(); + free(g); + free(g->keyname); + return NULL; + } + } + obj->layer->evas->grabs = evas_list_append(obj->layer->evas->grabs, g); + if (evas_list_alloc_error()) + { + MERR_BAD(); + evas_mem_free(sizeof(Evas_List)); + obj->layer->evas->grabs = evas_list_append(obj->layer->evas->grabs, g); + if (evas_list_alloc_error()) + { + MERR_FATAL(); + g->object->grabs = evas_list_remove(g->object->grabs, g); + free(g); + free(g->keyname); + return NULL; + } + } + g->object = obj; + g->modifiers = modifiers; + g->not_modifiers = not_modifiers; + g->exclusive = exclusive; + return g; +} + +static void +evas_key_grab_free(Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers) +{ + /* MEM OK */ + Evas_Key_Grab *g; + + g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers); + if (!g) return; + g->object->grabs = evas_list_remove(g->object->grabs, g); + if (g->keyname) free(g->keyname); + free(g); +} + +static Evas_Key_Grab * +evas_key_grab_find(Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers) +{ + /* MEM OK */ + Evas_List *l; + + for (l = obj->layer->evas->grabs; l; l = l->next) + { + Evas_Key_Grab *g; + + g = l->data; + if ((g->modifiers == modifiers) && + (g->not_modifiers == not_modifiers) && + (!strcmp(g->keyname, keyname))) + { + if ((!obj) || (obj == g->object)) return g; + } + } + return NULL; +} + +/* local calls */ + +void +evas_object_grabs_cleanup(Evas_Object *obj) +{ + while (obj->grabs) + { + Evas_Key_Grab *g; + + g = obj->grabs->data; + if (g->keyname) free(g->keyname); + free(g); + obj->layer->evas->grabs = evas_list_remove(obj->layer->evas->grabs, g); + obj->grabs = evas_list_remove(obj->grabs, g); + } +} + +/* public calls */ + +int +evas_object_key_grab(Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive) +{ + /* MEM OK */ + Evas_Key_Grab *g; + + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return 0; + MAGIC_CHECK_END(); + if (exclusive) + { + g = evas_key_grab_find(NULL, keyname, modifiers, not_modifiers); + if (g) return 0; + } + g = evas_key_grab_new(obj, keyname, modifiers, not_modifiers, exclusive); + if (!g) return 0; + return 1; +} + +void +evas_object_key_ungrab(Evas_Object *obj, char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers) +{ + /* MEM OK */ + Evas_Key_Grab *g; + + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers); + if (!g) return; + evas_key_grab_free(g->object, keyname, modifiers, not_modifiers); +} diff --git a/legacy/evas/src/lib/canvas/evas_object_main.c b/legacy/evas/src/lib/canvas/evas_object_main.c index 35babdfa38..ba0d544a58 100644 --- a/legacy/evas/src/lib/canvas/evas_object_main.c +++ b/legacy/evas/src/lib/canvas/evas_object_main.c @@ -20,6 +20,7 @@ void evas_object_free(Evas_Object *obj, int clean_layer) { evas_object_event_callback_call(obj, EVAS_CALLBACK_FREE, NULL); + evas_object_grabs_cleanup(obj); evas_object_intercept_cleanup(obj); evas_object_smart_cleanup(obj); obj->func->free(obj); @@ -414,6 +415,7 @@ evas_object_del(Evas_Object *obj) obj->layer->evas->focused = NULL; evas_object_event_callback_call(obj, EVAS_CALLBACK_FOCUS_OUT, NULL); } + evas_object_grabs_cleanup(obj); evas_object_hide(obj); while (obj->clip.clipees) evas_object_clip_unset(obj->clip.clipees->data); if (obj->cur.clipper) evas_object_clip_unset(obj); diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index a76f257f9a..946a95d2a0 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -46,13 +46,14 @@ typedef struct _Evas_Modifier Evas_Modifier; typedef struct _Evas_Lock Evas_Lock; typedef unsigned long long Evas_Modifier_Mask; typedef struct _Evas_Smart Evas_Smart; -typedef struct _Evas_Intercept_Func Evas_Intercept_Func; +typedef void Evas_Performance; +typedef struct _Evas_Intercept_Func Evas_Intercept_Func; typedef struct _Evas_Intercept_Func_Basic Evas_Intercept_Func_Basic; typedef struct _Evas_Intercept_Func_SizePos Evas_Intercept_Func_SizePos; typedef struct _Evas_Intercept_Func_Obj Evas_Intercept_Func_Obj; typedef struct _Evas_Intercept_Func_Int Evas_Intercept_Func_Int; -typedef void Evas_Performance; - +typedef struct _Evas_Key_Grab Evas_Key_Grab; + #define MAGIC_EVAS 0x70777770 #define MAGIC_OBJ 0x71777770 #define MAGIC_OBJ_RECTANGLE 0x71777771 @@ -92,8 +93,6 @@ if (_r) \ #define MERR_FATAL() _evas_alloc_error = EVAS_ALLOC_ERROR_FATAL #define MERR_BAD() _evas_alloc_error = EVAS_ALLOC_ERROR_RECOVERED -#define MEM_TRY_CALLOC(_ptr, _size) - struct _Evas_Rectangle { int x, y, w, h; @@ -123,6 +122,15 @@ struct _Evas_Intercept_Func_Int void *data; }; +struct _Evas_Key_Grab +{ + char *keyname; + Evas_Modifier_Mask modifiers; + Evas_Modifier_Mask not_modifiers; + Evas_Object *object; + int exclusive : 1; +}; + struct _Evas_Intercept_Func { Evas_Intercept_Func_Basic show; @@ -236,6 +244,8 @@ struct _Evas int info_magic; } engine; + Evas_List *grabs; + Evas_List *font_path; Evas_Object *focused; @@ -315,6 +325,8 @@ struct _Evas_Object Evas_List *elements; } data; + Evas_List *grabs; + struct { Evas_Object_List *in; Evas_Object_List *out; @@ -537,6 +549,7 @@ int evas_object_intercept_call_lower(Evas_Object *obj); int evas_object_intercept_call_stack_above(Evas_Object *obj, Evas_Object *above); int evas_object_intercept_call_stack_below(Evas_Object *obj, Evas_Object *below); int evas_object_intercept_call_layer_set(Evas_Object *obj, int l); +void evas_object_grabs_cleanup(Evas_Object *obj); extern int _evas_alloc_error;