Merge branch 'devs/iscaro/focus-event'

This series changes evas focus events, always providing
Efl.Input.Focus, making their usage way more straightforward.

Patches by Guilherme Iscaro <iscaro@profusion.mobi>
Differential Revision: https://phab.enlightenment.org/D4412
This commit is contained in:
Bruno Dilly 2016-11-24 19:18:52 -02:00
commit 6d530356b0
15 changed files with 324 additions and 61 deletions

View File

@ -48,6 +48,7 @@ evas_eolian_pub_files = \
lib/evas/canvas/efl_input_key.eo \
lib/evas/canvas/efl_input_pointer.eo \
lib/evas/canvas/efl_input_hold.eo \
lib/evas/canvas/efl_input_focus.eo \
lib/evas/canvas/efl_gfx_map.eo \
lib/evas/canvas/efl_canvas_output.eo \
$(NULL)
@ -208,6 +209,7 @@ lib/evas/canvas/efl_input_event.c \
lib/evas/canvas/efl_input_key.c \
lib/evas/canvas/efl_input_pointer.c \
lib/evas/canvas/efl_input_hold.c \
lib/evas/canvas/efl_input_focus.c \
$(NULL)
EXTRA_DIST2 += \

View File

@ -439,8 +439,8 @@ EFL_CALLBACKS_ARRAY_DEFINE(edje_callbacks,
{ EFL_EVENT_POINTER_WHEEL, _edje_mouse_wheel_signal_cb });
EFL_CALLBACKS_ARRAY_DEFINE(edje_focus_callbacks,
{ EFL_CANVAS_OBJECT_EVENT_FOCUS_IN, _edje_focus_in_signal_cb },
{ EFL_CANVAS_OBJECT_EVENT_FOCUS_OUT, _edje_focus_out_signal_cb });
{ EFL_EVENT_FOCUS_IN, _edje_focus_in_signal_cb },
{ EFL_EVENT_FOCUS_OUT, _edje_focus_out_signal_cb });
void
_edje_callbacks_add(Evas_Object *obj, Edje *ed, Edje_Real_Part *rp)

View File

@ -160,10 +160,10 @@ interface Efl.Canvas ()
}
}
events {
focus,in; [[Called when canvas got focus]]
focus,out; [[Called when canvas lost focus]]
object,focus,in: Efl.Canvas.Object; [[Called when object got focus]]
object,focus,out: Efl.Canvas.Object; [[Called when object lost focus]]
focus,in: Efl.Input.Focus; [[Called when canvas got focus]]
focus,out: Efl.Input.Focus; [[Called when canvas lost focus]]
object,focus,in: Efl.Input.Focus; [[Called when object got focus]]
object,focus,out: Efl.Input.Focus; [[Called when object lost focus]]
render,pre; [[Called when pre render happens]]
render,post; [[Called when post render happens]]
device,changed: Efl.Input.Device; [[Called when input device changed]]

View File

@ -17,6 +17,7 @@ typedef struct _Efl_Input_Pointer_Data Efl_Input_Pointer_Data;
typedef struct _Efl_Input_Key_Data Efl_Input_Key_Data;
typedef struct _Efl_Input_Device_Data Efl_Input_Device_Data;
typedef struct _Efl_Input_Hold_Data Efl_Input_Hold_Data;
typedef struct _Efl_Input_Focus_Data Efl_Input_Focus_Data;
#ifndef _EVAS_TYPES_EOT_H_
typedef struct _Evas_Modifier Evas_Modifier;
@ -110,6 +111,14 @@ struct _Efl_Input_Hold_Data
Eina_Bool evas_done : 1; /* set by evas */
};
struct _Efl_Input_Focus_Data
{
Eo *eo;
Efl_Input_Device *device; //The seat
Eo *object; //The focused object - Efl.Canvas.Object or Efl.Canvas.
double timestamp;
};
static inline Eina_Bool
_efl_input_value_has(const Efl_Input_Pointer_Data *pd, Efl_Input_Value key)
{

View File

@ -307,4 +307,5 @@ typedef void (Evas_Canvas3D_Surface_Func)(Evas_Real *out_x,
#include "canvas/efl_input_key.eo.h"
#include "canvas/efl_input_hold.eo.h"
#include "canvas/efl_input_interface.eo.h"
#include "canvas/efl_input_focus.eo.h"
#endif /* EFL_EO_API_SUPPORT */

View File

@ -636,10 +636,4 @@ abstract Efl.Canvas.Object (Efl.Object, Efl.Gfx, Efl.Gfx.Stack, Efl.Animator,
Efl.Gfx.Map.map_enable.set;
Efl.Gfx.Map.map_enable.get;
}
events {
focus,in; [[Focus In Event ]]
focus,out; [[Focus Out Event ]]
focus,device,in: Efl.Input.Device; [[Focus In event that contains the seat device that this object was focused. @since 1.19]]
focus,device,out: Efl.Input.Device; [[Focus Out event that contains the seat device that this object was unfocused.@since 1.19]]
}
}

View File

@ -0,0 +1,161 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define EFL_INPUT_EVENT_PROTECTED
#include <Evas.h>
#define EFL_INTERNAL_UNSTABLE
#include "interfaces/efl_common_internal.h"
#define MY_CLASS EFL_INPUT_FOCUS_CLASS
static Efl_Input_Focus *s_cached_event = NULL;
static void
_del_hook(Eo *evt)
{
if (!s_cached_event)
{
if (efl_parent_get(evt))
{
efl_ref(evt);
efl_parent_set(evt, NULL);
}
efl_reuse(evt);
s_cached_event = evt;
}
else
{
efl_del_intercept_set(evt, NULL);
efl_del(evt);
}
}
static void
_efl_input_focus_free(Efl_Input_Focus_Data *pd)
{
efl_unref(pd->device);
}
EOLIAN static Efl_Object *
_efl_input_focus_efl_object_constructor(Eo *obj,
Efl_Input_Focus_Data *pd EINA_UNUSED)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
return obj;
}
EOLIAN static void
_efl_input_focus_efl_object_destructor(Eo *obj,
Efl_Input_Focus_Data *pd)
{
_efl_input_focus_free(pd);
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_efl_input_focus_class_destructor(Efl_Class *klass EINA_UNUSED)
{
// this is a strange situation...
efl_del_intercept_set(s_cached_event, NULL);
efl_del(s_cached_event);
s_cached_event = NULL;
}
EOLIAN static void
_efl_input_focus_object_set(Eo *obj EINA_UNUSED, Efl_Input_Focus_Data *pd,
Efl_Object *object)
{
pd->object = object;
}
EOLIAN static Efl_Object *
_efl_input_focus_object_get(Eo *obj EINA_UNUSED, Efl_Input_Focus_Data *pd)
{
return pd->object;
}
EOLIAN static void
_efl_input_focus_efl_input_event_device_set(Eo *obj EINA_UNUSED,
Efl_Input_Focus_Data *pd,
Efl_Input_Device *device)
{
pd->device = efl_ref(device);
}
EOLIAN static Efl_Input_Device *
_efl_input_focus_efl_input_event_device_get(Eo *obj EINA_UNUSED,
Efl_Input_Focus_Data *pd)
{
return pd->device;
}
EOLIAN static void
_efl_input_focus_efl_input_event_timestamp_set(Eo *obj EINA_UNUSED,
Efl_Input_Focus_Data *pd,
double ms)
{
pd->timestamp = ms;
}
EOLIAN static double
_efl_input_focus_efl_input_event_timestamp_get(Eo *obj EINA_UNUSED,
Efl_Input_Focus_Data *pd)
{
return pd->timestamp;
}
EOLIAN static Efl_Input_Focus *
_efl_input_focus_efl_input_event_dup(Eo *obj EINA_UNUSED,
Efl_Input_Focus_Data *pd)
{
Efl_Input_Focus_Data *ev;
Efl_Input_Focus *evt;
// no parent
evt = efl_input_instance_get(MY_CLASS, NULL, (void **) &ev);
if (!evt || !ev) return NULL;
ev->eo = evt;
ev->object = pd->object;
ev->device = efl_ref(pd->device);
ev->timestamp = pd->timestamp;
return evt;
}
EOLIAN static Efl_Input_Focus *
_efl_input_focus_efl_input_event_instance_get(Eo *klass EINA_UNUSED, void *_pd EINA_UNUSED,
Eo *owner, void **priv)
{
Efl_Input_Focus_Data *ev;
Efl_Input_Focus *evt;
if (s_cached_event)
{
evt = s_cached_event;
s_cached_event = NULL;
efl_input_reset(evt);
efl_parent_set(evt, owner);
}
else
{
evt = efl_add(MY_CLASS, owner);
efl_del_intercept_set(evt, _del_hook);
}
ev = efl_data_scope_get(evt, MY_CLASS);
if (priv) *priv = ev;
return evt;
}
EOLIAN static void
_efl_input_focus_efl_input_event_reset(Eo *obj, Efl_Input_Focus_Data *pd)
{
_efl_input_focus_free(pd);
memset(pd, 0, sizeof(Efl_Input_Focus_Data));
pd->eo = obj;
}
#include "efl_input_focus.eo.c"

View File

@ -0,0 +1,25 @@
class Efl.Input.Focus(Efl.Object, Efl.Input.Event)
{
[[Reprents a focus event. @since 1.19]]
methods {
@property object {
values {
object: Efl.Object; [[The focused object.
In case this represents a canvas
focus the object will be $null]]
}
}
}
implements {
class.destructor;
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Input.Event.device.set;
Efl.Input.Event.device.get;
Efl.Input.Event.instance_get;
Efl.Input.Event.reset;
Efl.Input.Event.dup;
Efl.Input.Event.timestamp.set;
Efl.Input.Event.timestamp.get;
}
}

View File

@ -99,5 +99,7 @@ interface Efl.Input.Interface ()
key,down: Efl.Input.Key; [[Keyboard key press.]]
key,up: Efl.Input.Key; [[Keyboard key release.]]
hold: Efl.Input.Hold; [[All input events are on hold or resumed.]]
focus,in: Efl.Input.Focus; [[A focus in event.]]
focus,out: Efl.Input.Focus; [[A focus out event.]]
}
}

View File

@ -48,8 +48,8 @@ DEFINE_EVAS_CALLBACKS(_legacy_evas_callback_table, EVAS_CALLBACK_LAST,
EVAS_OBJECT_EVENT_FREE,
EFL_EVENT_KEY_DOWN,
EFL_EVENT_KEY_UP,
EFL_CANVAS_OBJECT_EVENT_FOCUS_IN,
EFL_CANVAS_OBJECT_EVENT_FOCUS_OUT,
EFL_EVENT_FOCUS_IN,
EFL_EVENT_FOCUS_OUT,
EFL_GFX_EVENT_SHOW,
EFL_GFX_EVENT_HIDE,
EFL_GFX_EVENT_MOVE,
@ -93,7 +93,8 @@ typedef enum {
EFL_EVENT_TYPE_STRUCT,
EFL_EVENT_TYPE_POINTER,
EFL_EVENT_TYPE_KEY,
EFL_EVENT_TYPE_HOLD
EFL_EVENT_TYPE_HOLD,
EFL_EVENT_TYPE_FOCUS
} Efl_Event_Info_Type;
typedef struct
@ -147,6 +148,10 @@ _evas_event_efl_event_info_type(Evas_Callback_Type type)
case EVAS_CALLBACK_DEVICE_CHANGED: /* Efl.Input.Device */
return EFL_EVENT_TYPE_OBJECT;
case EVAS_CALLBACK_FOCUS_IN:
case EVAS_CALLBACK_FOCUS_OUT:
return EFL_EVENT_TYPE_FOCUS;
default:
return EFL_EVENT_TYPE_NULL;
}
@ -164,6 +169,7 @@ _eo_evas_object_cb(void *data, const Efl_Event *event)
if (!info->func) return;
evas = evas_object_evas_get(event->object);
event_info = event->info;
switch (info->efl_event_type)
{
case EFL_EVENT_TYPE_POINTER:
@ -178,12 +184,13 @@ _eo_evas_object_cb(void *data, const Efl_Event *event)
event_info = efl_input_hold_legacy_info_fill(efl_event_info, &event_flags);
break;
case EFL_EVENT_TYPE_FOCUS:
event_info = NULL;
case EFL_EVENT_TYPE_NULL:
case EFL_EVENT_TYPE_STRUCT:
case EFL_EVENT_TYPE_OBJECT:
info->func(info->data, evas, event->object, event->info);
info->func(info->data, evas, event->object, event_info);
return;
default: return;
}
@ -197,8 +204,20 @@ _eo_evas_object_cb(void *data, const Efl_Event *event)
static void
_eo_evas_cb(void *data, const Efl_Event *event)
{
void *event_info;
_eo_evas_cb_info *info = data;
if (info->func) info->func(info->data, event->object, event->info);
//Keep the legacy behaviour for focus events.
if (event->desc == EFL_CANVAS_EVENT_FOCUS_IN ||
event->desc == EFL_CANVAS_EVENT_FOCUS_OUT)
event_info = NULL;
else if (event->desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_IN ||
event->desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_OUT)
event_info = efl_input_focus_object_get(event->info);
else
event_info = event->info;
if (info->func) info->func(info->data, event->object, event_info);
}
void

View File

@ -3528,6 +3528,27 @@ _evas_canvas_event_key_cb(void *data, const Efl_Event *event)
ev->evas_done = EINA_TRUE;
}
static void
_evas_canvas_event_focus_cb(void *data, const Efl_Event *event)
{
Evas_Public_Data *e = data;
if (event->desc == EFL_EVENT_FOCUS_IN)
{
if (e->focus) return;
e->focus = 1;
evas_event_callback_call(e->evas, EVAS_CALLBACK_CANVAS_FOCUS_IN,
event->info);
}
else
{
if (!e->focus) return;
e->focus = 0;
evas_event_callback_call(e->evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT,
event->info);
}
}
// note: "hold" event comes from above (elm), not below (ecore)
EFL_CALLBACKS_ARRAY_DEFINE(_evas_canvas_event_pointer_callbacks,
{ EFL_EVENT_POINTER_MOVE, _evas_canvas_event_pointer_cb },
@ -3542,7 +3563,9 @@ EFL_CALLBACKS_ARRAY_DEFINE(_evas_canvas_event_pointer_callbacks,
{ EFL_EVENT_FINGER_DOWN, _evas_canvas_event_pointer_cb },
{ EFL_EVENT_FINGER_UP, _evas_canvas_event_pointer_cb },
{ EFL_EVENT_KEY_DOWN, _evas_canvas_event_key_cb },
{ EFL_EVENT_KEY_UP, _evas_canvas_event_key_cb })
{ EFL_EVENT_KEY_UP, _evas_canvas_event_key_cb },
{ EFL_EVENT_FOCUS_IN, _evas_canvas_event_focus_cb },
{ EFL_EVENT_FOCUS_OUT, _evas_canvas_event_focus_cb })
void
_evas_canvas_event_init(Evas *eo_e, Evas_Public_Data *e)

View File

@ -1,5 +1,9 @@
#define EFL_INTERNAL_UNSTABLE
#define EFL_INPUT_EVENT_PROTECTED
#include "evas_common_private.h"
#include "evas_private.h"
#include "interfaces/efl_common_internal.h"
/* private calls */
@ -59,26 +63,49 @@ _current_focus_get(Eo *evas_obj, Efl_Input_Device *key)
return eina_hash_find(edata->focused_objects, &key);
}
void
_evas_focus_dispatch_event(Evas_Object_Protected_Data *obj, Efl_Input_Device *seat, Eina_Bool in)
{
Efl_Input_Focus_Data *ev_data;
Efl_Input_Focus *evt;
Evas_Callback_Type cb_evas, cb_obj_evas;
const Efl_Event_Description *efl_object_focus_event;
evt = efl_input_instance_get(EFL_INPUT_FOCUS_CLASS, NULL, (void **) &ev_data);
if (!evt) return;
ev_data->device = efl_ref(seat);
ev_data->object = obj->object;
ev_data->timestamp = time(NULL);
if (in)
{
cb_obj_evas = EVAS_CALLBACK_FOCUS_IN;
cb_evas = EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN;
efl_object_focus_event = EFL_EVENT_FOCUS_IN;
}
else
{
cb_obj_evas = EVAS_CALLBACK_FOCUS_OUT;
cb_evas = EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT;
efl_object_focus_event = EFL_EVENT_FOCUS_OUT;
}
evas_object_event_callback_call(obj->object, obj,
cb_obj_evas,
evt, _evas_object_event_new(),
efl_object_focus_event);
evas_event_callback_call(obj->layer->evas->evas, cb_evas, evt);
efl_del(evt);
}
static void
_evas_object_unfocus(Evas_Object_Protected_Data *obj, Efl_Input_Device *seat)
{
obj->focused_by_seats = eina_list_remove(obj->focused_by_seats, seat);
_evas_focus_set(obj->object, seat, EINA_FALSE);
//Legacy events...
if (seat == obj->layer->evas->default_seat)
{
evas_object_event_callback_call(obj->object, obj,
EVAS_CALLBACK_FOCUS_OUT,
NULL, _evas_object_event_new(),
EFL_CANVAS_OBJECT_EVENT_FOCUS_OUT);
evas_event_callback_call(obj->layer->evas->evas,
EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
obj->object);
}
efl_event_callback_call(obj->object,
EFL_CANVAS_OBJECT_EVENT_FOCUS_DEVICE_OUT,
seat);
_evas_focus_dispatch_event(obj, seat, EINA_FALSE);
_evas_post_event_callback_call(obj->layer->evas->evas,
obj->layer->evas);
}
@ -161,18 +188,7 @@ _efl_canvas_object_seat_focus_add(Eo *eo_obj,
obj->focused_by_seats = eina_list_append(obj->focused_by_seats, seat);
_evas_focus_set(eo_obj, seat, EINA_TRUE);
//Legacy events...
if (seat == _default_seat_get(eo_obj))
{
evas_object_event_callback_call(eo_obj, obj, EVAS_CALLBACK_FOCUS_IN,
NULL, _evas_object_event_new(),
EFL_CANVAS_OBJECT_EVENT_FOCUS_IN);
evas_event_callback_call(obj->layer->evas->evas,
EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN, eo_obj);
}
efl_event_callback_call(eo_obj,
EFL_CANVAS_OBJECT_EVENT_FOCUS_DEVICE_IN, seat);
_evas_focus_dispatch_event(obj, seat, EINA_TRUE);
end:
_evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas);
return EINA_TRUE;

View File

@ -1,5 +1,5 @@
#define EVAS_CANVAS_BETA
#define EFL_INPUT_EVENT_PROTECTED
#include "evas_common_private.h"
#include "evas_private.h"
//#include "evas_cs.h"
@ -13,6 +13,9 @@
#include <Ecore.h>
#define EFL_INTERNAL_UNSTABLE
#include "interfaces/efl_common_internal.h"
#define MY_CLASS EVAS_CANVAS_CLASS
#ifdef LKDEBUG
@ -529,20 +532,33 @@ _evas_canvas_data_attach_get(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
return e->attach_data;
}
static void
_evas_canvas_focus_inout_dispatch(Eo *eo_e, Evas_Public_Data *e, Eina_Bool in)
{
Efl_Input_Focus_Data *ev_data;
Efl_Input_Focus *evt;
evt = efl_input_instance_get(EFL_INPUT_FOCUS_CLASS, eo_e, (void **) &ev_data);
if (!evt) return;
ev_data->device = efl_ref(e->default_seat);
ev_data->timestamp = time(NULL);
efl_event_callback_call(eo_e,
in ? EFL_EVENT_FOCUS_IN : EFL_EVENT_FOCUS_OUT,
evt);
efl_del(evt);
}
EOLIAN static void
_evas_canvas_focus_in(Eo *eo_e, Evas_Public_Data *e)
{
if (e->focus) return;
e->focus = 1;
evas_event_callback_call(eo_e, EVAS_CALLBACK_CANVAS_FOCUS_IN, NULL);
_evas_canvas_focus_inout_dispatch(eo_e, e, EINA_TRUE);
}
EOLIAN static void
_evas_canvas_focus_out(Eo *eo_e, Evas_Public_Data *e)
{
if (!e->focus) return;
e->focus = 0;
evas_event_callback_call(eo_e, EVAS_CALLBACK_CANVAS_FOCUS_OUT, NULL);
_evas_canvas_focus_inout_dispatch(eo_e, e, EINA_FALSE);
}
EOLIAN static Eina_Bool

View File

@ -706,15 +706,7 @@ _efl_canvas_object_efl_object_destructor(Eo *eo_obj, Evas_Object_Protected_Data
efl_event_callback_del(dev, EFL_EVENT_DEL,
_evas_focus_device_del_cb, obj);
eina_hash_del_by_key(edata->focused_objects, &dev);
//default seat - legacy support.
if (dev == edata->default_seat)
{
evas_object_event_callback_call(eo_obj, obj, EVAS_CALLBACK_FOCUS_OUT,
NULL, _evas_object_event_new(),
EFL_CANVAS_OBJECT_EVENT_FOCUS_OUT);
}
efl_event_callback_call(eo_obj,
EFL_CANVAS_OBJECT_EVENT_FOCUS_DEVICE_OUT, dev);
_evas_focus_dispatch_event(obj, dev, EINA_FALSE);
if ((obj->layer) && (obj->layer->evas))
_evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas);
}

View File

@ -1945,6 +1945,9 @@ Eina_Bool evas_vg_loader_svg(Evas_Object *vg, const Eina_File *f, const char *ke
void *_evas_object_image_surface_get(Evas_Object *eo, Evas_Object_Protected_Data *obj);
Eina_Bool _evas_image_proxy_source_clip_get(const Eo *eo_obj);
void _evas_focus_dispatch_event(Evas_Object_Protected_Data *obj,
Efl_Input_Device *seat, Eina_Bool in);
extern Eina_Cow *evas_object_proxy_cow;
extern Eina_Cow *evas_object_map_cow;
extern Eina_Cow *evas_object_state_cow;