]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkmenushell.c
Fix the behaviour of insensitive actions, which was broken when
[~andy/gtk] / gtk / gtkmenushell.c
index 683de2666b2706796bf09ad044214ae53f7ecb2a..80eb0d97499d28028a78297b7d53468ca1f0c09c 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);
@@ -352,7 +323,6 @@ gtk_menu_shell_init (GtkMenuShell *menu_shell)
   menu_shell->active = FALSE;
   menu_shell->have_grab = FALSE;
   menu_shell->have_xgrab = FALSE;
-  menu_shell->ignore_leave = FALSE;
   menu_shell->button = 0;
   menu_shell->menu_flag = 0;
   menu_shell->activate_time = 0;
@@ -566,8 +536,13 @@ gtk_menu_shell_button_release (GtkWidget      *widget,
              gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
              return TRUE;
            }
+
+         /* If we ended up on an item with a submenu, leave the menu up.
+          */
+         if (menu_item && (menu_shell->active_menu_item == menu_item))
+           deactivate = FALSE;
        }
-      else
+      else /* a very fast press-release */
        {
          /* We only ever want to prevent deactivation on the first
            * press/release. Setting the time to zero is a bit of a
@@ -580,18 +555,6 @@ gtk_menu_shell_button_release (GtkWidget      *widget,
          deactivate = FALSE;
        }
       
-      /* If the button click was very fast, or we ended up on a submenu,
-       * leave the menu up
-       */
-      if (!deactivate || 
-         (menu_item && (menu_shell->active_menu_item == menu_item)))
-       {
-         deactivate = FALSE;
-         menu_shell->ignore_leave = TRUE;
-       }
-      else
-       deactivate = TRUE;
-
       if (deactivate)
        {
          gtk_menu_shell_deactivate (menu_shell);
@@ -692,12 +655,6 @@ gtk_menu_shell_leave_notify (GtkWidget        *widget,
 
       menu_item = GTK_MENU_ITEM (event_widget);
 
-      if (menu_shell->ignore_leave)
-       {
-         menu_shell->ignore_leave = FALSE;
-         return TRUE;
-       }
-
       if (!_gtk_menu_item_is_selectable (event_widget))
        return TRUE;
 
@@ -861,7 +818,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);
 }
 
@@ -1003,6 +962,8 @@ gtk_menu_shell_move_selected (GtkMenuShell  *menu_shell,
  * Select the first visible or selectable child of the menu shell;
  * don't select tearoff items unless the only item is a tearoff
  * item.
+ *
+ * Since: 2.2
  **/
 void
 gtk_menu_shell_select_first (GtkMenuShell *menu_shell,
@@ -1031,9 +992,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;
@@ -1095,6 +1056,20 @@ gtk_real_menu_shell_move_current (GtkMenuShell      *menu_shell,
              gtk_menu_shell_select_submenu_first (parent_menu_shell); 
            }
        }
+      /* If there is no parent and the submenu is in the opposite direction
+       * to the menu, then make the PARENT direction wrap around to
+       * the bottom of the submenu.
+       */
+      else if (menu_shell->active_menu_item &&
+              _gtk_menu_item_is_selectable (menu_shell->active_menu_item) &&
+              GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu)
+       {
+         GtkMenuShell *submenu = GTK_MENU_SHELL (GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu);
+
+         if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement !=
+             GTK_MENU_SHELL_GET_CLASS (submenu)->submenu_placement)
+           _gtk_menu_shell_select_last (submenu, TRUE);
+       }
       break;
       
     case GTK_MENU_DIR_CHILD:
@@ -1132,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);
@@ -1200,7 +1175,7 @@ _gtk_menu_shell_get_popup_delay (GtkMenuShell *menu_shell)
       gint popup_delay;
       GtkWidget *widget = GTK_WIDGET (menu_shell);
       
-      g_object_get (G_OBJECT (gtk_widget_get_settings (widget)),
+      g_object_get (gtk_widget_get_settings (widget),
                    "gtk-menu-popup-delay", &popup_delay,
                    NULL);