Introduce efl_ui_widget_focus_manager

Summary:
The mixin encapsulates the correct
- creation
- composition attaching
- Lifecycle handling

of the focus managers that are assosiated with the object.

This fixes error messages on shutdown, and additionally lifetime issues
where the composite_attached object was deleted before the object was
deleted.

Reviewers: cedric, zmike

Reviewed By: zmike

Subscribers: segfaultxavi, zmike

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D6108
This commit is contained in:
Marcel Hollerbach 2018-05-16 13:30:28 -04:00 committed by Mike Blumenkrantz
parent f1c03000c9
commit a218c883c7
18 changed files with 111 additions and 60 deletions

View File

@ -125,6 +125,7 @@ elm_public_eolian_files = \
lib/elementary/efl_ui_tab_bar.eo \
lib/elementary/efl_ui_tab_page.eo \
lib/elementary/efl_ui_tab_page_part_tab.eo \
lib/elementary/efl_ui_widget_focus_manager.eo \
$(NULL)
# More public files -- FIXME
@ -861,6 +862,7 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/efl_ui_tab_pager.c \
lib/elementary/efl_ui_tab_bar.c \
lib/elementary/efl_ui_tab_page.c \
lib/elementary/efl_ui_widget_focus_manager.c \
$(NULL)

View File

@ -2,6 +2,7 @@
# include "elementary_config.h"
#endif
#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED
#define EFL_UI_FOCUS_LAYER_PROTECTED
#include <Elementary.h>
@ -18,9 +19,10 @@ typedef struct {
} Efl_Ui_Focus_Layer_Data;
EOLIAN static Efl_Ui_Focus_Manager*
_efl_ui_focus_layer_efl_ui_widget_focus_manager_create(Eo *obj, Efl_Ui_Focus_Layer_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
_efl_ui_focus_layer_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj, Efl_Ui_Focus_Layer_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
{
return efl_add(EFL_UI_FOCUS_MANAGER_ROOT_FOCUS_CLASS, obj, efl_ui_focus_manager_root_set(efl_added, root));
pd->manager = efl_add(EFL_UI_FOCUS_MANAGER_ROOT_FOCUS_CLASS, obj, efl_ui_focus_manager_root_set(efl_added, root));
return pd->manager;
}
EOLIAN static void
@ -87,8 +89,6 @@ EOLIAN static Efl_Object*
_efl_ui_focus_layer_efl_object_constructor(Eo *obj, Efl_Ui_Focus_Layer_Data *pd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->manager = efl_ui_widget_focus_manager_create(obj, obj);
efl_composite_attach(obj, pd->manager);
pd->enable_on_visible = EINA_TRUE;
pd->cycle = EINA_TRUE;
return obj;

View File

@ -1,4 +1,4 @@
mixin Efl.Ui.Focus.Layer (Efl.Interface, Efl.Ui.Widget, Efl.Gfx.Entity, Efl.Ui.Focus.Manager) {
mixin Efl.Ui.Focus.Layer (Efl.Interface, Efl.Ui.Widget, Efl.Gfx.Entity, Efl.Ui.Widget_Focus_Manager) {
[[This defines the inheriting widget as focus layer
A focus layer is the uppermost one which received input and handles all focus related events for as long as it exists and is visible. It's NOT possible to escape this layer with focus movement.
@ -21,7 +21,7 @@ mixin Efl.Ui.Focus.Layer (Efl.Interface, Efl.Ui.Widget, Efl.Gfx.Entity, Efl.Ui.F
}
}
implements {
Efl.Ui.Widget.focus_manager_create;
Efl.Ui.Widget_Focus_Manager.focus_manager_create;
Efl.Ui.Widget.focus_state_apply;
Efl.Gfx.Entity.visible {set;}
Efl.Ui.Focus.Manager.move;

View File

@ -10,6 +10,7 @@
#define EFL_GFX_SIZE_HINT_PROTECTED
#define EFL_UI_VIEW_LIST_PROTECTED
#define EFL_UI_FOCUS_COMPOSITION_PROTECTED
#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED
#include <Elementary.h>
#include "efl_ui_view_list_private.h"
@ -659,7 +660,7 @@ _efl_ui_view_list_efl_canvas_group_group_del(Eo *obj, Efl_Ui_View_List_Data *pd)
}
EOLIAN static Efl_Ui_Focus_Manager*
_efl_ui_view_list_efl_ui_widget_focus_manager_create(Eo *obj EINA_UNUSED, Efl_Ui_View_List_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
_efl_ui_view_list_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj EINA_UNUSED, Efl_Ui_View_List_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
{
if (!pd->manager)
pd->manager = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj,
@ -687,8 +688,6 @@ _efl_ui_view_list_efl_object_finalize(Eo *obj, Efl_Ui_View_List_Data *pd)
EOLIAN static Eo *
_efl_ui_view_list_efl_object_constructor(Eo *obj, Efl_Ui_View_List_Data *pd)
{
Efl_Ui_Focus_Manager *manager;
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->obj = obj;
efl_canvas_object_type_set(obj, MY_CLASS_NAME);
@ -697,10 +696,6 @@ _efl_ui_view_list_efl_object_constructor(Eo *obj, Efl_Ui_View_List_Data *pd)
pd->segarray = efl_add(EFL_UI_VIEW_LIST_SEGARRAY_CLASS, obj, efl_ui_view_list_segarray_setup(efl_added, 32));
manager = efl_ui_widget_focus_manager_create(obj, obj);
efl_composite_attach(obj, manager);
_efl_ui_focus_manager_redirect_events_add(manager, obj);
efl_event_callback_add(obj, EFL_UI_FOCUS_MANAGER_EVENT_FOCUSED, _list_element_focused, NULL);
efl_ui_focus_composition_custom_manager_set(obj, obj);

View File

@ -8,7 +8,7 @@ struct Efl.Ui.View_List_Item_Event
}
class Efl.Ui.View_List (Efl.Ui.Layout.Object, Efl.Ui.View, Efl.Ui.Scrollable_Interactive, Efl.Ui.Scrollbar,
Efl.Access.Widget.Action, Efl.Access.Selection, Efl.Ui.Focus.Composition, Efl.Ui.Focus.Manager_Sub,
Efl.Ui.Clickable, Efl.Ui.Selectable, Efl.Ui.View_List_Model)
Efl.Ui.Clickable, Efl.Ui.Selectable, Efl.Ui.View_List_Model, Efl.Ui.Widget_Focus_Manager)
{
methods {
@property relayout {
@ -77,7 +77,7 @@ class Efl.Ui.View_List (Efl.Ui.Layout.Object, Efl.Ui.View, Efl.Ui.Scrollable_Int
Efl.Ui.View_List_Model.min_size { get; set; }
// Widget
Efl.Ui.Widget.focus_manager_create;
Efl.Ui.Widget_Focus_Manager.focus_manager_create;
Efl.Ui.Widget.widget_event;
Efl.Ui.Widget.focus_state_apply;
Efl.Ui.Focus.Composition.prepare;

View File

@ -5649,14 +5649,6 @@ _efl_ui_widget_efl_ui_focus_object_focus_set(Eo *obj, Elm_Widget_Smart_Data *pd,
efl_ui_focus_object_on_focus_update(obj);
}
EOLIAN static Efl_Ui_Focus_Manager*
_efl_ui_widget_focus_manager_create(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root EINA_UNUSED)
{
ERR("No manager presented");
return NULL;
}
/* Legacy APIs */
/* elm_object_content_xxx APIs are supposed to work on all objects for which

View File

@ -551,17 +551,6 @@ abstract Efl.Ui.Widget (Efl.Canvas.Group, Efl.Access.Object,
}
return: bool; [[Returns whether the widget is registered or not.]]
}
focus_manager_create @protected {
[[If the widget needs a focus manager, this function will be called.
It can be used and overriden to inject your own manager or set
custom options on the focus manager.
]]
params {
@in root: Efl.Ui.Focus.Object; [[The logical root object for focus.]]
}
return: Efl.Ui.Focus.Manager; [[The focus manager.]]
}
}
parts {
shadow: Efl.Ui.Widget_Part_Shadow;

View File

@ -0,0 +1,60 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED
#include <Elementary.h>
#include <Elementary_Cursor.h>
#include "elm_priv.h"
#define MY_CLASS EFL_UI_WIDGET_FOCUS_MANAGER_MIXIN
typedef struct
{
Efl_Ui_Focus_Manager *manager;
} Efl_Ui_Widget_Focus_Manager_Data;
EOLIAN static Efl_Object*
_efl_ui_widget_focus_manager_efl_object_constructor(Eo *obj, Efl_Ui_Widget_Focus_Manager_Data *pd)
{
Eo *res;
pd->manager = efl_ui_widget_focus_manager_create(obj, obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->manager, res);
efl_ref(pd->manager);
efl_composite_attach(obj, pd->manager);
_efl_ui_focus_manager_redirect_events_add(pd->manager, obj);
res = efl_constructor(efl_super(obj, MY_CLASS));
return res;
}
EOLIAN static void
_efl_ui_widget_focus_manager_efl_object_destructor(Eo *obj, Efl_Ui_Widget_Focus_Manager_Data *pd)
{
efl_destructor(efl_super(obj, MY_CLASS));
_efl_ui_focus_manager_redirect_events_del(pd->manager, obj);
efl_unref(pd->manager);
pd->manager = NULL;
}
EOLIAN static Eina_Bool
_efl_ui_widget_focus_manager_efl_ui_widget_focus_state_apply(Eo *obj, Efl_Ui_Widget_Focus_Manager_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect)
{
Eina_Bool state;
state = efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, redirect);
if (!state && !configured_state->manager && current_state.manager)
efl_ui_focus_manager_reset_history(obj);
return state;
}
#include "efl_ui_widget_focus_manager.eo.c"

View File

@ -0,0 +1,22 @@
mixin Efl.Ui.Widget_Focus_Manager (Efl.Interface, Efl.Ui.Widget, Efl.Ui.Focus.Manager)
{
methods {
focus_manager_create @protected @pure_virtual {
[[If the widget needs a focus manager, this function will be called.
It can be used and overriden to inject your own manager or set
custom options on the focus manager.
]]
params {
@in root: Efl.Ui.Focus.Object; [[The logical root object for focus.]]
}
return: Efl.Ui.Focus.Manager; [[The focus manager.]]
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Ui.Widget.focus_state_apply;
}
}

View File

@ -14,6 +14,7 @@
#define EFL_UI_FOCUS_OBJECT_PROTECTED
#define EFL_UI_WIN_BETA
#define EFL_CANVAS_SCENE_BETA
#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED
#include <Elementary.h>
#include <Elementary_Cursor.h>
@ -180,7 +181,6 @@ struct _Efl_Ui_Win_Data
Evas_Object *main_menu;
Efl_Ui_Focus_Manager *manager;
Efl_Ui_Focus_Parent_Provider_Standard *provider;
struct
@ -5603,7 +5603,7 @@ _efl_ui_win_efl_canvas_object_legacy_ctor(Eo *obj, Efl_Ui_Win_Data *sd)
}
EOLIAN static Efl_Ui_Focus_Manager*
_efl_ui_win_efl_ui_widget_focus_manager_create(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
_efl_ui_win_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
{
Efl_Ui_Focus_Manager *manager;
@ -5637,7 +5637,6 @@ _efl_ui_win_efl_object_constructor(Eo *obj, Efl_Ui_Win_Data *pd)
* really bad and hacky. Needs fixing. */
pd->obj = obj;
pd->manager = efl_ui_widget_focus_manager_create(obj, obj);
pd->provider = efl_add(EFL_UI_FOCUS_PARENT_PROVIDER_STANDARD_CLASS, obj);
pd->profile.available = eina_array_new(4);
@ -5645,9 +5644,6 @@ _efl_ui_win_efl_object_constructor(Eo *obj, Efl_Ui_Win_Data *pd)
if (!efl_parent_get(obj))
efl_allow_parent_unref_set(obj, EINA_TRUE);
efl_composite_attach(obj, pd->manager);
_efl_ui_focus_manager_redirect_events_add(pd->manager, obj);
return obj;
}

View File

@ -158,7 +158,7 @@ class Efl.Ui.Win (Efl.Ui.Widget, Efl.Canvas.Scene, Efl.Canvas.Pointer, Efl.Acces
Efl.Access.Component, Efl.Access.Widget.Action,
Efl.Content, Efl.Input.State, Efl.Input.Interface, Efl.Screen,
Efl.Gfx.Size_Hint, Efl.Text, Efl.Config_Global, Efl.Part,
Efl.Ui.Focus.Manager, Efl.Ui.Focus.Manager_Window_Root)
Efl.Ui.Widget_Focus_Manager, Efl.Ui.Focus.Manager_Window_Root)
{
[[Efl UI window class]]
legacy_prefix: elm_win;
@ -787,7 +787,7 @@ class Efl.Ui.Win (Efl.Ui.Widget, Efl.Canvas.Scene, Efl.Canvas.Pointer, Efl.Acces
Efl.Ui.Widget.focus_highlight_animate { get; set; }
Efl.Ui.Focus.Object.on_focus_update;
Efl.Ui.Widget.widget_event;
Efl.Ui.Widget.focus_manager_create;
Efl.Ui.Widget_Focus_Manager.focus_manager_create;
Efl.Access.Object.state_set { get; }
Efl.Access.Object.i18n_name { get; }
Efl.Access.Component.extents { get; }

View File

@ -8,6 +8,7 @@
#define EFL_ACCESS_EDITABLE_TEXT_PROTECTED
#define ELM_LAYOUT_PROTECTED
#define EFL_UI_FOCUS_OBJECT_PROTECTED
#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED 1
#define EFL_ACCESS_WIDGET_ACTION_PROTECTED
#include <Elementary.h>
@ -6139,7 +6140,7 @@ _elm_entry_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, E
}
EOLIAN static Efl_Ui_Focus_Manager*
_elm_entry_efl_ui_widget_focus_manager_create(Eo *obj, Elm_Entry_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
_elm_entry_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj, Elm_Entry_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
{
return efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj,
efl_ui_focus_manager_root_set(efl_added, root)

View File

@ -844,7 +844,7 @@ class Elm.Entry (Efl.Ui.Layout.Object, Elm.Interface_Scrollable, Efl.Ui.Clickabl
Efl.Layout.Calc.calc_force;
Efl.Ui.Widget.on_access_activate;
Efl.Ui.Widget.theme_apply;
Efl.Ui.Widget.focus_manager_create;
Efl.Ui.Widget_Focus_Manager.focus_manager_create;
Efl.Ui.Focus.Object.on_focus_update;
Efl.Ui.Widget.interest_region { get; }
Efl.Ui.Widget.on_disabled_update;

View File

@ -4,6 +4,8 @@
#include <Elementary.h>
#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED
#include "elm_priv.h"
#include "elm_interface_scrollable.h"
@ -4796,7 +4798,7 @@ EAPI void elm_pan_gravity_set(Elm_Pan *obj EINA_UNUSED, double x EINA_UNUSED, do
EAPI void elm_pan_gravity_get(const Elm_Pan *obj EINA_UNUSED, double *x EINA_UNUSED, double *y EINA_UNUSED) {}
EOLIAN static Efl_Ui_Focus_Manager*
_elm_interface_scrollable_efl_ui_widget_focus_manager_create(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
_elm_interface_scrollable_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
{
Efl_Ui_Focus_Manager *manager;
@ -4811,11 +4813,6 @@ EOLIAN static Efl_Object*
_elm_interface_scrollable_efl_object_constructor(Eo *obj, Elm_Scrollable_Smart_Interface_Data *pd EINA_UNUSED)
{
Eo *o = efl_constructor(efl_super(obj, MY_SCROLLABLE_INTERFACE));
pd->manager = efl_ui_widget_focus_manager_create(obj, obj);
efl_composite_attach(obj, pd->manager);
_efl_ui_focus_manager_redirect_events_add(pd->manager, obj);
return o;
}

View File

@ -27,7 +27,7 @@ enum Elm.Scroller.Single_Direction
last [[Sentinel value to indicate last enum field during iteration]]
}
mixin Elm.Interface_Scrollable(Efl.Ui.Scrollable, Efl.Ui.Focus.Manager_Sub, Efl.Ui.Widget)
mixin Elm.Interface_Scrollable(Efl.Ui.Scrollable, Efl.Ui.Focus.Manager_Sub, Efl.Ui.Widget, Efl.Ui.Widget_Focus_Manager)
{
[[Elm scrollable mixin]]
eo_prefix: elm_interface_scrollable;
@ -659,7 +659,7 @@ mixin Elm.Interface_Scrollable(Efl.Ui.Scrollable, Efl.Ui.Focus.Manager_Sub, Efl.
class.constructor;
Efl.Object.constructor;
Efl.Ui.Focus.Manager.border_elements { get; }
Efl.Ui.Widget.focus_manager_create;
Efl.Ui.Widget_Focus_Manager.focus_manager_create;
Efl.Ui.Base.mirrored { set; }
}
events {

View File

@ -7,6 +7,7 @@
#define EFL_ACCESS_SELECTION_PROTECTED
#define ELM_WIDGET_ITEM_PROTECTED
#define EFL_UI_TRANSLATABLE_PROTECTED
#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED
#include <Elementary.h>
@ -804,7 +805,7 @@ elm_menu_add(Evas_Object *parent)
}
EOLIAN static Efl_Ui_Focus_Manager*
_elm_menu_efl_ui_widget_focus_manager_create(Eo *obj EINA_UNUSED, Elm_Menu_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
_elm_menu_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj EINA_UNUSED, Elm_Menu_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
{
Efl_Ui_Focus_Manager *manager;
@ -819,11 +820,6 @@ EOLIAN static Eo *
_elm_menu_efl_object_constructor(Eo *obj, Elm_Menu_Data *sd)
{
Eo *parent = NULL;
Efl_Ui_Focus_Manager *manager;
manager = efl_ui_widget_focus_manager_create(obj, obj);
efl_composite_attach(obj, manager);
_efl_ui_focus_manager_redirect_events_add(manager, obj);
obj = efl_constructor(efl_super(obj, MY_CLASS));
efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);

View File

@ -1,5 +1,5 @@
class Elm.Menu (Efl.Ui.Widget, Efl.Ui.Clickable,
Efl.Access.Selection, Efl.Ui.Focus.Manager, Efl.Ui.Legacy)
Efl.Access.Selection, Efl.Ui.Widget_Focus_Manager, Efl.Ui.Legacy)
{
[[Elementary menu class]]
legacy_prefix: elm_menu;
@ -91,7 +91,7 @@ class Elm.Menu (Efl.Ui.Widget, Efl.Ui.Clickable,
Efl.Ui.Widget.widget_parent { get; set; }
Efl.Ui.Widget.theme_apply;
Efl.Ui.Translatable.translation_update;
Efl.Ui.Widget.focus_manager_create;
Efl.Ui.Widget_Focus_Manager.focus_manager_create;
Efl.Access.Object.access_children { get; }
Efl.Access.Selection.selected_children_count { get; }
Efl.Access.Selection.selected_child { get; }

View File

@ -64,6 +64,7 @@
# include "elm_access.eo.h"
# include "elm_code_private.h"
# include "efl_ui_focus_parent_provider.eo.h"
# include "efl_ui_widget_focus_manager.eo.h"
# include "efl_ui_focus_parent_provider_standard.eo.h"
# include "elm_widget_item_static_focus.eo.h"
#include "efl_selection_manager.eo.h"