diff options
author | Bruno Dilly <bdilly@profusion.mobi> | 2016-12-19 15:19:06 -0200 |
---|---|---|
committer | Bruno Dilly <bdilly@profusion.mobi> | 2016-12-19 15:19:06 -0200 |
commit | 6f9deb976a9774a14636cb3131743245347b2dd4 (patch) | |
tree | debe4b09a8aaf52bfcd875b3746bf9ae9e67ae31 | |
parent | 25792d64165ad4f5f647a36f087af2d2206a6618 (diff) | |
parent | 4449ec869888ff21c46d54ab2baaa1f209986819 (diff) | |
download | efl-6f9deb976a9774a14636cb3131743245347b2dd4.tar.gz |
Merge branch 'devs/bdilly/edje_multiseat'
This series implement multiseat support on Edje:
* emit signals with seat name as suffix
* handle multiseat focus
* add optional argument to FOCUS_SET and FOCUS_OBJECT actions
to specify a seat
* add Edje naming for seats (incremental) with flag
to disable this behaviour - so custom (evas) names will be used
* add 3 examples exploring all these new features
Reviewed By: cedric, iscaro, jpeg
Differential Revision: https://phab.enlightenment.org/D4451
@feature
-rw-r--r-- | src/bin/edje/edje_cc_handlers.c | 62 | ||||
-rw-r--r-- | src/examples/edje/.gitignore | 4 | ||||
-rw-r--r-- | src/examples/edje/Makefile.am | 14 | ||||
-rw-r--r-- | src/examples/edje/dynamic_multiseat.edc | 279 | ||||
-rw-r--r-- | src/examples/edje/edje-dynamic-multiseat.c | 136 | ||||
-rw-r--r-- | src/examples/edje/edje-focus.c | 157 | ||||
-rw-r--r-- | src/examples/edje/edje-multiseat-custom-names.c | 150 | ||||
-rw-r--r-- | src/examples/edje/edje-multiseat.c | 287 | ||||
-rw-r--r-- | src/examples/edje/focus.edc | 330 | ||||
-rw-r--r-- | src/examples/edje/multiseat.edc | 792 | ||||
-rw-r--r-- | src/examples/edje/multiseat_custom_names.edc | 175 | ||||
-rw-r--r-- | src/lib/edje/Edje_Common.h | 2 | ||||
-rw-r--r-- | src/lib/edje/edje_callbacks.c | 48 | ||||
-rw-r--r-- | src/lib/edje/edje_data.c | 3 | ||||
-rw-r--r-- | src/lib/edje/edje_edit.c | 21 | ||||
-rw-r--r-- | src/lib/edje/edje_entry.c | 165 | ||||
-rw-r--r-- | src/lib/edje/edje_load.c | 200 | ||||
-rw-r--r-- | src/lib/edje/edje_object.eo | 34 | ||||
-rw-r--r-- | src/lib/edje/edje_private.h | 22 | ||||
-rw-r--r-- | src/lib/edje/edje_program.c | 200 | ||||
-rw-r--r-- | src/lib/evas/Evas_Common.h | 16 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_device.c | 26 |
22 files changed, 3032 insertions, 91 deletions
diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c index 33aeb12df2..3861cd9aec 100644 --- a/src/bin/edje/edje_cc_handlers.c +++ b/src/bin/edje/edje_cc_handlers.c @@ -262,6 +262,7 @@ static void st_collections_group_broadcast_signal(void); static void st_collections_group_data_item(void); static void st_collections_group_orientation(void); static void st_collections_group_mouse_events(void); +static void st_collections_group_use_custom_seat_names(void); static void st_collections_group_limits_vertical(void); static void st_collections_group_limits_horizontal(void); @@ -716,6 +717,7 @@ New_Statement_Handler statement_handlers[] = {"collections.group.program_source", st_collections_group_program_source}, {"collections.group.inherit", st_collections_group_inherit}, {"collections.group.inherit_only", st_collections_group_inherit_only}, + {"collections.group.use_custom_seat_names", st_collections_group_use_custom_seat_names}, {"collections.group.target_group", st_collections_group_target_group}, /* dup */ {"collections.group.part_remove", st_collections_group_part_remove}, {"collections.group.program_remove", st_collections_group_program_remove}, @@ -2032,6 +2034,7 @@ _edje_program_copy(Edje_Program *ep, Edje_Program *ep2) ep->in.from = ep2->in.from; ep->in.range = ep2->in.range; ep->action = ep2->action; + ep->seat = STRDUP(ep2->seat); ep->state = STRDUP(ep2->state); ep->state2 = STRDUP(ep2->state2); ep->value = ep2->value; @@ -4516,6 +4519,43 @@ st_collections_group_inherit_only(void) /** @page edcref @property + use_custom_seat_names + @parameters + [1 or 0] + @effect + This flags a group as designed to listen for multiseat signals + following a custom naming instead of default Edje naming. + Seats are named on Edje as "seat1", "seat2", etc, in an incremental + way and never are changed. + + But on Evas, names may be set on different places + (Evas, Ecore Evas backends, the application itself) + and name changes are allowed. + So custom names come from system at first, but can be overriden with + evas_device_name_set(). + Also Evas seat names don't need to follow any pattern. + + It's useful for cases where there is control of the + system, as seat names, or when the application + sets the devices names to guarantee they'll match + seat names on EDC. + @since 1.19 + @endproperty +*/ +static void +st_collections_group_use_custom_seat_names(void) +{ + Edje_Part_Collection *pc; + + check_arg_count(1); + + pc = eina_list_data_get(eina_list_last(edje_collections)); + pc->use_custom_seat_names = parse_bool(0); +} + +/** + @page edcref + @property target_group @parameters [name] [part or program] (part or program) (part or program) ... @@ -4691,6 +4731,7 @@ st_collections_group_inherit(void) pc->prop.orientation = pc2->prop.orientation; pc->lua_script_only = pc2->lua_script_only; + pc->use_custom_seat_names = pc2->use_custom_seat_names; pcp = (Edje_Part_Collection_Parser *)pc; pcp2 = (Edje_Part_Collection_Parser *)pc2; @@ -6067,6 +6108,7 @@ _program_free(Edje_Program *pr) free((void*)pr->source); free((void*)pr->filter.part); free((void*)pr->filter.state); + free((void*)pr->seat); free((void*)pr->state); free((void*)pr->state2); free((void*)pr->sample_name); @@ -14091,8 +14133,8 @@ st_collections_group_programs_program_in(void) @li DRAG_VAL_SET 0.5 0.0 @li DRAG_VAL_STEP 1.0 0.0 @li DRAG_VAL_PAGE 0.0 0.0 - @li FOCUS_SET - @li FOCUS_OBJECT + @li FOCUS_SET ("seat") + @li FOCUS_OBJECT ("seat") @li PARAM_COPY "src_part" "src_param" "dst_part" "dst_param" @li PARAM_SET "part" "param" "value" @li PLAY_SAMPLE "sample name" speed (channel) @@ -14109,7 +14151,7 @@ st_collections_group_programs_program_in(void) @li PHYSICS_ROT_SET 0.707 0 0 0.707 Only one action can be specified per program. - + PLAY_SAMPLE (optional) channel can be one of: @li EFFECT/FX @li BACKGROUND/BG @@ -14167,6 +14209,14 @@ st_collections_group_programs_program_action(void) else ep->value = parse_float_range(2, 0.0, 1.0); } + else if ((ep->action == EDJE_ACTION_TYPE_FOCUS_SET) || + (ep->action == EDJE_ACTION_TYPE_FOCUS_OBJECT)) + { + if (get_arg_count() == 1) + ep->seat = NULL; + else + ep->seat = parse_str(1); + } else if (ep->action == EDJE_ACTION_TYPE_SIGNAL_EMIT) { ep->state = parse_str(1); @@ -14308,8 +14358,6 @@ st_collections_group_programs_program_action(void) * completeness */ break; case EDJE_ACTION_TYPE_ACTION_STOP: - case EDJE_ACTION_TYPE_FOCUS_OBJECT: - case EDJE_ACTION_TYPE_FOCUS_SET: case EDJE_ACTION_TYPE_PHYSICS_FORCES_CLEAR: case EDJE_ACTION_TYPE_PHYSICS_STOP: check_arg_count(1); @@ -14333,6 +14381,10 @@ st_collections_group_programs_program_action(void) case EDJE_ACTION_TYPE_STATE_SET: check_min_arg_count(2); break; + case EDJE_ACTION_TYPE_FOCUS_SET: + case EDJE_ACTION_TYPE_FOCUS_OBJECT: + check_min_arg_count(1); + break; default: check_arg_count(3); } diff --git a/src/examples/edje/.gitignore b/src/examples/edje/.gitignore index 5b5f5f0cd7..73b171ab35 100644 --- a/src/examples/edje/.gitignore +++ b/src/examples/edje/.gitignore @@ -9,8 +9,12 @@ /edje-codegen-example /edje-color-class /edje-drag +/edje-dynamic-multiseat /edje-edit-part-box /edje-entry +/edje-focus +/edje-multiseat +/edje-multiseat-custom-names /edje-multisense /edje-perspective /edje-signals-messages diff --git a/src/examples/edje/Makefile.am b/src/examples/edje/Makefile.am index 7dff1e3c86..2afacfc6fc 100644 --- a/src/examples/edje/Makefile.am +++ b/src/examples/edje/Makefile.am @@ -23,6 +23,7 @@ box_example.edc \ codegen.edc \ color-class.edc \ drag.edc \ +dynamic_multiseat.edc \ edje-group.edc \ edje-nested.edc \ edje-threshold.edc \ @@ -41,8 +42,11 @@ external_elm_button.edc \ external_elm_check.edc \ external_elm_panes.edc \ external_emotion_elm.edc \ +focus.edc \ lua_script.edc \ messages_echo.edc \ +multiseat.edc \ +multiseat_custom_names.edc \ perspective.edc \ signals-messages.edc \ signalsBubble.edc \ @@ -138,8 +142,12 @@ edje-box2.c \ edje-codegen-example.c \ edje-color-class.c \ edje-drag.c \ +edje-dynamic-multiseat.c \ edje-edit-part-box.c \ edje-entry.c \ +edje-focus.c \ +edje-multiseat.c \ +edje-multiseat-custom-names.c \ edje-multisense.c \ edje-perspective.c \ edje-signals-messages.c \ @@ -210,9 +218,13 @@ edje-box \ edje-box2 \ edje-codegen-example \ edje-color-class \ -edje-drag\ +edje-drag \ +edje-dynamic-multiseat \ edje-edit-part-box \ edje-entry \ +edje-focus \ +edje-multiseat \ +edje-multiseat-custom-names \ edje-perspective \ edje-signals-messages \ edje-swallow \ diff --git a/src/examples/edje/dynamic_multiseat.edc b/src/examples/edje/dynamic_multiseat.edc new file mode 100644 index 0000000000..d512f03f72 --- /dev/null +++ b/src/examples/edje/dynamic_multiseat.edc @@ -0,0 +1,279 @@ +collections { + + color_classes { + color_class { + name: "button_bg,1"; + color: 200 200 200 255; + } + color_class { + name: "button_bg,2"; + color: 200 200 200 255; + } + color_class { + name: "button_bg,3"; + color: 200 200 200 255; + } + color_class { + name: "button_bg,4"; + color: 200 200 200 255; + } + } + + group { + name: "example/main"; + min: 400 400; + + parts { + part { + name: "bg"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + } + } + + part { + name: "title"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + to: "bg"; + } + rel2 { + relative: 1.0 0.2; + offset: -1 -1; + to: "bg"; + } + text { + text: "Dynamic Multiseat Example"; + size: 16; + font: "sans"; + min: 1 1; + } + } + } + + part { + name: "buttons"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1.relative: 0.2 0.3; + rel2.relative: 0.8 0.9; + color: 255 255 255 0; + } + } + + part { + name: "button_bg,1"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1 { + to: "buttons"; + relative: 0.1 0.1; + } + rel2 { + to: "buttons"; + relative: 0.45 0.45; + } + color_class: "button_bg,1"; + } + } + + part { + name: "button1"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,1"; + offset: 10 10; + } + rel2 { + to: "button_bg,1"; + offset: -11 -11; + } + color: 200 200 200 255; + } + } + + part { + name: "button_bg,2"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1 { + to: "buttons"; + relative: 0.55 0.1; + } + rel2 { + to: "buttons"; + relative: 0.9 0.45; + } + color_class: "button_bg,2"; + } + } + + part { + name: "button2"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,2"; + offset: 10 10; + } + rel2 { + to: "button_bg,2"; + offset: -11 -11; + } + color: 200 200 200 255; + } + } + + part { + name: "button_bg,3"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1 { + to: "buttons"; + relative: 0.1 0.55; + } + rel2 { + to: "buttons"; + relative: 0.45 0.9; + } + color_class: "button_bg,3"; + } + } + + part { + name: "button3"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,3"; + offset: 10 10; + } + rel2 { + to: "button_bg,3"; + offset: -11 -11; + } + color: 200 200 200 255; + } + } + + part { + name: "button_bg,4"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1 { + to: "buttons"; + relative: 0.55 0.55; + } + rel2 { + to: "buttons"; + relative: 0.9 0.9; + } + color_class: "button_bg,4"; + } + } + + part { + name: "button4"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,4"; + offset: 10 10; + } + rel2 { + to: "button_bg,4"; + offset: -11 -11; + } + color: 200 200 200 255; + } + } + } + + script { + public red; + public green; + public blue; + public seat_count; + } + + programs { + program { + name: "seat,added"; + signal: "seat,added,*"; + source: ""; + script { + new seat_name[128]; + new buf[256]; + new r, g, b; + + r = rand() * 255 / 65535; + append_int(red, r); + g = rand() * 255 / 65535; + append_int(green, g); + b = rand() * 255 / 65535; + append_int(blue, b); + + set_int(seat_count, get_int(seat_count) + 1); + + strncpy(seat_name, sig[strlen("seat,added,")], + strchr(sig[strlen("seat,added,")], ",")); + snprintf(buf, 128, "seat,color,%s,r=%i,g=%i,b=%i", seat_name, + r, g, b); + emit(buf, "theme"); + } + } + + program { + name: "button,in"; + signal: "mouse,in,*"; + source: "button_bg,*"; + script { + new idx, r, g, b; + + idx = atoi(sig[strlen("mouse,in,seat")]) - 1; + r = fetch_int(red, idx); + g = fetch_int(green, idx); + b = fetch_int(blue, idx); + + set_color_class(src, r, g, b, 255); + } + } + + program { + name: "button,out"; + signal: "mouse,out,*"; + source: "button_bg,*"; + script { + set_color_class(src, 200, 200, 200, 255); + } + } + } + } +} diff --git a/src/examples/edje/edje-dynamic-multiseat.c b/src/examples/edje/edje-dynamic-multiseat.c new file mode 100644 index 0000000000..37bde33f99 --- /dev/null +++ b/src/examples/edje/edje-dynamic-multiseat.c @@ -0,0 +1,136 @@ +/** + * Edje example demonstrating how to use multiseat features following + * a dynamic approach. + * + * It's an example of how themes can be implemented even if the number + * of seats using the UI is unknown. + * + * You'll need at least one Evas engine built for it (excluding the + * buffer one) that supports multiseat. It may be wayland or + * X11 with VNC support. Using other engines will lead you to a + * situation where all seats are reported as the same one ("default"). + * + * @verbatim + * edje_cc dynamic-multiseat.edc && gcc -o edje-dynamic-multiseat edje-dynamic-multiseat.c `pkg-config --libs --cflags evas ecore ecore-evas edje` + * @endverbatim + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define EINA_UNUSED +#endif + +#ifndef PACKAGE_DATA_DIR +#define PACKAGE_DATA_DIR "." +#endif + +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <Edje.h> + +#define WIDTH 400 +#define HEIGHT 400 + +static const char *GROUPNAME = "example/main"; +static const char *EDJE_FILE = PACKAGE_DATA_DIR"/dynamic_multiseat.edj"; + +static void +_on_destroy(Ecore_Evas *ee EINA_UNUSED) +{ + ecore_main_loop_quit(); +} + +static void +_on_canvas_resize(Ecore_Evas *ee) +{ + Evas_Object *bg; + Evas_Object *edje_obj; + int w, h; + + bg = ecore_evas_data_get(ee, "background"); + edje_obj = ecore_evas_data_get(ee, "edje_obj"); + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + evas_object_resize(bg, w, h); + evas_object_resize(edje_obj, w, h); +} + +static void +_edje_seat_cb(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, const char *emission, const char *source EINA_UNUSED) +{ + const char *sig; + + sig = emission + strlen("seat,"); + printf("Device %s\n", sig); +} + +static void +_print_msg_cb(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, const char *emission, const char *source EINA_UNUSED) +{ + printf("Info: %s\n", emission); +} + +int +main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED) +{ + Evas_Object *edje_obj, *bg; + Ecore_Evas *ee; + Evas *evas; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + if (!edje_init()) + goto shutdown_ecore_evas; + + ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL); + if (!ee) goto shutdown_edje; + + ecore_evas_callback_destroy_set(ee, _on_destroy); + ecore_evas_callback_resize_set(ee, _on_canvas_resize); + ecore_evas_title_set(ee, "Edje Dynamic Multiseat Example"); + + evas = ecore_evas_get(ee); + + bg = evas_object_rectangle_add(evas); + evas_object_color_set(bg, 255, 255, 255, 255); + evas_object_resize(bg, WIDTH, HEIGHT); + evas_object_show(bg); + ecore_evas_data_set(ee, "background", bg); + + edje_obj = edje_object_add(evas); + + if (!edje_object_file_set(edje_obj, EDJE_FILE, GROUPNAME)) + printf("failed to set file %s.\n", EDJE_FILE); + + evas_object_move(edje_obj, 0, 0); + evas_object_resize(edje_obj, WIDTH, HEIGHT); + evas_object_show(edje_obj); + ecore_evas_data_set(ee, "edje_obj", edje_obj); + + edje_object_signal_callback_add(edje_obj, "seat,*", "", + _edje_seat_cb, NULL); + edje_object_signal_callback_add(edje_obj, "*", "theme", + _print_msg_cb, NULL); + + printf("Running example on evas engine %s\n", + ecore_evas_engine_name_get(ee)); + + ecore_evas_show(ee); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + edje_shutdown(); + + return EXIT_SUCCESS; + +shutdown_edje: + edje_shutdown(); +shutdown_ecore_evas: + ecore_evas_shutdown(); + + return EXIT_FAILURE; +} diff --git a/src/examples/edje/edje-focus.c b/src/examples/edje/edje-focus.c new file mode 100644 index 0000000000..01e9e2eeb6 --- /dev/null +++ b/src/examples/edje/edje-focus.c @@ -0,0 +1,157 @@ +/** + * Edje example demonstrating how to deal with part and objects focus. + * + * @verbatim + * edje_cc focus.edc && gcc -o edje-focus edje-focus.c `pkg-config --libs --cflags evas ecore ecore-evas edje` + * @endverbatim + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define EINA_UNUSED +#endif + +#ifndef PACKAGE_DATA_DIR +#define PACKAGE_DATA_DIR "." +#endif + +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <Edje.h> + +#define WIDTH 400 +#define HEIGHT 400 + +static const char *GROUPNAME = "example/main"; +static const char *EDJE_FILE = PACKAGE_DATA_DIR"/focus.edj"; + +static void +_on_destroy(Ecore_Evas *ee EINA_UNUSED) +{ + ecore_main_loop_quit(); +} + +static void +_on_canvas_resize(Ecore_Evas *ee) +{ + Evas_Object *edje_obj; + int w, h; + + edje_obj = ecore_evas_data_get(ee, "edje_obj"); + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + evas_object_resize(edje_obj, w, h); +} + +static void +_focus_part_in_cb(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, + const char *emission EINA_UNUSED, const char *source) +{ + printf("Focus set to part %s\n", source); +} + +static void +_focus_part_out_cb(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, + const char *emission EINA_UNUSED, const char *source) +{ + printf("Focus unset to part %s\n", source); +} + +static void +_focus_obj_in_cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + Efl_Input_Focus *ev = event->info; + Evas_Object *rect = event->object; + /* it always will print the default seat name, since FOCUS_OBJECT + isn't setting a specific seat */ + printf("Focus set to object %s (seat %s)\n", evas_object_name_get(rect), + efl_input_device_name_get(efl_input_device_get(ev))); +} + +static void +_focus_obj_out_cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + Efl_Input_Focus *ev = event->info; + Evas_Object *rect = event->object; + printf("Focus unset to object %s (seat %s)\n", evas_object_name_get(rect), + efl_input_device_name_get(efl_input_device_get(ev))); +} + +int +main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED) +{ + Evas_Object *edje_obj, *rect_left, *rect_right; + Ecore_Evas *ee; + Evas *evas; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + if (!edje_init()) + goto shutdown_ecore_evas; + + ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL); + if (!ee) goto shutdown_edje; + + ecore_evas_callback_destroy_set(ee, _on_destroy); + ecore_evas_callback_resize_set(ee, _on_canvas_resize); + ecore_evas_title_set(ee, "Edje Focus Example"); + + evas = ecore_evas_get(ee); + + edje_obj = edje_object_add(evas); + + if (!edje_object_file_set(edje_obj, EDJE_FILE, GROUPNAME)) + printf("failed to set file %s.\n", EDJE_FILE); + + evas_object_move(edje_obj, 0, 0); + evas_object_resize(edje_obj, WIDTH, HEIGHT); + evas_object_show(edje_obj); + ecore_evas_data_set(ee, "edje_obj", edje_obj); + + edje_object_signal_callback_add(edje_obj, "focus,part,in", "*", + _focus_part_in_cb, NULL); + edje_object_signal_callback_add(edje_obj, "focus,part,out", "*", + _focus_part_out_cb, NULL); + + rect_left = evas_object_rectangle_add(evas); + evas_object_name_set(rect_left, "rect left"); + evas_object_color_set(rect_left, 200, 200, 100, 255); + edje_object_part_swallow(edje_obj, "button,3", rect_left); + + efl_event_callback_add(rect_left, EFL_EVENT_FOCUS_IN, + _focus_obj_in_cb, NULL); + efl_event_callback_add(rect_left, EFL_EVENT_FOCUS_OUT, + _focus_obj_out_cb, NULL); + + rect_right = evas_object_rectangle_add(evas); + evas_object_name_set(rect_right, "rect right"); + evas_object_color_set(rect_right, 100, 200, 200, 255); + edje_object_part_swallow(edje_obj, "button,4", rect_right); + + efl_event_callback_add(rect_right, EFL_EVENT_FOCUS_IN, + _focus_obj_in_cb, NULL); + efl_event_callback_add(rect_right, EFL_EVENT_FOCUS_OUT, + _focus_obj_out_cb, NULL); + + printf("Running example on evas engine %s\n", + ecore_evas_engine_name_get(ee)); + + ecore_evas_show(ee); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + edje_shutdown(); + + return EXIT_SUCCESS; + +shutdown_edje: + edje_shutdown(); +shutdown_ecore_evas: + ecore_evas_shutdown(); + + return EXIT_FAILURE; +} diff --git a/src/examples/edje/edje-multiseat-custom-names.c b/src/examples/edje/edje-multiseat-custom-names.c new file mode 100644 index 0000000000..7182d0c1ea --- /dev/null +++ b/src/examples/edje/edje-multiseat-custom-names.c @@ -0,0 +1,150 @@ +/** + * Edje example demonstrating how to deal with part and objects focus. + * + * @verbatim + * edje_cc focus.edc && gcc -o edje-focus edje-focus.c `pkg-config --libs --cflags evas ecore ecore-evas edje` + * @endverbatim + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define EINA_UNUSED +#endif + +#ifndef PACKAGE_DATA_DIR +#define PACKAGE_DATA_DIR "." +#endif + +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <Edje.h> + +#define WIDTH 400 +#define HEIGHT 400 + +static const char *GROUPNAME = "example/main"; +static const char *EDJE_FILE = PACKAGE_DATA_DIR"/multiseat_custom_names.edj"; + +static Efl_Input_Device *default_seat = NULL; +static Efl_Input_Device *secondary_seat = NULL; + +static void +_on_destroy(Ecore_Evas *ee EINA_UNUSED) +{ + ecore_main_loop_quit(); +} + +static void +_on_canvas_resize(Ecore_Evas *ee) +{ + Evas_Object *edje_obj; + int w, h; + + edje_obj = ecore_evas_data_get(ee, "edje_obj"); + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + evas_object_resize(edje_obj, w, h); +} + +static void +_device_rename(Efl_Input_Device *dev) +{ + if (!default_seat) { + default_seat = dev; + efl_input_device_name_set(dev, "default"); + return; + } + + if (!secondary_seat) { + secondary_seat = dev; + efl_input_device_name_set(dev, "secondary"); + } +} + +static void +_device_added(void *data EINA_UNUSED, const Efl_Event *event) +{ + Efl_Input_Device *dev = event->info; + + if (efl_input_device_type_get(dev) != EFL_INPUT_DEVICE_CLASS_SEAT) + return; + _device_rename(dev); +} + +static void +_device_changed(void *data EINA_UNUSED, const Efl_Event *event) +{ + Efl_Input_Device *dev = event->info; + + if (dev == default_seat) + efl_input_device_name_set(dev, "default"); + else if (dev == secondary_seat) + efl_input_device_name_set(dev, "secondary"); +} + +int +main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED) +{ + const Eina_List *devices, *l; + Efl_Input_Device *dev; + Evas_Object *edje_obj; + Ecore_Evas *ee; + Evas *evas; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + if (!edje_init()) + goto shutdown_ecore_evas; + + ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL); + if (!ee) goto shutdown_edje; + + ecore_evas_callback_destroy_set(ee, _on_destroy); + ecore_evas_callback_resize_set(ee, _on_canvas_resize); + ecore_evas_title_set(ee, "Edje Focus Example"); + + evas = ecore_evas_get(ee); + + edje_obj = edje_object_add(evas); + + if (!edje_object_file_set(edje_obj, EDJE_FILE, GROUPNAME)) + printf("failed to set file %s.\n", EDJE_FILE); + + evas_object_move(edje_obj, 0, 0); + evas_object_resize(edje_obj, WIDTH, HEIGHT); + evas_object_show(edje_obj); + ecore_evas_data_set(ee, "edje_obj", edje_obj); + + devices = evas_device_list(evas, NULL); + EINA_LIST_FOREACH(devices, l, dev) + { + if (efl_input_device_type_get(dev) == EFL_INPUT_DEVICE_CLASS_SEAT) + _device_rename(dev); + } + efl_event_callback_add(evas, EFL_CANVAS_EVENT_DEVICE_ADDED, + _device_added, NULL); + efl_event_callback_add(evas, EFL_CANVAS_EVENT_DEVICE_CHANGED, + _device_changed, NULL); + + printf("Running example on evas engine %s\n", + ecore_evas_engine_name_get(ee)); + + ecore_evas_show(ee); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + edje_shutdown(); + + return EXIT_SUCCESS; + +shutdown_edje: + edje_shutdown(); +shutdown_ecore_evas: + ecore_evas_shutdown(); + + return EXIT_FAILURE; +} diff --git a/src/examples/edje/edje-multiseat.c b/src/examples/edje/edje-multiseat.c new file mode 100644 index 0000000000..3387fb11cc --- /dev/null +++ b/src/examples/edje/edje-multiseat.c @@ -0,0 +1,287 @@ +/** + * Edje example demonstrating how to use multiseat features. + * + * You'll need at least one Evas engine built for it (excluding the + * buffer one) that supports multiseat. It may be wayland or + * X11 with VNC support. Using other engines will lead you to a + * situation where all seats are reported as the same one ("default"). + * + * @verbatim + * edje_cc multiseat.edc && gcc -o edje-multiseat edje-multiseat.c `pkg-config --libs --cflags evas ecore ecore-evas edje` + * @endverbatim + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define EINA_UNUSED +#endif + +#ifndef PACKAGE_DATA_DIR +#define PACKAGE_DATA_DIR "." +#endif + +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <Edje.h> + +#define EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT +#include <Edje_Edit.h> + +#define WIDTH 400 +#define HEIGHT 400 + +static const char *GROUPNAME = "example/main"; +static const char *PARTNAME_KNOB1 = "example/knob1"; +static const char *PARTNAME_KNOB2 = "example/knob2"; +static const char *EDJE_FILE = PACKAGE_DATA_DIR"/multiseat.edj"; + +static void +_on_destroy(Ecore_Evas *ee EINA_UNUSED) +{ + ecore_main_loop_quit(); +} + +static void +_on_canvas_resize(Ecore_Evas *ee) +{ + Evas_Object *bg; + Evas_Object *edje_obj; + int w, h; + + bg = ecore_evas_data_get(ee, "background"); + edje_obj = ecore_evas_data_get(ee, "edje_obj"); + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + evas_object_resize(bg, w, h); + evas_object_resize(edje_obj, w, h); +} + +static void +_on_rect_focus_in(void *data, const Efl_Event *event) +{ + Evas_Object *rect, *edje_obj; + Efl_Input_Device *seat; + Eina_Stringshare *name; + Efl_Input_Focus *ev; + + edje_obj = data; + rect = event->object; + ev = event->info; + seat = efl_input_device_get(ev); + name = edje_obj_seat_name_get(edje_obj, seat); + + printf("Seat %s (%s) focused the rect object\n", + efl_input_device_name_get(seat), name); + + if (!strcmp(name, "seat1")) + evas_object_color_set(rect, 200, 0, 0, 255); + else if (!strcmp(name, "seat2")) + evas_object_color_set(rect, 0, 200, 0, 255); + else + printf("Unexpected seat %s - no color change\n", name); +} + +static void +_on_rect_focus_out(void *data, const Efl_Event *event) +{ + Evas_Object *rect, *edje_obj; + Efl_Input_Device *seat; + Eina_Stringshare *name; + Efl_Input_Focus *ev; + + edje_obj = data; + rect = event->object; + ev = event->info; + seat = efl_input_device_get(ev); + name = edje_obj_seat_name_get(edje_obj, seat); + + printf("Seat %s (%s) unfocused the rect object\n", + efl_input_device_name_get(seat), name); + evas_object_color_set(rect, 200, 200, 200, 255); + + efl_canvas_object_seat_focus_add(edje_obj, seat); +} + +static void +_on_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *event_info) +{ + Evas_Event_Key_Down *ev = event_info; + const Evas_Modifier *mods; + Efl_Input_Device *seat; + Evas *evas = data; + + seat = efl_input_device_seat_get(ev->dev); + printf("Seat %s (%s) pressed key %s\n", efl_input_device_name_get(seat), + edje_obj_seat_name_get(o, seat), ev->key); + + mods = evas_key_modifier_get(evas); + if (!strcmp(ev->key, "p") && + evas_seat_key_modifier_is_set(mods, "Control", seat)) + { + Evas_Object *edje_edit_obj; + + edje_edit_obj = edje_edit_object_add(evas); + if (!edje_object_file_set(edje_edit_obj, EDJE_FILE, GROUPNAME)) + printf("failed to set file %s.\n", EDJE_FILE); + + printf("EDC source code:\n%s\n", + edje_edit_source_generate(edje_edit_obj)); + evas_object_del(edje_edit_obj); + } +} + +static void +_on_drag_started(void *data EINA_UNUSED, Evas_Object *o, const char *emission, const char *source) +{ + Eina_Stringshare *seat_name; + const char *seat_name_str; + Efl_Input_Device *seat; + + seat_name_str = emission + strlen("drag,start,"); + seat_name = eina_stringshare_add(seat_name_str); + seat = edje_obj_seat_get(o, seat_name); + printf("Seat %s (%s) started drag %s\n", efl_input_device_name_get(seat), + seat_name, source); + eina_stringshare_del(seat_name); +} + +static void +_setup_drag(Evas_Object *edje_obj, const char *partname) +{ + if (!edje_object_part_drag_size_set(edje_obj, partname, 1.0, 0.4)) + printf("error when setting drag size.\n"); + + if (!edje_object_part_drag_step_set(edje_obj, partname, 0.0, 0.1)) + printf("error when setting drag step size.\n"); + + if (!edje_object_part_drag_page_set(edje_obj, partname, 0.0, 0.3)) + printf("error when setting drag page step size.\n"); + + edje_object_signal_callback_add(edje_obj, "drag,start,*", partname, + _on_drag_started, NULL); +} + +static void +_edje_load_cb(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) +{ + printf("Edje loaded\n"); +} + +static void +_edje_seat_cb(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, const char *emission, const char *source EINA_UNUSED) +{ + const char *sig; + + sig = emission + strlen("seat,"); + printf("Device %s\n", sig); +} + +static void +_device_added(void *data, const Efl_Event *event) +{ + Efl_Input_Device *dev = event->info; + Evas_Object *edje_obj = data; + + if (efl_input_device_type_get(dev) != EFL_INPUT_DEVICE_CLASS_SEAT) + return; + + efl_canvas_object_seat_focus_add(edje_obj, dev); +} + +int +main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED) +{ + const Eina_List *devices, *l; + Evas_Object *edje_obj, *bg, *rect; + Efl_Input_Device *dev; + Ecore_Evas *ee; + Evas *evas; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + if (!edje_init()) + goto shutdown_ecore_evas; + + ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL); + if (!ee) goto shutdown_edje; + + ecore_evas_callback_destroy_set(ee, _on_destroy); + ecore_evas_callback_resize_set(ee, _on_canvas_resize); + ecore_evas_title_set(ee, "Edje Multiseat Example"); + + evas = ecore_evas_get(ee); + + bg = evas_object_rectangle_add(evas); + evas_object_color_set(bg, 255, 255, 255, 255); + evas_object_resize(bg, WIDTH, HEIGHT); + evas_object_show(bg); + ecore_evas_data_set(ee, "background", bg); + + edje_obj = edje_object_add(evas); + + if (!edje_object_file_set(edje_obj, EDJE_FILE, GROUPNAME)) + printf("failed to set file %s.\n", EDJE_FILE); + + evas_object_move(edje_obj, 0, 0); + evas_object_resize(edje_obj, WIDTH, HEIGHT); + evas_object_show(edje_obj); + ecore_evas_data_set(ee, "edje_obj", edje_obj); + + _setup_drag(edje_obj, PARTNAME_KNOB1); + _setup_drag(edje_obj, PARTNAME_KNOB2); + + edje_object_part_text_set(edje_obj, "example/text1", "Type here : "); + edje_object_part_text_cursor_end_set(edje_obj, "example/text1", + EDJE_CURSOR_MAIN); + + edje_object_part_text_set(edje_obj, "example/text2", "Or maybe here : "); + edje_object_part_text_cursor_end_set(edje_obj, "example/text2", + EDJE_CURSOR_MAIN); + + rect = evas_object_rectangle_add(evas); + evas_object_color_set(rect, 200, 200, 200, 255); + edje_object_part_swallow(edje_obj, "example/swallow", rect); + efl_event_callback_add(rect, EFL_EVENT_FOCUS_IN, + _on_rect_focus_in, edje_obj); + efl_event_callback_add(rect, EFL_EVENT_FOCUS_OUT, + _on_rect_focus_out, edje_obj); + + devices = evas_device_list(evas, NULL); + EINA_LIST_FOREACH(devices, l, dev) + { + if (efl_input_device_type_get(dev) == EFL_INPUT_DEVICE_CLASS_SEAT) + efl_canvas_object_seat_focus_add(edje_obj, dev); + + } + efl_event_callback_add(evas, EFL_CANVAS_EVENT_DEVICE_ADDED, + _device_added, edje_obj); + evas_object_event_callback_add(edje_obj, EVAS_CALLBACK_KEY_DOWN, + _on_key_down, evas); + edje_object_signal_callback_add(edje_obj, "seat,*", "", + _edje_seat_cb, NULL); + edje_object_signal_callback_add(edje_obj, "load", "", + _edje_load_cb, NULL); + + printf("Running example on evas engine %s\n", + ecore_evas_engine_name_get(ee)); + printf("Press 'Ctrl + p' to print EDC source code\n"); + + ecore_evas_show(ee); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + edje_shutdown(); + + return EXIT_SUCCESS; + +shutdown_edje: + edje_shutdown(); +shutdown_ecore_evas: + ecore_evas_shutdown(); + + return EXIT_FAILURE; +} diff --git a/src/examples/edje/focus.edc b/src/examples/edje/focus.edc new file mode 100644 index 0000000000..9b2ad3bec8 --- /dev/null +++ b/src/examples/edje/focus.edc @@ -0,0 +1,330 @@ +collections { + + group { + name: "example/main"; + min: 400 400; + + parts { + part { + name: "bg"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + } + } + + part { + name: "title"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + to: "bg"; + } + rel2 { + relative: 1.0 0.2; + offset: -1 -1; + to: "bg"; + } + text { + text: "Focus Example"; + size: 16; + font: "sans"; + min: 1 1; + } + } + } + + part { + name: "buttons"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1.relative: 0.2 0.3; + rel2.relative: 0.8 0.9; + color: 255 255 255 0; + } + } + + part { + name: "button_bg,1"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1 { + to: "buttons"; + relative: 0.1 0.1; + } + rel2 { + to: "buttons"; + relative: 0.45 0.45; + } + color: 200 200 200 255; + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + color: 190 120 120 255; + } + } + + part { + name: "button,1"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,1"; + offset: 10 10; + } + rel2 { + to: "button_bg,1"; + offset: -11 -11; + } + color: 200 200 200 255; + } + } + + part { + name: "button_bg,2"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1 { + to: "buttons"; + relative: 0.55 0.1; + } + rel2 { + to: "buttons"; + relative: 0.9 0.45; + } + color: 200 200 200 255; + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + color: 190 120 120 255; + } + } + + part { + name: "button,2"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,2"; + offset: 10 10; + } + rel2 { + to: "button_bg,2"; + offset: -11 -11; + } + color: 200 200 200 255; + } + } + + part { + name: "button_bg,3"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1 { + to: "buttons"; + relative: 0.1 0.55; + } + rel2 { + to: "buttons"; + relative: 0.45 0.9; + } + color: 200 200 200 255; + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + color: 190 120 120 255; + } + } + + part { + name: "button,3"; + type: SWALLOW; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,3"; + offset: 10 10; + } + rel2 { + to: "button_bg,3"; + offset: -11 -11; + } + } + } + + part { + name: "button_bg,4"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1 { + to: "buttons"; + relative: 0.55 0.55; + } + rel2 { + to: "buttons"; + relative: 0.9 0.9; + } + color: 200 200 200 255; + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + color: 190 120 120 255; + } + } + + part { + name: "button,4"; + type: SWALLOW; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,4"; + offset: 10 10; + } + rel2 { + to: "button_bg,4"; + offset: -11 -11; + } + } + } + } + + programs { + program { + name: "button,clicked,1"; + signal: "mouse,clicked,1"; + source: "button_bg,1"; + action: FOCUS_SET; + target: "button,1"; + after: "unfocus,objects"; + } + + program { + name: "button,clicked,2"; + signal: "mouse,clicked,1"; + source: "button_bg,2"; + action: FOCUS_SET; + target: "button,2"; + after: "unfocus,objects"; + } + + program { + name: "unfocus,objects"; + action: FOCUS_OBJECT; + } + + program { + name: "button,clicked,3"; + signal: "mouse,clicked,1"; + source: "button_bg,3"; + action: FOCUS_OBJECT; + target: "button,3"; + after: "unset,part"; + } + + program { + name: "button,clicked,4"; + signal: "mouse,clicked,1"; + source: "button_bg,4"; + action: FOCUS_OBJECT; + target: "button,4"; + after: "unset,part"; + } + + program { + name: "unset,part"; + action: FOCUS_SET; + } + + program { + name: "button,focused,1"; + signal: "focus,part,in"; + source: "button,1"; + action: STATE_SET "focused" 0.0; + target: "button_bg,1"; + } + + program { + name: "button,focused,2"; + signal: "focus,part,in"; + source: "button,2"; + action: STATE_SET "focused" 0.0; + target: "button_bg,2"; + } + + program { + name: "button,focused,3"; + signal: "focus,part,in"; + source: "button,3"; + action: STATE_SET "focused" 0.0; + target: "button_bg,3"; + } + + program { + name: "button,focused,4"; + signal: "focus,part,in"; + source: "button,4"; + action: STATE_SET "focused" 0.0; + target: "button_bg,4"; + } + + program { + name: "button,unfocused,1"; + signal: "focus,part,out"; + source: "button,1"; + action: STATE_SET "default" 0.0; + target: "button_bg,1"; + } + + program { + name: "button,unfocused,2"; + signal: "focus,part,out"; + source: "button,2"; + action: STATE_SET "default" 0.0; + target: "button_bg,2"; + } + + program { + name: "button,unfocused,3"; + signal: "focus,part,out"; + source: "button,3"; + action: STATE_SET "default" 0.0; + target: "button_bg,3"; + } + + program { + name: "button,unfocused,4"; + signal: "focus,part,out"; + source: "button,4"; + action: STATE_SET "default" 0.0; + target: "button_bg,4"; + } + } + } +} diff --git a/src/examples/edje/multiseat.edc b/src/examples/edje/multiseat.edc new file mode 100644 index 0000000000..ce1779bf1c --- /dev/null +++ b/src/examples/edje/multiseat.edc @@ -0,0 +1,792 @@ +collections { + + styles { + style { + name: "entry_style"; + base: "font="sans" font_size=10 color=#000 wrap="word" left_margin=2 right_margin=2"; + } + } + + group { + name: "example/main"; + min: 400 400; + + parts { + part { + name: "bg"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + } + } + + part { + name: "title"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + to: "bg"; + } + rel2 { + relative: 1.0 0.2; + offset: -1 -1; + to: "bg"; + } + text { + text: "Multiseat Example"; + size: 16; + font: "sans"; + min: 1 1; + } + } + } + + part { + name: "drag_area1"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1 { + relative: 0.1 0.25; + offset: -5 0; + } + rel2 { + relative: 0.1 0.9; + offset: 4 0; + } + } + } + + part { + name: "example/knob1"; + type: RECT; + mouse_events: 1; + dragable { + confine: "drag_area1"; + x: 0 0 0; + y: 1 1 0; + } + description { + state: "default" 0.0; + min: 10 10; + color: 200 200 200 255; + } + description { + state: "focused,s1" 0.0; + inherit: "default" 0.0; + color: 200 0 0 255; + } + description { + state: "focused,s2" 0.0; + inherit: "default" 0.0; + color: 0 200 0 255; + } + } + + part { + name: "drag_area2"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1 { + relative: 0.2 0.25; + offset: -5 0; + } + rel2 { + relative: 0.2 0.9; + offset: 4 0; + } + } + } + + part { + name: "example/knob2"; + type: RECT; + mouse_events: 1; + dragable { + confine: "drag_area2"; + x: 0 0 0; + y: 1 1 0; + } + description { + state: "default" 0.0; + min: 10 10; + color: 200 200 200 255; + } + description { + state: "focused,s1" 0.0; + inherit: "default" 0.0; + color: 200 0 0 255; + } + description { + state: "focused,s2" 0.0; + inherit: "default" 0.0; + color: 0 200 0 255; + } + } + + part { + name: "bg_text1"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + min: 10 50; + rel1.relative: 0.3 0.25; + rel2.relative: 0.9 0.4; + color: 200 200 200 255; + } + description { + state: "focused,s1" 0.0; + inherit: "default" 0.0; + color: 200 0 0 255; + } + description { + state: "focused,s2" 0.0; + inherit: "default" 0.0; + color: 0 200 0 255; + } + } + + part { + name: "example/text1"; + type: TEXTBLOCK; + scale: 1; + entry_mode: EDITABLE; + select_mode: DEFAULT; + cursor_mode: UNDER; + mouse_events: 1; + multiline: 1; + source: "example/selection"; + source4: "example/cursor"; + description { + state: "default" 0.0; + min: 12 50; + rel1 { + to: "bg_text1"; + offset: 2 2; + } + rel2 { + to: "bg_text1"; + offset: -3 -3; + } + text { + style: "entry_style"; + min: 0 1; + align: 0.0 0.0; + } + } + } + + part { + name: "bg_text2"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + min: 10 50; + rel1.relative: 0.3 0.45; + rel2.relative: 0.9 0.6; + color: 200 200 200 255; + } + description { + state: "focused,s1" 0.0; + inherit: "default" 0.0; + color: 200 0 0 255; + } + description { + state: "focused,s2" 0.0; + inherit: "default" 0.0; + color: 0 200 0 255; + } + } + + part { + name: "example/text2"; + type: TEXTBLOCK; + scale: 1; + entry_mode: EDITABLE; + select_mode: DEFAULT; + cursor_mode: UNDER; + mouse_events: 1; + multiline: 1; + source: "example/selection"; + source4: "example/cursor"; + description { + state: "default" 0.0; + min: 12 50; + rel1 { + to: "bg_text2"; + offset: 2 2; + } + rel2 { + to: "bg_text2"; + offset: -3 -3; + } + text { + style: "entry_style"; + min: 0 1; + align: 0.0 0.0; + } + } + } + + part { + name: "button_bg"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1.relative: 0.45 0.65; + rel2.relative: 0.9 0.9; + color: 200 200 200 255; + } + } + + part { + name: "button_area"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg"; + offset: 10 10; + } + rel2 { + to: "button_bg"; + offset: -11 -11; + } + color: 0 0 0 0; + } + } + + part { + name: "button_left_over"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_area"; + relative: 0.0 0.0; + } + rel2 { + to: "button_area"; + relative: 0.5 0.5; + } + color: 255 0 0 100; + } + description { + state: "on" 0.0; + inherit: "default" 0.0; + color: 255 0 0 255; + } + } + + part { + name: "button_left_over_label"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1.to: "button_left_over"; + rel2.to: "button_left_over"; + text { + text: "Seat 1 over"; + size: 10; + font: "sans"; + min: 1 1; + } + } + } + + part { + name: "button_left_focus"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_area"; + relative: 0.0 0.5; + } + rel2 { + to: "button_area"; + relative: 0.5 1.0; + } + color: 255 0 0 100; + } + description { + state: "on" 0.0; + inherit: "default" 0.0; + color: 255 0 0 255; + } + } + + part { + name: "button_left_focus_label"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1.to: "button_left_focus"; + rel2.to: "button_left_focus"; + text { + text: "Seat 1 focus"; + size: 10; + font: "sans"; + min: 1 1; + } + } + } + + part { + name: "button_right_over"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_area"; + relative: 0.5 0.0; + } + rel2 { + to: "button_area"; + relative: 1.0 0.5; + } + color: 0 255 0 100; + } + description { + state: "on" 0.0; + inherit: "default" 0.0; + color: 0 255 0 255; + } + } + + part { + name: "button_right_over_label"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1.to: "button_right_over"; + rel2.to: "button_right_over"; + text { + text: "Seat 2 over"; + size: 10; + font: "sans"; + min: 1 1; + } + } + } + + part { + name: "button_right_focus"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_area"; + relative: 0.5 0.5; + } + rel2 { + to: "button_area"; + relative: 1.0 1.0; + } + color: 0 255 0 100; + } + description { + state: "on" 0.0; + inherit: "default" 0.0; + color: 0 255 0 255; + } + } + + part { + name: "button_right_focus_label"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1.to: "button_right_focus"; + rel2.to: "button_right_focus"; + text { + text: "Seat 2 focus"; + size: 10; + font: "sans"; + min: 1 1; + } + } + } + + part { + name: "unfocus_area"; + type: RECT; + mouse_events: 1; + repeat_events: 1; + description { + state: "default" 0.0; + color: 255 255 255 0; + } + } + + part { + name: "example/swallow"; + type: SWALLOW; + mouse_events: 1; + description { + state: "default" 0.0; + rel1.relative: 0.3 0.65; + rel2.relative: 0.4 0.9; + } + } + } + + programs { + program { + name: "focus"; + signal: "load"; + source: ""; + action: FOCUS_SET "seat1"; + target: "example/text1"; + } + + program { + name: "focus,t1,s1"; + signal: "mouse,clicked,1,seat1"; + source: "example/text1"; + action: FOCUS_SET "seat1"; + target: "example/text1"; + } + + program { + name: "focus,color,t1,s1"; + signal: "focus,part,in,seat1"; + source: "example/text1"; + action: STATE_SET "focused,s1" 0.0; + target: "bg_text1"; + } + + program { + name: "unfocus,color,t1,s1"; + signal: "focus,part,out,seat1"; + source: "example/text1"; + action: STATE_SET "default" 0.0; + target: "bg_text1"; + } + + program { + name: "focus,t2,s1"; + signal: "mouse,clicked,1,seat1"; + source: "example/text2"; + action: FOCUS_SET "seat1"; + target: "example/text2"; + } + + program { + name: "focus,color,t2,s1"; + signal: "focus,part,in,seat1"; + source: "example/text2"; + action: STATE_SET "focused,s1" 0.0; + target: "bg_text2"; + } + + program { + name: "unfocus,color,t2,s1"; + signal: "focus,part,out,seat1"; + source: "example/text2"; + action: STATE_SET "default" 0.0; + target: "bg_text2"; + } + + program { + name: "focus,t1,s2"; + signal: "mouse,clicked,1,seat2"; + source: "example/text1"; + action: FOCUS_SET "seat2"; + target: "example/text1"; + } + + program { + name: "focus,color,t1,s2"; + signal: "focus,part,in,seat2"; + source: "example/text1"; + action: STATE_SET "focused,s2" 0.0; + target: "bg_text1"; + } + + program { + name: "unfocus,color,t1,s2"; + signal: "focus,part,out,seat2"; + source: "example/text1"; + action: STATE_SET "default" 0.0; + target: "bg_text1"; + } + + program { + name: "focus,t2,s2"; + signal: "mouse,clicked,1,seat2"; + source: "example/text2"; + action: FOCUS_SET "seat2"; + target: "example/text2"; + } + + program { + name: "focus,color,t2,s2"; + signal: "focus,part,in,seat2"; + source: "example/text2"; + action: STATE_SET "focused,s2" 0.0; + target: "bg_text2"; + } + + program { + name: "unfocus,color,t2,s2"; + signal: "focus,part,out,seat2"; + source: "example/text2"; + action: STATE_SET "default" 0.0; + target: "bg_text2"; + } + + program { + name: "button,left,in"; + signal: "mouse,in,seat1"; + source: "button_bg"; + action: STATE_SET "on" 0.0; + target: "button_left_over"; + } + + program { + name: "button,left,out"; + signal: "mouse,out,seat1"; + source: "button_bg"; + action: STATE_SET "default" 0.0; + target: "button_left_over"; + } + + program { + name: "button,left,focus"; + signal: "mouse,clicked,1,seat1"; + source: "button_bg"; + action: FOCUS_SET "seat1"; + target: "button_bg"; + } + + program { + name: "button,left,focused"; + signal: "focus,part,in,seat1"; + source: "button_bg"; + action: STATE_SET "on" 0.0; + target: "button_left_focus"; + } + + program { + name: "button,left,unfocused"; + signal: "focus,part,out,seat1"; + source: "button_bg"; + action: STATE_SET "default" 0.0; + target: "button_left_focus"; + } + + program { + name: "button,right,in"; + signal: "mouse,in,seat2"; + source: "button_bg"; + action: STATE_SET "on" 0.0; + target: "button_right_over"; + } + + program { + name: "button,right,out"; + signal: "mouse,out,seat2"; + source: "button_bg"; + action: STATE_SET "default" 0.0; + target: "button_right_over"; + } + + program { + name: "button,right,focus"; + signal: "mouse,clicked,1,seat2"; + source: "button_bg"; + action: FOCUS_SET "seat2"; + target: "button_bg"; + } + + program { + name: "button,right,focused"; + signal: "focus,part,in,seat2"; + source: "button_bg"; + action: STATE_SET "on" 0.0; + target: "button_right_focus"; + } + + program { + name: "button,right,unfocused"; + signal: "focus,part,out,seat2"; + source: "button_bg"; + action: STATE_SET "default" 0.0; + target: "button_right_focus"; + } + + program { + name: "knob1,s1"; + signal: "drag,start,seat1"; + source: "example/knob1"; + action: STATE_SET "focused,s1" 0.0; + target: "example/knob1"; + } + + program { + name: "knob1,s2"; + signal: "drag,start,seat2"; + source: "example/knob1"; + action: STATE_SET "focused,s2" 0.0; + target: "example/knob1"; + } + + program { + name: "knob1,seat1"; + signal: "drag,stop,*"; + source: "example/knob1"; + action: STATE_SET "default" 0.0; + target: "example/knob1"; + } + + program { + name: "knob2,s1"; + signal: "drag,start,seat1"; + source: "example/knob2"; + action: STATE_SET "focused,s1" 0.0; + target: "example/knob2"; + } + + program { + name: "knob2,s2"; + signal: "drag,start,seat2"; + source: "example/knob2"; + action: STATE_SET "focused,s2" 0.0; + target: "example/knob2"; + } + + program { + name: "knob2,seat1"; + signal: "drag,stop,*"; + source: "example/knob2"; + action: STATE_SET "default" 0.0; + target: "example/knob2"; + } + + program { + name: "rect,focus,s1"; + signal: "mouse,clicked,1,seat1"; + source: "example/swallow"; + action: FOCUS_OBJECT "seat1"; + target: "example/swallow"; + } + + program { + name: "rect,unfocus,s1"; + signal: "mouse,clicked,1,seat1"; + source: "unfocus_area"; + action: FOCUS_OBJECT "seat1"; + } + + program { + name: "rect,focus,s2"; + signal: "mouse,clicked,1,seat2"; + source: "example/swallow"; + action: FOCUS_OBJECT "seat2"; + target: "example/swallow"; + } + + program { + name: "rect,unfocus,s2"; + signal: "mouse,clicked,1,seat2"; + source: "unfocus_area"; + action: FOCUS_OBJECT "seat2"; + } + } + } + + group { + name: "example/selection"; + + parts { + part { + name: "selection"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 180 180 180 255; + } + } + } + } + + group { + name: "example/cursor"; + min: 1 0; + + parts { + part { + name: "cursor"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + min: 2 12; + color: 0 0 0 255; + } + description { + state: "hidden" 0.0; + inherit: "default" 0.0; + color: 0 0 0 0; + } + } + } + + programs { + program { + name: "cursor_hide"; + signal: "load"; + source: ""; + action: STATE_SET "hidden" 0.0; + target: "cursor"; + transition: SINUSOIDAL 0.2; + after: "cursor_hide_timer"; + } + program { + name: "cursor_hide_timer"; + in: 0.2 0.0; + after: "cursor_show"; + } + program { + name: "cursor_show"; + action: STATE_SET "default" 0.0; + target: "cursor"; + after: "cursor_show_timer"; + } + program { + name: "cursor_show_timer"; + in: 0.5 0.0; + after: "cursor_hide"; + } + } + } +} diff --git a/src/examples/edje/multiseat_custom_names.edc b/src/examples/edje/multiseat_custom_names.edc new file mode 100644 index 0000000000..eb5c493ad0 --- /dev/null +++ b/src/examples/edje/multiseat_custom_names.edc @@ -0,0 +1,175 @@ +collections { + + group { + name: "example/main"; + min: 400 400; + use_custom_seat_names: 1; + + parts { + part { + name: "bg"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + } + } + + part { + name: "title"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + color: 0 0 0 255; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + to: "bg"; + } + rel2 { + relative: 1.0 0.2; + offset: -1 -1; + to: "bg"; + } + text { + text: "Multiseat System Names Example"; + size: 16; + font: "sans"; + min: 1 1; + } + } + } + + part { + name: "button_bg,1"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1.relative: 0.1 0.25; + rel2.relative: 0.45 0.8; + color: 200 200 200 255; + } + description { + state: "over,default" 0.0; + inherit: "default" 0.0; + color: 200 120 120 255; + } + description { + state: "over,secondary" 0.0; + inherit: "default" 0.0; + color: 120 120 200 255; + } + } + + part { + name: "button,1"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,1"; + offset: 10 10; + } + rel2 { + to: "button_bg,1"; + offset: -11 -11; + } + color: 200 200 200 255; + } + } + + part { + name: "button_bg,2"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + rel1.relative: 0.55 0.25; + rel2.relative: 0.9 0.8; + color: 200 200 200 255; + } + description { + state: "over,default" 0.0; + inherit: "default" 0.0; + color: 200 120 120 255; + } + description { + state: "over,secondary" 0.0; + inherit: "default" 0.0; + color: 120 120 200 255; + } + } + + part { + name: "button,2"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "button_bg,2"; + offset: 10 10; + } + rel2 { + to: "button_bg,2"; + offset: -11 -11; + } + color: 200 200 200 255; + } + } + } + + programs { + program { + name: "button,1,over,default"; + signal: "mouse,in,default"; + source: "button_bg,1"; + action: STATE_SET "over,default" 0.0; + target: "button_bg,1"; + } + + program { + name: "button,1,over,secondary"; + signal: "mouse,in,secondary"; + source: "button_bg,1"; + action: STATE_SET "over,secondary" 0.0; + target: "button_bg,1"; + } + + program { + name: "button,1,out"; + signal: "mouse,out"; + source: "button_bg,1"; + action: STATE_SET "default" 0.0; + target: "button_bg,1"; + } + + program { + name: "button,2,over,default"; + signal: "mouse,in,default"; + source: "button_bg,2"; + action: STATE_SET "over,default" 0.0; + target: "button_bg,2"; + } + + program { + name: "button,2,over,secondary"; + signal: "mouse,in,secondary"; + source: "button_bg,2"; + action: STATE_SET "over,secondary" 0.0; + target: "button_bg,2"; + } + + program { + name: "button,2,out"; + signal: "mouse,out"; + source: "button_bg,2"; + action: STATE_SET "default" 0.0; + target: "button_bg,2"; + } + } + } +} diff --git a/src/lib/edje/Edje_Common.h b/src/lib/edje/Edje_Common.h index b99de45935..243a28ca00 100644 --- a/src/lib/edje/Edje_Common.h +++ b/src/lib/edje/Edje_Common.h @@ -1924,7 +1924,7 @@ typedef enum _Edje_Action_Type EDJE_ACTION_TYPE_DRAG_VAL_STEP = 5, /**< Drag val step action value */ EDJE_ACTION_TYPE_DRAG_VAL_PAGE = 6, /**< Drag val page action value */ EDJE_ACTION_TYPE_SCRIPT = 7, /**< Script action value */ - EDJE_ACTION_TYPE_FOCUS_SET = 8, /**< Forcus set action value */ + EDJE_ACTION_TYPE_FOCUS_SET = 8, /**< Focus set action value */ EDJE_ACTION_TYPE_RESERVED00 = 9, /**< Reversed do action value */ EDJE_ACTION_TYPE_FOCUS_OBJECT = 10, /**< Forcus object action value */ EDJE_ACTION_TYPE_PARAM_COPY = 11, /**< Param copy action value */ diff --git a/src/lib/edje/edje_callbacks.c b/src/lib/edje/edje_callbacks.c index b27049fc83..c92f3295bf 100644 --- a/src/lib/edje/edje_callbacks.c +++ b/src/lib/edje/edje_callbacks.c @@ -15,37 +15,45 @@ _edje_hold_signal_cb(void *data, const Efl_Event *event) rp = evas_object_data_get(event->object, "real_part"); if (!rp) return; if (efl_input_hold_get(ev)) - _edje_emit(ed, "hold,on", rp->part->name); + _edje_seat_emit(ed, efl_input_device_get(ev), + "hold,on", rp->part->name); else - _edje_emit(ed, "hold,off", rp->part->name); + _edje_seat_emit(ed, efl_input_device_get(ev), + "hold,off", rp->part->name); } static void _edje_focus_in_signal_cb(void *data, const Efl_Event *event) { + Efl_Input_Focus *ev; Edje *ed; Edje_Real_Part *rp; + ev = event->info; ed = data; rp = evas_object_data_get(event->object, "real_part"); if ((!rp) || (!ed)) return; - _edje_emit(ed, "focus,part,in", rp->part->name); + _edje_seat_emit(ed, efl_input_device_get(ev), + "focus,part,in", rp->part->name); } static void _edje_focus_out_signal_cb(void *data, const Efl_Event *event) { + Efl_Input_Focus *ev; Edje *ed; Edje_Real_Part *rp; + ev = event->info; ed = data; rp = evas_object_data_get(event->object, "real_part"); if ((!rp) || (!ed)) return; - _edje_emit(ed, "focus,part,out", rp->part->name); + _edje_seat_emit(ed, efl_input_device_get(ev), + "focus,part,out", rp->part->name); } static void @@ -61,7 +69,7 @@ _edje_mouse_in_signal_cb(void *data, const Efl_Event *event) if (rp) { if (!(ev->event_flags) || !(rp->part->ignore_flags & ev->event_flags)) - _edje_emit(ed, "mouse,in", rp->part->name); + _edje_seat_emit(ed, ev->device, "mouse,in", rp->part->name); ev->event_flags |= rp->part->mask_flags; } @@ -80,7 +88,7 @@ _edje_mouse_out_signal_cb(void *data, const Efl_Event *event) if (rp) { if (!(ev->event_flags) || !(rp->part->ignore_flags & ev->event_flags)) - _edje_emit(ed, "mouse,out", rp->part->name); + _edje_seat_emit(ed, ev->device, "mouse,out", rp->part->name); ev->event_flags |= rp->part->mask_flags; } @@ -113,7 +121,7 @@ _edje_mouse_down_signal_cb(void *data, const Efl_Event *event) snprintf(buf, sizeof(buf), "mouse,down,%i,double", ev->button); else snprintf(buf, sizeof(buf), "mouse,down,%i", ev->button); - _edje_emit(ed, buf, rp->part->name); + _edje_seat_emit(ed, ev->device, buf, rp->part->name); } if (rp->part->dragable.event_id >= 0) @@ -122,7 +130,7 @@ _edje_mouse_down_signal_cb(void *data, const Efl_Event *event) if (!ignored) { snprintf(buf, sizeof(buf), "mouse,down,%i", ev->button); - _edje_emit(ed, buf, rp->part->name); + _edje_seat_emit(ed, ev->device, buf, rp->part->name); } } @@ -177,7 +185,7 @@ _edje_mouse_up_signal_cb(void *data, const Efl_Event *event) if ((!ev->event_flags) || (!ignored)) { snprintf(buf, sizeof(buf), "mouse,up,%i", ev->button); - _edje_emit(ed, buf, rp->part->name); + _edje_seat_emit(ed, ev->device, buf, rp->part->name); } if (rp->part->dragable.event_id >= 0) @@ -186,7 +194,7 @@ _edje_mouse_up_signal_cb(void *data, const Efl_Event *event) if (!ignored) { snprintf(buf, sizeof(buf), "mouse,up,%i", ev->button); - _edje_emit(ed, buf, rp->part->name); + _edje_seat_emit(ed, ev->device, buf, rp->part->name); } } @@ -206,7 +214,8 @@ _edje_mouse_up_signal_cb(void *data, const Efl_Event *event) rp->invalidate = EINA_TRUE; #endif if (!ignored && rp->drag->started) - _edje_emit(ed, "drag,stop", rp->part->name); + _edje_seat_emit(ed, ev->device, "drag,stop", + rp->part->name); rp->drag->started = EINA_FALSE; _edje_recalc_do(ed); } @@ -216,7 +225,7 @@ _edje_mouse_up_signal_cb(void *data, const Efl_Event *event) if ((rp->still_in) && (rp->clicked_button == ev->button) && (!ev->event_flags)) { snprintf(buf, sizeof(buf), "mouse,clicked,%i", ev->button); - _edje_emit(ed, buf, rp->part->name); + _edje_seat_emit(ed, ev->device, buf, rp->part->name); } rp->clicked_button = 0; rp->still_in = EINA_FALSE; @@ -249,7 +258,7 @@ _edje_mouse_move_signal_cb(void *data, const Efl_Event *event) _edje_ref(ed); if ((!ev->event_flags) || (!ignored)) - _edje_emit(ed, "mouse,move", rp->part->name); + _edje_seat_emit(ed, ev->device, "mouse,move", rp->part->name); if (rp->still_in) { @@ -264,7 +273,8 @@ _edje_mouse_move_signal_cb(void *data, const Efl_Event *event) (ev->cur.x >= (x + w)) || (ev->cur.y >= (y + h))) { if ((ev->pressed_buttons) && ((!ev->event_flags) || (!ignored))) - _edje_emit(ed, "mouse,pressed,out", rp->part->name); + _edje_seat_emit(ed, ev->device, "mouse,pressed,out", + rp->part->name); rp->still_in = EINA_FALSE; } @@ -281,7 +291,8 @@ _edje_mouse_move_signal_cb(void *data, const Efl_Event *event) (ev->cur.x < (x + w)) && (ev->cur.y < (y + h))) { if ((ev->pressed_buttons) && ((!ev->event_flags) || (!ignored))) - _edje_emit(ed, "mouse,pressed,in", rp->part->name); + _edje_seat_emit(ed, ev->device, "mouse,pressed,in", + rp->part->name); rp->still_in = EINA_TRUE; } @@ -316,8 +327,9 @@ _edje_mouse_move_signal_cb(void *data, const Efl_Event *event) if (!ignored) { if (!rp->drag->started) - _edje_emit(ed, "drag,start", rp->part->name); - _edje_emit(ed, "drag", rp->part->name); + _edje_seat_emit(ed, ev->device, "drag,start", + rp->part->name); + _edje_seat_emit(ed, ev->device, "drag", rp->part->name); rp->drag->started = EINA_TRUE; } ed->recalc_call = EINA_TRUE; @@ -353,7 +365,7 @@ _edje_mouse_wheel_signal_cb(void *data, const Efl_Event *event) snprintf(buf, sizeof(buf), "mouse,wheel,%i,%i", ev->wheel.dir == EFL_ORIENT_HORIZONTAL ? 1 : 0, (ev->wheel.z < 0) ? (-1) : (1)); - _edje_emit(ed, buf, rp->part->name); + _edje_seat_emit(ed, ev->device, buf, rp->part->name); } ev->event_flags |= rp->part->mask_flags; diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c index b9a0ee2532..6c4ef6aec1 100644 --- a/src/lib/edje/edje_data.c +++ b/src/lib/edje/edje_data.c @@ -1062,6 +1062,8 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "vibration_name", vibration_name, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "vibration_repeat", vibration_repeat, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "seat", seat, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "state", state, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "state2", state2, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "value", value, EET_T_DOUBLE); @@ -1812,6 +1814,7 @@ _edje_edd_init(void) #endif EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "physics_enabled", physics_enabled, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "script_recursion", script_recursion, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "use_custom_seat_names", use_custom_seat_names, EET_T_UCHAR); } EAPI void diff --git a/src/lib/edje/edje_edit.c b/src/lib/edje/edje_edit.c index 486395c491..6c57a7569b 100644 --- a/src/lib/edje/edje_edit.c +++ b/src/lib/edje/edje_edit.c @@ -10693,6 +10693,7 @@ edje_edit_program_add(Evas_Object *obj, const char *name) epr->in.from = 0.0; epr->in.range = 0.0; epr->action = 0; + epr->seat = NULL; epr->state = NULL; epr->value = 0.0; epr->state2 = NULL; @@ -10788,6 +10789,7 @@ edje_edit_program_del(Evas_Object *obj, const char *prog) _edje_if_string_free(ed, &epr->source); _edje_if_string_free(ed, &epr->filter.part); _edje_if_string_free(ed, &epr->filter.state); + _edje_if_string_free(ed, &epr->seat); _edje_if_string_free(ed, &epr->state); _edje_if_string_free(ed, &epr->state2); _edje_if_string_free(ed, &epr->sample_name); @@ -13185,13 +13187,25 @@ _edje_generate_source_of_program(Evas_Object *obj, const char *program, Eina_Str case EDJE_ACTION_TYPE_FOCUS_SET: { - BUF_APPEND(I4 "action: FOCUS_SET;\n"); + if (epr->seat) + { + BUF_APPEND(I4 "action: FOCUS_SET "); + BUF_APPENDF("\"%s\";\n", epr->seat); + } + else + BUF_APPEND(I4 "action: FOCUS_SET;\n"); break; } case EDJE_ACTION_TYPE_FOCUS_OBJECT: { - BUF_APPEND(I4 "action: FOCUS_OBJECT;\n"); + if (epr->seat) + { + BUF_APPEND(I4 "action: FOCUS_OBJECT "); + BUF_APPENDF("\"%s\";\n", epr->seat); + } + else + BUF_APPEND(I4 "action: FOCUS_OBJECT;\n"); break; } @@ -15602,6 +15616,9 @@ _edje_generate_source_of_group(Edje *ed, Edje_Part_Collection_Directory_Entry *p /* Limits */ _edje_limits_source_generate(ed, buf, &ret); + if (pc->use_custom_seat_names) + BUF_APPENDF(I2 "use_custom_seat_names: 1;\n"); + /* Data */ if (pc->data) { diff --git a/src/lib/edje/edje_entry.c b/src/lib/edje/edje_entry.c index 0d85a5b368..b836e9596e 100644 --- a/src/lib/edje/edje_entry.c +++ b/src/lib/edje/edje_entry.c @@ -113,8 +113,10 @@ _preedit_del(Entry *en) } static void -_edje_entry_focus_in_cb(void *data, Evas_Object *o, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) +_edje_entry_focus_in_cb(void *data, Evas_Object *o, const char *emission, const char *source EINA_UNUSED) { + Efl_Input_Device *seat; + const char *seat_name; Edje_Real_Part *rp; Entry *en; Edje *ed; @@ -130,7 +132,10 @@ _edje_entry_focus_in_cb(void *data, Evas_Object *o, const char *emission EINA_UN en = rp->typedata.text->entry_data; if (!en || !en->imf_context) return; - if (evas_object_focus_get(ed->obj)) + seat_name = emission + sizeof("focus,part,in,") - 1; + seat = _edje_seat_get(ed, seat_name); + + if (evas_object_seat_focus_check(ed->obj, seat)) { ecore_imf_context_focus_in(en->imf_context); _edje_entry_imf_cursor_info_set(en); @@ -158,17 +163,16 @@ _edje_entry_focus_out_cb(void *data, Evas_Object *o EINA_UNUSED, const char *emi #endif static void -_edje_focus_in_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_edje_focus_in(Edje *ed, Efl_Input_Device *seat) { - Edje *ed = data; #ifdef HAVE_ECORE_IMF Edje_Real_Part *rp; Entry *en; #endif - _edje_emit(ed, "focus,in", ""); + _edje_seat_emit(ed, seat, "focus,in", ""); #ifdef HAVE_ECORE_IMF - rp = ed->focused_part; + rp = _edje_focused_part_get(ed, efl_input_device_name_get(seat)); if (!rp) return; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return; @@ -185,17 +189,25 @@ _edje_focus_in_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, } static void -_edje_focus_out_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_edje_focus_in_cb(void *data, const Efl_Event *event) +{ + Efl_Input_Focus *ev = event->info; + + _edje_focus_in(data, efl_input_device_get(ev)); +} + +static void +_edje_focus_out(Edje *ed, Efl_Input_Device *seat) { - Edje *ed = data; #ifdef HAVE_ECORE_IMF - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; Entry *en; #endif - _edje_emit(ed, "focus,out", ""); + _edje_seat_emit(ed, seat, "focus,out", ""); #ifdef HAVE_ECORE_IMF + rp = _edje_focused_part_get(ed, efl_input_device_name_get(seat)); if (!rp) return; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return; @@ -211,6 +223,14 @@ _edje_focus_out_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED #endif } +static void +_edje_focus_out_cb(void *data, const Efl_Event *event) +{ + Efl_Input_Focus *ev = event->info; + + _edje_focus_out(data, efl_input_device_get(ev)); +} + static Edje_Entry_Change_Info * _text_filter_markup_prepend_internal(Edje *ed, Entry *en, Evas_Textblock_Cursor *c, char *text, @@ -1676,7 +1696,9 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, { Edje *ed = data; Evas_Event_Key_Down *ev = event_info; - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; + Efl_Input_Device *seat; + Entry *en; Eina_Bool control, alt, shift; #if defined(__APPLE__) && defined(__MACH__) @@ -1685,6 +1707,10 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, Eina_Bool multiline; Eina_Bool cursor_changed; int old_cur_pos; + + seat = efl_input_device_seat_get(ev->dev); + rp = _edje_focused_part_get(ed, _edje_seat_name_get(ed, seat)); + if (!rp) return; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return; @@ -2340,10 +2366,14 @@ end: static void _edje_key_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { + Evas_Event_Key_Up *ev = event_info; + Efl_Input_Device *seat; Edje *ed = data; - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; Entry *en; + seat = efl_input_device_seat_get(ev->dev); + rp = _edje_focused_part_get(ed, _edje_seat_name_get(ed, seat)); if (!rp) return; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return; @@ -2356,7 +2386,6 @@ _edje_key_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, v #ifdef HAVE_ECORE_IMF if (en->imf_context) { - Evas_Event_Key_Up *ev = event_info; Ecore_IMF_Event_Key_Up ecore_ev; ecore_imf_evas_event_key_up_wrap(ev, &ecore_ev); @@ -2797,26 +2826,36 @@ _canvas_viewport_resize_cb(void *data, Evas *e EINA_UNUSED, void *event_info EIN } static void -_evas_focus_in_cb(void *data, Evas *e, EINA_UNUSED void *event_info) +_evas_focus_in_cb(void *data, const Efl_Event *event) { - Edje *ed = (Edje *)data; + Efl_Input_Focus *ev = event->info; + Evas *e = event->object; + Efl_Input_Device *seat; + Edje *ed = data; + if (!ed) return; - if (evas_focus_get(e) == ed->obj) + seat = efl_input_device_get(ev); + if (evas_canvas_seat_focus_get(e, seat) == ed->obj) { - _edje_focus_in_cb(data, NULL, NULL, NULL); + _edje_focus_in(data, seat); } } static void -_evas_focus_out_cb(void *data, Evas *e, EINA_UNUSED void *event_info) +_evas_focus_out_cb(void *data, const Efl_Event *event) { - Edje *ed = (Edje *)data; + Efl_Input_Focus *ev = event->info; + Evas *e = event->object; + Efl_Input_Device *seat; + Edje *ed = data; + if (!ed) return; - if (evas_focus_get(e) == ed->obj) + seat = efl_input_device_get(ev); + if (evas_canvas_seat_focus_get(e, seat) == ed->obj) { - _edje_focus_out_cb(data, NULL, NULL, NULL); + _edje_focus_out(data, seat); } } @@ -2830,12 +2869,16 @@ _edje_entry_init(Edje *ed) return; ed->entries_inited = EINA_TRUE; - evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb, ed); - evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb, ed); - evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb, ed); - evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb, ed); - evas_event_callback_add(ed->base->evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed); - evas_event_callback_add(ed->base->evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed); + efl_event_callback_add(ed->obj, EFL_EVENT_FOCUS_IN, _edje_focus_in_cb, ed); + efl_event_callback_add(ed->obj, EFL_EVENT_FOCUS_OUT, _edje_focus_out_cb, ed); + evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_DOWN, + _edje_key_down_cb, ed); + evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_UP, + _edje_key_up_cb, ed); + efl_event_callback_add(ed->base->evas, EFL_CANVAS_EVENT_FOCUS_IN, + _evas_focus_in_cb, ed); + efl_event_callback_add(ed->base->evas, EFL_CANVAS_EVENT_FOCUS_OUT, + _evas_focus_out_cb, ed); } void @@ -2847,14 +2890,16 @@ _edje_entry_shutdown(Edje *ed) return; ed->entries_inited = EINA_FALSE; - evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb); - evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb); - evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb); - evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb); - if (evas_event_callback_del_full(ed->base->evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed) != ed) - ERR("could not unregister EVAS_CALLBACK_FOCUS_IN"); - if (evas_event_callback_del_full(ed->base->evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed) != ed) - ERR("could not unregister EVAS_CALLBACK_FOCUS_OUT"); + efl_event_callback_del(ed->obj, EFL_EVENT_FOCUS_IN, _edje_focus_in_cb, ed); + efl_event_callback_del(ed->obj, EFL_EVENT_FOCUS_OUT, _edje_focus_out_cb, ed); + evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_DOWN, + _edje_key_down_cb); + evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_UP, + _edje_key_up_cb); + efl_event_callback_del(ed->base->evas, EFL_CANVAS_EVENT_FOCUS_IN, + _evas_focus_in_cb, ed); + efl_event_callback_del(ed->base->evas, EFL_CANVAS_EVENT_FOCUS_OUT, + _evas_focus_out_cb, ed); } void @@ -2948,8 +2993,12 @@ _edje_entry_real_part_init(Edje *ed, Edje_Real_Part *rp) en->commit_cancel = EINA_FALSE; - edje_object_signal_callback_add(ed->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb, rp); - edje_object_signal_callback_add(ed->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb, rp); + edje_object_signal_callback_add(ed->obj, "focus,part,in,*", + rp->part->name, + _edje_entry_focus_in_cb, rp); + edje_object_signal_callback_add(ed->obj, "focus,part,out,*", + rp->part->name, + _edje_entry_focus_out_cb, rp); ctx_id = ecore_imf_context_default_id_get(); if (ctx_id) @@ -3053,8 +3102,12 @@ _edje_entry_real_part_shutdown(Edje *ed, Edje_Real_Part *rp) en->imf_context = NULL; } - edje_object_signal_callback_del(ed->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb); - edje_object_signal_callback_del(ed->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb); + edje_object_signal_callback_del(ed->obj, "focus,part,in,*", + rp->part->name, + _edje_entry_focus_in_cb); + edje_object_signal_callback_del(ed->obj, "focus,part,out,*", + rp->part->name, + _edje_entry_focus_out_cb); } #endif _compose_seq_reset(en); @@ -4425,15 +4478,31 @@ _edje_entry_imf_cursor_info_set(Entry *en) } #ifdef HAVE_ECORE_IMF + +static Edje_Real_Part * +_edje_entry_imf_default_focused_rp_get(Edje *ed) +{ + Eina_Stringshare *seat_name; + Efl_Input_Device *seat; + Evas *e; + + e = evas_object_evas_get(ed->obj); + seat = evas_canvas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_SEAT); + seat_name = _edje_seat_name_get(ed, seat); + + return _edje_focused_part_get(ed, seat_name); +} + static Eina_Bool _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, char **text, int *cursor_pos) { Edje *ed = data; - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; Entry *en = NULL; const char *str; char *plain_text; + rp = _edje_entry_imf_default_focused_rp_get(ed); if (!rp) return EINA_FALSE; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return EINA_FALSE; @@ -4506,11 +4575,12 @@ static void _edje_entry_imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info) { Edje *ed = data; - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; Entry *en = NULL; char *commit_str = event_info; Edje_Entry_Change_Info *info = NULL; + rp = _edje_entry_imf_default_focused_rp_get(ed); if ((!rp)) return; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return; @@ -4587,7 +4657,7 @@ static void _edje_entry_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info EINA_UNUSED) { Edje *ed = data; - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; Entry *en = NULL; Edje_Entry_Change_Info *info = NULL; int cursor_pos; @@ -4610,6 +4680,7 @@ _edje_entry_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx EINA Eina_Strbuf *buf; Eina_Strbuf *preedit_attr_str; + rp = _edje_entry_imf_default_focused_rp_get(ed); if ((!rp)) return; if ((rp->type != EDJE_RP_TYPE_TEXT) || @@ -4751,7 +4822,7 @@ static void _edje_entry_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info) { Edje *ed = data; - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; Entry *en = NULL; Ecore_IMF_Event_Delete_Surrounding *ev = event_info; Evas_Textblock_Cursor *del_start, *del_end; @@ -4759,6 +4830,8 @@ _edje_entry_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx E int cursor_pos; int start, end; + rp = _edje_entry_imf_default_focused_rp_get(ed); + if ((!rp)) return; if ((!rp) || (!ev)) return; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return; @@ -4810,10 +4883,11 @@ static void _edje_entry_imf_event_selection_set_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info) { Edje *ed = data; - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; Entry *en = NULL; Ecore_IMF_Event_Selection *ev = event_info; + rp = _edje_entry_imf_default_focused_rp_get(ed); if ((!rp) || (!ev)) return; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return; @@ -4844,10 +4918,11 @@ static Eina_Bool _edje_entry_imf_retrieve_selection_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, char **text) { Edje *ed = data; - Edje_Real_Part *rp = ed->focused_part; + Edje_Real_Part *rp; Entry *en = NULL; const char *selection_text = NULL; + rp = _edje_entry_imf_default_focused_rp_get(ed); if (!rp) return EINA_FALSE; if ((rp->type != EDJE_RP_TYPE_TEXT) || (!rp->typedata.text)) return EINA_FALSE; diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c index 3751fae34a..91695b2aa1 100644 --- a/src/lib/edje/edje_load.c +++ b/src/lib/edje/edje_load.c @@ -507,6 +507,176 @@ _edje_physics_world_update_cb(void *data, EPhysics_World *world EINA_UNUSED, voi } #endif +static void +_edje_device_add(Edje *ed, Efl_Input_Device *dev) +{ + Edje_Seat *s, *seat = NULL; + Eina_Stringshare *name; + char sig[256]; + Eina_List *l; + + if (ed->collection && ed->collection->use_custom_seat_names) + name = eina_stringshare_add(efl_input_device_name_get(dev)); + else + { + ed->seats_count++; + name = eina_stringshare_printf("seat%i", ed->seats_count); + } + EINA_SAFETY_ON_NULL_RETURN(name); + + EINA_LIST_FOREACH(ed->seats, l, s) + { + if (s->name != name) + continue; + seat = s; + break; + } + + if (!seat) + { + seat = calloc(1, sizeof(Edje_Seat)); + EINA_SAFETY_ON_NULL_GOTO(seat, seat_err); + ed->seats = eina_list_append(ed->seats, seat); + seat->name = eina_stringshare_ref(name); + } + + seat->device = dev; + snprintf(sig, sizeof(sig), "seat,added,%s,%s", seat->name, + efl_input_device_name_get(dev)); + _edje_emit(ed, sig, ""); + +seat_err: + eina_stringshare_del(name); +} + +static void +_edje_device_added_cb(void *data, const Efl_Event *event) +{ + Efl_Input_Device *dev = event->info; + Edje *ed = data; + + if (efl_input_device_type_get(dev) != EFL_INPUT_DEVICE_CLASS_SEAT) + return; + + _edje_device_add(ed, dev); +} + +static void +_edje_device_removed_cb(void *data, const Efl_Event *event) +{ + Efl_Input_Device *dev = event->info; + Edje_Seat *s, *seat = NULL; + Edje *ed = data; + char sig[256]; + Eina_List *l; + + if (efl_input_device_type_get(dev) != EFL_INPUT_DEVICE_CLASS_SEAT) + return; + + EINA_LIST_FOREACH(ed->seats, l, s) + { + if (s->device != dev) + continue; + seat = s; + break; + } + + /* It shouldn't happen. New seats are always registered. */ + EINA_SAFETY_ON_NULL_RETURN(seat); + + seat->device = NULL; + snprintf(sig, sizeof(sig), "seat,removed,%s", seat->name); + _edje_emit(ed, sig, ""); +} + +static void +_edje_device_changed_cb(void *data, const Efl_Event *event) +{ + Efl_Input_Device *dev = event->info; + Edje_Seat *s, *seat = NULL; + Eina_Stringshare *name; + Edje *ed = data; + char sig[256]; + Eina_List *l; + + if (efl_input_device_type_get(dev) != EFL_INPUT_DEVICE_CLASS_SEAT) + return; + + EINA_LIST_FOREACH(ed->seats, l, s) + { + if (s->device != dev) + continue; + seat = s; + break; + } + + /* not registered seat */ + if (!seat) + return; + + name = efl_input_device_name_get(dev); + if (!name) + return; + + /* no name changes */ + if (eina_streq(seat->name, name)) + return; + + /* check if device name was changed to match name used on EDC */ + EINA_LIST_FOREACH(ed->seats, l, s) + { + if (eina_streq(s->name, name)) + { + if (s->device == dev) + continue; + if (s->device) + { + WRN("Two seats were detected with the same name: %s.\n" + "Fix it or focus will misbehave", name); + break; + } + + /* merge seats */ + s->device = dev; + if (seat->focused_part) + s->focused_part = seat->focused_part; + + ed->seats = eina_list_remove(ed->seats, seat); + eina_stringshare_del(seat->name); + free(seat); + + return; + } + } + + snprintf(sig, sizeof(sig), "seat,renamed,%s,%s", seat->name, name); + eina_stringshare_replace(&seat->name, name); + _edje_emit(ed, sig, ""); +} + +static void +_edje_devices_add(Edje *ed, Evas *tev) +{ + const Eina_List *devices, *l; + Efl_Input_Device *dev; + + devices = evas_device_list(tev, NULL); + EINA_LIST_FOREACH(devices, l, dev) + { + if (efl_input_device_type_get(dev) == EFL_INPUT_DEVICE_CLASS_SEAT) + _edje_device_add(ed, dev); + } + + efl_event_callback_add(tev, EFL_CANVAS_EVENT_DEVICE_ADDED, + _edje_device_added_cb, ed); + efl_event_callback_add(tev, EFL_CANVAS_EVENT_DEVICE_REMOVED, + _edje_device_removed_cb, ed); + + if (ed->collection && ed->collection->use_custom_seat_names) + efl_event_callback_add(tev, EFL_CANVAS_EVENT_DEVICE_CHANGED, + _edje_device_changed_cb, ed); +} + int _edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const char *group, const char *parent, Eina_List *group_path, Eina_Array *nested) { @@ -627,6 +797,9 @@ _edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const ch ERR("Edje compiled without support to physics."); #endif + /* handle multiseat stuff */ + _edje_devices_add(ed, tev); + /* colorclass stuff */ for (i = 0; i < ed->collection->parts_count; ++i) { @@ -1599,7 +1772,19 @@ _edje_file_del(Edje *ed) ed->groups = eina_list_free(ed->groups); - if (tev) evas_event_freeze(tev); + if (tev) + { + efl_event_callback_del(tev, EFL_CANVAS_EVENT_DEVICE_ADDED, + _edje_device_added_cb, ed); + efl_event_callback_del(tev, EFL_CANVAS_EVENT_DEVICE_REMOVED, + _edje_device_removed_cb, ed); + if (ed->collection && ed->collection->use_custom_seat_names) + efl_event_callback_del(tev, EFL_CANVAS_EVENT_DEVICE_CHANGED, + _edje_device_changed_cb, ed); + + evas_event_freeze(tev); + } + if (ed->freeze_calc) { _edje_util_freeze_calc_list = eina_list_remove(_edje_util_freeze_calc_list, ed); @@ -1809,13 +1994,23 @@ _edje_file_del(Edje *ed) } } + if (ed->seats) + { + Edje_Seat *seat; + + EINA_LIST_FREE(ed->seats, seat) + { + eina_stringshare_del(seat->name); + free(seat); + } + } + if (ed->L) _edje_lua2_script_shutdown(ed); while (ed->subobjs) _edje_subobj_unregister(ed, ed->subobjs->data); if (ed->table_parts) free(ed->table_parts); ed->table_parts = NULL; ed->table_parts_size = 0; - ed->focused_part = NULL; if (tev) { evas_event_thaw(tev); @@ -1982,6 +2177,7 @@ _edje_program_free(Edje_Program *pr, Eina_Bool free_strings) if (pr->state2) eina_stringshare_del(pr->state2); if (pr->sample_name) eina_stringshare_del(pr->sample_name); if (pr->tone_name) eina_stringshare_del(pr->tone_name); + if (pr->seat) eina_stringshare_del(pr->seat); } EINA_LIST_FREE(pr->targets, prt) free(prt); diff --git a/src/lib/edje/edje_object.eo b/src/lib/edje/edje_object.eo index 35ce01ef40..4cfded612d 100644 --- a/src/lib/edje/edje_object.eo +++ b/src/lib/edje/edje_object.eo @@ -2066,6 +2066,40 @@ class Edje.Object (Efl.Canvas.Group.Clipped, Efl.File, Efl.Container, Efl.Part, part: string; [[The part name]] } } + @property seat { + get { + [[Return the seat device given its Edje's name. + + Edje references seats by a name that differs from Evas. + Edje naming follows a incrementional convention: first + registered name is "seat1", second is "seat2", differently + from Evas. + + @since 1.19]] + + return: Efl.Input.Device; [[The seat device or $null if not found.]] + } + keys { + name: stringshare; [[The name's character string.]] + } + } + @property seat_name { + get { + [[Get the name given to a set by Edje. + + Edje references seats by a name that differs from Evas. + Edje naming follows a incrementional convention: first + registered name is "seat1", second is "seat2", differently + from Evas. + + @since 1.19]] + + return: stringshare; [[The name's character string or $null if not found.]] + } + keys { + device: Efl.Input.Device; [[The seat device]] + } + } } implements { Efl.Gfx.visible.set; diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index 9a0fd21eb3..93b131cd09 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -805,6 +805,8 @@ struct _Edje_Program /* a conditional program to be run */ double range; } in; + const char *seat; /* which seat to focus, NULL = default seat */ + const char *state; /* what state of alternates to apply, NULL = default */ const char *state2; /* what other state to use - for signal emit action */ double value; /* value of state to apply (if multiple names match) */ @@ -1135,6 +1137,7 @@ struct _Edje_Part_Collection unsigned char broadcast_signal; unsigned char physics_enabled; /* will be 1 if a body is declared */ unsigned char script_recursion; /* permits unsafe Embryo->EDC->Embryo scripting */ + unsigned char use_custom_seat_names; unsigned char checked : 1; }; @@ -1659,7 +1662,7 @@ struct _Edje Edje_Var_Pool *var_pool; /* for faster lookups to avoid nth list walks */ Edje_Real_Part **table_parts; - Edje_Real_Part *focused_part; + Eina_List *seats; Eina_List *subobjs; Eina_List *text_insert_filter_callbacks; Eina_List *markup_filter_callbacks; @@ -1717,6 +1720,8 @@ struct _Edje unsigned short block; unsigned short state; + unsigned short seats_count; + unsigned char load_error; Eina_Bool is_rtl : 1; @@ -2273,6 +2278,14 @@ struct _Edje_Font char *file; }; +typedef struct _Edje_Seat Edje_Seat; +struct _Edje_Seat +{ + Edje_Real_Part *focused_part; + Efl_Input_Device *device; + Eina_Stringshare *name; +}; + Edje_Patterns *edje_match_collection_dir_init(const Eina_List *lst); Edje_Patterns *edje_match_programs_signal_init(Edje_Program * const *array, unsigned int count); @@ -2467,10 +2480,17 @@ void _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char void _edje_programs_patterns_clean(Edje_Part_Collection *ed); void _edje_programs_patterns_init(Edje_Part_Collection *ed); void _edje_emit(Edje *ed, const char *sig, const char *src); +void _edje_seat_emit(Edje *ed, Efl_Input_Device *dev, const char *sig, const char *src); void _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *)); void _edje_emit_handle(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop); void _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp); +void _edje_focused_part_set(Edje *ed, const char *seat_name, Edje_Real_Part *rp); +Edje_Real_Part *_edje_focused_part_get(Edje *ed, const char *seat_name); + +Eina_Stringshare *_edje_seat_name_get(Edje *ed, Efl_Input_Device *device); +Efl_Input_Device *_edje_seat_get(Edje *ed, Eina_Stringshare *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); void _edje_signal_callback_reset(Edje_Signal_Callback_Flags *flags, unsigned int length); diff --git a/src/lib/edje/edje_program.c b/src/lib/edje/edje_program.c index 3edaca98a9..a2df439e87 100644 --- a/src/lib/edje/edje_program.c +++ b/src/lib/edje/edje_program.c @@ -177,6 +177,18 @@ _edje_emit_send(Edje *ed, Eina_Bool broadcast, const char *sig, const char *src, * API * *============================================================================*/ +EOLIAN Eina_Stringshare* +_edje_object_seat_name_get(Eo *obj EINA_UNUSED, Edje *ed, Efl_Input_Device *device) +{ + return _edje_seat_name_get(ed, device); +} + +EOLIAN Efl_Input_Device * +_edje_object_seat_get(Eo *obj EINA_UNUSED, Edje *ed, Eina_Stringshare *name) +{ + return _edje_seat_get(ed, name); +} + EAPI void edje_frametime_set(double t) { @@ -615,6 +627,20 @@ _edje_physics_action_set(Edje *ed, Edje_Program *pr, void (*func)(EPhysics_Body #endif +static void +_edje_seat_name_emit(Edje *ed, const char *name, const char *sig, const char *src) +{ + char buf[128]; + + /* keep sending signals without seat information for legacy compatibility */ + _edje_emit_full(ed, sig, src, NULL, NULL); + + if (!name) return; + + snprintf(buf, sizeof(buf), "%s,%s", sig, name); + _edje_emit_full(ed, buf, src, NULL, NULL); +} + void _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, const char *ssrc) { @@ -943,12 +969,35 @@ low_mem_current: break; case EDJE_ACTION_TYPE_FOCUS_SET: + { + Edje_Real_Part *focused_part; + Eina_Stringshare *seat_name; + Eina_Bool unref_name = EINA_FALSE; + + if (pr->seat) + { + seat_name = eina_stringshare_add(pr->seat); + unref_name = EINA_TRUE; + } + else /* Use default seat name */ + { + Efl_Input_Device *seat; + Evas *e; + + e = evas_object_evas_get(ed->obj); + seat = evas_canvas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_SEAT); + seat_name = _edje_seat_name_get(ed, seat); + if (!seat_name) + break; + } + if (!pr->targets) { - if (ed->focused_part) - _edje_emit(ed, "focus,part,out", - ed->focused_part->part->name); - ed->focused_part = NULL; + focused_part = _edje_focused_part_get(ed, seat_name); + if (focused_part) + _edje_seat_name_emit(ed, seat_name, "focus,part,out", + focused_part->part->name); + _edje_focused_part_set(ed, seat_name, NULL); } else { @@ -959,27 +1008,53 @@ low_mem_current: rp = ed->table_parts[pt->id % ed->table_parts_size]; if (rp) { - if (ed->focused_part != rp) + focused_part = _edje_focused_part_get(ed, + seat_name); + if (focused_part != rp) { - if (ed->focused_part) - _edje_emit(ed, "focus,part,out", - ed->focused_part->part->name); - ed->focused_part = rp; - _edje_emit(ed, "focus,part,in", - ed->focused_part->part->name); + if (focused_part) + _edje_seat_name_emit(ed, seat_name, + "focus,part,out", + focused_part->part->name); + _edje_focused_part_set(ed, seat_name, rp); + _edje_seat_name_emit(ed, seat_name, + "focus,part,in", + rp->part->name); } } } } } - break; + + if (unref_name) + eina_stringshare_del(seat_name); + } + break; case EDJE_ACTION_TYPE_FOCUS_OBJECT: + { + Efl_Input_Device *seat = NULL; + + if (pr->seat) + { + Eina_Stringshare *seat_name; + + seat_name = eina_stringshare_add(pr->seat); + seat = _edje_seat_get(ed, seat_name); + eina_stringshare_del(seat_name); + } + if (!seat) + { + Evas *e; + + e = evas_object_evas_get(ed->obj); + seat = evas_canvas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_SEAT); + } if (!pr->targets) { Evas_Object *focused; - focused = evas_focus_get(evas_object_evas_get(ed->obj)); + focused = evas_seat_focus_get(evas_object_evas_get(ed->obj), seat); if (focused) { unsigned int i; @@ -993,7 +1068,7 @@ low_mem_current: (rp->typedata.swallow)) && (rp->typedata.swallow->swallowed_object == focused)) { - evas_object_focus_set(focused, EINA_FALSE); + evas_object_seat_focus_del(focused, seat); break; } } @@ -1010,11 +1085,13 @@ low_mem_current: ((rp->type == EDJE_RP_TYPE_SWALLOW) && (rp->typedata.swallow)) && (rp->typedata.swallow->swallowed_object)) - evas_object_focus_set(rp->typedata.swallow->swallowed_object, EINA_TRUE); + evas_object_seat_focus_add( + rp->typedata.swallow->swallowed_object, seat); } } } - break; + } + break; case EDJE_ACTION_TYPE_SOUND_SAMPLE: if (_edje_block_break(ed)) @@ -1209,6 +1286,26 @@ _edje_emit(Edje *ed, const char *sig, const char *src) _edje_emit_full(ed, sig, src, NULL, NULL); } +void +_edje_seat_emit(Edje *ed, Efl_Input_Device *dev, const char *sig, const char *src) +{ + Efl_Input_Device *seat; + char buf[128]; + + /* keep sending signals without seat information for legacy compatibility */ + _edje_emit_full(ed, sig, src, NULL, NULL); + + /* send extra signal with ",$SEAT" suffix if the input device originating + * the signal belongs to a seat */ + if (!dev) return; + + seat = efl_input_device_seat_get(dev); + if (!seat) return; + + snprintf(buf, sizeof(buf), "%s,%s", sig, _edje_seat_name_get(ed, seat)); + _edje_emit_full(ed, buf, src, NULL, NULL); +} + /* data should either be NULL or a malloc allocated data */ void _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *)) @@ -1247,6 +1344,77 @@ _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*f _edje_emit_send(ed, broadcast, sig, src, data, free_func); } +void +_edje_focused_part_set(Edje *ed, Eina_Stringshare *seat_name, Edje_Real_Part *rp) +{ + Edje_Seat *seat; + Eina_List *l; + + EINA_LIST_FOREACH(ed->seats, l, seat) + { + if (seat_name == seat->name) + { + seat->focused_part = rp; + return; + } + } + + /* A part to be set for a seat not yet announced by Evas */ + seat = calloc(1, sizeof(Edje_Seat)); + EINA_SAFETY_ON_NULL_RETURN(seat); + + seat->name = eina_stringshare_ref(seat_name); + seat->focused_part = rp; + ed->seats = eina_list_append(ed->seats, seat); + + return; +} + +Edje_Real_Part * +_edje_focused_part_get(Edje *ed, Eina_Stringshare *seat_name) +{ + Edje_Seat *seat; + Eina_List *l; + + EINA_LIST_FOREACH(ed->seats, l, seat) + { + if (seat_name == seat->name) + return seat->focused_part; + } + + return NULL; +} + +Eina_Stringshare* +_edje_seat_name_get(Edje *ed, Efl_Input_Device *device) +{ + Edje_Seat *seat; + Eina_List *l; + + EINA_LIST_FOREACH(ed->seats, l, seat) + { + if (seat->device == device) + return seat->name; + } + + return NULL; +} + +Efl_Input_Device * +_edje_seat_get(Edje *ed, Eina_Stringshare *name) +{ + Edje_Seat *seat; + Eina_List *l; + + EINA_LIST_FOREACH(ed->seats, l, seat) + { + if (seat->name == name) + return seat->device; + } + + return NULL; +} + struct _Edje_Program_Data { Eina_List *matches; diff --git a/src/lib/evas/Evas_Common.h b/src/lib/evas/Evas_Common.h index 2f54174121..8d2f85e006 100644 --- a/src/lib/evas/Evas_Common.h +++ b/src/lib/evas/Evas_Common.h @@ -1240,6 +1240,22 @@ EAPI void evas_device_pop(Evas *e); EAPI const Eina_List *evas_device_list(Evas *e, const Evas_Device *dev); /** + * Get a device by its name + * + * @param e The canvas to create the device node for. + * @param name The name of the device. + * + * Gets the first ocurrence of a device named as @p name + * on Evas @p e list of devices. + * + * @return the device or NULL if an error occurred, no name was provided, + * or no device with a matching name was found. + * + * @since 1.19 + */ +EAPI Evas_Device *evas_device_get(Evas *e, const char *name); + +/** * Set the name of a device as a string * * @p dev The device to set the name of diff --git a/src/lib/evas/canvas/evas_device.c b/src/lib/evas/canvas/evas_device.c index 4ab6d1532a..9a65d792fd 100644 --- a/src/lib/evas/canvas/evas_device.c +++ b/src/lib/evas/canvas/evas_device.c @@ -95,6 +95,32 @@ _del_cb(void *data, const Efl_Event *ev) } EAPI Evas_Device * +evas_device_get(Evas *eo_e, const char *name) +{ + const char *dev_name; + Evas_Public_Data *e; + Evas_Device *dev; + Eina_List *l; + + SAFETY_CHECK(eo_e, EVAS_CANVAS_CLASS, NULL); + + if (!name) + return NULL; + + e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS); + + EINA_LIST_FOREACH(e->devices, l, dev) + { + dev_name = efl_input_device_name_get(dev); + + if (eina_streq(dev_name, name)) + return dev; + } + + return NULL; +} + +EAPI Evas_Device * evas_device_add(Evas *eo_e) { return evas_device_add_full(eo_e, NULL, NULL, NULL, NULL, |