From 0c5a435128d6ec7cd43a72c62dc6bb9247d86242 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Tue, 8 Jul 2003 06:08:26 +0000 Subject: [PATCH] make deleting of grabs within a key callback "safe" SVN revision: 7117 --- legacy/evas/src/lib/canvas/evas_events.c | 70 ++++++++++++++++++++-- legacy/evas/src/lib/canvas/evas_key_grab.c | 40 ++++++++----- legacy/evas/src/lib/include/evas_private.h | 9 ++- 3 files changed, 97 insertions(+), 22 deletions(-) diff --git a/legacy/evas/src/lib/canvas/evas_events.c b/legacy/evas/src/lib/canvas/evas_events.c index 7b3acd6d6a..d2f9e0f356 100644 --- a/legacy/evas/src/lib/canvas/evas_events.c +++ b/legacy/evas/src/lib/canvas/evas_events.c @@ -515,7 +515,9 @@ evas_event_feed_key_down_data(Evas *e, const char *keyname, const void *data) if (e->events_frozen > 0) return; { Evas_Event_Key_Down ev; + int exclusive; + exclusive = 0; ev.keyname = (char *)keyname; ev.data = (void *)data; ev.modifiers = &(e->modifiers); @@ -524,11 +526,18 @@ evas_event_feed_key_down_data(Evas *e, const char *keyname, const void *data) { Evas_List *l; + e->walking_grabs++; for (l = e->grabs; l; l= l->next) { Evas_Key_Grab *g; g = l->data; + if (g->just_added) + { + g->just_added = 0; + continue; + } + if (g->delete_me) continue; if (((e->modifiers.mask & g->modifiers) || (g->modifiers == e->modifiers.mask)) && (!((e->modifiers.mask & g->not_modifiers) || @@ -537,11 +546,32 @@ evas_event_feed_key_down_data(Evas *e, const char *keyname, const void *data) { if (!e->events_frozen) evas_object_event_callback_call(g->object, EVAS_CALLBACK_KEY_DOWN, &ev); - if (g->exclusive) return; - } + if (g->exclusive) exclusive = 1; + } + } + e->walking_grabs--; + if (e->walking_grabs <= 0) + { + while (e->delete_grabs > 0) + { + Evas_List *l; + + e->delete_grabs--; + for (l = e->grabs; l; l= l->next) + { + Evas_Key_Grab *g; + + g = l->data; + if (g->delete_me) + { + evas_key_grab_free(g->object, g->keyname, g->modifiers, g->not_modifiers); + continue; + } + } + } } } - if (e->focused) + if ((e->focused) && (!exclusive)) { if (!e->events_frozen) evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev); @@ -565,7 +595,9 @@ evas_event_feed_key_up_data(Evas *e, const char *keyname, const void *data) if (e->events_frozen > 0) return; { Evas_Event_Key_Up ev; + int exclusive; + exclusive = 0; ev.keyname = (char *)keyname; ev.data = (void *)data; ev.modifiers = &(e->modifiers); @@ -574,11 +606,18 @@ evas_event_feed_key_up_data(Evas *e, const char *keyname, const void *data) { Evas_List *l; + e->walking_grabs++; for (l = e->grabs; l; l= l->next) { Evas_Key_Grab *g; g = l->data; + if (g->just_added) + { + g->just_added = 0; + continue; + } + if (g->delete_me) continue; if (((e->modifiers.mask & g->modifiers) || (g->modifiers == e->modifiers.mask)) && (!((e->modifiers.mask & g->not_modifiers) || @@ -587,11 +626,32 @@ evas_event_feed_key_up_data(Evas *e, const char *keyname, const void *data) { if (!e->events_frozen) evas_object_event_callback_call(g->object, EVAS_CALLBACK_KEY_UP, &ev); - if (g->exclusive) return; + if (g->exclusive) exclusive = 1; } } + e->walking_grabs--; + if (e->walking_grabs <= 0) + { + while (e->delete_grabs > 0) + { + Evas_List *l; + + e->delete_grabs--; + for (l = e->grabs; l; l= l->next) + { + Evas_Key_Grab *g; + + g = l->data; + if (g->delete_me) + { + evas_key_grab_free(g->object, g->keyname, g->modifiers, g->not_modifiers); + continue; + } + } + } + } } - if (e->focused) + if ((e->focused) && (!exclusive)) { if (!e->events_frozen) evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev); diff --git a/legacy/evas/src/lib/canvas/evas_key_grab.c b/legacy/evas/src/lib/canvas/evas_key_grab.c index 0e41336b5f..95970b9a41 100644 --- a/legacy/evas/src/lib/canvas/evas_key_grab.c +++ b/legacy/evas/src/lib/canvas/evas_key_grab.c @@ -9,7 +9,6 @@ /* modifiers/not_modifers they use */ static Evas_Key_Grab *evas_key_grab_new (Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive); -static void evas_key_grab_free (Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers); static Evas_Key_Grab *evas_key_grab_find (Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive); static Evas_Key_Grab * @@ -25,6 +24,8 @@ evas_key_grab_new(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modi g->not_modifiers = not_modifiers; g->exclusive = exclusive; g->keyname = strdup(keyname); + if (obj->layer->evas->walking_grabs) + g->just_added = 1; if (!g->keyname) { if (!evas_mem_free(strlen(keyname) + 1)) @@ -71,19 +72,6 @@ evas_key_grab_new(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modi return g; } -static void -evas_key_grab_free(Evas_Object *obj, const 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, 0); - 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, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive) { @@ -122,6 +110,19 @@ evas_object_grabs_cleanup(Evas_Object *obj) } } +void +evas_key_grab_free(Evas_Object *obj, const 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, 0); + if (!g) return; + g->object->grabs = evas_list_remove(g->object->grabs, g); + if (g->keyname) free(g->keyname); + free(g); +} + /* public calls */ /** @@ -168,5 +169,14 @@ evas_object_key_ungrab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask if (!keyname) return; g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, 0); if (!g) return; - evas_key_grab_free(g->object, keyname, modifiers, not_modifiers); + if (g->object->layer->evas->walking_grabs) + { + if (!g->delete_me) + { + g->object->layer->evas->delete_grabs++; + g->delete_me = 1; + } + } + else + evas_key_grab_free(g->object, keyname, modifiers, not_modifiers); } diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index 6150f9d579..4c592dcec5 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -160,6 +160,8 @@ struct _Evas_Key_Grab Evas_Modifier_Mask not_modifiers; Evas_Object *object; char exclusive : 1; + char just_added : 1; + char delete_me : 1; }; struct _Evas_Intercept_Func @@ -296,7 +298,9 @@ struct _Evas void *info; int info_magic; } engine; - + + int delete_grabs; + int walking_grabs; Evas_List *grabs; Evas_List *font_path; @@ -584,7 +588,8 @@ 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); - +void evas_key_grab_free(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers); + extern int _evas_alloc_error; #ifdef __cplusplus