diff --git a/po/POTFILES.in b/po/POTFILES.in index 30868fe69d20ea130b6ba814061738e592df3cfc..cc9a7fc8753efcde687b55512bd00a53d81eb90c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -5,5 +5,6 @@ src/menu.c src/panel.c src/phosh.c src/settings.c +src/ui/lockscreen.ui src/ui/settings-menu.ui src/ui/top-panel.ui diff --git a/po/phosh.pot b/po/phosh.pot index 0f8110154daf65be9c3f591ffd7f3df4427f777c..f2234fe19f387adb830e26f76ff47f038fcad6d1 100644 --- a/po/phosh.pot +++ b/po/phosh.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: phosh\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-01 18:31+0200\n" +"POT-Creation-Date: 2018-04-02 11:39+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/src/lockscreen.c b/src/lockscreen.c index e99b12c3bcb90c0e147835c7ab47a6dbbb83f25e..eaa495289673065ba552b495ebd9f4e308c4f7d6 100644 --- a/src/lockscreen.c +++ b/src/lockscreen.c @@ -5,9 +5,21 @@ */ #include "config.h" - #include "lockscreen.h" +#include <string.h> +#include <glib/gi18n.h> +#include <math.h> + +#define HANDY_USE_UNSTABLE_API +#include <libhandy-0.0/handy.h> + +#define GNOME_DESKTOP_USE_UNSTABLE_API +#include <libgnome-desktop/gnome-wall-clock.h> + +#define TEST_PIN "1234" +#define LOCKSCREEN_IDLE_SECONDS 5 + enum { LOCKSCREEN_UNLOCK, N_SIGNALS @@ -22,18 +34,138 @@ typedef struct _PhoshLockscreen typedef struct PhoshLockscreen { - gint _dummy; + GtkWidget *stack; + + /* info page */ + GtkWidget *ebox_info; + GtkWidget *grid_info; + GtkWidget *lbl_clock; + GtkGesture *ebox_pan_gesture; + + /* unlock page */ + GtkWidget *grid_unlock; + GtkWidget *dialer_keypad; + GtkWidget *lbl_keypad; + GtkWidget *lbl_unlock_status; + guint idle_timer; + gint64 last_input; + + GnomeWallClock *wall_clock; } PhoshLockscreenPrivate; G_DEFINE_TYPE_WITH_PRIVATE (PhoshLockscreen, phosh_lockscreen, GTK_TYPE_WINDOW) -/* FIXME: Temporarily add a button until we interface with pam */ static void -btn_clicked (PhoshLockscreen *lockscreen, - GtkButton *btn) +show_info_page (PhoshLockscreen *self) +{ + PhoshLockscreenPrivate *priv = phosh_lockscreen_get_instance_private (self); + + hdy_dialer_clear_number (HDY_DIALER (priv->dialer_keypad)); + gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->ebox_info); +} + + +static gboolean +keypad_check_idle (PhoshLockscreen *self) +{ + PhoshLockscreenPrivate *priv = phosh_lockscreen_get_instance_private (self); + gint64 now = g_get_monotonic_time (); + + g_assert (PHOSH_IS_LOCKSCREEN (self)); + if (now - priv->last_input > LOCKSCREEN_IDLE_SECONDS * 1000 * 1000) { + show_info_page (self); + priv->idle_timer = 0; + return FALSE; + } + return TRUE; +} + + +static void +show_unlock_page (PhoshLockscreen *self) +{ + PhoshLockscreenPrivate *priv = phosh_lockscreen_get_instance_private (self); + + gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->grid_unlock); + hdy_dialer_set_show_action_buttons (HDY_DIALER (priv->dialer_keypad), FALSE); + if (!priv->idle_timer) { + priv->last_input = g_get_monotonic_time (); + priv->idle_timer = g_timeout_add_seconds (LOCKSCREEN_IDLE_SECONDS, + (GSourceFunc) keypad_check_idle, + self); + } +} + + +static void +keypad_update_labels (PhoshLockscreen *self) +{ + PhoshLockscreenPrivate *priv = phosh_lockscreen_get_instance_private (self); + const gchar *number; + g_autofree gchar *stars = NULL; + + number = hdy_dialer_get_number (HDY_DIALER (priv->dialer_keypad)); + stars = g_strnfill (strlen(number), '*'); + gtk_label_set_label (GTK_LABEL (priv->lbl_keypad), stars); + gtk_label_set_label (GTK_LABEL (priv->lbl_unlock_status), _("Enter PIN to unlock")); +} + + +static void +keypad_number_notified_cb (PhoshLockscreen *self) +{ + PhoshLockscreenPrivate *priv; + const gchar *number; + + g_assert (PHOSH_IS_LOCKSCREEN (self)); + + priv = phosh_lockscreen_get_instance_private (self); + + number = hdy_dialer_get_number (HDY_DIALER (priv->dialer_keypad)); + if (strlen (number) == strlen (TEST_PIN)) { + if (!g_strcmp0 (number, TEST_PIN)) { + /* FIXME: compare to real PIN */ + g_signal_emit(self, signals[LOCKSCREEN_UNLOCK], 0); + } else { + gtk_label_set_label (GTK_LABEL (priv->lbl_unlock_status), _("Wrong PIN")); + hdy_dialer_clear_number (HDY_DIALER (priv->dialer_keypad)); + } + } + priv->last_input = g_get_monotonic_time (); +} + + +static void +keypad_symbol_clicked_cb (PhoshLockscreen *self, gchar symbol, HdyDialer *keypad) +{ + PhoshLockscreenPrivate *priv = phosh_lockscreen_get_instance_private (self); + g_assert (PHOSH_IS_LOCKSCREEN (self)); + g_assert (HDY_IS_DIALER (keypad)); + + keypad_update_labels (self); + priv->last_input = g_get_monotonic_time (); +} + + +static void +info_pan_cb (PhoshLockscreen *self, GtkPanDirection dir, gdouble offset, GtkGesturePan *pan) +{ + if (dir == GTK_PAN_DIRECTION_UP) + show_unlock_page (self); +} + + +static void +wall_clock_notify_cb (PhoshLockscreen *self, + GParamSpec *pspec, + GnomeWallClock *wall_clock) { - g_signal_emit(lockscreen, signals[LOCKSCREEN_UNLOCK], 0); + PhoshLockscreenPrivate *priv = phosh_lockscreen_get_instance_private (self); + const gchar *str; + + str = gnome_wall_clock_get_clock(wall_clock); + gtk_label_set_text (GTK_LABEL (priv->lbl_clock), str); } @@ -41,9 +173,7 @@ static void phosh_lockscreen_constructed (GObject *object) { PhoshLockscreen *self = PHOSH_LOCKSCREEN (object); - GtkWidget *grid; - GtkWidget *button; - GtkWidget *label; + PhoshLockscreenPrivate *priv = phosh_lockscreen_get_instance_private (self); GdkDisplay *display = gdk_display_get_default (); /* There's no primary monitor on nested wayland so just use the @@ -66,15 +196,37 @@ phosh_lockscreen_constructed (GObject *object) gtk_widget_get_style_context (GTK_WIDGET (self)), "phosh-lockscreen"); - grid = gtk_widget_new (GTK_TYPE_GRID, "halign", GTK_ALIGN_CENTER, "valign", GTK_ALIGN_CENTER, NULL); - gtk_container_add (GTK_CONTAINER (self), grid); + gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->ebox_info); + + priv->ebox_pan_gesture = gtk_gesture_pan_new (GTK_WIDGET (priv->ebox_info), + GTK_ORIENTATION_VERTICAL); + + g_signal_connect_swapped (priv->ebox_pan_gesture, + "pan", + G_CALLBACK (info_pan_cb), + self); + + priv->wall_clock = g_object_new (GNOME_TYPE_WALL_CLOCK, NULL); + g_signal_connect_swapped (priv->wall_clock, + "notify::clock", + G_CALLBACK (wall_clock_notify_cb), + self); + wall_clock_notify_cb (self, NULL, priv->wall_clock); +} + +static void +phosh_lockscreen_dispose (GObject *object) +{ + PhoshLockscreen *self = PHOSH_LOCKSCREEN (object); + PhoshLockscreenPrivate *priv = phosh_lockscreen_get_instance_private (self); + + g_clear_object (&priv->wall_clock); + if (priv->idle_timer) { + g_source_remove (priv->idle_timer); + priv->idle_timer = 0; + } - /* FIXME: just a button for now */ - label = gtk_label_new("Click to unlock desktop"); - button = gtk_button_new_from_icon_name ("face-surprise-symbolic", GTK_ICON_SIZE_DIALOG); - gtk_grid_attach (GTK_GRID (grid), label, 2, 1, 1, 1); - gtk_grid_attach (GTK_GRID (grid), button, 2, 3, 1, 1); - g_signal_connect_swapped (button, "clicked", G_CALLBACK (btn_clicked), self); + G_OBJECT_CLASS (phosh_lockscreen_parent_class)->dispose (object); } @@ -82,18 +234,43 @@ static void phosh_lockscreen_class_init (PhoshLockscreenClass *klass) { GObjectClass *object_class = (GObjectClass *)klass; + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->constructed = phosh_lockscreen_constructed; + object_class->dispose = phosh_lockscreen_dispose; signals[LOCKSCREEN_UNLOCK] = g_signal_new ("lockscreen-unlock", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); + + gtk_widget_class_set_template_from_resource (widget_class, + "/sm/puri/phosh/ui/lockscreen.ui"); + gtk_widget_class_bind_template_child_private (widget_class, PhoshLockscreen, stack); + + /* unlock page */ + gtk_widget_class_bind_template_child_private (widget_class, PhoshLockscreen, grid_unlock); + gtk_widget_class_bind_template_child_private (widget_class, PhoshLockscreen, dialer_keypad); + gtk_widget_class_bind_template_child_private (widget_class, PhoshLockscreen, lbl_keypad); + gtk_widget_class_bind_template_child_private (widget_class, PhoshLockscreen, lbl_unlock_status); + gtk_widget_class_bind_template_callback_full (widget_class, + "keypad_symbol_clicked_cb", + G_CALLBACK(keypad_symbol_clicked_cb)); + gtk_widget_class_bind_template_callback_full (widget_class, + "keypad_number_notified_cb", + G_CALLBACK(keypad_number_notified_cb)); + + + /* info page */ + gtk_widget_class_bind_template_child_private (widget_class, PhoshLockscreen, ebox_info); + gtk_widget_class_bind_template_child_private (widget_class, PhoshLockscreen, grid_info); + gtk_widget_class_bind_template_child_private (widget_class, PhoshLockscreen, lbl_clock); } static void phosh_lockscreen_init (PhoshLockscreen *self) { + gtk_widget_init_template (GTK_WIDGET (self)); } diff --git a/src/meson.build b/src/meson.build index 4ab6cf6e2a2ebb0a42f739c21e312ae6293a1d52..4de256def3ef3b47668a05b6c9c105e3c032a125 100644 --- a/src/meson.build +++ b/src/meson.build @@ -51,6 +51,7 @@ phosh_deps = [ dependency('gtk+-3.0'), dependency('gtk+-wayland-3.0'), dependency('wayland-client'), + dependency('libhandy-0.0'), cc.find_library('m', required: false), cc.find_library('rt', required: false), ] diff --git a/src/phosh.c b/src/phosh.c index ebc72238480dbf6d27f7387e7ae3e6fa9f948cea..75b4724975e80c4f74abd49b7e4a91d3a23d9416 100644 --- a/src/phosh.c +++ b/src/phosh.c @@ -32,7 +32,7 @@ #include "settings.h" /* FIXME: use org.gnome.desktop.session.idle-delay */ -#define LOCKSCREEN_TIMEOUT 60 * 1000 +#define LOCKSCREEN_TIMEOUT 300 * 1000 enum { PHOSH_SHELL_PROP_0, @@ -837,7 +837,6 @@ int main(int argc, char *argv[]) textdomain (GETTEXT_PACKAGE); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - gtk_init (&argc, &argv); g_object_new (PHOSH_TYPE_SHELL, NULL); diff --git a/src/phosh.gresources.xml b/src/phosh.gresources.xml index d633fa2618ae9f2769073544c29eb94a759f2f75..ce08d73a465b2186ce01b9d7878150f64e4d1369 100644 --- a/src/phosh.gresources.xml +++ b/src/phosh.gresources.xml @@ -1,8 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <gresources> <gresource prefix="/sm/puri/phosh"> - <file preprocess="xml-stripblanks">ui/top-panel.ui</file> + <file preprocess="xml-stripblanks">ui/lockscreen.ui</file> <file preprocess="xml-stripblanks">ui/settings-menu.ui</file> + <file preprocess="xml-stripblanks">ui/top-panel.ui</file> <file compressed="true">style.css</file> </gresource> </gresources> diff --git a/src/ui/lockscreen.ui b/src/ui/lockscreen.ui new file mode 100644 index 0000000000000000000000000000000000000000..a8cf178a77772ca05db27b591f2211bb433a057f --- /dev/null +++ b/src/ui/lockscreen.ui @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.0 --> +<interface> + <requires lib="gtk+" version="3.20"/> + <requires lib="libhandy" version="0.0"/> + <template class="PhoshLockscreen" parent="GtkWindow"> + <property name="can_focus">False</property> + <child> + <object class="GtkStack" id="stack"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="transition_duration">500</property> + <property name="transition_type">slide-up</property> + <child> + <object class="GtkGrid" id="grid_unlock"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <child> + <object class="GtkLabel" id="lbl_keypad"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">10</property> + <property name="margin_bottom">10</property> + <attributes> + <attribute name="font-desc" value="Cantarell Bold 16"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="HdyDialer" id="dialer_keypad"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="margin_top">12</property> + <property name="margin_bottom">12</property> + <signal name="symbol-clicked" handler="keypad_symbol_clicked_cb" swapped="yes"/> + <signal name="notify::number" handler="keypad_number_notified_cb" swapped="yes"/> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="lbl_unlock_status"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">10</property> + <property name="margin_bottom">10</property> + <property name="label" translatable="yes">Enter PIN to unlock</property> + <attributes> + <attribute name="font-desc" value="Cantarell 16"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + </object> + <packing> + <property name="name">unlock</property> + <property name="title">unlock</property> + </packing> + </child> + <child> + <object class="GtkEventBox" id="ebox_info"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="above_child">True</property> + <child> + <object class="GtkGrid" id="grid_info"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="lbl_clock"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="label">00:00</property> + <property name="single_line_mode">True</property> + <property name="track_visited_links">False</property> + <attributes> + <attribute name="font-desc" value="Cantarell 64"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Slide up to unlock</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="name">info</property> + <property name="title">info</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <child type="titlebar"> + <placeholder/> + </child> + </template> +</interface>