From 9308410479b398169ec81daa6b77ef522a0f84ee Mon Sep 17 00:00:00 2001 From: Bruno Dilly Date: Wed, 7 Dec 2016 21:10:34 -0200 Subject: [PATCH] edje: support filtering allowed seats per part collections.group.parts.part.allowed_seats keeps a list of seat names to be used for events filter. So when evas devices of seat type are added, filters may be applied for each part. If no seat is listed, every seat may interact with such part. --- src/bin/edje/edje_cc_handlers.c | 89 +++++++++++++++++++++++++++++++++ src/lib/edje/edje_data.c | 13 +++++ src/lib/edje/edje_edit.c | 13 +++++ src/lib/edje/edje_load.c | 69 +++++++++++++++++++++++++ src/lib/edje/edje_private.h | 10 ++++ src/lib/edje/edje_program.c | 5 ++ 6 files changed, 199 insertions(+) diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c index 188e169a07..c4968377aa 100644 --- a/src/bin/edje/edje_cc_handlers.c +++ b/src/bin/edje/edje_cc_handlers.c @@ -313,6 +313,7 @@ static void st_collections_group_parts_part_dragable_y(void); static void st_collections_group_parts_part_dragable_confine(void); static void st_collections_group_parts_part_dragable_threshold(void); static void st_collections_group_parts_part_dragable_events(void); +static void st_collections_group_parts_part_allowed_seats(void); /* box and table items share these */ static void ob_collections_group_parts_part_box_items_item(void); @@ -789,6 +790,7 @@ New_Statement_Handler statement_handlers[] = {"collections.group.parts.part.cursor_mode", st_collections_group_parts_part_cursor_mode}, {"collections.group.parts.part.multiline", st_collections_group_parts_part_multiline}, {"collections.group.parts.part.access", st_collections_group_parts_part_access}, + {"collections.group.parts.part.allowed_seats", st_collections_group_parts_part_allowed_seats}, IMAGE_SET_STATEMENTS("collections.group.parts.part") IMAGE_STATEMENTS("collections.group.parts.part.") {"collections.group.parts.part.font", st_fonts_font}, /* dup */ @@ -4418,6 +4420,36 @@ _part_copy(Edje_Part *ep, Edje_Part *ep2) ep->dragable.count_y = ep2->dragable.count_y; ep->nested_children_count = ep2->nested_children_count; + if (ep2->allowed_seats) + { + Edje_Part_Allowed_Seat *seat; + unsigned int s; + + ep->allowed_seats_count = ep2->allowed_seats_count; + ep->allowed_seats = calloc(ep2->allowed_seats_count, + sizeof(Edje_Part_Allowed_Seat *)); + if (!ep->allowed_seats) + { + ERR("Not enough memory."); + exit(-1); + } + + for (s = 0; s < ep->allowed_seats_count; s++) + { + seat = mem_alloc(SZ(Edje_Part_Allowed_Seat)); + if (ep2->allowed_seats[s]->name) + { + seat->name = strdup(ep2->allowed_seats[s]->name); + if (!seat->name) + { + ERR("Not enough memory."); + exit(-1); + } + } + ep->allowed_seats[s] = seat; + } + } + data_queue_copied_part_lookup(pc, &(ep2->dragable.confine_id), &(ep->dragable.confine_id)); data_queue_copied_part_lookup(pc, &(ep2->dragable.threshold_id), &(ep->dragable.threshold_id)); data_queue_copied_part_lookup(pc, &(ep2->dragable.event_id), &(ep->dragable.event_id)); @@ -5827,6 +5859,9 @@ edje_cc_handlers_part_make(int id) ep->items = NULL; ep->nested_children_count = 0; + ep->allowed_seats = NULL; + ep->allowed_seats_count = 0; + epp = (Edje_Part_Parser *)ep; epp->reorder.insert_before = NULL; epp->reorder.insert_after = NULL; @@ -6022,6 +6057,13 @@ _part_free(Edje_Part_Collection *pc, Edje_Part *ep) free(ep->items[j]); free(ep->items); + for (j = 0 ; j < ep->allowed_seats_count; j++) + { + free((void*)(ep->allowed_seats[j]->name)); + free(ep->allowed_seats[j]); + } + free(ep->allowed_seats); + free((void*)ep->name); free((void*)ep->source); free((void*)ep->source2); @@ -7398,6 +7440,53 @@ st_collections_group_parts_part_dragable_events(void) } } +/** + @page edcref + @property + allowed_seats + @parameters + [seat1] [seat2] [seat3] ... + @effect + List of seat names allowed to interact with the part. + + If no list is defined all seats are allowed. It's the + default behaviour. + + If a seat isn't allowed, no signals will be emitted + related to its actions, as mouse and focus events. + Also it won't be able to focus this part. + @since 1.19 + @endproperty +*/ +static void +st_collections_group_parts_part_allowed_seats(void) +{ + Edje_Part_Allowed_Seat *seat; + Edje_Part *ep; + int n, argc; + + check_min_arg_count(1); + + ep = current_part; + argc = get_arg_count(); + + ep->allowed_seats = calloc(argc, sizeof(Edje_Part_Allowed_Seat *)); + if (!ep->allowed_seats) + { + ERR("Not enough memory."); + exit(-1); + } + + for (n = 0; n < argc; n++) + { + seat = mem_alloc(SZ(Edje_Part_Allowed_Seat)); + seat->name = parse_str(n); + ep->allowed_seats[n] = seat; + } + + ep->allowed_seats_count = argc; +} + /** @edcsubsection{collections_group_parts_items, * Group.Parts.Part.Box/Table.Items} */ diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c index 6c4ef6aec1..0af3b130fb 100644 --- a/src/lib/edje/edje_data.c +++ b/src/lib/edje/edje_data.c @@ -37,6 +37,8 @@ Eet_Data_Descriptor *_edje_edd_edje_pack_element = NULL; Eet_Data_Descriptor *_edje_edd_edje_pack_element_pointer = NULL; Eet_Data_Descriptor *_edje_edd_edje_part = NULL; Eet_Data_Descriptor *_edje_edd_edje_part_pointer = NULL; +Eet_Data_Descriptor *_edje_edd_edje_part_allowed_seat = NULL; +Eet_Data_Descriptor *_edje_edd_edje_part_allowed_seat_pointer = NULL; Eet_Data_Descriptor *_edje_edd_edje_part_description_variant = NULL; Eet_Data_Descriptor *_edje_edd_edje_part_description_rectangle = NULL; Eet_Data_Descriptor *_edje_edd_edje_part_description_snapshot = NULL; @@ -690,6 +692,8 @@ _edje_edd_shutdown(void) FREED(_edje_edd_edje_pack_element_pointer); FREED(_edje_edd_edje_part); FREED(_edje_edd_edje_part_pointer); + FREED(_edje_edd_edje_part_allowed_seat); + FREED(_edje_edd_edje_part_allowed_seat_pointer); FREED(_edje_edd_edje_part_description_variant); FREED(_edje_edd_edje_part_description_rectangle); FREED(_edje_edd_edje_part_description_snapshot); @@ -946,6 +950,11 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_style_tag, Edje_Style_Tag, "key", key, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_style_tag, Edje_Style_Tag, "value", value, EET_T_STRING); + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Allowed_Seat); + _edje_edd_edje_part_allowed_seat = + eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_allowed_seat, Edje_Part_Allowed_Seat, "name", name, EET_T_STRING); + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Style); _edje_edd_edje_style = eet_data_descriptor_file_new(&eddc); @@ -1766,6 +1775,10 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "nested_children_count", nested_children_count, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "required", required, EET_T_UCHAR); + EDJE_DEFINE_POINTER_TYPE(Part_Allowed_Seat, part_allowed_seat); + EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_part, Edje_Part, "allowed_seats", allowed_seats, _edje_edd_edje_part_allowed_seat_pointer); + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Limit); _edje_edd_edje_part_limit = eet_data_descriptor_file_new(&eddc); diff --git a/src/lib/edje/edje_edit.c b/src/lib/edje/edje_edit.c index de88db33e4..291b5afaf0 100644 --- a/src/lib/edje/edje_edit.c +++ b/src/lib/edje/edje_edit.c @@ -15248,6 +15248,19 @@ _edje_generate_source_of_part(Evas_Object *obj, Edje_Part *ep, Eina_Strbuf *buf) BUF_APPEND(I4 "precise_is_inside: 1;\n"); if (rp->part->access) BUF_APPEND(I4 "access: 1;\n"); + if (rp->part->allowed_seats) + { + Edje_Part_Allowed_Seat *seat; + unsigned int i; + + BUF_APPEND(I4 "allowed_seats:"); + for (i = 0; i < rp->part->allowed_seats_count; i++) + { + seat = rp->part->allowed_seats[i]; + BUF_APPENDF(" %s", seat->name); + } + BUF_APPEND(";\n"); + } if ((str = _edje_part_clip_to_get(ed, rp))) { diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c index e530926c33..bdbf698ca7 100644 --- a/src/lib/edje/edje_load.c +++ b/src/lib/edje/edje_load.c @@ -507,6 +507,60 @@ _edje_physics_world_update_cb(void *data, EPhysics_World *world EINA_UNUSED, voi } #endif +Eina_Bool +_edje_part_allowed_seat_find(Edje_Real_Part *rp, const char *seat_name) +{ + const char *name; + unsigned int i; + + for (i = 0; i < rp->part->allowed_seats_count; i++) + { + name = rp->part->allowed_seats[i]->name; + if (!strcmp(seat_name, name)) + return EINA_TRUE; + } + + return EINA_FALSE; +} + +/* It goes throught the list of registered seats and + * set event filters for each of these seats. */ +static void +_edje_part_seat_filter_apply(Edje *ed, Edje_Real_Part *rp) +{ + Edje_Seat *seat; + Eina_List *l; + Eina_Bool found; + + EINA_LIST_FOREACH(ed->seats, l, seat) + { + found = _edje_part_allowed_seat_find(rp, seat->name); + efl_input_seat_event_filter_set(rp->object, seat->device, found); + } +} + +/* It goes throught the list of all edje parts and + * set event filters for each of these parts. Should be called when + * a new seat is added. + */ +static void +_edje_seat_event_filter_apply(Edje *ed, Edje_Seat *seat) +{ + Edje_Real_Part *rp; + unsigned short i; + Eina_Bool found; + + for (i = 0; i < ed->table_parts_size; i++) + { + rp = ed->table_parts[i]; + if (!rp->part->allowed_seats) + continue; + + found = _edje_part_allowed_seat_find(rp, seat->name); + efl_input_seat_event_filter_set(rp->object, seat->device, found); + } +} + static void _edje_device_add(Edje *ed, Efl_Input_Device *dev) { @@ -544,6 +598,7 @@ _edje_device_add(Edje *ed, Efl_Input_Device *dev) snprintf(sig, sizeof(sig), "seat,added,%s,%s", seat->name, efl_input_device_name_get(dev)); _edje_emit(ed, sig, ""); + _edje_seat_event_filter_apply(ed, seat); seat_err: eina_stringshare_del(name); @@ -645,6 +700,8 @@ _edje_device_changed_cb(void *data, const Efl_Event *event) eina_stringshare_del(seat->name); free(seat); + _edje_seat_event_filter_apply(ed, s); + return; } } @@ -652,6 +709,7 @@ _edje_device_changed_cb(void *data, const Efl_Event *event) snprintf(sig, sizeof(sig), "seat,renamed,%s,%s", seat->name, name); eina_stringshare_replace(&seat->name, name); _edje_emit(ed, sig, ""); + _edje_seat_event_filter_apply(ed, seat); } static void @@ -1093,6 +1151,9 @@ _edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const ch nested_smart = NULL; } + if (ep->allowed_seats) + _edje_part_seat_filter_apply(ed, rp); + if (ep->no_render) efl_canvas_object_no_render_set(rp->object, 1); @@ -2228,6 +2289,14 @@ _edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec, Edje_Part_Collec for (j = 0; j < ep->items_count; ++j) free(ep->items[j]); free(ep->items); + + for (j = 0; j < ep->allowed_seats_count; ++j) + { + if (edf->free_strings) + eina_stringshare_del(ep->allowed_seats[j]->name); + free(ep->allowed_seats[j]); + } + free(ep->allowed_seats); // technically need this - but we ASSUME we use "one_big" so everything gets // freed in one go lower down when we del the mempool... but what if pool goes // "over"? diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index 1a2d7dbdea..13dc7961dd 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -377,6 +377,7 @@ typedef struct _Edje_Part_Box_Animation Edje_Part_Box_Animation; typedef struct _Edje_Part_Limit Edje_Part_Limit; typedef struct _Edje_Part_Description_Vector Edje_Part_Description_Vector; typedef struct _Edje_Part_Description_Spec_Svg Edje_Part_Description_Spec_Svg; +typedef struct _Edje_Part_Allowed_Seat Edje_Part_Allowed_Seat; typedef struct _Edje_Real_Part_Vector Edje_Real_Part_Vector; typedef struct _Edje_Vector_Data Edje_Vector_Data; @@ -1195,6 +1196,8 @@ struct _Edje_Part unsigned int items_count; Edje_3D_Vec scale_3d; Edje_Part_Api api; + Edje_Part_Allowed_Seat **allowed_seats; + unsigned int allowed_seats_count; unsigned char type; /* what type (image, rect, text) */ #ifdef HAVE_EPHYSICS unsigned char physics_body; /* body (none, rigid box, soft circle, ...) */ @@ -1628,6 +1631,12 @@ struct _Edje_Part_Description_Vector Edje_Part_Description_Spec_Svg vg; }; +struct _Edje_Part_Allowed_Seat +{ + const char *name; +}; + + /*----------*/ struct _Edje_Signal_Source_Char @@ -2495,6 +2504,7 @@ void _edje_part_focus_set(Edje *ed, const char *seat_name, Edje_Real_Part *rp); Eina_Stringshare *_edje_seat_name_get(Edje *ed, Efl_Input_Device *device); Efl_Input_Device *_edje_seat_get(Edje *ed, Eina_Stringshare *name); +Eina_Bool _edje_part_allowed_seat_find(Edje_Real_Part *rp, const char *seat_name); const Edje_Signals_Sources_Patterns *_edje_signal_callback_patterns_ref(const Edje_Signal_Callback_Group *gp); void _edje_signal_callback_patterns_unref(const Edje_Signals_Sources_Patterns *essp); diff --git a/src/lib/edje/edje_program.c b/src/lib/edje/edje_program.c index ef4cf40d05..7ab1498814 100644 --- a/src/lib/edje/edje_program.c +++ b/src/lib/edje/edje_program.c @@ -662,6 +662,10 @@ _edje_part_focus_set(Edje *ed, const char *seat_name, Edje_Real_Part *rp) if (focused_part != rp) { + if ((rp->part->allowed_seats) && + (!_edje_part_allowed_seat_find(rp, sname))) + goto not_allowed; + if (focused_part) _edje_seat_name_emit(ed, sname, "focus,part,out", focused_part->part->name); @@ -670,6 +674,7 @@ _edje_part_focus_set(Edje *ed, const char *seat_name, Edje_Real_Part *rp) _edje_seat_name_emit(ed, sname, "focus,part,in", rp->part->name); } +not_allowed: eina_stringshare_del(sname); }