Merge branch 'devs/bdilly/edje_multiseat_filter'

This series add support to filter events per seat
on edje parts.
With the flag allowed_seats the developer may choose which
seats are allowed to input each part.

Also it adds functions to embryo to set/unset focus, since
it's relevant when writting multiseat applications with
dynamic seats (not fixed number of seats). Seats are
optional arguments on such functions.

Reviewed By: iscaro

Differential Revision: https://phab.enlightenment.org/D4499

@feature
This commit is contained in:
Bruno Dilly 2016-12-21 23:04:48 -02:00
commit 8a42514d71
12 changed files with 1244 additions and 48 deletions

View File

@ -141,6 +141,12 @@ native set_mask_flags (part_id, flags);
native get_mask_flags (part_id);
native part_swallow (part_id, GROUP:str[]);
/* set_focus() and unset_focus() may receive an optional parameter
seat_name[], as set_focus(part_id, seat_name[]) and
unset_focus(seat_name[]) */
native set_focus (part_id, ...);
native unset_focus (...);
native external_param_get_int(id, param_name[]);
native external_param_set_int(id, param_name[], value);
native Float:external_param_get_float(id, param_name[]);

View File

@ -313,6 +313,7 @@ static void st_collections_group_parts_part_dragable_y(void);
static void st_collections_group_parts_part_dragable_confine(void);
static void st_collections_group_parts_part_dragable_threshold(void);
static void st_collections_group_parts_part_dragable_events(void);
static void st_collections_group_parts_part_allowed_seats(void);
/* box and table items share these */
static void ob_collections_group_parts_part_box_items_item(void);
@ -789,6 +790,7 @@ New_Statement_Handler statement_handlers[] =
{"collections.group.parts.part.cursor_mode", st_collections_group_parts_part_cursor_mode},
{"collections.group.parts.part.multiline", st_collections_group_parts_part_multiline},
{"collections.group.parts.part.access", st_collections_group_parts_part_access},
{"collections.group.parts.part.allowed_seats", st_collections_group_parts_part_allowed_seats},
IMAGE_SET_STATEMENTS("collections.group.parts.part")
IMAGE_STATEMENTS("collections.group.parts.part.")
{"collections.group.parts.part.font", st_fonts_font}, /* dup */
@ -4418,6 +4420,36 @@ _part_copy(Edje_Part *ep, Edje_Part *ep2)
ep->dragable.count_y = ep2->dragable.count_y;
ep->nested_children_count = ep2->nested_children_count;
if (ep2->allowed_seats)
{
Edje_Part_Allowed_Seat *seat;
unsigned int s;
ep->allowed_seats_count = ep2->allowed_seats_count;
ep->allowed_seats = calloc(ep2->allowed_seats_count,
sizeof(Edje_Part_Allowed_Seat *));
if (!ep->allowed_seats)
{
ERR("Not enough memory.");
exit(-1);
}
for (s = 0; s < ep->allowed_seats_count; s++)
{
seat = mem_alloc(SZ(Edje_Part_Allowed_Seat));
if (ep2->allowed_seats[s]->name)
{
seat->name = strdup(ep2->allowed_seats[s]->name);
if (!seat->name)
{
ERR("Not enough memory.");
exit(-1);
}
}
ep->allowed_seats[s] = seat;
}
}
data_queue_copied_part_lookup(pc, &(ep2->dragable.confine_id), &(ep->dragable.confine_id));
data_queue_copied_part_lookup(pc, &(ep2->dragable.threshold_id), &(ep->dragable.threshold_id));
data_queue_copied_part_lookup(pc, &(ep2->dragable.event_id), &(ep->dragable.event_id));
@ -5827,6 +5859,9 @@ edje_cc_handlers_part_make(int id)
ep->items = NULL;
ep->nested_children_count = 0;
ep->allowed_seats = NULL;
ep->allowed_seats_count = 0;
epp = (Edje_Part_Parser *)ep;
epp->reorder.insert_before = NULL;
epp->reorder.insert_after = NULL;
@ -6022,6 +6057,13 @@ _part_free(Edje_Part_Collection *pc, Edje_Part *ep)
free(ep->items[j]);
free(ep->items);
for (j = 0 ; j < ep->allowed_seats_count; j++)
{
free((void*)(ep->allowed_seats[j]->name));
free(ep->allowed_seats[j]);
}
free(ep->allowed_seats);
free((void*)ep->name);
free((void*)ep->source);
free((void*)ep->source2);
@ -7398,6 +7440,53 @@ st_collections_group_parts_part_dragable_events(void)
}
}
/**
@page edcref
@property
allowed_seats
@parameters
[seat1] [seat2] [seat3] ...
@effect
List of seat names allowed to interact with the part.
If no list is defined all seats are allowed. It's the
default behaviour.
If a seat isn't allowed, no signals will be emitted
related to its actions, as mouse and focus events.
Also it won't be able to focus this part.
@since 1.19
@endproperty
*/
static void
st_collections_group_parts_part_allowed_seats(void)
{
Edje_Part_Allowed_Seat *seat;
Edje_Part *ep;
int n, argc;
check_min_arg_count(1);
ep = current_part;
argc = get_arg_count();
ep->allowed_seats = calloc(argc, sizeof(Edje_Part_Allowed_Seat *));
if (!ep->allowed_seats)
{
ERR("Not enough memory.");
exit(-1);
}
for (n = 0; n < argc; n++)
{
seat = mem_alloc(SZ(Edje_Part_Allowed_Seat));
seat->name = parse_str(n);
ep->allowed_seats[n] = seat;
}
ep->allowed_seats_count = argc;
}
/** @edcsubsection{collections_group_parts_items,
* Group.Parts.Part.Box/Table.Items} */

View File

@ -15,6 +15,7 @@
/edje-focus
/edje-multiseat
/edje-multiseat-custom-names
/edje-multiseat-filter
/edje-multisense
/edje-perspective
/edje-signals-messages

View File

@ -47,6 +47,7 @@ lua_script.edc \
messages_echo.edc \
multiseat.edc \
multiseat_custom_names.edc \
multiseat_filter.edc \
perspective.edc \
signals-messages.edc \
signalsBubble.edc \
@ -148,6 +149,7 @@ edje-entry.c \
edje-focus.c \
edje-multiseat.c \
edje-multiseat-custom-names.c \
edje-multiseat-filter.c \
edje-multisense.c \
edje-perspective.c \
edje-signals-messages.c \
@ -225,6 +227,7 @@ edje-entry \
edje-focus \
edje-multiseat \
edje-multiseat-custom-names \
edje-multiseat-filter \
edje-perspective \
edje-signals-messages \
edje-swallow \

View File

@ -0,0 +1,130 @@
/**
* Edje example demonstrating how to use multiseat filtering.
*
* It presents 4 widgets that can be controlled by:
* * seat1 only
* * seat2 only
* * seat1 + seat2
* * any seat
*
* 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_filter.edc && gcc -o edje-multiseat-filter edje-multiseat-filter.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_filter.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
_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;
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 Multiseat Filter 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)
efl_canvas_object_seat_focus_add(edje_obj, dev);
}
efl_event_callback_add(evas, EFL_CANVAS_EVENT_DEVICE_ADDED,
_device_added, edje_obj);
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,811 @@
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 Filter Example";
size: 16;
font: "sans";
min: 1 1;
}
}
}
// focus_bt is important to test if focus action are
// respecting allowed seats list
part {
name: "focus_bt";
type: RECT;
mouse_events: 1;
description {
state: "default" 0.0;
rel1.relative: 0.3 0.2;
rel2.relative: 0.7 0.25;
color: 192 50 50 255;
}
description {
state: "over" 0.0;
inherit: "default" 0.0;
color: 142 30 30 255;
}
description {
state: "pressed" 0.0;
inherit: "default" 0.0;
color: 220 70 70 255;
}
}
part {
name: "focus_bt,label";
type: TEXT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 92 0 0 255;
rel1 {
relative: 0.5 0.5;
to: "focus_bt";
}
rel2 {
relative: 0.5 0.5;
to: "focus_bt";
}
text {
text: "Focus 'Seat 1 Only' Entry";
size: 11;
font: "sans";
min: 1 1;
}
}
}
part {
name: "widget1";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
rel1.relative: 0.0 0.3;
rel2.relative: 0.5 0.65;
color: 255 255 0 255;
}
}
part {
name: "widget2";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
rel1.relative: 0.0 0.65;
rel2.relative: 0.5 1.0;
color: 255 0 255 255;
}
}
part {
name: "widget3";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
rel1.relative: 0.5 0.3;
rel2.relative: 1.0 0.65;
color: 0 255 255 255;
}
}
part {
name: "widget4";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
rel1.relative: 0.5 0.65;
rel2.relative: 1.0 1.0;
color: 130 255 130 255;
}
}
part {
name: "widget1,title";
type: TEXT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 0 0 0 255;
rel1 {
relative: 0.0 0.02;
offset: 0 0;
to: "widget1";
}
rel2 {
relative: 1.0 0.1;
offset: -1 -1;
to: "widget1";
}
text {
text: "Seat1 Only";
size: 10;
font: "sans";
min: 1 1;
}
}
}
part {
name: "widget1,drag_area";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 20 20 20 255;
rel1 {
relative: 0.1 0.2;
offset: -5 0;
to: "widget1";
}
rel2 {
relative: 0.1 0.8;
offset: 4 0;
to: "widget1";
}
}
}
part {
name: "widget,knob,1";
type: RECT;
mouse_events: 1;
allowed_seats: "seat1";
dragable {
confine: "widget1,drag_area";
x: 0 0 0;
y: 1 1 0;
}
description {
state: "default" 0.0;
min: 10 30;
color: 120 120 120 255;
}
description {
state: "focused" 0.0;
inherit: "default" 0.0;
color: 200 200 200 255;
}
}
part {
name: "widget,bg_text,1";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
min: 10 50;
rel1 {
to: "widget1";
relative: 0.25 0.2;
}
rel2 {
to: "widget1";
relative: 0.85 0.8;
}
color: 120 120 120 255;
}
description {
state: "focused" 0.0;
inherit: "default" 0.0;
color: 200 200 200 255;
}
}
part {
name: "widget,text,1";
type: TEXTBLOCK;
scale: 1;
entry_mode: EDITABLE;
select_mode: DEFAULT;
cursor_mode: UNDER;
mouse_events: 1;
allowed_seats: "seat1";
multiline: 1;
source: "example/selection";
source4: "example/cursor";
description {
state: "default" 0.0;
min: 12 50;
rel1 {
to: "widget,bg_text,1";
offset: 2 2;
}
rel2 {
to: "widget,bg_text,1";
offset: -3 -3;
}
text {
style: "entry_style";
min: 0 1;
align: 0.0 0.0;
}
}
}
part {
name: "widget2,title";
type: TEXT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 0 0 0 255;
rel1 {
relative: 0.0 0.02;
offset: 0 0;
to: "widget2";
}
rel2 {
relative: 1.0 0.1;
offset: -1 -1;
to: "widget2";
}
text {
text: "Seat2 Only";
size: 10;
font: "sans";
min: 1 1;
}
}
}
part {
name: "widget2,drag_area";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 20 20 20 255;
rel1 {
relative: 0.1 0.2;
offset: -5 0;
to: "widget2";
}
rel2 {
relative: 0.1 0.8;
offset: 4 0;
to: "widget2";
}
}
}
part {
name: "widget,knob,2";
type: RECT;
mouse_events: 1;
allowed_seats: "seat2";
dragable {
confine: "widget2,drag_area";
x: 0 0 0;
y: 1 1 0;
}
description {
state: "default" 0.0;
min: 10 30;
color: 120 120 120 255;
}
description {
state: "focused" 0.0;
inherit: "default" 0.0;
color: 200 200 200 255;
}
}
part {
name: "widget,bg_text,2";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
min: 10 50;
rel1 {
to: "widget2";
relative: 0.25 0.2;
}
rel2 {
to: "widget2";
relative: 0.85 0.8;
}
color: 120 120 120 255;
}
description {
state: "focused" 0.0;
inherit: "default" 0.0;
color: 200 200 200 255;
}
}
part {
name: "widget,text,2";
type: TEXTBLOCK;
scale: 1;
entry_mode: EDITABLE;
select_mode: DEFAULT;
cursor_mode: UNDER;
mouse_events: 1;
allowed_seats: "seat2";
multiline: 1;
source: "example/selection";
source4: "example/cursor";
description {
state: "default" 0.0;
min: 12 50;
rel1 {
to: "widget,bg_text,2";
offset: 2 2;
}
rel2 {
to: "widget,bg_text,2";
offset: -3 -3;
}
text {
style: "entry_style";
min: 0 1;
align: 0.0 0.0;
}
}
}
part {
name: "widget3,title";
type: TEXT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 0 0 0 255;
rel1 {
relative: 0.0 0.02;
offset: 0 0;
to: "widget3";
}
rel2 {
relative: 1.0 0.1;
offset: -1 -1;
to: "widget3";
}
text {
text: "Seat 1 + Seat2";
size: 10;
font: "sans";
min: 1 1;
}
}
}
part {
name: "widget3,drag_area";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 20 20 20 255;
rel1 {
relative: 0.1 0.2;
offset: -5 0;
to: "widget3";
}
rel2 {
relative: 0.1 0.8;
offset: 4 0;
to: "widget3";
}
}
}
part {
name: "widget,knob,3";
type: RECT;
mouse_events: 1;
allowed_seats: "seat1" "seat2";
dragable {
confine: "widget3,drag_area";
x: 0 0 0;
y: 1 1 0;
}
description {
state: "default" 0.0;
min: 10 30;
color: 120 120 120 255;
}
description {
state: "focused" 0.0;
inherit: "default" 0.0;
color: 200 200 200 255;
}
}
part {
name: "widget,bg_text,3";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
min: 10 50;
rel1 {
to: "widget3";
relative: 0.25 0.2;
}
rel2 {
to: "widget3";
relative: 0.85 0.8;
}
color: 120 120 120 255;
}
description {
state: "focused" 0.0;
inherit: "default" 0.0;
color: 200 200 200 255;
}
}
part {
name: "widget,text,3";
type: TEXTBLOCK;
scale: 1;
entry_mode: EDITABLE;
select_mode: DEFAULT;
cursor_mode: UNDER;
mouse_events: 1;
allowed_seats: "seat1" "seat2";
multiline: 1;
source: "example/selection";
source4: "example/cursor";
description {
state: "default" 0.0;
min: 12 50;
rel1 {
to: "widget,bg_text,3";
offset: 2 2;
}
rel2 {
to: "widget,bg_text,3";
offset: -3 -3;
}
text {
style: "entry_style";
min: 0 1;
align: 0.0 0.0;
}
}
}
part {
name: "widget4,title";
type: TEXT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 0 0 0 255;
rel1 {
relative: 0.0 0.02;
offset: 0 0;
to: "widget4";
}
rel2 {
relative: 1.0 0.1;
offset: -1 -1;
to: "widget4";
}
text {
text: "Any seat";
size: 10;
font: "sans";
min: 1 1;
}
}
}
part {
name: "widget4,drag_area";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
color: 20 20 20 255;
rel1 {
relative: 0.1 0.2;
offset: -5 0;
to: "widget4";
}
rel2 {
relative: 0.1 0.8;
offset: 4 0;
to: "widget4";
}
}
}
part {
name: "widget,knob,4";
type: RECT;
mouse_events: 1;
dragable {
confine: "widget4,drag_area";
x: 0 0 0;
y: 1 1 0;
}
description {
state: "default" 0.0;
min: 10 30;
color: 120 120 120 255;
}
description {
state: "focused" 0.0;
inherit: "default" 0.0;
color: 200 200 200 255;
}
}
part {
name: "widget,bg_text,4";
type: RECT;
mouse_events: 0;
description {
state: "default" 0.0;
min: 10 50;
rel1 {
to: "widget4";
relative: 0.25 0.2;
}
rel2 {
to: "widget4";
relative: 0.85 0.8;
}
color: 120 120 120 255;
}
description {
state: "focused" 0.0;
inherit: "default" 0.0;
color: 200 200 200 255;
}
}
part {
name: "widget,text,4";
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: "widget,bg_text,4";
offset: 2 2;
}
rel2 {
to: "widget,bg_text,4";
offset: -3 -3;
}
text {
style: "entry_style";
min: 0 1;
align: 0.0 0.0;
}
}
}
}
programs {
program {
name: "clicked";
signal: "mouse,clicked,1,*";
source: "widget,text,*";
script {
new partid;
partid = get_part_id(src);
set_focus(partid, sig[strlen("mouse,clicked,1,")]);
}
}
program {
name: "focused";
signal: "focus,part,in,*";
source: "widget,text,*";
script {
new buf[256];
new partid;
snprintf(buf, 128, "widget,bg_text,%s",
src[strlen("widget,text,")]);
partid = get_part_id(buf);
set_state(partid, "focused", 0.0);
}
}
program {
name: "unfocused";
signal: "focus,part,out,*";
source: "widget,text,*";
script {
new buf[256];
new partid;
snprintf(buf, 128, "widget,bg_text,%s",
src[strlen("widget,text,")]);
partid = get_part_id(buf);
set_state(partid, "default", 0.0);
}
}
program {
name: "drag,start";
signal: "drag,start,*";
source: "widget,knob,*";
script {
new partid;
partid = get_part_id(src);
set_state(partid, "focused", 0.0);
}
}
program {
name: "drag,stop";
signal: "drag,stop,*";
source: "widget,knob,*";
script {
new partid;
partid = get_part_id(src);
set_state(partid, "default", 0.0);
}
}
program {
name: "focus_bt,in";
signal: "mouse,in";
source: "focus_bt";
action: STATE_SET "over" 0.0;
target: "focus_bt";
}
program {
name: "focus_bt,out";
signal: "mouse,out";
source: "focus_bt";
action: STATE_SET "default" 0.0;
target: "focus_bt";
}
program {
name: "focus_bt,down";
signal: "mouse,down,1";
source: "focus_bt";
action: STATE_SET "pressed" 0.0;
target: "focus_bt";
}
program {
name: "focus_bt,up";
signal: "mouse,up,1";
source: "focus_bt";
action: STATE_SET "default" 0.0;
target: "focus_bt";
}
program {
name: "focus_bt,clicked";
signal: "mouse,clicked,1,*";
source: "focus_bt";
script {
set_focus(PART:"widget,text,1",
sig[strlen("mouse,clicked,1,")]);
}
}
}
}
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

@ -37,6 +37,8 @@ Eet_Data_Descriptor *_edje_edd_edje_pack_element = NULL;
Eet_Data_Descriptor *_edje_edd_edje_pack_element_pointer = NULL;
Eet_Data_Descriptor *_edje_edd_edje_part = NULL;
Eet_Data_Descriptor *_edje_edd_edje_part_pointer = NULL;
Eet_Data_Descriptor *_edje_edd_edje_part_allowed_seat = NULL;
Eet_Data_Descriptor *_edje_edd_edje_part_allowed_seat_pointer = NULL;
Eet_Data_Descriptor *_edje_edd_edje_part_description_variant = NULL;
Eet_Data_Descriptor *_edje_edd_edje_part_description_rectangle = NULL;
Eet_Data_Descriptor *_edje_edd_edje_part_description_snapshot = NULL;
@ -690,6 +692,8 @@ _edje_edd_shutdown(void)
FREED(_edje_edd_edje_pack_element_pointer);
FREED(_edje_edd_edje_part);
FREED(_edje_edd_edje_part_pointer);
FREED(_edje_edd_edje_part_allowed_seat);
FREED(_edje_edd_edje_part_allowed_seat_pointer);
FREED(_edje_edd_edje_part_description_variant);
FREED(_edje_edd_edje_part_description_rectangle);
FREED(_edje_edd_edje_part_description_snapshot);
@ -946,6 +950,11 @@ _edje_edd_init(void)
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_style_tag, Edje_Style_Tag, "key", key, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_style_tag, Edje_Style_Tag, "value", value, EET_T_STRING);
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Allowed_Seat);
_edje_edd_edje_part_allowed_seat =
eet_data_descriptor_file_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_allowed_seat, Edje_Part_Allowed_Seat, "name", name, EET_T_STRING);
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Style);
_edje_edd_edje_style =
eet_data_descriptor_file_new(&eddc);
@ -1766,6 +1775,10 @@ _edje_edd_init(void)
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "nested_children_count", nested_children_count, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "required", required, EET_T_UCHAR);
EDJE_DEFINE_POINTER_TYPE(Part_Allowed_Seat, part_allowed_seat);
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_part, Edje_Part, "allowed_seats", allowed_seats, _edje_edd_edje_part_allowed_seat_pointer);
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Limit);
_edje_edd_edje_part_limit = eet_data_descriptor_file_new(&eddc);

View File

@ -15248,6 +15248,19 @@ _edje_generate_source_of_part(Evas_Object *obj, Edje_Part *ep, Eina_Strbuf *buf)
BUF_APPEND(I4 "precise_is_inside: 1;\n");
if (rp->part->access)
BUF_APPEND(I4 "access: 1;\n");
if (rp->part->allowed_seats)
{
Edje_Part_Allowed_Seat *seat;
unsigned int i;
BUF_APPEND(I4 "allowed_seats:");
for (i = 0; i < rp->part->allowed_seats_count; i++)
{
seat = rp->part->allowed_seats[i];
BUF_APPENDF(" %s", seat->name);
}
BUF_APPEND(";\n");
}
if ((str = _edje_part_clip_to_get(ed, rp)))
{

View File

@ -193,8 +193,9 @@
* get_ignore_flags(part_id)
* set_mask_flags(part_id, flags)
* get_mask_flags(part_id)
* set_clip(part_id, clip_part_id)
* get_clip(part_id)
*
* set_focus(part_id, seat_name[])
* unset_focus(seat_name[])
*
* part_swallow(part_id, group_name)
*
@ -3771,6 +3772,59 @@ _edje_embryo_fn_part_swallow(Embryo_Program *ep, Embryo_Cell *params)
return 0;
}
/* set_focus(part_id, seat_name[]) */
static Embryo_Cell
_edje_embryo_fn_set_focus(Embryo_Program *ep, Embryo_Cell *params)
{
Edje *ed;
int part_id;
Edje_Real_Part *rp;
char *seat_name = NULL;
if (!(HASNPARAMS(1) || HASNPARAMS(2))) return -1;
ed = embryo_program_data_get(ep);
part_id = params[1];
if (part_id < 0) return 0;
rp = ed->table_parts[part_id % ed->table_parts_size];
if (!rp) return 0;
/* if no seat name is passed, that's fine. it means
it should be applied to default seat */
if (HASNPARAMS(2))
{
GETSTR(seat_name, params[2]);
if (!seat_name) return 0;
}
_edje_part_focus_set(ed, seat_name, rp);
return 0;
}
/* unset_focus(seat_name[]) */
static Embryo_Cell
_edje_embryo_fn_unset_focus(Embryo_Program *ep, Embryo_Cell *params)
{
Edje *ed;
char *seat_name = NULL;
if (!(HASNPARAMS(0) || HASNPARAMS(1))) return -1;
ed = embryo_program_data_get(ep);
/* seat name is optional. no seat means
it should be applied to default seat */
if (HASNPARAMS(1))
{
GETSTR(seat_name, params[1]);
if (!seat_name) return 0;
}
_edje_part_focus_set(ed, seat_name, NULL);
return 0;
}
/* external_param_get_int(id, param_name[]) */
static Embryo_Cell
_edje_embryo_fn_external_param_get_int(Embryo_Program *ep, Embryo_Cell *params)
@ -4510,6 +4564,9 @@ _edje_embryo_script_init(Edje_Part_Collection *edc)
embryo_program_native_call_add(ep, "set_mask_flags", _edje_embryo_fn_set_mask_flags);
embryo_program_native_call_add(ep, "get_mask_flags", _edje_embryo_fn_get_mask_flags);
embryo_program_native_call_add(ep, "set_focus", _edje_embryo_fn_set_focus);
embryo_program_native_call_add(ep, "unset_focus", _edje_embryo_fn_unset_focus);
embryo_program_native_call_add(ep, "part_swallow", _edje_embryo_fn_part_swallow);
embryo_program_native_call_add(ep, "external_param_get_int", _edje_embryo_fn_external_param_get_int);

View File

@ -507,6 +507,60 @@ _edje_physics_world_update_cb(void *data, EPhysics_World *world EINA_UNUSED, voi
}
#endif
Eina_Bool
_edje_part_allowed_seat_find(Edje_Real_Part *rp, const char *seat_name)
{
const char *name;
unsigned int i;
for (i = 0; i < rp->part->allowed_seats_count; i++)
{
name = rp->part->allowed_seats[i]->name;
if (!strcmp(seat_name, name))
return EINA_TRUE;
}
return EINA_FALSE;
}
/* It goes throught the list of registered seats and
* set event filters for each of these seats. */
static void
_edje_part_seat_filter_apply(Edje *ed, Edje_Real_Part *rp)
{
Edje_Seat *seat;
Eina_List *l;
Eina_Bool found;
EINA_LIST_FOREACH(ed->seats, l, seat)
{
found = _edje_part_allowed_seat_find(rp, seat->name);
efl_input_seat_event_filter_set(rp->object, seat->device, found);
}
}
/* It goes throught the list of all edje parts and
* set event filters for each of these parts. Should be called when
* a new seat is added.
*/
static void
_edje_seat_event_filter_apply(Edje *ed, Edje_Seat *seat)
{
Edje_Real_Part *rp;
unsigned short i;
Eina_Bool found;
for (i = 0; i < ed->table_parts_size; i++)
{
rp = ed->table_parts[i];
if (!rp->part->allowed_seats)
continue;
found = _edje_part_allowed_seat_find(rp, seat->name);
efl_input_seat_event_filter_set(rp->object, seat->device, found);
}
}
static void
_edje_device_add(Edje *ed, Efl_Input_Device *dev)
{
@ -544,6 +598,7 @@ _edje_device_add(Edje *ed, Efl_Input_Device *dev)
snprintf(sig, sizeof(sig), "seat,added,%s,%s", seat->name,
efl_input_device_name_get(dev));
_edje_emit(ed, sig, "");
_edje_seat_event_filter_apply(ed, seat);
seat_err:
eina_stringshare_del(name);
@ -645,6 +700,8 @@ _edje_device_changed_cb(void *data, const Efl_Event *event)
eina_stringshare_del(seat->name);
free(seat);
_edje_seat_event_filter_apply(ed, s);
return;
}
}
@ -652,6 +709,7 @@ _edje_device_changed_cb(void *data, const Efl_Event *event)
snprintf(sig, sizeof(sig), "seat,renamed,%s,%s", seat->name, name);
eina_stringshare_replace(&seat->name, name);
_edje_emit(ed, sig, "");
_edje_seat_event_filter_apply(ed, seat);
}
static void
@ -1093,6 +1151,9 @@ _edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const ch
nested_smart = NULL;
}
if (ep->allowed_seats)
_edje_part_seat_filter_apply(ed, rp);
if (ep->no_render)
efl_canvas_object_no_render_set(rp->object, 1);
@ -2228,6 +2289,14 @@ _edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec, Edje_Part_Collec
for (j = 0; j < ep->items_count; ++j)
free(ep->items[j]);
free(ep->items);
for (j = 0; j < ep->allowed_seats_count; ++j)
{
if (edf->free_strings)
eina_stringshare_del(ep->allowed_seats[j]->name);
free(ep->allowed_seats[j]);
}
free(ep->allowed_seats);
// technically need this - but we ASSUME we use "one_big" so everything gets
// freed in one go lower down when we del the mempool... but what if pool goes
// "over"?

View File

@ -377,6 +377,7 @@ typedef struct _Edje_Part_Box_Animation Edje_Part_Box_Animation;
typedef struct _Edje_Part_Limit Edje_Part_Limit;
typedef struct _Edje_Part_Description_Vector Edje_Part_Description_Vector;
typedef struct _Edje_Part_Description_Spec_Svg Edje_Part_Description_Spec_Svg;
typedef struct _Edje_Part_Allowed_Seat Edje_Part_Allowed_Seat;
typedef struct _Edje_Real_Part_Vector Edje_Real_Part_Vector;
typedef struct _Edje_Vector_Data Edje_Vector_Data;
@ -1195,6 +1196,8 @@ struct _Edje_Part
unsigned int items_count;
Edje_3D_Vec scale_3d;
Edje_Part_Api api;
Edje_Part_Allowed_Seat **allowed_seats;
unsigned int allowed_seats_count;
unsigned char type; /* what type (image, rect, text) */
#ifdef HAVE_EPHYSICS
unsigned char physics_body; /* body (none, rigid box, soft circle, ...) */
@ -1628,6 +1631,12 @@ struct _Edje_Part_Description_Vector
Edje_Part_Description_Spec_Svg vg;
};
struct _Edje_Part_Allowed_Seat
{
const char *name;
};
/*----------*/
struct _Edje_Signal_Source_Char
@ -2491,9 +2500,11 @@ 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);
void _edje_part_focus_set(Edje *ed, const char *seat_name, Edje_Real_Part *rp);
Eina_Stringshare *_edje_seat_name_get(Edje *ed, Efl_Input_Device *device);
Efl_Input_Device *_edje_seat_get(Edje *ed, Eina_Stringshare *name);
Eina_Bool _edje_part_allowed_seat_find(Edje_Real_Part *rp, const char *seat_name);
const Edje_Signals_Sources_Patterns *_edje_signal_callback_patterns_ref(const Edje_Signal_Callback_Group *gp);
void _edje_signal_callback_patterns_unref(const Edje_Signals_Sources_Patterns *essp);

View File

@ -641,6 +641,43 @@ _edje_seat_name_emit(Edje *ed, const char *name, const char *sig, const char *sr
_edje_emit_full(ed, buf, src, NULL, NULL);
}
void
_edje_part_focus_set(Edje *ed, const char *seat_name, Edje_Real_Part *rp)
{
Edje_Real_Part *focused_part;
Eina_Stringshare *sname;
Efl_Input_Device *seat;
Evas *e;
if (seat_name)
sname = eina_stringshare_add(seat_name);
else /* Use default seat name */
{
e = evas_object_evas_get(ed->obj);
seat = evas_canvas_default_device_get(e, EFL_INPUT_DEVICE_CLASS_SEAT);
sname = eina_stringshare_ref(_edje_seat_name_get(ed, seat));
}
focused_part = _edje_focused_part_get(ed, sname);
if (focused_part != rp)
{
if ((rp->part->allowed_seats) &&
(!_edje_part_allowed_seat_find(rp, sname)))
goto not_allowed;
if (focused_part)
_edje_seat_name_emit(ed, sname, "focus,part,out",
focused_part->part->name);
_edje_focused_part_set(ed, sname, rp);
if (rp)
_edje_seat_name_emit(ed, sname, "focus,part,in", rp->part->name);
}
not_allowed:
eina_stringshare_del(sname);
}
void
_edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, const char *ssrc)
{
@ -970,35 +1007,8 @@ low_mem_current:
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)
{
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);
}
_edje_part_focus_set(ed, pr->seat, NULL);
else
{
EINA_LIST_FOREACH(pr->targets, l, pt)
@ -1007,27 +1017,10 @@ low_mem_current:
{
rp = ed->table_parts[pt->id % ed->table_parts_size];
if (rp)
{
focused_part = _edje_focused_part_get(ed,
seat_name);
if (focused_part != rp)
{
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);
}
}
_edje_part_focus_set(ed, pr->seat, rp);
}
}
}
if (unref_name)
eina_stringshare_del(seat_name);
}
break;