Skip to content


Browse files Browse the repository at this point in the history
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.

NOTE: Patch copied from mutter and adapted for metacity.
  • Loading branch information
owtaylor authored and vkareh committed Aug 28, 2018
1 parent 728f002 commit a47f178
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 3 deletions.
4 changes: 4 additions & 0 deletions doc/theme-format.txt
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions src/ui/frames.c
Expand Up @@ -482,6 +482,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);

pango_layout_set_single_paragraph_mode (frame->layout, TRUE);
Expand Down
14 changes: 14 additions & 0 deletions src/ui/theme-parser.c
Expand Up @@ -2615,12 +2615,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,
"!color", &color,
"!x", &x, "!y", &y,
"ellipsize_width", &ellipsize_width,

Expand All @@ -2630,8 +2632,18 @@ parse_draw_op_element (GMarkupParseContext *context,

if (!check_expression (y, FALSE, info->theme, context, error))

if (!check_expression (ellipsize_width, FALSE, info->theme, context, error))

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);

/* Check last so we don't have to free it when other
* stuff fails
Expand All @@ -2648,6 +2660,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);

Expand Down
43 changes: 40 additions & 3 deletions src/ui/theme.c
Expand Up @@ -3010,6 +3010,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);

Expand Down Expand Up @@ -3875,14 +3877,47 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
if (info->title_layout)
int rx, ry;
PangoRectangle ink_rect, logical_rect;

meta_color_spec_render (op->data.title.color_spec, style_gtk, &color);
gdk_cairo_set_source_rgba (cr, &color);

rx = parse_x_position_unchecked (op->data.title.x, env);
ry = parse_y_position_unchecked (op->data.title.y, env);

if (rx - env->rect.x + env->title_width >= env->rect.width)
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
* cairo_move_to() 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);
else if (rx - env->rect.x + env->title_width >= env->rect.width)
const double alpha_margin = 30.0;
int text_space = env->rect.x + env->rect.width -
Expand All @@ -3907,12 +3942,14 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,, 0);
cairo_set_source(cr, linpat);
} else {
gdk_cairo_set_source_rgba (cr, &color);

cairo_move_to (cr, rx, ry);
pango_cairo_show_layout (cr, 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);

Expand Down
1 change: 1 addition & 0 deletions src/ui/theme.h
Expand Up @@ -539,6 +539,7 @@ struct _MetaDrawOp
MetaColorSpec *color_spec;
MetaDrawSpec *x;
MetaDrawSpec *y;
MetaDrawSpec *ellipsize_width;
} title;

struct {
Expand Down

0 comments on commit a47f178

Please sign in to comment.