feature: add PIN-style desklock for lokker module

accessible from the normal screen lock dialog
This commit is contained in:
discomfitor 2013-10-26 18:02:20 +01:00 committed by Mike Blumenkrantz
parent 235c369adf
commit 3b15315764
6 changed files with 282 additions and 18 deletions

View File

@ -570,6 +570,7 @@ _e_config_edd_init(Eina_Bool old)
E_CONFIG_LIST(D, T, shelves, _e_config_shelf_edd);
E_CONFIG_VAL(D, T, font_hinting, INT); /**/
E_CONFIG_VAL(D, T, desklock_passwd, INT);
E_CONFIG_VAL(D, T, desklock_pin, INT);
E_CONFIG_LIST(D, T, desklock_backgrounds, _e_config_desklock_bg_edd); /**/
E_CONFIG_VAL(D, T, desklock_auth_method, INT);
E_CONFIG_VAL(D, T, desklock_login_box_zone, INT);

View File

@ -207,6 +207,7 @@ struct _E_Config
int font_hinting; // GUI
int desklock_passwd; // GUI // hashed
int desklock_pin; // GUI // hashed
Eina_List *desklock_backgrounds; // GUI
int desklock_auth_method; // GUI
int desklock_login_box_zone; // GUI

View File

@ -16,6 +16,7 @@ typedef enum
E_DESKLOCK_AUTH_METHOD_SYSTEM = 0,
E_DESKLOCK_AUTH_METHOD_PERSONAL = 1,
E_DESKLOCK_AUTH_METHOD_EXTERNAL = 2,
E_DESKLOCK_AUTH_METHOD_PIN = 3,
} E_Desklock_Auth_Method;
typedef struct E_Desklock_Interface E_Desklock_Interface;

View File

@ -17,7 +17,7 @@ static void _cb_bg_mouse_down(void *data, Evas *evas, Evas_Object *obj,
struct _E_Config_Dialog_Data
{
Evas_Object *lock_cmd_entry, *passwd_entry;
Evas_Object *lock_cmd_entry, *passwd_entry, *pin_entry;
E_Config_Dialog *cfd, *bg_fsel;
/* Common vars */
@ -32,6 +32,7 @@ struct _E_Config_Dialog_Data
int login_zone;
int zone;
char *desklock_personal_passwd;
char *pin_str;
char *custom_lock_cmd;
/* Layout */
@ -173,6 +174,7 @@ _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
e_object_del(E_OBJECT(cfdata->bg_fsel));
E_FREE(cfdata->custom_lock_cmd);
E_FREE(cfdata->desklock_personal_passwd);
E_FREE(cfdata->pin_str);
EINA_LIST_FREE(cfdata->bgs, bg)
eina_stringshare_del(bg);
E_FREE(cfdata);
@ -210,6 +212,9 @@ _basic_create(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data
ow = e_widget_radio_add(evas, _("Use Personal Screenlock Password"), E_DESKLOCK_AUTH_METHOD_PERSONAL, rg);
evas_object_smart_callback_add(ow, "changed", _login_method_change, cfdata);
e_widget_list_object_append(ol, ow, 1, 1, 0.5);
ow = e_widget_radio_add(evas, _("Use PIN"), E_DESKLOCK_AUTH_METHOD_PIN, rg);
evas_object_smart_callback_add(ow, "changed", _login_method_change, cfdata);
e_widget_list_object_append(ol, ow, 1, 1, 0.5);
ow = e_widget_radio_add(evas, _("Use External Screenlock Command"), E_DESKLOCK_AUTH_METHOD_EXTERNAL, rg);
evas_object_smart_callback_add(ow, "changed", _login_method_change, cfdata);
e_widget_list_object_append(ol, ow, 1, 1, 0.5);
@ -220,12 +225,20 @@ _basic_create(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data
e_widget_framelist_object_append(of, ow);
e_widget_list_object_append(ol, of, 1, 1, 0.5);
of = e_widget_framelist_add(evas, _("PIN Entry"), 0);
cfdata->pin_entry = ow = e_widget_entry_add(evas, &(cfdata->pin_str), NULL, NULL, NULL);
e_widget_entry_password_set(ow, 1);
e_widget_framelist_object_append(of, ow);
e_widget_list_object_append(ol, of, 1, 1, 0.5);
of = e_widget_framelist_add(evas, _("External Screenlock Command"), 0);
cfdata->lock_cmd_entry = ow = e_widget_entry_add(evas, &(cfdata->custom_lock_cmd), NULL, NULL, NULL);
e_widget_framelist_object_append(of, ow);
e_widget_disabled_set(cfdata->passwd_entry,
(cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_PERSONAL));
e_widget_disabled_set(cfdata->pin_entry,
(cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_PIN));
e_widget_disabled_set(cfdata->lock_cmd_entry,
(cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_EXTERNAL));
@ -397,6 +410,24 @@ _basic_apply(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
eina_hash_djb2(cfdata->desklock_personal_passwd,
strlen(cfdata->desklock_personal_passwd));
}
else if (cfdata->desklock_auth_method == E_DESKLOCK_AUTH_METHOD_PIN)
{
if (cfdata->pin_str && cfdata->pin_str[0])
{
int test;
char *pp;
errno = 0;
test = strtol(cfdata->pin_str, &pp, 10);
if (errno) return 0; //NAN
if (pp && pp[0]) return 0;
if (test < 1) return 0;
e_config->desklock_pin = eina_hash_djb2(cfdata->pin_str, strlen(cfdata->pin_str));
}
else
/* dumb, but let them do what they want... */
e_config->desklock_pin = 0;
}
e_config->desklock_start_locked = cfdata->start_locked;
e_config->desklock_on_suspend = cfdata->lock_on_suspend;
e_config->desklock_autolock_idle = cfdata->auto_lock;
@ -480,6 +511,13 @@ _basic_check_changed(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfda
strlen(cfdata->desklock_personal_passwd)))
return 1;
}
if (e_config->desklock_auth_method == E_DESKLOCK_AUTH_METHOD_PIN)
{
if (e_config->desklock_pin !=
eina_hash_djb2(cfdata->pin_str,
strlen(cfdata->pin_str)))
return 1;
}
if (e_config->desklock_autolock_screensaver != cfdata->screensaver_lock)
return 1;
@ -644,6 +682,13 @@ _login_method_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info
e_widget_entry_select_all(cfdata->passwd_entry);
e_widget_focus_set(cfdata->passwd_entry, 1);
}
e_widget_disabled_set(cfdata->pin_entry,
(cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_PIN));
if (!e_widget_disabled_get(cfdata->pin_entry))
{
e_widget_entry_select_all(cfdata->pin_entry);
e_widget_focus_set(cfdata->pin_entry, 1);
}
e_widget_disabled_set(cfdata->lock_cmd_entry,
(cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_EXTERNAL));
if (!e_widget_disabled_get(cfdata->lock_cmd_entry))

View File

@ -18,7 +18,13 @@
#define ERR(...) EINA_LOG_DOM_ERR(_e_lokker_log_dom, __VA_ARGS__)
#define CRIT(...) EINA_LOG_DOM_CRIT(_e_lokker_log_dom, __VA_ARGS__)
typedef enum
{
E_DESKLOCK_AUTH_METHOD_LINES = 4,
} E_Desklock_Auth_Method2;
EINTERN Eina_Bool lokker_lock(void);
EINTERN void lokker_unlock(void);
EAPI E_Config_Dialog *e_int_config_lokker(E_Comp *comp, const char *params EINA_UNUSED);
#endif

View File

@ -34,6 +34,14 @@ static E_Zone *last_active_zone = NULL;
static Lokker_Data *edd = NULL;
static int _lokker_check_auth(void);
static Eina_Bool
lokker_is_pin(void)
{
return e_config->desklock_auth_method == E_DESKLOCK_AUTH_METHOD_PIN;
}
static int
_zone_count_get(void)
{
@ -156,6 +164,147 @@ _lokker_delete(void)
_lokker_backspace();
}
static Eina_Bool
_pin_mouse_button_down(Lokker_Popup *lp, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
{
Evas *e;
if (ev->buttons != 1) return ECORE_CALLBACK_DONE;
e = e_comp_get(lp->zone)->evas;
evas_event_feed_mouse_move(e,
e_comp_canvas_x_root_adjust(lp->zone->comp, ev->root.x),
e_comp_canvas_y_root_adjust(lp->zone->comp, ev->root.y),
0, NULL);
evas_event_feed_mouse_down(e, 1, 0, 0, NULL);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_pin_mouse_button_up(Lokker_Popup *lp, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
{
if (ev->buttons != 1) return ECORE_CALLBACK_DONE;
evas_event_feed_mouse_up(evas_object_evas_get(lp->comp_object), 1, 0, 0, NULL);
return ECORE_CALLBACK_RENEW;
}
static void
_pin_click(void *data EINA_UNUSED, Evas_Object *obj, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
{
const char *name;
int num;
name = edje_object_part_text_get(obj, "e.text.label");
if (!name) //wtf
return;
if (!e_util_strcmp(name, "Login"))
{
_lokker_check_auth();
return;
}
if (!e_util_strcmp(name, "Delete"))
{
_lokker_backspace();
return;
}
num = strtol(name, NULL, 10);
if (num < 0) return;
if (num > 9) return;
if (edd->selected)
{
_lokker_null();
_lokker_unselect();
}
if ((strlen(edd->passwd) < (PASSWD_LEN - strlen(name))))
{
strcat(edd->passwd, name);
_text_passwd_update();
}
}
static void
_pin_box_add(Lokker_Popup *lp)
{
int mw, mh;
Evas *evas;
Evas_Object *table, *o, *o2;
int x, a = 0, b = 0;
evas = evas_object_evas_get(lp->bg_object);
lp->login_box = edje_object_add(evas);
evas_object_name_set(lp->login_box, "desklock->login_box");
e_theme_edje_object_set(lp->login_box,
"base/theme/desklock",
"e/desklock/pin_box");
edje_object_part_text_set(lp->login_box, "e.text.title",
_("Please enter your PIN"));
table = e_table_add(evas);
e_comp_object_util_del_list_append(lp->login_box, table);
e_table_homogenous_set(table, 1);
e_table_freeze(table);
for (x = 1; x < 11; x++)
{
char buf[8];
o = edje_object_add(evas);
e_comp_object_util_del_list_append(lp->login_box, o);
e_theme_edje_object_set(o, "base/theme/desklock", "e/desklock/pin_button");
snprintf(buf, sizeof(buf), "%d", x % 10);
edje_object_part_text_set(o, "e.text.label", buf);
evas_object_show(o);
edje_object_signal_callback_add(o, "e,action,click", "*", _pin_click, lp);
if (x == 10) a = 1;
e_table_pack(table, o, a, b, 1, 1);
e_table_pack_options_set(o, 1, 1, 0, 0, 0.5, 0.5,
48 * e_scale, 48 * e_scale, 48 * e_scale, 48 * e_scale);
if (++a >= 3)
{
a = 0;
b++;
}
}
/* delete */
o = edje_object_add(evas);
e_comp_object_util_del_list_append(lp->login_box, o);
e_theme_edje_object_set(o, "base/theme/desklock", "e/desklock/pin_button");
edje_object_part_text_set(o, "e.text.label", "Delete");
o2 = e_icon_add(evas);
e_comp_object_util_del_list_append(lp->login_box, o2);
e_util_icon_theme_set(o2, "list-remove");
edje_object_part_swallow(o, "e.swallow.icon", o2);
evas_object_show(o2);
evas_object_show(o);
edje_object_signal_callback_add(o, "e,action,click", "*", _pin_click, lp);
e_table_pack(table, o, 0, 3, 1, 1);
e_table_pack_options_set(o, 1, 1, 0, 0, 0.5, 0.5,
48 * e_scale, 48 * e_scale, 48 * e_scale, 48 * e_scale);
/* login */
o = edje_object_add(evas);
e_comp_object_util_del_list_append(lp->login_box, o);
e_theme_edje_object_set(o, "base/theme/desklock", "e/desklock/pin_button");
edje_object_part_text_set(o, "e.text.label", "Login");
o2 = e_icon_add(evas);
e_comp_object_util_del_list_append(lp->login_box, o2);
e_util_icon_theme_set(o2, "preferences-applications-screen-unlock");
edje_object_part_swallow(o, "e.swallow.icon", o2);
evas_object_show(o2);
evas_object_show(o);
edje_object_signal_callback_add(o, "e,action,click", "*", _pin_click, lp);
e_table_pack(table, o, 2, 3, 1, 1);
e_table_pack_options_set(o, 1, 1, 0, 0, 0.5, 0.5,
48 * e_scale, 48 * e_scale, 48 * e_scale, 48 * e_scale);
e_table_thaw(table);
evas_object_show(table);
e_table_size_min_get(table, &mw, &mh);
edje_extern_object_min_size_set(table, mw, mh);
edje_extern_object_max_size_set(table, mw, mh);
edje_object_part_swallow(lp->login_box, "e.swallow.buttons", table);
edje_object_size_min_calc(lp->login_box, &mw, &mh);
edje_extern_object_min_size_set(lp->login_box, mw, mh);
edje_extern_object_max_size_set(lp->login_box, mw, mh);
}
static void
_text_login_box_add(Lokker_Popup *lp)
@ -205,10 +354,13 @@ _text_login_box_add(Lokker_Popup *lp)
static void
_lokker_popup_add(E_Zone *zone)
{
E_Zone *current_zone;
int total_zone_num;
Lokker_Popup *lp;
E_Config_Desklock_Background *cbg;
Eina_Stringshare *bg;
Evas *evas;
int nocreate = 0;
lp = E_NEW(Lokker_Popup, 1);
cbg = eina_list_nth(e_config->desklock_backgrounds, zone->num);
@ -265,7 +417,37 @@ _lokker_popup_add(E_Zone *zone)
evas_object_layer_set(lp->comp_object, E_LAYER_DESKLOCK);
evas_object_clip_set(lp->comp_object, lp->zone->bg_clip_object);
_text_login_box_add(lp);
last_active_zone = current_zone = e_util_zone_current_get(e_manager_current_get());
total_zone_num = _zone_count_get();
if (total_zone_num > 1)
{
if ((e_config->desklock_login_box_zone == -2) && (zone != current_zone))
nocreate = 1;
else if ((e_config->desklock_login_box_zone > -1) && (e_config->desklock_login_box_zone != (int)eina_list_count(edd->elock_wnd_list)))
nocreate = 1;
}
if (!nocreate)
{
switch (e_config->desklock_auth_method)
{
case E_DESKLOCK_AUTH_METHOD_SYSTEM:
case E_DESKLOCK_AUTH_METHOD_PERSONAL:
_text_login_box_add(lp);
break;
case E_DESKLOCK_AUTH_METHOD_PIN:
_pin_box_add(lp);
edje_object_part_swallow(lp->bg_object, "e.swallow.login_box", lp->login_box);
evas_object_clip_set(lp->login_box, lp->zone->bg_clip_object);
E_LIST_HANDLER_APPEND(edd->handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, _pin_mouse_button_down, lp);
E_LIST_HANDLER_APPEND(edd->handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _pin_mouse_button_up, lp);
break;
case E_DESKLOCK_AUTH_METHOD_EXTERNAL: //handled by e_desklock
default: break;
}
}
evas_event_thaw(evas);
@ -436,8 +618,7 @@ static int
_lokker_check_auth(void)
{
if (!edd) return 0;
#ifdef HAVE_PAM
if (e_config->desklock_auth_method == 0)
if (e_desklock_is_system())
{
int ret;
@ -446,22 +627,32 @@ _lokker_check_auth(void)
_lokker_null();
return ret;
}
else if (e_config->desklock_auth_method == 1)
else if (e_desklock_is_personal())
{
#endif
if ((e_config->desklock_passwd) && (edd->passwd && edd->passwd[0]) &&
(e_config->desklock_passwd == eina_hash_djb2(edd->passwd, strlen(edd->passwd))))
{
/* password ok */
/* security - null out passwd string once we are done with it */
_lokker_null();
e_desklock_hide();
return 1;
if ((e_config->desklock_passwd) && (edd->passwd && edd->passwd[0]) &&
(e_config->desklock_passwd == eina_hash_djb2(edd->passwd, strlen(edd->passwd))))
{
/* password ok */
/* security - null out passwd string once we are done with it */
_lokker_null();
e_desklock_hide();
return 1;
}
}
else if (lokker_is_pin())
{
if (edd->passwd && edd->passwd[0])
{
if (eina_hash_djb2(edd->passwd, strlen(edd->passwd)) ==
e_config->desklock_pin)
{
_lokker_null();
e_desklock_hide();
return 1;
}
}
}
#ifdef HAVE_PAM
}
#endif
/* password is definitely wrong */
_lokker_state_set(LOKKER_STATE_INVALID);
_lokker_null();
@ -518,6 +709,16 @@ _lokker_cb_key_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
/* here we have to grab a password */
if (ev->compose)
{
if (lokker_is_pin())
{
/* block non-digits */
const char *c;
for (c = ev->compose; c[0]; c++)
{
if (!isdigit(c[0])) return ECORE_CALLBACK_RENEW;
}
}
if (edd->selected)
{
_lokker_null();
@ -542,6 +743,15 @@ lokker_lock(void)
E_Comp *comp;
if (edd) return EINA_TRUE;
if (lokker_is_pin())
{
if (!e_config->desklock_pin)
{
e_configure_registry_call("screen/screen_lock", NULL, NULL);
return EINA_FALSE;
}
}
edd = E_NEW(Lokker_Data, 1);
if (!edd) return EINA_FALSE;