[mutter] Allow a theme to specify ellipsize width for a title



commit 1d7476a7257e9c41e5649160859ba98247af92d9
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Thu Aug 20 15:54:11 2009 -0400

    Allow a theme to specify ellipsize width for a title
    
    It's nice to indicate when a title is truncated with an ellipsis.
    Because themes may draw a title multiple times to draw a shadow, or
    may include the window icon within the title area, we can't determine
    the proper ellipsization width automatically, so add an optional
    attribute to the <title/> element "ellipsize_width" which, if set,
    is the width to ellipsize at.
    
    This is only enabled if a theme version of 3.1 is required.
    
    When it's not set, we keep the old behavior of just letting the
    title be clipped with a hard edge.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=591842

 doc/theme-format.txt  |    4 ++++
 src/ui/frames.c       |    1 +
 src/ui/theme-parser.c |   14 ++++++++++++++
 src/ui/theme.c        |   48 ++++++++++++++++++++++++++++++++++++++++++++----
 src/ui/theme.h        |    1 +
 5 files changed, 64 insertions(+), 4 deletions(-)
---
diff --git a/doc/theme-format.txt b/doc/theme-format.txt
index cefc316..b23e6ac 100644
--- a/doc/theme-format.txt
+++ b/doc/theme-format.txt
@@ -32,6 +32,10 @@ Additional predefined variables are added for positioning expressions:
  frame_y_center: the Y center of the entire frame, with respect to the
      piece currently being drawn.
 
+The <title/> element now supports an "ellipsize_width" attribute. When
+specified, this gives a width at which to ellipsize the title. If not
+specified, the title will simply be clipped to the title area.
+
 New Features in Theme Format Version 3
 ======================================
 
diff --git a/src/ui/frames.c b/src/ui/frames.c
index 01e5027..6316882 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -501,6 +501,7 @@ meta_frames_ensure_layout (MetaFrames  *frames,
       
       frame->layout = gtk_widget_create_pango_layout (widget, frame->title);
 
+      pango_layout_set_ellipsize (frame->layout, PANGO_ELLIPSIZE_END);
       pango_layout_set_auto_dir (frame->layout, FALSE);
       
       font_desc = meta_gtk_widget_get_font_desc (widget, scale,
diff --git a/src/ui/theme-parser.c b/src/ui/theme-parser.c
index b2d8bf7..2d18eff 100644
--- a/src/ui/theme-parser.c
+++ b/src/ui/theme-parser.c
@@ -2584,12 +2584,14 @@ parse_draw_op_element (GMarkupParseContext  *context,
       const char *color;
       const char *x;
       const char *y;
+      const char *ellipsize_width;
       MetaColorSpec *color_spec;
       
       if (!locate_attributes (context, element_name, attribute_names, attribute_values,
                               error,
                               "!color", &color,
                               "!x", &x, "!y", &y,
+                              "ellipsize_width", &ellipsize_width,
                               NULL))
         return;
 
@@ -2599,8 +2601,18 @@ parse_draw_op_element (GMarkupParseContext  *context,
 
       if (!check_expression (y, FALSE, info->theme, context, error))
         return;
+
+      if (!check_expression (ellipsize_width, FALSE, info->theme, context, error))
+        return;
 #endif
 
+      if (ellipsize_width && peek_required_version (info) < 3001)
+        {
+          set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                     ATTRIBUTE_NOT_FOUND, "ellipsize_width", element_name);
+          return;
+        }
+
       /* Check last so we don't have to free it when other
        * stuff fails
        */
@@ -2617,6 +2629,8 @@ parse_draw_op_element (GMarkupParseContext  *context,
 
       op->data.title.x = meta_draw_spec_new (info->theme, x, NULL);
       op->data.title.y = meta_draw_spec_new (info->theme, y, NULL);
+      if (ellipsize_width)
+        op->data.title.ellipsize_width = meta_draw_spec_new (info->theme, ellipsize_width, NULL);
 
       g_assert (info->op_list);
       
diff --git a/src/ui/theme.c b/src/ui/theme.c
index 3674233..cc8ec1b 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -2884,6 +2884,8 @@ meta_draw_op_free (MetaDrawOp *op)
 
       meta_draw_spec_free (op->data.title.x);
       meta_draw_spec_free (op->data.title.y);
+      if (op->data.title.ellipsize_width)
+        meta_draw_spec_free (op->data.title.ellipsize_width);
       break;
 
     case META_DRAW_OP_LIST:
@@ -3756,6 +3758,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
       if (info->title_layout)
         {
           int rx, ry;
+          PangoRectangle ink_rect, logical_rect;
 
           gc = get_gc_for_primitive (widget, drawable,
                                      op->data.title.color_spec,
@@ -3764,10 +3767,47 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
           rx = parse_x_position_unchecked (op->data.title.x, env);
           ry = parse_y_position_unchecked (op->data.title.y, env);
 
+          if (op->data.title.ellipsize_width)
+            {
+              int ellipsize_width;
+              int right_bearing;
+
+              ellipsize_width = parse_x_position_unchecked (op->data.title.ellipsize_width, env);
+              /* HACK: parse_x_position_unchecked adds in env->rect.x, subtract out again */
+              ellipsize_width -= env->rect.x;
+
+              pango_layout_set_width (info->title_layout, -1);
+              pango_layout_get_pixel_extents (info->title_layout,
+                                              &ink_rect, &logical_rect);
+
+              /* Pango's idea of ellipsization is with respect to the logical rect.
+               * correct for this, by reducing the ellipsization width by the overflow
+               * of the un-ellipsized text on the right... it's always the visual
+               * right we want regardless of bidi, since since the X we pass in to
+               * gdk_draw_layout() is always the left edge of the line.
+               */
+              right_bearing = (ink_rect.x + ink_rect.width) - (logical_rect.x + logical_rect.width);
+              right_bearing = MAX (right_bearing, 0);
+
+              ellipsize_width -= right_bearing;
+              ellipsize_width = MAX (ellipsize_width, 0);
+
+              /* Only ellipsizing when necessary is a performance optimization -
+               * pango_layout_set_width() will force a relayout if it isn't the
+               * same as the current width of -1.
+               */
+              if (ellipsize_width < logical_rect.width)
+                pango_layout_set_width (info->title_layout, PANGO_SCALE * ellipsize_width);
+            }
+
           gdk_draw_layout (drawable, gc,
                            rx, ry,
                            info->title_layout);
 
+          /* Remove any ellipsization we might have set; will short-circuit
+           * if the width is already -1 */
+          pango_layout_set_width (info->title_layout, -1);
+
           g_object_unref (G_OBJECT (gc));
         }
       break;
@@ -4326,7 +4366,7 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
   GdkRectangle bottom_titlebar_edge;
   GdkRectangle top_titlebar_edge;
   GdkRectangle left_edge, right_edge, bottom_edge;
-  PangoRectangle extents;
+  PangoRectangle logical_rect;
   MetaDrawInfo draw_info;
   
   g_return_if_fail (style_gtk->colormap == gdk_drawable_get_colormap (drawable));
@@ -4373,13 +4413,13 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
 
   if (title_layout)
     pango_layout_get_pixel_extents (title_layout,
-                                    NULL, &extents);
+                                    NULL, &logical_rect);
 
   draw_info.mini_icon = mini_icon;
   draw_info.icon = icon;
   draw_info.title_layout = title_layout;
-  draw_info.title_layout_width = title_layout ? extents.width : 0;
-  draw_info.title_layout_height = title_layout ? extents.height : 0;
+  draw_info.title_layout_width = title_layout ? logical_rect.width : 0;
+  draw_info.title_layout_height = title_layout ? logical_rect.height : 0;
   draw_info.fgeom = fgeom;
   
   /* The enum is in the order the pieces should be rendered. */
diff --git a/src/ui/theme.h b/src/ui/theme.h
index 02a6156..e9369b1 100644
--- a/src/ui/theme.h
+++ b/src/ui/theme.h
@@ -534,6 +534,7 @@ struct _MetaDrawOp
       MetaColorSpec *color_spec;
       MetaDrawSpec *x;
       MetaDrawSpec *y;
+      MetaDrawSpec *ellipsize_width;
     } title;
 
     struct {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]