[libadwaita/entry-row: 3/5] Add AdwPasswordEntryRow
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/entry-row: 3/5] Add AdwPasswordEntryRow
- Date: Fri, 22 Apr 2022 11:12:39 +0000 (UTC)
commit 1833f42581469850408555ffa53cb42557924648
Author: Maximiliano Sandoval R <msandova protonmail com>
Date: Sun Jul 25 17:07:51 2021 +0200
Add AdwPasswordEntryRow
doc/boxed-lists.md | 11 ++
doc/images/password-entry-row-dark.png | Bin 0 -> 2264 bytes
doc/images/password-entry-row.png | Bin 0 -> 2695 bytes
doc/libadwaita.toml.in | 2 +
doc/tools/data/password-entry-row.ui | 23 +++++
doc/visual-index.md | 7 ++
po/POTFILES.in | 1 +
src/adw-password-entry-row.c | 182 +++++++++++++++++++++++++++++++++
src/adw-password-entry-row.h | 29 ++++++
src/adwaita.h | 1 +
src/meson.build | 2 +
11 files changed, 258 insertions(+)
---
diff --git a/doc/boxed-lists.md b/doc/boxed-lists.md
index d2c45049..6c9b912e 100644
--- a/doc/boxed-lists.md
+++ b/doc/boxed-lists.md
@@ -88,6 +88,17 @@ widgets, and an apply button.
<img src="entry-row.png" alt="entry-row">
</picture>
+## Password Entry Rows
+
+[class@PasswordEntryRow] is a variant of [class@EntryRow] tailored for entering
+secrets. It conceals the text and provides a button to show it, along with a
+<kbd>Caps Lock</kbd> indicator.
+
+<picture>
+ <source srcset="password-entry-row-dark.png" media="(prefers-color-scheme: dark)">
+ <img src="password-entry-row.png" alt="password-entry-row">
+</picture>
+
## Preferences Group
[class@PreferencesGroup] provides a boxed list along with a title and a
diff --git a/doc/images/password-entry-row-dark.png b/doc/images/password-entry-row-dark.png
new file mode 100644
index 00000000..a7f4b00e
Binary files /dev/null and b/doc/images/password-entry-row-dark.png differ
diff --git a/doc/images/password-entry-row.png b/doc/images/password-entry-row.png
new file mode 100644
index 00000000..6e73115d
Binary files /dev/null and b/doc/images/password-entry-row.png differ
diff --git a/doc/libadwaita.toml.in b/doc/libadwaita.toml.in
index a80efa7c..76ae6c2d 100644
--- a/doc/libadwaita.toml.in
+++ b/doc/libadwaita.toml.in
@@ -154,6 +154,8 @@ content_images = [
"images/osd-progress-bar-dark.png",
"images/osd-toolbar.png",
"images/osd-toolbar-dark.png",
+ "images/password-entry-row.png",
+ "images/password-entry-row-dark.png",
"images/popover-menu-list.png",
"images/popover-menu-list-dark.png",
"images/preferences-group.png",
diff --git a/doc/tools/data/password-entry-row.ui b/doc/tools/data/password-entry-row.ui
new file mode 100644
index 00000000..cbd82ac9
--- /dev/null
+++ b/doc/tools/data/password-entry-row.ui
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <requires lib="libadwaita" version="1.0"/>
+ <object class="GtkListBox" id="widget">
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="selection-mode">none</property>
+ <property name="width-request">400</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="AdwPasswordEntryRow">
+ <property name="title">Title</property>
+ <property name="text">A long password</property>
+ <property name="can-focus">False</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/doc/visual-index.md b/doc/visual-index.md
index 30d6b3ed..b2597403 100644
--- a/doc/visual-index.md
+++ b/doc/visual-index.md
@@ -56,6 +56,13 @@ Slug: visual-index
<img src="entry-row.png" alt="entry-row">
</picture>](class.EntryRow.html)
+### Password Entry Row
+
+[<picture>
+ <source srcset="password-entry-row-dark.png" media="(prefers-color-scheme: dark)">
+ <img src="password-entry-row.png" alt="password-entry-row">
+</picture>](class.PasswordEntryRow.html)
+
## Preferences
### Preferences Group
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 29355757..31db95b2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,5 +3,6 @@
src/adw-entry-row.ui
src/adw-inspector-page.c
src/adw-inspector-page.ui
+src/adw-password-entry-row.c
src/adw-preferences-window.c
src/adw-preferences-window.ui
diff --git a/src/adw-password-entry-row.c b/src/adw-password-entry-row.c
new file mode 100644
index 00000000..881dfe50
--- /dev/null
+++ b/src/adw-password-entry-row.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2021 Maximiliano Sandoval <msandova protonmail com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include "adw-password-entry-row.h"
+
+#include "adw-entry-row-private.h"
+#include "adw-macros-private.h"
+
+/**
+ * AdwPasswordEntryRow:
+ *
+ * A [class@Gtk.ListBoxRow] tailored for entering secrets inside a list.
+ *
+ * <picture>
+ * <source srcset="password-entry-row-dark.png" media="(prefers-color-scheme: dark)">
+ * <img src="password-entry-row.png" alt="password-entry-row">
+ * </picture>
+ *
+ * It does not show its contents in clear text, does not allow to copy it to the
+ * clipboard, and it shows a warning when Caps Lock is engaged. If the
+ * underlying platform allows it, `AdwPasswordEntryRow` will also place the text
+ * in a non-pageable memory area, to avoid it being written out to disk by the
+ * operating system.
+ *
+ * Optionally, it can offer a way to reveal the contents in clear text.
+ *
+ * `AdwPasswordEntryRow` provides only minimal API and should be used with the
+ * [iface@Gtk.Editable] API.
+ *
+ * # CSS Nodes
+ *
+ * `AdwPasswordEntryRow` has a single CSS node with name row that carries a
+ * `.password` style class. The text CSS node below it has a child with name
+ * `image` and style class `.caps-lock-indicator` for the Caps Lock icon, and
+ * possibly other children.
+ *
+ * Since: 1.2
+ */
+
+struct _AdwPasswordEntryRow
+{
+ AdwEntryRow parent_instance;
+
+ GtkWidget *show_text_toggle;
+
+ GdkDevice *keyboard;
+};
+
+G_DEFINE_FINAL_TYPE (AdwPasswordEntryRow, adw_password_entry_row, ADW_TYPE_ENTRY_ROW)
+
+static void
+update_caps_lock (AdwPasswordEntryRow *self)
+{
+ GtkEditable *delegate = gtk_editable_get_delegate (GTK_EDITABLE (self));
+
+ adw_entry_row_set_show_indicator (ADW_ENTRY_ROW (self),
+ !gtk_text_get_visibility (GTK_TEXT (delegate)) &&
+ gdk_device_get_caps_lock_state (self->keyboard));
+}
+
+static void
+notify_visibility_cb (AdwPasswordEntryRow *self)
+{
+ GtkEditable *delegate = gtk_editable_get_delegate (GTK_EDITABLE (self));
+
+ if (gtk_text_get_visibility (GTK_TEXT (delegate))) {
+ gtk_button_set_icon_name (GTK_BUTTON (self->show_text_toggle),
+ "eye-open-negative-filled-symbolic");
+ gtk_widget_set_tooltip_text (self->show_text_toggle, _("Hide Text"));
+ } else {
+ gtk_button_set_icon_name (GTK_BUTTON (self->show_text_toggle),
+ "eye-not-looking-symbolic");
+ gtk_widget_set_tooltip_text (self->show_text_toggle, _("Show Text"));
+ }
+
+ if (self->keyboard)
+ update_caps_lock (self);
+}
+
+static void
+notify_has_focus_cb (AdwPasswordEntryRow *self)
+{
+ if (self->keyboard)
+ update_caps_lock (self);
+}
+
+static void
+adw_password_entry_row_realize (GtkWidget *widget)
+{
+ AdwPasswordEntryRow *self = ADW_PASSWORD_ENTRY_ROW (widget);
+ GdkSeat *seat;
+
+ GTK_WIDGET_CLASS (adw_password_entry_row_parent_class)->realize (widget);
+
+ seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
+ if (seat)
+ self->keyboard = gdk_seat_get_keyboard (seat);
+
+ if (self->keyboard) {
+ g_signal_connect_swapped (self->keyboard, "notify::caps-lock-state",
+ G_CALLBACK (update_caps_lock), self);
+ update_caps_lock (self);
+ }
+}
+
+static void
+adw_password_entry_row_dispose (GObject *object)
+{
+ AdwPasswordEntryRow *self = ADW_PASSWORD_ENTRY_ROW (object);
+
+ if (self->keyboard)
+ g_signal_handlers_disconnect_by_func (self->keyboard, update_caps_lock, self);
+
+ G_OBJECT_CLASS (adw_password_entry_row_parent_class)->dispose (object);
+}
+
+static void
+adw_password_entry_row_class_init (AdwPasswordEntryRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = adw_password_entry_row_dispose;
+
+ widget_class->realize = adw_password_entry_row_realize;
+}
+
+static void
+adw_password_entry_row_init (AdwPasswordEntryRow *self)
+{
+ GtkEditable *delegate;
+
+ self->show_text_toggle = gtk_toggle_button_new ();
+ gtk_widget_set_valign (self->show_text_toggle, GTK_ALIGN_CENTER);
+ gtk_widget_set_focus_on_click (self->show_text_toggle, FALSE);
+ gtk_widget_add_css_class (self->show_text_toggle, "flat");
+ adw_entry_row_add_suffix (ADW_ENTRY_ROW (self), self->show_text_toggle);
+
+ delegate = gtk_editable_get_delegate (GTK_EDITABLE (self));
+
+ g_assert (GTK_IS_TEXT (delegate));
+
+ gtk_text_set_visibility (GTK_TEXT (delegate), FALSE);
+ gtk_text_set_buffer (GTK_TEXT (delegate), gtk_password_entry_buffer_new ());
+
+ g_signal_connect_swapped (delegate, "notify::has-focus",
+ G_CALLBACK (notify_has_focus_cb), self);
+ g_signal_connect_swapped (delegate, "notify::visibility",
+ G_CALLBACK (notify_visibility_cb), self);
+ g_object_bind_property (self->show_text_toggle, "active",
+ delegate, "visibility",
+ G_BINDING_SYNC_CREATE);
+
+ adw_entry_row_set_indicator_icon_name (ADW_ENTRY_ROW (self), "caps-lock-symbolic");
+ adw_entry_row_set_indicator_tooltip (ADW_ENTRY_ROW (self), _("Caps Lock is on"));
+
+ gtk_widget_add_css_class (GTK_WIDGET (self), "password");
+
+ notify_visibility_cb (self);
+
+}
+
+/**
+ * adw_password_entry_row_new:
+ *
+ * Creates a new `AdwPasswordEntryRow`.
+ *
+ * Returns: the newly created `AdwPasswordEntryRow`
+ *
+ * Since: 1.2
+ */
+GtkWidget *
+adw_password_entry_row_new (void)
+{
+ return g_object_new (ADW_TYPE_PASSWORD_ENTRY_ROW, NULL);
+}
diff --git a/src/adw-password-entry-row.h b/src/adw-password-entry-row.h
new file mode 100644
index 00000000..4b9623c7
--- /dev/null
+++ b/src/adw-password-entry-row.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 Maximiliano Sandoval <msandova protonmail com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION)
+#error "Only <adwaita.h> can be included directly."
+#endif
+
+#include "adw-version.h"
+
+#include <gtk/gtk.h>
+
+#include "adw-entry-row.h"
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_PASSWORD_ENTRY_ROW (adw_password_entry_row_get_type())
+
+ADW_AVAILABLE_IN_1_2
+G_DECLARE_FINAL_TYPE (AdwPasswordEntryRow, adw_password_entry_row, ADW, PASSWORD_ENTRY_ROW, AdwEntryRow)
+
+ADW_AVAILABLE_IN_1_2
+GtkWidget *adw_password_entry_row_new (void) G_GNUC_WARN_UNUSED_RESULT;
+
+G_END_DECLS
diff --git a/src/adwaita.h b/src/adwaita.h
index 2cb03ee1..aa1ca1da 100644
--- a/src/adwaita.h
+++ b/src/adwaita.h
@@ -48,6 +48,7 @@ G_BEGIN_DECLS
#include "adw-leaflet.h"
#include "adw-main.h"
#include "adw-navigation-direction.h"
+#include "adw-password-entry-row.h"
#include "adw-preferences-group.h"
#include "adw-preferences-page.h"
#include "adw-preferences-row.h"
diff --git a/src/meson.build b/src/meson.build
index 886d3edd..0f6c5217 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -107,6 +107,7 @@ src_headers = [
'adw-leaflet.h',
'adw-main.h',
'adw-navigation-direction.h',
+ 'adw-password-entry-row.h',
'adw-preferences-group.h',
'adw-preferences-page.h',
'adw-preferences-row.h',
@@ -168,6 +169,7 @@ src_sources = [
'adw-leaflet.c',
'adw-main.c',
'adw-navigation-direction.c',
+ 'adw-password-entry-row.c',
'adw-preferences-group.c',
'adw-preferences-page.c',
'adw-preferences-row.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]