clouseau: introduce focus inspector

This for now shows the nodes that are registered in a manager, in the
hirarchy that is used. Redirects are displayed red, logicals gray and
normals in a e-style blue. If something is part of the focus history its
green.
This commit is contained in:
Marcel Hollerbach 2017-10-29 14:33:13 +01:00
parent 4ae284bd0b
commit 65d89b92c2
15 changed files with 966 additions and 1 deletions

View File

@ -3,13 +3,20 @@ add_custom_command (
COMMAND edje_cc -id ${CMAKE_CURRENT_SOURCE_DIR}/images ${CMAKE_CURRENT_SOURCE_DIR}/evlog.edc clouseau_evlog.edj
DEPENDS evlog.edc
)
add_custom_command (
OUTPUT clouseau_focus_inspector.edj
COMMAND edje_cc -id ${CMAKE_CURRENT_SOURCE_DIR}/images ${CMAKE_CURRENT_SOURCE_DIR}/focus_inspector.edc clouseau_focus_inspector.edj
DEPENDS focus_inspector.edc
)
add_custom_target (
clouseau_evlog_edj
DEPENDS clouseau_evlog.edj evlog.edc
)
add_custom_target(focus_inspector_theme DEPENDS clouseau_focus_inspector.edj)
install (
FILES ${CMAKE_CURRENT_BINARY_DIR}/clouseau_evlog.edj images/show-screenshot.png images/take-screenshot.png
FILES ${CMAKE_CURRENT_BINARY_DIR}/clouseau_focus_inspector.edj ${CMAKE_CURRENT_BINARY_DIR}/clouseau_evlog.edj images/show-screenshot.png images/take-screenshot.png
DESTINATION share/${PROJECT_NAME_LOWER}
)

91
data/focus_inspector.edc Normal file
View File

@ -0,0 +1,91 @@
collections {
images {
image: "focus_inspector_history.svg" COMP;
image: "focus_inspector_logical.svg" COMP;
image: "focus_inspector_regular.svg" COMP;
image: "focus_inspector_redirect.svg" COMP;
}
group { "focus_inspector/regular";
parts {
image { "indicator";
desc { "default";
rel1.to: "widget_name";
rel1.offset: -3px -3px;
rel2.to: "widget_name";
rel2.offset: 3px 3px;
image {
border: 1 1 1 1;
normal: "focus_inspector_regular.svg";
}
}
}
text { "widget_name";
desc { "default";
text {
font: Sans;
text: "<widget-name>";
size: 8;
min: 1 1;
max: 1 1;
}
}
}
}
}
group { "focus_inspector/logical";
inherit: "focus_inspector/regular";
parts {
image { "indicator";
desc { "default";
rel1.to: "widget_name";
rel1.offset: -3px -3px;
rel2.to: "widget_name";
rel2.offset: 3px 3px;
image {
border: 1 1 1 1;
normal: "focus_inspector_logical.svg";
}
}
}
}
}
group { "focus_inspector/history";
inherit: "focus_inspector/regular";
parts {
image { "indicator";
desc { "default";
rel1.to: "widget_name";
rel1.offset: -3px -3px;
rel2.to: "widget_name";
rel2.offset: 3px 3px;
image {
border: 1 1 1 1;
normal: "focus_inspector_history.svg";
}
}
}
}
}
group { "focus_inspector/redirect";
inherit: "focus_inspector/regular";
parts {
image { "indicator";
desc { "default";
rel1.to: "widget_name";
rel1.offset: -3px -3px;
rel2.to: "widget_name";
rel2.offset: 3px 3px;
image {
border: 1 1 1 1;
normal: "focus_inspector_redirect.svg";
}
}
}
}
}
}

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="99.855179mm"
height="28.76149mm"
viewBox="0 0 99.855179 28.76149"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="focus_inspector_history.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-3.7169149"
inkscape:cy="-166.01003"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-0.58634746,-0.38263321)">
<rect
style="fill:#484e4d;fill-opacity:1;fill-rule:nonzero;stroke:#259700;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4504"
width="98.355179"
height="27.26149"
x="1.3363475"
y="1.1326332"
ry="8.5526237"
rx="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="99.855179mm"
height="28.76149mm"
viewBox="0 0 99.855179 28.76149"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="focus_inspector_logical.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-3.7169149"
inkscape:cy="-166.01003"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-0.58634746,-0.38263321)">
<rect
style="fill:#484e4d;fill-opacity:1;fill-rule:nonzero;stroke:#787878;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4504"
width="98.355179"
height="27.26149"
x="1.3363475"
y="1.1326332"
ry="8.5526237"
rx="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="99.855179mm"
height="28.76149mm"
viewBox="0 0 99.855179 28.76149"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="focus_inspector_redirect.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-3.7169149"
inkscape:cy="-166.01003"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-0.58634746,-0.38263321)">
<rect
style="fill:#484e4d;fill-opacity:1;fill-rule:nonzero;stroke:#c0392b;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4504"
width="98.355179"
height="27.26149"
x="1.3363475"
y="1.1326332"
ry="8.5526237"
rx="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="99.855179mm"
height="28.76149mm"
viewBox="0 0 99.855179 28.76149"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="focus_inspector_regular.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-3.7169149"
inkscape:cy="-166.01003"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-0.58634746,-0.38263321)">
<rect
style="fill:#484e4d;fill-opacity:1;fill-rule:nonzero;stroke:#2288ee;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4504"
width="98.355179"
height="27.26149"
x="1.3363475"
y="1.1326332"
ry="8.5526237"
rx="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -31,6 +31,7 @@
#include <Eo.h>
#include <Eolian.h>
#include <Elementary.h>
typedef void (*Eo_Debug_Class_Extract_Cb)(void *data, uint64_t kl, char *kl_name);
@ -107,6 +108,19 @@ typedef struct
int tm_hour;
} Evas_Debug_Screenshot;
typedef struct {
Eo *redirect_manager;
Eo *focused;
const char *class_name;
Eina_List *relations;
} Clouseau_Focus_Manager_Data;
typedef struct {
Efl_Ui_Focus_Relations relation;
const char *class_name;
} Clouseau_Focus_Relation;
EAPI void *eo_debug_eoids_request_prepare(int *size, ...);
EAPI void eo_debug_klids_extract(void *buffer, int size, Eo_Debug_Class_Extract_Cb cb, void *data);

View File

@ -71,6 +71,11 @@ static int _eoids_get_op = EINA_DEBUG_OPCODE_INVALID;
static int _obj_info_op = EINA_DEBUG_OPCODE_INVALID;
static int _obj_highlight_op = EINA_DEBUG_OPCODE_INVALID;
static int _win_screenshot_op = EINA_DEBUG_OPCODE_INVALID;
static int _focus_manager_list_op = EINA_DEBUG_OPCODE_INVALID;
static int _focus_manager_detail_op = EINA_DEBUG_OPCODE_INVALID;
static Eet_Data_Descriptor *managers = NULL, *manager_details = NULL;
#include "clouseau_focus_serialization.x"
enum {
HIGHLIGHT_R = 255,
@ -915,6 +920,142 @@ _main_loop_win_screenshot_cb(Eina_Debug_Session *session, int srcid, void *buffe
WRAPPER_TO_XFER_MAIN_LOOP(_win_screenshot_cb)
static Eina_Bool
_only_manager(const void *container, void *data, void *fdata)
{
return efl_isa(data, EFL_UI_FOCUS_MANAGER_INTERFACE);
}
static void
_main_loop_focus_manager_list_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size)
{
Eina_Iterator *obj_iterator, *manager_iterator;
Eina_Array *array;
Eo *obj;
array = eina_array_new(10);
obj_iterator = eo_objects_iterator_new();
manager_iterator = eina_iterator_filter_new(obj_iterator, _only_manager, NULL, NULL);
EINA_ITERATOR_FOREACH(manager_iterator, obj)
{
eina_array_push(array, obj);
}
eina_debug_session_send(session, srcid, _focus_manager_list_op, array->data, array->count * sizeof(void*));
}
WRAPPER_TO_XFER_MAIN_LOOP(_focus_manager_list_cb)
EAPI Efl_Dbg_Info*
clouseau_eo_info_find(Efl_Dbg_Info *root, const char *name)
{
Eina_Value_List eo_list;
Eina_List *n;
Efl_Dbg_Info *info;
if (!root) return NULL;
eina_value_pget(&(root->value), &eo_list);
EINA_LIST_FOREACH(eo_list.list, n, info)
{
if (!strcmp(info->name, name))
{
return info;
}
}
return NULL;
}
static Eina_List*
_fetch_children(Efl_Ui_Focus_Manager *m)
{
Efl_Dbg_Info *manager_data, *children_data, *root;
Eina_List *lst = NULL, *n;
Eina_Value_List result;
Efl_Dbg_Info *elem;
root = EFL_DBG_INFO_LIST_APPEND(NULL, "Root");
efl_dbg_info_get(m, root);
manager_data = clouseau_eo_info_find(root, "Efl.Ui.Focus.Manager");
EINA_SAFETY_ON_NULL_RETURN_VAL(manager_data, NULL);
children_data = clouseau_eo_info_find(manager_data, "children");
EINA_SAFETY_ON_NULL_RETURN_VAL(children_data, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_get(&children_data->value) == EINA_VALUE_TYPE_LIST, NULL);
eina_value_pget(&children_data->value, &result);
EINA_LIST_FOREACH(result.list, n, elem)
{
void *ptr;
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_get(&elem->value) == EINA_VALUE_TYPE_UINT64, NULL);
eina_value_get(&elem->value, &ptr);
lst = eina_list_append(lst, ptr);
}
efl_dbg_info_free(root);
return lst;
}
static Eina_Bool
_main_loop_focus_manager_detail_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size)
{
Clouseau_Focus_Manager_Data *res;
uint64_t ptr64;
Eo *elem, *manager;
if (!manager_details) _init_data_descriptors();
memcpy(&ptr64, buffer, sizeof(ptr64));
manager = (Eo *)SWAP_64(ptr64);
if (!efl_isa(manager, EFL_UI_FOCUS_MANAGER_INTERFACE)) return EINA_TRUE;
Eina_List *children = _fetch_children(manager);
res = alloca(sizeof(Clouseau_Focus_Manager_Data));
res->class_name = efl_class_name_get(manager);
res->relations = NULL;
res->focused = efl_ui_focus_manager_focus_get(manager);
res->redirect_manager = efl_ui_focus_manager_redirect_get(manager);
EINA_LIST_FREE(children, elem)
{
Clouseau_Focus_Relation *crel = calloc(1, sizeof(Clouseau_Focus_Relation));
Efl_Ui_Focus_Relations *rel;
rel = efl_ui_focus_manager_fetch(manager, elem);
memcpy(&crel->relation, rel, sizeof(Efl_Ui_Focus_Relations));
crel->class_name = efl_class_name_get(elem);
res->relations = eina_list_append(res->relations, crel);
free(rel);
}
int blob_size;
void *blob = eet_data_descriptor_encode(manager_details, res, &blob_size);
Clouseau_Focus_Manager_Data *aaah = eet_data_descriptor_decode(manager_details, blob, blob_size);
if (eina_list_count(aaah->relations) != eina_list_count(res->relations)) abort();
eina_debug_session_send(session, srcid, _focus_manager_detail_op, blob, blob_size);
return EINA_TRUE;
}
WRAPPER_TO_XFER_MAIN_LOOP(_focus_manager_detail_cb)
EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
{"Clouseau/Object_Introspection/snapshot_start", &_snapshot_start_op, &_snapshot_start_cb},
{"Clouseau/Object_Introspection/snapshot_done", &_snapshot_done_op, NULL},
@ -923,6 +1064,8 @@ EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
{"Clouseau/Eolian/object/info_get", &_obj_info_op, &_obj_info_req_cb},
{"Clouseau/Evas/object/highlight", &_obj_highlight_op, &_obj_highlight_cb},
{"Clouseau/Evas/window/screenshot", &_win_screenshot_op, &_win_screenshot_cb},
{"Clouseau/Elementary_Focus/list", &_focus_manager_list_op, &_focus_manager_list_cb},
{"Clouseau/Elementary_Focus/detail", &_focus_manager_detail_op, &_focus_manager_detail_cb},
{NULL, NULL, NULL}
);

View File

@ -0,0 +1,38 @@
static void
_init_data_descriptors(void)
{
Eet_Data_Descriptor_Class klass;
Eet_Data_Descriptor *relations_eed;
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&klass, Clouseau_Focus_Relation);
relations_eed = eet_data_descriptor_file_new(&klass);
#define BASIC(field, type) EET_DATA_DESCRIPTOR_ADD_BASIC(relations_eed, Clouseau_Focus_Relation, #field , field, type)
BASIC(class_name, EET_T_STRING);
BASIC(relation.next, EET_T_UINT);
BASIC(relation.prev, EET_T_UINT);
BASIC(relation.logical, EET_T_CHAR);
BASIC(relation.parent, EET_T_UINT);
BASIC(relation.redirect, EET_T_UINT);
BASIC(relation.node, EET_T_UINT);
BASIC(relation.position_in_history, EET_T_INT);
#undef BASIC
#define LIST(field, type) EET_DATA_DESCRIPTOR_ADD_LIST(relations_eed, Clouseau_Focus_Relation, #field , field, type)
/*LIST(relation.right, EET_T_UINT);
LIST(relation.left, EET_T_UINT);
LIST(relation.top, EET_T_UINT);
LIST(relation.down, EET_T_UINT);*/
#undef LIST
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&klass, Clouseau_Focus_Manager_Data);
manager_details = eet_data_descriptor_file_new(&klass);
EET_DATA_DESCRIPTOR_ADD_BASIC(manager_details, Clouseau_Focus_Manager_Data, "redirect_manager", redirect_manager, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(manager_details, Clouseau_Focus_Manager_Data, "focused", focused, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(manager_details, Clouseau_Focus_Manager_Data, "class_name", class_name, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_LIST(manager_details, Clouseau_Focus_Manager_Data, "relations", relations, relations_eed);
}

View File

@ -1,5 +1,6 @@
add_subdirectory(objects_introspection)
add_subdirectory(evlog)
add_subdirectory(focus_inspector)
if (${EFL_PROFILER_FOUND})
add_subdirectory(profiling_viewer)

View File

@ -0,0 +1,38 @@
set(CMAKE_BUILD_TYPE Debug)
STRING(REGEX REPLACE "\n" "" EOLIAN_EO_DIR ${EOLIAN_EO_DIR})
STRING(REGEX REPLACE " " "" EOLIAN_EO_DIR ${EOLIAN_EO_DIR})
add_definitions(${CLI_COMMON_DEFINITIONS} -DEFL_EO_API_SUPPORT
-DEOLIAN_EO_DIR="${EOLIAN_EO_DIR}" -DFOCUS_EDJ="${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME_LOWER}/clouseau_focus_inspector.edj")
add_definitions(-DEFL_EO_API_SUPPORT -DGUI_IMAGES_PATH="${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME_LOWER}")
set(EOLIAN_INCLUDE_FLAG -I \"${EOLIAN_EO_DIR}/eo-1\" -I${CMAKE_CURRENT_SOURCE_DIR})
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${ELEMENTARY_INCLUDE_DIRS}
${EVAS_INCLUDE_DIRS}
${EO_INCLUDE_DIRS}
${EINA_INCLUDE_DIRS}
${EET_INCLUDE_DIRS}
${EOLIAN_INCLUDE_DIRS}
)
link_directories (${PC_LIBELEMENTARY_LIBRARY_DIRS})
add_library(focus_inspector SHARED main.c gui.c tree_view.c)
target_link_libraries(focus_inspector
${ELEMENTARY_LIBRARIES}
${EVAS_LIBRARIES}
${EO_LIBRARIES}
${EINA_LIBRARIES}
${EET_LIBRARIES}
${EOLIAN_LIBRARIES}
clouseau_debug
)
add_dependencies(focus_inspector focus_inspector_theme)
INSTALL(TARGETS focus_inspector LIBRARY DESTINATION lib)

View File

@ -0,0 +1,118 @@
#include <Elementary.h>
#include "../../Clouseau_Debug.h"
#include "gui.h"
static Evas_Object *table, *managers, *redirect, *history, *scroller;
static Elm_Genlist_Item_Class *itc;
static char*
_text_get(void *data, Elm_Genlist *list, const char *part)
{
Efl_Ui_Focus_Manager *manager = data;
Eina_Strbuf *res = eina_strbuf_new();
eina_strbuf_append_printf(res, "%p", manager);
return eina_strbuf_release(res);
}
EAPI Evas_Object*
ui_create(Instance *inst, Evas_Object *obj)
{
Evas_Object *o;
o = table = elm_table_add(obj);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(o);
o = managers = elm_combobox_add(obj);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_part_text_set(o, "guide", "Manager to inspect");
evas_object_show(o);
elm_table_pack(table, o, 0, 0, 1, 1);
itc = elm_genlist_item_class_new();
itc->func.text_get = _text_get;
o = elm_label_add(obj);
elm_object_text_set(o, "Redirect:");
evas_object_show(o);
elm_table_pack(table, o, 1, 0, 1, 1);
o = redirect = elm_label_add(obj);
evas_object_show(o);
elm_table_pack(table, o, 2, 0, 1, 1);
o = history = elm_hoversel_add(obj);
elm_object_text_set(o, "History");
evas_object_show(o);
elm_table_pack(table, o, 3, 0, 1, 1);
o = scroller = elm_scroller_add(table);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(o);
elm_table_pack(table, o, 0, 1, 4, 1);
return table;
}
static void
_sel(void *data, Evas_Object *obj, void *event_info)
{
com_defailt_manager(data, elm_object_item_data_get(event_info));
}
EAPI void
ui_managers_add(Instance *inst, Efl_Ui_Focus_Manager **manager, int size)
{
elm_genlist_clear(managers);
for (int i = 0; i < size; ++i)
{
elm_genlist_item_append(managers, itc, manager[i], NULL, 0, _sel, inst);
}
}
static int
_sort(const void *a_raw, const void *b_raw)
{
const Clouseau_Focus_Relation *a = a_raw;
const Clouseau_Focus_Relation *b = b_raw;
int val_a, val_b;
if (a) val_a = a->relation.position_in_history;
if (b) val_b = b->relation.position_in_history;
return val_a - val_b;
}
EAPI void
ui_manager_data_arrived(Instance *inst, Clouseau_Focus_Manager_Data *data)
{
Clouseau_Focus_Relation *rel;
Evas_Object *box, *o;
Eina_List *n, *sorted = NULL;
EINA_LIST_FREE(inst->realized.objects, o)
evas_object_del(o);
inst->realized.data = data;
elm_hoversel_clear(history);
EINA_LIST_FOREACH(data->relations, n, rel)
{
if (rel->relation.position_in_history != -1)
sorted = eina_list_sorted_insert(sorted, _sort, rel);
}
EINA_LIST_FOREACH(sorted, n, rel)
{
elm_hoversel_item_add(history, rel->class_name, NULL, 0, NULL, NULL);
}
tree_view_update(inst, scroller);
}

View File

@ -0,0 +1,25 @@
#ifndef GUI_H
#define GUI_H
#include "../../Clouseau.h"
#include "../../Clouseau_Debug.h"
typedef struct {
Clouseau_Extension *ext;
struct {
Eina_List *objects;
Clouseau_Focus_Manager_Data *data;
} realized;
} Instance;
#define PUSH_CLEANUP(inst, o) inst->realized.objects = eina_list_append(inst->realized.objects, o)
EAPI void tree_view_update(Instance *inst, Evas_Object *scroller);
EAPI void ui_managers_add(Instance *inst, Efl_Ui_Focus_Manager **manager, int size);
EAPI void ui_manager_data_arrived(Instance *inst, Clouseau_Focus_Manager_Data *data);
EAPI Evas_Object* ui_create(Instance *inst, Evas_Object *obj);
EAPI void com_refresh_managers(Instance *inst);
EAPI void com_defailt_manager(Instance *inst, Efl_Ui_Focus_Manager *manager);
#endif

View File

@ -0,0 +1,119 @@
#include <Eina.h>
#include <Elementary.h>
#include "../../Clouseau.h"
#include "../../Clouseau_Debug.h"
#include "gui.h"
static Instance inst;
static int _focus_manager_list_op = EINA_DEBUG_OPCODE_INVALID;
static int _focus_manager_detail_op = EINA_DEBUG_OPCODE_INVALID;
static Eet_Data_Descriptor *managers = NULL, *manager_details = NULL;
#include "../../clouseau_focus_serialization.x"
static Eina_Bool
_main_loop_focus_manager_list_cb(Eina_Debug_Session *session, int src, void *buffer, int size)
{
int managers = size / sizeof(Efl_Ui_Focus_Manager*);
Efl_Ui_Focus_Manager *manager_arr[managers];
Clouseau_Extension *ext = eina_debug_session_data_get(session);
memcpy(manager_arr, buffer, size);
ui_managers_add(ext->data, manager_arr, managers);
return EINA_TRUE;
}
WRAPPER_TO_XFER_MAIN_LOOP(_focus_manager_list_cb)
static Eina_Bool
_main_loop_focus_manager_detail_cb(Eina_Debug_Session *session, int src, void *buffer, int size)
{
Clouseau_Extension *ext = eina_debug_session_data_get(session);
Clouseau_Focus_Manager_Data *pd;
if (!manager_details) _init_data_descriptors();
pd = eet_data_descriptor_decode(manager_details, buffer, size);
ui_manager_data_arrived(ext->data, pd);
return EINA_TRUE;
}
WRAPPER_TO_XFER_MAIN_LOOP(_focus_manager_detail_cb)
EINA_DEBUG_OPCODES_ARRAY_DEFINE(_ops,
{"Clouseau/Elementary_Focus/list", &_focus_manager_list_op, &_focus_manager_list_cb},
{"Clouseau/Elementary_Focus/detail", &_focus_manager_detail_op, &_focus_manager_detail_cb},
{NULL, NULL, NULL}
);
static void
_session_changed(Clouseau_Extension *ext)
{
int i = 0;
Instance *inst = ext->data;
Eina_Debug_Opcode *ops = _ops();
while (ops[i].opcode_name)
{
if (ops[i].opcode_id) *(ops[i].opcode_id) = EINA_DEBUG_OPCODE_INVALID;
i++;
}
if (ext->session)
{
eina_debug_session_data_set(ext->session, ext);
eina_debug_opcodes_register(ext->session, ops, NULL, ext);
}
}
static void
_app_changed(Clouseau_Extension *ext)
{
com_refresh_managers(ext->data);
}
EAPI void
com_refresh_managers(Instance *inst)
{
int i = eina_debug_session_send(inst->ext->session, inst->ext->app_id, _focus_manager_list_op, NULL, 0);
}
EAPI void
com_defailt_manager(Instance *inst, Efl_Ui_Focus_Manager *manager)
{
void *tmp[1];
tmp[0] = manager;
int i = eina_debug_session_send(inst->ext->session, inst->ext->app_id, _focus_manager_detail_op, tmp, sizeof(void*));
}
EAPI const char *
extension_name_get()
{
return "Focus Inspector";
}
EAPI Eina_Bool
extension_start(Clouseau_Extension *ext, Eo *parent)
{
eina_init();
inst.ext = ext;
ext->data = &inst;
ext->ui_object = ui_create(ext->data, parent);
ext->session_changed_cb = _session_changed;
ext->app_changed_cb = _app_changed;
return !!ext->ui_object;
}
EAPI Eina_Bool
extension_stop(Clouseau_Extension *ext)
{
efl_del(ext->ui_object);
eina_shutdown();
return EINA_TRUE;
}

View File

@ -0,0 +1,91 @@
#include <Elementary.h>
#include "../../Clouseau_Debug.h"
#include "gui.h"
static void
find(Instance *pd, void *parent, void (*found)(void *data, Instance *pd, Clouseau_Focus_Relation *relation), void *data)
{
for (int i = 0; pd->realized.data->relations && i < eina_list_count(pd->realized.data->relations); ++i)
{
Clouseau_Focus_Relation *rel;
rel = eina_list_nth(pd->realized.data->relations, i);
if (rel->relation.parent == parent)
found(data, pd, rel);
}
}
void
tree_level(void *data, Instance *inst, Clouseau_Focus_Relation *relation)
{
Evas_Object *box, *childbox, *vis;
int maxw, maxh, minw, minh;
Eina_Strbuf *buf;
char group[PATH_MAX];
box = evas_object_box_add(evas_object_evas_get(data));
evas_object_box_padding_set(box, 20, 20);
evas_object_show(box);
PUSH_CLEANUP(inst, box);
buf = eina_strbuf_new();
eina_strbuf_append_printf(buf, "%p", relation->relation.node);
vis = edje_object_add(evas_object_evas_get(data));
evas_object_size_hint_weight_set(vis, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(vis, 0.0, EVAS_HINT_FILL);
if (relation->relation.position_in_history != -1 )
snprintf(group, sizeof(group), "focus_inspector/history");
else if (relation->relation.redirect)
snprintf(group, sizeof(group), "focus_inspector/redirect");
else if (relation->relation.logical)
snprintf(group, sizeof(group), "focus_inspector/logical");
else
snprintf(group, sizeof(group), "focus_inspector/regular");
edje_object_file_set(vis, FOCUS_EDJ, group);
edje_object_part_text_set(vis, "widget_name", relation->class_name);
evas_object_show(vis);
evas_object_box_append(box, vis);
edje_object_size_max_get(vis, &maxw, &maxh);
edje_object_size_min_get(vis, &minw, &minh);
if ((minw <= 0) && (minh <= 0))
edje_object_size_min_calc(vis, &minw, &minh);
evas_object_size_hint_max_set(vis, maxw, maxh);
evas_object_size_hint_min_set(vis, minw, minh);
PUSH_CLEANUP(inst, vis);
childbox = evas_object_box_add(evas_object_evas_get(data));
evas_object_box_padding_set(childbox, 20, 20);
evas_object_box_layout_set(childbox, evas_object_box_layout_vertical, NULL, NULL);
evas_object_box_append(box, childbox);
evas_object_show(childbox);
PUSH_CLEANUP(inst, childbox);
find(inst, relation->relation.node, tree_level, childbox);
evas_object_box_append(data, box);
}
EAPI void
tree_view_update(Instance *inst, Evas_Object *scroller)
{
Evas_Object *box;
box = evas_object_box_add(evas_object_evas_get(scroller));
evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_box_layout_set(box, evas_object_box_layout_vertical, NULL, NULL);
evas_object_show(box);
PUSH_CLEANUP(inst, box);
if (inst->realized.data)
find(inst, NULL, tree_level, box);
elm_object_content_set(scroller, box);
}