Merge branch 'devs/iscaro/evas-focus-per-seat'

This series adds support to multiple focused objects
on Evas, so each seat can focus a different object.

Patches by Guilherme Iscaro <iscaro@profusion.mobi>
Differential Revision: https://phab.enlightenment.org/D4374

@feature
This commit is contained in:
Bruno Dilly 2016-11-08 17:55:07 -02:00
commit 2a96097a65
12 changed files with 529 additions and 79 deletions

View File

@ -3788,6 +3788,8 @@ _direct_mouse_updown(Ecore_Evas *ee, const Ecore_Event_Mouse_Button *info, Efl_P
ev->radius_y = info->multi.radius_y;
ev->pressure = info->multi.pressure;
ev->angle = info->multi.angle - ee->rotation;
if (info->dev) ev->device = efl_ref(info->dev);
else ev->device = efl_ref(evas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_MOUSE));
efl_event_callback_legacy_call(e, _event_description_get(ev->action), evt);
processed = ev->evas_done;
@ -3846,6 +3848,8 @@ _direct_mouse_move_cb(Ecore_Evas *ee, const Ecore_Event_Mouse_Move *info)
ev->radius_y = info->multi.radius_y;
ev->pressure = info->multi.pressure;
ev->angle = info->multi.angle - ee->rotation;
if (info->dev) ev->device = efl_ref(info->dev);
else ev->device = efl_ref(evas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_MOUSE));
efl_event_callback_legacy_call(e, _event_description_get(ev->action), evt);
processed = ev->evas_done;
@ -3878,6 +3882,8 @@ _direct_mouse_wheel_cb(Ecore_Evas *ee, const Ecore_Event_Mouse_Wheel *info)
_pointer_position_set(ev, ee, info->x, info->y, info->x, info->y);
ev->wheel.z = info->z;
ev->wheel.dir = info->direction ? EFL_ORIENT_HORIZONTAL : EFL_ORIENT_VERTICAL;
if (info->dev) ev->device = efl_ref(info->dev);
else ev->device = efl_ref(evas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_MOUSE));
efl_event_callback_legacy_call(e, _event_description_get(ev->action), evt);
processed = ev->evas_done;
@ -3905,6 +3911,8 @@ _direct_mouse_inout(Ecore_Evas *ee, const Ecore_Event_Mouse_IO *info, Efl_Pointe
ev->action = action;
ev->timestamp = info->timestamp;
_pointer_position_set(ev, ee, info->x, info->y, info->x, info->y);
if (info->dev) ev->device = efl_ref(info->dev);
else ev->device = efl_ref(evas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_MOUSE));
efl_event_callback_legacy_call(e, _event_description_get(ev->action), evt);
processed = ev->evas_done;
@ -4032,6 +4040,8 @@ _direct_axis_update_cb(Ecore_Evas *ee, const Ecore_Event_Axis_Update *info)
}
}
_pointer_position_set(ev, ee, x, y, x, y);
if (info->dev) ev->device = efl_ref(info->dev);
else ev->device = efl_ref(evas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_MOUSE));
efl_event_callback_legacy_call(e, _event_description_get(ev->action), evt);
processed = ev->evas_done;
@ -4068,7 +4078,8 @@ _direct_key_updown_cb(Ecore_Evas *ee, const Ecore_Event_Key *info, Eina_Bool dow
ev->keycode = info->keycode;
ev->data = info->data;
ev->event_flags = 0;
ev->device = NULL; /* FIXME */
if (info->dev) ev->device = efl_ref(info->dev);
else ev->device = efl_ref(evas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_KEYBOARD));
if (down)
efl_event_callback_legacy_call(e, EFL_EVENT_KEY_DOWN, evt);

View File

@ -209,6 +209,8 @@ abstract Efl.Canvas.Object (Efl.Object, Efl.Gfx, Efl.Gfx.Stack, Efl.Animator,
is $true, $obj will be set as the currently focused object
and it will receive all keyboard events that are not
exclusive key grabs on other objects.
See also @.seat_focus_check,
@.seat_focus_add, @.seat_focus_del.
]]
set {
legacy: evas_object_focus_set;
@ -220,6 +222,55 @@ abstract Efl.Canvas.Object (Efl.Object, Efl.Gfx, Efl.Gfx.Stack, Efl.Animator,
focus: bool; [[$true when set as focused or $false otherwise.]]
}
}
@property seat_focus {
[[
Check if this object is focused.
@since 1.19
]]
get {
}
values {
focus: bool; [[$true if focused by at least one seat or $false otherwise.]]
}
}
seat_focus_check {
[[ Check if this object is focused by a given seat @since 1.19 ]]
params {
@in seat: Efl.Input.Device; [[The seat to check if the object is focused. Use $null for the default seat.]]
}
return: bool; [[$true if focused or $false otherwise.]]
}
seat_focus_add {
[[ Add a seat to the focus list.
Evas supports that an Efl.Canvas.Object may be focused by multiple seats
at the same time. This function adds a new seat to the focus list, in other words,
after the seat is added to the list this object will now be also focused by this new seat.
This function generates an \@ref EFL_CANVAS_OBJECT_EVENT_FOCUS_DEVICE_IN event.
\@note The old focus APIs ( \@ref evas_object_focus_get, \@ref evas_object_focus_set,
@.key_grab) will still work, however they will only act on the default seat.
@since 1.19
]]
params {
@in seat: Efl.Input.Device; [[The seat that should be added to the focus list. Use $null for the default seat.]]
}
return: bool; [[$true if the focus has been set or $false otherwise.]]
}
seat_focus_del {
[[ Remove a seat from the focus list.
Removing an seat from the focus list is an unfocus operation, thus it will generate an
\@ref EFL_CANVAS_OBJECT_EVENT_FOCUS_DEVICE_OUT event.
@since 1.19
]]
params {
@in seat: Efl.Input.Device; [[The seat that should be removed from the focus list. Use $null for the default seat.]]
}
return: bool; [[$true if the seat was removed from the focus list or $false otherwise.]]
}
@property is_frame_object {
set {
[[@since 1.2]]
@ -568,5 +619,7 @@ abstract Efl.Canvas.Object (Efl.Object, Efl.Gfx, Efl.Gfx.Stack, Efl.Animator,
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

@ -26,7 +26,7 @@ _efl_input_hold_hold_get(Eo *obj EINA_UNUSED, Efl_Input_Hold_Data *pd)
EOLIAN static void
_efl_input_hold_efl_input_event_device_set(Eo *obj EINA_UNUSED, Efl_Input_Hold_Data *pd, Efl_Input_Device *dev)
{
pd->device = dev;
pd->device = efl_ref(dev);
}
EOLIAN static Efl_Input_Device *
@ -70,6 +70,7 @@ _efl_input_hold_efl_object_constructor(Eo *obj, Efl_Input_Hold_Data *pd EINA_UNU
static inline void
_efl_input_hold_free(Efl_Input_Hold_Data *pd)
{
efl_unref(pd->device);
free(pd->legacy);
}
@ -110,7 +111,7 @@ _efl_input_hold_efl_input_event_dup(Eo *obj, Efl_Input_Hold_Data *pd)
ev->timestamp = pd->timestamp;
ev->data = pd->data;
ev->hold = pd->hold;
ev->device = pd->device; // lacks a proper ref :(
ev->device = efl_ref(pd->device);
return evt;
}

View File

@ -81,6 +81,7 @@ static inline void
_efl_input_key_free(Efl_Input_Key_Data *pd)
{
free(pd->legacy);
efl_unref(pd->device);
if (pd->no_stringshare) return;
eina_stringshare_del(pd->key);
eina_stringshare_del(pd->keyname);
@ -197,6 +198,7 @@ _efl_input_key_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Key_Data *pd)
ev->win_fed = 0;
ev->fake = 1;
ev->legacy = NULL;
ev->device = efl_ref(pd->device);
return evt;
}
@ -228,7 +230,7 @@ _efl_input_key_efl_input_event_event_flags_get(Eo *obj EINA_UNUSED, Efl_Input_Ke
EOLIAN static void
_efl_input_key_efl_input_event_device_set(Eo *obj EINA_UNUSED, Efl_Input_Key_Data *pd, Efl_Input_Device *dev)
{
pd->device = dev;
pd->device = efl_ref(dev);
}
EOLIAN static Efl_Input_Device *

View File

@ -93,6 +93,7 @@ static inline void
_efl_input_pointer_free(Efl_Input_Pointer_Data *pd)
{
free(pd->legacy);
efl_unref(pd->device);
}
EOLIAN static void
@ -130,6 +131,7 @@ _efl_input_pointer_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Pointer_Da
ev->win_fed = 0;
ev->fake = 1;
ev->legacy = NULL;
ev->device = efl_ref(pd->device);
return evt;
}
@ -222,8 +224,7 @@ _efl_input_pointer_delta_get(Eo *obj EINA_UNUSED, Efl_Input_Pointer_Data *pd, in
EOLIAN static void
_efl_input_pointer_efl_input_event_device_set(Eo *obj EINA_UNUSED, Efl_Input_Pointer_Data *pd, Efl_Input_Device *dev)
{
/* ref? */
pd->device = dev;
pd->device = efl_ref(dev);
}
EOLIAN static Efl_Input_Device *

View File

@ -119,9 +119,8 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
}
@property focus {
get {
[[Retrieve the object that currently has focus.
[[Retrieve the object focused by the default seat.
Evas can have (at most) one of its objects focused at a time.
Focused objects will be the ones having key events delivered
to, which the programmer can act upon by means of
\@ref evas_object_event_callback_add usage.
@ -136,7 +135,10 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
See also \@ref evas_object_focus_set,
\@ref evas_object_focus_get, \@ref evas_object_key_grab,
\@ref evas_object_key_ungrab.
\@ref evas_object_key_ungrab, @.seat_focus_get,
@.focused_objects.get, @Efl.Canvas.Object.seat_focus_check,
@Efl.Canvas.Object.seat_focus_add,
@Efl.Canvas.Object.seat_focus_del.
]]
/* FIXME-doc
Example:
@ -154,6 +156,23 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
or $null if there is not one.]]
}
}
@property focused_objects {
[[Return an iterator of focused objects. @since 1.19]]
get {
return: free(own(iterator<Eina_Hash_Tuple>), eina_iterator_free); [[An iterator that contains
Eina_Hash_Tuple which the key is an
Efl.Input.Device and the data is an Efl.Canvas.Object or $null on error.]]
}
}
seat_focus_get {
[[Return the focused object by a given seat. @since 1.19]]
params {
@in seat: Efl.Input.Device;[[The seat to fetch the focused
object or $null for the default seat.]]
}
return: Efl.Canvas.Object; [[The object that has the focus or $null if
the seat has no focused object.]]
}
@property object_top {
get {
[[Get the highest (stacked) Evas object on the canvas $e.
@ -1116,6 +1135,16 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
re-compute of that data etc.
]]
}
default_device_get {
[[Return the default device of a given type.
\@note Currently Evas only creates a seat, mouse and keyboard.
@since 1.19
]]
params {
@in type: Efl.Input.Device.Class; [[The class of the default device to fetch.]]
}
return: Efl.Input.Device; [[The default device or $null on error.]]
}
coord_world_y_to_screen @const {
[[Convert/scale a canvas coordinate into output screen
coordinates.

View File

@ -24,6 +24,53 @@
* here (callbacks and canvas private data).
*/
static Eina_Bool
_is_pointer(Evas_Device_Class clas)
{
if (clas == EVAS_DEVICE_CLASS_MOUSE ||
clas == EVAS_DEVICE_CLASS_TOUCH ||
clas == EVAS_DEVICE_CLASS_WAND ||
clas == EVAS_DEVICE_CLASS_PEN)
return EINA_TRUE;
return EINA_FALSE;
}
static Evas_Device *
_new_default_device_find(Evas_Public_Data *e, Evas_Device *old_dev)
{
Eina_List *l;
Evas_Device *dev, *def, *old_parent;
Evas_Device_Class old_class;
old_class = efl_input_device_type_get(old_dev);
old_parent = efl_input_device_parent_get(old_dev);
def = NULL;
EINA_LIST_FOREACH(e->devices, l, dev)
{
if (efl_input_device_type_get(dev) != old_class)
continue;
def = dev;
//Prefer devices with the same parent.
if (efl_input_device_parent_get(dev) == old_parent)
break;
}
if (!def)
{
const char *class_str;
if (old_class == EVAS_DEVICE_CLASS_SEAT)
class_str = "seat";
else if (old_class == EVAS_DEVICE_CLASS_KEYBOARD)
class_str = "keyboard";
else
class_str = "mouse";
WRN("Could not find a default %s device.", class_str);
}
return def;
}
static void
_del_cb(void *data, const Efl_Event *ev)
{
@ -31,6 +78,14 @@ _del_cb(void *data, const Efl_Event *ev)
// can not be done in std destructor
e->devices = eina_list_remove(e->devices, ev->object);
if (e->default_seat == ev->object)
e->default_seat = _new_default_device_find(e, ev->object);
else if (e->default_mouse == ev->object)
e->default_mouse = _new_default_device_find(e, ev->object);
else if (e->default_keyboard == ev->object)
e->default_keyboard = _new_default_device_find(e, ev->object);
efl_event_callback_call(e->evas, EFL_CANVAS_EVENT_DEVICE_REMOVED,
ev->object);
}
@ -66,6 +121,16 @@ evas_device_add_full(Evas *eo_e, const char *name, const char *desc,
d->evas = eo_e;
e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
/* This is the case when the user is using wayland backend,
since evas itself will not create the devices we must set them here. */
if (!e->default_seat && clas == EVAS_DEVICE_CLASS_SEAT)
e->default_seat = dev;
else if (!e->default_keyboard && clas == EVAS_DEVICE_CLASS_KEYBOARD)
e->default_keyboard = dev;
else if (!e->default_mouse && _is_pointer(clas))
e->default_mouse = dev;
e->devices = eina_list_append(e->devices, dev);
efl_event_callback_add(dev, EFL_EVENT_DEL, _del_cb, e);

View File

@ -369,6 +369,21 @@ _transform_to_src_space_f(Evas_Object_Protected_Data *obj, Evas_Object_Protected
point->y = tmp_y;
}
static Efl_Input_Device *
_evas_event_legacy_device_get(Eo *evas, Eina_Bool mouse)
{
Efl_Input_Device *dev = _evas_device_top_get(evas);
//The user did not push a device, use the default mouse/keyboard instead.
if (!dev)
{
Evas_Public_Data *e = efl_data_scope_get(evas, EVAS_CANVAS_CLASS);
if (mouse)
return e->default_mouse;
return e->default_keyboard;
}
return dev;
}
static void
_evas_event_source_mouse_down_events(Evas_Object *eo_obj, Evas *eo_e,
Efl_Input_Pointer *parent_ev, int event_id)
@ -1512,11 +1527,10 @@ _canvas_event_feed_mouse_updown_legacy(Eo *eo_e, int b, Evas_Button_Flags flags,
ev->data = (void *) data;
ev->timestamp = timestamp;
ev->device = _evas_device_top_get(eo_e);
ev->device = efl_ref(_evas_event_legacy_device_get(eo_e, EINA_TRUE));
ev->action = down ? EFL_POINTER_ACTION_DOWN : EFL_POINTER_ACTION_UP;
ev->button = b;
ev->button_flags = flags;
ev->device = _evas_device_top_get(e->evas);
ev->radius = 1;
ev->radius_x = 1;
ev->radius_y = 1;
@ -1613,7 +1627,7 @@ evas_event_feed_mouse_cancel(Eo *eo_e, unsigned int timestamp, const void *data)
ev->timestamp = timestamp;
ev->data = (void *) data;
ev->device = _evas_device_top_get(e->evas);
ev->device = efl_ref(_evas_event_legacy_device_get(e->evas, EINA_TRUE));
_canvas_event_feed_mouse_cancel_internal(e, ev);
@ -1652,7 +1666,6 @@ _canvas_event_feed_mouse_wheel_internal(Eo *eo_e, Efl_Input_Pointer_Data *pe)
ev->modifiers = &(e->modifiers);
ev->locks = &(e->locks);
ev->event_flags = e->default_event_flags;
ev->device = efl_ref(_evas_device_top_get(eo_e));
ev->action = EFL_POINTER_ACTION_WHEEL;
ev->value_flags |= value_flags;
@ -1677,7 +1690,6 @@ _canvas_event_feed_mouse_wheel_internal(Eo *eo_e, Efl_Input_Pointer_Data *pe)
eina_list_free(copy);
_evas_post_event_callback_call(eo_e, e);
efl_unref(ev->device);
efl_del(evt);
_evas_unwalk(e);
}
@ -1695,6 +1707,7 @@ evas_event_feed_mouse_wheel(Eo *eo_e, int direction, int z, unsigned int timesta
ev->wheel.z = z;
ev->timestamp = timestamp;
ev->data = (void *) data;
ev->device = efl_ref(_evas_event_legacy_device_get(eo_e, EINA_TRUE));
_canvas_event_feed_mouse_wheel_internal(eo_e, ev);
efl_del(evt);
@ -2069,7 +2082,7 @@ _canvas_event_feed_mouse_move_legacy(Evas *eo_e, Evas_Public_Data *e, int x, int
ev->data = (void *) data;
ev->timestamp = timestamp;
ev->device = _evas_device_top_get(eo_e);
ev->device = efl_ref(_evas_event_legacy_device_get(eo_e, EINA_TRUE));
ev->cur.x = x;
ev->cur.y = y;
@ -2243,7 +2256,7 @@ _canvas_event_feed_mouse_inout_legacy(Eo *eo_e, unsigned int timestamp,
ev->timestamp = timestamp;
ev->data = (void *) data;
ev->device = _evas_device_top_get(eo_e);
ev->device = efl_ref(_evas_event_legacy_device_get(eo_e, EINA_TRUE));
if (in)
_canvas_event_feed_mouse_in_internal(eo_e, ev);
@ -2443,7 +2456,7 @@ _canvas_event_feed_multi_internal(Evas *eo_e, Evas_Public_Data *e,
ev->button_flags = flags;
ev->timestamp = timestamp;
ev->data = (void *) data;
ev->device = _evas_device_top_get(eo_e);
ev->device = efl_ref(_evas_event_legacy_device_get(eo_e, EINA_TRUE));
switch (action)
{
@ -2651,6 +2664,48 @@ evas_event_feed_multi_move(Eo *eo_e, int d, int x, int y, double rad, double rad
EFL_POINTER_ACTION_MOVE);
}
static void
_key_event_dispatch(Evas_Public_Data *e, void *event_info,
Efl_Input_Device *device,
const Efl_Event_Description *efl_event_desc,
Evas_Callback_Type evas_event_type, int event_id)
{
Eo *focused;
if (!device)
device = e->default_seat;
else
{
const char *name = efl_input_device_name_get(device);
while ((device = efl_input_device_parent_get(device)))
{
if (efl_input_device_type_get(device) == EFL_INPUT_DEVICE_CLASS_SEAT)
break;
}
if (!device)
{
ERR("Could not find the parent seat from device name '%s'. Using default seat instead", name);
device = e->default_seat;
}
}
focused = eina_hash_find(e->focused_objects, &device);
if (!focused)
return;
Evas_Object_Protected_Data *focused_obj =
efl_data_scope_get(focused, EFL_CANVAS_OBJECT_CLASS);
if (!e->is_frozen && !evas_event_freezes_through(focused, focused_obj))
{
evas_object_event_callback_call(focused, focused_obj,
evas_event_type, event_info,
event_id, efl_event_desc);
}
}
static void
_canvas_event_feed_key_down_internal(Evas_Public_Data *e, Efl_Input_Key_Data *ev)
{
@ -2725,15 +2780,9 @@ _canvas_event_feed_key_down_internal(Evas_Public_Data *e, Efl_Input_Key_Data *ev
}
}
}
if ((e->focused) && (!exclusive))
{
Evas_Object_Protected_Data *focused_obj = efl_data_scope_get(e->focused, EFL_CANVAS_OBJECT_CLASS);
if (!e->is_frozen && !evas_event_freezes_through(e->focused, focused_obj))
{
evas_object_event_callback_call(e->focused, focused_obj, EVAS_CALLBACK_KEY_DOWN, evt,
event_id, EFL_EVENT_KEY_DOWN);
}
}
if (!exclusive)
_key_event_dispatch(e, evt, ev->device, EFL_EVENT_KEY_DOWN,
EVAS_CALLBACK_KEY_DOWN, event_id);
_evas_post_event_callback_call(e->evas, e);
_evas_unwalk(e);
@ -2815,16 +2864,9 @@ _canvas_event_feed_key_up_internal(Evas_Public_Data *e, Efl_Input_Key_Data *ev)
}
}
}
if ((e->focused) && (!exclusive))
{
Evas_Object_Protected_Data *focused_obj = efl_data_scope_get(e->focused, EFL_CANVAS_OBJECT_CLASS);
if (!e->is_frozen && !evas_event_freezes_through(e->focused, focused_obj))
{
evas_object_event_callback_call
(e->focused, focused_obj, EVAS_CALLBACK_KEY_UP, evt,
event_id, EFL_EVENT_KEY_UP);
}
}
if (!exclusive)
_key_event_dispatch(e, evt, ev->device, EFL_EVENT_KEY_UP,
EVAS_CALLBACK_KEY_UP, event_id);
_evas_post_event_callback_call(e->evas, e);
_evas_unwalk(e);
@ -2854,7 +2896,7 @@ _canvas_event_feed_key_legacy(Eo *eo_e, Evas_Public_Data *e,
ev->timestamp = timestamp;
ev->keycode = keycode;
ev->no_stringshare = EINA_TRUE;
ev->device = _evas_device_top_get(e->evas);
ev->device = efl_ref(_evas_event_legacy_device_get(e->evas, EINA_FALSE));
if (down)
_canvas_event_feed_key_down_internal(e, ev);
@ -2922,7 +2964,7 @@ evas_event_feed_hold(Eo *eo_e, int hold, unsigned int timestamp, const void *dat
ev->data = (void *) data;
ev->timestamp = timestamp;
ev->event_flags = e->default_event_flags;
ev->device = efl_ref(_evas_device_top_get(eo_e));
ev->device = efl_ref(_evas_event_legacy_device_get(eo_e, EINA_TRUE));
_evas_walk(e);
copy = evas_event_list_copy(e->pointer.object.in);
@ -2943,7 +2985,6 @@ evas_event_feed_hold(Eo *eo_e, int hold, unsigned int timestamp, const void *dat
_evas_unwalk(e);
_evas_object_event_new();
efl_unref(ev->device);
efl_del(evt);
}
@ -3101,7 +3142,7 @@ evas_event_feed_axis_update(Evas *eo_e, unsigned int timestamp, int device, int
ev->cur.y = y;
/* FIXME: set proper device based on the device id (X or WL specific) */
ev->device = _evas_device_top_get(eo_e); // FIXME
ev->device = efl_ref(_evas_event_legacy_device_get(eo_e, EINA_TRUE)); // FIXME
(void) device;
_canvas_event_feed_axis_update_internal(e, ev);
@ -3371,7 +3412,7 @@ _evas_canvas_event_pointer_cb(void *data, const Efl_Event *event)
if (!ev->device)
{
nodev = 1;
ev->device = _evas_device_top_get(e->evas);
ev->device = _evas_event_legacy_device_get(e->evas, EINA_TRUE);
}
switch (ev->action)
@ -3440,7 +3481,7 @@ _evas_canvas_event_key_cb(void *data, const Efl_Event *event)
if (!ev->device)
{
nodev = 1;
ev->device = _evas_device_top_get(e->evas);
ev->device = _evas_event_legacy_device_get(e->evas, EINA_FALSE);
}
if (ev->pressed)

View File

@ -7,51 +7,247 @@
/* public calls */
static Eina_Bool
_already_focused(Eina_List *seats, Efl_Input_Device *seat)
{
Eina_List *l;
const Efl_Input_Device *s;
EINA_LIST_FOREACH(seats, l, s)
{
if (s == seat)
return EINA_TRUE;
}
return EINA_FALSE;
}
static Efl_Input_Device *
_default_seat_get(Eo *evas_obj)
{
Evas_Public_Data *edata;
Evas *evas = evas_object_evas_get(evas_obj);
edata = efl_data_scope_get(evas, EVAS_CANVAS_CLASS);
return edata->default_seat;
}
static void
_evas_focus_set(Eo *evas_obj, Efl_Input_Device *key, Eina_Bool focus)
{
Evas_Public_Data *edata;
Evas *evas = evas_object_evas_get(evas_obj);
edata = efl_data_scope_get(evas, EVAS_CANVAS_CLASS);
if (focus)
eina_hash_add(edata->focused_objects, &key, evas_obj);
else
eina_hash_del_by_key(edata->focused_objects, &key);
}
static Eo *
_current_focus_get(Eo *evas_obj, Efl_Input_Device *key)
{
Evas_Public_Data *edata;
Evas *evas = evas_object_evas_get(evas_obj);
edata = efl_data_scope_get(evas, EVAS_CANVAS_CLASS);
return eina_hash_find(edata->focused_objects, &key);
}
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_post_event_callback_call(obj->layer->evas->evas,
obj->layer->evas);
}
void
_evas_focus_device_del_cb(void *data, const Efl_Event *ev)
{
_evas_object_unfocus(data, ev->object);
}
EOLIAN Eina_Bool
_efl_canvas_object_seat_focus_del(Eo *eo_obj,
Evas_Object_Protected_Data *obj,
Efl_Input_Device *seat)
{
Eina_List *l;
Efl_Input_Device *dev, *def;
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
return EINA_FALSE;
MAGIC_CHECK_END();
def = _default_seat_get(eo_obj);
if (!seat)
seat = def;
EINA_LIST_FOREACH(obj->focused_by_seats, l, dev)
{
if (dev != seat)
continue;
if (_evas_object_intercept_call(eo_obj,
EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET,
1, EINA_FALSE))
{
return EINA_FALSE;
}
efl_event_callback_del(dev, EFL_EVENT_DEL,
_evas_focus_device_del_cb, obj);
_evas_object_unfocus(obj, dev);
return EINA_TRUE;
}
return EINA_FALSE;
}
EOLIAN Eina_Bool
_efl_canvas_object_seat_focus_add(Eo *eo_obj,
Evas_Object_Protected_Data *obj,
Efl_Input_Device *seat)
{
Eo *current_focus;
Efl_Input_Device *def;
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
return EINA_FALSE;
MAGIC_CHECK_END();
def = _default_seat_get(eo_obj);
if (!seat)
seat = def;
EINA_SAFETY_ON_NULL_RETURN_VAL(seat, EINA_FALSE);
if (efl_input_device_type_get(seat) != EFL_INPUT_DEVICE_CLASS_SEAT)
return EINA_FALSE;
if (_already_focused(obj->focused_by_seats, seat))
goto end;
if (_evas_object_intercept_call(eo_obj, EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET,
1, EINA_TRUE))
{
return EINA_FALSE;
}
current_focus = _current_focus_get(eo_obj, seat);
if (current_focus)
efl_canvas_object_seat_focus_del(current_focus, seat);
efl_event_callback_add(seat, EFL_EVENT_DEL, _evas_focus_device_del_cb, 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 == def)
{
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);
end:
_evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas);
return EINA_TRUE;
}
EOLIAN Eina_Bool
_efl_canvas_object_seat_focus_check(Eo *eo_obj,
Evas_Object_Protected_Data *obj,
Efl_Input_Device *seat)
{
Eina_List *l;
Efl_Input_Device *s;
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
return EINA_FALSE;
MAGIC_CHECK_END();
if (!seat)
seat = _default_seat_get(eo_obj);
EINA_LIST_FOREACH(obj->focused_by_seats, l, s)
{
if (s == seat)
return EINA_TRUE;
}
return EINA_FALSE;
}
EOLIAN void
_efl_canvas_object_key_focus_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Eina_Bool focus)
{
int event_id = 0;
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
event_id = _evas_object_event_new();
if (obj->focused == focus) goto end;
if (_evas_object_intercept_call(eo_obj, EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET, 1, focus)) return;
if (focus)
{
if (obj->layer->evas->focused)
evas_object_focus_set(obj->layer->evas->focused, 0);
if (obj->layer->evas->focused) goto end;
obj->focused = 1;
obj->layer->evas->focused = eo_obj;
evas_object_event_callback_call(eo_obj, obj, EVAS_CALLBACK_FOCUS_IN, NULL, event_id, EFL_CANVAS_OBJECT_EVENT_FOCUS_IN);
evas_event_callback_call(obj->layer->evas->evas,
EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN, eo_obj);
}
_efl_canvas_object_seat_focus_add(eo_obj, obj, NULL);
else
{
obj->focused = 0;
obj->layer->evas->focused = NULL;
evas_object_event_callback_call(eo_obj, obj, EVAS_CALLBACK_FOCUS_OUT, NULL, event_id, EFL_CANVAS_OBJECT_EVENT_FOCUS_OUT);
evas_event_callback_call(obj->layer->evas->evas,
EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT, eo_obj);
}
end:
_evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas);
_efl_canvas_object_seat_focus_del(eo_obj, obj, NULL);
}
EOLIAN Eina_Bool
_efl_canvas_object_key_focus_get(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
_efl_canvas_object_seat_focus_get(Eo *eo_obj, Evas_Object_Protected_Data *obj)
{
return obj->focused;
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
return EINA_FALSE;
MAGIC_CHECK_END();
return eina_list_count(obj->focused_by_seats) ? EINA_TRUE : EINA_FALSE;
}
EOLIAN Eina_Bool
_efl_canvas_object_key_focus_get(Eo *eo_obj, Evas_Object_Protected_Data *obj)
{
return _efl_canvas_object_seat_focus_check(eo_obj, obj, NULL);
}
EOLIAN Evas_Object *
_evas_canvas_seat_focus_get(Eo *eo_obj EINA_UNUSED, Evas_Public_Data *e,
Efl_Input_Device *seat)
{
if (!seat)
seat = e->default_seat;
return eina_hash_find(e->focused_objects, &seat);
}
EOLIAN Evas_Object*
_evas_canvas_focus_get(Eo *eo_obj EINA_UNUSED, Evas_Public_Data *e)
{
return e->focused;
return _evas_canvas_seat_focus_get(eo_obj, e, NULL);
}
EOLIAN Eina_Iterator *
_evas_canvas_focused_objects_get(Eo *eo_obj EINA_UNUSED, Evas_Public_Data *e)
{
return eina_hash_iterator_tuple_new(e->focused_objects);
}

View File

@ -212,6 +212,8 @@ _evas_canvas_efl_object_constructor(Eo *eo_obj, Evas_Public_Data *e)
_evas_canvas_event_init(eo_obj, e);
e->focused_objects = eina_hash_pointer_new(NULL);
return eo_obj;
}
@ -342,6 +344,7 @@ _evas_canvas_efl_object_destructor(Eo *eo_e, Evas_Public_Data *e)
eina_array_flush(&e->image_unref_queue);
eina_array_flush(&e->glyph_unref_queue);
eina_array_flush(&e->texts_unref_queue);
eina_hash_free(e->focused_objects);
EINA_LIST_FREE(e->touch_points, touch_point)
free(touch_point);
@ -410,6 +413,20 @@ _evas_canvas_coord_world_y_to_screen(const Eo *eo_e EINA_UNUSED, Evas_Public_Dat
else return (int)((((long long)y - (long long)e->viewport.y) * (long long)e->output.h) / (long long)e->viewport.h);
}
EOLIAN static Efl_Input_Device *
_evas_canvas_default_device_get(Eo *eo_e EINA_UNUSED,
Evas_Public_Data *e,
Efl_Input_Device_Class klass)
{
if (klass == EFL_INPUT_DEVICE_CLASS_SEAT)
return e->default_seat;
if (klass == EFL_INPUT_DEVICE_CLASS_MOUSE)
return e->default_mouse;
if (klass == EFL_INPUT_DEVICE_CLASS_KEYBOARD)
return e->default_keyboard;
return NULL;
}
EAPI int
evas_render_method_lookup(const char *name)
{
@ -807,7 +824,25 @@ evas_output_method_set(Evas *eo_e, int render_method)
evas_module_ref(em);
/* get the engine info struct */
if (e->engine.func->info) e->engine.info = e->engine.func->info(eo_e);
return;
//Wayland already handle seats.
if (render_method == evas_render_method_lookup("wayland_shm") ||
render_method == evas_render_method_lookup("wayland_egl"))
return;
e->default_seat = evas_device_add_full(eo_e, "default", "The default seat",
NULL, NULL, EVAS_DEVICE_CLASS_SEAT,
EVAS_DEVICE_SUBCLASS_NONE);
e->default_mouse = evas_device_add_full(eo_e, "keyboard",
"The default mouse",
e->default_seat, NULL,
EVAS_DEVICE_CLASS_MOUSE,
EVAS_DEVICE_SUBCLASS_NONE);
e->default_keyboard = evas_device_add_full(eo_e, "keyboard",
"The default keyboard",
e->default_seat, NULL,
EVAS_DEVICE_CLASS_KEYBOARD,
EVAS_DEVICE_SUBCLASS_NONE);
}
EAPI int

View File

@ -696,14 +696,25 @@ _efl_canvas_object_efl_object_destructor(Eo *eo_obj, Evas_Object_Protected_Data
Evas_Object *proxy;
Eina_List *l, *l2;
Evas_Canvas3D_Texture *texture;
Efl_Input_Device *dev;
Evas_Public_Data *edata;
edata = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS);
evas_object_hide(eo_obj);
if (obj->focused)
EINA_LIST_FREE (obj->focused_by_seats, dev)
{
obj->focused = EINA_FALSE;
if ((obj->layer) && (obj->layer->evas))
obj->layer->evas->focused = NULL;
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_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);
if ((obj->layer) && (obj->layer->evas))
_evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas);
}

View File

@ -889,7 +889,7 @@ struct _Evas_Public_Data
int in_smart_calc;
int smart_calc_count;
Evas_Object *focused;
Eina_Hash *focused_objects; //Key - seat; value - the focused object
void *attach_data;
Evas_Modifier modifiers;
Evas_Lock locks;
@ -905,6 +905,10 @@ struct _Evas_Public_Data
Eina_List *outputs;
Evas_Device *default_seat;
Evas_Device *default_mouse;
Evas_Device *default_keyboard;
unsigned char changed : 1;
unsigned char delete_me : 1;
unsigned char invalidate : 1;
@ -1105,6 +1109,7 @@ struct _Evas_Object_Protected_Data
const Evas_Object_Map_Data *map;
const Evas_Object_3D_Data *data_3d;
const Evas_Object_Mask_Data *mask;
Eina_List *focused_by_seats;
// Pointer to the Evas_Object itself
Evas_Object *object;
@ -1154,7 +1159,6 @@ struct _Evas_Object_Protected_Data
Eina_Bool rect_del : 1;
Eina_Bool mouse_in : 1;
Eina_Bool pre_render_done : 1;
Eina_Bool focused : 1;
Eina_Bool in_layer : 1;
Eina_Bool no_propagate : 1;
@ -1711,6 +1715,7 @@ void _canvas_font_cache_flush(Eo *e, void *_pd, va_list *list);
void _canvas_font_cache_set(Eo *e, void *_pd, va_list *list);
void _canvas_font_cache_get(Eo *e, void *_pd, va_list *list);
void _canvas_font_available_list(Eo *e, void *_pd, va_list *list);
void _evas_focus_device_del_cb(void *data, const Efl_Event *ev);
void _canvas_key_modifier_get(Eo *e, void *_pd, va_list *list);
void _canvas_key_lock_get(Eo *e, void *_pd, va_list *list);