* src/hildon-note.c Added new transfer_window and close_if_pressed_outside private...
authorAlberto Garcia <agarcia@igalia.com>
Mon, 9 Jun 2008 17:06:29 +0000 (17:06 +0000)
committerAlberto Garcia <agarcia@igalia.com>
Mon, 9 Jun 2008 17:06:29 +0000 (17:06 +0000)
* src/hildon-app-menu.c
(hildon_app_menu_button_release, hildon_app_menu_class_init):
Close the menu on button release, not button press

ChangeLog
src/hildon-app-menu.c
src/hildon-note-private.h
src/hildon-note.c

index 9bdb1c7..1afcbf8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,23 @@
 2008-06-09  Alberto Garcia  <agarcia@igalia.com>
 
+       * src/hildon-note.c
+       Added new transfer_window and close_if_pressed_outside private
+       attributes.
+       (hildon_note_rebuild):
+       Don't add a cancel button to the information note. It will be
+       closed when tapping outside
+       (hildon_note_realize):
+       Set the notification type hint
+       (hildon_note_map, hildon_note_unmap, grab_transfer_window_get):
+       Grab/ungrab pointer and keyboard if the note has to be closed when
+       tapping outside
+       (hildon_note_button_release):
+       Close the note when tapping outside (if applicable)
+
        * src/hildon-app-menu.c
        Grab/ungrab pointer and keyboard on map/unmap
+       (hildon_app_menu_button_release, hildon_app_menu_class_init):
+       Close the menu on button release, not button press
 
        * src/hildon-banner.c
        (hildon_banner_set_property)
index c1f1a37..0c84211 100644 (file)
@@ -121,7 +121,7 @@ hildon_app_menu_append                          (HildonAppMenu *menu,
     /* GtkTable already calls gtk_table_resize() if necessary */
     gtk_table_attach_defaults (priv->table, GTK_WIDGET (item), col, col + 1, row, row + 1);
 
-    /* Close the menu when the button is pressed */
+    /* Close the menu when the button is clicked */
     g_signal_connect_swapped (item, "clicked", G_CALLBACK (gtk_widget_hide), menu);
 
     gtk_widget_show (GTK_WIDGET (item));
@@ -161,7 +161,7 @@ hildon_app_menu_add_filter                      (HildonAppMenu *menu,
     gtk_box_pack_start (GTK_BOX (group), GTK_WIDGET (filter), TRUE, TRUE, 0);
     gtk_size_group_add_widget (priv->sizegroup, GTK_WIDGET (filter));
 
-    /* Close the menu when the button is pressed */
+    /* Close the menu when the button is clicked */
     g_signal_connect_swapped (filter, "clicked", G_CALLBACK (gtk_widget_hide), menu);
 
     gtk_widget_show (GTK_WIDGET (filter));
@@ -279,19 +279,26 @@ hildon_app_menu_unmap                           (GtkWidget *widget)
 }
 
 static gboolean
-hildon_app_menu_button_press                    (GtkWidget *widget,
+hildon_app_menu_button_release                  (GtkWidget *widget,
                                                  GdkEventButton *event)
 {
     int x, y;
+    gboolean released_outside;
     HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget);
-    gdk_window_get_position(widget->window, &x, &y);
-    if (event->window != priv->transfer_window ||
-        event->x < x || event->x > x + widget->allocation.width ||
-        event->y < y || event->y > y + widget->allocation.height) {
+
+    gdk_window_get_position (widget->window, &x, &y);
+
+    /* Whether the button has been released outside the widget */
+    released_outside = (event->window != priv->transfer_window ||
+                        event->x < x || event->x > x + widget->allocation.width ||
+                        event->y < y || event->y > y + widget->allocation.height);
+
+    if (released_outside) {
         gtk_widget_hide (widget);
-        return TRUE;
-    } else if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event) {
-        return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event (widget, event);
+    }
+
+    if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event) {
+        return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event (widget, event);
     } else {
         return FALSE;
     }
@@ -403,7 +410,7 @@ hildon_app_menu_class_init                      (HildonAppMenuClass *klass)
     widget_class->map = hildon_app_menu_map;
     widget_class->unmap = hildon_app_menu_unmap;
     widget_class->realize = hildon_app_menu_realize;
-    widget_class->button_press_event = hildon_app_menu_button_press;
+    widget_class->button_release_event = hildon_app_menu_button_release;
 
     g_type_class_add_private (klass, sizeof (HildonAppMenuPrivate));
 
index 077d544..3514df2 100644 (file)
@@ -40,6 +40,8 @@ struct                                          _HildonNotePrivate
     GtkWidget *label;
     GtkWidget *box;
     GtkWidget *icon;
+    GdkWindow *transfer_window;
+    guint close_if_pressed_outside : 1;
 
     HildonNoteType note_n;
     GtkWidget *progressbar;
index d5e67ed..f634646 100644 (file)
@@ -94,6 +94,16 @@ hildon_note_rebuild                             (HildonNote *note);
 static void
 hildon_note_finalize                            (GObject *obj_self);
 
+static gboolean
+hildon_note_button_release                      (GtkWidget *widget,
+                                                 GdkEventButton *event);
+
+static void
+hildon_note_map                                 (GtkWidget *widget);
+
+static void
+hildon_note_unmap                               (GtkWidget *widget);
+
 static void
 hildon_note_realize                             (GtkWidget *widget);
 
@@ -126,6 +136,33 @@ enum
 
 static GtkDialogClass*                          parent_class;
 
+static GdkWindow *
+grab_transfer_window_get                        (GtkWidget *widget)
+{
+    GdkWindow *window;
+    GdkWindowAttr attributes;
+    gint attributes_mask;
+
+    attributes.x = 0;
+    attributes.y = 0;
+    attributes.width = 10;
+    attributes.height = 10;
+    attributes.window_type = GDK_WINDOW_TEMP;
+    attributes.wclass = GDK_INPUT_ONLY;
+    attributes.override_redirect = TRUE;
+    attributes.event_mask = 0;
+
+    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
+
+    window = gdk_window_new (gtk_widget_get_root_window (widget),
+                             &attributes, attributes_mask);
+    gdk_window_set_user_data (window, widget);
+
+    gdk_window_show (window);
+
+    return window;
+}
+
 static void
 hildon_note_set_property                        (GObject *object,
                                                  guint prop_id,
@@ -275,6 +312,9 @@ hildon_note_class_init                          (HildonNoteClass *class)
     object_class->finalize      = hildon_note_finalize;
     object_class->set_property  = hildon_note_set_property;
     object_class->get_property  = hildon_note_get_property;
+    widget_class->button_release_event = hildon_note_button_release;
+    widget_class->map           = hildon_note_map;
+    widget_class->unmap         = hildon_note_unmap;
     widget_class->realize       = hildon_note_realize;
 
     g_object_class_install_property (object_class,
@@ -349,6 +389,8 @@ hildon_note_init                                (HildonNote *dialog)
     gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
     
     priv->icon  = gtk_image_new ();
+    priv->close_if_pressed_outside = FALSE;
+    priv->transfer_window = NULL;
 
     /* Acquire real references to our internal children, since
        they are not nessecarily packed into container in each
@@ -385,6 +427,72 @@ hildon_note_finalize                            (GObject *obj_self)
     G_OBJECT_CLASS (parent_class)->finalize (obj_self);
 }
 
+
+static gboolean
+hildon_note_button_release                      (GtkWidget *widget,
+                                                 GdkEventButton *event)
+{
+    int x, y;
+    gboolean released_outside;
+    HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
+
+    gdk_window_get_position (widget->window, &x, &y);
+
+    /* Whether the button has been released outside the widget */
+    released_outside = (event->window != priv->transfer_window ||
+                        event->x < x || event->x > x + widget->allocation.width ||
+                        event->y < y || event->y > y + widget->allocation.height);
+
+    if (released_outside && priv->close_if_pressed_outside) {
+        gtk_dialog_response (GTK_DIALOG (widget), GTK_RESPONSE_CANCEL);
+    }
+
+    if (GTK_WIDGET_CLASS (parent_class)->button_release_event) {
+        return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
+    } else {
+        return FALSE;
+    }
+}
+
+static void
+hildon_note_map                                 (GtkWidget *widget)
+{
+    HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
+    g_assert (priv);
+
+    /* Map the window */
+    GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+    if (priv->transfer_window == NULL && priv->close_if_pressed_outside) {
+        priv->transfer_window = grab_transfer_window_get (widget);
+        gdk_pointer_grab (
+            priv->transfer_window, TRUE,
+            GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+            GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+            GDK_POINTER_MOTION_MASK, NULL, NULL, GDK_CURRENT_TIME);
+        gdk_keyboard_grab (priv->transfer_window, TRUE, GDK_CURRENT_TIME);
+        gtk_grab_add (widget);
+    }
+}
+
+static void
+hildon_note_unmap                               (GtkWidget *widget)
+{
+    HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
+    g_assert (priv);
+
+    if (priv->transfer_window != NULL) {
+        /* Remove the grab */
+        gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
+                                    GDK_CURRENT_TIME);
+        gtk_grab_remove (widget);
+
+        /* Destroy the transfer window */
+        gdk_window_destroy (priv->transfer_window);
+        priv->transfer_window = NULL;
+    }
+}
+
 static void
 hildon_note_realize                             (GtkWidget *widget)
 {
@@ -402,6 +510,9 @@ hildon_note_realize                             (GtkWidget *widget)
     if (priv->sound_signal_handler == 0)
         priv->sound_signal_handler = g_signal_connect_after(widget, 
                 "expose-event", G_CALLBACK (sound_handling), NULL);
+
+    /* We use special hint to turn the note into information notification. */
+    gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
 }
 
 /* Helper function for removing a widget from it's container.
@@ -449,6 +560,9 @@ hildon_note_rebuild                             (HildonNote *note)
         priv->cancelButton = NULL;
     }
 
+    /* By default the note won't be closed when pressing outside */
+    priv->close_if_pressed_outside = FALSE;
+
     /* Add needed buttons and images for each note type */
     switch (priv->note_n)
     {
@@ -467,10 +581,7 @@ hildon_note_rebuild                             (HildonNote *note)
 
         case HILDON_NOTE_TYPE_INFORMATION_THEME:
         case HILDON_NOTE_TYPE_INFORMATION:
-            /* Add clickable OK button (cancel really,
-               but doesn't matter since this is info) */
-            priv->cancelButton = gtk_dialog_add_button (dialog,
-                    _("ecdg_bd_information_note_ok"), GTK_RESPONSE_CANCEL);
+            priv->close_if_pressed_outside = TRUE;
             gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
                     HILDON_NOTE_INFORMATION_ICON,
                     HILDON_ICON_SIZE_BIG_NOTE);