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
This commit is contained in:
Bruno Dilly 2016-12-19 15:19:06 -02:00
commit 6f9deb976a
22 changed files with 3032 additions and 91 deletions

View File

@ -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;
@ -4513,6 +4516,43 @@ st_collections_group_inherit_only(void)
pcp->inherit_only = parse_bool(0);
}
/**
@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
@ -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);
}

View File

@ -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

View File

@ -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 \

View File

@ -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);
}
}
}
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

330
src/examples/edje/focus.edc Normal file
View File

@ -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";
}
}
}
}

View File

@ -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";
}
}
}
}

View File

@ -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";
}
}
}
}

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -1239,6 +1239,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
*

View File

@ -94,6 +94,32 @@ _del_cb(void *data, const Efl_Event *ev)
ev->object);
}
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)
{