Make sure that buttons in HildonAppMenu receive 'button-release-event'
authorAlberto Garcia <agarcia@igalia.com>
Mon, 15 Jun 2009 15:01:27 +0000 (17:01 +0200)
committerAlberto Garcia <agarcia@igalia.com>
Mon, 15 Jun 2009 15:02:40 +0000 (17:02 +0200)
* hildon/hildon-app-menu-private.h
* hildon/hildon-app-menu.c (hildon_app_menu_insert)
(hildon_app_menu_add_filter, +menu_item_button_event)
(hildon_app_menu_button_release, hildon_app_menu_init):
Make sure that buttons receive 'button-release-event' in spite of
the grab held by HildonAppMenu

Fixes: NB#108337 (Focus mismatch in items of AppMenu)

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

index 7aee303..1fb6197 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2009-06-15  Alberto Garcia  <agarcia@igalia.com>
 
+       * hildon/hildon-app-menu-private.h
+       * hildon/hildon-app-menu.c (hildon_app_menu_insert)
+       (hildon_app_menu_add_filter, +menu_item_button_event)
+       (hildon_app_menu_button_release, hildon_app_menu_init):
+       Make sure that buttons receive 'button-release-event' in spite of
+       the grab held by HildonAppMenu
+
+       Fixes: NB#108337 (Focus mismatch in items of AppMenu)
+
+2009-06-15  Alberto Garcia  <agarcia@igalia.com>
+
        * hildon/hildon-app-menu.c
        (hildon_app_menu_apply_style, hildon_app_menu_class_init):
        New style property to set the size of the group of filter buttons.
index ce5f1ad..9ca1a30 100644 (file)
@@ -34,6 +34,7 @@ struct                                          _HildonAppMenuPrivate
     GdkWindow *transfer_window;
     gboolean pressed_outside;
     gboolean inhibit_repack;
+    GtkButton *last_pressed_button;
     GList *buttons;
     GList *filters;
     guint columns;
index 10dd120..9c98081 100644 (file)
@@ -131,6 +131,11 @@ filter_visibility_changed                       (GtkWidget     *item,
                                                  GParamSpec    *arg1,
                                                  HildonAppMenu *menu);
 
+static gboolean
+menu_item_button_event                          (GtkButton      *item,
+                                                 GdkEventButton *event,
+                                                 GtkWidget      *menu);
+
 static void
 remove_item_from_list                           (GList    **list,
                                                  gpointer   item);
@@ -195,6 +200,10 @@ hildon_app_menu_insert                          (HildonAppMenu *menu,
     g_signal_connect_swapped (item, "clicked", G_CALLBACK (gtk_widget_hide), menu);
     g_signal_connect (item, "notify::visible", G_CALLBACK (item_visibility_changed), menu);
 
+    /* Keep track of the latest menu item to receive a button-press event */
+    g_signal_connect (item, "button-press-event", G_CALLBACK (menu_item_button_event), menu);
+    g_signal_connect (item, "button-release-event", G_CALLBACK (menu_item_button_event), menu);
+
     /* Remove item from list when it is destroyed */
     g_object_weak_ref (G_OBJECT (item), (GWeakNotify) remove_item_from_list, &(priv->buttons));
 }
@@ -302,6 +311,10 @@ hildon_app_menu_add_filter                      (HildonAppMenu *menu,
     g_signal_connect_swapped (filter, "clicked", G_CALLBACK (gtk_widget_hide), menu);
     g_signal_connect (filter, "notify::visible", G_CALLBACK (filter_visibility_changed), menu);
 
+    /* Keep track of the latest menu item to receive a button-press event */
+    g_signal_connect (filter, "button-press-event", G_CALLBACK (menu_item_button_event), menu);
+    g_signal_connect (filter, "button-release-event", G_CALLBACK (menu_item_button_event), menu);
+
     /* Remove filter from list when it is destroyed */
     g_object_weak_ref (G_OBJECT (filter), (GWeakNotify) remove_item_from_list, &(priv->filters));
 }
@@ -423,6 +436,27 @@ filter_visibility_changed                       (GtkWidget     *item,
         hildon_app_menu_repack_filters (menu);
 }
 
+static gboolean
+menu_item_button_event                          (GtkButton      *item,
+                                                 GdkEventButton *event,
+                                                 GtkWidget      *menu)
+{
+    HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (menu);
+
+    if (event->type == GDK_BUTTON_PRESS) {
+        priv->last_pressed_button = item;
+    } else if (event->type == GDK_BUTTON_RELEASE) {
+        /* A pressed button might not receive the button-release event due
+         * to the grab that HildonAppMenu has, so we have to simulate that
+         * event. See NB#108337 */
+        if (priv->last_pressed_button && priv->last_pressed_button != item) {
+            gtk_button_released (priv->last_pressed_button);
+        }
+        priv->last_pressed_button = NULL;
+    }
+    return FALSE;
+}
+
 static void
 remove_item_from_list                           (GList    **list,
                                                  gpointer   item)
@@ -698,6 +732,8 @@ hildon_app_menu_button_release                  (GtkWidget *widget,
         }
 
         priv->pressed_outside = FALSE; /* Always reset pressed_outside to FALSE */
+    } else if (priv->last_pressed_button) {
+        menu_item_button_event (NULL, event, widget);
     }
 
     if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event) {
@@ -1023,6 +1059,7 @@ hildon_app_menu_init                            (HildonAppMenu *menu)
     priv->transfer_window = NULL;
     priv->pressed_outside = FALSE;
     priv->inhibit_repack = FALSE;
+    priv->last_pressed_button = NULL;
     priv->buttons = NULL;
     priv->filters = NULL;
     priv->columns = 2;