efl/src/lib/evas/canvas/evas_object_intercept.c

271 lines
11 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdarg.h>
#include "evas_common_private.h"
#include "evas_private.h"
/* local calls */
static void evas_object_intercept_init(Evas_Object *eo_obj);
static void evas_object_intercept_deinit(Evas_Object *eo_obj);
static void
evas_object_intercept_init(Evas_Object *eo_obj)
{
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
if (!obj->interceptors)
obj->interceptors = evas_mem_calloc(sizeof(Evas_Intercept_Func));
}
static void
evas_object_intercept_deinit(Evas_Object *eo_obj)
{
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
if (!obj->interceptors) return;
if ((obj->interceptors->show.func) ||
(obj->interceptors->hide.func) ||
(obj->interceptors->move.func) ||
(obj->interceptors->resize.func) ||
(obj->interceptors->raise.func) ||
(obj->interceptors->lower.func) ||
(obj->interceptors->stack_above.func) ||
(obj->interceptors->stack_below.func) ||
(obj->interceptors->layer_set.func) ||
(obj->interceptors->color_set.func) ||
(obj->interceptors->clip_set.func) ||
(obj->interceptors->clip_unset.func))
return;
free(obj->interceptors);
obj->interceptors = NULL;
}
/* private calls */
void
evas_object_intercept_cleanup(Evas_Object *eo_obj)
{
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
if (obj->interceptors) free(obj->interceptors);
}
#define COMMON_ARGS Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
#define UNPACK_ARG1(a) , a
#define UNPACK_ARG2(a, b) , a, b
#define UNPACK_ARG4(a, b, c, d) , a, b, c, d
#define EVAS_OBJECT_INTERCEPT_CALL(Type, Args, ...) \
static inline int evas_object_intercept_call_##Type Args \
{ \
if (!obj->interceptors) return 0; \
if (obj->interceptors->Type.intercepted) return 0; \
if (!obj->interceptors->Type.func) return 0; \
obj->interceptors->Type.intercepted = EINA_TRUE; \
obj->interceptors->Type.func(obj->interceptors->Type.data, eo_obj __VA_ARGS__); \
if (obj->interceptors) obj->interceptors->Type.intercepted = EINA_FALSE; \
return 1; \
}
EVAS_OBJECT_INTERCEPT_CALL(show, (COMMON_ARGS))
EVAS_OBJECT_INTERCEPT_CALL(hide, (COMMON_ARGS))
EVAS_OBJECT_INTERCEPT_CALL(raise, (COMMON_ARGS))
EVAS_OBJECT_INTERCEPT_CALL(lower, (COMMON_ARGS))
EVAS_OBJECT_INTERCEPT_CALL(clip_unset, (COMMON_ARGS))
EVAS_OBJECT_INTERCEPT_CALL(move, (COMMON_ARGS, int a, int b), UNPACK_ARG2(a, b))
EVAS_OBJECT_INTERCEPT_CALL(resize, (COMMON_ARGS, int a, int b), UNPACK_ARG2(a, b))
EVAS_OBJECT_INTERCEPT_CALL(stack_above, (COMMON_ARGS, Evas_Object *rel_to), UNPACK_ARG1(rel_to))
EVAS_OBJECT_INTERCEPT_CALL(stack_below, (COMMON_ARGS, Evas_Object *rel_to), UNPACK_ARG1(rel_to))
EVAS_OBJECT_INTERCEPT_CALL(layer_set, (COMMON_ARGS, int l), UNPACK_ARG1(l))
EVAS_OBJECT_INTERCEPT_CALL(focus_set, (COMMON_ARGS, int focus), UNPACK_ARG1(focus))
EVAS_OBJECT_INTERCEPT_CALL(color_set, (COMMON_ARGS, int r, int g, int b, int a), UNPACK_ARG4(r, g, b, a))
EVAS_OBJECT_INTERCEPT_CALL(clip_set, (COMMON_ARGS, Evas_Object *clip), UNPACK_ARG1(clip))
/* This is a legacy-only compatibility function.
* Made public for other parts of EFL (elm, ecore_evas).
*/
EWAPI Eina_Bool
_evas_object_intercept_call(Evas_Object *eo_obj, Evas_Object_Intercept_Cb_Type cb_type,
Eina_Bool internal, ...)
{
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Eina_Bool blocked = 0;
Evas_Object *eo_other;
int r, g, b, a, i, j;
va_list args;
EVAS_OBJECT_DATA_ALIVE_CHECK(obj, 1);
evas_object_async_block(obj);
va_start(args, internal);
switch (cb_type)
{
case EVAS_OBJECT_INTERCEPT_CB_VISIBLE:
i = !!va_arg(args, int);
if (i == obj->cur->visible) goto end_block;
if (!obj->interceptors) goto end_noblock;
if (i) blocked = evas_object_intercept_call_show(eo_obj, obj);
else blocked = evas_object_intercept_call_hide(eo_obj, obj);
break;
case EVAS_OBJECT_INTERCEPT_CB_MOVE:
if (obj->doing.in_move > 0)
{
WRN("evas_object_move() called on object %p (%s) in the middle "
"of moving the same object", eo_obj, efl_class_name_get(eo_obj));
goto end_block;
}
i = va_arg(args, int);
j = va_arg(args, int);
if ((obj->cur->geometry.x == i) && (obj->cur->geometry.y == j)) goto end_block;
if (!obj->interceptors) goto end_noblock;
blocked = evas_object_intercept_call_move(eo_obj, obj, i, j);
break;
case EVAS_OBJECT_INTERCEPT_CB_RESIZE:
i = va_arg(args, int);
j = va_arg(args, int);
if (!internal)
{
if (_efl_canvas_object_efl_gfx_size_set_block(eo_obj, obj, i, j))
goto end_block;
}
if (!obj->interceptors) goto end_noblock;
blocked = evas_object_intercept_call_resize(eo_obj, obj, i, j);
break;
case EVAS_OBJECT_INTERCEPT_CB_RAISE:
if (!obj->interceptors) goto end_noblock;
blocked = evas_object_intercept_call_raise(eo_obj, obj);
break;
case EVAS_OBJECT_INTERCEPT_CB_LOWER:
if (!obj->interceptors) goto end_noblock;
blocked = evas_object_intercept_call_lower(eo_obj, obj);
break;
case EVAS_OBJECT_INTERCEPT_CB_STACK_ABOVE:
if (!obj->interceptors) goto end_noblock;
eo_other = va_arg(args, Evas_Object *);
blocked = evas_object_intercept_call_stack_above(eo_obj, obj, eo_other);
break;
case EVAS_OBJECT_INTERCEPT_CB_STACK_BELOW:
if (!obj->interceptors) goto end_noblock;
eo_other = va_arg(args, Evas_Object *);
blocked = evas_object_intercept_call_stack_below(eo_obj, obj, eo_other);
break;
case EVAS_OBJECT_INTERCEPT_CB_LAYER_SET:
if (!obj->interceptors) goto end_noblock;
i = va_arg(args, int);
blocked = evas_object_intercept_call_layer_set(eo_obj, obj, i);
break;
case EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET:
if (!obj->interceptors) goto end_noblock;
i = va_arg(args, int);
blocked = evas_object_intercept_call_focus_set(eo_obj, obj, !!i);
break;
case EVAS_OBJECT_INTERCEPT_CB_COLOR_SET:
if (!obj->interceptors) goto end_noblock;
r = va_arg(args, int);
g = va_arg(args, int);
b = va_arg(args, int);
a = va_arg(args, int);
blocked = evas_object_intercept_call_color_set(eo_obj, obj, r, g, b, a);
break;
case EVAS_OBJECT_INTERCEPT_CB_CLIP_SET:
eo_other = va_arg(args, Evas_Object *);
if (eo_other)
{
if (!internal)
{
if (_efl_canvas_object_clip_set_block(eo_obj, obj, eo_other, NULL))
goto end_block;
}
if (!obj->interceptors) goto end_noblock;
blocked = evas_object_intercept_call_clip_set(eo_obj, obj, eo_other);
break;
}
// else: fallthrough to unset
case EVAS_OBJECT_INTERCEPT_CB_CLIP_UNSET:
if (!internal)
{
if (_efl_canvas_object_clip_unset_block(eo_obj, obj))
goto end_block;
}
if (!obj->interceptors) goto end_noblock;
blocked = evas_object_intercept_call_clip_unset(eo_obj, obj);
break;
}
va_end(args);
return blocked;
end_block:
va_end(args);
return 1;
end_noblock:
va_end(args);
return 0;
}
/* public calls */
#define EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Up_Type, Lower_Type) \
EAPI void \
evas_object_intercept_##Lower_Type##_callback_add(Evas_Object *eo_obj,\
Evas_Object_Intercept_##Up_Type##_Cb func, const void *data) \
{ \
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ); \
return; \
MAGIC_CHECK_END(); \
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); \
if (!func) return; \
evas_object_intercept_init(eo_obj); \
if (!obj->interceptors) return; \
obj->interceptors->Lower_Type.func = func; \
obj->interceptors->Lower_Type.data = (void *)data; \
} \
\
EAPI void * \
evas_object_intercept_##Lower_Type##_callback_del(Evas_Object *eo_obj,\
Evas_Object_Intercept_##Up_Type##_Cb func) \
{ \
void *data; \
\
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ); \
return NULL; \
MAGIC_CHECK_END(); \
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); \
if (!func) return NULL; \
if (!obj->interceptors) return NULL; \
obj->interceptors->Lower_Type.func = NULL; \
data = obj->interceptors->Lower_Type.data; \
obj->interceptors->Lower_Type.data = NULL; \
evas_object_intercept_deinit(eo_obj); \
return data; \
}
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Show, show);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Hide, hide);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Move, move);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Resize, resize);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Raise, raise);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Lower, lower);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Stack_Above, stack_above);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Stack_Below, stack_below);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Layer_Set, layer_set);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Focus_Set, focus_set);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Color_Set, color_set);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Clip_Set, clip_set);
EVAS_OBJECT_INTERCEPT_CALLBACK_DEFINE(Clip_Unset, clip_unset);