From 4921d26fc8efa2acdf424ce47075ecb4ccacaaa4 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 16 Jun 2017 15:03:09 -0400 Subject: [PATCH] evas: add seat-based focus interceptor @feature --- src/lib/evas/Evas_Legacy.h | 49 +++++++++++++++++++++ src/lib/evas/canvas/evas_focus.c | 43 +++++++++++++++--- src/lib/evas/canvas/evas_object_intercept.c | 10 +++++ src/lib/evas/include/evas_private.h | 5 +++ 4 files changed, 100 insertions(+), 7 deletions(-) diff --git a/src/lib/evas/Evas_Legacy.h b/src/lib/evas/Evas_Legacy.h index ac6c429ce4..3fd1fcb02a 100644 --- a/src/lib/evas/Evas_Legacy.h +++ b/src/lib/evas/Evas_Legacy.h @@ -2765,6 +2765,21 @@ typedef void (*Evas_Object_Intercept_Layer_Set_Cb)(void *data, Evas_Object *obj, */ typedef void (*Evas_Object_Intercept_Focus_Set_Cb)(void *data, Evas_Object *obj, Eina_Bool focus); +/** + * Function signature for the focus set event of an evas object with seat info + * + * @param data the pointer passed through the callback. + * @param obj the object being focused + * @param focus the focus value, EINA_TRUE if the object is focused, EINA_FALSE otherwise + * @param seat the seat for which focus is being set + * + * @see evas_object_intercept_device_focus_set_callback_add() + * @see evas_object_intercept_device_focus_set_callback_del() + * + * @since 1.20 + */ +typedef void (*Evas_Object_Intercept_Device_Focus_Set_Cb)(void *data, Evas_Object *obj, Eina_Bool focus, Eo *seat); + /** * Function signature for the color set event of an evas object * @@ -3183,6 +3198,39 @@ EAPI void evas_object_intercept_focus_set_callback_add(Evas_Object *obj, Evas_O */ EAPI void *evas_object_intercept_focus_set_callback_del(Evas_Object *obj, Evas_Object_Intercept_Focus_Set_Cb func) EINA_ARG_NONNULL(1, 2); +/** + * Set the callback function that intercepts a focus set event of an object. + * + * @param obj The given canvas object pointer. + * @param func The given function to be the callback function. + * @param data The data passed to the callback function. + * + * This function sets a callback function to intercepts a focus set event + * of a canvas object and provides seat info. + * + * @see evas_object_intercept_device_focus_set_callback_del(). + * + * @since 1.20 + * + */ +EAPI void evas_object_intercept_device_focus_set_callback_add(Evas_Object *obj, Evas_Object_Intercept_Device_Focus_Set_Cb func, const void *data) EINA_ARG_NONNULL(1, 2); + +/** + * Unset the callback function that intercepts a focus set event of an object. + * + * @param obj The given canvas object pointer. + * @param func The given callback function. + * + * This function sets a callback function to intercepts a focus set event + * of a canvas object and provides seat info. + * + * @see evas_object_intercept_device_focus_set_callback_add(). + * + * @since 1.20 + * + */ +EAPI void *evas_object_intercept_device_focus_set_callback_del(Evas_Object *obj, Evas_Object_Intercept_Device_Focus_Set_Cb func) EINA_ARG_NONNULL(1, 2); + /* Internal APIs for legacy compatibility */ #ifdef EFL_CANVAS_OBJECT_PROTECTED @@ -3199,6 +3247,7 @@ enum _Evas_Object_Intercept_Cb_Type EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET, EVAS_OBJECT_INTERCEPT_CB_COLOR_SET, EVAS_OBJECT_INTERCEPT_CB_CLIP_SET, + EVAS_OBJECT_INTERCEPT_CB_DEVICE_FOCUS_SET, }; typedef enum _Evas_Object_Intercept_Cb_Type Evas_Object_Intercept_Cb_Type; diff --git a/src/lib/evas/canvas/evas_focus.c b/src/lib/evas/canvas/evas_focus.c index 6ea934a8cd..2dd137d19e 100644 --- a/src/lib/evas/canvas/evas_focus.c +++ b/src/lib/evas/canvas/evas_focus.c @@ -128,12 +128,14 @@ _efl_canvas_object_seat_focus_del(Eo *eo_obj, { Eina_List *l; Efl_Input_Device *dev; + Eo *default_seat; MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ); return EINA_FALSE; MAGIC_CHECK_END(); - if (!seat) seat = _default_seat_get(eo_obj); + if (seat) default_seat = _default_seat_get(eo_obj); + else default_seat = seat = _default_seat_get(eo_obj); if ((!seat) && obj->layer) { @@ -145,8 +147,21 @@ _efl_canvas_object_seat_focus_del(Eo *eo_obj, { if (dev != seat) continue; - if (_evas_object_intercept_call_evas(obj, EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET, - 1, EINA_FALSE)) + if (obj->interceptors && obj->interceptors->focus_set.func && obj->interceptors->device_focus_set.func) + { + CRI("Your object is trying to use both focus_set and device_focus_set intercept! Sad!"); + return EINA_FALSE; + } + if (obj->interceptors && obj->interceptors->focus_set.func && (seat == default_seat)) + { + if (_evas_object_intercept_call_evas(obj, EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET, + 1, EINA_FALSE)) + { + return EINA_FALSE; + } + } + else if (_evas_object_intercept_call_evas(obj, EVAS_OBJECT_INTERCEPT_CB_DEVICE_FOCUS_SET, + 1, EINA_FALSE, seat)) { return EINA_FALSE; } @@ -167,13 +182,15 @@ _efl_canvas_object_seat_focus_add(Eo *eo_obj, { Eo *current_focus; int event_id; + Eo *default_seat; MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ); return EINA_FALSE; MAGIC_CHECK_END(); event_id = _evas_event_counter; - if (!seat) seat = _default_seat_get(eo_obj); + if (seat) default_seat = _default_seat_get(eo_obj); + else default_seat = seat = _default_seat_get(eo_obj); if (seat && (efl_input_device_type_get(seat) != EFL_INPUT_DEVICE_TYPE_SEAT)) return EINA_FALSE; @@ -190,12 +207,24 @@ _efl_canvas_object_seat_focus_add(Eo *eo_obj, if (_already_focused(obj->events->focused_by_seats, seat)) goto end; - if (_evas_object_intercept_call_evas(obj, EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET, - 1, EINA_TRUE)) + if (obj->interceptors && obj->interceptors->focus_set.func && obj->interceptors->device_focus_set.func) + { + CRI("Your object is trying to use both focus_set and device_focus_set intercept! Sad!"); + return EINA_FALSE; + } + if (obj->interceptors && obj->interceptors->focus_set.func && (seat == default_seat)) + { + if (_evas_object_intercept_call_evas(obj, EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET, + 1, EINA_TRUE)) + { + return EINA_FALSE; + } + } + else if (_evas_object_intercept_call_evas(obj, EVAS_OBJECT_INTERCEPT_CB_DEVICE_FOCUS_SET, + 1, EINA_TRUE, seat)) { return EINA_FALSE; } - current_focus = _current_focus_get(eo_obj, seat); if (current_focus) efl_canvas_object_seat_focus_del(current_focus, seat); diff --git a/src/lib/evas/canvas/evas_object_intercept.c b/src/lib/evas/canvas/evas_object_intercept.c index cd8d6d20de..e627daab97 100644 --- a/src/lib/evas/canvas/evas_object_intercept.c +++ b/src/lib/evas/canvas/evas_object_intercept.c @@ -79,6 +79,7 @@ EVAS_OBJECT_INTERCEPT_CALL(stack_above, (COMMON_ARGS, Evas_Object *rel_to), UNPA 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(device_focus_set, (COMMON_ARGS, int focus, Eo *seat), UNPACK_ARG2(focus, seat)) 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)) @@ -91,6 +92,7 @@ _evas_object_intercept_call_internal(Evas_Object *eo_obj, Eina_Bool blocked = 0; Evas_Object *eo_other; int r, g, b, a, i, j; + Eo *seat; evas_object_async_block(obj); @@ -162,6 +164,13 @@ _evas_object_intercept_call_internal(Evas_Object *eo_obj, blocked = evas_object_intercept_call_focus_set(eo_obj, obj, !!i); break; + case EVAS_OBJECT_INTERCEPT_CB_DEVICE_FOCUS_SET: + if (!obj->interceptors) return 0; + i = va_arg(args, int); + seat = va_arg(args, Eo*); + blocked = evas_object_intercept_call_device_focus_set(eo_obj, obj, !!i, seat); + break; + case EVAS_OBJECT_INTERCEPT_CB_COLOR_SET: if (!obj->interceptors) return 0; r = va_arg(args, int); @@ -283,6 +292,7 @@ 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(Device_Focus_Set, device_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); diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 7cd3b6fde6..d5d9e66be7 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -749,6 +749,11 @@ struct _Evas_Intercept_Func void *data; Eina_Bool intercepted; } focus_set; + struct { + Evas_Object_Intercept_Device_Focus_Set_Cb func; + void *data; + Eina_Bool intercepted; + } device_focus_set; }; struct _Evas_Smart_Cb_Description_Array