diff --git a/data/gnome-shell-theme.gresource.xml b/data/gnome-shell-theme.gresource.xml
index 21191f0ce..cc9caef0a 100644
--- a/data/gnome-shell-theme.gresource.xml
+++ b/data/gnome-shell-theme.gresource.xml
@@ -20,6 +20,8 @@
no-notifications.svg
noise-texture.png
pad-osd.css
+ eye-open-negative-filled-symbolic.svg
+ eye-not-looking-symbolic.svg
pointer-double-click-symbolic.svg
pointer-drag-symbolic.svg
pointer-primary-click-symbolic.svg
diff --git a/data/theme/eye-not-looking-symbolic.svg b/data/theme/eye-not-looking-symbolic.svg
new file mode 100644
index 000000000..a168c87d8
--- /dev/null
+++ b/data/theme/eye-not-looking-symbolic.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/data/theme/eye-open-negative-filled-symbolic.svg b/data/theme/eye-open-negative-filled-symbolic.svg
new file mode 100644
index 000000000..1e5351c99
--- /dev/null
+++ b/data/theme/eye-open-negative-filled-symbolic.svg
@@ -0,0 +1,27 @@
+
+
+
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
index 8d203ada7..d4148306f 100644
--- a/data/theme/gnome-shell-sass/_common.scss
+++ b/data/theme/gnome-shell-sass/_common.scss
@@ -97,6 +97,11 @@ StEntry {
warning-color: $warning_color;
padding: 0 4px;
}
+
+ StIcon.peek-password {
+ icon-size: 1.09em;
+ padding: 0 4px;
+ }
}
diff --git a/src/st/st-password-entry.c b/src/st/st-password-entry.c
index be8c92612..79793d28b 100644
--- a/src/st/st-password-entry.c
+++ b/src/st/st-password-entry.c
@@ -19,6 +19,7 @@
#include "st-private.h"
#include "st-password-entry.h"
+#include "st-icon.h"
#define BLACK_CIRCLE 9679
@@ -34,7 +35,9 @@ struct _StPasswordEntry
struct _StPasswordEntryPrivate
{
+ ClutterActor *peek_password_icon;
gboolean password_visible;
+ gboolean show_peek_icon;
};
enum
@@ -42,6 +45,7 @@ enum
PROP_0,
PROP_PASSWORD_VISIBLE,
+ PROP_SHOW_PEEK_ICON,
N_PROPS
};
@@ -50,6 +54,15 @@ static GParamSpec *props[N_PROPS] = { NULL, };
G_DEFINE_TYPE_WITH_PRIVATE (StPasswordEntry, st_password_entry, ST_TYPE_ENTRY);
+static void
+st_password_entry_secondary_icon_clicked (StEntry *entry)
+{
+ StPasswordEntry *password_entry = ST_PASSWORD_ENTRY (entry);
+ StPasswordEntryPrivate *priv = ST_PASSWORD_ENTRY_PRIV (password_entry);
+
+ st_password_entry_set_password_visible (password_entry, !priv->password_visible);
+}
+
static void
st_password_entry_get_property (GObject *gobject,
guint prop_id,
@@ -63,7 +76,9 @@ st_password_entry_get_property (GObject *gobject,
case PROP_PASSWORD_VISIBLE:
g_value_set_boolean (value, priv->password_visible);
break;
-
+ case PROP_SHOW_PEEK_ICON:
+ g_value_set_boolean (value, priv->show_peek_icon);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
@@ -83,7 +98,9 @@ st_password_entry_set_property (GObject *gobject,
case PROP_PASSWORD_VISIBLE:
st_password_entry_set_password_visible (entry, g_value_get_boolean (value));
break;
-
+ case PROP_SHOW_PEEK_ICON:
+ st_password_entry_set_show_peek_icon (entry, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
@@ -94,16 +111,25 @@ static void
st_password_entry_class_init (StPasswordEntryClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ StEntryClass *st_entry_class = ST_ENTRY_CLASS (klass);
gobject_class->get_property = st_password_entry_get_property;
gobject_class->set_property = st_password_entry_set_property;
+ st_entry_class->secondary_icon_clicked = st_password_entry_secondary_icon_clicked;
+
props[PROP_PASSWORD_VISIBLE] = g_param_spec_boolean ("password-visible",
"Password visible",
"Whether to text in the entry is masked or not",
FALSE,
ST_PARAM_READWRITE);
+ props[PROP_SHOW_PEEK_ICON] = g_param_spec_boolean ("show-peek-icon",
+ "Show peek icon",
+ "Whether to show the password peek icon",
+ TRUE,
+ ST_PARAM_READWRITE);
+
g_object_class_install_properties (gobject_class, N_PROPS, props);
}
@@ -125,10 +151,17 @@ clutter_text_password_char_cb (GObject *object,
static void
st_password_entry_init (StPasswordEntry *entry)
{
+ StPasswordEntryPrivate *priv = ST_PASSWORD_ENTRY_PRIV (entry);
ClutterActor *clutter_text;
st_entry_set_text (ST_ENTRY (entry), "");
+ priv->peek_password_icon = g_object_new (ST_TYPE_ICON,
+ "style-class", "peek-password",
+ "icon-name", "eye-not-looking-symbolic",
+ NULL);
+ st_entry_set_secondary_icon (ST_ENTRY (entry), priv->peek_password_icon);
+
clutter_text = st_entry_get_clutter_text (ST_ENTRY (entry));
clutter_text_set_password_char (CLUTTER_TEXT (clutter_text), BLACK_CIRCLE);
@@ -151,6 +184,50 @@ st_password_entry_new (void)
return ST_ENTRY (g_object_new (ST_TYPE_PASSWORD_ENTRY, NULL));
}
+/**
+ * st_password_entry_set_show_peek_icon:
+ * @entry: a #StPasswordEntry
+ * @value: #TRUE to show the peek-icon in the entry, #FALSE otherwise
+ *
+ * Sets whether to show or hide the peek-icon in the password entry.
+ */
+void
+st_password_entry_set_show_peek_icon (StPasswordEntry *entry, gboolean value)
+{
+ StPasswordEntryPrivate *priv;
+
+ g_return_if_fail (ST_IS_PASSWORD_ENTRY (entry));
+
+ priv = ST_PASSWORD_ENTRY_PRIV (entry);
+ if (priv->show_peek_icon == value)
+ return;
+
+ priv->show_peek_icon = value;
+ if (priv->show_peek_icon)
+ st_entry_set_secondary_icon (ST_ENTRY (entry), priv->peek_password_icon);
+ else
+ st_entry_set_secondary_icon (ST_ENTRY (entry), NULL);
+
+ g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_SHOW_PEEK_ICON]);
+}
+
+/**
+ * st_password_entry_get_show_peek_icon:
+ * @entry: a #StPasswordEntry
+ *
+ * Gets whether peek-icon is shown or hidden in the password entry.
+ */
+gboolean
+st_password_entry_get_show_peek_icon (StPasswordEntry *entry)
+{
+ StPasswordEntryPrivate *priv;
+
+ g_return_val_if_fail (ST_IS_PASSWORD_ENTRY (entry), TRUE);
+
+ priv = ST_PASSWORD_ENTRY_PRIV (entry);
+ return priv->show_peek_icon;
+}
+
/**
* st_password_entry_set_password_visible:
* @entry: a #StPasswordEntry
@@ -174,9 +251,15 @@ st_password_entry_set_password_visible (StPasswordEntry *entry, gboolean value)
clutter_text = st_entry_get_clutter_text (ST_ENTRY (entry));
if (priv->password_visible)
- clutter_text_set_password_char (CLUTTER_TEXT (clutter_text), 0);
+ {
+ clutter_text_set_password_char (CLUTTER_TEXT (clutter_text), 0);
+ st_icon_set_icon_name (ST_ICON (priv->peek_password_icon), "eye-open-negative-filled-symbolic");
+ }
else
- clutter_text_set_password_char (CLUTTER_TEXT (clutter_text), BLACK_CIRCLE);
+ {
+ clutter_text_set_password_char (CLUTTER_TEXT (clutter_text), BLACK_CIRCLE);
+ st_icon_set_icon_name (ST_ICON (priv->peek_password_icon), "eye-not-looking-symbolic");
+ }
g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_PASSWORD_VISIBLE]);
}
diff --git a/src/st/st-password-entry.h b/src/st/st-password-entry.h
index 44dd0b193..399806808 100644
--- a/src/st/st-password-entry.h
+++ b/src/st/st-password-entry.h
@@ -36,6 +36,9 @@ StEntry *st_password_entry_new (void);
gboolean st_password_entry_get_password_visible (StPasswordEntry *entry);
void st_password_entry_set_password_visible (StPasswordEntry *entry,
gboolean value);
+gboolean st_password_entry_get_show_peek_icon (StPasswordEntry *entry);
+void st_password_entry_set_show_peek_icon (StPasswordEntry *entry,
+ gboolean value);
G_END_DECLS