Skip to content

Commit a47f178

Browse files
owtaylorvkareh
authored andcommitted
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 NOTE: Patch copied from mutter and adapted for metacity.
1 parent 728f002 commit a47f178

File tree

5 files changed

+60
-3
lines changed

5 files changed

+60
-3
lines changed

doc/theme-format.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ Additional predefined variables are added for positioning expressions:
3232
frame_y_center: the Y center of the entire frame, with respect to the
3333
piece currently being drawn.
3434

35+
The <title/> element now supports an "ellipsize_width" attribute. When
36+
specified, this gives a width at which to ellipsize the title. If not
37+
specified, the title will simply be clipped to the title area.
38+
3539
New Features in Theme Format Version 3
3640
======================================
3741

src/ui/frames.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ meta_frames_ensure_layout (MetaFrames *frames,
482482

483483
frame->layout = gtk_widget_create_pango_layout (widget, frame->title);
484484

485+
pango_layout_set_ellipsize (frame->layout, PANGO_ELLIPSIZE_END);
485486
pango_layout_set_auto_dir (frame->layout, FALSE);
486487

487488
pango_layout_set_single_paragraph_mode (frame->layout, TRUE);

src/ui/theme-parser.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2615,12 +2615,14 @@ parse_draw_op_element (GMarkupParseContext *context,
26152615
const char *color;
26162616
const char *x;
26172617
const char *y;
2618+
const char *ellipsize_width;
26182619
MetaColorSpec *color_spec;
26192620

26202621
if (!locate_attributes (context, element_name, attribute_names, attribute_values,
26212622
error,
26222623
"!color", &color,
26232624
"!x", &x, "!y", &y,
2625+
"ellipsize_width", &ellipsize_width,
26242626
NULL))
26252627
return;
26262628

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

26312633
if (!check_expression (y, FALSE, info->theme, context, error))
26322634
return;
2635+
2636+
if (!check_expression (ellipsize_width, FALSE, info->theme, context, error))
2637+
return;
26332638
#endif
26342639

2640+
if (ellipsize_width && peek_required_version (info) < 3001)
2641+
{
2642+
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
2643+
ATTRIBUTE_NOT_FOUND, "ellipsize_width", element_name);
2644+
return;
2645+
}
2646+
26352647
/* Check last so we don't have to free it when other
26362648
* stuff fails
26372649
*/
@@ -2648,6 +2660,8 @@ parse_draw_op_element (GMarkupParseContext *context,
26482660

26492661
op->data.title.x = meta_draw_spec_new (info->theme, x, NULL);
26502662
op->data.title.y = meta_draw_spec_new (info->theme, y, NULL);
2663+
if (ellipsize_width)
2664+
op->data.title.ellipsize_width = meta_draw_spec_new (info->theme, ellipsize_width, NULL);
26512665

26522666
g_assert (info->op_list);
26532667

src/ui/theme.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,6 +3010,8 @@ meta_draw_op_free (MetaDrawOp *op)
30103010

30113011
meta_draw_spec_free (op->data.title.x);
30123012
meta_draw_spec_free (op->data.title.y);
3013+
if (op->data.title.ellipsize_width)
3014+
meta_draw_spec_free (op->data.title.ellipsize_width);
30133015
break;
30143016

30153017
case META_DRAW_OP_LIST:
@@ -3875,14 +3877,47 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
38753877
if (info->title_layout)
38763878
{
38773879
int rx, ry;
3880+
PangoRectangle ink_rect, logical_rect;
38783881

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

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

3885-
if (rx - env->rect.x + env->title_width >= env->rect.width)
3888+
if (op->data.title.ellipsize_width)
3889+
{
3890+
int ellipsize_width;
3891+
int right_bearing;
3892+
3893+
ellipsize_width = parse_x_position_unchecked (op->data.title.ellipsize_width, env);
3894+
/* HACK: parse_x_position_unchecked adds in env->rect.x, subtract out again */
3895+
ellipsize_width -= env->rect.x;
3896+
3897+
pango_layout_set_width (info->title_layout, -1);
3898+
pango_layout_get_pixel_extents (info->title_layout,
3899+
&ink_rect, &logical_rect);
3900+
3901+
/* Pango's idea of ellipsization is with respect to the logical rect.
3902+
* correct for this, by reducing the ellipsization width by the overflow
3903+
* of the un-ellipsized text on the right... it's always the visual
3904+
* right we want regardless of bidi, since since the X we pass in to
3905+
* cairo_move_to() is always the left edge of the line.
3906+
*/
3907+
right_bearing = (ink_rect.x + ink_rect.width) - (logical_rect.x + logical_rect.width);
3908+
right_bearing = MAX (right_bearing, 0);
3909+
3910+
ellipsize_width -= right_bearing;
3911+
ellipsize_width = MAX (ellipsize_width, 0);
3912+
3913+
/* Only ellipsizing when necessary is a performance optimization -
3914+
* pango_layout_set_width() will force a relayout if it isn't the
3915+
* same as the current width of -1.
3916+
*/
3917+
if (ellipsize_width < logical_rect.width)
3918+
pango_layout_set_width (info->title_layout, PANGO_SCALE * ellipsize_width);
3919+
}
3920+
else if (rx - env->rect.x + env->title_width >= env->rect.width)
38863921
{
38873922
const double alpha_margin = 30.0;
38883923
int text_space = env->rect.x + env->rect.width -
@@ -3907,12 +3942,14 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
39073942
color.blue, 0);
39083943
cairo_set_source(cr, linpat);
39093944
cairo_pattern_destroy(linpat);
3910-
} else {
3911-
gdk_cairo_set_source_rgba (cr, &color);
39123945
}
39133946

39143947
cairo_move_to (cr, rx, ry);
39153948
pango_cairo_show_layout (cr, info->title_layout);
3949+
3950+
/* Remove any ellipsization we might have set; will short-circuit
3951+
* if the width is already -1 */
3952+
pango_layout_set_width (info->title_layout, -1);
39163953
}
39173954
break;
39183955

src/ui/theme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ struct _MetaDrawOp
539539
MetaColorSpec *color_spec;
540540
MetaDrawSpec *x;
541541
MetaDrawSpec *y;
542+
MetaDrawSpec *ellipsize_width;
542543
} title;
543544

544545
struct {

0 commit comments

Comments
 (0)