Index: gtkbindings.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbindings.c,v
retrieving revision 1.23
diff -u -p -r1.23 gtkbindings.c
--- gtkbindings.c	2001/04/03 13:17:59	1.23
+++ gtkbindings.c	2001/09/21 16:03:32
@@ -67,6 +67,7 @@ binding_signal_new (const gchar *signal_
   signal->signal_name = g_strdup (signal_name);
   signal->n_args = n_args;
   signal->args = g_new0 (GtkBindingArg, n_args);
+  signal->enabled = TRUE;
   
   return signal;
 }
@@ -351,12 +352,13 @@ binding_compose_params (GtkBindingArg	*a
   return valid;
 }
 
-static void
+static gboolean
 gtk_binding_entry_activate (GtkBindingEntry	*entry,
 			    GtkObject	*object)
 {
   GtkBindingSignal *sig;
   gboolean old_emission;
+  gboolean retval = FALSE;
   
   old_emission = entry->in_emission;
   entry->in_emission = TRUE;
@@ -370,6 +372,9 @@ gtk_binding_entry_activate (GtkBindingEn
       GtkArg *params = NULL;
       gchar *accelerator = NULL;
       
+      if (!sig->enabled)
+        continue;
+
       signal_id = gtk_signal_lookup (sig->signal_name, GTK_OBJECT_TYPE (object));
       if (!signal_id)
 	{
@@ -413,6 +418,7 @@ gtk_binding_entry_activate (GtkBindingEn
 
       gtk_signal_emitv (object, signal_id, params);
       g_free (params);
+      retval = TRUE;
       
       if (GTK_OBJECT_DESTROYED (object) || entry->destroyed)
 	break;
@@ -423,6 +429,7 @@ gtk_binding_entry_activate (GtkBindingEn
   entry->in_emission = old_emission;
   if (entry->destroyed && !entry->in_emission)
     binding_entry_free (entry);
+  return retval;
 }
 
 GtkBindingSet*
@@ -509,9 +516,7 @@ gtk_binding_set_activate (GtkBindingSet	
       entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
       if (entry)
 	{
-	  gtk_binding_entry_activate (entry, object);
-	  
-	  return TRUE;
+	  return gtk_binding_entry_activate (entry, object);
 	}
     }
   
@@ -721,6 +726,36 @@ gtk_binding_entry_add_signal (GtkBinding
   g_slist_free (free_slist);
 }
 
+gboolean
+gtk_binding_set_enable_signal (GtkBindingSet  *binding_set,
+                               const gchar    *signal_name,
+                               gboolean        enable)
+{
+  GtkBindingEntry *entry;
+  GtkBindingSignal *sig;
+  gboolean retval = FALSE;
+
+  g_return_val_if_fail (binding_set != NULL, retval);
+  g_return_val_if_fail (signal_name != NULL, retval);
+  
+  for (entry = binding_set->entries; entry; entry = entry->set_next)
+    {
+      for (sig = entry->signals; sig; sig = sig->next)
+        {
+          if (strcmp (signal_name, sig->signal_name) == 0)
+            {
+              if (sig->enabled != enable)
+                {
+                  sig->enabled = enable;
+                  retval = TRUE;
+                }
+            }
+        }     
+    }     
+
+  return retval;  
+}
+
 void
 gtk_binding_set_add_path (GtkBindingSet	     *binding_set,
 			  GtkPathType	      path_type,
@@ -800,9 +835,8 @@ binding_match_activate (GSList          
 
 	  binding_set = pspec->user_data;
 
-	  gtk_binding_entry_activate (binding_set->current, object);
+	  return gtk_binding_entry_activate (binding_set->current, object);
 
-	  return TRUE;
 	}
     }
 
Index: gtkbindings.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbindings.h,v
retrieving revision 1.9
diff -u -p -r1.9 gtkbindings.h
--- gtkbindings.h	2001/04/03 13:17:59	1.9
+++ gtkbindings.h	2001/09/21 16:03:32
@@ -81,6 +81,7 @@ struct _GtkBindingSignal
   gchar			*signal_name;
   guint			 n_args;
   GtkBindingArg		*args;
+  guint			enabled : 1;
 };
 
 struct _GtkBindingArg
@@ -116,6 +117,9 @@ void	 gtk_binding_entry_add_signal	(GtkB
 					 const gchar	*signal_name,
 					 guint		 n_args,
 					 ...);
+gboolean gtk_binding_set_enable_signal	(GtkBindingSet	*binding_set,
+					 const gchar	*signal_name,
+                                         gboolean       enable);
 void	 gtk_binding_set_add_path	(GtkBindingSet	*binding_set,
 					 GtkPathType	 path_type,
 					 const gchar	*path_pattern,
Index: gtktooltips.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktooltips.c,v
retrieving revision 1.42
diff -u -p -r1.42 gtktooltips.c
--- gtktooltips.c	2001/08/19 11:48:31	1.42
+++ gtktooltips.c	2001/09/21 16:03:32
@@ -34,7 +34,9 @@
 #include "gtkwindow.h"
 #include "gtksignal.h"
 #include "gtkstyle.h"
+#include "gtkbindings.h"
 #include "gtktooltips.h"
+#include "gdk/gdkkeysyms.h"
 
 
 #define DEFAULT_DELAY 500           /* Default delay in ms */
@@ -318,7 +320,7 @@ gtk_tooltips_draw_tips (GtkTooltips * to
   GtkRequisition requisition;
   GtkWidget *widget;
   GtkStyle *style;
-  gint x, y, w, h, scr_w, scr_h;
+  gint xp, x, y, w, h, scr_w, scr_h;
   GtkTooltipsData *data;
 
   if (!tooltips->tip_window)
@@ -342,10 +344,23 @@ gtk_tooltips_draw_tips (GtkTooltips * to
   w = requisition.width;
   h = requisition.height;
 
-  gdk_window_get_pointer (NULL, &x, NULL, NULL);
-  gdk_window_get_origin (widget->window, NULL, &y);
+  gdk_window_get_pointer (NULL, &xp, NULL, NULL);
+  gdk_window_get_origin (widget->window, &x, &y);
   if (GTK_WIDGET_NO_WINDOW (widget))
-    y += widget->allocation.y;
+    {
+      x += widget->allocation.x;
+      y += widget->allocation.y;
+    }
+  /*
+   * Ensure that centre of tooltip is close to widget.
+   * The tooltip may be displayed because of keyboard action so the
+   * pointer may not be near the widget.
+   */
+  if (xp < x)
+    xp = x;
+  else if (xp > x + widget->allocation.width)
+    xp = x + widget->allocation.width;  
+  x = xp;
 
   x -= (w / 2 + 4);
 
@@ -395,12 +410,11 @@ gtk_tooltips_set_active_widget (GtkToolt
       tooltips->timer_tag = 0;
     }
   
-  tooltips->active_tips_data = NULL;
-  
   if (widget)
     {
       GList *list;
       
+      tooltips->active_tips_data = NULL;
       for (list = tooltips->tips_data_list; list; list = list->next)
 	{
 	  GtkTooltipsData *tooltipsdata;
@@ -417,7 +431,17 @@ gtk_tooltips_set_active_widget (GtkToolt
     }
   else
     {
+      if (tooltips->active_tips_data && 
+          (tooltips->active_tips_data->widget))
+        {
+          GtkBindingSet* set;
+
+          set = gtk_binding_set_find ("GtkWidget");
+          if (set)
+            gtk_binding_set_enable_signal (set, "popdown_tooltip", FALSE);
+        }
       tooltips->use_sticky_delay = FALSE;
+      tooltips->active_tips_data = NULL;
     }
 }
 
@@ -492,7 +516,6 @@ gtk_tooltips_event_handler (GtkWidget *w
       
     default:
       gtk_tooltips_set_active_widget (tooltips, NULL);
-      return FALSE;
       break;
     }
 
@@ -527,13 +550,8 @@ gtk_tooltips_widget_remove (GtkWidget *w
 void
 _gtk_tooltips_show_tip (GtkWidget *widget)
 {
-  /* Showing the tip from the keyboard */
-
-  /* FIXME this function is completely broken right now,
-   * popdown doesn't occur when it should.
-   */
-  
   GtkTooltipsData *tooltipsdata;
+  GtkBindingSet* set;
 
   tooltipsdata = gtk_tooltips_data_get (widget);
 
@@ -542,6 +560,24 @@ _gtk_tooltips_show_tip (GtkWidget *widge
 
   gtk_tooltips_set_active_widget (tooltipsdata->tooltips,
                                   widget);
+  set = gtk_binding_set_find ("GtkWidget");
+  if (set)
+    gtk_binding_set_enable_signal (set, "popdown_tooltip", TRUE);
 
   gtk_tooltips_timeout (tooltipsdata->tooltips);
+}
+
+void
+_gtk_tooltips_popdown_tip (GtkWidget *widget)
+{
+  GtkTooltipsData *tooltipsdata;
+
+  tooltipsdata = gtk_tooltips_data_get (widget);
+
+  if (tooltipsdata == NULL)
+    return;
+
+  if (tooltipsdata->tooltips->active_tips_data &&
+      (tooltipsdata->tooltips->active_tips_data->widget == widget))
+    gtk_tooltips_set_active_widget (tooltipsdata->tooltips, NULL);
 }
Index: gtktooltips.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktooltips.h,v
retrieving revision 1.21
diff -u -p -r1.21 gtktooltips.h
--- gtktooltips.h	2001/09/19 21:29:57	1.21
+++ gtktooltips.h	2001/09/21 16:03:32
@@ -95,6 +95,7 @@ void             gtk_tooltips_force_wind
 
 
 void             _gtk_tooltips_show_tip    (GtkWidget    *widget);
+void             _gtk_tooltips_popdown_tip (GtkWidget    *widget);
 
 #ifdef __cplusplus
 }
Index: gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.253
diff -u -p -r1.253 gtkwidget.c
--- gtkwidget.c	2001/09/19 21:29:57	1.253
+++ gtkwidget.c	2001/09/21 16:03:33
@@ -114,6 +114,7 @@ enum {
   WINDOW_STATE_EVENT,
   POPUP_MENU,
   SHOW_HELP,
+  POPDOWN_TOOLTIP,
   LAST_SIGNAL
 };
 
@@ -180,6 +181,7 @@ static void	gtk_widget_direction_changed
 static void	gtk_widget_real_grab_focus	 (GtkWidget         *focus_widget);
 static void     gtk_widget_real_show_help        (GtkWidget         *widget,
                                                   GtkWidgetHelpType  help_type);
+static void     gtk_widget_real_popdown_tooltip  (GtkWidget         *widget);
 
 static void	gtk_widget_dispatch_child_properties_changed	(GtkWidget        *object,
 								 guint             n_pspecs,
@@ -376,6 +378,7 @@ gtk_widget_class_init (GtkWidgetClass *k
   klass->drag_data_received = NULL;
 
   klass->show_help = gtk_widget_real_show_help;
+  klass->popdown_tooltip = gtk_widget_real_popdown_tooltip;
   
   /* Accessibility support */
   klass->get_accessible = gtk_widget_real_get_accessible;
@@ -1017,6 +1020,13 @@ gtk_widget_class_init (GtkWidgetClass *k
 		    GTK_SIGNAL_OFFSET (GtkWidgetClass, show_help),
                     gtk_marshal_NONE__ENUM,
 		    GTK_TYPE_NONE, 1, GTK_TYPE_WIDGET_HELP_TYPE);
+  widget_signals[POPDOWN_TOOLTIP] =
+    gtk_signal_new ("popdown_tooltip",
+		    GTK_RUN_LAST | GTK_RUN_ACTION,
+		    GTK_CLASS_TYPE (object_class),
+		    GTK_SIGNAL_OFFSET (GtkWidgetClass, popdown_tooltip),
+                    gtk_marshal_NONE__NONE,
+		    GTK_TYPE_NONE, 0);
   
   binding_set = gtk_binding_set_by_class (klass);
   gtk_binding_entry_add_signal (binding_set, GDK_F10, GDK_SHIFT_MASK,
@@ -1041,6 +1051,9 @@ gtk_widget_class_init (GtkWidgetClass *k
                                 "show_help", 1,
                                 GTK_TYPE_WIDGET_HELP_TYPE,
                                 GTK_WIDGET_HELP_WHATS_THIS);
+  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+                                "popdown_tooltip", 0);  
+  gtk_binding_set_enable_signal (binding_set, "popdown_tooltip", FALSE);
 
   gtk_widget_class_install_style_property (klass,
 					   g_param_spec_boolean ("interior_focus",
@@ -3073,6 +3086,12 @@ gtk_widget_real_show_help (GtkWidget    
 {
   if (help_type == GTK_WIDGET_HELP_TOOLTIP)
     _gtk_tooltips_show_tip (widget);
+}
+
+static void
+gtk_widget_real_popdown_tooltip (GtkWidget        *widget)
+{
+  _gtk_tooltips_popdown_tip (widget);
 }
 
 static gboolean
Index: gtkwidget.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.h,v
retrieving revision 1.122
diff -u -p -r1.122 gtkwidget.h
--- gtkwidget.h	2001/09/19 19:51:53	1.122
+++ gtkwidget.h	2001/09/21 16:03:33
@@ -409,6 +409,9 @@ struct _GtkWidgetClass
   void (* show_help)               (GtkWidget          *widget,
                                     GtkWidgetHelpType   help_type);
   
+  /* Popdown tooltip if it showing */
+  void (* popdown_tooltip)         (GtkWidget          *widget);
+
   /* accessibility support 
    */
   AtkObject*   (* get_accessible)  (GtkWidget          *widget);
