summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Dilly <bdilly@profusion.mobi>2016-11-08 17:55:07 -0200
committerBruno Dilly <bdilly@profusion.mobi>2016-11-08 17:55:07 -0200
commit2a96097a658e0817c95f72b56d37879720886fa5 (patch)
tree9525053a9ba47f30508d8b71cf8ffbe7a4aeca87
parent11ef74c9620796c21e0979c12a2da49b3ebde82c (diff)
parent0e53b9a8ac92041de40244a597087d77611b92f2 (diff)
downloadefl-2a96097a658e0817c95f72b56d37879720886fa5.tar.gz
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
-rw-r--r--src/lib/ecore_evas/ecore_evas.c13
-rw-r--r--src/lib/evas/canvas/efl_canvas_object.eo53
-rw-r--r--src/lib/evas/canvas/efl_input_hold.c5
-rw-r--r--src/lib/evas/canvas/efl_input_key.c4
-rw-r--r--src/lib/evas/canvas/efl_input_pointer.c5
-rw-r--r--src/lib/evas/canvas/evas_canvas.eo35
-rw-r--r--src/lib/evas/canvas/evas_device.c65
-rw-r--r--src/lib/evas/canvas/evas_events.c107
-rw-r--r--src/lib/evas/canvas/evas_focus.c246
-rw-r--r--src/lib/evas/canvas/evas_main.c37
-rw-r--r--src/lib/evas/canvas/evas_object_main.c21
-rw-r--r--src/lib/evas/include/evas_private.h9
12 files changed, 525 insertions, 75 deletions
diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c
index 51f89fb45a..56bf222adc 100644
--- a/src/lib/ecore_evas/ecore_evas.c
+++ b/src/lib/ecore_evas/ecore_evas.c
@@ -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);
diff --git a/src/lib/evas/canvas/efl_canvas_object.eo b/src/lib/evas/canvas/efl_canvas_object.eo
index 84c7f8dd8f..69121114fc 100644
--- a/src/lib/evas/canvas/efl_canvas_object.eo
+++ b/src/lib/evas/canvas/efl_canvas_object.eo
@@ -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]]
}
}
diff --git a/src/lib/evas/canvas/efl_input_hold.c b/src/lib/evas/canvas/efl_input_hold.c
index 4c509dce60..774af38ed6 100644
--- a/src/lib/evas/canvas/efl_input_hold.c
+++ b/src/lib/evas/canvas/efl_input_hold.c
@@ -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;
}
diff --git a/src/lib/evas/canvas/efl_input_key.c b/src/lib/evas/canvas/efl_input_key.c
index c69491c165..387723b9c6 100644
--- a/src/lib/evas/canvas/efl_input_key.c
+++ b/src/lib/evas/canvas/efl_input_key.c
@@ -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 *
diff --git a/src/lib/evas/canvas/efl_input_pointer.c b/src/lib/evas/canvas/efl_input_pointer.c
index 68c13bc597..9b068d7730 100644
--- a/src/lib/evas/canvas/efl_input_pointer.c
+++ b/src/lib/evas/canvas/efl_input_pointer.c
@@ -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 *
diff --git a/src/lib/evas/canvas/evas_canvas.eo b/src/lib/evas/canvas/evas_canvas.eo
index bd60468b39..6888257a25 100644
--- a/src/lib/evas/canvas/evas_canvas.eo
+++ b/src/lib/evas/canvas/evas_canvas.eo
@@ -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.
diff --git a/src/lib/evas/canvas/evas_device.c b/src/lib/evas/canvas/evas_device.c
index f243b894f0..14ebfe3216 100644
--- a/src/lib/evas/canvas/evas_device.c
+++ b/src/lib/evas/canvas/evas_device.c
@@ -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);
diff --git a/src/lib/evas/canvas/evas_events.c b/src/lib/evas/canvas/evas_events.c
index b345a7aa5c..d199cfc885 100644
--- a/src/lib/evas/canvas/evas_events.c
+++ b/src/lib/evas/canvas/evas_events.c
@@ -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)
{
@@ -2652,6 +2665,48 @@ evas_event_feed_multi_move(Eo *eo_e, int d, int x, int y, double rad, double rad
}
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)
{
Eina_Bool exclusive = EINA_FALSE;
@@ -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)
diff --git a/src/lib/evas/canvas/evas_focus.c b/src/lib/evas/canvas/evas_focus.c
index 6737589a3a..96cf0ca947 100644
--- a/src/lib/evas/canvas/evas_focus.c
+++ b/src/lib/evas/canvas/evas_focus.c
@@ -7,51 +7,247 @@
/* public calls */
-EOLIAN void
-_efl_canvas_object_key_focus_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Eina_Bool focus)
+
+static Eina_Bool
+_already_focused(Eina_List *seats, Efl_Input_Device *seat)
{
+ Eina_List *l;
+ const Efl_Input_Device *s;
- int event_id = 0;
- MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
- return;
- MAGIC_CHECK_END();
+ 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);
- 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)
+ 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)
{
- 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_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_IN, eo_obj);
+ EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
+ obj->object);
}
- else
+ 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))
{
- 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);
+ 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_OUT, eo_obj);
+ 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_key_focus_get(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
+_efl_canvas_object_seat_focus_check(Eo *eo_obj,
+ Evas_Object_Protected_Data *obj,
+ Efl_Input_Device *seat)
{
- return obj->focused;
+ 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)
+{
+ MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
+ return;
+ MAGIC_CHECK_END();
+
+ if (focus)
+ _efl_canvas_object_seat_focus_add(eo_obj, obj, NULL);
+ else
+ _efl_canvas_object_seat_focus_del(eo_obj, obj, NULL);
+}
+
+EOLIAN Eina_Bool
+_efl_canvas_object_seat_focus_get(Eo *eo_obj, Evas_Object_Protected_Data *obj)
+{
+ 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);
}
diff --git a/src/lib/evas/canvas/evas_main.c b/src/lib/evas/canvas/evas_main.c
index e3283896fe..822b387d22 100644
--- a/src/lib/evas/canvas/evas_main.c
+++ b/src/lib/evas/canvas/evas_main.c
@@ -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
diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c
index 76c3c2bf66..c74d01dea3 100644
--- a/src/lib/evas/canvas/evas_object_main.c
+++ b/src/lib/evas/canvas/evas_object_main.c
@@ -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);
}
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index 5d7168451c..bb24435567 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -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);