moving ::focus from container to widget



Hi,

About to put in the following patch, which moves the "focus" method
from container to widget, to handle cases where a widget has focusable
locations which are not child widgets.

This also removes code checking visible/sensitive/focusable from
container implementations, so cleans things up along these lines:

-      if (GTK_WIDGET_DRAWABLE (bin->child) &&
-	  GTK_WIDGET_IS_SENSITIVE (bin->child))
-	{
-	  if (GTK_IS_CONTAINER (bin->child))
-	    {
-	      if (gtk_container_focus (GTK_CONTAINER (bin->child), direction))
-		return TRUE;
-	    }
-	  else if (GTK_WIDGET_CAN_FOCUS (bin->child))
-	    {
-	      gtk_widget_grab_focus (bin->child);
-	      return TRUE;
-	    }
-	}
+      
+      if (gtk_widget_child_focus (bin->child, direction))
+        return TRUE;

As you can see from the above RTTI hack, the virtual function was
simply on the wrong class before.

This will break any widgets overriding GtkContainer::focus in an
easy-to-fix way. There's a note in Changes-2.0.txt included.

Havoc

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.2027
diff -u -u -p -r1.2027 ChangeLog
--- ChangeLog	2001/06/07 22:01:25	1.2027
+++ ChangeLog	2001/06/08 18:01:41
@@ -1,3 +1,23 @@
+2001-06-08  Havoc Pennington  <hp redhat com>
+
+	* gtk/gtktextbuffer.c (gtk_text_buffer_remove_all_tags): geez,
+	don't call g_list funcs on GSList
+
+	* gtk/gtkwidget.c (gtk_widget_child_focus): replaces
+	gtk_container_focus(), since some widgets have focusable locations
+	which are not other widgets. These widgets should not have to be 
+	containers just to manage the focus. For example, GtkHSV is
+	currently a container for no good reason. Also, this cleans
+	up the "if (is_container && is_sensitive && is_drawable)
+	container_focus ()" mess in widget implementations.
+
+	* gtk/gtkcontainer.c (gtk_container_focus): deprecate this
+	function, and have it just call gtk_widget_child_focus().
+
+	* gtk/gtkhsv.c: derive from widget not container
+	
+	Throughout: fix to reflect GtkContainer::focus change
+	
 2001-06-07  Havoc Pennington  <hp redhat com>
 
 	* gtk/Makefile.am: fix glib-mkenums and glib-genmarshal again
Index: docs/Changes-2.0.txt
===================================================================
RCS file: /cvs/gnome/gtk+/docs/Changes-2.0.txt,v
retrieving revision 1.19
diff -u -u -p -r1.19 Changes-2.0.txt
--- docs/Changes-2.0.txt	2001/06/04 23:15:48	1.19
+++ docs/Changes-2.0.txt	2001/06/08 18:01:41
@@ -352,3 +352,16 @@ Incompatible Changes from GTK+-1.2 to GT
   these widgets will need a rewrite (though if you could figure out
   how to subclass the old version of GtkRange, you have our
   respect). Also, GtkTroughType is gone.
+
+* The GtkContainer::focus signal/virtualfunction and
+  gtk_container_focus() call were replaced by 
+  GtkWidget::focus and gtk_widget_child_focus(). 
+  The semantics are the same, so you should be able to just 
+  replace "container_class->focus = mywidget_focus" with 
+  "widget_class->focus = mywidget_focus" and replace 
+  gtk_container_focus() calls with gtk_widget_child_focus() calls.
+
+  The purpose of this change was to allow non-containers to have 
+  focusable elements.
+ 
+ 
\ No newline at end of file
Index: docs/reference/gtk/tmpl/gtk-unused.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtk-unused.sgml,v
retrieving revision 1.46
diff -u -u -p -r1.46 gtk-unused.sgml
--- docs/reference/gtk/tmpl/gtk-unused.sgml	2001/06/05 21:53:55	1.46
+++ docs/reference/gtk/tmpl/gtk-unused.sgml	2001/06/08 18:01:41
@@ -361,6 +361,15 @@ Define a function pointer.  Deprecated.
 @arg: 
 @arg_id: 
 
+<!-- ##### SIGNAL GtkContainer::focus ##### -->
+<para>
+
+</para>
+
+ container: the object which received the signal.
+ direction: 
+ Returns: 
+
 <!-- ##### ARG GtkContainer:reallocate-redraws ##### -->
 <para>
 
Index: docs/reference/gtk/tmpl/gtkcontainer.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkcontainer.sgml,v
retrieving revision 1.8
diff -u -u -p -r1.8 gtkcontainer.sgml
--- docs/reference/gtk/tmpl/gtkcontainer.sgml	2001/05/18 18:28:52	1.8
+++ docs/reference/gtk/tmpl/gtkcontainer.sgml	2001/06/08 18:01:41
@@ -382,15 +382,6 @@ GtkContainer
 
 @container: the object which received the signal.
 
-<!-- ##### SIGNAL GtkContainer::focus ##### -->
-<para>
-
-</para>
-
- container: the object which received the signal.
- direction: 
- Returns: 
-
 <!-- ##### SIGNAL GtkContainer::remove ##### -->
 <para>
 
Index: docs/reference/gtk/tmpl/gtkwidget.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkwidget.sgml,v
retrieving revision 1.21
diff -u -u -p -r1.21 gtkwidget.sgml
--- docs/reference/gtk/tmpl/gtkwidget.sgml	2001/05/11 17:13:44	1.21
+++ docs/reference/gtk/tmpl/gtkwidget.sgml	2001/06/08 18:01:41
@@ -1530,6 +1530,15 @@ GtkWidget
 @event: 
 @Returns: 
 
+<!-- ##### SIGNAL GtkWidget::focus ##### -->
+<para>
+
+</para>
+
+ widget: the object which received the signal.
+ arg1: 
+ Returns: 
+
 <!-- ##### SIGNAL GtkWidget::focus-in-event ##### -->
 <para>
 
Index: gtk/gtkclist.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkclist.c,v
retrieving revision 1.194
diff -u -u -p -r1.194 gtkclist.c
--- gtk/gtkclist.c	2001/06/04 21:55:20	1.194
+++ gtk/gtkclist.c	2001/06/08 18:01:42
@@ -216,7 +216,7 @@ static gint gtk_clist_focus_in        (G
 				       GdkEventFocus    *event);
 static gint gtk_clist_focus_out       (GtkWidget        *widget,
 				       GdkEventFocus    *event);
-static gint gtk_clist_focus           (GtkContainer     *container,
+static gint gtk_clist_focus           (GtkWidget        *widget,
 				       GtkDirectionType  direction);
 static void gtk_clist_set_focus_child (GtkContainer     *container,
 				       GtkWidget        *child);
@@ -530,12 +530,12 @@ gtk_clist_class_init (GtkCListClass *kla
   widget_class->drag_drop = gtk_clist_drag_drop;
   widget_class->drag_data_get = gtk_clist_drag_data_get;
   widget_class->drag_data_received = gtk_clist_drag_data_received;
-
+  widget_class->focus = gtk_clist_focus;
+  
   /* container_class->add = NULL; use the default GtkContainerClass warning */
   /* container_class->remove=NULL; use the default GtkContainerClass warning */
 
   container_class->forall = gtk_clist_forall;
-  container_class->focus = gtk_clist_focus;
   container_class->set_focus_child = gtk_clist_set_focus_child;
 
   klass->set_scroll_adjustments = gtk_clist_set_scroll_adjustments;
@@ -6402,23 +6402,22 @@ gtk_clist_focus_content_area (GtkCList *
 }
 
 static gboolean
-gtk_clist_focus (GtkContainer     *container,
+gtk_clist_focus (GtkWidget        *widget,
 		 GtkDirectionType  direction)
 {
-  GtkCList *clist = GTK_CLIST (container);
-  GtkWidget *focus_child = container->focus_child;
+  GtkCList *clist = GTK_CLIST (widget);
+  GtkWidget *focus_child;
   gboolean is_current_focus;
 
-  if (!GTK_WIDGET_IS_SENSITIVE (container))
+  if (!GTK_WIDGET_IS_SENSITIVE (widget))
     return FALSE;
 
+  focus_child = GTK_CONTAINER (widget)->focus_child;
+  
   is_current_focus = gtk_widget_is_focus (GTK_WIDGET (clist));
 			  
   if (focus_child &&
-      GTK_IS_CONTAINER (focus_child) &&
-      GTK_WIDGET_DRAWABLE (focus_child) &&
-      GTK_WIDGET_IS_SENSITIVE (focus_child) &&
-      gtk_container_focus (GTK_CONTAINER (focus_child), direction))
+      gtk_widget_child_focus (focus_child, direction))
     return TRUE;
       
   switch (direction)
@@ -6562,8 +6561,7 @@ focus_column (GtkCList *clist, gint colu
 {
   GtkWidget *child = clist->column[column].button;
   
-  if (GTK_IS_CONTAINER (child) &&
-      gtk_container_focus (GTK_CONTAINER (child), dir))
+  if (gtk_widget_child_focus (child, dir))
     {
       return TRUE;
     }
Index: gtk/gtkcontainer.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcontainer.c,v
retrieving revision 1.75
diff -u -u -p -r1.75 gtkcontainer.c
--- gtk/gtkcontainer.c	2001/05/18 18:30:56	1.75
+++ gtk/gtkcontainer.c	2001/06/08 18:01:42
@@ -39,7 +39,6 @@ enum {
   ADD,
   REMOVE,
   CHECK_RESIZE,
-  FOCUS,
   SET_FOCUS_CHILD,
   LAST_SIGNAL
 };
@@ -79,7 +78,7 @@ static void     gtk_container_add_unimpl
 static void     gtk_container_remove_unimplemented (GtkContainer      *container,
 						    GtkWidget         *widget);
 static void     gtk_container_real_check_resize    (GtkContainer      *container);
-static gboolean gtk_container_real_focus           (GtkContainer      *container,
+static gboolean gtk_container_focus                (GtkWidget         *widget,
 						    GtkDirectionType   direction);
 static void     gtk_container_real_set_focus_child (GtkContainer      *container,
 						    GtkWidget         *widget);
@@ -205,12 +204,12 @@ gtk_container_class_init (GtkContainerCl
   widget_class->show_all = gtk_container_show_all;
   widget_class->hide_all = gtk_container_hide_all;
   widget_class->expose_event = gtk_container_expose;
+  widget_class->focus = gtk_container_focus;
   
   class->add = gtk_container_add_unimplemented;
   class->remove = gtk_container_remove_unimplemented;
   class->check_resize = gtk_container_real_check_resize;
   class->forall = NULL;
-  class->focus = gtk_container_real_focus;
   class->set_focus_child = gtk_container_real_set_focus_child;
   class->child_type = NULL;
   class->composite_name = gtk_container_child_default_composite_name;
@@ -238,14 +237,6 @@ gtk_container_class_init (GtkContainerCl
                     GTK_SIGNAL_OFFSET (GtkContainerClass, check_resize),
 		    gtk_marshal_VOID__VOID,
 		    GTK_TYPE_NONE, 0);
-  container_signals[FOCUS] =
-    gtk_signal_new ("focus",
-                    GTK_RUN_LAST,
-                    GTK_CLASS_TYPE (object_class),
-                    GTK_SIGNAL_OFFSET (GtkContainerClass, focus),
-                    gtk_marshal_ENUM__ENUM,
-		    GTK_TYPE_DIRECTION_TYPE, 1,
-                    GTK_TYPE_DIRECTION_TYPE);
   container_signals[SET_FOCUS_CHILD] =
     gtk_signal_new ("set-focus-child",
                     GTK_RUN_FIRST,
@@ -1282,22 +1273,6 @@ gtk_container_foreach_full (GtkContainer
     notify (callback_data);
 }
 
-gboolean
-gtk_container_focus (GtkContainer     *container,
-		     GtkDirectionType  direction)
-{
-  gint return_val;
-
-  g_return_val_if_fail (container != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
-  
-  gtk_signal_emit (GTK_OBJECT (container),
-                   container_signals[FOCUS],
-                   direction, &return_val);
-
-  return return_val;
-}
-
 void
 gtk_container_set_focus_child (GtkContainer *container,
 			       GtkWidget    *widget)
@@ -1480,20 +1455,16 @@ filter_unfocusable (GtkContainer *contai
 }
 
 static gboolean
-gtk_container_real_focus (GtkContainer     *container,
-			  GtkDirectionType  direction)
+gtk_container_focus (GtkWidget        *widget,
+                     GtkDirectionType  direction)
 {
   GList *children;
   gint return_val;
+  GtkContainer *container;
 
-  g_return_val_if_fail (container != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
+  g_return_val_if_fail (GTK_IS_CONTAINER (widget), FALSE);
 
-  /* Fail if the container is inappropriate for focus movement
-   */
-  if (!GTK_WIDGET_DRAWABLE (container) ||
-      !GTK_WIDGET_IS_SENSITIVE (container))
-    return FALSE;
+  container = GTK_CONTAINER (widget);
 
   return_val = FALSE;
 
@@ -1936,25 +1907,15 @@ gtk_container_focus_move (GtkContainer  
             {
               focus_child = NULL;
 
-              if (GTK_WIDGET_DRAWABLE (child) &&
-		  GTK_IS_CONTAINER (child))
-		if (gtk_container_focus (GTK_CONTAINER (child), direction))
+		if (gtk_widget_child_focus (child, direction))
 		  return TRUE;
             }
         }
       else if (GTK_WIDGET_DRAWABLE (child) &&
                gtk_widget_is_ancestor (child, GTK_WIDGET (container)))
         {
-	  if (GTK_IS_CONTAINER (child))
-            {
-              if (gtk_container_focus (GTK_CONTAINER (child), direction))
-                return TRUE;
-            }
-          else if (GTK_WIDGET_CAN_FOCUS (child))
-            {
-              gtk_widget_grab_focus (child);
-              return TRUE;
-            }
+          if (gtk_widget_child_focus (child, direction))
+            return TRUE;
         }
     }
 
Index: gtk/gtkcontainer.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcontainer.h,v
retrieving revision 1.37
diff -u -u -p -r1.37 gtkcontainer.h
--- gtk/gtkcontainer.h	2001/03/22 20:59:37	1.37
+++ gtk/gtkcontainer.h	2001/06/08 18:01:42
@@ -83,9 +83,7 @@ struct _GtkContainerClass
   void (* forall)     		(GtkContainer	 *container,
 				 gboolean	  include_internals,
 				 GtkCallback	  callback,
-				 gpointer	  callbabck_data);
-  gboolean (* focus)   		(GtkContainer	 *container,
-				 GtkDirectionType  direction);
+				 gpointer	  callback_data);
   void (* set_focus_child)	(GtkContainer	 *container,
 				 GtkWidget	 *widget);
   GtkType (*child_type)		(GtkContainer	*container);
@@ -129,8 +127,6 @@ void     gtk_container_foreach_full (Gtk
 				     gpointer            callback_data,
 				     GtkDestroyNotify    notify);
 GList*   gtk_container_children     (GtkContainer       *container);
-gboolean gtk_container_focus        (GtkContainer       *container,
-				     GtkDirectionType    direction);
 void     gtk_container_propagate_expose (GtkContainer   *container,
 					 GtkWidget      *child,
 					 GdkEventExpose *event);
@@ -203,8 +199,7 @@ void    gtk_container_addv		   (GtkConta
 void	gtk_container_child_set		   (GtkContainer      *container,
 					    GtkWidget         *child,
 					    const gchar	      *first_arg_name,
-					    ...);
-     
+					    ...);     
 
 /* Non-public methods */
 
Index: gtk/gtkhsv.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkhsv.c,v
retrieving revision 1.11
diff -u -u -p -r1.11 gtkhsv.c
--- gtk/gtkhsv.c	2001/05/11 22:24:59	1.11
+++ gtk/gtkhsv.c	2001/06/08 18:01:42
@@ -103,7 +103,7 @@ static gint gtk_hsv_motion         (GtkW
 				    GdkEventMotion *event);
 static gint gtk_hsv_expose         (GtkWidget      *widget,
 				    GdkEventExpose *event);
-static gboolean gtk_hsv_focus      (GtkContainer    *container,
+static gboolean gtk_hsv_focus      (GtkWidget       *widget,
                                     GtkDirectionType direction);
 
 static void gtk_hsv_move           (GtkHSV          *hsv,
@@ -139,7 +139,7 @@ gtk_hsv_get_type (void)
       (GtkClassInitFunc) NULL
     };
     
-    hsv_type = gtk_type_unique (GTK_TYPE_CONTAINER, &hsv_info);
+    hsv_type = gtk_type_unique (GTK_TYPE_WIDGET, &hsv_info);
   }
   
   return hsv_type;
@@ -151,13 +151,11 @@ gtk_hsv_class_init (GtkHSVClass *class)
 {
   GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
-  GtkContainerClass *container_class;
   GtkHSVClass    *hsv_class;
   GtkBindingSet *binding_set;
   
   object_class = (GtkObjectClass *) class;
   widget_class = (GtkWidgetClass *) class;
-  container_class = GTK_CONTAINER_CLASS (class);
   hsv_class = GTK_HSV_CLASS (class);
   
   parent_class = gtk_type_class (GTK_TYPE_WIDGET);  
@@ -174,8 +172,7 @@ gtk_hsv_class_init (GtkHSVClass *class)
   widget_class->button_release_event = gtk_hsv_button_release;
   widget_class->motion_notify_event = gtk_hsv_motion;
   widget_class->expose_event = gtk_hsv_expose;
-
-  container_class->focus = gtk_hsv_focus;
+  widget_class->focus = gtk_hsv_focus;
   
   hsv_class->move = gtk_hsv_move;
   
@@ -1357,18 +1354,14 @@ gtk_hsv_expose (GtkWidget      *widget,
 }
 
 static gboolean
-gtk_hsv_focus (GtkContainer    *container,
+gtk_hsv_focus (GtkWidget       *widget,
                GtkDirectionType dir)
 {
   GtkHSV *hsv;
   HSVPrivate *priv;
 
-  hsv = GTK_HSV (container);
+  hsv = GTK_HSV (widget);
   priv = hsv->priv;
-  
-  if (!GTK_WIDGET_DRAWABLE (container) ||
-      !GTK_WIDGET_IS_SENSITIVE (container))
-    return FALSE;
 
   if (!GTK_WIDGET_HAS_FOCUS (hsv))
     {
Index: gtk/gtkhsv.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkhsv.h,v
retrieving revision 1.6
diff -u -u -p -r1.6 gtkhsv.h
--- gtk/gtkhsv.h	2001/03/24 06:10:39	1.6
+++ gtk/gtkhsv.h	2001/06/08 18:01:42
@@ -50,8 +50,7 @@ typedef struct _GtkHSVClass GtkHSVClass;
 
 struct _GtkHSV
 {
-  /* we derive from container purely so we can have a _focus method */
-  GtkContainer parent_instance;
+  GtkWidget parent_instance;
   
   /* Private data */
   gpointer priv;
Index: gtk/gtklist.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtklist.c,v
retrieving revision 1.59
diff -u -u -p -r1.59 gtklist.c
--- gtk/gtklist.c	2001/04/16 20:33:02	1.59
+++ gtk/gtklist.c	2001/06/08 18:01:42
@@ -75,6 +75,9 @@ static gint gtk_list_button_press    (Gt
 static gint gtk_list_button_release  (GtkWidget	     *widget,
 				      GdkEventButton *event);
 
+static gboolean gtk_list_focus       (GtkWidget        *widget,
+                                      GtkDirectionType  direction);
+
 /*** GtkContainer Methods ***/
 static void gtk_list_add	     (GtkContainer     *container,
 				      GtkWidget        *widget);
@@ -87,8 +90,6 @@ static void gtk_list_forall	     (GtkCon
 static GtkType gtk_list_child_type   (GtkContainer     *container);
 static void gtk_list_set_focus_child (GtkContainer     *container,
 				      GtkWidget        *widget);
-static gint gtk_list_focus           (GtkContainer     *container,
-				      GtkDirectionType  direction);
 
 /*** GtkList Private Functions ***/
 static void gtk_list_move_focus_child      (GtkList       *list,
@@ -228,13 +229,13 @@ gtk_list_class_init (GtkListClass *class
   widget_class->size_request = gtk_list_size_request;
   widget_class->size_allocate = gtk_list_size_allocate;
   widget_class->drag_begin = gtk_list_drag_begin;
-
+  widget_class->focus = gtk_list_focus;
+  
   container_class->add = gtk_list_add;
   container_class->remove = gtk_list_remove;
   container_class->forall = gtk_list_forall;
   container_class->child_type = gtk_list_child_type;
   container_class->set_focus_child = gtk_list_set_focus_child;
-  container_class->focus = gtk_list_focus;
 
   class->selection_changed = NULL;
   class->select_child = gtk_real_list_select_child;
@@ -973,15 +974,15 @@ gtk_list_set_focus_child (GtkContainer *
     }
 }
 
-static gint
-gtk_list_focus (GtkContainer     *container,
+static gboolean
+gtk_list_focus (GtkWidget        *widget,
 		GtkDirectionType  direction)
 {
   gint return_val = FALSE;
-
-  g_return_val_if_fail (container != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_LIST (container), FALSE);
+  GtkContainer *container;
 
+  container = GTK_CONTAINER (widget);
+  
   if (container->focus_child == NULL ||
       !GTK_WIDGET_HAS_FOCUS (container->focus_child))
     {
@@ -989,9 +990,9 @@ gtk_list_focus (GtkContainer     *contai
 	gtk_container_set_focus_child
 	  (container, GTK_LIST (container)->last_focus_child);
 
-      if (GTK_CONTAINER_CLASS (parent_class)->focus)
-	return_val = GTK_CONTAINER_CLASS (parent_class)->focus (container,
-								direction);
+      if (GTK_WIDGET_CLASS (parent_class)->focus)
+	return_val = GTK_WIDGET_CLASS (parent_class)->focus (widget,
+                                                             direction);
     }
 
   if (!return_val)
Index: gtk/gtkmarshal.list
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmarshal.list,v
retrieving revision 1.33
diff -u -u -p -r1.33 gtkmarshal.list
--- gtk/gtkmarshal.list	2001/06/07 00:07:31	1.33
+++ gtk/gtkmarshal.list	2001/06/08 18:01:42
@@ -23,6 +23,7 @@
 
 BOOLEAN:BOXED
 BOOLEAN:BOXED,BOXED
+BOOLEAN:ENUM
 BOOLEAN:OBJECT,INT,INT,UINT
 BOOLEAN:OBJECT,STRING,STRING,BOXED
 BOOLEAN:OBJECT,BOXED,BOXED
Index: gtk/gtknotebook.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtknotebook.c,v
retrieving revision 1.89
diff -u -u -p -r1.89 gtknotebook.c
--- gtk/gtknotebook.c	2001/05/17 16:22:04	1.89
+++ gtk/gtknotebook.c	2001/06/08 18:01:42
@@ -156,6 +156,8 @@ static gint gtk_notebook_focus_in       
 static void gtk_notebook_draw_focus          (GtkWidget        *widget);
 static void gtk_notebook_style_set           (GtkWidget        *widget,
 					      GtkStyle         *previous_style);
+static gint gtk_notebook_focus               (GtkWidget        *widget,
+					      GtkDirectionType  direction);
 
 /*** GtkContainer Methods ***/
 static void gtk_notebook_set_child_arg	     (GtkContainer     *container,
@@ -170,8 +172,6 @@ static void gtk_notebook_add            
 					      GtkWidget        *widget);
 static void gtk_notebook_remove              (GtkContainer     *container,
 					      GtkWidget        *widget);
-static gint gtk_notebook_focus               (GtkContainer     *container,
-					      GtkDirectionType  direction);
 static void gtk_notebook_set_focus_child     (GtkContainer     *container,
 					      GtkWidget        *child);
 static GtkType gtk_notebook_child_type       (GtkContainer     *container);
@@ -310,11 +310,11 @@ gtk_notebook_class_init (GtkNotebookClas
   widget_class->motion_notify_event = gtk_notebook_motion_notify;
   widget_class->focus_in_event = gtk_notebook_focus_in;
   widget_class->style_set = gtk_notebook_style_set;
-   
+  widget_class->focus = gtk_notebook_focus;
+  
   container_class->add = gtk_notebook_add;
   container_class->remove = gtk_notebook_remove;
   container_class->forall = gtk_notebook_forall;
-  container_class->focus = gtk_notebook_focus;
   container_class->set_focus_child = gtk_notebook_set_focus_child;
   container_class->get_child_arg = gtk_notebook_get_child_arg;
   container_class->set_child_arg = gtk_notebook_set_child_arg;
@@ -1190,7 +1190,7 @@ gtk_notebook_arrow_button_press (GtkNote
 	    dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
 	  else
 	    dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
-	  gtk_container_focus (GTK_CONTAINER (notebook), dir);
+	  gtk_widget_child_focus (widget, dir);
 	}
       
       if (!notebook->timer)
@@ -1677,28 +1677,14 @@ static gboolean
 focus_child_in (GtkNotebook     *notebook,
 		GtkDirectionType direction)
 {
-  if (GTK_WIDGET_DRAWABLE (notebook->cur_page->child) &&
-      GTK_WIDGET_IS_SENSITIVE (notebook->cur_page->child))
-    {
-      if (GTK_IS_CONTAINER (notebook->cur_page->child))
-	{
-	  if (gtk_container_focus (GTK_CONTAINER (notebook->cur_page->child), direction))
-	    return TRUE;
-	}
-      else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
-	{
-	  gtk_widget_grab_focus (notebook->cur_page->child);
-	  return TRUE;
-	}
-    }
-  return FALSE;
+  return gtk_widget_child_focus (notebook->cur_page->child, direction);
 }
 
 /* Focus in the notebook can either be on the pages, or on
  * the tabs.
  */
 static gint
-gtk_notebook_focus (GtkContainer     *container,
+gtk_notebook_focus (GtkWidget        *widget,
 		    GtkDirectionType  direction)
 {
   GtkWidget *old_focus_child;
@@ -1720,26 +1706,23 @@ gtk_notebook_focus (GtkContainer     *co
 #undef D  
 
   gboolean widget_is_focus;
+  GtkContainer *container;
 
-  g_return_val_if_fail (container != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
+  g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
 
+  container = GTK_CONTAINER (widget);
   notebook = GTK_NOTEBOOK (container);
 
-  widget_is_focus = gtk_widget_is_focus (GTK_WIDGET (container));
+  widget_is_focus = gtk_widget_is_focus (widget);
   old_focus_child = container->focus_child; 
 
   effective_direction = translate_direction[notebook->tab_pos][direction];
 
-  if (old_focus_child &&
-      GTK_IS_CONTAINER (old_focus_child) &&
-      GTK_WIDGET_DRAWABLE (old_focus_child) &&
-      GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
-      gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
-    return TRUE;
-
   if (old_focus_child)		/* Focus on page child */
     {
+      if (gtk_widget_child_focus (old_focus_child, direction))
+        return TRUE;
+      
       switch (effective_direction)
 	{
 	case GTK_DIR_TAB_BACKWARD:
@@ -2041,14 +2024,14 @@ gtk_notebook_timer (GtkNotebook *noteboo
 	  if (!notebook->focus_tab ||
 	      gtk_notebook_search_page (notebook, notebook->focus_tab,
 					STEP_PREV, TRUE))
-	    gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
+	    gtk_widget_child_focus (GTK_WIDGET (notebook), GTK_DIR_LEFT);
 	}
       else if (notebook->click_child == GTK_ARROW_RIGHT)
 	{
 	  if (!notebook->focus_tab ||
 	      gtk_notebook_search_page (notebook, notebook->focus_tab,
 					STEP_NEXT, TRUE))
-	    gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
+	    gtk_widget_child_focus (GTK_WIDGET (notebook), GTK_DIR_RIGHT);
 	}
       if (notebook->need_timer) 
 	{
@@ -3490,22 +3473,10 @@ gtk_notebook_page_select (GtkNotebook *n
 	case GTK_POS_RIGHT:
 	  dir = GTK_DIR_LEFT;
 	  break;
-	}
-      
-      if (GTK_WIDGET_VISIBLE (page->child))
-	{
-	  if (GTK_IS_CONTAINER (page->child))
-	    {
-	      if (gtk_container_focus (GTK_CONTAINER (page->child), 
-				       dir))
-		return TRUE;
-	    }
-	  else if (GTK_WIDGET_CAN_FOCUS (page->child))
-	    {
-	      gtk_widget_grab_focus (page->child);
-	      return TRUE;
-	    }
 	}
+
+      if (gtk_widget_child_focus (page->child, dir))
+        return TRUE;
     }
   return FALSE;
 }
Index: gtk/gtkplug.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkplug.c,v
retrieving revision 1.24
diff -u -u -p -r1.24 gtkplug.c
--- gtk/gtkplug.c	2001/04/23 19:51:06	1.24
+++ gtk/gtkplug.c	2001/06/08 18:01:42
@@ -43,7 +43,7 @@ static void            gtk_plug_forward_
 						       GdkEventKey      *event);
 static void            gtk_plug_set_focus             (GtkWindow        *window,
 						       GtkWidget        *focus);
-static gboolean        gtk_plug_focus                 (GtkContainer     *container,
+static gboolean        gtk_plug_focus                 (GtkWidget        *widget,
 						       GtkDirectionType  direction);
 static void            gtk_plug_accel_entries_changed (GtkWindow        *window);
 static GdkFilterReturn gtk_plug_filter_func           (GdkXEvent        *gdk_xevent,
@@ -94,7 +94,6 @@ static void
 gtk_plug_class_init (GtkPlugClass *class)
 {
   GtkWidgetClass *widget_class = (GtkWidgetClass *)class;
-  GtkContainerClass *container_class = (GtkContainerClass *)class;
   GtkWindowClass *window_class = (GtkWindowClass *)class;
 
   parent_class = gtk_type_class (GTK_TYPE_WINDOW);
@@ -103,7 +102,7 @@ gtk_plug_class_init (GtkPlugClass *class
   widget_class->unrealize = gtk_plug_unrealize;
   widget_class->key_press_event = gtk_plug_key_press_event;
 
-  container_class->focus = gtk_plug_focus;
+ widget_class->focus = gtk_plug_focus;
 
   window_class->set_focus = gtk_plug_set_focus;
 #if 0  
@@ -441,12 +440,13 @@ gtk_plug_accel_entries_changed (GtkWindo
 #endif
 
 static gboolean
-gtk_plug_focus (GtkContainer     *container,
+gtk_plug_focus (GtkWidget        *widget,
 		GtkDirectionType  direction)
 {
-  GtkBin *bin = GTK_BIN (container);
-  GtkPlug *plug = GTK_PLUG (container);
-  GtkWindow *window = GTK_WINDOW (container);
+  GtkBin *bin = GTK_BIN (widget);
+  GtkPlug *plug = GTK_PLUG (widget);
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkContainer *container = GTK_CONTAINER (widget);
   GtkWidget *old_focus_child = container->focus_child;
   GtkWidget *parent;
   
@@ -454,10 +454,7 @@ gtk_plug_focus (GtkContainer     *contai
    */
   if (old_focus_child)
     {
-      if (GTK_IS_CONTAINER (old_focus_child) &&
-	  GTK_WIDGET_DRAWABLE (old_focus_child) &&
-	  GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
-	  gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
+      if (gtk_widget_child_focus (old_focus_child, direction))
 	return TRUE;
 
       if (window->focus_widget)
@@ -513,20 +510,9 @@ gtk_plug_focus (GtkContainer     *contai
   else
     {
       /* Try to focus the first widget in the window */
-      if (GTK_WIDGET_DRAWABLE (bin->child) &&
-	  GTK_WIDGET_IS_SENSITIVE (bin->child))
-	{
-	  if (GTK_IS_CONTAINER (bin->child))
-	    {
-	      if (gtk_container_focus (GTK_CONTAINER (bin->child), direction))
-		return TRUE;
-	    }
-	  else if (GTK_WIDGET_CAN_FOCUS (bin->child))
-	    {
-	      gtk_widget_grab_focus (bin->child);
-	      return TRUE;
-	    }
-	}
+      
+      if (gtk_widget_child_focus (bin->child, direction))
+        return TRUE;
     }
 
   return FALSE;
@@ -582,7 +568,7 @@ focus_first_last (GtkPlug          *plug
       gtk_window_set_focus (GTK_WINDOW (plug), NULL);
     }
 
-  gtk_container_focus (GTK_CONTAINER (plug), direction);
+  gtk_widget_child_focus (GTK_WIDGET (plug), direction);
 }
 
 static void
Index: gtk/gtksocket.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksocket.c,v
retrieving revision 1.24
diff -u -u -p -r1.24 gtksocket.c
--- gtk/gtksocket.c	2001/04/23 23:03:52	1.24
+++ gtk/gtksocket.c	2001/06/08 18:01:42
@@ -57,7 +57,7 @@ static void            gtk_socket_claim_
 static gboolean        gtk_socket_focus_out_event      (GtkWidget        *widget,
 							GdkEventFocus    *event);
 static void            gtk_socket_send_configure_event (GtkSocket        *socket);
-static gboolean        gtk_socket_focus                (GtkContainer     *container,
+static gboolean        gtk_socket_focus                (GtkWidget        *widget,
 							GtkDirectionType  direction);
 static GdkFilterReturn gtk_socket_filter_func          (GdkXEvent        *gdk_xevent,
 							GdkEvent         *event,
@@ -126,7 +126,7 @@ gtk_socket_class_init (GtkSocketClass *c
   widget_class->focus_in_event = gtk_socket_focus_in_event;
   widget_class->focus_out_event = gtk_socket_focus_out_event;
 
-  container_class->focus = gtk_socket_focus;
+  widget_class->focus = gtk_socket_focus;
 }
 
 static void
@@ -702,16 +702,16 @@ gtk_socket_claim_focus (GtkSocket *socke
 }
 
 static gboolean
-gtk_socket_focus (GtkContainer *container, GtkDirectionType direction)
+gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
 {
   GtkSocket *socket;
   gint detail = -1;
 
-  g_return_val_if_fail (GTK_IS_SOCKET (container), FALSE);
+  g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
   
-  socket = GTK_SOCKET (container);
+  socket = GTK_SOCKET (widget);
 
-  if (!GTK_WIDGET_HAS_FOCUS (container))
+  if (!GTK_WIDGET_HAS_FOCUS (widget))
     {
       switch (direction)
 	{
@@ -730,8 +730,8 @@ gtk_socket_focus (GtkContainer *containe
       send_xembed_message (socket, XEMBED_FOCUS_IN, detail, 0, 0,
 			   gtk_get_current_event_time ());
 
-      GTK_WIDGET_SET_FLAGS (container, GTK_HAS_FOCUS);
-      gtk_widget_grab_focus (GTK_WIDGET (container));
+      GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+      gtk_widget_grab_focus (widget);
  
       return TRUE;
     }
@@ -935,11 +935,11 @@ handle_xembed_message (GtkSocket *socket
     case XEMBED_FOCUS_PREV:
       {
 	GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
-	if (toplevel && GTK_IS_CONTAINER (toplevel))
+	if (toplevel)
 	  {
-	    gtk_container_focus (GTK_CONTAINER (toplevel),
-				 (message == XEMBED_FOCUS_NEXT ?
-				  GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
+	    gtk_widget_child_focus (toplevel,
+                                    (message == XEMBED_FOCUS_NEXT ?
+                                     GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
 	  }
 	break;
       }
Index: gtk/gtktextbuffer.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextbuffer.c,v
retrieving revision 1.47
diff -u -u -p -r1.47 gtktextbuffer.c
--- gtk/gtktextbuffer.c	2001/06/05 21:53:56	1.47
+++ gtk/gtktextbuffer.c	2001/06/08 18:01:42
@@ -2210,7 +2210,7 @@ gtk_text_buffer_remove_all_tags (GtkText
         }
     }
 
-  g_list_foreach (tags, (GFunc) g_object_ref, NULL);
+  g_slist_foreach (tags, (GFunc) g_object_ref, NULL);
   
   tmp_list = tags;
   while (tmp_list != NULL)
@@ -2222,7 +2222,7 @@ gtk_text_buffer_remove_all_tags (GtkText
       tmp_list = tmp_list->next;
     }
 
-  g_list_foreach (tags, (GFunc) g_object_unref, NULL);
+  g_slist_foreach (tags, (GFunc) g_object_unref, NULL);
   
   g_slist_free (tags);
 }
Index: gtk/gtktoolbar.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktoolbar.c,v
retrieving revision 1.55
diff -u -u -p -r1.55 gtktoolbar.c
--- gtk/gtktoolbar.c	2001/06/05 20:45:33	1.55
+++ gtk/gtktoolbar.c	2001/06/08 18:01:42
@@ -91,6 +91,8 @@ static void gtk_toolbar_size_allocate   
 				                  GtkAllocation   *allocation);
 static void gtk_toolbar_style_set                (GtkWidget       *widget,
                                                   GtkStyle        *prev_style);
+static gboolean gtk_toolbar_focus                (GtkWidget       *widget,
+                                                  GtkDirectionType dir);
 static void gtk_toolbar_show_all                 (GtkWidget       *widget);
 static void gtk_toolbar_add                      (GtkContainer    *container,
 				                  GtkWidget       *widget);
@@ -100,6 +102,7 @@ static void gtk_toolbar_forall          
 						  gboolean	   include_internals,
 				                  GtkCallback      callback,
 				                  gpointer         callback_data);
+
 static void gtk_real_toolbar_orientation_changed (GtkToolbar      *toolbar,
 						  GtkOrientation   orientation);
 static void gtk_real_toolbar_style_changed       (GtkToolbar      *toolbar,
@@ -192,11 +195,11 @@ gtk_toolbar_class_init (GtkToolbarClass 
   widget_class->size_allocate = gtk_toolbar_size_allocate;
   widget_class->style_set = gtk_toolbar_style_set;
   widget_class->show_all = gtk_toolbar_show_all;
+  widget_class->focus = gtk_toolbar_focus;
   
   container_class->add = gtk_toolbar_add;
   container_class->remove = gtk_toolbar_remove;
   container_class->forall = gtk_toolbar_forall;
-  container_class->focus = NULL;
   
   class->orientation_changed = gtk_real_toolbar_orientation_changed;
   class->style_changed = gtk_real_toolbar_style_changed;
@@ -832,6 +835,15 @@ gtk_toolbar_style_set (GtkWidget  *widge
 {
   if (prev_style)
     gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
+}
+
+static gboolean
+gtk_toolbar_focus (GtkWidget       *widget,
+                   GtkDirectionType dir)
+{
+  /* Focus can't go in toolbars */
+  
+  return FALSE;
 }
 
 static void
Index: gtk/gtktreeview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktreeview.c,v
retrieving revision 1.90
diff -u -u -p -r1.90 gtktreeview.c
--- gtk/gtktreeview.c	2001/06/07 18:06:08	1.90
+++ gtk/gtktreeview.c	2001/06/08 18:01:42
@@ -164,7 +164,7 @@ static gint     gtk_tree_view_focus_in  
 						    GdkEventFocus    *event);
 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
 						    GdkEventFocus    *event);
-static gint     gtk_tree_view_focus                (GtkContainer     *container,
+static gint     gtk_tree_view_focus                (GtkWidget        *widget,
 						    GtkDirectionType  direction);
 
 /* container signals */
@@ -418,11 +418,11 @@ gtk_tree_view_class_init (GtkTreeViewCla
   widget_class->drag_motion = gtk_tree_view_drag_motion;
   widget_class->drag_drop = gtk_tree_view_drag_drop;
   widget_class->drag_data_received = gtk_tree_view_drag_data_received;
-
+  widget_class->focus = gtk_tree_view_focus;
+  
   /* GtkContainer signals */
   container_class->remove = gtk_tree_view_remove;
   container_class->forall = gtk_tree_view_forall;
-  container_class->focus = gtk_tree_view_focus;
   container_class->set_focus_child = gtk_tree_view_set_focus_child;
 
   class->set_scroll_adjustments = gtk_tree_view_set_adjustments;
@@ -3784,7 +3784,7 @@ gtk_tree_view_header_focus (GtkTreeView 
 	  break;
 	}
 
-      if (gtk_container_focus (GTK_CONTAINER (focus_child), dir))
+      if (gtk_widget_child_focus (focus_child, dir))
 	{
 	  /* The focus moves inside the button. */
 	  /* This is probably a great example of bad UI */
@@ -3880,7 +3880,7 @@ gtk_tree_view_header_focus (GtkTreeView 
  * handling scrolling by keyboard, such that in cases.
  */
 static gint
-gtk_tree_view_focus (GtkContainer     *container,
+gtk_tree_view_focus (GtkWidget        *widget,
 		     GtkDirectionType  direction)
 {
   GtkTreeView *tree_view;
@@ -3889,11 +3889,13 @@ gtk_tree_view_focus (GtkContainer     *c
   GtkRBTree *cursor_tree;
   GtkRBNode *cursor_node;
   GtkTreePath *cursor_path;
+  GtkContainer *container;
 
-  g_return_val_if_fail (GTK_IS_TREE_VIEW (container), FALSE);
-  g_return_val_if_fail (GTK_WIDGET_VISIBLE (container), FALSE);
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
+  g_return_val_if_fail (GTK_WIDGET_VISIBLE (widget), FALSE);
 
-  tree_view = GTK_TREE_VIEW (container);
+  container = GTK_CONTAINER (widget);
+  tree_view = GTK_TREE_VIEW (widget);
 
   if (!GTK_WIDGET_IS_SENSITIVE (container))
     return FALSE;
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.219
diff -u -u -p -r1.219 gtkwidget.c
--- gtk/gtkwidget.c	2001/06/01 15:44:13	1.219
+++ gtk/gtkwidget.c	2001/06/08 18:01:42
@@ -69,6 +69,7 @@ enum {
   REMOVE_ACCELERATOR,
   ACTIVATE_MNEMONIC,
   GRAB_FOCUS,
+  FOCUS,
   EVENT,
   BUTTON_PRESS_EVENT,
   BUTTON_RELEASE_EVENT,
@@ -179,6 +180,8 @@ static void gtk_widget_style_set		 (GtkW
 static void gtk_widget_direction_changed	 (GtkWidget	    *widget,
 						  GtkTextDirection   previous_direction);
 static void gtk_widget_real_grab_focus           (GtkWidget         *focus_widget);
+static gboolean gtk_widget_real_focus            (GtkWidget         *widget,
+                                                  GtkDirectionType   direction);
 
 static GdkColormap*  gtk_widget_peek_colormap      (void);
 static GtkStyle*     gtk_widget_peek_style         (void);
@@ -323,6 +326,7 @@ gtk_widget_class_init (GtkWidgetClass *k
   klass->remove_accelerator = (void*) gtk_accel_group_handle_remove;
   klass->mnemonic_activate = gtk_widget_real_mnemonic_activate;
   klass->grab_focus = gtk_widget_real_grab_focus;
+  klass->focus = gtk_widget_real_focus;
   klass->event = NULL;
   klass->button_press_event = NULL;
   klass->button_release_event = NULL;
@@ -650,6 +654,15 @@ gtk_widget_class_init (GtkWidgetClass *k
 		    GTK_SIGNAL_OFFSET (GtkWidgetClass, grab_focus),
 		    gtk_marshal_VOID__VOID,
 		    GTK_TYPE_NONE, 0);
+  widget_signals[FOCUS] =
+    g_signal_newc ("focus",
+                   G_TYPE_FROM_CLASS (object_class),
+                   G_SIGNAL_RUN_LAST,
+                   G_STRUCT_OFFSET (GtkWidgetClass, focus),
+                   _gtk_boolean_handled_accumulator, NULL,
+                   gtk_marshal_BOOLEAN__ENUM,
+                   G_TYPE_BOOLEAN, 1,
+                   GTK_TYPE_DIRECTION_TYPE);
   widget_signals[EVENT] =
     g_signal_newc ("event",
 		   G_TYPE_FROM_CLASS(object_class),
@@ -3021,6 +3034,23 @@ gtk_widget_real_grab_focus (GtkWidget *f
     }
 }
 
+static gboolean
+gtk_widget_real_focus (GtkWidget         *widget,
+                       GtkDirectionType   direction)
+{
+  if (!GTK_WIDGET_CAN_FOCUS (widget))
+    return FALSE;
+  
+  if (!GTK_WIDGET_HAS_FOCUS (widget))
+    {
+      gtk_widget_grab_focus (widget);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+
 /**
  * gtk_widget_is_focus:
  * @widget: a #GtkWidget
@@ -4118,6 +4148,66 @@ gtk_widget_get_parent_window   (GtkWidge
 					     quark_parent_window);
 
   return (parent_window != NULL) ? parent_window : widget->parent->window;
+}
+
+/**
+ * gtk_widget_child_focus:
+ * @widget: a #GtkWidget
+ * @direction: direction of focus movement
+ *
+ * This function is used by custom widget implementations; if you're
+ * writing an app, you'd use gtk_widget_grab_focus() to move the focus
+ * to a particular widget, and gtk_container_set_focus_chain() to
+ * change the focus tab order. So you may want to investigate those
+ * functions instead.
+ * 
+ * gtk_widget_child_focus() is called by containers as the user moves
+ * around the window using keyboard shortcuts. @direction indicates
+ * what kind of motion is taking place (up, down, left, right, tab
+ * forward, tab backward).  gtk_widget_child_focus() invokes the
+ * "focus" signal on #GtkWidget; widgets override the default handler
+ * for this signal in order to implement appropriate focus behavior.
+ *
+ * The "focus" default handler for a widget should return %TRUE if
+ * moving in @direction left the focus on a focusable location inside
+ * that widget, and %FALSE if moving in @direction moved the focus
+ * outside the widget. If returning %TRUE, widgets normally
+ * call gtk_widget_grab_focus() to place the focus accordingly;
+ * if returning %FALSE, they don't modify the current focus location.
+ * 
+ * This function replaces gtk_container_focus() from GTK+ 1.2.  It was
+ * necessary to check that the child was visible, sensitive, and
+ * focusable before calling
+ * gtk_container_focus(). gtk_widget_child_focus() returns %FALSE if
+ * the widget is not currently in a focusable state, so there's no
+ * need for those checks.
+ * 
+ * Return value: %TRUE if focus ended up inside @widget
+ **/
+gboolean
+gtk_widget_child_focus (GtkWidget       *widget,
+                        GtkDirectionType direction)
+{
+  gboolean return_val;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  if (!GTK_WIDGET_VISIBLE (widget) ||
+      !GTK_WIDGET_IS_SENSITIVE (widget))
+    return FALSE;
+
+  /* child widgets must set CAN_FOCUS, containers
+   * don't have to though.
+   */
+  if (!GTK_IS_CONTAINER (widget) &&
+      !GTK_WIDGET_CAN_FOCUS (widget))
+    return FALSE;
+  
+  gtk_signal_emit (GTK_OBJECT (widget),
+                   widget_signals[FOCUS],
+                   direction, &return_val);
+
+  return return_val;
 }
 
 /* Update the position from aux_info. Used from gtk_widget_set_uposition
Index: gtk/gtkwidget.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.h,v
retrieving revision 1.108
diff -u -u -p -r1.108 gtkwidget.h
--- gtk/gtkwidget.h	2001/06/05 18:51:52	1.108
+++ gtk/gtkwidget.h	2001/06/08 18:01:42
@@ -276,7 +276,9 @@ struct _GtkWidgetClass
 				  gboolean      group_cycling);
   
   /* explicit focus */
-  void (* grab_focus)          (GtkWidget      *widget);
+  void (* grab_focus)          (GtkWidget        *widget);
+  gboolean (* focus)           (GtkWidget        *widget,
+                                GtkDirectionType  direction);
   
   /* events */
   gboolean (* event)			(GtkWidget	     *widget,
@@ -523,6 +525,8 @@ void	   gtk_widget_set_parent	  (GtkWidg
 void	   gtk_widget_set_parent_window	  (GtkWidget	       *widget,
 					   GdkWindow	       *parent_window);
 GdkWindow *gtk_widget_get_parent_window	  (GtkWidget	       *widget);
+gboolean   gtk_widget_child_focus         (GtkWidget           *widget,
+                                           GtkDirectionType     direction);
 void	   gtk_widget_set_uposition	  (GtkWidget	       *widget,
 					   gint			x,
 					   gint			y);
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.120
diff -u -u -p -r1.120 gtkwindow.c
--- gtk/gtkwindow.c	2001/05/22 19:18:46	1.120
+++ gtk/gtkwindow.c	2001/06/08 18:01:42
@@ -143,7 +143,7 @@ static gint gtk_window_focus_out_event  
 static gint gtk_window_client_event	  (GtkWidget	     *widget,
 					   GdkEventClient    *event);
 static void gtk_window_check_resize       (GtkContainer      *container);
-static gint gtk_window_focus              (GtkContainer     *container,
+static gint gtk_window_focus              (GtkWidget        *widget,
 				           GtkDirectionType  direction);
 static void gtk_window_real_set_focus     (GtkWindow         *window,
 					   GtkWidget         *focus);
@@ -301,11 +301,11 @@ gtk_window_class_init (GtkWindowClass *k
   widget_class->focus_in_event = gtk_window_focus_in_event;
   widget_class->focus_out_event = gtk_window_focus_out_event;
   widget_class->client_event = gtk_window_client_event;
+  widget_class->focus = gtk_window_focus;
   
   widget_class->expose_event = gtk_window_expose;
    
   container_class->check_resize = gtk_window_check_resize;
-  container_class->focus = gtk_window_focus;
 
   klass->set_focus = gtk_window_real_set_focus;
   klass->frame_event = gtk_window_frame_event;
@@ -2190,7 +2190,7 @@ static void
 gtk_window_move_focus (GtkWindow       *window,
                        GtkDirectionType dir)
 {
-  gtk_container_focus (GTK_CONTAINER (window), dir);
+  gtk_widget_child_focus (GTK_WIDGET (window), dir);
   
   if (!GTK_CONTAINER (window)->focus_child)
     gtk_window_set_focus (window, NULL);
@@ -2382,13 +2382,20 @@ gtk_window_check_resize (GtkContainer *c
 }
 
 static gboolean
-gtk_window_focus (GtkContainer     *container,
+gtk_window_focus (GtkWidget        *widget,
 		  GtkDirectionType  direction)
 {
-  GtkBin *bin = GTK_BIN (container);
-  GtkWindow *window = GTK_WINDOW (container);
-  GtkWidget *old_focus_child = container->focus_child;
+  GtkBin *bin;
+  GtkWindow *window;
+  GtkContainer *container;
+  GtkWidget *old_focus_child;
   GtkWidget *parent;
+
+  container = GTK_CONTAINER (widget);
+  window = GTK_WINDOW (widget);
+  bin = GTK_BIN (widget);
+
+  old_focus_child = container->focus_child;
   
   /* We need a special implementation here to deal properly with wrapping
    * around in the tab chain without the danger of going into an
@@ -2396,10 +2403,7 @@ gtk_window_focus (GtkContainer     *cont
    */
   if (old_focus_child)
     {
-      if (GTK_IS_CONTAINER (old_focus_child) &&
-	  GTK_WIDGET_DRAWABLE (old_focus_child) &&
-	  GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
-	  gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
+      if (gtk_widget_child_focus (old_focus_child, direction))
 	return TRUE;
     }
 
@@ -2417,20 +2421,10 @@ gtk_window_focus (GtkContainer     *cont
     }
 
   /* Now try to focus the first widget in the window */
-  if (bin->child &&
-      GTK_WIDGET_DRAWABLE (bin->child) &&
-      GTK_WIDGET_IS_SENSITIVE (bin->child))
+  if (bin->child)
     {
-      if (GTK_IS_CONTAINER (bin->child))
-	{
-	  if (gtk_container_focus (GTK_CONTAINER (bin->child), direction))
-	    return TRUE;
-	}
-      else if (GTK_WIDGET_CAN_FOCUS (bin->child))
-	{
-	  gtk_widget_grab_focus (bin->child);
-	  return TRUE;
-	}
+      if (gtk_widget_child_focus (bin->child, direction))
+        return TRUE;
     }
 
   return FALSE;




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