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