summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog26
-rw-r--r--src/frames.c137
-rw-r--r--src/frames.h4
-rw-r--r--src/stack.c2
-rw-r--r--src/theme-parser.c182
-rw-r--r--src/theme-viewer.c3
-rw-r--r--src/theme.c49
-rw-r--r--src/theme.h13
-rw-r--r--src/themes/Atlanta/metacity-theme-1.xml28
-rw-r--r--theme-format.txt9
10 files changed, 341 insertions, 112 deletions
diff --git a/ChangeLog b/ChangeLog
index 449bc1f..07f00f2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,31 @@
2002-02-09 Havoc Pennington <hp@pobox.com>
+ * src/theme-parser.c: try to make more error message strings the
+ same, easier for translators
+
+ * src/theme.c (meta_draw_op_free): free color spec for line op
+ (meta_theme_free): free the integer_constants hash
+
+ * src/theme-parser.c (parse_boolean): move above first use
+
+ * src/theme-viewer.c: fixes for theme.h changes
+
+ * src/frames.c (queue_recalc_func): don't recreate layout
+ immediately, just save title text. should speed things up.
+ (meta_frames_set_title): just remove the layout here also,
+ and save title text.
+
+ * src/theme-parser.c (parse_toplevel_element): parse title_scale
+ attribute on frame_geometry
+
+ * src/theme.c: support setting the text size
+
+ * src/frames.c: support setting the text size
+
+ * theme-format.txt: updates
+
+2002-02-09 Havoc Pennington <hp@pobox.com>
+
* src/themes/Atlanta/metacity-theme-1.xml: put in some kind of
distinctive frame for UTILITY, though it's ugly. Also put in the
borderless look for maximized windows.
diff --git a/src/frames.c b/src/frames.c
index bd56408..5e0e5a4 100644
--- a/src/frames.c
+++ b/src/frames.c
@@ -62,6 +62,9 @@ static void meta_frames_calc_geometry (MetaFrames *frames,
MetaUIFrame *frame,
MetaFrameGeometry *fgeom);
+static void meta_frames_ensure_layout (MetaFrames *frames,
+ MetaUIFrame *frame);
+
static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames,
Window xwindow);
@@ -156,6 +159,8 @@ meta_frames_init (MetaFrames *frames)
{
GTK_WINDOW (frames)->type = GTK_WINDOW_POPUP;
+ frames->text_heights = g_hash_table_new (g_int_hash, g_int_equal);
+
frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
frames->tooltip_timeout = 0;
@@ -212,6 +217,8 @@ meta_frames_finalize (GObject *object)
frames = META_FRAMES (object);
+ g_hash_table_destroy (frames->text_heights);
+
g_assert (g_hash_table_size (frames->frames) == 0);
g_hash_table_destroy (frames->frames);
@@ -238,17 +245,13 @@ queue_recalc_func (gpointer key, gpointer value, gpointer data)
frame->xwindow);
if (frame->layout)
{
- /* recreate layout */
- char *text;
+ /* save title to recreate layout */
+ g_free (frame->title);
- text = g_strdup (pango_layout_get_text (frame->layout));
+ frame->title = g_strdup (pango_layout_get_text (frame->layout));
g_object_unref (G_OBJECT (frame->layout));
-
- frame->layout = gtk_widget_create_pango_layout (GTK_WIDGET (frames),
- text);
-
- g_free (text);
+ frame->layout = NULL;
}
}
@@ -260,13 +263,10 @@ meta_frames_style_set (GtkWidget *widget,
frames = META_FRAMES (widget);
- if (GTK_WIDGET_REALIZED (widget))
- {
- frames->text_height = meta_gtk_widget_get_text_height (widget);
- }
- else
+ if (g_hash_table_size (frames->text_heights) > 0)
{
- frames->text_height = 0;
+ g_hash_table_destroy (frames->text_heights);
+ frames->text_heights = g_hash_table_new (g_int_hash, g_int_equal);
}
/* Queue a draw/resize on all frames */
@@ -277,6 +277,81 @@ meta_frames_style_set (GtkWidget *widget,
}
static void
+meta_frames_ensure_layout (MetaFrames *frames,
+ MetaUIFrame *frame)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (GTK_WIDGET_REALIZED (frames));
+
+ widget = GTK_WIDGET (frames);
+
+ if (frame->layout == NULL)
+ {
+ gpointer key, value;
+ PangoFontDescription *font_desc;
+ MetaFrameFlags flags;
+ MetaFrameType type;
+ double scale;
+ int size;
+
+ flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
+ type = meta_core_get_frame_type (gdk_display, frame->xwindow);
+
+ scale = meta_theme_get_title_scale (meta_theme_get_current (),
+ type,
+ flags);
+
+ frame->layout = gtk_widget_create_pango_layout (widget, frame->title);
+
+ font_desc = meta_gtk_widget_get_font_desc (widget, scale);
+
+ size = pango_font_description_get_size (font_desc);
+
+ if (g_hash_table_lookup_extended (frames->text_heights,
+ &size,
+ &key, &value))
+ {
+ frame->text_height = GPOINTER_TO_INT (value);
+ }
+ else
+ {
+ frame->text_height =
+ meta_pango_font_desc_get_text_height (font_desc,
+ gtk_widget_get_pango_context (widget));
+
+ g_hash_table_insert (frames->text_heights,
+ &size,
+ GINT_TO_POINTER (frame->text_height));
+ }
+
+ if (pango_font_description_get_size (font_desc) !=
+ pango_font_description_get_size (widget->style->font_desc))
+ {
+ PangoAttrList *attrs;
+ PangoAttribute *attr;
+
+ attrs = pango_attr_list_new ();
+
+ attr = pango_attr_size_new (pango_font_description_get_size (font_desc));
+ attr->start_index = 0;
+ attr->end_index = G_MAXINT;
+
+ pango_attr_list_insert (attrs, attr);
+
+ pango_layout_set_attributes (frame->layout, attrs);
+
+ pango_attr_list_unref (attrs);
+ }
+
+ pango_font_description_free (font_desc);
+
+ g_free (frame->title);
+ frame->title = NULL;
+ }
+}
+
+static void
meta_frames_calc_geometry (MetaFrames *frames,
MetaUIFrame *frame,
MetaFrameGeometry *fgeom)
@@ -290,10 +365,12 @@ meta_frames_calc_geometry (MetaFrames *frames,
flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
type = meta_core_get_frame_type (gdk_display, frame->xwindow);
+
+ meta_frames_ensure_layout (frames, frame);
meta_theme_calc_geometry (meta_theme_get_current (),
type,
- frames->text_height,
+ frame->text_height,
flags,
width, height,
fgeom);
@@ -328,6 +405,8 @@ meta_frames_manage_window (MetaFrames *frames,
frame->xwindow = xwindow;
frame->layout = NULL;
+ frame->text_height = -1;
+ frame->title = NULL;
frame->expose_delayed = FALSE;
meta_core_grab_buttons (gdk_display, frame->xwindow);
@@ -358,6 +437,9 @@ meta_frames_unmanage_window (MetaFrames *frames,
if (frame->layout)
g_object_unref (G_OBJECT (frame->layout));
+
+ if (frame->title)
+ g_free (frame->title);
g_free (frame);
}
@@ -374,8 +456,6 @@ meta_frames_realize (GtkWidget *widget)
if (GTK_WIDGET_CLASS (parent_class)->realize)
GTK_WIDGET_CLASS (parent_class)->realize (widget);
-
- frames->text_height = meta_gtk_widget_get_text_height (widget);
}
static void
@@ -387,8 +467,6 @@ meta_frames_unrealize (GtkWidget *widget)
if (GTK_WIDGET_CLASS (parent_class)->unrealize)
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
-
- frames->text_height = 0;
}
static MetaUIFrame*
@@ -421,6 +499,8 @@ meta_frames_get_geometry (MetaFrames *frames,
type = meta_core_get_frame_type (gdk_display, frame->xwindow);
g_return_if_fail (type < META_FRAME_TYPE_LAST);
+
+ meta_frames_ensure_layout (frames, frame);
/* We can't get the full geometry, because that depends on
* the client window size and probably we're being called
@@ -429,7 +509,7 @@ meta_frames_get_geometry (MetaFrames *frames,
*/
meta_theme_get_frame_borders (meta_theme_get_current (),
type,
- frames->text_height,
+ frame->text_height,
flags,
top_height, bottom_height,
left_width, right_width);
@@ -512,12 +592,15 @@ meta_frames_set_title (MetaFrames *frames,
widget = GTK_WIDGET (frames);
frame = meta_frames_lookup_window (frames, xwindow);
+
+ g_free (frame->title);
+ frame->title = g_strdup (title);
- if (frame->layout == NULL)
- frame->layout = gtk_widget_create_pango_layout (widget,
- title);
- else
- pango_layout_set_text (frame->layout, title, -1);
+ if (frame->layout)
+ {
+ g_object_unref (frame->layout);
+ frame->layout = NULL;
+ }
gdk_window_invalidate_rect (frame->window, NULL, FALSE);
}
@@ -1210,6 +1293,8 @@ meta_frames_paint_to_drawable (MetaFrames *frames,
meta_core_get_client_size (gdk_display, frame->xwindow,
&w, &h);
+
+ meta_frames_ensure_layout (frames, frame);
meta_theme_draw_frame (meta_theme_get_current (),
widget,
@@ -1220,7 +1305,7 @@ meta_frames_paint_to_drawable (MetaFrames *frames,
flags,
w, h,
frame->layout,
- frames->text_height,
+ frame->text_height,
button_states,
mini_icon, icon);
}
diff --git a/src/frames.h b/src/frames.h
index e756ec5..66f27c7 100644
--- a/src/frames.h
+++ b/src/frames.h
@@ -68,6 +68,8 @@ struct _MetaUIFrame
Window xwindow;
GdkWindow *window;
PangoLayout *layout;
+ int text_height;
+ char *title; /* NULL once we have a layout */
guint expose_delayed : 1;
};
@@ -75,7 +77,7 @@ struct _MetaFrames
{
GtkWindow parent_instance;
- int text_height;
+ GHashTable *text_heights;
GHashTable *frames;
diff --git a/src/stack.c b/src/stack.c
index 37834ae..813287e 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -715,7 +715,7 @@ meta_stack_sync_to_server (MetaStack *stack)
changes.stack_mode = Below;
meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
- *newp, last_window);
+ *newp, last_window);
XConfigureWindow (stack->screen->display->xdisplay,
*newp,
diff --git a/src/theme-parser.c b/src/theme-parser.c
index 331b565..d857be8 100644
--- a/src/theme-parser.c
+++ b/src/theme-parser.c
@@ -534,6 +534,28 @@ parse_double (const char *str,
}
static gboolean
+parse_boolean (const char *str,
+ gboolean *val,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ if (strcmp ("true", str) == 0)
+ *val = TRUE;
+ else if (strcmp ("false", str) == 0)
+ *val = FALSE;
+ else
+ {
+ set_error (error, context, G_MARKUP_ERROR,
+ G_MARKUP_ERROR_PARSE,
+ _("Boolean values must be \"true\" or \"false\" not \"%s\""),
+ str);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
parse_angle (const char *str,
double *val,
GMarkupParseContext *context,
@@ -573,6 +595,41 @@ parse_alpha (const char *str,
return TRUE;
}
+static gboolean
+parse_title_scale (const char *str,
+ double *val,
+ GMarkupParseContext *context,
+ GError **error)
+{
+ double factor;
+
+ if (strcmp (str, "xx-small") == 0)
+ factor = PANGO_SCALE_XX_SMALL;
+ else if (strcmp (str, "x-small") == 0)
+ factor = PANGO_SCALE_X_SMALL;
+ else if (strcmp (str, "small") == 0)
+ factor = PANGO_SCALE_SMALL;
+ else if (strcmp (str, "medium") == 0)
+ factor = PANGO_SCALE_MEDIUM;
+ else if (strcmp (str, "large") == 0)
+ factor = PANGO_SCALE_LARGE;
+ else if (strcmp (str, "x-large") == 0)
+ factor = PANGO_SCALE_X_LARGE;
+ else if (strcmp (str, "xx-large") == 0)
+ factor = PANGO_SCALE_XX_LARGE;
+ else
+ {
+ set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+ _("Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,large,x-large,xx-large)\n"),
+ str);
+ return FALSE;
+ }
+
+ *val = factor;
+
+ return TRUE;
+}
+
static void
parse_toplevel_element (GMarkupParseContext *context,
const gchar *element_name,
@@ -608,14 +665,16 @@ parse_toplevel_element (GMarkupParseContext *context,
if (name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"name\" attribute on element <%s>"), element_name);
+ _("No \"%s\" attribute on element <%s>"),
+ "name", element_name);
return;
}
-
+
if (value == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"value\" attribute on element <%s>"), element_name);
+ _("No \"%s\" attribute on element <%s>"),
+ "value", element_name);
return;
}
@@ -657,27 +716,33 @@ parse_toplevel_element (GMarkupParseContext *context,
const char *name = NULL;
const char *parent = NULL;
const char *has_title = NULL;
+ const char *title_scale = NULL;
gboolean has_title_val;
+ double title_scale_val;
MetaFrameLayout *parent_layout;
if (!locate_attributes (context, element_name, attribute_names, attribute_values,
error,
"name", &name, "parent", &parent,
- "has_title", &has_title,
+ "has_title", &has_title, "title_scale", &title_scale,
NULL))
return;
if (name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"name\" attribute on <%s> element"),
- element_name);
+ _("No \"%s\" attribute on <%s> element"),
+ "name", element_name);
return;
}
has_title_val = TRUE;
if (has_title && !parse_boolean (has_title, &has_title_val, context, error))
return;
+
+ title_scale_val = 1.0;
+ if (title_scale && !parse_title_scale (title_scale, &title_scale_val, context, error))
+ return;
if (meta_theme_lookup_layout (info->theme, name))
{
@@ -709,6 +774,9 @@ parse_toplevel_element (GMarkupParseContext *context,
if (has_title) /* only if explicit, otherwise inherit */
info->layout->has_title = has_title_val;
+
+ if (title_scale)
+ info->layout->title_scale = title_scale_val;
meta_theme_insert_layout (info->theme, name, info->layout);
@@ -727,8 +795,8 @@ parse_toplevel_element (GMarkupParseContext *context,
if (name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"name\" attribute on <%s> element"),
- element_name);
+ _("No \"%s\" attribute on <%s> element"),
+ "name", element_name);
return;
}
@@ -765,8 +833,8 @@ parse_toplevel_element (GMarkupParseContext *context,
if (name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"name\" attribute on <%s> element"),
- element_name);
+ _("No \"%s\" attribute on <%s> element"),
+ "name", element_name);
return;
}
@@ -842,8 +910,8 @@ parse_toplevel_element (GMarkupParseContext *context,
if (name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"name\" attribute on <%s> element"),
- element_name);
+ _("No \"%s\" attribute on <%s> element"),
+ "name", element_name);
return;
}
@@ -892,16 +960,16 @@ parse_toplevel_element (GMarkupParseContext *context,
if (type_name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"type\" attribute on <%s> element"),
- element_name);
+ _("No \"%s\" attribute on <%s> element"),
+ "type", element_name);
return;
}
if (style_set_name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"style_set\" attribute on <%s> element"),
- element_name);
+ _("No \"%s\" attribute on <%s> element"),
+ "style_set", element_name);
return;
}
@@ -956,16 +1024,16 @@ parse_toplevel_element (GMarkupParseContext *context,
if (function == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"function\" attribute on <%s> element"),
- element_name);
+ _("No \"%s\" attribute on <%s> element"),
+ "function", element_name);
return;
}
if (state == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No \"state\" attribute on <%s> element"),
- element_name);
+ _("No \"%s\" attribute on <%s> element"),
+ "state", element_name);
return;
}
@@ -1022,8 +1090,8 @@ parse_toplevel_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <metacity_theme>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "metacity_theme");
}
}
@@ -1086,8 +1154,8 @@ parse_info_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <info>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "info");
}
}
@@ -1284,8 +1352,8 @@ parse_geometry_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <frame_geometry>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "frame_geometry");
}
}
@@ -1354,28 +1422,6 @@ optimize_expression (MetaTheme *theme,
return meta_theme_replace_constants (theme, expr, NULL);
}
-static gboolean
-parse_boolean (const char *str,
- gboolean *val,
- GMarkupParseContext *context,
- GError **error)
-{
- if (strcmp ("true", str) == 0)
- *val = TRUE;
- else if (strcmp ("false", str) == 0)
- *val = FALSE;
- else
- {
- set_error (error, context, G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Boolean values must be \"true\" or \"false\" not \"%s\""),
- str);
- return FALSE;
- }
-
- return TRUE;
-}
-
static void
parse_draw_op_element (GMarkupParseContext *context,
const gchar *element_name,
@@ -2655,8 +2701,8 @@ parse_draw_op_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <draw_ops>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "draw_ops");
}
}
@@ -2709,8 +2755,8 @@ parse_gradient_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <gradient>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "gradient");
}
}
@@ -2869,8 +2915,8 @@ parse_style_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <frame_style>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "frame_style");
}
}
@@ -3046,8 +3092,8 @@ parse_style_set_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <frame_style_set>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "frame_style_set");
}
}
@@ -3084,8 +3130,8 @@ parse_piece_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <piece>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "piece");
}
}
@@ -3122,8 +3168,8 @@ parse_button_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <piece>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "button");
}
}
@@ -3160,8 +3206,8 @@ parse_menu_icon_element (GMarkupParseContext *context,
{
set_error (error, context,
G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <piece>"),
- element_name);
+ _("Element <%s> is not allowed below <%s>"),
+ element_name, "menu_icon");
}
}
@@ -3257,8 +3303,8 @@ start_element_handler (GMarkupParseContext *context,
break;
case STATE_COLOR:
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a <color> element"),
- element_name);
+ _("Element <%s> is not allowed inside a <%s> element"),
+ element_name, "color");
break;
case STATE_FRAME_STYLE:
parse_style_element (context, element_name,
@@ -3287,13 +3333,13 @@ start_element_handler (GMarkupParseContext *context,
break;
case STATE_FRAME:
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a <frame> element"),
- element_name);
+ _("Element <%s> is not allowed inside a <%s> element"),
+ element_name, "frame");
break;
case STATE_WINDOW:
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a <window> element"),
- element_name);
+ _("Element <%s> is not allowed inside a <%s> element"),
+ element_name, "window");
break;
}
}
diff --git a/src/theme-viewer.c b/src/theme-viewer.c
index 0f8a24a..ef3ffc5 100644
--- a/src/theme-viewer.c
+++ b/src/theme-viewer.c
@@ -55,7 +55,8 @@ get_flags (GtkWidget *widget)
static int
get_text_height (GtkWidget *widget)
{
- return meta_gtk_widget_get_text_height (widget);
+ return meta_pango_font_desc_get_text_height (widget->style->font_desc,
+ gtk_widget_get_pango_context (widget));
}
static PangoLayout*
diff --git a/src/theme.c b/src/theme.c
index 95bf0ab..10090be 100644
--- a/src/theme.c
+++ b/src/theme.c
@@ -2302,6 +2302,8 @@ meta_draw_op_free (MetaDrawOp *op)
switch (op->type)
{
case META_DRAW_LINE:
+ if (op->data.line.color_spec)
+ meta_color_spec_free (op->data.line.color_spec);
g_free (op->data.line.x1);
g_free (op->data.line.y1);
g_free (op->data.line.x2);
@@ -3973,6 +3975,7 @@ meta_theme_free (MetaTheme *theme)
g_free (theme->author);
g_free (theme->copyright);
+ g_hash_table_destroy (theme->integer_constants);
g_hash_table_destroy (theme->images_by_filename);
g_hash_table_destroy (theme->layouts_by_name);
g_hash_table_destroy (theme->draw_op_lists_by_name);
@@ -4208,6 +4211,24 @@ theme_get_style (MetaTheme *theme,
return style;
}
+double
+meta_theme_get_title_scale (MetaTheme *theme,
+ MetaFrameType type,
+ MetaFrameFlags flags)
+{
+ MetaFrameStyle *style;
+
+ g_return_val_if_fail (type < META_FRAME_TYPE_LAST, 1.0);
+
+ style = theme_get_style (theme, type, flags);
+
+ /* Parser is not supposed to allow this currently */
+ if (style == NULL)
+ return 1.0;
+
+ return style->layout->title_scale;
+}
+
void
meta_theme_draw_frame (MetaTheme *theme,
GtkWidget *widget,
@@ -4542,19 +4563,33 @@ meta_theme_lookup_float_constant (MetaTheme *theme,
}
}
+PangoFontDescription*
+meta_gtk_widget_get_font_desc (GtkWidget *widget,
+ double scale)
+{
+ PangoFontDescription *font_desc;
+
+ g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), 0);
+
+ font_desc = pango_font_description_copy (widget->style->font_desc);
+
+ pango_font_description_set_size (font_desc,
+ MAX (pango_font_description_get_size (font_desc) * scale, 1));
+
+ return font_desc;
+}
+
int
-meta_gtk_widget_get_text_height (GtkWidget *widget)
+meta_pango_font_desc_get_text_height (PangoFontDescription *font_desc,
+ PangoContext *context)
{
PangoFontMetrics *metrics;
PangoFont *font;
PangoLanguage *lang;
int retval;
-
- g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), 0);
- font = pango_context_load_font (gtk_widget_get_pango_context (widget),
- widget->style->font_desc);
- lang = pango_context_get_language (gtk_widget_get_pango_context (widget));
+ font = pango_context_load_font (context, font_desc);
+ lang = pango_context_get_language (context);
metrics = pango_font_get_metrics (font, lang);
g_object_unref (G_OBJECT (font));
@@ -4563,7 +4598,7 @@ meta_gtk_widget_get_text_height (GtkWidget *widget)
pango_font_metrics_get_descent (metrics));
pango_font_metrics_unref (metrics);
-
+
return retval;
}
diff --git a/src/theme.h b/src/theme.h
index 8f9936f..5ba1790 100644
--- a/src/theme.h
+++ b/src/theme.h
@@ -79,6 +79,9 @@ struct _MetaFrameLayout
/* Space around buttons */
GtkBorder button_border;
+ /* scale factor for title text */
+ double title_scale;
+
/* Whether title text will be displayed */
guint has_title : 1;
};
@@ -632,6 +635,10 @@ GdkPixbuf* meta_theme_load_image (MetaTheme *theme,
const char *filename,
GError **error);
+double meta_theme_get_title_scale (MetaTheme *theme,
+ MetaFrameType type,
+ MetaFrameFlags flags);
+
void meta_theme_draw_frame (MetaTheme *theme,
GtkWidget *widget,
GdkDrawable *drawable,
@@ -716,7 +723,11 @@ char* meta_theme_replace_constants (MetaTheme *theme,
/* random stuff */
-int meta_gtk_widget_get_text_height (GtkWidget *widget);
+PangoFontDescription* meta_gtk_widget_get_font_desc (GtkWidget *widget,
+ double scale);
+int meta_pango_font_desc_get_text_height (PangoFontDescription *font_desc,
+ PangoContext *context);
+
/* Enum converters */
MetaGtkColorComponent meta_color_component_from_string (const char *str);
diff --git a/src/themes/Atlanta/metacity-theme-1.xml b/src/themes/Atlanta/metacity-theme-1.xml
index 8913a6f..6cfa134 100644
--- a/src/themes/Atlanta/metacity-theme-1.xml
+++ b/src/themes/Atlanta/metacity-theme-1.xml
@@ -30,7 +30,7 @@
<distance name="right_titlebar_edge" value="4"/>
</frame_geometry>
-<frame_geometry name="utility" has_title="false">
+<frame_geometry name="utility" title_scale="xx-small">
<distance name="left_width" value="3"/>
<distance name="right_width" value="3"/>
<distance name="bottom_height" value="4"/>
@@ -38,7 +38,7 @@
<distance name="right_titlebar_edge" value="3"/>
<distance name="button_width" value="11"/>
<distance name="button_height" value="11"/>
- <distance name="title_vertical_pad" value="11"/>
+ <distance name="title_vertical_pad" value="1"/>
<border name="title_border" left="3" right="4" top="3" bottom="3"/>
<border name="button_border" left="0" right="0" top="1" bottom="1"/>
</frame_geometry>
@@ -178,7 +178,7 @@
y2="height - (height-SpacerHeight)/2"/>
</draw_ops>
-<draw_ops name="title_text_focused">
+<draw_ops name="title_text_focused_with_icon">
<clip x="0" y="0" width="width-SpacerWidth" height="height"/>
<title color="gtk:fg[SELECTED]"
x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing"
@@ -188,7 +188,14 @@
width="mini_icon_width" height="mini_icon_height"/>
</draw_ops>
-<draw_ops name="title_text">
+<draw_ops name="title_text_focused_no_icon">
+ <clip x="0" y="0" width="width-SpacerWidth" height="height"/>
+ <title color="gtk:fg[SELECTED]"
+ x="(0 `max` (width-title_width)) / 2"
+ y="((height - title_height) / 2) `max` 0"/>
+</draw_ops>
+
+<draw_ops name="title_text_with_icon">
<clip x="0" y="0" width="width-SpacerWidth" height="height"/>
<title color="gtk:fg[NORMAL]"
x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing"
@@ -198,24 +205,33 @@
width="mini_icon_width" height="mini_icon_height"/>
</draw_ops>
+<draw_ops name="title_text_no_icon">
+ <clip x="0" y="0" width="width-SpacerWidth" height="height"/>
+ <title color="gtk:fg[NORMAL]"
+ x="(0 `max` (width-title_width)) / 2"
+ y="((height - title_height) / 2) `max` 0"/>
+</draw_ops>
+
<draw_ops name="title_normal">
<include name="title_spacer"/>
- <include name="title_text"/>
+ <include name="title_text_with_icon"/>
</draw_ops>
<draw_ops name="title_focused">
<include name="title_gradient"/>
<include name="title_spacer"/>
- <include name="title_text_focused"/>
+ <include name="title_text_focused_with_icon"/>
</draw_ops>
<draw_ops name="title_utility">
<include name="title_spacer"/>
+ <include name="title_text_no_icon"/>
</draw_ops>
<draw_ops name="title_utility_focused">
<include name="title_gradient"/>
<include name="title_spacer"/>
+ <include name="title_text_focused_no_icon"/>
</draw_ops>
<frame_style name="normal_unfocused" geometry="normal">
diff --git a/theme-format.txt b/theme-format.txt
index 744f74a..c540334 100644
--- a/theme-format.txt
+++ b/theme-format.txt
@@ -14,7 +14,12 @@ Themes are in a simple XML-subset format.
</info>
<!-- define a frame geometry to be referenced later -->
-<frame_geometry name="normal">
+<!-- frame_geometry has an optional has_title attribute which
+ determines whether the title text height is included in the
+ height calculation. if not specified, defaults to true.
+ It also has an optional text_size="medium" attribute
+ (same sizes as with Pango markup, xx-small thru medium thru xx-large) -->
+<frame_geometry name="normal" has_title="true" title_size="medium">
<distance name="left_width" value="6"/>
<distance name="right_width" value="6"/>
<distance name="bottom_height" value="7"/>
@@ -94,6 +99,8 @@ Themes are in a simple XML-subset format.
<!-- color obtained by a 0.5 alpha composite of the second color onto the first -->
<color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/>
</gradient>
+ <!-- image has an optional colorize="#color" attribute to give the
+ image a certain color -->
<image filename="foo.png" alpha="0.7"
x="10" y="30" width="width / 3" height="height / 4"/>
<gtk_arrow state="normal" shadow="in" arrow="up"