]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtklabel.c
Add length to gtk_tree_path_get_indices
[~andy/gtk] / gtk / gtklabel.c
index 31eb186874f249ddb97c876568305bbc9076a40e..f35910784caf8969b79eadfbb7b114449f5ac696 100644 (file)
@@ -48,7 +48,7 @@
 #include "gtkimage.h"
 #include "gtkshow.h"
 #include "gtktooltip.h"
-#include "gtkextendedlayout.h"
+#include "gtksizerequest.h"
 #include "gtkprivate.h"
 #include "gtkalias.h"
 
@@ -59,6 +59,7 @@ typedef struct
   gint wrap_width;
   gint width_chars;
   gint max_width_chars;
+
   gboolean mnemonics_visible;
 } GtkLabelPrivate;
 
@@ -156,7 +157,7 @@ enum {
 /* When rotating ellipsizable text we want the natural size to request 
  * more to ensure the label wont ever ellipsize in an allocation of full natural size.
  * */
-#define ROTATION_ELLIPSIZE_PADDING 12
+#define ROTATION_ELLIPSIZE_PADDING 2
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -304,22 +305,22 @@ static void          gtk_label_get_link_colors  (GtkWidget  *widget,
 static void          emit_activate_link         (GtkLabel     *label,
                                                  GtkLabelLink *link);
 
-static void gtk_label_layout_interface_init (GtkExtendedLayoutIface *iface);
-
-static void gtk_label_get_desired_width     (GtkExtendedLayout      *layout,
-                                             gint                   *minimum_size,
-                                             gint                   *natural_size);
-static void gtk_label_get_desired_height    (GtkExtendedLayout      *layout,
-                                             gint                   *minimum_size,
-                                             gint                   *natural_size);
-static void gtk_label_get_width_for_height  (GtkExtendedLayout      *layout,
-                                             gint                    height,
-                                             gint                   *minimum_width,
-                                             gint                   *natural_width);
-static void gtk_label_get_height_for_width  (GtkExtendedLayout      *layout,
-                                             gint                    width,
-                                             gint                   *minimum_height,
-                                             gint                   *natural_height);
+static void               gtk_label_size_request_init     (GtkSizeRequestIface *iface);
+static GtkSizeRequestMode gtk_label_get_request_mode      (GtkSizeRequest      *widget);
+static void               gtk_label_get_width             (GtkSizeRequest      *widget,
+                                                          gint                *minimum_size,
+                                                          gint                *natural_size);
+static void               gtk_label_get_height            (GtkSizeRequest      *widget,
+                                                          gint                *minimum_size,
+                                                          gint                *natural_size);
+static void               gtk_label_get_width_for_height  (GtkSizeRequest      *widget,
+                                                          gint                 height,
+                                                          gint                *minimum_width,
+                                                          gint                *natural_width);
+static void               gtk_label_get_height_for_width  (GtkSizeRequest      *widget,
+                                                          gint                 width,
+                                                          gint                *minimum_height,
+                                                          gint                *natural_height);
 
 static GQuark quark_angle = 0;
 
@@ -328,8 +329,8 @@ static GtkBuildableIface *buildable_parent_iface = NULL;
 G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_MISC,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_label_buildable_interface_init)
-                         G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
-                                                gtk_label_layout_interface_init));
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST,
+                                                gtk_label_size_request_init));
 
 static void
 add_move_binding (GtkBindingSet  *binding_set,
@@ -664,12 +665,13 @@ gtk_label_class_init (GtkLabelClass *class)
 
   /**
    * GtkLabel:width-chars:
-   * 
+   *
    * The desired width of the label, in characters. If this property is set to
-   * -1, the width will be calculated automatically, otherwise the label will
-   * request either 3 characters or the property value, whichever is greater.
-   * If the "width-chars" property is set to a positive value, then the 
-   * #GtkLabel:max-width-chars property is ignored. 
+   * -1, the width will be calculated automatically.
+   *
+   * See the section on <link linkend="label-text-layout">text layout</link>
+   * for details of how #GtkLabel:width-chars and #GtkLabel:max-width-chars
+   * determine the width of ellipsized and wrapped labels.
    *
    * Since: 2.6
    **/
@@ -726,11 +728,12 @@ gtk_label_class_init (GtkLabelClass *class)
    * GtkLabel:max-width-chars:
    * 
    * The desired maximum width of the label, in characters. If this property 
-   * is set to -1, the width will be calculated automatically, otherwise the 
-   * label will request space for no more than the requested number of 
-   * characters. If the #GtkLabel:width-chars property is set to a positive 
-   * value, then the "max-width-chars" property is ignored.
-   * 
+   * is set to -1, the width will be calculated automatically.
+   *
+   * See the section on <link linkend="label-text-layout">text layout</link>
+   * for details of how #GtkLabel:width-chars and #GtkLabel:max-width-chars
+   * determine the width of ellipsized and wrapped labels.
+   *
    * Since: 2.6
    **/
   g_object_class_install_property (gobject_class,
@@ -2876,17 +2879,6 @@ gtk_label_get_line_wrap_mode (GtkLabel *label)
   return label->wrap_mode;
 }
 
-
-void
-gtk_label_get (GtkLabel *label,
-              gchar   **str)
-{
-  g_return_if_fail (GTK_IS_LABEL (label));
-  g_return_if_fail (str != NULL);
-  
-  *str = label->text;
-}
-
 static void
 gtk_label_destroy (GtkObject *object)
 {
@@ -3024,7 +3016,7 @@ get_label_width (GtkLabel *label,
 
          *natural = MAX (*minimum, max_width);
        }
-   }
+    }
   else
     {
       *minimum = text_width;
@@ -3061,7 +3053,7 @@ get_label_wrap_width (GtkLabel *label)
   
   if (priv->wrap_width < 0)
     {
-      if (priv->width_chars > 0 || priv->max_width_chars > 0)
+      if (priv->width_chars > 0)
        {
          PangoLayout      *layout;
          PangoContext     *context;
@@ -3085,21 +3077,14 @@ get_label_wrap_width (GtkLabel *label)
 
          text_width = rect.width;
 
-         if (priv->max_width_chars < 0)
-           {
-             priv->wrap_width = PANGO_PIXELS (MAX (text_width, char_pixels * priv->width_chars));
-           }
-         else
-           {
-             priv->wrap_width = PANGO_PIXELS (MIN (text_width, char_pixels * priv->max_width_chars));
-           }
+         priv->wrap_width = PANGO_PIXELS (MAX (text_width, char_pixels * priv->width_chars));
        }
       else
        {
          PangoLayout *layout;
   
          layout = gtk_widget_create_pango_layout (GTK_WIDGET (label), 
-                                                  "This long string gives a good enough length for any line to have.");
+                                                  "This string is just about long enough.");
          pango_layout_get_size (layout, &priv->wrap_width, NULL);
          g_object_unref (layout);
        }
@@ -3184,13 +3169,22 @@ gtk_label_ensure_layout (GtkLabel *label, gboolean guess_wrap_width)
          GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
          gint longest_paragraph;
          gint width, height;
+         gint aux_width = 0;
+
+         if ((angle == 90 || angle == 270) && aux_info && aux_info->height > 0)
+           aux_width = aux_info->height;
+         else if (aux_info && aux_info->width > 0)
+           aux_width = aux_info->width;
 
-         if (aux_info && aux_info->width > 0)
-           pango_layout_set_width (label->layout, aux_info->width * PANGO_SCALE);
+         if (aux_width > 0)
+           pango_layout_set_width (label->layout, aux_width * PANGO_SCALE);
          else if (guess_wrap_width == FALSE &&
-                  widget->allocation.width > 1)
+                  widget->allocation.width > 1 && widget->allocation.height > 1)
            {
-             width = widget->allocation.width - label->misc.xpad * 2;
+             if (angle == 90 || angle == 270)
+               width = widget->allocation.height - label->misc.ypad * 2;
+             else
+               width = widget->allocation.width  - label->misc.xpad * 2;
 
              pango_layout_set_wrap (label->layout, label->wrap_mode);
              pango_layout_set_width (label->layout, MAX (width, 1) * PANGO_SCALE);
@@ -3276,28 +3270,37 @@ get_single_line_height (GtkWidget   *widget,
   return ascent + descent;
 }
 
-
-
 static void
-gtk_label_layout_interface_init (GtkExtendedLayoutIface *iface)
+gtk_label_size_request_init (GtkSizeRequestIface *iface)
 {
-  iface->get_desired_width    = gtk_label_get_desired_width;
-  iface->get_desired_height    = gtk_label_get_desired_height;
+  iface->get_request_mode     = gtk_label_get_request_mode;
+  iface->get_width            = gtk_label_get_width;
+  iface->get_height           = gtk_label_get_height;
   iface->get_width_for_height = gtk_label_get_width_for_height;
   iface->get_height_for_width = gtk_label_get_height_for_width;
 }
 
+static GtkSizeRequestMode
+gtk_label_get_request_mode (GtkSizeRequest *layout)
+{
+  GtkLabel *label = GTK_LABEL (layout);
+  gdouble   angle = gtk_label_get_angle (label);
 
+  if (angle == 90 || angle == 270)
+    return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
+
+  return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
+}
 
 static void
 get_size_for_allocation (GtkLabel        *label,
-                        GtkOrientation   orientation,
-                        gint             allocation,
-                        gint            *minimum_size,
-                        gint            *natural_size)
+                         GtkOrientation   orientation,
+                         gint             allocation,
+                         gint            *minimum_size,
+                         gint            *natural_size)
 {
   PangoLayout *layout;
-  GtkWidgetAuxInfo *aux_info = 
+  GtkWidgetAuxInfo *aux_info =
     _gtk_widget_get_aux_info (GTK_WIDGET (label), FALSE);
   gint aux_size;
   gint text_height;
@@ -3308,9 +3311,9 @@ get_size_for_allocation (GtkLabel        *label,
   if (aux_info)
     {
       if (orientation == GTK_ORIENTATION_HORIZONTAL)
-       aux_size = aux_info->width;
+        aux_size = aux_info->width;
       else
-       aux_size = aux_info->height;
+        aux_size = aux_info->height;
     }
   else
     aux_size = 0;
@@ -3332,16 +3335,17 @@ get_size_for_allocation (GtkLabel        *label,
 }
 
 static void
-gtk_label_get_desired_size (GtkExtendedLayout *layout,
-                           GtkOrientation     orientation,
-                            gint              *minimum_size,
-                            gint              *natural_size)
+gtk_label_get_size (GtkSizeRequest *widget,
+                   GtkOrientation  orientation,
+                   gint           *minimum_size,
+                   gint           *natural_size)
 {
-  GtkLabel      *label = GTK_LABEL (layout);
+  GtkLabel      *label = GTK_LABEL (widget);
   PangoRectangle required_rect;
   PangoRectangle natural_rect;
+  gdouble        angle;
 
-  /* "width-chars" Hard-coded minimum width: 
+  /* "width-chars" Hard-coded minimum width:
    *    - minimum size should be MAX (width-chars, strlen ("..."));
    *    - natural size should be MAX (width-chars, strlen (label->text));
    *
@@ -3349,15 +3353,16 @@ gtk_label_get_desired_size (GtkExtendedLayout *layout,
    *    - minimum size should be MAX (width-chars, 0)
    *    - natural size should be MIN (max-width-chars, strlen (label->text))
    *
-   *
-   *
    */
 
-  /* Refresh layout if needed */
+  /* When calculating ->wrap sometimes we need to invent a size; Ideally we should be doing
+   * that stuff here instead of inside gtk_label_ensure_layout() */
   if (label->wrap)
     gtk_label_clear_layout (label);
   gtk_label_ensure_layout (label, TRUE);
 
+  angle = gtk_label_get_angle (label);
+
   /* Start off with the pixel extents of the rendered layout */
   pango_layout_get_extents (label->layout, NULL, &required_rect);
   required_rect.x = required_rect.y = 0;
@@ -3366,7 +3371,7 @@ gtk_label_get_desired_size (GtkExtendedLayout *layout,
     required_rect.height = get_single_line_height (GTK_WIDGET (label), label->layout);
 
   natural_rect = required_rect;
-  
+
   /* Calculate text width itself based on GtkLabel property rules */
   get_label_width (label, &required_rect.width, &natural_rect.width);
 
@@ -3376,7 +3381,6 @@ gtk_label_get_desired_size (GtkExtendedLayout *layout,
       PangoLayout       *layout  = pango_layout_copy (label->layout);
       PangoContext      *context = pango_layout_get_context (label->layout);
       const PangoMatrix *matrix  = pango_context_get_matrix (context);
-      gdouble           angle;
 
       pango_layout_set_width (layout, -1);
       pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE);
@@ -3387,22 +3391,21 @@ gtk_label_get_desired_size (GtkExtendedLayout *layout,
       pango_matrix_transform_rectangle (matrix, &required_rect);
       pango_matrix_transform_rectangle (matrix, &natural_rect);
 
-      /* Bump the natural size incase of ellipsize to ensure pango has enough space in the angles 
-       * (note, we could alternatively set the layout to not ellipsize when we know we have been
-       * allocated our full natural size, or it may be that pango needs a fix here).
+      /* Bump the natural size in case of ellipsize to ensure pango has
+       * enough space in the angles (note, we could alternatively set the
+       * layout to not ellipsize when we know we have been allocated our
+       * full natural size, or it may be that pango needs a fix here).
        */
-      angle = gtk_label_get_angle (label);
-      if (label->ellipsize && 
-         angle != 0 && angle != 90 && angle != 180 && angle != 270 && angle != 360)
-       {
-         /* For some reason we only need this at about 110 degrees, and only
-          * when gaining in height
-          */
-         natural_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
-         natural_rect.width  += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
-       }
+      if (label->ellipsize && angle != 0 && angle != 90 && angle != 180 && angle != 270 && angle != 360)
+        {
+          /* For some reason we only need this at about 110 degrees, and only
+           * when gaining in height
+           */
+          natural_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+          natural_rect.width  += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+        }
     }
-  
+
   required_rect.width  = PANGO_PIXELS_CEIL (required_rect.width);
   required_rect.height = PANGO_PIXELS_CEIL (required_rect.height);
 
@@ -3411,81 +3414,142 @@ gtk_label_get_desired_size (GtkExtendedLayout *layout,
 
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
-      *minimum_size = required_rect.width + label->misc.xpad * 2;
-      *natural_size = natural_rect.width  + label->misc.xpad * 2;
+      /* Note, we cant use get_size_for_allocation() when rotating
+       * ellipsized labels.
+       */
+      if (!(label->ellipsize && label->have_transform) &&
+          (angle == 90 || angle == 270))
+        {
+          /* Doing a h4w request on a rotated label here, return the
+           * required width for the minimum height.
+           */
+          get_size_for_allocation (label,
+                                   GTK_ORIENTATION_VERTICAL,
+                                   required_rect.height,
+                                   minimum_size, natural_size);
+
+        }
+      else
+        {
+          /* Normal desired width */
+          *minimum_size = required_rect.width;
+          *natural_size = natural_rect.width;
+        }
+
+      *minimum_size += label->misc.xpad * 2;
+      *natural_size += label->misc.xpad * 2;
     }
-  else
+  else /* GTK_ORIENTATION_VERTICAL */
     {
-      /* When wrapping, just return a height contextual to the minimum width
-       * (minimum widths can only be specified by explicitly setting width-chars).
+      /* Note, we cant use get_size_for_allocation() when rotating
+       * ellipsized labels.
        */
-      if (label->wrap && !label->have_transform)
-       get_size_for_allocation (label, GTK_ORIENTATION_HORIZONTAL, 
-                                (required_rect.width  + label->misc.xpad * 2), minimum_size, natural_size);
+      if (!(label->ellipsize && label->have_transform) &&
+          (angle == 0 || angle == 180))
+        {
+          /* Doing a w4h request on a label here, return the required
+           * height for the minimum width.
+           */
+          get_size_for_allocation (label,
+                                   GTK_ORIENTATION_HORIZONTAL,
+                                   required_rect.width,
+                                   minimum_size, natural_size);
+        }
       else
-       {
-         /* If there is no wrapping, the height is static */
-         *minimum_size = required_rect.height + label->misc.ypad * 2;
-         *natural_size = *minimum_size;
-       }
+        {
+          /* A vertically rotated label does w4h, so return the base
+           * desired height (text length)
+           */
+          *minimum_size = required_rect.height;
+          *natural_size = natural_rect.height;
+        }
+
+      *minimum_size += label->misc.ypad * 2;
+      *natural_size += label->misc.ypad * 2;
     }
+
+  /* Restore real allocated size of layout; sometimes size-requests
+   * are randomly called without a following allocation; for this case
+   * we need to make sure we dont have a mucked up layout because we
+   * went and guessed the wrap-size.
+   */
+  if (label->wrap)
+    gtk_label_clear_layout (label);
+  gtk_label_ensure_layout (label, FALSE);
+
 }
 
 
 static void
-gtk_label_get_desired_width (GtkExtendedLayout *layout,
-                            gint              *minimum_size,
-                            gint              *natural_size)
+gtk_label_get_width (GtkSizeRequest *widget,
+                    gint           *minimum_size,
+                    gint           *natural_size)
 {
-  gtk_label_get_desired_size (layout, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
+  gtk_label_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
 }
 
 static void
-gtk_label_get_desired_height (GtkExtendedLayout *layout,
-                             gint              *minimum_size,
-                             gint              *natural_size)
+gtk_label_get_height (GtkSizeRequest *widget,
+                     gint           *minimum_size,
+                     gint           *natural_size)
 {
-  gtk_label_get_desired_size (layout, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
+  gtk_label_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
 }
 
 static void
-gtk_label_get_width_for_height (GtkExtendedLayout *layout,
-                                gint               height,
-                                gint              *minimum_width,
-                                gint              *natural_width)
+gtk_label_get_width_for_height (GtkSizeRequest *widget,
+                                gint            height,
+                                gint           *minimum_width,
+                                gint           *natural_width)
 {
-  GtkLabel *label = GTK_LABEL (layout);
+  GtkLabel *label = GTK_LABEL (widget);
   gdouble angle = gtk_label_get_angle (label);
 
-  if (label->wrap && (90 == angle || 270 == angle))
+  if (label->wrap && (angle == 90 || angle == 270))
     {
       if (label->wrap)
-       gtk_label_clear_layout (label);
+        gtk_label_clear_layout (label);
+
+      get_size_for_allocation (label, GTK_ORIENTATION_VERTICAL,
+                               MAX (1, height - (label->misc.ypad * 2)),
+                               minimum_width, natural_width);
 
-      get_size_for_allocation (label, GTK_ORIENTATION_VERTICAL, height, minimum_width, natural_width);
+      if (minimum_width)
+        *minimum_width += label->misc.xpad * 2;
+
+      if (natural_width)
+        *natural_width += label->misc.xpad * 2;
     }
   else
-    GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_width (layout, minimum_width, natural_width);
+    GTK_SIZE_REQUEST_GET_IFACE (widget)->get_width (widget, minimum_width, natural_width);
 }
 
 static void
-gtk_label_get_height_for_width (GtkExtendedLayout *layout,
-                                gint               width,
-                                gint              *minimum_height,
-                                gint              *natural_height)
+gtk_label_get_height_for_width (GtkSizeRequest *widget,
+                                gint            width,
+                                gint           *minimum_height,
+                                gint           *natural_height)
 {
-  GtkLabel *label = GTK_LABEL (layout);
+  GtkLabel *label = GTK_LABEL (widget);
   gdouble angle = gtk_label_get_angle (label);
 
-  if (label->wrap && (0 == angle || 180 == angle))
+  if (label->wrap && (angle == 0 || angle == 180 || angle == 360))
     {
       if (label->wrap)
-       gtk_label_clear_layout (label);
+        gtk_label_clear_layout (label);
+
+      get_size_for_allocation (label, GTK_ORIENTATION_HORIZONTAL,
+                               MAX (1, width - label->misc.xpad * 2),
+                               minimum_height, natural_height);
 
-      get_size_for_allocation (label, GTK_ORIENTATION_HORIZONTAL, width, minimum_height, natural_height);
+      if (minimum_height)
+        *minimum_height += label->misc.ypad * 2;
+
+      if (natural_height)
+        *natural_height += label->misc.ypad * 2;
     }
   else
-    GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_height (layout, minimum_height, natural_height);
+    GTK_SIZE_REQUEST_GET_IFACE (widget)->get_height (widget, minimum_height, natural_height);
 }
 
 static void
@@ -3498,8 +3562,8 @@ gtk_label_size_allocate (GtkWidget     *widget,
 
   GTK_WIDGET_CLASS (gtk_label_parent_class)->size_allocate (widget, allocation);
 
-  /* The layout may have been recently cleared in get_size_for_orientation(), but the 
-   * width at that point may not be the same as the allocated width
+  /* The layout may have been recently cleared in get_size_for_orientation(),
+   * but the width at that point may not be the same as the allocated width
    */
   if (label->wrap)
     gtk_label_clear_layout (label);
@@ -3509,7 +3573,7 @@ gtk_label_size_allocate (GtkWidget     *widget,
   if (label->ellipsize)
     {
       if (label->layout)
-       {
+        {
           PangoRectangle logical;
           PangoRectangle bounds;
 
@@ -3544,13 +3608,13 @@ gtk_label_size_allocate (GtkWidget     *widget,
                   gint cy;
 
                   x0 = bounds.width / 2;
-                  y0 = dx ? x0 * dy / dx : dy * INFINITY;
+                  y0 = dx ? x0 * dy / dx : G_MAXDOUBLE;
                   vertical = fabs (y0) > bounds.height / 2;
 
                   if (vertical)
                     {
                       y0 = bounds.height/2;
-                      x0 = dy ? y0 * dx / dy : dx * INFINITY;
+                      x0 = dy ? y0 * dx / dy : G_MAXDOUBLE;
                     }
 
                   length = 2 * sqrt (x0 * x0 + y0 * y0);
@@ -3677,10 +3741,12 @@ get_layout_location (GtkLabel  *label,
   gint req_width, x, y;
   gint req_height;
   PangoRectangle logical;
+  gdouble angle;
 
-  misc = GTK_MISC (label);
+  misc   = GTK_MISC (label);
   widget = GTK_WIDGET (label);
-  priv = GTK_LABEL_GET_PRIVATE (label);
+  priv   = GTK_LABEL_GET_PRIVATE (label);
+  angle  = gtk_label_get_angle (label);
 
   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
     xalign = misc->xalign;
@@ -3689,37 +3755,33 @@ get_layout_location (GtkLabel  *label,
 
   pango_layout_get_extents (label->layout, NULL, &logical);
 
-  if (label->have_transform)
-    {
-      PangoContext *context = gtk_widget_get_pango_context (widget);
-      const PangoMatrix *matrix = pango_context_get_matrix (context);
-      pango_matrix_transform_rectangle (matrix, &logical);
-    }
-
-  pango_extents_to_pixels (&logical, NULL);
-
+  /* Do the wrap width delimiting before the transform
+   */
   if (label->wrap || label->ellipsize || priv->width_chars > 0)
     {
       int width;
 
       width = pango_layout_get_width (label->layout);
 
-      req_width = logical.width;
-      req_height = logical.height;
-
       if (width != -1)
-       req_width = MIN(PANGO_PIXELS (width), req_width);
-      req_width += 2 * misc->xpad;
-      req_height += 2 * misc->ypad;
+       logical.width = MIN (width, logical.width);
     }
-  else
+
+  if (label->have_transform)
     {
-      req_width = logical.width;
-      req_height = logical.height;
-/*       req_width = widget->requisition.width; */
-/*       req_height = widget->requisition.height; */
+      PangoContext *context = gtk_widget_get_pango_context (widget);
+      const PangoMatrix *matrix = pango_context_get_matrix (context);
+      pango_matrix_transform_rectangle (matrix, &logical);
     }
 
+  pango_extents_to_pixels (&logical, NULL);
+
+  req_width  = logical.width;
+  req_height = logical.height;
+
+  req_width  += 2 * misc->xpad;
+  req_height += 2 * misc->ypad;
+
   x = floor (widget->allocation.x + (gint)misc->xpad +
              xalign * (widget->allocation.width - req_width));
 
@@ -3728,6 +3790,9 @@ get_layout_location (GtkLabel  *label,
   else
     x = MIN (x, widget->allocation.x + widget->allocation.width - misc->xpad);
 
+
+
+
   /* bgo#315462 - For single-line labels, *do* align the requisition with
    * respect to the allocation, even if we are under-allocated.  For multi-line
    * labels, always show the top of the text when they are under-allocated.  The
@@ -4147,36 +4212,6 @@ gtk_label_set_uline_text_internal (GtkLabel    *label,
   g_free (pattern);
 }
 
-guint
-gtk_label_parse_uline (GtkLabel    *label,
-                      const gchar *str)
-{
-  guint keyval;
-  
-  g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
-  g_return_val_if_fail (str != NULL, GDK_VoidSymbol);
-
-  g_object_freeze_notify (G_OBJECT (label));
-  
-  gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
-  gtk_label_set_use_markup_internal (label, FALSE);
-  gtk_label_set_use_underline_internal (label, TRUE);
-  
-  gtk_label_recalculate (label);
-
-  keyval = label->mnemonic_keyval;
-  if (keyval != GDK_VoidSymbol)
-    {
-      label->mnemonic_keyval = GDK_VoidSymbol;
-      gtk_label_setup_mnemonic (label, keyval);
-      g_object_notify (G_OBJECT (label), "mnemonic-keyval");
-    }
-  
-  g_object_thaw_notify (G_OBJECT (label));
-
-  return keyval;
-}
-
 /**
  * gtk_label_set_text_with_mnemonic:
  * @label: a #GtkLabel
@@ -4747,7 +4782,6 @@ gtk_label_motion (GtkWidget      *widget,
   GtkLabel *label = GTK_LABEL (widget);
   GtkLabelSelectionInfo *info = label->select_info;
   gint index;
-  gint x, y;
 
   if (info == NULL)
     return FALSE;
@@ -4760,8 +4794,7 @@ gtk_label_motion (GtkWidget      *widget,
 
       if (info->selection_anchor == info->selection_end)
         {
-          gdk_window_get_pointer (event->window, &x, &y, NULL);
-          if (get_layout_index (label, x, y, &index))
+          if (get_layout_index (label, event->x, event->y, &index))
             {
               for (l = info->links; l != NULL; l = l->next)
                 {
@@ -4803,8 +4836,6 @@ gtk_label_motion (GtkWidget      *widget,
   if ((event->state & GDK_BUTTON1_MASK) == 0)
     return FALSE;
 
-  gdk_window_get_pointer (info->window, &x, &y, NULL);
   if (info->in_drag)
     {
       if (gtk_drag_check_threshold (widget,
@@ -4829,6 +4860,9 @@ gtk_label_motion (GtkWidget      *widget,
     }
   else
     {
+      gint x, y;
+
+      gdk_window_get_device_position (info->window, event->device, &x, &y, NULL);
       get_layout_index (label, x, y, &index);
 
       if (info->select_words)