2009-03-19 Alejandro G. Castro <alex@igalia.com>
[hildon] / src / hildon-code-dialog.c
index 9a53ff1..c886590 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * This file is part of hildon-libs
+ * This file is a part of hildon
  *
  * Copyright (C) 2006 Nokia Corporation, all rights reserved.
  *
- * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
+ * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
  * as published by the Free Software Foundation; version 2.1 of
- * the License.
+ * the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  *
  */
 
+/**
+ * SECTION:hildon-code-dialog
+ * @short_description: A keypad-like widget used to enter pincodes.
+ *
+ * #HildonCodeDialog displays a keypad that can be used to enter 
+ * numerical pin codes or lock codes. It emits a 'input' signal each time 
+ * an input action is performed on the dialog.
+ *
+ */
 
-#include "hildon-code-dialog.h"
-#include "hildon-defines.h"
-#include "hildon-banner.h"
-
-#include <gdk/gdkkeysyms.h>
+/* FIXME We need property access in this widget */
 
-#include<gtk/gtkbutton.h>
-#include<gtk/gtkentry.h>
-#include<gtk/gtkicontheme.h>
-#include<gtk/gtktable.h>
-#include<gtk/gtkvbox.h>
-#include<gtk/gtkbbox.h>
-#include<gtk/gtklabel.h>
-#include<gtk/gtkalignment.h>
+#undef                                          HILDON_DISABLE_DEPRECATED
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
+#ifdef                                          HAVE_CONFIG_H
+#include                                        <config.h>
 #endif
 
-#include <libintl.h>
+#include                                        <libintl.h>
+#include                                        <gdk/gdkkeysyms.h>
+
+#include                                        "hildon-code-dialog.h"
+#include                                        "hildon-defines.h"
+#include                                        "hildon-banner.h"
+#include                                        "hildon-code-dialog-private.h"
+
+#define                                         HEIGHT (48-HILDON_MARGIN_DEFAULT)
 
-#define HEIGHT (38-HILDON_MARGIN_DEFAULT)
-#define WIDTH  (60-HILDON_MARGIN_DEFAULT)
-#define BACKSPACE_ICON    "qgn_calculator_backspace"
+#define                                         WIDTH  (100-HILDON_MARGIN_DEFAULT)
 
-#define _(String)  dgettext(PACKAGE, String)
-#define c_(String) dgettext("hildon-common-strings", String)
-#define DEVICELOCK_OK               _("secu_enter_lock_code_dialog_ok")
-#define DEVICELOCK_CANCEL           _("secu_enter_lock_code_dialog_cancel")
-#define DEVICELOCK_TITLE            _("secu_application_title")
-#define DEVICELOCK_MAX_CHAR_REACHED c_("ckdg_ib_maximum_characters_reached")
+#define                                         BACKSPACE_ICON "general_backspace"
+
+#define                                         _(String) \
+                                                dgettext("hildon-libs", String)
+
+#define                                         c_(String) \
+                                                dgettext("hildon-common-strings", String)
+
+#define                                         DEVICELOCK_OK _("wdgt_bd_done")
+
+#define                                         DEVICELOCK_TITLE _("secu_application_title")
+
+#define                                         DEVICELOCK_MAX_CHAR_REACHED c_("ckdg_ib_maximum_characters_reached")
         
+#define                                         MAX_PINCODE_LEN (10)
 
+static void 
+hildon_code_dialog_class_init                   (HildonCodeDialogClass *cd_class);
 
-#define MAX_PINCODE_LEN   (10)
+static void 
+hildon_code_dialog_init                         (HildonCodeDialog *self);
 
+static void
+hildon_code_dialog_realize                      (GtkWidget *widget);
 
+static void
+hildon_code_dialog_unrealize                    (GtkWidget *widget);
 
-static void hildon_code_dialog_class_init (HildonCodeDialogClass *cd_class);
-static void hildon_code_dialog_init (HildonCodeDialog *self);
-static void hildon_code_dialog_finalize (GObject *self);
-static void hildon_code_dialog_button_clicked (GtkButton *buttonm,
-                                               gpointer user_data);
-static void hildon_code_dialog_insert_text (GtkEditable *editable,
-                                            gchar *new_text,
-                                            gint new_text_length,
-                                            gint *position,
-                                            gpointer user_data);
+static void
+hildon_code_dialog_finalize                     (GObject *object);
 
-static gboolean hildon_code_dialog_key_press_event (GtkWidget *widget,
-                                                    GdkEventKey *event,
-                                                    gpointer user_data);
+static void 
+hildon_code_dialog_button_clicked               (GtkButton *buttonm,
+                                                 gpointer user_data);
 
+static void
+hildon_code_dialog_backspace                    (HildonCodeDialog *dialog);
 
-GtkDialogClass *parent_class;
+static void
+hildon_code_dialog_im_commit                    (GtkIMContext *im_context,
+                                                 gchar *utf8,
+                                                 gpointer user_data);
 
-struct _HildonCodeDialogPrivate
-{
-    GtkWidget *entry;
-    GtkWidget *buttons[5][3]; 
-    GtkWidget *help_text;
-};
+static void 
+hildon_code_dialog_insert_text                  (GtkEditable *editable,
+                                                 gchar *new_text,
+                                                 gint new_text_length,
+                                                 gint *position,
+                                                 gpointer user_data);
+
+static gboolean 
+hildon_code_dialog_key_press_event              (GtkWidget *widget,
+                                                 GdkEventKey *event,
+                                                 gpointer user_data);
 
-GType hildon_code_dialog_get_type (void)
+static void 
+hildon_code_dialog_real_input                   (HildonCodeDialog *dialog);
+
+static void
+hildon_code_dialog_input                        (HildonCodeDialog *dialog);
+
+static GtkDialogClass*                          parent_class = NULL;
+
+static guint                                    input_signal;
+
+/**
+ * hildon_code_dialog_get_type:
+ *
+ * Initializes and returns the type of a hildon code dialog.
+ *
+ * Returns: GType of #HildonCodeDialog
+ */
+GType G_GNUC_CONST
+hildon_code_dialog_get_type                     (void)
 {
     static GType type = 0;
 
@@ -94,13 +133,13 @@ GType hildon_code_dialog_get_type (void)
     {
         static const GTypeInfo info = 
         {
-            sizeof(HildonCodeDialogClass),
+            sizeof (HildonCodeDialogClass),
             NULL, /* base_init */
             NULL, /* base_finalize */
             (GClassInitFunc) hildon_code_dialog_class_init,
             NULL,       /* class_finalize */
             NULL,       /* class_data */
-            sizeof(HildonCodeDialog),
+            sizeof (HildonCodeDialog),
             0,  /* n_preallocs */
             (GInstanceInitFunc) hildon_code_dialog_init
         };
@@ -110,18 +149,35 @@ GType hildon_code_dialog_get_type (void)
     return type;
 }
 
-static void hildon_code_dialog_class_init (HildonCodeDialogClass *cd_class)
+static void
+hildon_code_dialog_class_init                   (HildonCodeDialogClass *cd_class)
 {
-    /* Get convenience variables */
-    GObjectClass *object_class = G_OBJECT_CLASS (cd_class);
+    GObjectClass *gobject_class = G_OBJECT_CLASS (cd_class);
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (cd_class);
 
     parent_class = GTK_DIALOG_CLASS (g_type_class_peek_parent (cd_class));
+    g_type_class_add_private (cd_class, sizeof (HildonCodeDialogPrivate));
+
+    gobject_class->finalize = hildon_code_dialog_finalize;
 
-    object_class->finalize = hildon_code_dialog_finalize;
+    widget_class->realize = hildon_code_dialog_realize;
+    widget_class->unrealize = hildon_code_dialog_unrealize;
 
+    cd_class->input = hildon_code_dialog_real_input;
+
+    /* FIXME Document this signal! */
+    input_signal = g_signal_new("input",
+                                HILDON_TYPE_CODE_DIALOG,
+                                G_SIGNAL_RUN_LAST,
+                                G_STRUCT_OFFSET (HildonCodeDialogClass, input),
+                                NULL, NULL,
+                                g_cclosure_marshal_VOID__VOID,
+                                G_TYPE_NONE,
+                                0);
 }
 
-static void hildon_code_dialog_init (HildonCodeDialog *dialog)
+static void 
+hildon_code_dialog_init                         (HildonCodeDialog *dialog)
 {
     HildonCodeDialogPrivate *priv;
     gint i, x, y;
@@ -133,11 +189,10 @@ static void hildon_code_dialog_init (HildonCodeDialog *dialog)
     GtkWidget *dialog_action_area1 = NULL;
     GdkGeometry hints;
     GtkWidget *okButton;
-    GtkWidget *cancelButton;
-
-    priv = dialog->priv = (HildonCodeDialogPrivate*) g_malloc0 
-        (sizeof (HildonCodeDialogPrivate));
 
+    priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    g_assert (priv);
+    
     const gchar* numstrs[10] = {
         "0","1","2","3","4","5","6","7","8","9"
     };
@@ -145,20 +200,20 @@ static void hildon_code_dialog_init (HildonCodeDialog *dialog)
     GdkPixbuf* pixbuf = NULL;
     GtkIconTheme* icon_theme = NULL;
     GtkIconInfo *icon_info = NULL;
-    gint base_size=0;
+    gint base_size = 0;
 
     /* Set default title */
     gtk_window_set_title (GTK_WINDOW (dialog), DEVICELOCK_TITLE);
 
-    gtk_window_set_type_hint(GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
+    gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
+    gtk_dialog_set_has_separator ((GtkDialog *) dialog, FALSE);
 
     hints.min_width  = -1;
     hints.min_height = -1;
     hints.max_width  = -1;
     hints.max_height = -1;
 
-    gtk_window_set_geometry_hints(GTK_WINDOW(dialog), GTK_WIDGET(dialog), 
-            &hints,
+    gtk_window_set_geometry_hints (GTK_WINDOW (dialog), GTK_WIDGET (dialog), &hints,
             GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
 
     table = gtk_table_new (4, 3, FALSE);
@@ -167,101 +222,110 @@ static void hildon_code_dialog_init (HildonCodeDialog *dialog)
 
     dialog_vbox1 = GTK_DIALOG (dialog)->vbox;
     vbox1 = gtk_vbox_new (FALSE, 0);
-    gtk_box_set_spacing (GTK_BOX(vbox1),HILDON_MARGIN_DOUBLE);
+    gtk_box_set_spacing (GTK_BOX (vbox1), HILDON_MARGIN_DOUBLE);
 
-    priv->help_text= gtk_label_new ("");
-    alignment=gtk_alignment_new(0.5,0,1,1);
-    gtk_container_add(GTK_CONTAINER(alignment),priv->help_text);
+    priv->help_text = gtk_label_new ("");
+    alignment = gtk_alignment_new (0.5,0,1,1);
+    gtk_container_add (GTK_CONTAINER (alignment), priv->help_text);
 
     priv->entry = gtk_entry_new ();
     
-    GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(priv->entry),GTK_CAN_FOCUS);
-    gtk_entry_set_invisible_char (GTK_ENTRY(priv->entry), g_utf8_get_char ("*"));
-    gtk_entry_set_alignment (GTK_ENTRY(priv->entry),1.0);
-
-    gtk_editable_set_editable (GTK_EDITABLE(priv->entry),FALSE);
-    gtk_entry_set_visibility (GTK_ENTRY(priv->entry), FALSE);
+    GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->entry), GTK_CAN_FOCUS);
+    gtk_entry_set_invisible_char (GTK_ENTRY (priv->entry), g_utf8_get_char ("*"));
+    gtk_entry_set_alignment (GTK_ENTRY (priv->entry), 1.0);
 
-    gtk_box_pack_start (GTK_BOX (vbox1),alignment,TRUE,FALSE,0);
-    gtk_box_pack_start (GTK_BOX (vbox1),priv->entry,TRUE,FALSE,0);
-    gtk_box_pack_start (GTK_BOX (vbox1),table,FALSE,TRUE,0);
+    gtk_editable_set_editable (GTK_EDITABLE (priv->entry),FALSE);
+    gtk_entry_set_visibility (GTK_ENTRY (priv->entry), FALSE);
 
-    gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox1,FALSE,TRUE,0);
+    gtk_box_pack_start (GTK_BOX (vbox1), alignment, TRUE,FALSE,0);
+    gtk_box_pack_start (GTK_BOX (vbox1), priv->entry, TRUE,FALSE,0);
+    gtk_box_pack_start (GTK_BOX (vbox1), table, FALSE,TRUE,0);
 
+    gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox1, FALSE,TRUE,0);
 
-    for(i=1;i<=3;i++) {
-        priv->buttons[0][i-1] = gtk_button_new_with_mnemonic(numstrs[i]);
-        gtk_widget_set_size_request(priv->buttons[0][i-1],WIDTH,HEIGHT);
-        gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[0][i-1],
-                i-1,i,0,1);
+    for(i = 1;i <= 3; i++) {
+        priv->buttons[0][i-1] = gtk_button_new_with_mnemonic (numstrs[i]);
+        gtk_widget_set_size_request (priv->buttons[0][i-1], WIDTH, HEIGHT);
+        gtk_table_attach_defaults (GTK_TABLE (table), priv->buttons[0][i-1],
+                i-1, i, 0, 1);
     }
 
-    for(i=4;i<=6;i++) {
+    for(i = 4;i <= 6;i++) {
         priv->buttons[1][i-4] = gtk_button_new_with_mnemonic (numstrs[i]);
-        gtk_widget_set_size_request(priv->buttons[1][i-4],WIDTH,HEIGHT);
-        gtk_table_attach_defaults(GTK_TABLE(table),priv->buttons[1][i-4],
-                i-4,i-3,1,2);
+        gtk_widget_set_size_request (priv->buttons[1][i-4], WIDTH, HEIGHT);
+        gtk_table_attach_defaults (GTK_TABLE (table), priv->buttons[1][i-4],
+                i-4, i-3, 1, 2);
     }
 
     for(i=7;i<=9;i++) {
         priv->buttons[2][i-7] = gtk_button_new_with_mnemonic (numstrs[i]);
-        gtk_widget_set_size_request(priv->buttons[2][i-7], WIDTH,HEIGHT);
-        gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[2][i-7],
-                i-7,i-6,2,3);
+        gtk_widget_set_size_request (priv->buttons[2][i-7], WIDTH, HEIGHT);
+        gtk_table_attach_defaults (GTK_TABLE (table), priv->buttons[2][i-7],
+                i-7, i-6, 2, 3);
     }
 
     priv->buttons[3][0] = priv->buttons[3][1] = 
         gtk_button_new_with_mnemonic (numstrs[0]);
-    gtk_widget_set_size_request (priv->buttons[3][0], WIDTH,HEIGHT);
-    gtk_table_attach (GTK_TABLE(table), priv->buttons[3][0],
+    gtk_widget_set_size_request (priv->buttons[3][0], WIDTH, HEIGHT);
+    gtk_table_attach (GTK_TABLE (table), priv->buttons[3][0],
             0,2,3,4, (GtkAttachOptions) (GTK_FILL),
             (GtkAttachOptions) (0), 0, 0);
 
     priv->buttons[3][2] = gtk_button_new ();
-    gtk_widget_set_size_request(priv->buttons[3][2], WIDTH,HEIGHT);
-    gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[3][2],
-            2,3,3,4);
+    gtk_widget_set_size_request (priv->buttons[3][2], WIDTH, HEIGHT);
+    gtk_table_attach_defaults (GTK_TABLE (table), priv->buttons[3][2],
+            2, 3, 3, 4);
 
     icon_theme = gtk_icon_theme_get_default ();
 
-    icon_info = gtk_icon_theme_lookup_icon(icon_theme, BACKSPACE_ICON, 1,
+    icon_info = gtk_icon_theme_lookup_icon (icon_theme, BACKSPACE_ICON, 1,
             GTK_ICON_LOOKUP_NO_SVG);
-    base_size = gtk_icon_info_get_base_size(icon_info);
-    gtk_icon_info_free(icon_info);
+    base_size = gtk_icon_info_get_base_size (icon_info);
+    gtk_icon_info_free (icon_info);
     icon_info = NULL;
     pixbuf = gtk_icon_theme_load_icon (icon_theme,
             BACKSPACE_ICON, base_size,
             GTK_ICON_LOOKUP_NO_SVG,
             NULL);
+
     image1 = gtk_image_new_from_pixbuf (pixbuf);
     g_object_unref (G_OBJECT(pixbuf));
     gtk_container_add (GTK_CONTAINER (priv->buttons[3][2]), image1);
     dialog_action_area1 = GTK_DIALOG (dialog)->action_area;
-    gtk_button_box_set_layout (GTK_BUTTON_BOX(dialog_action_area1),
-            GTK_BUTTONBOX_END);
+    gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1),
+#if GTK_CHECK_VERSION(2,11,0) || defined(MAEMO_GTK)
+                               GTK_BUTTONBOX_CENTER);
+#else
+                               GTK_BUTTONBOX_DEFAULT_STYLE);
+#endif
 
-    okButton = gtk_dialog_add_button (GTK_DIALOG(dialog),DEVICELOCK_OK,
+    okButton = gtk_dialog_add_button (GTK_DIALOG (dialog) ,DEVICELOCK_OK,
             GTK_RESPONSE_OK);
-    cancelButton =
-        gtk_dialog_add_button (GTK_DIALOG(dialog),DEVICELOCK_CANCEL,
-                GTK_RESPONSE_CANCEL);
-    
+
     gtk_widget_set_sensitive (okButton, FALSE);
 
     priv->buttons[4][0] = priv->buttons[4][1] = okButton;
-    priv->buttons[4][2] = cancelButton;
+
+    priv->im_context = gtk_im_multicontext_new();
+#ifdef MAEMO_GTK
+    g_object_set (G_OBJECT (priv->im_context), "hildon-input-mode",
+                  HILDON_GTK_INPUT_MODE_NUMERIC, NULL);
+#endif
 
     /*
        Connect signals.
     */
-    g_signal_connect (G_OBJECT(priv->entry), "insert_text",
+    g_signal_connect (G_OBJECT (priv->im_context), "commit",
+                      G_CALLBACK (hildon_code_dialog_im_commit), dialog);
+
+    g_signal_connect (G_OBJECT (priv->entry), "insert_text",
             G_CALLBACK (hildon_code_dialog_insert_text), dialog);
     
-    gtk_entry_set_max_length(GTK_ENTRY(priv->entry),MAX_PINCODE_LEN);
+    gtk_entry_set_max_length (GTK_ENTRY (priv->entry), MAX_PINCODE_LEN);
 
-    for (x=0; x<3; x++)
+    for (x = 0; x < 3; x++)
     {
-        for (y=0; y<3 ;y++)
+        for (y = 0; y < 3; y++)
         {
             g_signal_connect (G_OBJECT (priv->buttons[x][y]), "clicked",
                 G_CALLBACK (hildon_code_dialog_button_clicked), dialog);
@@ -283,99 +347,185 @@ static void hildon_code_dialog_init (HildonCodeDialog *dialog)
     g_signal_connect (G_OBJECT (okButton), "key-press-event",
                 G_CALLBACK(hildon_code_dialog_key_press_event), dialog);
     
-    g_signal_connect (G_OBJECT (cancelButton), "key-press-event",
-                G_CALLBACK (hildon_code_dialog_key_press_event), dialog);
+    gtk_widget_show_all (GTK_WIDGET (GTK_DIALOG (dialog)->vbox));
+}
+
+static void
+hildon_code_dialog_realize                      (GtkWidget *widget)
+{
+    HildonCodeDialog *dialog = HILDON_CODE_DIALOG (widget);
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+      (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
+
+    gtk_im_context_set_client_window (GTK_IM_CONTEXT (priv->im_context),
+                                     GTK_WIDGET (dialog)->window);
+    gtk_im_context_focus_in (priv->im_context);
+}
 
+static void
+hildon_code_dialog_unrealize                    (GtkWidget *widget)
+{
+    HildonCodeDialog *dialog = HILDON_CODE_DIALOG (widget);
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+
+    gtk_im_context_set_client_window (GTK_IM_CONTEXT (priv->im_context), NULL);
+
+    if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+      (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+hildon_code_dialog_finalize                     (GObject *object)
+{
+    HildonCodeDialog *dialog = HILDON_CODE_DIALOG (object);
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+
+    g_object_unref (priv->im_context);
+
+    G_OBJECT_CLASS(parent_class)->finalize(object);
 }
 
-static void hildon_code_dialog_finalize (GObject *self)
+static void
+hildon_code_dialog_backspace                    (HildonCodeDialog *dialog)
 {
-    HildonCodeDialog *dialog = HILDON_CODE_DIALOG (self);
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    gchar *text, *pos;
+
+    g_assert (priv);
+
+    text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry)));
+        
+    pos = text;
+
+    while (*pos != '\0')
+    {
+      pos ++;
+    }
 
-    fprintf( stderr, "called destroy\n" );
+    pos = g_utf8_find_prev_char (text, pos);
 
-    g_free (dialog->priv);
+    if (pos)
+    {
+      *pos=0;
+    }
+
+    gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
+
+    if (*text == 0)
+    {
+      gtk_widget_set_sensitive (priv->buttons[4][0], FALSE);
+    }
+
+    gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1);
 
-    G_OBJECT_CLASS (parent_class)->finalize (self);
+    g_free (text);
 }
 
-/* Signal handlers */
-void hildon_code_dialog_button_clicked (GtkButton *button, gpointer user_data)
+static void 
+hildon_code_dialog_button_clicked               (GtkButton *button, 
+                                                 gpointer user_data)
 {
     HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data);
-    HildonCodeDialogPrivate *priv = dialog->priv;
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    g_assert (priv);
+
     const char *number = gtk_button_get_label (button);
 
     if (number && *number )
     {
-        gtk_entry_append_text (GTK_ENTRY (priv->entry), number);
+        gtk_editable_set_editable (GTK_EDITABLE (priv->entry), TRUE);
+
+        g_signal_emit_by_name (GTK_ENTRY (priv->entry)->im_context, "commit",
+                               number);
+
+        gtk_editable_set_editable (GTK_EDITABLE (priv->entry), FALSE);
+
+        gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1);
     }
     else
     {
-        /* Backspace */
-        gchar *text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry)));
-        gchar *pos;
-        
-        pos = text;
+        hildon_code_dialog_backspace (dialog);
+    }
+}
 
-        while (*pos != '\0')
-        {
-            pos ++;
-        }
+static void
+hildon_code_dialog_im_commit                    (GtkIMContext *im_context,
+                                                 gchar *utf8,
+                                                 gpointer user_data)
+{
+    HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data);
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    gint digit;
 
-        pos = g_utf8_find_prev_char (text, pos);
+    g_assert (priv);
 
-        if (pos)
-        {
-            *pos=0;
-        }
+    digit = g_ascii_strtod(utf8, NULL);
 
-        gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
+    if (g_ascii_isdigit(*utf8))
+    {
+        gtk_editable_set_editable (GTK_EDITABLE (priv->entry), TRUE);
 
-        if (*text == 0)
-        {
-            gtk_widget_set_sensitive (priv->buttons[4][0], FALSE);
-        }
+        g_signal_emit_by_name (GTK_ENTRY (priv->entry)->im_context, "commit",
+                               utf8);
 
-        g_free (text);
-    }
+        gtk_editable_set_editable (GTK_EDITABLE (priv->entry), FALSE);
 
+        gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1);
+    }
 }
 
-static void hildon_code_dialog_insert_text (GtkEditable *editable,
-                                            gchar *new_text,
-                                            gint new_text_length,
-                                            gint *position,
-                                            gpointer user_data)
+static void 
+hildon_code_dialog_insert_text                  (GtkEditable *editable,
+                                                 gchar *new_text,
+                                                 gint new_text_length,
+                                                 gint *position,
+                                                 gpointer user_data)
 {
     HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data);
-    HildonCodeDialogPrivate *priv = dialog->priv;
-    gchar * text = g_strdup(gtk_entry_get_text (GTK_ENTRY (priv->entry)));
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    gchar *text = g_strdup(gtk_entry_get_text (GTK_ENTRY (priv->entry)));
     glong length = g_utf8_strlen (text, -1);
     g_free (text);
+    g_assert (priv);
 
     if (length == MAX_PINCODE_LEN)
     {
-        hildon_banner_show_information (dialog,
+        hildon_banner_show_information (GTK_WIDGET (dialog),
                                         NULL,
                                         DEVICELOCK_MAX_CHAR_REACHED);
     }
 
-    else if (!length)
+    else if (! length)
     { 
         /* make the Ok button sensitive */
-        gtk_widget_set_sensitive(priv->buttons[4][0], TRUE);
+        gtk_widget_set_sensitive (priv->buttons[4][0], TRUE);
     }
+
+    hildon_code_dialog_input (dialog);
 }
 
-static gboolean hildon_code_dialog_key_press_event (GtkWidget *widget,
-                                                    GdkEventKey *event,
-                                                    gpointer user_data)
+static gboolean 
+hildon_code_dialog_key_press_event              (GtkWidget *widget,
+                                                 GdkEventKey *event,
+                                                 gpointer user_data)
 {
     HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data);
-    HildonCodeDialogPrivate *priv = dialog->priv;
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
     GtkWidget *new_widget = widget;
     gint x, y;
+    
+    g_assert (priv);
+
+    if (gtk_im_context_filter_keypress (priv->im_context, event))
+        return TRUE;
+
+    if (event->keyval == GDK_BackSpace)
+    {
+        hildon_code_dialog_backspace (dialog);
+        return TRUE;
+    }
 
     for (x = 0; x < 5; x++)
     {
@@ -421,8 +571,6 @@ found:
     return TRUE;
 }
 
-/* Public methods */
-
 /**
  * hildon_code_dialog_new:
  *
@@ -430,7 +578,8 @@ found:
  *
  * Return value: A @HildonCodeDialog.
  **/
-GtkWidget *hildon_code_dialog_new()
+GtkWidget*
+hildon_code_dialog_new                          (void)
 {
     HildonCodeDialog *dialog = g_object_new (HILDON_TYPE_CODE_DIALOG, NULL);
 
@@ -445,10 +594,15 @@ GtkWidget *hildon_code_dialog_new()
  *
  * Return value: The entered code.
  **/
-const gchar *hildon_code_dialog_get_code (HildonCodeDialog *dialog)
+const gchar*
+hildon_code_dialog_get_code                     (HildonCodeDialog *dialog)
 {
     g_return_val_if_fail (HILDON_IS_CODE_DIALOG (dialog), NULL);
-    return gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry));
+    
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    g_assert (priv);
+
+    return gtk_entry_get_text (GTK_ENTRY (priv->entry));
 }
 
 /**
@@ -457,11 +611,16 @@ const gchar *hildon_code_dialog_get_code (HildonCodeDialog *dialog)
  *
  * Use this function to clear the user entered code.
  **/
-void hildon_code_dialog_clear_code (HildonCodeDialog *dialog)
+void 
+hildon_code_dialog_clear_code                   (HildonCodeDialog *dialog)
 {
     g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog));
-    gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), "");
-    gtk_widget_set_sensitive (dialog->priv->buttons[4][0], FALSE);
+
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    g_assert (priv);
+
+    gtk_entry_set_text (GTK_ENTRY (priv->entry), "");
+    gtk_widget_set_sensitive (priv->buttons[4][0], FALSE);
 }
 
 /**
@@ -472,9 +631,55 @@ void hildon_code_dialog_clear_code (HildonCodeDialog *dialog)
  * Use this function to set the text that will be displayd in the
  * help label
  **/
-void hildon_code_dialog_set_help_text (HildonCodeDialog *dialog, 
-                                       const gchar *text)
+void 
+hildon_code_dialog_set_help_text                (HildonCodeDialog *dialog, 
+                                                 const gchar *text)
+{
+    g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog));
+
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    g_assert (priv);
+
+    gtk_label_set_text (GTK_LABEL (priv->help_text), text);
+}
+
+static void 
+hildon_code_dialog_real_input                   (HildonCodeDialog *dialog)
+{
+}
+
+static void 
+hildon_code_dialog_input                        (HildonCodeDialog *dialog)
+{
+    /* Emit the signal */
+    g_signal_emit (dialog, input_signal, 0);
+}
+
+/**
+ * hildon_code_dialog_set_input_sensitive
+ * @dialog: The #HildonCodeDialog whose state is to be changed
+ * @sensitive: The new state 
+ *
+ * This function will block or enable the input on the code dialog by
+ * making the input button sensitive (or not).
+ **/
+void
+hildon_code_dialog_set_input_sensitive          (HildonCodeDialog *dialog, 
+                                                 gboolean sensitive)
 {
+    int i;
+    int k;
+
     g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog));
-    gtk_label_set_text (GTK_LABEL (dialog->priv->help_text), text);
+
+    HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
+    g_assert (priv);
+
+    for (i = 0; i < 5; i++)
+        for (k = 0; k < 3; k++) 
+            if (i != 4 && (k != 0 || k != 2))
+                gtk_widget_set_sensitive (priv->buttons [i][k], sensitive);
+
+    gtk_widget_set_sensitive (priv->help_text, sensitive);
+    gtk_widget_set_sensitive (priv->entry, sensitive);
 }