Index: gtksettings.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksettings.c,v
retrieving revision 1.19
diff -u -p -r1.19 gtksettings.c
--- gtksettings.c	2001/10/04 06:48:09	1.19
+++ gtksettings.c	2001/10/31 08:49:49
@@ -29,7 +29,8 @@ enum {
   PROP_SPLIT_CURSOR,
   PROP_THEME_NAME,
   PROP_KEY_THEME_NAME,
-  PROP_MENU_BAR_ACCEL
+  PROP_MENU_BAR_ACCEL,
+  PROP_TOOLTIP_POPDOWN
 };
 
 
@@ -197,8 +198,16 @@ gtk_settings_class_init (GtkSettingsClas
                                                                   "F10",
                                                                   G_PARAM_READWRITE),
                                              NULL);
-
   g_assert (result == PROP_MENU_BAR_ACCEL);
+
+  result = settings_install_property_parser (class,
+                                             g_param_spec_string ("gtk-tooltip-popdown",
+                                                                  _("Tooltip popdown"),
+                                                                  _("Keybinding to popdown tooltip"),
+                                                                  "Escape",
+                                                                  G_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_TOOLTIP_POPDOWN);
 }
 
 static void
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/10/31 08:49:51
@@ -318,7 +318,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,11 +342,25 @@ 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 the centre of the tooltip is close to the widget
+   * The tooltip may be displayed because of keyboard action so the
+   * pointer may not be newar 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);
 
   if ((x + w) > scr_w)
@@ -440,11 +454,16 @@ gtk_tooltips_event_handler (GtkWidget *w
   GtkTooltips *tooltips;
   GtkTooltipsData *old_tips_data;
   GtkWidget *event_widget;
+  GtkWidget *toplevel;
+  gboolean keyboard_tooltips_mode;
 
   if ((event->type == GDK_LEAVE_NOTIFY || event->type == GDK_ENTER_NOTIFY) &&
       event->crossing.detail == GDK_NOTIFY_INFERIOR)
     return FALSE;
 
+  if (event->type == GDK_MOTION_NOTIFY || event->type == GDK_EXPOSE)
+    return FALSE;
+
   event_widget = gtk_get_event_widget (event);
   if (event_widget != widget)
     return FALSE;
@@ -452,14 +471,26 @@ gtk_tooltips_event_handler (GtkWidget *w
   old_tips_data = gtk_tooltips_data_get (widget);
   tooltips = old_tips_data->tooltips;
 
+  /*
+   * Check the keyboard tooltips mode of the toplevel of the widget.
+   */
+
+  toplevel = gtk_widget_get_toplevel (widget);
+  if (GTK_WIDGET_TOPLEVEL (toplevel))
+    keyboard_tooltips_mode = gtk_window_get_keyboard_tooltips_mode (GTK_WINDOW (toplevel));
+
   switch (event->type)
     {
     case GDK_MOTION_NOTIFY:
     case GDK_EXPOSE:
       /* do nothing */
+      g_assert_not_reached ();
       break;
       
     case GDK_ENTER_NOTIFY:
+      if (keyboard_tooltips_mode)
+        break;
+
       old_tips_data = tooltips->active_tips_data;
       if (tooltips->enabled &&
 	  (!old_tips_data || old_tips_data->widget != widget))
@@ -480,6 +511,9 @@ gtk_tooltips_event_handler (GtkWidget *w
       break;
 
     case GDK_LEAVE_NOTIFY:
+      if (keyboard_tooltips_mode)
+        break;
+
       {
 	gboolean use_sticky_delay;
 
@@ -490,6 +524,15 @@ gtk_tooltips_event_handler (GtkWidget *w
       }
       break;
       
+    case GDK_FOCUS_CHANGE:
+      if (keyboard_tooltips_mode)
+        {
+          GdkEventFocus *focus_event = (GdkEventFocus *)event;
+
+          _gtk_tooltips_show_tip (widget, focus_event->in);
+          return FALSE;
+        } 
+      /* FALL THRU */
     default:
       gtk_tooltips_set_active_widget (tooltips, NULL);
       return FALSE;
@@ -525,14 +568,11 @@ gtk_tooltips_widget_remove (GtkWidget *w
 }
 
 void
-_gtk_tooltips_show_tip (GtkWidget *widget)
+_gtk_tooltips_show_tip (GtkWidget *widget,
+                        gboolean   show)
 {
-  /* Showing the tip from the keyboard */
+  /* Show or popdown the tip from the keyboard */
 
-  /* FIXME this function is completely broken right now,
-   * popdown doesn't occur when it should.
-   */
-  
   GtkTooltipsData *tooltipsdata;
 
   tooltipsdata = gtk_tooltips_data_get (widget);
@@ -540,8 +580,14 @@ _gtk_tooltips_show_tip (GtkWidget *widge
   if (tooltipsdata == NULL)
     return;
 
-  gtk_tooltips_set_active_widget (tooltipsdata->tooltips,
-                                  widget);
+  if (show)
+    {
+      gtk_tooltips_set_active_widget (tooltipsdata->tooltips,
+                                      widget);
+
+      gtk_tooltips_timeout (tooltipsdata->tooltips);
+    }
+  else
+    gtk_tooltips_set_active_widget (tooltipsdata->tooltips, NULL);
 
-  gtk_tooltips_timeout (tooltipsdata->tooltips);
 }
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/10/31 08:49:51
@@ -94,7 +94,8 @@ GtkTooltipsData* gtk_tooltips_data_get	 
 void             gtk_tooltips_force_window (GtkTooltips   *tooltips);
 
 
-void             _gtk_tooltips_show_tip    (GtkWidget    *widget);
+void             _gtk_tooltips_show_tip    (GtkWidget     *widget,
+                                            gboolean       show);
 
 #ifdef __cplusplus
 }
Index: gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.260
diff -u -p -r1.260 gtkwidget.c
--- gtkwidget.c	2001/10/22 04:34:41	1.260
+++ gtkwidget.c	2001/10/31 08:50:04
@@ -3233,7 +3233,27 @@ gtk_widget_real_show_help (GtkWidget    
                            GtkWidgetHelpType help_type)
 {
   if (help_type == GTK_WIDGET_HELP_TOOLTIP)
-    _gtk_tooltips_show_tip (widget);
+    {
+      GtkWidget *toplevel;
+
+      toplevel = gtk_widget_get_toplevel (widget);
+      if (GTK_WIDGET_TOPLEVEL (toplevel))
+        {
+          GtkWindow *window;
+          gboolean mode;
+
+          window = GTK_WINDOW (toplevel);
+          mode = gtk_window_get_keyboard_tooltips_mode (window);
+
+          /*
+           * Consecutive calls toggle the mode.
+           */
+          mode = !mode;
+          gtk_window_set_keyboard_tooltips_mode (window, mode);
+          _gtk_tooltips_show_tip (widget, mode);
+
+        }
+    }
 }
 
 static gboolean
Index: gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.158
diff -u -p -r1.158 gtkwindow.c
--- gtkwindow.c	2001/10/28 21:15:33	1.158
+++ gtkwindow.c	2001/10/31 08:50:17
@@ -65,6 +65,7 @@ enum {
   PROP_DEFAULT_HEIGHT,
   PROP_DESTROY_WITH_PARENT,
   PROP_ICON,
+  PROP_KEYBOARD_TOOLTIPS_MODE,
   
   LAST_ARG
 };
@@ -221,6 +222,9 @@ static void     gtk_window_set_default_s
 static void     gtk_window_realize_icon               (GtkWindow    *window);
 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
 
+static gboolean gtk_window_tooltip_popdown            (GtkWidget    *widget,
+                                                       GdkEventKey  *event);
+
 static GSList      *toplevel_list = NULL;
 static GHashTable  *mnemonic_hash_table = NULL;
 static GtkBinClass *parent_class = NULL;
@@ -442,6 +446,13 @@ gtk_window_class_init (GtkWindowClass *k
                                                         _("Icon for this window"),
                                                         GDK_TYPE_PIXBUF,
                                                         G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_KEYBOARD_TOOLTIPS_MODE,
+                                   g_param_spec_boolean ("keyboard_tooltips_mode",
+							 _("Keyboard Tooltips Mode"),
+							 _("If TRUE, the tooltipis displayed when a widget recfeives focus"),
+							 FALSE,
+							 G_PARAM_READWRITE));
   
   window_signals[SET_FOCUS] =
     g_signal_new ("set_focus",
@@ -592,6 +603,7 @@ gtk_window_init (GtkWindow *window)
   window->need_default_size = TRUE;
   window->need_default_position = TRUE;
   window->modal = FALSE;
+  window->keyboard_tooltips_mode = FALSE;
   window->frame = NULL;
   window->has_frame = FALSE;
   window->frame_left = 0;
@@ -675,6 +687,8 @@ gtk_window_set_property (GObject      *o
       gtk_window_set_icon (window,
                            g_value_get_object (value));
       break;
+    case PROP_KEYBOARD_TOOLTIPS_MODE:
+      gtk_window_set_keyboard_tooltips_mode (window, g_value_get_boolean (value));
 
     default:
       break;
@@ -735,6 +749,9 @@ gtk_window_get_property (GObject      *o
     case PROP_ICON:
       g_value_set_object (value, gtk_window_get_icon (window));
       break;
+    case PROP_KEYBOARD_TOOLTIPS_MODE:
+      g_value_set_boolean (value, window->keyboard_tooltips_mode);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1272,6 +1289,60 @@ gtk_window_get_modal (GtkWindow *window)
 }
 
 /**
+ * gtk_window_set_keyboard_tooltips_mode:
+ * @window: a #GtkWindow
+ * @mode: whether the tooltip should be displayed when widget receives focus.
+ * 
+ * Specifies whether a widget's tooltip should be displayed when a widget
+ * receives focus. When this mode is set, tooltip will not be displayed 
+ * because of mouse movement.
+ * 
+ **/
+void
+gtk_window_set_keyboard_tooltips_mode (GtkWindow *window,
+		                       gboolean   mode)
+{
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  
+  if (window->keyboard_tooltips_mode != (mode != FALSE))
+    {
+      window->keyboard_tooltips_mode = mode != FALSE;
+  
+      if (window->keyboard_tooltips_mode)
+        {
+          gtk_signal_connect (GTK_OBJECT (window),
+                              "key_press_event",
+                              GTK_SIGNAL_FUNC (gtk_window_tooltip_popdown),
+                              NULL);
+        }
+      else
+        {
+          gtk_signal_disconnect_by_func (GTK_OBJECT (window),
+                                         GTK_SIGNAL_FUNC (gtk_window_tooltip_popdown),
+                                         NULL);
+        }
+      g_object_notify (G_OBJECT (window), "keyboard_tooltips_mode");
+    }
+}
+
+/**
+ * gtk_window_get_keyboard_tooltips_mode:
+ * @window: a #GtkWindow
+ * 
+ * Returns whether the window's keyboard_tooltips_mode is set.
+ * See gtk_window_set_keyboard_tooltips_mode().
+ *
+ * Return value: %TRUE if the window's keyboard_tooltips_mode is set 
+ **/
+gboolean
+gtk_window_get_keyboard_tooltips_mode (GtkWindow *window)
+{
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  return window->keyboard_tooltips_mode;
+}
+
+/**
  * gtk_window_list_toplevels:
  * 
  * Returns a list of all existing toplevel windows. The widgets
@@ -3493,6 +3564,8 @@ gtk_window_focus_out_event (GtkWidget   
 
   window->has_focus = FALSE;
   
+  gtk_window_set_keyboard_tooltips_mode (window, FALSE);
+
   if (window->focus_widget &&
       window->focus_widget != widget &&
       GTK_WIDGET_HAS_FOCUS (window->focus_widget))
@@ -5485,3 +5558,44 @@ gtk_window_parse_geometry (GtkWindow   *
   
   return result != 0;
 }
+
+static gboolean
+gtk_window_tooltip_popdown (GtkWidget   *widget,
+                            GdkEventKey *event)
+{
+  gchar *accel = NULL;
+  gboolean retval = FALSE;
+
+  g_object_get (G_OBJECT (gtk_widget_get_settings (widget)),
+                "gtk-tooltip-popdown",
+                &accel,
+                NULL);
+
+  if (accel)
+    {
+      guint keyval = 0;
+      GdkModifierType mods = 0;
+
+      gtk_accelerator_parse (accel, &keyval, &mods);
+
+      if (keyval == 0)
+        g_warning ("Failed to parse tooltip popdown bar key '%s'\n", accel);
+
+      if (event->keyval == keyval &&
+          (mods & event->state) == mods)
+        {
+          GtkWindow *window;
+
+          window = GTK_WINDOW (widget);
+
+          gtk_window_set_keyboard_tooltips_mode (window, FALSE);
+          _gtk_tooltips_show_tip (window->focus_widget, FALSE);
+
+          retval = TRUE;
+        }
+      g_free (accel);
+    }
+
+  return retval;
+}
+
Index: gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.51
diff -u -p -r1.51 gtkwindow.h
--- gtkwindow.h	2001/09/19 00:58:09	1.51
+++ gtkwindow.h	2001/10/31 08:50:17
@@ -91,6 +91,8 @@ struct _GtkWindow
   
   guint has_frame : 1;
 
+  guint keyboard_tooltips_mode : 1;
+
   /* gtk_window_iconify() called before realization */
   guint iconify_initially : 1;
   guint stick_initially : 1;
@@ -220,6 +222,9 @@ GList*     gtk_window_get_default_icon_l
 void       gtk_window_set_modal      (GtkWindow *window,
 				      gboolean   modal);
 gboolean   gtk_window_get_modal      (GtkWindow *window);
+void       gtk_window_set_keyboard_tooltips_mode   (GtkWindow *window,
+				                    gboolean   mode);
+gboolean   gtk_window_get_keyboard_tooltips_mode   (GtkWindow *window);
 GList*     gtk_window_list_toplevels (void);
 
 void     gtk_window_add_mnemonic          (GtkWindow       *window,
