a11y: cally-util: use password-char to fill a key_event if required

This commit is contained in:
Alejandro Piñeiro 2012-09-24 15:09:43 +02:00
parent a622d34444
commit 78a3590fd6

View File

@ -50,6 +50,8 @@
#include "cally-root.h" #include "cally-root.h"
#include "cally-stage.h" #include "cally-stage.h"
#define DEFAULT_PASSWORD_CHAR '*'
/* atkutil.h */ /* atkutil.h */
static guint cally_util_add_key_event_listener (AtkKeySnoopFunc listener, static guint cally_util_add_key_event_listener (AtkKeySnoopFunc listener,
@ -77,8 +79,6 @@ static gboolean notify_hf (gpointer k
static void insert_hf (gpointer key, static void insert_hf (gpointer key,
gpointer value, gpointer value,
gpointer data); gpointer data);
static AtkKeyEventStruct * atk_key_event_from_clutter_event_key (ClutterKeyEvent *event);
/* This is just a copy of the Gail one, a shared library or place to /* This is just a copy of the Gail one, a shared library or place to
define it could be a good idea. */ define it could be a good idea. */
@ -249,7 +249,8 @@ cally_util_simulate_snooper_remove (void)
} }
static AtkKeyEventStruct * static AtkKeyEventStruct *
atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event) atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event,
gunichar password_char)
{ {
AtkKeyEventStruct *atk_event = g_new0 (AtkKeyEventStruct, 1); AtkKeyEventStruct *atk_event = g_new0 (AtkKeyEventStruct, 1);
gunichar key_unichar; gunichar key_unichar;
@ -267,7 +268,10 @@ atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event)
return NULL; return NULL;
} }
atk_event->state = clutter_event->modifier_state; if (password_char)
atk_event->state = 0;
else
atk_event->state = clutter_event->modifier_state;
/* We emit the clutter keyval. This is not exactly the one expected /* We emit the clutter keyval. This is not exactly the one expected
by AtkKeyEventStruct, as it expects a Gdk-like event, with the by AtkKeyEventStruct, as it expects a Gdk-like event, with the
@ -275,7 +279,10 @@ atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event)
that on the AT application. that on the AT application.
More information: Bug 1952 and bug 2072 More information: Bug 1952 and bug 2072
*/ */
atk_event->keyval = clutter_event->keyval; if (password_char)
atk_event->keyval = clutter_unicode_to_keysym (password_char);
else
atk_event->keyval = clutter_event->keyval;
/* It is expected to store a key defining string here (ie "Space" in /* It is expected to store a key defining string here (ie "Space" in
case you press a space). Anyway, there are no function on clutter case you press a space). Anyway, there are no function on clutter
@ -286,7 +293,10 @@ atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event)
More information: Bug 1952 and 2072 More information: Bug 1952 and 2072
*/ */
key_unichar = clutter_event_get_key_unicode ((ClutterEvent *) clutter_event); if (password_char)
key_unichar = password_char;
else
key_unichar = clutter_event_get_key_unicode ((ClutterEvent *) clutter_event);
if (g_unichar_validate (key_unichar) && !g_unichar_iscntrl (key_unichar)) if (g_unichar_validate (key_unichar) && !g_unichar_iscntrl (key_unichar))
{ {
@ -302,7 +312,15 @@ atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event)
atk_event->length = 0; atk_event->length = 0;
atk_event->keycode = clutter_event->hardware_keycode; /* Computing the hardware keycode from the password-char is
difficult. But we are in a password situation. We are already a
unichar that it is not the original one. Providing a "almost
real" keycode is irrelevant */
if (password_char)
atk_event->keycode = 0;
else
atk_event->keycode = clutter_event->hardware_keycode;
atk_event->timestamp = clutter_event->time; atk_event->timestamp = clutter_event->time;
#ifdef CALLY_DEBUG #ifdef CALLY_DEBUG
@ -335,6 +353,37 @@ insert_hf (gpointer key, gpointer value, gpointer data)
g_hash_table_insert (new_table, key, value); g_hash_table_insert (new_table, key, value);
} }
/*
* 0 if the key of that event is visible, in other case the password
* char
*/
static gunichar
check_key_visibility (ClutterEvent *event)
{
ClutterKeyEvent *key_event = (ClutterKeyEvent *)event;
AtkObject *accessible = clutter_actor_get_accessible (key_event->source);
g_return_val_if_fail (accessible != NULL, 0);
if (atk_object_get_role (accessible) != ATK_ROLE_PASSWORD_TEXT)
return 0;
/* If it is a clutter text, we use his password char. Note that
although at Clutter toolkit itself, only ClutterText exposes a
password role, nothing prevents on any derived toolkit (like st)
to create a new actor that can behave like a password entry. And
the key event will still be emitted here. Although in that case
we would lose any password char from the derived toolkit, it is
still better fill this with a default unichar that the original
one */
if (CLUTTER_IS_TEXT (key_event->source))
return clutter_text_get_password_char (CLUTTER_TEXT (key_event->source));
else
return DEFAULT_PASSWORD_CHAR;
}
static gboolean static gboolean
cally_key_snooper (ClutterActor *actor, cally_key_snooper (ClutterActor *actor,
ClutterEvent *event, ClutterEvent *event,
@ -342,6 +391,7 @@ cally_key_snooper (ClutterActor *actor,
{ {
AtkKeyEventStruct *key_event = NULL; AtkKeyEventStruct *key_event = NULL;
gint consumed = 0; gint consumed = 0;
gunichar password_char = 0;
/* filter key events */ /* filter key events */
if ((event->type != CLUTTER_KEY_PRESS) && (event->type != CLUTTER_KEY_RELEASE)) if ((event->type != CLUTTER_KEY_PRESS) && (event->type != CLUTTER_KEY_RELEASE))
@ -349,12 +399,15 @@ cally_key_snooper (ClutterActor *actor,
return FALSE; return FALSE;
} }
password_char = check_key_visibility (event);
if (key_listener_list) if (key_listener_list)
{ {
GHashTable *new_hash = g_hash_table_new (NULL, NULL); GHashTable *new_hash = g_hash_table_new (NULL, NULL);
g_hash_table_foreach (key_listener_list, insert_hf, new_hash); g_hash_table_foreach (key_listener_list, insert_hf, new_hash);
key_event = atk_key_event_from_clutter_event_key ((ClutterKeyEvent *)event); key_event = atk_key_event_from_clutter_event_key ((ClutterKeyEvent *)event,
password_char);
/* func data is inside the hash table */ /* func data is inside the hash table */
consumed = g_hash_table_foreach_steal (new_hash, notify_hf, key_event); consumed = g_hash_table_foreach_steal (new_hash, notify_hf, key_event);
g_hash_table_destroy (new_hash); g_hash_table_destroy (new_hash);