--- gtk/gtkstatusicon.c	2007/09/17 22:38:53	1.1
+++ gtk/gtkstatusicon.c	2007/09/23 22:07:41
@@ -39,6 +39,7 @@
 
 #include "gtkprivate.h"
 #include "gtkwidget.h"
+#include "gtktooltip.h"
 
 #ifdef GDK_WINDOWING_WIN32
 #include "gtkicontheme.h"
@@ -70,7 +71,10 @@ enum
   PROP_VISIBLE,
   PROP_ORIENTATION,
   PROP_EMBEDDED,
-  PROP_BLINKING
+  PROP_BLINKING,
+  PROP_HAS_TOOLTIP,
+  PROP_TOOLTIP_TEXT,
+  PROP_TOOLTIP_MARKUP
 };
 
 enum 
@@ -78,6 +82,10 @@ enum 
   ACTIVATE_SIGNAL,
   POPUP_MENU_SIGNAL,
   SIZE_CHANGED_SIGNAL,
+  BUTTON_PRESS_EVENT_SIGNAL,
+  BUTTON_RELEASE_EVENT_SIGNAL,
+  SCROLL_EVENT_SIGNAL,
+  QUERY_TOOLTIP_SIGNAL,
   LAST_SIGNAL
 };
 
@@ -99,11 +107,13 @@ struct _GtkStatusIconPrivate
   NOTIFYICONDATAW nid;
   gint		last_click_x, last_click_y;
   GtkOrientation orientation;
+  gchar         *tooltip_text;
 #endif
 	
 #ifdef GDK_WINDOWING_QUARTZ
   GtkWidget     *dummy_widget;
   GtkQuartzStatusIcon *status_item;
+  gchar         *tooltip_text;
 #endif
 
   gint          size;
@@ -148,10 +158,19 @@ static void     gtk_status_icon_screen_c
 						  GdkScreen      *old_screen);
 static void     gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon);
 static void     gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon);
+static gboolean gtk_status_icon_scroll           (GtkStatusIcon  *status_icon,
+						  GdkEventScroll *event);
+static gboolean gtk_status_icon_query_tooltip    (GtkStatusIcon *status_icon,
+						  gint           x,
+						  gint           y,
+						  gboolean       keyboard_tip,
+						  GtkTooltip    *tooltip);
 
 #endif
 static gboolean gtk_status_icon_button_press     (GtkStatusIcon  *status_icon,
 						  GdkEventButton *event);
+static gboolean gtk_status_icon_button_release   (GtkStatusIcon  *status_icon,
+						  GdkEventButton *event);
 static void     gtk_status_icon_disable_blinking (GtkStatusIcon  *status_icon);
 static void     gtk_status_icon_reset_image_data (GtkStatusIcon  *status_icon);
 					   
@@ -168,6 +187,11 @@ gtk_status_icon_class_init (GtkStatusIco
   gobject_class->set_property = gtk_status_icon_set_property;
   gobject_class->get_property = gtk_status_icon_get_property;
 
+  class->button_press_event   = NULL;
+  class->button_release_event = NULL;
+  class->scroll_event         = NULL;
+  class->query_tooltip        = NULL;
+
   g_object_class_install_property (gobject_class,
 				   PROP_PIXBUF,
 				   g_param_spec_object ("pixbuf",
@@ -276,6 +300,77 @@ gtk_status_icon_class_init (GtkStatusIco
 						      GTK_ORIENTATION_HORIZONTAL,
 						      GTK_PARAM_READABLE));
 
+/**
+ * GtkStatusIcon:has-tooltip:
+ *
+ * Enables or disables the emission of #GtkStatusIcon::query-tooltip on
+ * @status_icon.  A value of %TRUE indicates that @status_icon can have a
+ * tooltip, in this case the status icon will be queried using
+ * #GtkStatusIcon::query-tooltip to determine whether it will provide a
+ * tooltip or not.
+ *
+ * Note that setting this property to %TRUE for the first time will change
+ * the event masks of the GdkWindows of this status icon to include
+ * leave-notify and motion-notify events.  This cannot and will not be undone
+ * when the property is set to %FALSE again.
+ *
+ * Whether this property is respected is platform dependent.  For plain text
+ * tooltips, use :tooltip-text in preference.
+ *
+ * Since: 2.14
+ */
+  g_object_class_install_property (gobject_class,
+				   PROP_HAS_TOOLTIP,
+				   g_param_spec_boolean ("has-tooltip",
+ 							 P_("Has tooltip"),
+ 							 P_("Whether this tray icon has a tooltip"),
+ 							 FALSE,
+ 							 GTK_PARAM_READWRITE));
+  /**
+   * GtkStatusIcon:tooltip-text:
+   *
+   * Sets the text of tooltip to be the given string.
+   *
+   * Also see gtk_tooltip_set_text().
+   *
+   * This is a convenience property which will take care of getting the
+   * tooltip shown if the given string is not %NULL: #GtkStatusIcon:has-tooltip
+   * will automatically be set to %TRUE and there will be taken care of
+   * #GtkStatusIcon::query-tooltip in the default signal handler.
+   *
+   * Since: 2.14
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_TOOLTIP_TEXT,
+                                   g_param_spec_string ("tooltip-text",
+                                                        P_("Tooltip Text"),
+                                                        P_("The contents of the tooltip for this widget"),
+                                                        NULL,
+                                                        GTK_PARAM_READWRITE));
+  /**
+   * GtkStatusIcon:tooltip-markup:
+   *
+   * Sets the text of tooltip to be the given string, which is marked up
+   * with the <link linkend="PangoMarkupFormat">Pango text markup language</link>.
+   * Also see gtk_tooltip_set_markup().
+   *
+   * This is a convenience property which will take care of getting the
+   * tooltip shown if the given string is not %NULL: #GtkStatusIcon:has-tooltip
+   * will automatically be set to %TRUE and there will be taken care of
+   * #GtkStatusIcon::query-tooltip in the default signal handler.
+   *
+   * On some platforms, embedded markup will be ignored.
+   *
+   * Since: 2.14
+   */
+  g_object_class_install_property (gobject_class,
+				   PROP_TOOLTIP_MARKUP,
+				   g_param_spec_string ("tooltip-markup",
+ 							P_("Tooltip markup"),
+							P_("The contents of the tooltip for this tray icon"),
+							NULL,
+							GTK_PARAM_READWRITE));
+
 
   /**
    * GtkStatusIcon::activate:
@@ -352,6 +447,125 @@ gtk_status_icon_class_init (GtkStatusIco
 		  1,
 		  G_TYPE_INT);
 
+  /**
+   * GtkStatusIcon::button-press-event:
+   * @status_icon: the object which received the signal
+   * @event: the #GdkEventButton which triggered this signal
+   *
+   * The ::button-press-event signal will be emitted when a button
+   * (typically from a mouse) is pressed.
+   *
+   * Whether this event is emitted is platform-dependent.  Use the ::activate
+   * and ::popup-menu signals in preference.
+   *
+   * Return value: %TRUE to stop other handlers from being invoked
+   * for the event. %FALSE to propagate the event further.
+   *
+   * Since: 2.14
+   */
+  status_icon_signals [BUTTON_PRESS_EVENT_SIGNAL] =
+    g_signal_new (I_("button_press_event"),
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkStatusIconClass, button_press_event),
+		  g_signal_accumulator_true_handled, NULL,
+		  _gtk_marshal_BOOLEAN__BOXED,
+		  G_TYPE_BOOLEAN, 1,
+		  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+  /**
+   * GtkStatusIcon::button-release-event:
+   * @status_icon: the object which received the signal
+   * @event: the #GdkEventButton which triggered this signal
+   *
+   * The ::button-release-event signal will be emitted when a button
+   * (typically from a mouse) is released.
+   *
+   * Whether this event is emitted is platform-dependent.  Use the ::activate
+   * and ::popup-menu signals in preference.
+   *
+   * Return value: %TRUE to stop other handlers from being invoked
+   * for the event. %FALSE to propagate the event further.
+   *
+   * Since: 2.14
+   */
+  status_icon_signals [BUTTON_RELEASE_EVENT_SIGNAL] =
+    g_signal_new (I_("button_release_event"),
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkStatusIconClass, button_release_event),
+		  g_signal_accumulator_true_handled, NULL,
+		  _gtk_marshal_BOOLEAN__BOXED,
+		  G_TYPE_BOOLEAN, 1,
+		  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+  /**
+   * GtkStatusIcon::scroll-event:
+   * @status_icon: the object which received the signal.
+   * @event: the #GdkEventScroll which triggered this signal
+   *
+   * The ::scroll-event signal is emitted when a button in the 4 to 7
+   * range is pressed. Wheel mice are usually configured to generate 
+   * button press events for buttons 4 and 5 when the wheel is turned.
+   *
+   * Whether this event is emitted is platform-dependent.
+   *
+   * Returns: %TRUE to stop other handlers from being invoked for the event. 
+   *   %FALSE to propagate the event further.
+   */
+  status_icon_signals[SCROLL_EVENT_SIGNAL] =
+    g_signal_new (I_("scroll_event"),
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkStatusIconClass, scroll_event),
+		  g_signal_accumulator_true_handled, NULL,
+		  _gtk_marshal_BOOLEAN__BOXED,
+		  G_TYPE_BOOLEAN, 1,
+		  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+  /**
+   * GtkStatusIcon::query-tooltip:
+   * @status_icon: the object which received the signal
+   * @x: the x coordinate of the cursor position where the request has been
+   *     emitted, relative to @status_icon
+   * @y: the y coordinate of the cursor position where the request has been
+   *     emitted, relative to @status_icon
+   * @keyboard_mode: %TRUE if the tooltip was trigged using the keyboard
+   * @tooltip: a #GtkTooltip
+   *
+   * Emitted when the #GtkSettings:gtk-tooltip-timeout has expired with the
+   * cursor hovering "above" @status_icon; or emitted when @status_icon got
+   * focus in keyboard mode.
+   * 
+   * Using the given coordinates, the signal handler should determine
+   * whether a tooltip should be shown for @status_icon. If this is
+   * the case %TRUE should be returned, %FALSE otherwise. Note that if
+   * @keyboard_mode is %TRUE, the values of @x and @y are undefined and
+   * should not be used.
+   * 
+   * The signal handler is free to manipulate @tooltip with the therefore
+   * destined function calls.
+   *
+   * Whether this event is emitted is platform-dependent.  For plain text
+   * tooltips, use :tooltip-text in preference.
+   *
+   * Returns: %TRUE if @tooltip should be shown right now, %FALSE otherwise.
+   *
+   * Since: 2.14
+   */
+  status_icon_signals [QUERY_TOOLTIP_SIGNAL] =
+    g_signal_new (I_("query_tooltip"),
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkStatusIconClass, query_tooltip),
+		  g_signal_accumulator_true_handled, NULL,
+		  _gtk_marshal_BOOLEAN__INT_INT_BOOLEAN_OBJECT,
+		  G_TYPE_BOOLEAN, 4,
+		  G_TYPE_INT,
+		  G_TYPE_INT,
+		  G_TYPE_BOOLEAN,
+		  GTK_TYPE_TOOLTIP);
+
   g_type_class_add_private (class, sizeof (GtkStatusIconPrivate));
 }
 
@@ -392,7 +606,10 @@ button_callback (gpointer data)
 {
   ButtonCallbackData *bc = (ButtonCallbackData *) data;
 
-  gtk_status_icon_button_press (bc->status_icon, bc->event);
+  if (event->type == GDK_BUTTON_PRESS)
+    gtk_status_icon_button_press (bc->status_icon, bc->event);
+  else
+    gtk_status_icon_button_release (bc->status_icon, bc->event);
 
   gdk_event_free ((GdkEvent *) bc->event);
   g_free (data);
@@ -409,17 +626,62 @@ wndproc (HWND   hwnd,
   if (message == WM_GTK_TRAY_NOTIFICATION)
     {
       ButtonCallbackData *bc;
+      guint button;
       
       switch (lparam)
 	{
 	case WM_LBUTTONDOWN:
+	  button = 1;
+	  goto buttondown0;
+
+	case WM_MBUTTONDOWN:
+	  button = 2;
+	  goto buttondown0;
+
 	case WM_RBUTTONDOWN:
+	  button = 3;
+	  goto buttondown0;
+
+	case WM_XBUTTONDOWN:
+	  if (HIWORD (wparam) == XBUTTON1)
+	    button = 4;
+	  else
+	    button = 5;
+
+	buttondown0:
 	  bc = g_new (ButtonCallbackData, 1);
 	  bc->event = (GdkEventButton *) gdk_event_new (GDK_BUTTON_PRESS);
 	  bc->status_icon = GTK_STATUS_ICON (wparam);
-	  build_button_event (bc->status_icon->priv, bc->event, (lparam == WM_LBUTTONDOWN) ? 1 : 3);
+	  build_button_event (bc->status_icon->priv, bc->event, button);
+	  g_idle_add (button_callback, bc);
+	  break;
+
+	case WM_LBUTTONUP:
+	  button = 1;
+	  goto buttonup0;
+
+	case WM_MBUTTONUP:
+	  button = 2;
+	  goto buttonup0;
+
+	case WM_RBUTTONUP:
+	  button = 3;
+	  goto buttonup0;
+
+	case WM_XBUTTONUP:
+	  if (HIWORD (wparam) == XBUTTON1)
+	    button = 4;
+	  else
+	    button = 5;
+
+	buttonup0:
+	  bc = g_new (ButtonCallbackData, 1);
+	  bc->event = (GdkEventButton *) gdk_event_new (GDK_BUTTON_RELEASE);
+	  bc->status_icon = GTK_STATUS_ICON (wparam);
+	  build_button_event (bc->status_icon->priv, bc->event, button);
 	  g_idle_add (button_callback, bc);
 	  break;
+
 	default :
 	  break;
 	}
@@ -486,7 +748,8 @@ gtk_status_icon_init (GtkStatusIcon *sta
   priv->tray_icon = GTK_WIDGET (_gtk_tray_icon_new (NULL));
 
   gtk_widget_add_events (GTK_WIDGET (priv->tray_icon),
-			 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+			 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+			 GDK_SCROLL_MASK);
 
   g_signal_connect_swapped (priv->tray_icon, "notify::embedded",
 			    G_CALLBACK (gtk_status_icon_embedded_changed), status_icon);
@@ -494,6 +757,12 @@ gtk_status_icon_init (GtkStatusIcon *sta
 			    G_CALLBACK (gtk_status_icon_orientation_changed), status_icon);
   g_signal_connect_swapped (priv->tray_icon, "button-press-event",
 			    G_CALLBACK (gtk_status_icon_button_press), status_icon);
+  g_signal_connect_swapped (priv->tray_icon, "button-release-event",
+			    G_CALLBACK (gtk_status_icon_button_release), status_icon);
+  g_signal_connect_swapped (priv->tray_icon, "scroll-event",
+			    G_CALLBACK (gtk_status_icon_scroll), status_icon);
+  g_signal_connect_swapped (priv->tray_icon, "query-tooltip",
+			    G_CALLBACK (gtk_status_icon_query_tooltip), status_icon);
   g_signal_connect_swapped (priv->tray_icon, "screen-changed",
 		    	    G_CALLBACK (gtk_status_icon_screen_changed), status_icon);
   priv->image = gtk_image_new ();
@@ -604,6 +873,7 @@ gtk_status_icon_finalize (GObject *objec
     Shell_NotifyIconW (NIM_DELETE, &priv->nid);
   if (priv->nid.hIcon)
     DestroyIcon (priv->nid.hIcon);
+  g_free (priv->tooltip_text);
 
   gtk_widget_destroy (priv->dummy_widget);
 #endif
@@ -612,6 +882,7 @@ gtk_status_icon_finalize (GObject *objec
   QUARTZ_POOL_ALLOC;
   [priv->status_item release];
   QUARTZ_POOL_RELEASE;
+  g_free (priv->tooltip_text);
 #endif
 
   G_OBJECT_CLASS (gtk_status_icon_parent_class)->finalize (object);
@@ -648,6 +919,12 @@ gtk_status_icon_set_property (GObject   
     case PROP_VISIBLE:
       gtk_status_icon_set_visible (status_icon, g_value_get_boolean (value));
       break;
+    case PROP_HAS_TOOLTIP:
+      gtk_status_icon_set_has_tooltip (status_icon, g_value_get_boolean (value));
+    case PROP_TOOLTIP_TEXT:
+      gtk_status_icon_set_tooltip_text (status_icon, g_value_get_string (value));
+    case PROP_TOOLTIP_MARKUP:
+      gtk_status_icon_set_tooltip_markup (status_icon, g_value_get_string (value));
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -715,6 +992,15 @@ gtk_status_icon_get_property (GObject   
       g_value_set_enum (value, status_icon->priv->orientation);
 #endif
       break;
+    case PROP_HAS_TOOLTIP:
+      g_value_set_boolean (value, gtk_status_icon_get_has_tooltip (status_icon));
+      break;
+    case PROP_TOOLTIP_TEXT:
+      g_value_set_string (value, gtk_status_icon_get_tooltip_text (status_icon));
+      break;
+    case PROP_TOOLTIP_MARKUP:
+      g_value_set_string (value, gtk_status_icon_get_tooltip_markup (status_icon));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1204,6 +1490,14 @@ static gboolean
 gtk_status_icon_button_press (GtkStatusIcon  *status_icon,
 			      GdkEventButton *event)
 {
+  gboolean handled = FALSE;
+
+  g_signal_emit (status_icon,
+		 status_icon_signals [BUTTON_PRESS_EVENT_SIGNAL], 0,
+		 event, &handled);
+  if (handled)
+    return TRUE;
+
   if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
     {
       emit_activate_signal (status_icon);
@@ -1218,6 +1512,44 @@ gtk_status_icon_button_press (GtkStatusI
   return FALSE;
 }
 
+static gboolean
+gtk_status_icon_button_release (GtkStatusIcon  *status_icon,
+				GdkEventButton *event)
+{
+  gboolean handled = FALSE;
+  g_signal_emit (status_icon,
+		 status_icon_signals [BUTTON_RELEASE_EVENT_SIGNAL], 0,
+		 event, &handled);
+  return handled;
+}
+
+#ifdef GDK_WINDOWING_X11
+static gboolean
+gtk_status_icon_scroll (GtkStatusIcon  *status_icon,
+			GdkEventScroll *event)
+{
+  gboolean handled = FALSE;
+  g_signal_emit (status_icon,
+		 status_icon_signals [SCROLL_EVENT_SIGNAL], 0,
+		 event, &handled);
+  return handled;
+}
+
+static gboolean
+gtk_status_icon_query_tooltip (GtkStatusIcon *status_icon,
+			       gint           x,
+			       gint           y,
+			       gboolean       keyboard_tip,
+			       GtkTooltip    *tooltip)
+{
+  gboolean handled = FALSE;
+  g_signal_emit (status_icon,
+		 status_icon_signals [QUERY_TOOLTIP_SIGNAL], 0,
+		 x, y, keyboard_tip, tooltip, &handled);
+  return handled;
+}
+#endif /* GDK_WINDOWING_X11 */
+
 static void
 gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon)
 {
@@ -1581,43 +1913,14 @@ gtk_status_icon_get_screen (GtkStatusIco
  * Sets the tooltip of the status icon.
  * 
  * Since: 2.10
+ *
+ * Deprecated: Use gtk_status_icon_set_tooltip_text() instead.
  **/ 
 void
 gtk_status_icon_set_tooltip (GtkStatusIcon *status_icon,
 			     const gchar   *tooltip_text)
 {
-  GtkStatusIconPrivate *priv;
-
-  g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
-
-  priv = status_icon->priv;
-
-#ifdef GDK_WINDOWING_X11
-
-  gtk_widget_set_tooltip_text (priv->tray_icon, tooltip_text);
-
-#endif
-#ifdef GDK_WINDOWING_WIN32
-  if (tooltip_text == NULL)
-    priv->nid.uFlags &= ~NIF_TIP;
-  else
-    {
-      WCHAR *wcs = g_utf8_to_utf16 (tooltip_text, -1, NULL, NULL, NULL);
-
-      priv->nid.uFlags |= NIF_TIP;
-      wcsncpy (priv->nid.szTip, wcs, G_N_ELEMENTS (priv->nid.szTip) - 1);
-      priv->nid.szTip[G_N_ELEMENTS (priv->nid.szTip) - 1] = 0;
-      g_free (wcs);
-    }
-  if (priv->nid.hWnd != NULL && priv->visible)
-    if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
-      g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1);
-#endif
-#ifdef GDK_WINDOWING_QUARTZ
-  QUARTZ_POOL_ALLOC;
-  [priv->status_item setToolTip:tooltip_text];
-  QUARTZ_POOL_RELEASE;
-#endif
+  gtk_status_icon_set_tooltip_text (status_icon, tooltip_text);
 }
 
 static gboolean
@@ -2017,6 +2320,248 @@ gtk_status_icon_get_geometry (GtkStatusI
 #endif /* GDK_WINDOWING_X11 */
 }
 
+/**
+ * gtk_status_icon_set_has_tooltip:
+ * @status_icon: a #GtkStatusIcon
+ * @has_tooltip: whether or not @status_icon has a tooltip.
+ *
+ * Sets the has-tooltip property on @status_icon to @has_tooltip.  See
+ * GtkStatusIcon:has-tooltip for more information.
+ *
+ * Since: 2.14
+ */
+void
+gtk_status_icon_set_has_tooltip (GtkStatusIcon *status_icon,
+				 gboolean       has_tooltip)
+{
+  GtkStatusIconPrivate *priv;
+
+  g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
+
+  priv = status_icon->priv;
+
+#ifdef GDK_WINDOWING_X11
+  gtk_widget_set_has_tooltip (priv->tray_icon, has_tooltip);
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (!has_tooltip && priv->tooltip_text)
+    gtk_tray_icon_set_tooltip_text (status_icon, NULL);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+  if (!has_tooltip && priv->tooltip_text)
+    gtk_tray_icon_set_tooltip_text (status_icon, NULL);
+#endif
+}
+
+/**
+ * gtk_status_icon_get_has_tooltip:
+ * @status_icon: a #GtkStatusIcon
+ *
+ * Returns the current value of the has-tooltip property.  See
+ * GtkStatusIcon:has-tooltip for more information.
+ *
+ * Return value: current value of has-tooltip on @status_icon.
+ *
+ * Since: 2.14
+ */
+gboolean
+gtk_status_icon_get_has_tooltip (GtkStatusIcon *status_icon)
+{
+  GtkStatusIconPrivate *priv;
+  gboolean has_tooltip = FALSE;
+
+  g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
+
+  priv = status_icon->priv;
+
+#ifdef GDK_WINDOWING_X11
+  has_tooltip = gtk_widget_get_has_tooltip (priv->tray_icon);
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  has_tooltip = (priv->tooltip_text != NULL);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+  has_tooltip = (priv->tooltip_text != NULL);
+#endif
+
+  return has_tooltip;
+}
+
+/**
+ * gtk_status_icon_set_tooltip_text:
+ * @status_icon: a #GtkStatusIcon
+ * @tooltip_text: the contents of the tooltip for @status_icon
+ *
+ * Sets @tooltip_text as the contents of the tooltip. This function will take
+ * care of setting GtkStatusIcon:has-tooltip to %TRUE and of the default
+ * handler for the GtkStatusIcon::query-tooltip signal.
+ *
+ * See also the GtkStatusIcon:tooltip-text property and gtk_tooltip_set_text().
+ *
+ * Since: 2.14
+ */
+void
+gtk_status_icon_set_tooltip_text (GtkStatusIcon *status_icon,
+				  const gchar   *tooltip_text)
+{
+  GtkStatusIconPrivate *priv;
+
+  g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
+
+  priv = status_icon->priv;
+
+#ifdef GDK_WINDOWING_X11
+
+  gtk_widget_set_tooltip_text (priv->tray_icon, tooltip_text);
+
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (tooltip_text == NULL)
+    priv->nid.uFlags &= ~NIF_TIP;
+  else
+    {
+      WCHAR *wcs = g_utf8_to_utf16 (tooltip_text, -1, NULL, NULL, NULL);
+
+      priv->nid.uFlags |= NIF_TIP;
+      wcsncpy (priv->nid.szTip, wcs, G_N_ELEMENTS (priv->nid.szTip) - 1);
+      priv->nid.szTip[G_N_ELEMENTS (priv->nid.szTip) - 1] = 0;
+      g_free (wcs);
+    }
+  if (priv->nid.hWnd != NULL && priv->visible)
+    if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
+      g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+
+  g_free (priv->tooltip_text);
+  priv->tooltip_text = g_strdup (tooltip_text);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+  QUARTZ_POOL_ALLOC;
+  [priv->status_item setToolTip:tooltip_text];
+  QUARTZ_POOL_RELEASE;
+
+  g_free (priv->tooltip_text);
+  priv->tooltip_text = g_strdup (tooltip_text);
+#endif
+}
+
+/**
+ * gtk_status_icon_get_tooltip_text:
+ * @status_icon: a #GtkStatusIcon
+ *
+ * Gets the contents of the tooltip for @status_icon.
+ *
+ * Return value: the tooltip text, or %NULL. You should free the
+ *   returned string with g_free() when done.
+ *
+ * Since: 2.14
+ */
+gchar *
+gtk_status_icon_get_tooltip_text (GtkStatusIcon *status_icon)
+{
+  GtkStatusIconPrivate *priv;
+  gchar *tooltip_text = NULL;
+
+  g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
+
+  priv = status_icon->priv;
+
+#ifdef GDK_WINDOWING_X11
+  tooltip_text = gtk_widget_get_tooltip_text (priv->tray_icon);
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (priv->tooltip_text)
+    tooltip_text = g_strdup (priv->tooltip_text);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+  if (priv->tooltip_text)
+    tooltip_text = g_strdup (priv->tooltip_text);
+#endif
+
+  return tooltip_text;
+}
+
+/**
+ * gtk_status_icon_set_tooltip_markup:
+ * @status_icon: a #GtkStatusIcon
+ * @markup: the contents of the tooltip for @status_icon, or %NULL
+ *
+ * Sets @markup as the contents of the tooltip, which is marked up with
+ *  the <link linkend="PangoMarkupFormat">Pango text markup language</link>.
+ *
+ * This function will take care of setting GtkStatusIcon:has-tooltip to %TRUE
+ * and of the default handler for the GtkStatusIcon::query-tooltip signal.
+ *
+ * See also the GtkStatusIcon:tooltip-markup property and
+ * gtk_tooltip_set_markup().
+ *
+ * Since: 2.14
+ */
+void
+gtk_status_icon_set_tooltip_markup (GtkStatusIcon *status_icon,
+				    const gchar   *markup)
+{
+  GtkStatusIconPrivate *priv;
+#ifndef GDK_WINDOWING_X11
+  gchar *text = NULL;
+#endif
+
+  g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
+
+  priv = status_icon->priv;
+
+#ifdef GDK_WINDOWING_X11
+  gtk_widget_set_tooltip_markup (priv->tray_icon, markup);
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (markup)
+    pango_parse_markup (markup, -1, 0, NULL, &text, NULL, NULL);
+  gtk_status_icon_set_tooltip_text (status_icon, text);
+  g_free (text);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+  if (markup)
+    pango_parse_markup (markup, -1, 0, NULL, &text, NULL, NULL);
+  gtk_status_icon_set_tooltip_text (status_icon, text);
+  g_free (text);
+#endif
+}
+
+/**
+ * gtk_status_icon_get_tooltip_markup:
+ * @status_icon: a #GtkStatusIcon
+ *
+ * Gets the contents of the tooltip for @status_icon.
+ *
+ * Return value: the tooltip text, or %NULL. You should free the
+ *   returned string with g_free() when done.
+ *
+ * Since: 2.14
+ */
+gchar *
+gtk_status_icon_get_tooltip_markup (GtkStatusIcon *status_icon)
+{
+  GtkStatusIconPrivate *priv;
+  gchar *markup = NULL;
+
+  g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
+
+  priv = status_icon->priv;
+
+#ifdef GDK_WINDOWING_X11
+  markup = gtk_widget_get_tooltip_markup (priv->tray_icon);
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (priv->tooltip_text)
+    markup = g_markup_escape_text (priv->tooltip_text);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+  if (priv->tooltip_text)
+    markup = g_markup_escape_text (priv->tooltip_text);
+#endif
+
+  return markup;
+}
+
 
 #define __GTK_STATUS_ICON_C__
 #include "gtkaliasdef.c"
--- gtk/gtkstatusicon.h	2007/09/17 22:38:53	1.1
+++ gtk/gtkstatusicon.h	2007/09/24 06:53:50
@@ -57,11 +57,18 @@ struct _GtkStatusIconClass
 			     guint32        activate_time);
   gboolean (* size_changed) (GtkStatusIcon *status_icon,
 			     gint           size);
+  gboolean (* button_press_event)   (GtkStatusIcon  *status_icon,
+				     GdkEventButton *event);
+  gboolean (* button_release_event) (GtkStatusIcon  *status_icon,
+				     GdkEventButton *event);
+  gboolean (* scroll_event)         (GtkStatusIcon  *status_icon,
+				     GdkEventScroll *event);
+  gboolean (* query_tooltip)        (GtkStatusIcon  *status_icon,
+				     gint            x,
+				     gint            y,
+				     gboolean        keyboard_mode,
+				     GtkTooltip     *tooltip);
 
-  void (*__gtk_reserved1);
-  void (*__gtk_reserved2);
-  void (*__gtk_reserved3);
-  void (*__gtk_reserved4);
   void (*__gtk_reserved5);
   void (*__gtk_reserved6);  
 };
@@ -82,6 +89,12 @@ void                  gtk_status_icon_se
 							  const gchar        *stock_id);
 void                  gtk_status_icon_set_from_icon_name (GtkStatusIcon      *status_icon,
 							  const gchar        *icon_name);
+void                  gtk_status_icon_set_has_tooltip    (GtkStatusIcon      *status_icon,
+							  gboolean            has_tooltip);
+void                  gtk_status_icon_set_tooltip_text   (GtkStatusIcon      *status_icon,
+							  const char         *text);
+void                  gtk_status_icon_set_tooltip_markup (GtkStatusIcon      *status_icon,
+							  const char         *markup);
 
 GtkImageType          gtk_status_icon_get_storage_type   (GtkStatusIcon      *status_icon);
 
@@ -95,8 +108,10 @@ void                  gtk_status_icon_se
                                                           GdkScreen          *screen);
 GdkScreen            *gtk_status_icon_get_screen         (GtkStatusIcon      *status_icon);
 
+#ifndef GTK_DISABLE_DEPRECATED
 void                  gtk_status_icon_set_tooltip        (GtkStatusIcon      *status_icon,
 							  const gchar        *tooltip_text);
+#endif
 
 void                  gtk_status_icon_set_visible        (GtkStatusIcon      *status_icon,
 							  gboolean            visible);
@@ -117,6 +132,9 @@ gboolean              gtk_status_icon_ge
 							  GdkScreen         **screen,
 							  GdkRectangle       *area,
 							  GtkOrientation     *orientation);
+gboolean              gtk_status_icon_get_has_tooltip    (GtkStatusIcon      *status_icon);
+gchar                *gtk_status_icon_get_tooltip_text   (GtkStatusIcon      *status_icon);
+gchar                *gtk_status_icon_get_tooltip_markup (GtkStatusIcon      *status_icon);
 
 G_END_DECLS
 
--- gtk/gtk.symbols	2007/09/24 06:36:02	1.1
+++ gtk/gtk.symbols	2007/09/24 21:56:59
@@ -1110,7 +1110,9 @@ gtk_status_icon_get_stock
 gtk_status_icon_get_icon_name
 gtk_status_icon_get_size
 gtk_status_icon_set_screen
+#ifndef GTK_DISABLE_DEPRECATED
 gtk_status_icon_set_tooltip
+#endif
 gtk_status_icon_set_visible
 gtk_status_icon_get_visible
 gtk_status_icon_set_blinking
@@ -1118,6 +1120,12 @@ gtk_status_icon_get_blinking
 gtk_status_icon_is_embedded
 gtk_status_icon_position_menu
 gtk_status_icon_get_geometry
+gtk_status_icon_set_has_tooltip
+gtk_status_icon_set_tooltip_text
+gtk_status_icon_set_tooltip_markup
+gtk_status_icon_get_has_tooltip
+gtk_status_icon_get_tooltip_text
+gtk_status_icon_get_tooltip_markup
 #endif
 #endif
 
