1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include <stdarg.h>
6 
7 #include "evas_common_private.h"
8 #include "evas_private.h"
9 
10 /* local calls */
11 
12 static void evas_object_intercept_init(Evas_Object_Protected_Data *obj);
13 static void evas_object_intercept_deinit(Evas_Object_Protected_Data *obj);
14 
15 static void
evas_object_intercept_init(Evas_Object_Protected_Data * obj)16 evas_object_intercept_init(Evas_Object_Protected_Data *obj)
17 {
18    if (!obj) return;
19    if (!obj->interceptors)
20      obj->interceptors = calloc(1, sizeof(Evas_Intercept_Func));
21 }
22 
23 static void
evas_object_intercept_deinit(Evas_Object_Protected_Data * obj)24 evas_object_intercept_deinit(Evas_Object_Protected_Data *obj)
25 {
26    if (!obj || !obj->interceptors) return;
27    if ((obj->interceptors->show.func) ||
28        (obj->interceptors->hide.func) ||
29        (obj->interceptors->move.func) ||
30        (obj->interceptors->resize.func) ||
31        (obj->interceptors->raise.func) ||
32        (obj->interceptors->lower.func) ||
33        (obj->interceptors->stack_above.func) ||
34        (obj->interceptors->stack_below.func) ||
35        (obj->interceptors->layer_set.func) ||
36        (obj->interceptors->color_set.func) ||
37        (obj->interceptors->clip_set.func) ||
38        (obj->interceptors->clip_unset.func))
39      return;
40    free(obj->interceptors);
41    obj->interceptors = NULL;
42 }
43 
44 /* private calls */
45 
46 void
evas_object_intercept_cleanup(Evas_Object * eo_obj)47 evas_object_intercept_cleanup(Evas_Object *eo_obj)
48 {
49    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
50    if (!obj) return;
51    if (obj->interceptors) free(obj->interceptors);
52 }
53 
54 #define COMMON_ARGS Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
55 #define UNPACK_ARG1(a) , a
56 #define UNPACK_ARG2(a, b) , a, b
57 #define UNPACK_ARG4(a, b, c, d) , a, b, c, d
58 
59 #define EVAS_OBJECT_INTERCEPT_CALL(Type, Args, ...) \
60   static inline int evas_object_intercept_call_##Type Args \
61   { \
62      if (!obj->interceptors) return 0; \
63      if (obj->interceptors->Type.intercepted) return 0; \
64      if (!obj->interceptors->Type.func) return 0; \
65      obj->interceptors->Type.intercepted = EINA_TRUE; \
66      obj->interceptors->Type.func(obj->interceptors->Type.data, eo_obj __VA_ARGS__); \
67      if (obj->interceptors) obj->interceptors->Type.intercepted = EINA_FALSE; \
68      return 1; \
69   }
70 
71 EVAS_OBJECT_INTERCEPT_CALL(show,        (COMMON_ARGS))
72 EVAS_OBJECT_INTERCEPT_CALL(hide,        (COMMON_ARGS))
73 EVAS_OBJECT_INTERCEPT_CALL(raise,       (COMMON_ARGS))
74 EVAS_OBJECT_INTERCEPT_CALL(lower,       (COMMON_ARGS))
75 EVAS_OBJECT_INTERCEPT_CALL(clip_unset,  (COMMON_ARGS))
76 EVAS_OBJECT_INTERCEPT_CALL(move,        (COMMON_ARGS, int a, int b), UNPACK_ARG2(a, b))
77 EVAS_OBJECT_INTERCEPT_CALL(resize,      (COMMON_ARGS, int a, int b), UNPACK_ARG2(a, b))
78 EVAS_OBJECT_INTERCEPT_CALL(stack_above, (COMMON_ARGS, Evas_Object *rel_to), UNPACK_ARG1(rel_to))
79 EVAS_OBJECT_INTERCEPT_CALL(stack_below, (COMMON_ARGS, Evas_Object *rel_to), UNPACK_ARG1(rel_to))
80 EVAS_OBJECT_INTERCEPT_CALL(layer_set,   (COMMON_ARGS, int l), UNPACK_ARG1(l))
81 EVAS_OBJECT_INTERCEPT_CALL(focus_set,   (COMMON_ARGS, int focus), UNPACK_ARG1(focus))
82 EVAS_OBJECT_INTERCEPT_CALL(device_focus_set,   (COMMON_ARGS, int focus, Eo *seat), UNPACK_ARG2(focus, seat))
83 EVAS_OBJECT_INTERCEPT_CALL(color_set,   (COMMON_ARGS, int r, int g, int b, int a), UNPACK_ARG4(r, g, b, a))
84 EVAS_OBJECT_INTERCEPT_CALL(clip_set,    (COMMON_ARGS, Evas_Object *clip), UNPACK_ARG1(clip))
85 
86 static Eina_Bool
_evas_object_intercept_call_internal(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,Evas_Object_Intercept_Cb_Type cb_type,int internal,va_list args)87 _evas_object_intercept_call_internal(Evas_Object *eo_obj,
88                                      Evas_Object_Protected_Data *obj,
89                                      Evas_Object_Intercept_Cb_Type cb_type,
90                                      int internal, va_list args)
91 {
92    Eina_Bool blocked = 0;
93    Evas_Object *eo_other;
94    int r, g, b, a, i, j;
95    Eo *seat;
96 
97    evas_object_async_block(obj);
98 
99    switch (cb_type)
100      {
101       case EVAS_OBJECT_INTERCEPT_CB_VISIBLE:
102         i = !!va_arg(args, int);
103         if (!obj->legacy.visible_set) obj->legacy.visible_set = 1;
104         if (i == obj->cur->visible)
105           {
106              /* If show is called during hide animation is running, then the
107               * current hide animation is cancelled and show operation is
108               * proceeded. */
109              if ((!obj->anim_player) || (!efl_player_playing_get(obj->anim_player)))
110                return 1;
111           }
112         if (!obj->interceptors) return 0;
113         if (i) blocked = evas_object_intercept_call_show(eo_obj, obj);
114         else blocked = evas_object_intercept_call_hide(eo_obj, obj);
115         break;
116 
117       case EVAS_OBJECT_INTERCEPT_CB_MOVE:
118         if (obj->doing.in_move > 0)
119           {
120              WRN("evas_object_move() called on object %p (%s) in the middle "
121                  "of moving the same object", eo_obj, efl_class_name_get(eo_obj));
122              return 1;
123           }
124         i = va_arg(args, int);
125         j = va_arg(args, int);
126         if (obj->interceptors)
127           blocked = evas_object_intercept_call_move(eo_obj, obj, i, j);
128         if (!blocked && (obj->cur->geometry.x == i) && (obj->cur->geometry.y == j))
129           blocked = 1;
130         break;
131 
132       case EVAS_OBJECT_INTERCEPT_CB_RESIZE:
133         i = va_arg(args, int);
134         j = va_arg(args, int);
135         if (obj->interceptors)
136           blocked = evas_object_intercept_call_resize(eo_obj, obj, i, j);
137         if (!blocked && _efl_canvas_object_efl_gfx_entity_size_set_block(eo_obj, obj, i, j, internal))
138           blocked = 1;
139         break;
140 
141       case EVAS_OBJECT_INTERCEPT_CB_RAISE:
142         if (!obj->interceptors) return 0;
143         blocked = evas_object_intercept_call_raise(eo_obj, obj);
144         break;
145 
146       case EVAS_OBJECT_INTERCEPT_CB_LOWER:
147         if (!obj->interceptors) return 0;
148         blocked = evas_object_intercept_call_lower(eo_obj, obj);
149         break;
150 
151       case EVAS_OBJECT_INTERCEPT_CB_STACK_ABOVE:
152         if (!obj->interceptors) return 0;
153         eo_other = va_arg(args, Evas_Object *);
154         blocked = evas_object_intercept_call_stack_above(eo_obj, obj, eo_other);
155         break;
156 
157       case EVAS_OBJECT_INTERCEPT_CB_STACK_BELOW:
158         if (!obj->interceptors) return 0;
159         eo_other = va_arg(args, Evas_Object *);
160         blocked = evas_object_intercept_call_stack_below(eo_obj, obj, eo_other);
161         break;
162 
163       case EVAS_OBJECT_INTERCEPT_CB_LAYER_SET:
164         if (!obj->interceptors) return 0;
165         i = va_arg(args, int);
166         blocked = evas_object_intercept_call_layer_set(eo_obj, obj, i);
167         break;
168 
169       case EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET:
170         if (!obj->interceptors) return 0;
171         i = va_arg(args, int);
172         blocked = evas_object_intercept_call_focus_set(eo_obj, obj, !!i);
173         break;
174 
175       case EVAS_OBJECT_INTERCEPT_CB_DEVICE_FOCUS_SET:
176         if (!obj->interceptors) return 0;
177         i = va_arg(args, int);
178         seat = va_arg(args, Eo*);
179         blocked = evas_object_intercept_call_device_focus_set(eo_obj, obj, !!i, seat);
180         break;
181 
182       case EVAS_OBJECT_INTERCEPT_CB_COLOR_SET:
183         if (!obj->interceptors) return 0;
184         r = va_arg(args, int);
185         g = va_arg(args, int);
186         b = va_arg(args, int);
187         a = va_arg(args, int);
188         blocked = evas_object_intercept_call_color_set(eo_obj, obj, r, g, b, a);
189         break;
190 
191       case EVAS_OBJECT_INTERCEPT_CB_CLIP_SET:
192         eo_other = va_arg(args, Evas_Object *);
193         if (eo_other)
194           {
195              if (!internal)
196                {
197                   if (_efl_canvas_object_clipper_set_block(eo_obj, obj, eo_other, NULL))
198                     return 1;
199                }
200              if (!obj->interceptors) return 0;
201              blocked = evas_object_intercept_call_clip_set(eo_obj, obj, eo_other);
202           }
203         else
204           {
205              if (!internal)
206                {
207                   if (_efl_canvas_object_clipper_unset_block(eo_obj, obj))
208                     return 1;
209                }
210              if (!obj->interceptors) return 0;
211              blocked = evas_object_intercept_call_clip_unset(eo_obj, obj);
212           }
213         break;
214      }
215 
216    return blocked;
217 }
218 
219 /* This is a legacy-only compatibility function.
220  * Made public for other parts of EFL (elm, ecore_evas).
221  */
222 EWAPI Eina_Bool
_evas_object_intercept_call(Evas_Object * eo_obj,Evas_Object_Intercept_Cb_Type cb_type,int internal,...)223 _evas_object_intercept_call(Evas_Object *eo_obj, Evas_Object_Intercept_Cb_Type cb_type,
224                             int internal, ...)
225 {
226    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
227    Eina_Bool ret;
228    va_list args;
229 
230    EVAS_OBJECT_DATA_ALIVE_CHECK(obj, 1);
231 
232    va_start(args, internal);
233    ret = _evas_object_intercept_call_internal(eo_obj, obj, cb_type, internal, args);
234    va_end(args);
235 
236    return ret;
237 }
238 
239 Eina_Bool
_evas_object_intercept_call_evas(Evas_Object_Protected_Data * obj,Evas_Object_Intercept_Cb_Type cb_type,int internal,...)240 _evas_object_intercept_call_evas(Evas_Object_Protected_Data *obj,
241                                  Evas_Object_Intercept_Cb_Type cb_type,
242                                  int internal, ...)
243 {
244    Eina_Bool ret;
245    va_list args;
246 
247    EVAS_OBJECT_DATA_ALIVE_CHECK(obj, 1);
248 
249    va_start(args, internal);
250    ret = _evas_object_intercept_call_internal(obj->object, obj, cb_type, internal, args);
251    va_end(args);
252 
253    return ret;
254 }
255 
256 /* public calls */
257 
258 #define EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Up_Type, Lower_Type)      \
259   EAPI void                                                             \
260   evas_object_intercept_##Lower_Type##_callback_add(Evas_Object *eo_obj,\
261                                                     Evas_Object_Intercept_##Up_Type##_Cb func, const void *data) \
262   {                                                                     \
263      MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);                       \
264      return;                                                            \
265      MAGIC_CHECK_END();                                                 \
266      Evas_Object_Protected_Data *obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); \
267      if ((!obj) || (!func)) return;                                     \
268      evas_object_intercept_init(obj);                                   \
269      if (!obj->interceptors) return;                                    \
270      obj->interceptors->Lower_Type.func = func;                         \
271      obj->interceptors->Lower_Type.data = (void *)data;                 \
272   }                                                                     \
273                                                                         \
274   EAPI void *                                                           \
275   evas_object_intercept_##Lower_Type##_callback_del(Evas_Object *eo_obj,\
276                                                     Evas_Object_Intercept_##Up_Type##_Cb func) \
277   {                                                                     \
278      void *data;                                                        \
279                                                                         \
280      MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);                       \
281      return NULL;                                                       \
282      MAGIC_CHECK_END();                                                 \
283      Evas_Object_Protected_Data *obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); \
284      if ((!obj) || (!func)) return NULL;                                \
285      if (!obj->interceptors) return NULL;                               \
286      obj->interceptors->Lower_Type.func = NULL;                         \
287      data = obj->interceptors->Lower_Type.data;                         \
288      obj->interceptors->Lower_Type.data = NULL;                         \
289      evas_object_intercept_deinit(obj);                                 \
290      return data;                                                       \
291   }
292 
293 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Show, show);
294 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Hide, hide);
295 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Move, move);
296 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Resize, resize);
297 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Raise, raise);
298 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Lower, lower);
299 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Stack_Above, stack_above);
300 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Stack_Below, stack_below);
301 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Layer_Set, layer_set);
302 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Focus_Set, focus_set);
303 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Device_Focus_Set, device_focus_set);
304 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Color_Set, color_set);
305 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Clip_Set, clip_set);
306 EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Clip_Unset, clip_unset);
307