diff options
author | Bruno Dilly <bdilly@profusion.mobi> | 2016-11-08 17:55:07 -0200 |
---|---|---|
committer | Bruno Dilly <bdilly@profusion.mobi> | 2016-11-08 17:55:07 -0200 |
commit | 2a96097a658e0817c95f72b56d37879720886fa5 (patch) | |
tree | 9525053a9ba47f30508d8b71cf8ffbe7a4aeca87 | |
parent | 11ef74c9620796c21e0979c12a2da49b3ebde82c (diff) | |
parent | 0e53b9a8ac92041de40244a597087d77611b92f2 (diff) | |
download | efl-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.c | 13 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_canvas_object.eo | 53 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_input_hold.c | 5 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_input_key.c | 4 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_input_pointer.c | 5 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_canvas.eo | 35 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_device.c | 65 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_events.c | 107 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_focus.c | 246 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_main.c | 37 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_object_main.c | 21 | ||||
-rw-r--r-- | src/lib/evas/include/evas_private.h | 9 |
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); |