jpeg pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=b147911bad2b216b23f504ad3470278418ff32d2
commit b147911bad2b216b23f504ad3470278418ff32d2 Author: Jean-Philippe Andre <jp.an...@samsung.com> Date: Thu Jun 2 14:36:55 2016 +0900 elm_win: Forward events between window and evas This does: 1. Forward keyboard events from evas to win 2. Allow feeding external input events Input events can be faked by apps by simply forging eo objects of the proper type (key or pointer evt) and calling eo_event_callback_call(). Such events will be forwarded to the internal Evas, and some bool flags prevent infinite refeeding loops. efl_event_dup() returns fake events for this to work. @feature --- src/lib/ecore_evas/ecore_evas.c | 14 ++-- src/lib/efl/Efl.h | 1 + src/lib/efl/interfaces/efl_common_internal.h | 8 ++- src/lib/efl/interfaces/efl_event.eo | 7 ++ src/lib/elementary/elm_win.c | 88 ++++++++++++++++++++++- src/lib/evas/canvas/efl_event_input.eo | 7 ++ src/lib/evas/canvas/efl_event_key.c | 100 ++++++++++++++++++++++----- src/lib/evas/canvas/efl_event_key.eo | 3 + src/lib/evas/canvas/efl_event_pointer.c | 32 ++++++--- src/lib/evas/canvas/efl_event_pointer.eo | 12 +--- src/lib/evas/canvas/evas_events.c | 5 +- 11 files changed, 231 insertions(+), 46 deletions(-) diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c index 7f7b1dc..fb225ad 100644 --- a/src/lib/ecore_evas/ecore_evas.c +++ b/src/lib/ecore_evas/ecore_evas.c @@ -3,6 +3,7 @@ #endif #define ECORE_EVAS_INTERNAL +#define EFL_EVENT_PROTECTED #include <stdlib.h> #include <string.h> @@ -4358,7 +4359,7 @@ _direct_mouse_updown(Ecore_Evas *ee, const Ecore_Event_Mouse_Button *info, Efl_P * modifiers (already passed to evas, no need to do anything) */ - evt = efl_event_pointer_instance_get(EFL_EVENT_POINTER_CLASS, e, (void **) &ev); + evt = efl_event_instance_get(EFL_EVENT_POINTER_CLASS, e, (void **) &ev); if (!evt) return EINA_FALSE; ev->action = action; @@ -4418,7 +4419,7 @@ _direct_mouse_move_cb(Ecore_Evas *ee, const Ecore_Event_Mouse_Move *info) * modifiers (already passed to evas, no need to do anything) */ - evt = efl_event_pointer_instance_get(EFL_EVENT_POINTER_CLASS, e, (void **) &ev); + evt = efl_event_instance_get(EFL_EVENT_POINTER_CLASS, e, (void **) &ev); if (!evt) return EINA_FALSE; ev->action = EFL_POINTER_ACTION_MOVE; @@ -4455,7 +4456,7 @@ _direct_mouse_wheel_cb(Ecore_Evas *ee, const Ecore_Event_Mouse_Wheel *info) * modifiers (already passed to evas, no need to do anything) */ - evt = efl_event_pointer_instance_get(EFL_EVENT_POINTER_CLASS, e, (void **) &ev); + evt = efl_event_instance_get(EFL_EVENT_POINTER_CLASS, e, (void **) &ev); if (!evt) return EINA_FALSE; ev->action = EFL_POINTER_ACTION_WHEEL; @@ -4484,7 +4485,7 @@ _direct_mouse_inout(Ecore_Evas *ee, const Ecore_Event_Mouse_IO *info, Efl_Pointe * modifiers (already passed to evas, no need to do anything) */ - evt = efl_event_pointer_instance_get(EFL_EVENT_POINTER_CLASS, e, (void **) &ev); + evt = efl_event_instance_get(EFL_EVENT_POINTER_CLASS, e, (void **) &ev); if (!evt) return EINA_FALSE; ev->action = action; @@ -4526,9 +4527,8 @@ _direct_key_updown_cb(Ecore_Evas *ee, const Ecore_Event_Key *info, Eina_Bool dow * modifiers (already passed to evas, no need to do anything) */ - evt = eo_add(EFL_EVENT_KEY_CLASS, e); - ev = eo_data_scope_get(evt, EFL_EVENT_KEY_CLASS); - if (!ev) return EINA_FALSE; + evt = efl_event_instance_get(EFL_EVENT_KEY_CLASS, e, (void **) &ev); + if (!evt || !ev) return EINA_FALSE; ev->timestamp = info->timestamp; ev->pressed = down; diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h index 0dba0f2..cca5614 100644 --- a/src/lib/efl/Efl.h +++ b/src/lib/efl/Efl.h @@ -38,6 +38,7 @@ extern "C" { /* Add here all the required ifdef for any @protected method */ #ifdef EFL_EFL_BUILD # define EFL_PACK_LAYOUT_PROTECTED +# define EFL_EVENT_PROTECTED #endif /** diff --git a/src/lib/efl/interfaces/efl_common_internal.h b/src/lib/efl/interfaces/efl_common_internal.h index b7eb818..60adfef 100644 --- a/src/lib/efl/interfaces/efl_common_internal.h +++ b/src/lib/efl/interfaces/efl_common_internal.h @@ -50,7 +50,9 @@ struct _Efl_Event_Pointer_Data (see input vs. feed: this is "input") */ Evas_Modifier *modifiers; Evas_Lock *locks; - Eina_Bool evas_done; /* set by evas */ + Eina_Bool evas_done : 1; /* set by evas */ + Eina_Bool fake : 1; + Eina_Bool win_fed : 1; }; struct _Efl_Event_Key_Data @@ -70,7 +72,9 @@ struct _Efl_Event_Key_Data Evas_Lock *locks; Efl_Event_Flags event_flags; Efl_Input_Device *device; - Eina_Bool evas_done; /* set by evas */ + Eina_Bool evas_done : 1; /* set by evas */ + Eina_Bool fake : 1; + Eina_Bool win_fed : 1; }; struct _Efl_Input_Device_Data diff --git a/src/lib/efl/interfaces/efl_event.eo b/src/lib/efl/interfaces/efl_event.eo index 1e50274..223545f 100644 --- a/src/lib/efl/interfaces/efl_event.eo +++ b/src/lib/efl/interfaces/efl_event.eo @@ -33,5 +33,12 @@ interface Efl.Event [[Creates a copy of this event.]] return: own(Efl.Event); } + instance_get @class @protected { + params { + @in owner: Eo.Base; + @out priv: void*; + } + return: Efl.Event; + } } } diff --git a/src/lib/elementary/elm_win.c b/src/lib/elementary/elm_win.c index d792ece..0cb8574 100644 --- a/src/lib/elementary/elm_win.c +++ b/src/lib/elementary/elm_win.c @@ -17,6 +17,9 @@ #include "../evas/canvas/evas_box.eo.h" +#define EFL_INTERNAL_UNSTABLE +#include "interfaces/efl_common_internal.h" + #define MY_CLASS ELM_WIN_CLASS #define MY_CLASS_NAME "Elm_Win" @@ -1629,11 +1632,36 @@ _elm_win_elm_widget_event(Eo *obj, Elm_Win_Data *_pd EINA_UNUSED, Evas_Object *s return EINA_TRUE; } +/* forward events sent to evas to the window */ +static Eina_Bool +_evas_event_key_cb(void *data, const Eo_Event *ev) +{ + Eo *win = data; + Eo *evt = ev->info; + Efl_Event_Key_Data *evdata; + + evdata = eo_data_scope_get(evt, EFL_EVENT_KEY_CLASS); + if (!evdata || evdata->win_fed) + return EO_CALLBACK_CONTINUE; + + // evas_callbacks will send the event to the focussed object (ie. this win) + if (evas_focus_get(evas_object_evas_get(win)) == win) + return EO_CALLBACK_CONTINUE; + + eo_event_callback_call(win, ev->desc, evt); + return EO_CALLBACK_CONTINUE; +} + static Eina_Bool _evas_event_pointer_cb(void *data, const Eo_Event *ev) { Eo *win = data; Eo *evt = ev->info; + Efl_Event_Pointer_Data *evdata; + + evdata = eo_data_scope_get(evt, EFL_EVENT_POINTER_CLASS); + if (!evdata || evdata->win_fed) + return EO_CALLBACK_CONTINUE; eo_event_callback_call(win, ev->desc, evt); return EO_CALLBACK_CONTINUE; @@ -1646,7 +1674,63 @@ EO_CALLBACKS_ARRAY_DEFINE(_elm_win_evas_forward_callbacks, { EFL_EVENT_POINTER_IN, _evas_event_pointer_cb }, { EFL_EVENT_POINTER_OUT, _evas_event_pointer_cb }, { EFL_EVENT_POINTER_CANCEL, _evas_event_pointer_cb }, -{ EFL_EVENT_POINTER_WHEEL, _evas_event_pointer_cb }) +{ EFL_EVENT_POINTER_WHEEL, _evas_event_pointer_cb }, +{ EFL_EVENT_KEY_DOWN, _evas_event_key_cb }, +{ EFL_EVENT_KEY_UP, _evas_event_key_cb }) + +/* feed events from the window to evas - for fake inputs */ +static Eina_Bool +_evas_event_key_feed_fake_cb(void *data, const Eo_Event *ev) +{ + Eo *evas = data; + Efl_Event *evt = ev->info; + Efl_Event_Key_Data *evdata; + + if (!efl_event_fake_get(evt)) + return EO_CALLBACK_CONTINUE; + + evdata = eo_data_scope_get(evt, EFL_EVENT_KEY_CLASS); + if (!evdata || evdata->win_fed) + return EO_CALLBACK_CONTINUE; + evdata->win_fed = EINA_TRUE; + + eo_event_callback_call(evas, ev->desc, evt); + evdata->win_fed = EINA_FALSE; + evdata->evas_done = EINA_FALSE; + return EO_CALLBACK_CONTINUE; +} + +static Eina_Bool +_evas_event_pointer_feed_fake_cb(void *data, const Eo_Event *ev) +{ + Eo *evas = data; + Efl_Event *evt = ev->info; + Efl_Event_Pointer_Data *evdata; + + if (!efl_event_fake_get(evt)) + return EO_CALLBACK_CONTINUE; + + evdata = eo_data_scope_get(evt, EFL_EVENT_POINTER_CLASS); + if (!evdata || evdata->win_fed) + return EO_CALLBACK_CONTINUE; + evdata->win_fed = EINA_TRUE; + + eo_event_callback_call(evas, ev->desc, evt); + evdata->win_fed = EINA_FALSE; + evdata->evas_done = EINA_FALSE; + return EO_CALLBACK_CONTINUE; +} + +EO_CALLBACKS_ARRAY_DEFINE(_elm_win_evas_feed_fake_callbacks, +{ EFL_EVENT_POINTER_MOVE, _evas_event_pointer_feed_fake_cb }, +{ EFL_EVENT_POINTER_DOWN, _evas_event_pointer_feed_fake_cb }, +{ EFL_EVENT_POINTER_UP, _evas_event_pointer_feed_fake_cb }, +{ EFL_EVENT_POINTER_IN, _evas_event_pointer_feed_fake_cb }, +{ EFL_EVENT_POINTER_OUT, _evas_event_pointer_feed_fake_cb }, +{ EFL_EVENT_POINTER_CANCEL, _evas_event_pointer_feed_fake_cb }, +{ EFL_EVENT_POINTER_WHEEL, _evas_event_pointer_feed_fake_cb }, +{ EFL_EVENT_KEY_DOWN, _evas_event_key_feed_fake_cb }, +{ EFL_EVENT_KEY_UP, _evas_event_key_feed_fake_cb }) static void _deferred_ecore_evas_free(void *data) @@ -1996,6 +2080,7 @@ _elm_win_evas_object_smart_del(Eo *obj, Elm_Win_Data *sd) _elm_win_on_resize_obj_changed_size_hints, obj); eo_event_callback_array_del(sd->evas, _elm_win_evas_forward_callbacks(), obj); + eo_event_callback_array_del(obj, _elm_win_evas_feed_fake_callbacks(), sd->evas); evas_object_del(sd->box); evas_object_del(sd->edje); @@ -4054,6 +4139,7 @@ _elm_win_finalize_internal(Eo *obj, Elm_Win_Data *sd, const char *name, Elm_Win_ elm_interface_atspi_window_created_signal_emit(obj); eo_event_callback_array_add(sd->evas, _elm_win_evas_forward_callbacks(), obj); + eo_event_callback_array_add(obj, _elm_win_evas_feed_fake_callbacks(), sd->evas); evas_object_show(sd->edje); diff --git a/src/lib/evas/canvas/efl_event_input.eo b/src/lib/evas/canvas/efl_event_input.eo index 6679d87..6f64da3 100644 --- a/src/lib/evas/canvas/efl_event_input.eo +++ b/src/lib/evas/canvas/efl_event_input.eo @@ -28,5 +28,12 @@ interface Efl.Event.Input (Efl.Event) val: bool; } } + @property fake { + [[$true if the event was fake, not triggered by real hardware.]] + get {} + values { + val: bool; + } + } } } diff --git a/src/lib/evas/canvas/efl_event_key.c b/src/lib/evas/canvas/efl_event_key.c index 6d6dc15..5bb32f7 100644 --- a/src/lib/evas/canvas/efl_event_key.c +++ b/src/lib/evas/canvas/efl_event_key.c @@ -2,6 +2,8 @@ # include <config.h> #endif +#define EFL_EVENT_PROTECTED + #include <Evas.h> #define EFL_INTERNAL_UNSTABLE @@ -9,6 +11,62 @@ #define MY_CLASS EFL_EVENT_KEY_CLASS +static Efl_Event_Key *s_cached_event = NULL; + +static void +_del_hook(Eo *evt) +{ + if (!s_cached_event) + { + if (eo_parent_get(evt)) + { + eo_ref(evt); + eo_parent_set(evt, NULL); + } + s_cached_event = evt; + } + else + { + eo_del_intercept_set(evt, NULL); + eo_del(evt); + } +} + +EOLIAN static Efl_Event_Key * +_efl_event_key_efl_event_instance_get(Eo *klass EINA_UNUSED, void *_pd EINA_UNUSED, + Eo *owner, void **priv) +{ + Efl_Event_Key_Data *ev; + Efl_Event_Key *evt; + + if (s_cached_event) + { + evt = s_cached_event; + s_cached_event = NULL; + efl_event_reset(evt); + eo_parent_set(evt, owner); + } + else + { + evt = eo_add(EFL_EVENT_KEY_CLASS, owner); + eo_del_intercept_set(evt, _del_hook); + } + + ev = eo_data_scope_get(evt, EFL_EVENT_KEY_CLASS); + ev->fake = EINA_FALSE; + if (priv) *priv = ev; + + return evt; +} + +EOLIAN static void +_efl_event_key_class_destructor(Eo_Class *klass EINA_UNUSED) +{ + // this is a strange situation... + eo_del(s_cached_event); + s_cached_event = NULL; +} + EOLIAN static Eo_Base * _efl_event_key_eo_base_constructor(Eo *obj, Efl_Event_Key_Data *pd EINA_UNUSED) { @@ -98,28 +156,30 @@ _efl_event_key_efl_event_reset(Eo *obj EINA_UNUSED, Efl_Event_Key_Data *pd) eina_stringshare_del(pd->compose); memset(pd, 0, sizeof(*pd)); pd->eo = obj; + pd->fake = EINA_TRUE; } EOLIAN static Efl_Event * _efl_event_key_efl_event_dup(Eo *obj EINA_UNUSED, Efl_Event_Key_Data *pd) { - Efl_Event_Key_Data *pd2; - Efl_Event *ev; - - ev = eo_add(MY_CLASS, NULL); // no parent - pd2 = eo_data_scope_get(ev, MY_CLASS); - if (pd2) - { - memcpy(pd2, pd, sizeof(*pd)); - pd2->eo = ev; - pd2->key = eina_stringshare_add(pd->key); - pd2->keyname = eina_stringshare_add(pd->keyname); - pd2->string = eina_stringshare_add(pd->string); - pd2->compose = eina_stringshare_add(pd->compose); - pd2->evas_done = 0; - } - - return ev; + Efl_Event_Key_Data *ev; + Efl_Event_Key *evt; + + // no parent + evt = efl_event_instance_get(EFL_EVENT_KEY_CLASS, NULL, (void **) &ev); + if (!evt || !ev) return NULL; + + memcpy(ev, pd, sizeof(*ev)); + ev->eo = evt; + ev->key = eina_stringshare_add(pd->key); + ev->keyname = eina_stringshare_add(pd->keyname); + ev->string = eina_stringshare_add(pd->string); + ev->compose = eina_stringshare_add(pd->compose); + ev->evas_done = 0; + ev->win_fed = 0; + ev->fake = 1; + + return evt; } EOLIAN static void @@ -202,4 +262,10 @@ _efl_event_key_efl_input_state_lock_enabled_get(Eo *obj EINA_UNUSED, Efl_Event_K return evas_key_lock_is_set(pd->locks, name); } +EOLIAN static Eina_Bool +_efl_event_key_efl_event_input_fake_get(Eo *obj EINA_UNUSED, Efl_Event_Key_Data *pd) +{ + return pd->fake; +} + #include "efl_event_key.eo.c" diff --git a/src/lib/evas/canvas/efl_event_key.eo b/src/lib/evas/canvas/efl_event_key.eo index ef17720..f702cce 100644 --- a/src/lib/evas/canvas/efl_event_key.eo +++ b/src/lib/evas/canvas/efl_event_key.eo @@ -52,11 +52,14 @@ class Efl.Event.Key (Eo.Base, Efl.Event, Efl.Input.State, Efl.Event.Input) } } implements { + class.destructor; Eo.Base.constructor; + Efl.Event.instance_get; Efl.Event.reset; Efl.Event.dup; Efl.Event.timestamp.set; Efl.Event.timestamp.get; + Efl.Event.Input.fake.get; Efl.Event.Input.event_flags.set; Efl.Event.Input.event_flags.get; Efl.Event.Input.on_hold.set; diff --git a/src/lib/evas/canvas/efl_event_pointer.c b/src/lib/evas/canvas/efl_event_pointer.c index 35688dc..33a734a 100644 --- a/src/lib/evas/canvas/efl_event_pointer.c +++ b/src/lib/evas/canvas/efl_event_pointer.c @@ -2,6 +2,8 @@ # include <config.h> #endif +#define EFL_EVENT_PROTECTED + #include <Evas.h> #define EFL_INTERNAL_UNSTABLE @@ -42,9 +44,10 @@ _del_hook(Eo *evt) } EOLIAN static Efl_Event_Pointer * -_efl_event_pointer_instance_get(Eo_Class *klass EINA_UNUSED, void *pd EINA_UNUSED, - Eo *owner, void **priv) +_efl_event_pointer_efl_event_instance_get(Eo *klass EINA_UNUSED, void *_pd EINA_UNUSED, + Eo *owner, void **priv) { + Efl_Event_Pointer_Data *ev; Efl_Event_Pointer *evt; if (s_cached_event) @@ -60,8 +63,9 @@ _efl_event_pointer_instance_get(Eo_Class *klass EINA_UNUSED, void *pd EINA_UNUSE eo_del_intercept_set(evt, _del_hook); } - if (priv) - *priv = eo_data_scope_get(evt, EFL_EVENT_POINTER_CLASS); + ev = eo_data_scope_get(evt, EFL_EVENT_POINTER_CLASS); + ev->fake = EINA_FALSE; + if (priv) *priv = ev; return evt; } @@ -70,7 +74,7 @@ EOLIAN static void _efl_event_pointer_class_destructor(Eo_Class *klass EINA_UNUSED) { // this is a strange situation... - eo_unref(s_cached_event); + eo_del(s_cached_event); s_cached_event = NULL; } @@ -85,23 +89,28 @@ _efl_event_pointer_eo_base_constructor(Eo *obj, Efl_Event_Pointer_Data *pd EINA_ EOLIAN static void _efl_event_pointer_efl_event_reset(Eo *obj, Efl_Event_Pointer_Data *pd) { + Eina_Bool fake = pd->fake; memset(pd, 0, sizeof(*pd)); pd->eo = obj; pd->wheel.dir = EFL_ORIENT_VERTICAL; + pd->fake = fake; } EOLIAN static Efl_Event * -_efl_event_pointer_efl_event_dup(Eo *obj, Efl_Event_Pointer_Data *pd) +_efl_event_pointer_efl_event_dup(Eo *obj EINA_UNUSED, Efl_Event_Pointer_Data *pd) { Efl_Event_Pointer_Data *ev; Efl_Event_Pointer *evt; - evt = _efl_event_pointer_instance_get((Eo_Class *) EFL_EVENT_POINTER_CLASS, - NULL, obj, (void **) &ev); + // no parent + evt = efl_event_instance_get(EFL_EVENT_POINTER_CLASS, NULL, (void **) &ev); if (!evt) return NULL; memcpy(ev, pd, sizeof(*ev)); ev->eo = evt; + ev->evas_done = 0; + ev->win_fed = 0; + ev->fake = 1; return evt; } @@ -397,4 +406,11 @@ _efl_event_pointer_efl_event_input_on_scroll_get(Eo *obj EINA_UNUSED, Efl_Event_ return !!(pd->event_flags & EFL_EVENT_FLAGS_ON_SCROLL); } +EOLIAN static Eina_Bool +_efl_event_pointer_efl_event_input_fake_get(Eo *obj EINA_UNUSED, Efl_Event_Pointer_Data *pd) +{ + // read-only + return pd->fake; +} + #include "efl_event_pointer.eo.c" diff --git a/src/lib/evas/canvas/efl_event_pointer.eo b/src/lib/evas/canvas/efl_event_pointer.eo index b6def27..31d8b09 100644 --- a/src/lib/evas/canvas/efl_event_pointer.eo +++ b/src/lib/evas/canvas/efl_event_pointer.eo @@ -125,24 +125,16 @@ class Efl.Event.Pointer (Eo.Base, Efl.Event, Efl.Input.State, Efl.Event.Input) dist: int; } } - instance_get @class { - [[Creates an instance of this events or returns a fresh one from - a memory pool. - ]] - params { - @in owner: Eo.Base; [[The parent object.]] - @out priv: void_ptr; [[Pointer to the internal data of the object.]] - } - return: own(Efl.Event.Pointer); - } } implements { Eo.Base.constructor; class.destructor; + Efl.Event.instance_get; Efl.Event.reset; Efl.Event.dup; Efl.Event.timestamp.set; Efl.Event.timestamp.get; + Efl.Event.Input.fake.get; Efl.Event.Input.event_flags.set; Efl.Event.Input.event_flags.get; Efl.Event.Input.on_hold.set; diff --git a/src/lib/evas/canvas/evas_events.c b/src/lib/evas/canvas/evas_events.c index 7fac4ad..67faf11 100644 --- a/src/lib/evas/canvas/evas_events.c +++ b/src/lib/evas/canvas/evas_events.c @@ -1,3 +1,5 @@ +#define EFL_EVENT_PROTECTED + #include "evas_common_private.h" #include "evas_private.h" @@ -104,7 +106,7 @@ _efl_event_create(Efl_Event *evt, Evas_Callback_Type type, void *ev, #define EV_CASE(TYPE, Type, OBJTYP, objtyp) \ case EVAS_CALLBACK_ ## TYPE: \ - if (!evt) evt = eo_add(EFL_EVENT_ ## OBJTYP ## _CLASS, parentev); \ + if (!evt) evt = efl_event_instance_get(EFL_EVENT_ ## OBJTYP ## _CLASS, parentev, NULL); \ efl_event_ ## objtyp ## _legacy_info_set(evt, ev, type); \ if (pflags) *pflags = &(((Evas_Event_ ## Type *) ev)->event_flags); \ break; @@ -122,6 +124,7 @@ _efl_event_create(Efl_Event *evt, Evas_Callback_Type type, void *ev, EV_CASE(MOUSE_WHEEL, Mouse_Wheel, POINTER, pointer); EV_CASE(KEY_DOWN, Key_Down, KEY, key); EV_CASE(KEY_UP, Key_Up, KEY, key); + default: DBG("Support for event type %d not implemented yet.", type); break; --