]> Pileus Git - ~andy/gtk/commitdiff
Add a new binding signal, "move_scroll", and use it to hook up
authorOwen Taylor <otaylor@redhat.com>
Sat, 14 Dec 2002 22:43:52 +0000 (22:43 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Sat, 14 Dec 2002 22:43:52 +0000 (22:43 +0000)
Sat Dec 14 14:19:16 2002  Owen Taylor  <otaylor@redhat.com>

        * gtk/gtkmenu.c: Add a new binding signal, "move_scroll",
        and use it to hook up Home/End/Page_Up/Page_Down keybindings.
        (#80484, Narayana Pattipati, Marius Andreiana)

        * gtk/gtkmenu.c (gtk_menu_scroll_item_visible): Fix some
        bugs in the computation of when an item is visible. (#99545)

        * gtk/gtkbindings.[ch] (_gtk_binding_signal_new) gtk/gtkmenushell.c:
        Move here, export privately.

        * gtk/gtkmenushell.c (_gtk_menu_shell_select_last): Export
        privately.

        * gtk/gtkmenushell.c (gtk_menu_shell_select_item): Don't
        select the item if it is already selected.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkbindings.c
gtk/gtkbindings.h
gtk/gtkmenu.c
gtk/gtkmenushell.c
gtk/gtkmenushell.h

index 6b94a4b8d235f860303cc31450a0fef16f440333..3f831f76e38433b484a11216c5dff874eadf16d8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+Sat Dec 14 14:19:16 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkmenu.c: Add a new binding signal, "move_scroll",
+       and use it to hook up Home/End/Page_Up/Page_Down keybindings.
+       (#80484, Narayana Pattipati, Marius Andreiana)
+
+       * gtk/gtkmenu.c (gtk_menu_scroll_item_visible): Fix some
+       bugs in the computation of when an item is visible. (#99545)
+       
+       * gtk/gtkbindings.[ch] (_gtk_binding_signal_new) gtk/gtkmenushell.c:
+       Move here, export privately.
+
+       * gtk/gtkmenushell.c (_gtk_menu_shell_select_last): Export
+       privately.
+
+       * gtk/gtkmenushell.c (gtk_menu_shell_select_item): Don't
+       select the item if it is already selected.
+
 Sat Dec 14 01:51:05 2002  Chema Celorio  <chema@celorio.com>
 
        * gtk/gtkdialog.c (gtk_dialog_add_buttons_valist): minor coding
index 6b94a4b8d235f860303cc31450a0fef16f440333..3f831f76e38433b484a11216c5dff874eadf16d8 100644 (file)
@@ -1,3 +1,21 @@
+Sat Dec 14 14:19:16 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkmenu.c: Add a new binding signal, "move_scroll",
+       and use it to hook up Home/End/Page_Up/Page_Down keybindings.
+       (#80484, Narayana Pattipati, Marius Andreiana)
+
+       * gtk/gtkmenu.c (gtk_menu_scroll_item_visible): Fix some
+       bugs in the computation of when an item is visible. (#99545)
+       
+       * gtk/gtkbindings.[ch] (_gtk_binding_signal_new) gtk/gtkmenushell.c:
+       Move here, export privately.
+
+       * gtk/gtkmenushell.c (_gtk_menu_shell_select_last): Export
+       privately.
+
+       * gtk/gtkmenushell.c (gtk_menu_shell_select_item): Don't
+       select the item if it is already selected.
+
 Sat Dec 14 01:51:05 2002  Chema Celorio  <chema@celorio.com>
 
        * gtk/gtkdialog.c (gtk_dialog_add_buttons_valist): minor coding
index 6b94a4b8d235f860303cc31450a0fef16f440333..3f831f76e38433b484a11216c5dff874eadf16d8 100644 (file)
@@ -1,3 +1,21 @@
+Sat Dec 14 14:19:16 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkmenu.c: Add a new binding signal, "move_scroll",
+       and use it to hook up Home/End/Page_Up/Page_Down keybindings.
+       (#80484, Narayana Pattipati, Marius Andreiana)
+
+       * gtk/gtkmenu.c (gtk_menu_scroll_item_visible): Fix some
+       bugs in the computation of when an item is visible. (#99545)
+       
+       * gtk/gtkbindings.[ch] (_gtk_binding_signal_new) gtk/gtkmenushell.c:
+       Move here, export privately.
+
+       * gtk/gtkmenushell.c (_gtk_menu_shell_select_last): Export
+       privately.
+
+       * gtk/gtkmenushell.c (gtk_menu_shell_select_item): Don't
+       select the item if it is already selected.
+
 Sat Dec 14 01:51:05 2002  Chema Celorio  <chema@celorio.com>
 
        * gtk/gtkdialog.c (gtk_dialog_add_buttons_valist): minor coding
index 6b94a4b8d235f860303cc31450a0fef16f440333..3f831f76e38433b484a11216c5dff874eadf16d8 100644 (file)
@@ -1,3 +1,21 @@
+Sat Dec 14 14:19:16 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkmenu.c: Add a new binding signal, "move_scroll",
+       and use it to hook up Home/End/Page_Up/Page_Down keybindings.
+       (#80484, Narayana Pattipati, Marius Andreiana)
+
+       * gtk/gtkmenu.c (gtk_menu_scroll_item_visible): Fix some
+       bugs in the computation of when an item is visible. (#99545)
+       
+       * gtk/gtkbindings.[ch] (_gtk_binding_signal_new) gtk/gtkmenushell.c:
+       Move here, export privately.
+
+       * gtk/gtkmenushell.c (_gtk_menu_shell_select_last): Export
+       privately.
+
+       * gtk/gtkmenushell.c (gtk_menu_shell_select_item): Don't
+       select the item if it is already selected.
+
 Sat Dec 14 01:51:05 2002  Chema Celorio  <chema@celorio.com>
 
        * gtk/gtkdialog.c (gtk_dialog_add_buttons_valist): minor coding
index 6b94a4b8d235f860303cc31450a0fef16f440333..3f831f76e38433b484a11216c5dff874eadf16d8 100644 (file)
@@ -1,3 +1,21 @@
+Sat Dec 14 14:19:16 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkmenu.c: Add a new binding signal, "move_scroll",
+       and use it to hook up Home/End/Page_Up/Page_Down keybindings.
+       (#80484, Narayana Pattipati, Marius Andreiana)
+
+       * gtk/gtkmenu.c (gtk_menu_scroll_item_visible): Fix some
+       bugs in the computation of when an item is visible. (#99545)
+       
+       * gtk/gtkbindings.[ch] (_gtk_binding_signal_new) gtk/gtkmenushell.c:
+       Move here, export privately.
+
+       * gtk/gtkmenushell.c (_gtk_menu_shell_select_last): Export
+       privately.
+
+       * gtk/gtkmenushell.c (gtk_menu_shell_select_item): Don't
+       select the item if it is already selected.
+
 Sat Dec 14 01:51:05 2002  Chema Celorio  <chema@celorio.com>
 
        * gtk/gtkdialog.c (gtk_dialog_add_buttons_valist): minor coding
index 6b94a4b8d235f860303cc31450a0fef16f440333..3f831f76e38433b484a11216c5dff874eadf16d8 100644 (file)
@@ -1,3 +1,21 @@
+Sat Dec 14 14:19:16 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkmenu.c: Add a new binding signal, "move_scroll",
+       and use it to hook up Home/End/Page_Up/Page_Down keybindings.
+       (#80484, Narayana Pattipati, Marius Andreiana)
+
+       * gtk/gtkmenu.c (gtk_menu_scroll_item_visible): Fix some
+       bugs in the computation of when an item is visible. (#99545)
+       
+       * gtk/gtkbindings.[ch] (_gtk_binding_signal_new) gtk/gtkmenushell.c:
+       Move here, export privately.
+
+       * gtk/gtkmenushell.c (_gtk_menu_shell_select_last): Export
+       privately.
+
+       * gtk/gtkmenushell.c (gtk_menu_shell_select_item): Don't
+       select the item if it is already selected.
+
 Sat Dec 14 01:51:05 2002  Chema Celorio  <chema@celorio.com>
 
        * gtk/gtkdialog.c (gtk_dialog_add_buttons_valist): minor coding
index d6c65a022c21c8b4a481c376108c14e0d6399a76..efb4ea08c58c8f1a80b827e403f079f8afd9fe4c 100644 (file)
@@ -1472,3 +1472,32 @@ _gtk_binding_reset_parsed (void)
       slist = next;
     }
 }
+
+guint
+_gtk_binding_signal_new (const gchar       *signal_name,
+                        GType               itype,
+                        GSignalFlags        signal_flags,
+                        GCallback           handler,
+                        GSignalAccumulator  accumulator,
+                        gpointer            accu_data,
+                        GSignalCMarshaller  c_marshaller,
+                        GType               return_type,
+                        guint               n_params,
+                        ...)
+{
+  va_list args;
+  guint signal_id;
+
+  g_return_val_if_fail (signal_name != NULL, 0);
+  
+  va_start (args, n_params);
+
+  signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
+                                   g_cclosure_new (handler, NULL, NULL),
+                                  accumulator, accu_data, c_marshaller,
+                                   return_type, n_params, args);
+
+  va_end (args);
+  return signal_id;
+}
index c906ca6fbd1fb76d9c9a83e60f4ad8042991b22d..5d4549582222cc7cb46140016a374d863b2f4165 100644 (file)
@@ -140,6 +140,19 @@ gboolean _gtk_bindings_activate_event (GtkObject   *object,
                                       GdkEventKey *event);
 void     _gtk_binding_reset_parsed    (void);
 
+/* Creates a signal with a fixed callback instead of a class offset;
+ * useful for key binding signals
+ */
+guint _gtk_binding_signal_new (const gchar       *signal_name,
+                              GType              itype,
+                              GSignalFlags       signal_flags,
+                              GCallback          handler,
+                              GSignalAccumulator accumulator,
+                              gpointer           accu_data,
+                              GSignalCMarshaller c_marshaller,
+                              GType              return_type,
+                              guint              n_params,
+                              ...);
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 3a3cf67e5f96bdd47584ca64881562793cc25bbd..9404d5ca96c26361a1809a6c809b499fec166a4e 100644 (file)
 #include "gtkbindings.h"
 #include "gtklabel.h"
 #include "gtkmain.h"
+#include "gtkmarshalers.h"
 #include "gtkmenu.h"
 #include "gtkmenuitem.h"
+#include "gtktearoffmenuitem.h"
 #include "gtkwindow.h"
 #include "gtkhbox.h"
 #include "gtkvscrollbar.h"
@@ -74,6 +76,11 @@ struct _GtkMenuPrivate
   gint y;
 };
 
+enum {
+  MOVE_SCROLL,
+  LAST_SIGNAL
+};
+
 enum {
   PROP_0,
   PROP_TEAROFF_TITLE
@@ -138,8 +145,9 @@ static void     gtk_menu_style_set         (GtkWidget        *widget,
                                            GtkStyle         *previous_style);
 static gboolean gtk_menu_focus             (GtkWidget        *widget,
                                            GtkDirectionType direction);
-static gint     gtk_menu_get_popup_delay   (GtkMenuShell    *menu_shell);
-
+static gint     gtk_menu_get_popup_delay   (GtkMenuShell     *menu_shell);
+static void     gtk_menu_real_move_scroll  (GtkMenu          *menu,
+                                           GtkScrollType     type);
 
 static void     gtk_menu_stop_navigating_submenu       (GtkMenu          *menu);
 static gboolean gtk_menu_stop_navigating_submenu_cb    (gpointer          user_data);
@@ -171,6 +179,8 @@ static void _gtk_menu_refresh_accel_paths (GtkMenu *menu,
 static GtkMenuShellClass *parent_class = NULL;
 static const gchar      *attach_data_key = "gtk-menu-attach-data";
 
+static guint menu_signals[LAST_SIGNAL] = { 0 };
+
 GtkMenuPrivate *
 gtk_menu_get_private (GtkMenu *menu)
 {
@@ -237,6 +247,16 @@ gtk_menu_class_init (GtkMenuClass *class)
   gobject_class->set_property = gtk_menu_set_property;
   gobject_class->get_property = gtk_menu_get_property;
 
+  menu_signals[MOVE_SCROLL] =
+    _gtk_binding_signal_new ("move_scroll",
+                            G_OBJECT_CLASS_TYPE (object_class),
+                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                            G_CALLBACK (gtk_menu_real_move_scroll),
+                            NULL, NULL,
+                            _gtk_marshal_VOID__ENUM,
+                            G_TYPE_NONE, 1,
+                            GTK_TYPE_SCROLL_TYPE);
+  
   g_object_class_install_property (gobject_class,
                                    PROP_TEAROFF_TITLE,
                                    g_param_spec_string ("tearoff-title",
@@ -314,6 +334,46 @@ gtk_menu_class_init (GtkMenuClass *class)
                                "move_current", 1,
                                GTK_TYPE_MENU_DIRECTION_TYPE,
                                GTK_MENU_DIR_CHILD);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_Home, 0,
+                               "move_scroll", 1,
+                               GTK_TYPE_SCROLL_TYPE,
+                               GTK_SCROLL_START);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Home, 0,
+                               "move_scroll", 1,
+                               GTK_TYPE_SCROLL_TYPE,
+                               GTK_SCROLL_START);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_End, 0,
+                               "move_scroll", 1,
+                               GTK_TYPE_SCROLL_TYPE,
+                               GTK_SCROLL_END);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_End, 0,
+                               "move_scroll", 1,
+                               GTK_TYPE_SCROLL_TYPE,
+                               GTK_SCROLL_END);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_Page_Up, 0,
+                               "move_scroll", 1,
+                               GTK_TYPE_SCROLL_TYPE,
+                               GTK_SCROLL_PAGE_UP);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Page_Up, 0,
+                               "move_scroll", 1,
+                               GTK_TYPE_SCROLL_TYPE,
+                               GTK_SCROLL_PAGE_UP);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_Page_Down, 0,
+                               "move_scroll", 1,
+                               GTK_TYPE_SCROLL_TYPE,
+                               GTK_SCROLL_PAGE_DOWN);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Page_Down, 0,
+                               "move_scroll", 1,
+                               GTK_TYPE_SCROLL_TYPE,
+                               GTK_SCROLL_PAGE_DOWN);
 
   gtk_settings_install_property (g_param_spec_boolean ("gtk-can-change-accels",
                                                       _("Can change accelerators"),
@@ -2730,7 +2790,9 @@ gtk_menu_scroll_to (GtkMenu *menu,
       menu->tearoff_adjustment &&
       (menu->tearoff_adjustment->value != offset))
     {
-      menu->tearoff_adjustment->value = offset;
+      menu->tearoff_adjustment->value =
+       CLAMP (offset,
+              0, menu->tearoff_adjustment->upper - menu->tearoff_adjustment->page_size);
       gtk_adjustment_value_changed (menu->tearoff_adjustment);
     }
   
@@ -2745,11 +2807,11 @@ gtk_menu_scroll_to (GtkMenu *menu,
 
   x = border_width + widget->style->xthickness;
   y = border_width + widget->style->ythickness;
-  
+
   if (!menu->tearoff_active)
     {
       last_visible = menu->upper_arrow_visible;
-      menu->upper_arrow_visible = (offset > 0);
+      menu->upper_arrow_visible = (view_height < menu_height && offset > 0);
       
       if (menu->upper_arrow_visible)
        view_height -= MENU_SCROLL_ARROW_HEIGHT;
@@ -2763,9 +2825,9 @@ gtk_menu_scroll_to (GtkMenu *menu,
          if (menu->scroll_step < 0)
            gtk_menu_stop_scrolling (menu);
        }
-      
+
       last_visible = menu->lower_arrow_visible;
-      menu->lower_arrow_visible = (view_height + offset < menu_height);
+      menu->lower_arrow_visible = (view_height < menu_height && offset < menu_height - view_height);
       
       if (menu->lower_arrow_visible)
        view_height -= MENU_SCROLL_ARROW_HEIGHT;
@@ -2800,14 +2862,54 @@ gtk_menu_scroll_to (GtkMenu *menu,
   menu->scroll_offset = offset;
 }
 
+static gboolean
+compute_child_offset (GtkMenu   *menu,
+                     GtkWidget *menu_item,
+                     gint      *offset,
+                     gint      *height,
+                     gboolean  *is_last_child)
+{
+  GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu);
+  GList *children;
+  gint child_offset = 0;
+
+  for (children = menu_shell->children; children; children = children->next)
+    {
+      GtkWidget *child = children->data;
+      GtkRequisition child_requisition;
+      gint child_height;
+      
+      if (GTK_WIDGET_VISIBLE (child))
+       {
+         gtk_widget_size_request (child, &child_requisition);
+         child_height = child_requisition.height;
+       }
+      else
+       child_height = 0;
+      
+      if (child == menu_item)
+       {
+         if (is_last_child)
+           *is_last_child = (children == NULL);
+         if (offset)
+           *offset = child_offset;
+         if (height)
+           *height = child_height;
+         
+         return TRUE;
+       }
+      
+      child_offset += child_height;
+    }
+
+  return FALSE;
+}
+
 static void
 gtk_menu_scroll_item_visible (GtkMenuShell    *menu_shell,
                              GtkWidget       *menu_item)
 {
   GtkMenu *menu;
-  GtkWidget *child;
-  GList *children;
-  GtkRequisition child_requisition;
   gint child_offset, child_height;
   gint width, height;
   gint y;
@@ -2821,37 +2923,15 @@ gtk_menu_scroll_item_visible (GtkMenuShell    *menu_shell,
    * visible.
    */
 
-  child = NULL;
-  child_offset = 0;
-  child_height = 0;
-  children = menu_shell->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
-      
-      if (GTK_WIDGET_VISIBLE (child))
-       {
-         gtk_widget_size_request (child, &child_requisition);
-         child_offset += child_height;
-         child_height = child_requisition.height;
-       }
-      
-      if (child == menu_item)
-       {
-         last_child = (children == NULL);
-         break;
-       }
-    }
-
-  if (child == menu_item)
+  if (compute_child_offset (menu, menu_item,
+                           &child_offset, &child_height, &last_child))
     {
       y = menu->scroll_offset;
       gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height);
 
       height -= 2*GTK_CONTAINER (menu)->border_width + 2*GTK_WIDGET (menu)->style->ythickness;
       
-      if (child_offset + child_height <= y)
+      if (child_offset < y)
        {
          /* Ignore the enter event we might get if the pointer is on the menu
           */
@@ -2866,7 +2946,7 @@ gtk_menu_scroll_item_visible (GtkMenuShell    *menu_shell,
          if (menu->lower_arrow_visible && !menu->tearoff_active)
            arrow_height += MENU_SCROLL_ARROW_HEIGHT;
          
-         if (child_offset >= y + height - arrow_height)
+         if (child_offset + child_height > y + height - arrow_height)
            {
              arrow_height = 0;
              if (!last_child && !menu->tearoff_active)
@@ -3022,3 +3102,136 @@ gtk_menu_get_popup_delay (GtkMenuShell *menu_shell)
 
   return popup_delay;
 }
+
+static gint
+get_visible_size (GtkMenu *menu)
+{
+  GtkWidget *widget = GTK_WIDGET (menu);
+  GtkContainer *container = GTK_CONTAINER (menu);
+  
+  gint menu_height = (widget->allocation.height
+                     - 2 * (container->border_width
+                            + widget->style->ythickness));
+  
+  if (menu->upper_arrow_visible && !menu->tearoff_active)
+    menu_height -= MENU_SCROLL_ARROW_HEIGHT;
+  if (menu->lower_arrow_visible && !menu->tearoff_active)
+    menu_height -= MENU_SCROLL_ARROW_HEIGHT;
+
+  return menu_height;
+}
+
+/* Find the sensitive on-screen child containing @y, or if none,
+ * the nearest selectable onscreen child. (%NULL if none)
+ */
+static GtkWidget *
+child_at (GtkMenu *menu,
+         gint     y)
+{
+  GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu);
+  GtkWidget *child = NULL;
+  gint child_offset = 0;
+  GList *children;
+  gint menu_height;
+  gint lower, upper;           /* Onscreen bounds */
+
+  menu_height = get_visible_size (menu);
+  lower = menu->scroll_offset;
+  upper = menu->scroll_offset + menu_height;
+  
+  for (children = menu_shell->children; children; children = children->next)
+    {
+      if (GTK_WIDGET_VISIBLE (children->data))
+       {
+         GtkRequisition child_requisition;
+
+         gtk_widget_size_request (children->data, &child_requisition);
+
+         if (_gtk_menu_item_is_selectable (children->data) &&
+             child_offset >= lower &&
+             child_offset + child_requisition.height <= upper)
+           {
+             child = children->data;
+             
+             if (child_offset + child_requisition.height > y &&
+                 !GTK_IS_TEAROFF_MENU_ITEM (child))
+               return child;
+           }
+      
+         child_offset += child_requisition.height;
+       }
+    }
+
+  return child;
+}
+
+static void
+gtk_menu_real_move_scroll (GtkMenu       *menu,
+                          GtkScrollType  type)
+{
+  GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu);
+  
+  switch (type)
+    {
+    case GTK_SCROLL_PAGE_UP:
+    case GTK_SCROLL_PAGE_DOWN:
+      {
+       gint page_size = get_visible_size (menu);
+       gint old_offset;
+       gint child_offset = 0;
+       gboolean old_upper_arrow_visible;
+       gint step;
+
+       if (type == GTK_SCROLL_PAGE_UP)
+         step = - page_size;
+       else
+         step = page_size;
+
+       if (menu_shell->active_menu_item)
+         {
+           gint child_height;
+           
+           compute_child_offset (menu, menu_shell->active_menu_item,
+                                 &child_offset, &child_height, NULL);
+           child_offset += child_height / 2;
+         }
+
+       menu_shell->ignore_enter = TRUE;
+       old_upper_arrow_visible = menu->upper_arrow_visible && !menu->tearoff_active;
+       old_offset = menu->scroll_offset;
+       gtk_menu_scroll_to (menu, menu->scroll_offset + step);
+       
+       if (menu_shell->active_menu_item)
+         {
+           GtkWidget *new_child;
+           gboolean new_upper_arrow_visible = menu->upper_arrow_visible && !menu->tearoff_active;
+
+           if (menu->scroll_offset != old_offset)
+             step = menu->scroll_offset - old_offset;
+
+           step -= (new_upper_arrow_visible - old_upper_arrow_visible) * MENU_SCROLL_ARROW_HEIGHT;
+
+           new_child = child_at (menu, child_offset + step);
+           if (new_child)
+             gtk_menu_shell_select_item (menu_shell, new_child);
+         }
+      }
+      break;
+    case GTK_SCROLL_START:
+      /* Ignore the enter event we might get if the pointer is on the menu
+       */
+      menu_shell->ignore_enter = TRUE;
+      gtk_menu_scroll_to (menu, 0);
+      gtk_menu_shell_select_first (menu_shell, TRUE);
+      break;
+    case GTK_SCROLL_END:
+      /* Ignore the enter event we might get if the pointer is on the menu
+       */
+      menu_shell->ignore_enter = TRUE;
+      gtk_menu_scroll_to (menu, G_MAXINT);
+      _gtk_menu_shell_select_last (menu_shell, TRUE);
+      break;
+    default:
+      break;
+    }
+}
index 2cded4b87af254ec072b1697bfb419e1d3688ac4..b72c04d217891ba6016886a3c648844a501ebcf9 100644 (file)
@@ -185,35 +185,6 @@ gtk_menu_shell_get_type (void)
   return menu_shell_type;
 }
 
-static guint
-binding_signal_new (const gchar               *signal_name,
-                   GType               itype,
-                   GSignalFlags        signal_flags,
-                   GCallback           handler,
-                   GSignalAccumulator  accumulator,
-                   gpointer            accu_data,
-                   GSignalCMarshaller  c_marshaller,
-                   GType               return_type,
-                   guint               n_params,
-                   ...)
-{
-  va_list args;
-  guint signal_id;
-
-  g_return_val_if_fail (signal_name != NULL, 0);
-  
-  va_start (args, n_params);
-
-  signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
-                                   g_cclosure_new (handler, NULL, NULL),
-                                  accumulator, accu_data, c_marshaller,
-                                   return_type, n_params, args);
-
-  va_end (args);
-  return signal_id;
-}
-
 static void
 gtk_menu_shell_class_init (GtkMenuShellClass *klass)
 {
@@ -293,14 +264,14 @@ gtk_menu_shell_class_init (GtkMenuShellClass *klass)
                  _gtk_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
   menu_shell_signals[CYCLE_FOCUS] =
-    binding_signal_new ("cycle_focus",
-                       G_OBJECT_CLASS_TYPE (object_class),
-                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-                       G_CALLBACK (gtk_real_menu_shell_cycle_focus),
-                       NULL, NULL,
-                       _gtk_marshal_VOID__ENUM,
-                       G_TYPE_NONE, 1,
-                       GTK_TYPE_DIRECTION_TYPE);
+    _gtk_binding_signal_new ("cycle_focus",
+                            G_OBJECT_CLASS_TYPE (object_class),
+                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                            G_CALLBACK (gtk_real_menu_shell_cycle_focus),
+                            NULL, NULL,
+                            _gtk_marshal_VOID__ENUM,
+                            G_TYPE_NONE, 1,
+                            GTK_TYPE_DIRECTION_TYPE);
 
 
   binding_set = gtk_binding_set_by_class (klass);
@@ -861,7 +832,9 @@ gtk_menu_shell_select_item (GtkMenuShell *menu_shell,
 
   class = GTK_MENU_SHELL_GET_CLASS (menu_shell);
 
-  if (class->select_item)
+  if (class->select_item &&
+      !(menu_shell->active &&
+       menu_shell->active_menu_item == menu_item))
     class->select_item (menu_shell, menu_item);
 }
 
@@ -1033,9 +1006,9 @@ gtk_menu_shell_select_first (GtkMenuShell *menu_shell,
     gtk_menu_shell_select_item (menu_shell, to_select);
 }
 
-static void
-gtk_menu_shell_select_last (GtkMenuShell *menu_shell,
-                           gboolean      search_sensitive)
+void
+_gtk_menu_shell_select_last (GtkMenuShell *menu_shell,
+                            gboolean      search_sensitive)
 {
   GtkWidget *to_select = NULL;
   GList *tmp_list;
@@ -1134,7 +1107,7 @@ gtk_real_menu_shell_move_current (GtkMenuShell      *menu_shell,
       if (!had_selection &&
          !menu_shell->active_menu_item &&
          menu_shell->children)
-       gtk_menu_shell_select_last (menu_shell, TRUE);
+       _gtk_menu_shell_select_last (menu_shell, TRUE);
       break;
     case GTK_MENU_DIR_NEXT:
       gtk_menu_shell_move_selected (menu_shell, 1);
index 2177223059cc76f326cffe72a29749bcd1e14481..7b4e32af5c5e497054408debf189b4efd4477563 100644 (file)
@@ -112,6 +112,8 @@ void  gtk_menu_shell_activate_item     (GtkMenuShell *menu_shell,
                                        gboolean      force_deactivate);
 void  gtk_menu_shell_select_first      (GtkMenuShell *menu_shell,
                                        gboolean      search_sensitive);
+void _gtk_menu_shell_select_last       (GtkMenuShell *menu_shell,
+                                       gboolean      search_sensitive);
 void  _gtk_menu_shell_activate         (GtkMenuShell *menu_shell);
 gint  _gtk_menu_shell_get_popup_delay  (GtkMenuShell *menu_shell);