239 lines
6.7 KiB
C
239 lines
6.7 KiB
C
#include "evas_common.h"
|
|
#include "evas_private.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, 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 *
|
|
evas_key_grab_new(Evas_Object *obj, const 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 NULL;
|
|
g->object = obj;
|
|
g->modifiers = modifiers;
|
|
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))
|
|
{
|
|
free(g);
|
|
return NULL;
|
|
}
|
|
g->keyname = strdup(keyname);
|
|
if (!g->keyname)
|
|
{
|
|
free(g);
|
|
return NULL;
|
|
}
|
|
}
|
|
g->object->grabs = eina_list_append(g->object->grabs, g);
|
|
if (eina_error_get())
|
|
{
|
|
MERR_BAD();
|
|
evas_mem_free(sizeof(Eina_List));
|
|
g->object->grabs = eina_list_append(g->object->grabs, g);
|
|
if (eina_error_get())
|
|
{
|
|
MERR_FATAL();
|
|
free(g->keyname);
|
|
free(g);
|
|
return NULL;
|
|
}
|
|
}
|
|
obj->layer->evas->grabs = eina_list_append(obj->layer->evas->grabs, g);
|
|
if (eina_error_get())
|
|
{
|
|
MERR_BAD();
|
|
evas_mem_free(sizeof(Eina_List));
|
|
obj->layer->evas->grabs = eina_list_append(obj->layer->evas->grabs, g);
|
|
if (eina_error_get())
|
|
{
|
|
MERR_FATAL();
|
|
g->object->grabs = eina_list_remove(g->object->grabs, g);
|
|
free(g->keyname);
|
|
free(g);
|
|
return NULL;
|
|
}
|
|
}
|
|
return 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)
|
|
{
|
|
/* MEM OK */
|
|
Eina_List *l;
|
|
Evas_Key_Grab *g;
|
|
|
|
EINA_LIST_FOREACH(obj->layer->evas->grabs, l, g)
|
|
{
|
|
if ((g->modifiers == modifiers) &&
|
|
(g->not_modifiers == not_modifiers) &&
|
|
(!strcmp(g->keyname, keyname)))
|
|
{
|
|
if ((exclusive) || (obj == g->object)) return g;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* local calls */
|
|
|
|
void
|
|
evas_object_grabs_cleanup(Evas_Object *obj)
|
|
{
|
|
if (obj->layer->evas->walking_grabs)
|
|
{
|
|
Eina_List *l;
|
|
Evas_Key_Grab *g;
|
|
|
|
EINA_LIST_FOREACH(obj->grabs, l, g)
|
|
g->delete_me = 1;
|
|
}
|
|
else
|
|
{
|
|
while (obj->grabs)
|
|
{
|
|
Evas_Key_Grab *g;
|
|
|
|
g = obj->grabs->data;
|
|
if (g->keyname) free(g->keyname);
|
|
free(g);
|
|
obj->layer->evas->grabs = eina_list_remove(obj->layer->evas->grabs, g);
|
|
obj->grabs = eina_list_remove(obj->grabs, g);
|
|
}
|
|
}
|
|
}
|
|
|
|
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 = eina_list_remove(g->object->grabs, g);
|
|
obj->layer->evas->grabs = eina_list_remove(obj->layer->evas->grabs, g);
|
|
if (g->keyname) free(g->keyname);
|
|
free(g);
|
|
}
|
|
|
|
/* public calls */
|
|
|
|
/**
|
|
* Requests @p keyname key events be directed to @p obj.
|
|
*
|
|
* Key grabs allow an object to receive key events for specific key
|
|
* strokes even if another object has focus. If the grab is
|
|
* non-exclusive then all objects that have grabs on the key will get
|
|
* the event, however if the grab is exclusive, no other object can
|
|
* get a grab on the key and only that object will get the event.
|
|
*
|
|
* @p keyname is a platform dependent symbolic name for the key
|
|
* pressed. It is sometimes possible to convert the string to an
|
|
* ASCII value of the key, but not always for example the enter key
|
|
* may be returned as the string 'Enter'.
|
|
*
|
|
* Typical platforms are Linux frame buffer (Ecore_FB) and X server
|
|
* (Ecore_X) when using Evas with Ecore and Ecore_Evas.
|
|
*
|
|
* For a list of keynames for the Linux frame buffer, please refer to
|
|
* the Ecore_FB documentation.
|
|
*
|
|
* @p modifiers and @p not_modifiers are bit masks of all the
|
|
* modifiers that are required and not required respectively for the
|
|
* new grab. Modifiers can be things such as shift and ctrl as well
|
|
* as user defigned types via evas_key_modifier_add.
|
|
*
|
|
* @see evas_object_key_ungrab
|
|
* @see evas_object_focus_set
|
|
* @see evas_object_focus_get
|
|
* @see evas_focus_get
|
|
* @see evas_key_modifier_add
|
|
*
|
|
* @param obj the object to direct @p keyname events to.
|
|
* @param keyname the key to request events for.
|
|
* @param modifiers a mask of modifiers that should be present to
|
|
* trigger the event.
|
|
* @param not_modifiers a mask of modifiers that should not be present
|
|
* to trigger the event.
|
|
* @param exclusive request that the @p obj is the only object
|
|
* receiving the @p keyname events.
|
|
* @return Boolean indicating whether the grab succeeded
|
|
*/
|
|
EAPI Eina_Bool
|
|
evas_object_key_grab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive)
|
|
{
|
|
/* MEM OK */
|
|
Evas_Key_Grab *g;
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
|
return 0;
|
|
MAGIC_CHECK_END();
|
|
if (!keyname) return 0;
|
|
if (exclusive)
|
|
{
|
|
g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, exclusive);
|
|
if (g) return 0;
|
|
}
|
|
g = evas_key_grab_new(obj, keyname, modifiers, not_modifiers, exclusive);
|
|
if (!g) return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Request that the grab on @p obj be removed.
|
|
*
|
|
* Removes the grab on @p obj if @p keyname, @p modifiers, and @p not_modifiers
|
|
* match.
|
|
*
|
|
* @see evas_object_key_grab
|
|
* @see evas_object_focus_set
|
|
* @see evas_object_focus_get
|
|
* @see evas_focus_get
|
|
*
|
|
* @param obj the object that has an existing grab.
|
|
* @param keyname the key the grab is for.
|
|
* @param modifiers a mask of modifiers that should be present to
|
|
* trigger the event.
|
|
* @param not_modifiers a mask of modifiers that should not be present
|
|
* to trigger the event.
|
|
*/
|
|
EAPI void
|
|
evas_object_key_ungrab(Evas_Object *obj, const 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();
|
|
if (!keyname) return;
|
|
g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, 0);
|
|
if (!g) return;
|
|
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);
|
|
}
|