svn update: 57457 (latest:57457)
[framework/uifw/evas.git] / src / lib / canvas / evas_key_grab.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 /* private calls */
5
6 /* FIXME: this is not optimal, but works. i should have a hash of keys per */
7 /* Evas and then a linked lists of grabs for that key and what */
8 /* modifiers/not_modifers they use */
9
10 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);
11 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);
12
13 static Evas_Key_Grab *
14 evas_key_grab_new(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive)
15 {
16    /* MEM OK */
17    Evas_Key_Grab *g;
18
19    g = evas_mem_calloc(sizeof(Evas_Key_Grab));
20    if (!g) return NULL;
21    g->object = obj;
22    g->modifiers = modifiers;
23    g->not_modifiers = not_modifiers;
24    g->exclusive = exclusive;
25    g->keyname = strdup(keyname);
26    if (obj->layer->evas->walking_grabs)
27      g->just_added = 1;
28    if (!g->keyname)
29      {
30         if (!evas_mem_free(strlen(keyname) + 1))
31           {
32              free(g);
33              return NULL;
34           }
35         g->keyname = strdup(keyname);
36         if (!g->keyname)
37           {
38              free(g);
39              return NULL;
40           }
41      }
42    g->object->grabs = eina_list_append(g->object->grabs, g);
43    if (eina_error_get())
44      {
45         MERR_BAD();
46         evas_mem_free(sizeof(Eina_List));
47         g->object->grabs = eina_list_append(g->object->grabs, g);
48         if (eina_error_get())
49           {
50              MERR_FATAL();
51              free(g->keyname);
52              free(g);
53              return NULL;
54           }
55      }
56    obj->layer->evas->grabs = eina_list_append(obj->layer->evas->grabs, g);
57    if (eina_error_get())
58      {
59         MERR_BAD();
60         evas_mem_free(sizeof(Eina_List));
61         obj->layer->evas->grabs = eina_list_append(obj->layer->evas->grabs, g);
62         if (eina_error_get())
63           {
64              MERR_FATAL();
65              g->object->grabs = eina_list_remove(g->object->grabs, g);
66              free(g->keyname);
67              free(g);
68              return NULL;
69           }
70      }
71    return g;
72 }
73
74 static Evas_Key_Grab *
75 evas_key_grab_find(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, int exclusive)
76 {
77    /* MEM OK */
78    Eina_List *l;
79    Evas_Key_Grab *g;
80
81    EINA_LIST_FOREACH(obj->layer->evas->grabs, l, g)
82      {
83         if ((g->modifiers == modifiers) &&
84             (g->not_modifiers == not_modifiers) &&
85             (!strcmp(g->keyname, keyname)))
86           {
87              if ((exclusive) ||  (obj == g->object)) return g;
88           }
89      }
90    return NULL;
91 }
92
93 /* local calls */
94
95 void
96 evas_object_grabs_cleanup(Evas_Object *obj)
97 {
98    if (obj->layer->evas->walking_grabs)
99      {
100         Eina_List *l;
101         Evas_Key_Grab *g;
102
103         EINA_LIST_FOREACH(obj->grabs, l, g)
104           g->delete_me = 1;
105      }
106    else
107      {
108         while (obj->grabs)
109           {
110              Evas_Key_Grab *g;
111
112              g = obj->grabs->data;
113              if (g->keyname) free(g->keyname);
114              free(g);
115              obj->layer->evas->grabs = eina_list_remove(obj->layer->evas->grabs, g);
116              obj->grabs = eina_list_remove(obj->grabs, g);
117           }
118      }
119 }
120
121 void
122 evas_key_grab_free(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
123 {
124    /* MEM OK */
125    Evas_Key_Grab *g;
126
127    g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, 0);
128    if (!g) return;
129    g->object->grabs = eina_list_remove(g->object->grabs, g);
130    obj->layer->evas->grabs = eina_list_remove(obj->layer->evas->grabs, g);
131    if (g->keyname) free(g->keyname);
132    free(g);
133 }
134
135 /* public calls */
136
137 /**
138  * Requests @p keyname key events be directed to @p obj.
139  *
140  * Key grabs allow an object to receive key events for specific key
141  * strokes even if another object has focus.  If the grab is
142  * non-exclusive then all objects that have grabs on the key will get
143  * the event, however if the grab is exclusive, no other object can
144  * get a grab on the key and only that object will get the event.
145  *
146  * @p keyname is a platform dependent symbolic name for the key
147  * pressed.  It is sometimes possible to convert the string to an
148  * ASCII value of the key, but not always for example the enter key
149  * may be returned as the string 'Enter'.
150  *
151  * Typical platforms are Linux frame buffer (Ecore_FB) and X server
152  * (Ecore_X) when using Evas with Ecore and Ecore_Evas.
153  *
154  * For a list of keynames for the Linux frame buffer, please refer to
155  * the Ecore_FB documentation.
156  *
157  * @p modifiers and @p not_modifiers are bit masks of all the
158  * modifiers that are required and not required respectively for the
159  * new grab.  Modifiers can be things such as shift and ctrl as well
160  * as user defigned types via evas_key_modifier_add.
161  *
162  * @see evas_object_key_ungrab
163  * @see evas_object_focus_set
164  * @see evas_object_focus_get
165  * @see evas_focus_get
166  * @see evas_key_modifier_add
167  *
168  * @param obj the object to direct @p keyname events to.
169  * @param keyname the key to request events for.
170  * @param modifiers a mask of modifiers that should be present to
171  * trigger the event.
172  * @param not_modifiers a mask of modifiers that should not be present
173  * to trigger the event.
174  * @param exclusive request that the @p obj is the only object
175  * receiving the @p keyname events.
176  * @return Boolean indicating whether the grab succeeded
177  */
178 EAPI Eina_Bool
179 evas_object_key_grab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive)
180 {
181    /* MEM OK */
182    Evas_Key_Grab *g;
183
184    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
185    return 0;
186    MAGIC_CHECK_END();
187    if (!keyname) return 0;
188    if (exclusive)
189      {
190         g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, exclusive);
191         if (g) return 0;
192      }
193    g = evas_key_grab_new(obj, keyname, modifiers, not_modifiers, exclusive);
194    if (!g) return 0;
195    return 1;
196 }
197
198 /**
199  * Request that the grab on @p obj be removed.
200  *
201  * Removes the grab on @p obj if @p keyname, @p modifiers, and @p not_modifiers
202  * match.
203  *
204  * @see evas_object_key_grab
205  * @see evas_object_focus_set
206  * @see evas_object_focus_get
207  * @see evas_focus_get
208  *
209  * @param obj the object that has an existing grab.
210  * @param keyname the key the grab is for.
211  * @param modifiers a mask of modifiers that should be present to
212  * trigger the event.
213  * @param not_modifiers a mask of modifiers that should not be present
214  * to trigger the event.
215  */
216 EAPI void
217 evas_object_key_ungrab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
218 {
219    /* MEM OK */
220    Evas_Key_Grab *g;
221
222    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
223    return;
224    MAGIC_CHECK_END();
225    if (!keyname) return;
226    g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, 0);
227    if (!g) return;
228    if (g->object->layer->evas->walking_grabs)
229      {
230         if (!g->delete_me)
231           {
232              g->object->layer->evas->delete_grabs++;
233              g->delete_me = 1;
234           }
235      }
236    else
237      evas_key_grab_free(g->object, keyname, modifiers, not_modifiers);
238 }