From 8451b5cc08714f006d1b5a09e9e00aec4d6a9d2d Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Sun, 5 Jan 2003 12:55:37 +0000 Subject: [PATCH] key grabs are done... ok not as efficiently as i'd liek so having more than a dozen key grabs at any time may impact key event handling a little... oh yeah.. added to the api .. now theres a modifier mask and a not_mask. the not mas means "grab the key only if NONE of these modifiers are active and only if one or more of the mask modifiers are active). using this you can easily select allmodifiers, none, or a certain set of modifiers. if you need more than that put in multiple grabs then :) to just have that exact set of modifiers grabbed have not_mask be the inverse of mask. :) SVN revision: 6546 --- legacy/evas/src/lib/Evas.h | 4 +- legacy/evas/src/lib/canvas/Makefile.am | 1 + legacy/evas/src/lib/canvas/evas_events.c | 51 +++++- legacy/evas/src/lib/canvas/evas_key.c | 10 -- legacy/evas/src/lib/canvas/evas_key_grab.c | 158 ++++++++++++++++++ legacy/evas/src/lib/canvas/evas_object_main.c | 2 + legacy/evas/src/lib/include/evas_private.h | 23 ++- 7 files changed, 223 insertions(+), 26 deletions(-) create mode 100644 legacy/evas/src/lib/canvas/evas_key_grab.c 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;