make deleting of grabs within a key callback "safe"

SVN revision: 7117
This commit is contained in:
Carsten Haitzler 2003-07-08 06:08:26 +00:00
parent 0656623f54
commit 0c5a435128
3 changed files with 97 additions and 22 deletions

View File

@ -515,7 +515,9 @@ evas_event_feed_key_down_data(Evas *e, const char *keyname, const void *data)
if (e->events_frozen > 0) return; if (e->events_frozen > 0) return;
{ {
Evas_Event_Key_Down ev; Evas_Event_Key_Down ev;
int exclusive;
exclusive = 0;
ev.keyname = (char *)keyname; ev.keyname = (char *)keyname;
ev.data = (void *)data; ev.data = (void *)data;
ev.modifiers = &(e->modifiers); 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; Evas_List *l;
e->walking_grabs++;
for (l = e->grabs; l; l= l->next) for (l = e->grabs; l; l= l->next)
{ {
Evas_Key_Grab *g; Evas_Key_Grab *g;
g = l->data; g = l->data;
if (g->just_added)
{
g->just_added = 0;
continue;
}
if (g->delete_me) continue;
if (((e->modifiers.mask & g->modifiers) || if (((e->modifiers.mask & g->modifiers) ||
(g->modifiers == e->modifiers.mask)) && (g->modifiers == e->modifiers.mask)) &&
(!((e->modifiers.mask & g->not_modifiers) || (!((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) if (!e->events_frozen)
evas_object_event_callback_call(g->object, EVAS_CALLBACK_KEY_DOWN, &ev); 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) if (!e->events_frozen)
evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev); 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; if (e->events_frozen > 0) return;
{ {
Evas_Event_Key_Up ev; Evas_Event_Key_Up ev;
int exclusive;
exclusive = 0;
ev.keyname = (char *)keyname; ev.keyname = (char *)keyname;
ev.data = (void *)data; ev.data = (void *)data;
ev.modifiers = &(e->modifiers); 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; Evas_List *l;
e->walking_grabs++;
for (l = e->grabs; l; l= l->next) for (l = e->grabs; l; l= l->next)
{ {
Evas_Key_Grab *g; Evas_Key_Grab *g;
g = l->data; g = l->data;
if (g->just_added)
{
g->just_added = 0;
continue;
}
if (g->delete_me) continue;
if (((e->modifiers.mask & g->modifiers) || if (((e->modifiers.mask & g->modifiers) ||
(g->modifiers == e->modifiers.mask)) && (g->modifiers == e->modifiers.mask)) &&
(!((e->modifiers.mask & g->not_modifiers) || (!((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) if (!e->events_frozen)
evas_object_event_callback_call(g->object, EVAS_CALLBACK_KEY_UP, &ev); 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) if (!e->events_frozen)
evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev); evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev);

View File

@ -9,7 +9,6 @@
/* modifiers/not_modifers they use */ /* 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 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 *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 * 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->not_modifiers = not_modifiers;
g->exclusive = exclusive; g->exclusive = exclusive;
g->keyname = strdup(keyname); g->keyname = strdup(keyname);
if (obj->layer->evas->walking_grabs)
g->just_added = 1;
if (!g->keyname) if (!g->keyname)
{ {
if (!evas_mem_free(strlen(keyname) + 1)) 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; 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 * 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) 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 */ /* public calls */
/** /**
@ -168,5 +169,14 @@ evas_object_key_ungrab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask
if (!keyname) return; if (!keyname) return;
g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, 0); g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, 0);
if (!g) return; 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);
} }

View File

@ -160,6 +160,8 @@ struct _Evas_Key_Grab
Evas_Modifier_Mask not_modifiers; Evas_Modifier_Mask not_modifiers;
Evas_Object *object; Evas_Object *object;
char exclusive : 1; char exclusive : 1;
char just_added : 1;
char delete_me : 1;
}; };
struct _Evas_Intercept_Func struct _Evas_Intercept_Func
@ -296,7 +298,9 @@ struct _Evas
void *info; void *info;
int info_magic; int info_magic;
} engine; } engine;
int delete_grabs;
int walking_grabs;
Evas_List *grabs; Evas_List *grabs;
Evas_List *font_path; 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_stack_below(Evas_Object *obj, Evas_Object *below);
int evas_object_intercept_call_layer_set(Evas_Object *obj, int l); int evas_object_intercept_call_layer_set(Evas_Object *obj, int l);
void evas_object_grabs_cleanup(Evas_Object *obj); 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; extern int _evas_alloc_error;
#ifdef __cplusplus #ifdef __cplusplus