[metacity] Allow a theme to specify ellipsize width for a title
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [metacity] Allow a theme to specify ellipsize width for a title
- Date: Sun, 28 Sep 2014 16:02:15 +0000 (UTC)
commit d5f905db37560669ad62032fa4c21fd0412ffbf6
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Sat Sep 27 16:47:27 2014 +0300
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.
doc/theme-format.txt | 4 ++++
src/ui/frames.c | 1 +
src/ui/theme-parser.c | 14 ++++++++++++++
src/ui/theme.c | 43 ++++++++++++++++++++++++++++++++++++++++---
src/ui/theme.h | 1 +
5 files changed, 60 insertions(+), 3 deletions(-)
---
diff --git a/doc/theme-format.txt b/doc/theme-format.txt
index bacc6e4..54138e6 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 f0dbb90..37b9618 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -483,6 +483,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 9098e7c..10c6944 100644
--- a/src/ui/theme-parser.c
+++ b/src/ui/theme-parser.c
@@ -2609,12 +2609,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;
@@ -2624,8 +2626,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
*/
@@ -2642,6 +2654,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 8e8e22d..a96a612 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -3001,6 +3001,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:
@@ -3880,6 +3882,7 @@ 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);
@@ -3887,7 +3890,39 @@ 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 (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 -
@@ -3912,12 +3947,14 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
color.blue, 0);
cairo_set_source(cr, linpat);
cairo_pattern_destroy(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);
}
break;
diff --git a/src/ui/theme.h b/src/ui/theme.h
index 7c47657..28cc3a1 100644
--- a/src/ui/theme.h
+++ b/src/ui/theme.h
@@ -587,6 +587,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]