]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktooltip.c
gtk: remove "gboolean homogeneous" from gtk_box_new()
[~andy/gtk] / gtk / gtktooltip.c
index d5a301be4e56c3bcc1c3da9ab2225856504ebeec..309013f8470464f1d9312c72bccf26c230713f51 100644 (file)
 
 #include "config.h"
 
+#include "gtktooltip.h"
+
 #include <math.h>
 #include <string.h>
 
-#include "gtktooltip.h"
 #include "gtkintl.h"
 #include "gtkwindow.h"
 #include "gtkmain.h"
 #include "gtkimage.h"
 #include "gtkhbox.h"
 #include "gtkalignment.h"
+#include "gtksizerequest.h"
+
+
+/**
+ * SECTION:gtktooltip
+ * @Short_description: Add tips to your widgets
+ * @Title: GtkTooltip
+ *
+ * Basic tooltips can be realized simply by using gtk_widget_set_tooltip_text()
+ * or gtk_widget_set_tooltip_markup() without any explicit tooltip object.
+ *
+ * When you need a tooltip with a little more fancy contents, like adding an
+ * image, or you want the tooltip to have different contents per #GtkTreeView
+ * row or cell, you will have to do a little more work:
+ * <itemizedlist>
+ * <listitem>
+ * <para>
+ * Set the #GtkWidget:has-tooltip property to %TRUE, this will make GTK+
+ * monitor the widget for motion and related events which are needed to
+ * determine when and where to show a tooltip.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * Connect to the #GtkWidget::query-tooltip signal.  This signal will be
+ * emitted when a tooltip is supposed to be shown. One of the arguments passed
+ * to the signal handler is a GtkTooltip object. This is the object that we
+ * are about to display as a tooltip, and can be manipulated in your callback
+ * using functions like gtk_tooltip_set_icon(). There are functions for setting
+ * the tooltip's markup, setting an image from a stock icon, or even putting in
+ * a custom widget.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * Return %TRUE from your query-tooltip handler. This causes the tooltip to be
+ * show. If you return %FALSE, it will not be shown.
+ * </para>
+ * </listitem>
+ * </itemizedlist>
+ *
+ * In the probably rare case where you want to have even more control over the
+ * tooltip that is about to be shown, you can set your own #GtkWindow which
+ * will be used as tooltip window.  This works as follows:
+ * <itemizedlist>
+ * <listitem>
+ * <para>
+ * Set #GtkWidget:has-tooltip and connect to #GtkWidget::query-tooltip as
+ * before.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * Use gtk_widget_set_tooltip_window() to set a #GtkWindow created by you as
+ * tooltip window.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * In the #GtkWidget::query-tooltip callback you can access your window using
+ * gtk_widget_get_tooltip_window() and manipulate as you wish. The semantics of
+ * the return value are exactly as before, return %TRUE to show the window,
+ * %FALSE to not show it.
+ * </para>
+ * </listitem>
+ * </itemizedlist>
+ */
 
-#include "gtkalias.h"
 
 #undef DEBUG_TOOLTIP
 
@@ -89,7 +156,8 @@ static void       gtk_tooltip_init                 (GtkTooltip      *tooltip);
 static void       gtk_tooltip_dispose              (GObject         *object);
 
 static void       gtk_tooltip_window_style_set     (GtkTooltip      *tooltip);
-static gboolean   gtk_tooltip_paint_window         (GtkTooltip      *tooltip);
+static gboolean   gtk_tooltip_paint_window         (GtkTooltip      *tooltip,
+                                                    cairo_t         *cr);
 static void       gtk_tooltip_window_hide          (GtkWidget       *widget,
                                                    gpointer         user_data);
 static void       gtk_tooltip_display_closed       (GdkDisplay      *display,
@@ -114,6 +182,8 @@ gtk_tooltip_class_init (GtkTooltipClass *klass)
 static void
 gtk_tooltip_init (GtkTooltip *tooltip)
 {
+  GtkStyle *style;
+
   tooltip->timeout_id = 0;
   tooltip->browse_mode_timeout_id = 0;
 
@@ -137,21 +207,21 @@ gtk_tooltip_init (GtkTooltip *tooltip)
   g_signal_connect (tooltip->window, "hide",
                    G_CALLBACK (gtk_tooltip_window_hide), tooltip);
 
+  style = gtk_widget_get_style (tooltip->window);
+
   tooltip->alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
   gtk_alignment_set_padding (GTK_ALIGNMENT (tooltip->alignment),
-                            tooltip->window->style->ythickness,
-                            tooltip->window->style->ythickness,
-                            tooltip->window->style->xthickness,
-                            tooltip->window->style->xthickness);
+                             style->ythickness, style->ythickness,
+                             style->xthickness, style->xthickness);
   gtk_container_add (GTK_CONTAINER (tooltip->window), tooltip->alignment);
   gtk_widget_show (tooltip->alignment);
 
   g_signal_connect_swapped (tooltip->window, "style-set",
                            G_CALLBACK (gtk_tooltip_window_style_set), tooltip);
-  g_signal_connect_swapped (tooltip->window, "expose-event",
+  g_signal_connect_swapped (tooltip->window, "draw",
                            G_CALLBACK (gtk_tooltip_paint_window), tooltip);
 
-  tooltip->box = gtk_hbox_new (FALSE, tooltip->window->style->xthickness);
+  tooltip->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, style->xthickness);
   gtk_container_add (GTK_CONTAINER (tooltip->alignment), tooltip->box);
   gtk_widget_show (tooltip->box);
 
@@ -499,30 +569,33 @@ gtk_tooltip_reset (GtkTooltip *tooltip)
 static void
 gtk_tooltip_window_style_set (GtkTooltip *tooltip)
 {
+  GtkStyle *style;
+
+  style = gtk_widget_get_style (tooltip->window);
+
   gtk_alignment_set_padding (GTK_ALIGNMENT (tooltip->alignment),
-                            tooltip->window->style->ythickness,
-                            tooltip->window->style->ythickness,
-                            tooltip->window->style->xthickness,
-                            tooltip->window->style->xthickness);
+                             style->ythickness, style->ythickness,
+                             style->xthickness, style->xthickness);
+
   gtk_box_set_spacing (GTK_BOX (tooltip->box),
-                      tooltip->window->style->xthickness);
+                       style->xthickness);
 
   gtk_widget_queue_draw (tooltip->window);
 }
 
 static gboolean
-gtk_tooltip_paint_window (GtkTooltip *tooltip)
+gtk_tooltip_paint_window (GtkTooltip *tooltip,
+                          cairo_t    *cr)
 {
-  gtk_paint_flat_box (tooltip->window->style,
-                     tooltip->window->window,
+  gtk_paint_flat_box (gtk_widget_get_style (tooltip->window),
+                     cr,
                      GTK_STATE_NORMAL,
                      GTK_SHADOW_OUT,
-                     NULL,
                      tooltip->window,
                      "tooltip",
                      0, 0,
-                     tooltip->window->allocation.width,
-                     tooltip->window->allocation.height);
+                      gtk_widget_get_allocated_width (tooltip->window),
+                      gtk_widget_get_allocated_height (tooltip->window));
 
   return FALSE;
 }
@@ -551,6 +624,7 @@ static void
 child_location_foreach (GtkWidget *child,
                        gpointer   data)
 {
+  GtkAllocation child_allocation;
   gint x, y;
   struct ChildLocation *child_loc = data;
 
@@ -558,6 +632,8 @@ child_location_foreach (GtkWidget *child,
   if (!gtk_widget_is_drawable (child))
     return;
 
+  gtk_widget_get_allocation (child, &child_allocation);
+
   x = 0;
   y = 0;
 
@@ -573,17 +649,17 @@ child_location_foreach (GtkWidget *child,
 #ifdef DEBUG_TOOLTIP
       g_print ("candidate: %s  alloc=[(%d,%d)  %dx%d]     (%d, %d)->(%d, %d)\n",
               gtk_widget_get_name (child),
-              child->allocation.x,
-              child->allocation.y,
-              child->allocation.width,
-              child->allocation.height,
+               child_allocation.x,
+               child_allocation.y,
+               child_allocation.width,
+               child_allocation.height,
               child_loc->x, child_loc->y,
               x, y);
 #endif /* DEBUG_TOOLTIP */
 
       /* (x, y) relative to child's allocation. */
-      if (x >= 0 && x < child->allocation.width
-         && y >= 0 && y < child->allocation.height)
+      if (x >= 0 && x < child_allocation.width
+         && y >= 0 && y < child_allocation.height)
         {
          if (GTK_IS_CONTAINER (child))
            {
@@ -620,22 +696,28 @@ window_to_alloc (GtkWidget *dest_widget,
                 gint      *dest_x,
                 gint      *dest_y)
 {
+  GtkAllocation allocation;
+
+  gtk_widget_get_allocation (dest_widget, &allocation);
+
   /* Translate from window relative to allocation relative */
-  if (gtk_widget_get_has_window (dest_widget) && dest_widget->parent)
+  if (gtk_widget_get_has_window (dest_widget) &&
+      gtk_widget_get_parent (dest_widget))
     {
       gint wx, wy;
-      gdk_window_get_position (dest_widget->window, &wx, &wy);
+      gdk_window_get_position (gtk_widget_get_window (dest_widget),
+                               &wx, &wy);
 
       /* Offset coordinates if widget->window is smaller than
        * widget->allocation.
        */
-      src_x += wx - dest_widget->allocation.x;
-      src_y += wy - dest_widget->allocation.y;
+      src_x += wx - allocation.x;
+      src_y += wy - allocation.y;
     }
   else
     {
-      src_x -= dest_widget->allocation.x;
-      src_y -= dest_widget->allocation.y;
+      src_x -= allocation.x;
+      src_y -= allocation.y;
     }
 
   if (dest_x)
@@ -647,14 +729,18 @@ window_to_alloc (GtkWidget *dest_widget,
 /* Translates coordinates from window relative (x, y) to
  * allocation relative (x, y) of the returned widget.
  */
-static GtkWidget *
-find_widget_under_pointer (GdkWindow *window,
-                          gint      *x,
-                          gint      *y)
+GtkWidget *
+_gtk_widget_find_at_coords (GdkWindow *window,
+                            gint       window_x,
+                            gint       window_y,
+                            gint      *widget_x,
+                            gint      *widget_y)
 {
   GtkWidget *event_widget;
   struct ChildLocation child_loc = { NULL, NULL, 0, 0 };
 
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
   gdk_window_get_user_data (window, (void **)&event_widget);
 
   if (!event_widget)
@@ -663,18 +749,18 @@ find_widget_under_pointer (GdkWindow *window,
 #ifdef DEBUG_TOOLTIP
   g_print ("event window %p (belonging to %p (%s))  (%d, %d)\n",
           window, event_widget, gtk_widget_get_name (event_widget),
-          *x, *y);
+          window_x, window_y);
 #endif
 
   /* Coordinates are relative to event window */
-  child_loc.x = *x;
-  child_loc.y = *y;
+  child_loc.x = window_x;
+  child_loc.y = window_y;
 
   /* We go down the window hierarchy to the widget->window,
    * coordinates stay relative to the current window.
    * We end up with window == widget->window, coordinates relative to that.
    */
-  while (window && window != event_widget->window)
+  while (window && window != gtk_widget_get_window (event_widget))
     {
       gdouble px, py;
 
@@ -725,14 +811,13 @@ find_widget_under_pointer (GdkWindow *window,
       gtk_widget_translate_coordinates (container, event_widget,
                                        child_loc.x, child_loc.y,
                                        &child_loc.x, &child_loc.y);
-
     }
 
   /* We return (x, y) relative to the allocation of event_widget. */
-  if (x)
-    *x = child_loc.x;
-  if (y)
-    *y = child_loc.y;
+  if (widget_x)
+    *widget_x = child_loc.x;
+  if (widget_y)
+    *widget_y = child_loc.y;
 
   return event_widget;
 }
@@ -745,23 +830,23 @@ find_topmost_widget_coords_from_event (GdkEvent *event,
                                       gint     *x,
                                       gint     *y)
 {
+  GtkAllocation allocation;
   gint tx, ty;
   gdouble dx, dy;
   GtkWidget *tmp;
 
   gdk_event_get_coords (event, &dx, &dy);
-  tx = dx;
-  ty = dy;
 
   /* Returns coordinates relative to tmp's allocation. */
-  tmp = find_widget_under_pointer (event->any.window, &tx, &ty);
+  tmp = _gtk_widget_find_at_coords (event->any.window, dx, dy, &tx, &ty);
 
   if (!tmp)
     return NULL;
 
   /* Make sure the pointer can actually be on the widget returned. */
-  if (tx < 0 || tx >= tmp->allocation.width ||
-      ty < 0 || ty >= tmp->allocation.height)
+  gtk_widget_get_allocation (tmp, &allocation);
+  if (tx < 0 || tx >= allocation.width ||
+      ty < 0 || ty >= allocation.height)
     return NULL;
 
   if (x)
@@ -842,7 +927,7 @@ gtk_tooltip_run_requery (GtkWidget  **widget,
 
       if (!return_value)
         {
-         GtkWidget *parent = (*widget)->parent;
+         GtkWidget *parent = gtk_widget_get_parent (*widget);
 
          if (parent)
            gtk_widget_translate_coordinates (*widget, parent, *x, *y, x, y);
@@ -867,6 +952,7 @@ static void
 get_bounding_box (GtkWidget    *widget,
                   GdkRectangle *bounds)
 {
+  GtkAllocation allocation;
   GdkWindow *window;
   gint x, y;
   gint w, h;
@@ -876,11 +962,14 @@ get_bounding_box (GtkWidget    *widget,
   gint x4, y4;
 
   window = gtk_widget_get_parent_window (widget);
+  if (window == NULL)
+    window = gtk_widget_get_window (widget);
 
-  x = widget->allocation.x;
-  y = widget->allocation.y;
-  w = widget->allocation.width;
-  h = widget->allocation.height;
+  gtk_widget_get_allocation (widget, &allocation);
+  x = allocation.x;
+  y = allocation.y;
+  w = allocation.width;
+  h = allocation.height;
 
   gdk_window_get_root_coords (window, x, y, &x1, &y1);
   gdk_window_get_root_coords (window, x + w, y, &x2, &y2);
@@ -915,7 +1004,8 @@ gtk_tooltip_position (GtkTooltip *tooltip,
 
   screen = gtk_widget_get_screen (new_tooltip_widget);
 
-  gtk_widget_size_request (GTK_WIDGET (tooltip->current_window), &requisition);
+  gtk_widget_get_preferred_size (GTK_WIDGET (tooltip->current_window),
+                                 &requisition, NULL);
 
   monitor_num = gdk_screen_get_monitor_at_point (screen,
                                                  tooltip->last_x,
@@ -1084,8 +1174,9 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
       tooltip->last_x = tx;
       tooltip->last_y = ty;
 
-      pointer_widget = tooltip_widget = find_widget_under_pointer (window,
-                                                                  &x, &y);
+      pointer_widget = tooltip_widget = _gtk_widget_find_at_coords (window,
+                                                                    x, y,
+                                                                    &x, &y);
     }
 
   if (!tooltip_widget)
@@ -1273,7 +1364,8 @@ _gtk_tooltip_focus_in (GtkWidget *widget)
 
   tooltip->keyboard_widget = g_object_ref (widget);
 
-  gdk_window_get_device_position (widget->window, device, &x, &y, NULL);
+  gdk_window_get_device_position (gtk_widget_get_window (widget),
+                                  device, &x, &y, NULL);
 
   return_value = gtk_tooltip_run_requery (&widget, tooltip, &x, &y);
   if (!return_value)
@@ -1373,7 +1465,7 @@ _gtk_tooltip_hide (GtkWidget *widget)
   toplevel = gtk_widget_get_toplevel (widget);
 
   if (widget == tooltip->tooltip_widget
-      || toplevel->window == tooltip->toplevel_window)
+      || gtk_widget_get_window (toplevel) == tooltip->toplevel_window)
     gtk_tooltip_hide_tooltip (tooltip);
 }
 
@@ -1385,7 +1477,7 @@ tooltips_enabled (GdkWindow *window)
   GdkScreen *screen;
   GtkSettings *settings;
 
-  screen = gdk_drawable_get_screen (window);
+  screen = gdk_window_get_screen (window);
   settings = gtk_settings_get_for_screen (screen);
 
   g_object_get (settings,
@@ -1410,7 +1502,7 @@ _gtk_tooltip_handle_event (GdkEvent *event)
 
   /* Returns coordinates relative to has_tooltip_widget's allocation. */
   has_tooltip_widget = find_topmost_widget_coords_from_event (event, &x, &y);
-  display = gdk_drawable_get_display (event->any.window);
+  display = gdk_window_get_display (event->any.window);
   current_tooltip = g_object_get_data (G_OBJECT (display),
                                       "gdk-display-current-tooltip");
 
@@ -1531,7 +1623,3 @@ _gtk_tooltip_handle_event (GdkEvent *event)
        break;
     }
 }
-
-
-#define __GTK_TOOLTIP_C__
-#include "gtkaliasdef.c"