Patch to use normal focus system for menu keynav



This patch attempts to address one of the issues Owen raised in 
http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00224.html.

A grab is not done when F10 is used to focus the menubar or a item in the 
menubar is clicked by the mouse. Instead the focus is changed to the menubar and 
is changed back to the previously focussed widget when leaving the menu bar.

Can this patch be committed?


Index: gtk/gtkmenushell.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenushell.c,v
retrieving revision 1.51
diff -u -p -r1.51 gtkmenushell.c
--- gtk/gtkmenushell.c	2002/01/16 08:53:15	1.51
+++ gtk/gtkmenushell.c	2002/01/16 09:25:33
@@ -147,6 +147,9 @@ static void gtk_real_menu_shell_activate
 						  gboolean           
force_hide);
 static void gtk_real_menu_shell_cancel           (GtkMenuShell      
*menu_shell);
 
+static void focus_widget_destroyed           (gpointer          data,
+                                              GtkWindow         *window);
+
 static GtkContainerClass *parent_class = NULL;
 static guint menu_shell_signals[LAST_SIGNAL] = { 0 };
 
@@ -402,7 +405,7 @@ gtk_menu_shell_button_press (GtkWidget  
     {
       if (!menu_shell->active)
 	{
-	  gtk_grab_add (GTK_WIDGET (widget));
+	  _gtk_menu_shell_activate (menu_shell);
 	  menu_shell->have_grab = TRUE;
 	  menu_shell->active = TRUE;
 	}
@@ -736,8 +739,42 @@ gtk_real_menu_shell_deactivate (GtkMenuS
 
       if (menu_shell->have_grab)
 	{
+          GtkWidget *toplevel;
+
+          toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell));
+          if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
+            {
+              GtkWindow *window;
+              GtkWidget *previous_focus;
+
+              window = GTK_WINDOW (toplevel);
+              previous_focus = g_object_get_data (G_OBJECT (window), 
+                                                  "gtk-previous-focus-widget");
+
+              if (previous_focus)
+                {
+                  g_object_weak_unref (G_OBJECT (previous_focus), 
+                                        (GWeakNotify) focus_widget_destroyed,
+                                       window);
+                  g_object_set_data (G_OBJECT (window), 
+                                     "gtk-previous-focus-widget",
+                                     NULL);
+                  if (gtk_widget_is_ancestor (previous_focus, toplevel))
+                    {
+	              gtk_window_set_focus (window, previous_focus);
+                    }
+                  else
+                    {
+	              gtk_window_set_focus (window, NULL);
+                    }
+
+                }
+              else
+                {
+	          gtk_window_set_focus (window, previous_focus);
+                }
+            }
 	  menu_shell->have_grab = FALSE;
-	  gtk_grab_remove (GTK_WIDGET (menu_shell));
 	}
       if (menu_shell->have_xgrab)
 	{
@@ -1039,4 +1076,48 @@ gtk_real_menu_shell_cancel (GtkMenuShell
   
   gtk_menu_shell_deactivate (menu_shell);
   gtk_signal_emit (GTK_OBJECT (menu_shell), 
menu_shell_signals[SELECTION_DONE]);
+}
+
+void
+_gtk_menu_shell_activate (GtkMenuShell *menu_shell)
+{
+  GtkWidget *toplevel;
+
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell));
+  if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
+    {
+      GtkWindow *window;
+      GtkWidget *focus_widget;
+
+      window = GTK_WINDOW (toplevel);
+      focus_widget = window->focus_widget;
+
+      if (focus_widget && !GTK_IS_MENU_SHELL (focus_widget))
+        {
+          GtkWidget *previous_focus;
+
+          previous_focus = g_object_get_data (G_OBJECT (window), 
+                                              "gtk-previous-focus-widget");
+          if (!previous_focus)
+            {
+              g_object_set_data (G_OBJECT (window), 
+                                 "gtk-previous-focus-widget",
+                                 focus_widget);
+              g_object_weak_ref (G_OBJECT (focus_widget),
+                                 (GWeakNotify) focus_widget_destroyed, 
+                                 window);
+
+            }
+        }
+      gtk_widget_grab_focus (GTK_WIDGET (menu_shell));
+    }
+}
+
+static void
+focus_widget_destroyed (gpointer  data,
+                        GtkWindow *window)
+{
+  g_object_set_data (G_OBJECT (window), 
+                     "gtk-previous-focus-widget",
+                     NULL);
 }
Index: gtk/gtkmenushell.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenushell.h,v
retrieving revision 1.12
diff -u -p -r1.12 gtkmenushell.h
--- gtk/gtkmenushell.h	2000/11/22 01:00:26	1.12
+++ gtk/gtkmenushell.h	2002/01/16 09:25:33
@@ -104,6 +104,7 @@ void    gtk_menu_shell_deselect    (GtkM
 void    gtk_menu_shell_activate_item  (GtkMenuShell      *menu_shell,
 				       GtkWidget         *menu_item,
 				       gboolean           force_deactivate);
+void	_gtk_menu_shell_activate   (GtkMenuShell *menu_shell);
 
 
 #ifdef __cplusplus
Index: gtk/gtkmenuitem.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenuitem.c,v
retrieving revision 1.69
diff -u -p -r1.69 gtkmenuitem.c
--- gtk/gtkmenuitem.c	2002/01/15 13:24:03	1.69
+++ gtk/gtkmenuitem.c	2002/01/16 09:25:33
@@ -752,7 +752,7 @@ gtk_real_menu_item_activate_item (GtkMen
 
 	  if (!menu_shell->active)
 	    {
-	      gtk_grab_add (GTK_WIDGET (menu_shell));
+	      _gtk_menu_shell_activate (menu_shell);
 	      menu_shell->have_grab = TRUE;
 	      menu_shell->active = TRUE;
 	    }


Padraig




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]