bluez5 - add device specific options like unlock and force connect

i added 2 more device specific options, so i had to move all of the
device controls to an expandable button set. it's not brilliant
actually. the icons are poor and these probably should become toggle
like states rather than a button with an action. it's just not that
intuitive. this i think needs more theme styles in elm core theme
though, so for now keep what's there. but this was necessary due to
the ever expanding set to keep space usage sane.

now the 2 features are "force connect" for any device that is
discovered and responds to pings - connect to it if not connected.
this seems to not always work and maybe this should eventually be
removed, but this leads to there needing to be config per device so we
now have config storage for that like adapters.

the other feature which is much more interesting is the unlock
feature. this means if that bt device is around and responds to pings,
e will unlock (and only explicit manual locking will lock it), but
when that bt device stops responding to pings, e will lock. you could
use your phone, or smartwatch or any other bt device you have on your
all the time as some unlock device.

this required the fixing of the l2ping support in e_sys and i've fixed
it to properly work now and added an optional timeout value as input.
the unlock feature uses this and it pings bt devices on a frequency
that depends on e's powersave state which is dependent on if on ac, or
battery and what battery level is if you have the battery module
running. a handy feature to have just there at the click of a button.

i've kept the printf logging in for now so people trying it out get
some semblance of logging and state so they could figure out why
things are doing what they do and maybe debug it more easily.
This commit is contained in:
Carsten Haitzler 2018-12-15 16:03:41 +00:00
parent cbe3858b15
commit 7d39369434
5 changed files with 608 additions and 70 deletions

View File

@ -19,6 +19,10 @@ struct _Obj {
unsigned int ref;
Eina_Bool in_table : 1;
Eina_Bool add_called : 1;
Eina_Bool ping_ok : 1;
Ecore_Timer *ping_timer;
Ecore_Exe *ping_exe;
Ecore_Event_Handler *ping_exe_handler;
//// public data to read
const char *path;
Obj_Type type;
@ -196,9 +200,11 @@ void bz_obj_pair(Obj *o);
void bz_obj_pair_cancel(Obj *o);
void bz_obj_connect(Obj *o);
void bz_obj_disconnect(Obj *o);
void bz_obj_ping_begin(Obj *o);
void bz_obj_ping_end(Obj *o);
void bz_obj_remove(Obj *o);
void bz_obj_profile_connect(Obj *o, const char *uuid);
void bz_obj_profile_disconnect(Obj *o, const char *uuid);
//void bz_obj_profile_connect(Obj *o, const char *uuid);
//void bz_obj_profile_disconnect(Obj *o, const char *uuid);
void bz_obj_ref(Obj *o);
void bz_obj_unref(Obj *o);
void bz_obj_discover_start(Obj *o);

View File

@ -286,6 +286,12 @@ cb_obj_prop_changed(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSE
eldbus_proxy_property_get_all(o->proxy, cb_obj_prop, o);
}
static void
cb_obj_discovery_filter(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Discovery Filter Clear");
}
Obj *
bz_obj_add(const char *path)
{
@ -339,6 +345,9 @@ bz_obj_add(const char *path)
o->prop_sig = eldbus_proxy_signal_handler_add(o->prop_proxy,
"PropertiesChanged",
cb_obj_prop_changed, o);
// disable the filter for discovery later
eldbus_proxy_call
(o->proxy, "SetDiscoveryFilter", cb_obj_discovery_filter, o, -1, "");
}
goto done;
}
@ -526,6 +535,157 @@ bz_obj_disconnect(Obj *o)
eldbus_proxy_call
(o->proxy, "Disconnect", cb_disconnect, o, -1, "");
}
static Eina_Bool
cb_ping_exit(void *data, int type EINA_UNUSED, void *event)
{
Obj *o = data;
Ecore_Exe_Event_Del *ev = event;
printf("@@@EXE EXIT.. %p == %p\n", ev->exe, o->ping_exe);
if (ev->exe != o->ping_exe) return ECORE_CALLBACK_PASS_ON;
printf("@@@PING RESULT... %i\n", ev->exit_code);
o->ping_exe = NULL;
if (ev->exit_code == 0)
{
if (!o->ping_ok)
{
printf("@@@PING SUCCEED\n");
o->ping_ok = EINA_TRUE;
if (o->fn_change) o->fn_change(o);
}
}
else
{
if (o->ping_ok)
{
printf("@@@PING FAIL\n");
o->ping_ok = EINA_FALSE;
if (o->fn_change) o->fn_change(o);
}
}
return ECORE_CALLBACK_PASS_ON;
}
static int
ping_powersave_timeout_get(void)
{
int timeout = 10;
E_Powersave_Mode pm = e_powersave_mode_get();
if (pm <= E_POWERSAVE_MODE_LOW) timeout = 5;
else if (pm <= E_POWERSAVE_MODE_MEDIUM) timeout = 8;
else if (pm <= E_POWERSAVE_MODE_HIGH) timeout = 12;
else if (pm <= E_POWERSAVE_MODE_EXTREME) timeout = 30;
return timeout;
}
static void
ping_do(Obj *o)
{
Eina_Strbuf *buf;
if (!o->ping_exe_handler)
o->ping_exe_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
cb_ping_exit, o);
buf = eina_strbuf_new();
if (buf)
{
int timeout = ping_powersave_timeout_get();
timeout *= 1000;
eina_strbuf_append_printf
(buf, "%s/enlightenment/utils/enlightenment_sys l2ping %s %i",
e_prefix_lib_get(), o->address, timeout);
o->ping_exe = ecore_exe_run(eina_strbuf_string_get(buf), NULL);
eina_strbuf_free(buf);
printf("@@@ run new ping %s %i = %p\n", o->address, timeout, o->ping_exe);
}
}
static Eina_Bool cb_ping_timer(void *data);
static void
ping_schedule(Obj *o)
{
double timeout = ping_powersave_timeout_get() + 1.0;
if (o->ping_timer) ecore_timer_del(o->ping_timer);
o->ping_timer = ecore_timer_add(timeout, cb_ping_timer, o);
}
static Eina_Bool
cb_ping_timer(void *data)
{
Obj *o = data;
printf("@@@ ping timer %s\n", o->address);
if (o->ping_exe)
{
printf("@@@PING TIMEOUT\n");
ecore_exe_free(o->ping_exe);
o->ping_exe = NULL;
if (o->ping_ok)
{
o->ping_ok = EINA_FALSE;
if (o->fn_change) o->fn_change(o);
}
}
ping_do(o);
ping_schedule(o);
return EINA_TRUE;
}
void
bz_obj_ping_begin(Obj *o)
{
if (o->ping_timer) return;
if (o->ping_exe_handler)
{
ecore_event_handler_del(o->ping_exe_handler);
o->ping_exe_handler = NULL;
}
if (o->ping_exe)
{
ecore_exe_free(o->ping_exe);
o->ping_exe = NULL;
}
ping_do(o);
ping_schedule(o);
}
void
bz_obj_ping_end(Obj *o)
{
if (o->ping_exe_handler)
{
ecore_event_handler_del(o->ping_exe_handler);
o->ping_exe_handler = NULL;
}
if (o->ping_timer)
{
ecore_timer_del(o->ping_timer);
o->ping_timer = NULL;
}
if (o->ping_exe)
{
ecore_exe_free(o->ping_exe);
o->ping_exe = NULL;
}
if (o->ping_ok)
{
printf("@@@PING END %s\n", o->address);
o->ping_ok = EINA_FALSE;
if (o->fn_change) o->fn_change(o);
}
}
static void
cb_remove(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Remove");
}
/*
void
bz_obj_profile_connect(Obj *o, const char *uuid)
@ -541,11 +701,6 @@ bz_obj_profile_disconnect(Obj *o, const char *uuid)
eldbus_proxy_call(o->proxy, "DisconnectProfile", NULL, NULL, -1, "s", uuid);
}
*/
static void
cb_remove(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Remove");
}
void
bz_obj_remove(Obj *o)
@ -615,6 +770,21 @@ bz_obj_unref(Obj *o)
bz_agent_msg_drop(o->agent_msg_ok);
o->agent_msg_ok = NULL;
}
if (o->ping_exe_handler)
{
ecore_event_handler_del(o->ping_exe_handler);
o->ping_exe_handler = NULL;
}
if (o->ping_timer)
{
ecore_timer_del(o->ping_timer);
o->ping_timer = NULL;
}
if (o->ping_exe)
{
ecore_exe_free(o->ping_exe);
o->ping_exe = NULL;
}
free(o);
}

View File

@ -5,6 +5,7 @@ static E_Module *mod = NULL;
/* Local config */
static E_Config_DD *conf_adapter_edd = NULL;
static E_Config_DD *conf_device_edd = NULL;
static E_Config_DD *conf_edd = NULL;
Config *ebluez5_config = NULL;
@ -332,6 +333,88 @@ ebluez5_instances_update(void)
}
}
static void
_device_prop_clean(Config_Device *dev)
{
if ((!dev->unlock) && (!dev->force_connect))
{
ebluez5_config->devices = eina_list_remove(ebluez5_config->devices, dev);
eina_stringshare_del(dev->addr);
free(dev);
}
}
static Config_Device *
_device_prop_new(const char *address)
{
Config_Device *dev = calloc(1, sizeof(Config_Device));
if (!dev) return NULL;
dev->addr = eina_stringshare_add(address);
if (!dev->addr)
{
free(dev);
return NULL;
}
ebluez5_config->devices = eina_list_append(ebluez5_config->devices, dev);
return dev;
}
Config_Device *
ebluez5_device_prop_find(const char *address)
{
Config_Device *dev;
Eina_List *l;
if (!address) return NULL;
EINA_LIST_FOREACH(ebluez5_config->devices, l, dev)
{
if ((dev->addr) && (!strcmp(address, dev->addr)))
return dev;
}
return NULL;
}
void
ebluez5_device_prop_force_connect_set(const char *address, Eina_Bool enable)
{
Config_Device *dev;
if (!address) return;
dev = ebluez5_device_prop_find(address);
if (dev)
{
dev->force_connect = enable;
_device_prop_clean(dev);
return;
}
if (enable)
{
dev = _device_prop_new(address);
dev->force_connect = enable;
}
}
void
ebluez5_device_prop_unlock_set(const char *address, Eina_Bool enable)
{
Config_Device *dev;
if (!address) return;
dev = ebluez5_device_prop_find(address);
if (dev)
{
dev->unlock = enable;
_device_prop_clean(dev);
return;
}
if (enable)
{
dev = _device_prop_new(address);
dev->unlock = enable;
}
}
/////////////////////////////////////////////////////////////////////////////
/* Module Functions */
@ -349,12 +432,22 @@ e_modapi_init(E_Module *m)
E_CONFIG_VAL(D, T, powered, UCHAR);
E_CONFIG_VAL(D, T, pairable, UCHAR);
conf_device_edd = E_CONFIG_DD_NEW("Config_Device", Config_Device);
#undef T
#undef D
#define T Config_Device
#define D conf_device_edd
E_CONFIG_VAL(D, T, addr, STR);
E_CONFIG_VAL(D, T, force_connect, UCHAR);
E_CONFIG_VAL(D, T, unlock, UCHAR);
conf_edd = E_CONFIG_DD_NEW("Config", Config);
#undef T
#undef D
#define T Config
#define D conf_edd
E_CONFIG_LIST(D, T, adapters, conf_adapter_edd);
E_CONFIG_LIST(D, T, devices, conf_device_edd);
ebluez5_config = e_config_domain_load("module.ebluez5", conf_edd);
if (!ebluez5_config) ebluez5_config = E_NEW(Config, 1);
@ -372,6 +465,7 @@ E_API int
e_modapi_shutdown(E_Module *m EINA_UNUSED)
{
Config_Adapter *ad;
Config_Device *dev;
E_CONFIG_DD_FREE(conf_edd);
E_CONFIG_DD_FREE(conf_adapter_edd);
@ -381,6 +475,11 @@ e_modapi_shutdown(E_Module *m EINA_UNUSED)
eina_stringshare_del(ad->addr);
free(ad);
}
EINA_LIST_FREE(ebluez5_config->devices, dev)
{
eina_stringshare_del(dev->addr);
free(dev);
}
free(ebluez5_config);
ebluez5_config = NULL;

View File

@ -23,6 +23,7 @@ typedef struct _Config Config;
struct _Config
{
Eina_List *adapters;
Eina_List *devices;
};
typedef struct _Config_Adapter Config_Adapter;
struct _Config_Adapter
@ -31,6 +32,13 @@ struct _Config_Adapter
Eina_Bool powered;
Eina_Bool pairable;
};
typedef struct _Config_Device Config_Device;
struct _Config_Device
{
const char *addr;
Eina_Bool force_connect;
Eina_Bool unlock;
};
extern Config *ebluez5_config;
@ -45,6 +53,10 @@ void ebluez5_popups_show(void);
void ebluez5_rfkill_unblock(const char *name);
void ebluez5_instances_update(void);
void ebluez5_device_prop_force_connect_set(const char *address, Eina_Bool enable);
void ebluez5_device_prop_unlock_set(const char *address, Eina_Bool enable);
Config_Device *ebluez5_device_prop_find(const char *address);
void ebluez5_popup_hide(Instance *inst);
Evas_Object *ebluez5_popup_content_add(Evas_Object *base, Instance *inst);

View File

@ -7,12 +7,137 @@ static Eina_List *lists = NULL;
static Eina_List *adapters = NULL;
static Eina_List *devices = NULL;
static int unlock_count = 0;
static int unlock_do = 0;
static Eina_Bool unlock_block = EINA_FALSE;
static Config_Device *
_devices_conifg_find(const char *address)
{
Config_Device *dev;
Eina_List *l;
if (!ebluez5_config) return NULL;
if (!address) return NULL;
EINA_LIST_FOREACH(ebluez5_config->devices, l, dev)
{
if ((dev->addr) && (!strcmp(address, dev->addr))) return dev;
}
return NULL;
}
static void
_devices_eval(void)
{
Obj *o;
Eina_List *l;
Config_Device *dev;
int unlock_count_prev = 0;
unlock_count_prev = unlock_count;
unlock_count = 0;
unlock_do = 0;
printf("=== _devices_eval...\n");
EINA_LIST_FOREACH(devices, l, o)
{
if (o->paired)
{
Eina_Bool need_ping = EINA_FALSE;
dev = _devices_conifg_find(o->address);
if (dev)
{
printf("=== dev: %s|%s [%s]\n", dev->addr, o->address, o->name);
if ((dev->force_connect) && (!o->connected))
{
printf("=== %s force con, not conn, ping ok=%i\n", o->address, o->ping_ok);
if (o->ping_ok)
{
printf("=== %s force con, not conn, ping ok=%i\n", o->address, o->ping_ok);
bz_obj_connect(o);
}
else need_ping = EINA_TRUE;
}
if (dev->unlock)
{
printf("=== unlock...\n");
// if a device on our list needs an unlock, then
// add to our possible unlock counts needed
unlock_count++;
#if 0
// if the device is connected then assume it unlocks
if (o->connected)
{
printf("=== don't need ping1\n");
unlock_do++;
}
else
#endif
{
printf("=== need ping2\n");
need_ping = EINA_TRUE;
if (o->ping_ok) unlock_do++;
}
}
}
printf("=== %s need_ping=%i conn=%i ping_ok=%i\n", o->address, need_ping, o->connected, o->ping_ok);
if (need_ping) bz_obj_ping_begin(o);
else bz_obj_ping_end(o);
}
}
printf("=================== unlock: %i/%i\n", unlock_do, unlock_count);
if (unlock_count > 0)
{
if (unlock_do == 0)
{
if (unlock_block)
{
unlock_block = EINA_FALSE;
printf("=== DESKLOCK UNBLOCK\n");
e_desklock_unblock();
printf("=== DESLOCK SHOW\n");
e_desklock_show(EINA_FALSE);
}
}
else
{
if (!unlock_block)
{
unlock_block = EINA_TRUE;
printf("=== DESKLOCK BLOCK\n");
e_desklock_block();
}
}
}
else
{
if (unlock_count_prev != unlock_count)
{
if (!e_desklock_manual_get())
{
if (e_desklock_state_get())
{
printf("=== DESKLOCK HIDE\n");
e_desklock_hide();
}
}
}
if (unlock_block)
{
unlock_block = EINA_FALSE;
printf("=== DESKLOCK UNBLOCK\n");
e_desklock_unblock();
}
}
}
static void
_adapter_add(Evas_Object *gl, Obj *o)
{
Elm_Object_Item *it = evas_object_data_get(gl, "adapters_item");;
elm_genlist_item_append(gl, adapt_itc, o, it, ELM_GENLIST_ITEM_NONE,
NULL, NULL);
NULL, NULL);
}
static int
@ -44,7 +169,8 @@ _device_add(Evas_Object *gl, Obj *o)
{
Elm_Object_Item *it = evas_object_data_get(gl, "devices_item");;
elm_genlist_item_sorted_insert(gl, dev_itc, o, it, ELM_GENLIST_ITEM_NONE,
elm_genlist_item_sorted_insert(gl, dev_itc, o, it,
ELM_GENLIST_ITEM_NONE,
_cb_insert_cmp, NULL, NULL);
}
@ -131,6 +257,61 @@ _cb_unpair(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSE
bz_obj_remove(o);
}
static void
_cb_unlock_start(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
printf("unlock start %s\n", o->address);
ebluez5_device_prop_unlock_set(o->address, EINA_TRUE);
ebluez5_popup_device_change(o);
}
static void
_cb_unlock_stop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
printf("unlock stop %s\n", o->address);
ebluez5_device_prop_unlock_set(o->address, EINA_FALSE);
ebluez5_popup_device_change(o);
}
static void
_cb_force_connect_start(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
ebluez5_device_prop_force_connect_set(o->address, EINA_TRUE);
ebluez5_popup_adapter_change(o);
}
static void
_cb_force_connect_stop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
ebluez5_device_prop_force_connect_set(o->address, EINA_FALSE);
ebluez5_popup_adapter_change(o);
}
static void
_cb_flip(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
{
Obj *o = data;
Evas_Object *gl = evas_object_data_get(obj, "genlist");
Elm_Object_Item *it;
for (it = elm_genlist_first_item_get(gl); it;
it = elm_genlist_item_next_get(it))
{
if (o == elm_object_item_data_get(it))
{
if (elm_genlist_item_flip_get(it))
elm_genlist_item_flip_set(it, EINA_FALSE);
else
elm_genlist_item_flip_set(it, EINA_TRUE);
break;
}
}
}
static void
_agent_done(Obj *o)
{
@ -305,7 +486,7 @@ _cb_dev_text_get(void *data, Evas_Object *obj EINA_UNUSED,
static Evas_Object *
_cb_dev_content_get(void *data EINA_UNUSED, Evas_Object *obj,
const char *part EINA_UNUSED)
const char *part)
{
Obj *o = data;
char buf[512];
@ -342,14 +523,49 @@ _cb_dev_content_get(void *data EINA_UNUSED, Evas_Object *obj,
evas_object_show(ic);
return bx;
}
else if (!strcmp(part, "elm.swallow.end"))
else if (!strcmp(part, "elm.text.flip"))
{
Evas_Object *bx, *ic, *bt, *lb, *tb, *en, *rec;
Evas_Object *bx, *bt, *ic;
bx = elm_box_add(obj);
elm_box_horizontal_set(bx, EINA_TRUE);
elm_box_align_set(bx, 1.0, 0.5);
if (o->paired)
{
if (o->paired)
{
Config_Device *dev = ebluez5_device_prop_find(o->address);
if ((dev) && (dev->unlock))
{
bt = util_button_icon_add(obj, "changes-allow-symbolic",
_("Stop this from being an unlock device"));
evas_object_smart_callback_add(bt, "clicked", _cb_unlock_stop, o);
}
else
{
bt = util_button_icon_add(obj, "channel-insecure-symbolic",
_("Make this auto unlock when detected (and lock when not)"));
evas_object_smart_callback_add(bt, "clicked", _cb_unlock_start, o);
}
elm_box_pack_end(bx, bt);
evas_object_show(bt);
if ((dev) && (dev->force_connect))
{
bt = util_button_icon_add(obj, "checkbox-symbolic",
_("Stop this device from being forcefullty connected"));
evas_object_smart_callback_add(bt, "clicked", _cb_force_connect_stop, o);
}
else
{
bt = util_button_icon_add(obj, "checkbox-checked-symbolic",
_("Force this device to be connected when detected"));
evas_object_smart_callback_add(bt, "clicked", _cb_force_connect_start, o);
}
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
if (o->connected)
{
bt = util_button_icon_add(obj, "network-offline",
@ -382,64 +598,7 @@ _cb_dev_content_get(void *data EINA_UNUSED, Evas_Object *obj,
}
if (!o->paired)
{
if (o->agent_request)
{
if (o->agent_entry_fn)
{
tb = elm_table_add(obj);
rec = evas_object_rectangle_add(evas_object_evas_get(obj));
evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(80), ELM_SCALE_SIZE(1));
elm_table_pack(tb, rec, 0, 0, 1, 1);
en = elm_entry_add(obj);
elm_entry_single_line_set(en, EINA_TRUE);
elm_entry_scrollable_set(en, EINA_TRUE);
elm_scroller_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
elm_object_part_text_set(en, "guide", o->agent_request);
// elm_entry_password_set(en, EINA_TRUE);
evas_object_smart_callback_add(en, "activated", _cb_agent_ok, o);
evas_object_smart_callback_add(en, "aborted", _cb_agent_cancel, o);
elm_table_pack(tb, en, 0, 0, 1, 1);
evas_object_show(en);
elm_box_pack_end(bx, tb);
evas_object_show(tb);
bt = util_button_icon_add(obj, "list-add",
_("Pair with this device"));
evas_object_data_set(bt, "entry", en);
evas_object_smart_callback_add(bt, "clicked", _cb_agent_ok, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
bt = util_button_icon_add(obj, "list-remove",
_("Reject pairing"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_cancel, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
else
{
lb = elm_label_add(obj);
elm_layout_text_set(lb, NULL, o->agent_request);
elm_box_pack_end(bx, lb);
evas_object_show(lb);
bt = util_button_icon_add(obj, "list-add",
_("Pair with this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_ok, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
bt = util_button_icon_add(obj, "list-remove",
_("Reject pairing"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_cancel, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
}
else
if (!o->agent_request)
{
bt = util_button_icon_add(obj, "list-add",
_("Pair with this device"));
@ -457,6 +616,90 @@ _cb_dev_content_get(void *data EINA_UNUSED, Evas_Object *obj,
evas_object_show(bt);
}
bt = util_button_icon_add(obj, "view-more-horizontal",
_("Cancel"));
evas_object_data_set(bt, "genlist", obj);
evas_object_smart_callback_add(bt, "clicked", _cb_flip, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
ic = util_obj_icon_rssi_add(obj, o, 24);
elm_box_pack_end(bx, ic);
evas_object_show(ic);
return bx;
}
else if (!strcmp(part, "elm.swallow.end"))
{
Evas_Object *bx, *ic, *bt, *lb, *tb, *en, *rec;
bx = elm_box_add(obj);
elm_box_horizontal_set(bx, EINA_TRUE);
if (o->agent_request)
{
if (o->agent_entry_fn)
{
tb = elm_table_add(obj);
rec = evas_object_rectangle_add(evas_object_evas_get(obj));
evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(80), ELM_SCALE_SIZE(1));
elm_table_pack(tb, rec, 0, 0, 1, 1);
en = elm_entry_add(obj);
elm_entry_single_line_set(en, EINA_TRUE);
elm_entry_scrollable_set(en, EINA_TRUE);
elm_scroller_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
elm_object_part_text_set(en, "guide", o->agent_request);
// elm_entry_password_set(en, EINA_TRUE);
evas_object_smart_callback_add(en, "activated", _cb_agent_ok, o);
evas_object_smart_callback_add(en, "aborted", _cb_agent_cancel, o);
elm_table_pack(tb, en, 0, 0, 1, 1);
evas_object_show(en);
elm_box_pack_end(bx, tb);
evas_object_show(tb);
bt = util_button_icon_add(obj, "list-add",
_("Pair with this device"));
evas_object_data_set(bt, "entry", en);
evas_object_smart_callback_add(bt, "clicked", _cb_agent_ok, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
bt = util_button_icon_add(obj, "list-remove",
_("Reject pairing"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_cancel, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
else
{
lb = elm_label_add(obj);
elm_layout_text_set(lb, NULL, o->agent_request);
elm_box_pack_end(bx, lb);
evas_object_show(lb);
bt = util_button_icon_add(obj, "list-add",
_("Pair with this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_ok, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
bt = util_button_icon_add(obj, "list-remove",
_("Reject pairing"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_cancel, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
}
bt = util_button_icon_add(obj, "view-more-horizontal",
_("Options for device like conneect, pair etc."));
evas_object_data_set(bt, "genlist", obj);
evas_object_smart_callback_add(bt, "clicked", _cb_flip, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
ic = util_obj_icon_rssi_add(obj, o, 24);
elm_box_pack_end(bx, ic);
evas_object_show(ic);
@ -581,6 +824,11 @@ ebluze5_popup_init(void)
void
ebluze5_popup_shutdown(void)
{
if (unlock_block)
{
unlock_block = EINA_FALSE;
e_desklock_unblock();
}
ebluze5_popup_clear();
elm_genlist_item_class_free(group_itc);
elm_genlist_item_class_free(dev_itc);
@ -717,6 +965,7 @@ ebluez5_popup_device_add(Obj *o)
{
_device_add(gl, o);
}
_devices_eval();
}
void
@ -739,6 +988,7 @@ ebluez5_popup_device_del(Obj *o)
}
}
devices = eina_list_remove(devices, o);
_devices_eval();
}
void
@ -779,6 +1029,7 @@ ebluez5_popup_device_change(Obj *o)
}
}
}
_devices_eval();
}
const Eina_List *