add code to save ACLOCAL_FLAGS

2002-01-08  Havoc Pennington  <hp@pobox.com>

	* configure.in (ACLOCAL): add code to save ACLOCAL_FLAGS

	* src/frames.c (meta_frames_expose_event): max dither

	* src/testgradient.c (render_simple): change dither mode to MAX
	to avoid banding

	* src/theme.c: lose the gradient cache, and put in some initial
	data types for the theme format
This commit is contained in:
Havoc Pennington 2002-01-08 07:23:35 +00:00 committed by Havoc Pennington
parent 9ed27d3dcb
commit 402c0b5036
9 changed files with 605 additions and 374 deletions

View File

@ -1,9 +1,27 @@
2002-01-08 Havoc Pennington <hp@pobox.com>
* configure.in (ACLOCAL): add code to save ACLOCAL_FLAGS
* src/frames.c (meta_frames_expose_event): max dither
* src/testgradient.c (render_simple): change dither mode to MAX
to avoid banding
* src/theme.c: lose the gradient cache, and put in some initial
data types for the theme format
2002-01-07 Havoc Pennington <hp@redhat.com> 2002-01-07 Havoc Pennington <hp@redhat.com>
* src/frames.c (meta_frames_expose_event): make gradient a bit * src/frames.c (meta_frames_expose_event): make gradient a bit
more subtle (don't go to the full background, but to a blend of more subtle (don't go to the full background, but to a blend of
selection and background; put lighter color on top) selection and background; put lighter color on top)
2002-01-06 Havoc Pennington <hp@pobox.com>
* src/window.c (meta_window_notify_focus): rearrange code a bit to
make it clear that has_focus flag always follows
display->focus_window
2002-01-06 Havoc Pennington <hp@pobox.com> 2002-01-06 Havoc Pennington <hp@pobox.com>
* src/window.c (meta_window_notify_focus): put in attempted fix * src/window.c (meta_window_notify_focus): put in attempted fix

View File

@ -4,6 +4,9 @@ AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(metacity, 2.3.34) AM_INIT_AUTOMAKE(metacity, 2.3.34)
# Honor aclocal flags
ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS"
GETTEXT_PACKAGE=metacity GETTEXT_PACKAGE=metacity
AC_SUBST(GETTEXT_PACKAGE) AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE") AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE")

View File

@ -1771,11 +1771,11 @@ meta_frames_expose_event (GtkWidget *widget,
layout_gc = widget->style->fg_gc[GTK_STATE_SELECTED]; layout_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
gradient = meta_theme_get_gradient (META_GRADIENT_DIAGONAL, gradient = meta_gradient_create_simple (fgeom.title_rect.width,
fgeom.title_rect.height,
&selected_faded, &selected_faded,
&widget->style->bg[GTK_STATE_SELECTED], &widget->style->bg[GTK_STATE_SELECTED],
fgeom.title_rect.width, META_GRADIENT_DIAGONAL);
fgeom.title_rect.height);
if (gradient != NULL) if (gradient != NULL)
{ {
@ -1787,7 +1787,7 @@ meta_frames_expose_event (GtkWidget *widget,
fgeom.title_rect.y, fgeom.title_rect.y,
fgeom.title_rect.width, fgeom.title_rect.width,
fgeom.title_rect.height, fgeom.title_rect.height,
GDK_RGB_DITHER_NORMAL, GDK_RGB_DITHER_MAX,
0, 0); 0, 0);
g_object_unref (G_OBJECT (gradient)); g_object_unref (G_OBJECT (gradient));

View File

@ -20,6 +20,7 @@
* 02111-1307, USA. */ * 02111-1307, USA. */
#include "gradient.h" #include "gradient.h"
#include "util.h"
#include <string.h> #include <string.h>
/* This is all Alfredo's and Dan's usual very nice WindowMaker code, /* This is all Alfredo's and Dan's usual very nice WindowMaker code,
@ -277,10 +278,7 @@ meta_gradient_create_horizontal (int width, int height,
int rf, gf, bf; int rf, gf, bf;
int rowstride; int rowstride;
/* FIXME the no_padding = TRUE here is a workaround for a problem pixbuf = blank_pixbuf (width, height, FALSE);
* create_diagonal that can't handle a funky rowstride
*/
pixbuf = blank_pixbuf (width, height, TRUE);
if (pixbuf == NULL) if (pixbuf == NULL)
return NULL; return NULL;
@ -448,9 +446,6 @@ meta_gradient_create_diagonal (int width, int height,
pixels = gdk_pixbuf_get_pixels (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf);
rowstride = gdk_pixbuf_get_rowstride (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf);
/* FIXME here is the pixbuf that we require to have width == rowstride
* resulting in no_padding = TRUE in create_horizontal
*/
tmp = meta_gradient_create_horizontal (2*width-1, 1, from, to); tmp = meta_gradient_create_horizontal (2*width-1, 1, from, to);
if (!tmp) if (!tmp)
{ {
@ -473,9 +468,6 @@ meta_gradient_create_diagonal (int width, int height,
/* copy the first line to the other lines with corresponding offset */ /* copy the first line to the other lines with corresponding offset */
for (j=0, offset=0.0; j<rowstride*height; j += rowstride) for (j=0, offset=0.0; j<rowstride*height; j += rowstride)
{ {
/* FIXME this algorithm assumes rowstride == width in the source
* pixbuf, because otherwise we'd accidentally copy junk pixels.
*/
memcpy (&(pixels[j]), &ptr[3*(int)offset], width); memcpy (&(pixels[j]), &ptr[3*(int)offset], width);
offset += a; offset += a;
} }
@ -702,9 +694,6 @@ meta_gradient_create_multi_diagonal (int width, int height,
if (count > height) if (count > height)
count = height; count = height;
/* FIXME here again is a bug that requires multi_horizontal
* to have width == rowstride
*/
if (count > 2) if (count > 2)
tmp = meta_gradient_create_multi_horizontal (2*width-1, 1, colors, count); tmp = meta_gradient_create_multi_horizontal (2*width-1, 1, colors, count);
else else
@ -736,39 +725,3 @@ meta_gradient_create_multi_diagonal (int width, int height,
return pixbuf; return pixbuf;
} }
MetaGradientDescription*
meta_gradient_description_new (MetaGradientType type,
const GdkColor *colors,
int n_colors)
{
MetaGradientDescription *desc;
desc = g_new (MetaGradientDescription, 1);
desc->type = type;
desc->colors = g_new (GdkColor, n_colors);
desc->n_colors = n_colors;
memcpy (desc->colors, colors, sizeof (GdkColor) * n_colors);
return desc;
}
void
meta_gradient_description_free (MetaGradientDescription *desc)
{
g_return_if_fail (desc != NULL);
g_free (desc->colors);
g_free (desc);
}
GdkPixbuf*
meta_gradient_description_render (const MetaGradientDescription *desc,
int width,
int height)
{
return meta_gradient_create_multi (width, height,
desc->colors, desc->n_colors,
desc->type);
}

View File

@ -32,27 +32,6 @@ typedef enum
META_GRADIENT_DIAGONAL META_GRADIENT_DIAGONAL
} MetaGradientType; } MetaGradientType;
typedef struct _MetaGradientDescription MetaGradientDescription;
/* this doesn't support interwoven at the moment, since
* I don't know what interwoven is good for
*/
struct _MetaGradientDescription
{
MetaGradientType type;
GdkColor *colors;
int n_colors;
};
MetaGradientDescription* meta_gradient_description_new (MetaGradientType type,
const GdkColor *colors,
int n_colors);
void meta_gradient_description_free (MetaGradientDescription *desc);
GdkPixbuf* meta_gradient_description_render (const MetaGradientDescription *desc,
int width,
int height);
GdkPixbuf* meta_gradient_create_simple (int width, GdkPixbuf* meta_gradient_create_simple (int width,
int height, int height,
const GdkColor *from, const GdkColor *from,
@ -70,4 +49,5 @@ GdkPixbuf* meta_gradient_create_interwoven (int width,
const GdkColor colors2[2], const GdkColor colors2[2],
int thickness2); int thickness2);
#endif #endif

View File

@ -47,7 +47,7 @@ render_simple (GdkDrawable *drawable,
gc, gc,
0, 0, 0, 0,
0, 0, width, height, 0, 0, width, height,
GDK_RGB_DITHER_NORMAL, GDK_RGB_DITHER_MAX,
0, 0); 0, 0);
g_object_unref (G_OBJECT (pixbuf)); g_object_unref (G_OBJECT (pixbuf));

View File

@ -24,307 +24,403 @@
#include "gradient.h" #include "gradient.h"
#include <string.h> #include <string.h>
#if 0
/* fill_gradient routine from GNOME background-properties, CVS says MetaGradientSpec*
* Michael Fulbright checked it in, Copyright 1998 Red Hat Inc. meta_gradient_spec_new (MetaGradientType type)
*/
static void
fill_gradient (GdkPixbuf *pixbuf,
const GdkColor *c1,
const GdkColor *c2,
int vertical,
int gradient_width,
int gradient_height,
int pixbuf_x,
int pixbuf_y)
{ {
int i, j; MetaGradientSpec *spec;
int dr, dg, db;
int gs1;
int vc = (!vertical || (c1 == c2));
int w = gdk_pixbuf_get_width (pixbuf);
int h = gdk_pixbuf_get_height (pixbuf);
guchar *b, *row;
guchar *d = gdk_pixbuf_get_pixels (pixbuf);
int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
#define R1 c1->red spec = g_new (MetaGradientSpec, 1);
#define G1 c1->green
#define B1 c1->blue
#define R2 c2->red
#define G2 c2->green
#define B2 c2->blue
dr = R2 - R1; spec->type = type;
dg = G2 - G1; spec->color_specs = NULL;
db = B2 - B1;
gs1 = (vertical) ? gradient_height - 1 : gradient_width - 1; return spec;
row = g_new (unsigned char, rowstride);
if (vc)
{
b = row;
for (j = 0; j < w; j++)
{
*b++ = (R1 + ((j + pixbuf_x) * dr) / gs1) >> 8;
*b++ = (G1 + ((j + pixbuf_x) * dg) / gs1) >> 8;
*b++ = (B1 + ((j + pixbuf_x) * db) / gs1) >> 8;
}
} }
for (i = 0; i < h; i++) void
meta_gradient_spec_free (MetaGradientSpec *spec)
{ {
if (!vc) g_return_if_fail (spec != NULL);
{
unsigned char cr, cg, cb;
cr = (R1 + ((i + pixbuf_y) * dr) / gs1) >> 8;
cg = (G1 + ((i + pixbuf_y) * dg) / gs1) >> 8;
cb = (B1 + ((i + pixbuf_y) * db) / gs1) >> 8;
b = row;
for (j = 0; j < w; j++)
{
*b++ = cr;
*b++ = cg;
*b++ = cb;
}
}
memcpy (d, row, w * 3);
d += rowstride;
}
#undef R1 g_slist_foreach (spec->color_specs, (GFunc) meta_color_spec_free, NULL);
#undef G1 g_slist_free (spec->color_specs);
#undef B1 g_free (spec);
#undef R2
#undef G2
#undef B2
g_free (row);
}
#endif
typedef struct _CachedGradient CachedGradient;
struct _CachedGradient
{
MetaGradientType type;
GdkColor color_one;
GdkColor color_two;
int width;
int height;
GdkPixbuf *pixbuf;
int access_serial;
};
static GHashTable *gradient_cache = NULL;
static int access_counter = 0;
static int cache_size = 0;
#define GRADIENT_SIZE(g) ((g)->width * (g)->height * 4)
#define MAX_CACHE_SIZE (1024 * 128) /* 128k */
static guint
cached_gradient_hash (gconstpointer value)
{
/* I have no idea how to write a hash function. */
const CachedGradient *gradient = value;
guint colorone_hash = gdk_color_hash (&gradient->color_one);
guint colortwo_hash = gdk_color_hash (&gradient->color_two);
guint hash = (colorone_hash >> 16) | (colortwo_hash << 16);
hash ^= gradient->width << 22;
hash ^= gradient->height;
hash ^= gradient->type << 15;
return hash;
}
static gboolean
cached_gradient_equal (gconstpointer value_a,
gconstpointer value_b)
{
const CachedGradient *gradient_a = value_a;
const CachedGradient *gradient_b = value_b;
return gradient_a->type == gradient_b->type &&
gradient_a->width == gradient_b->width &&
gradient_a->height == gradient_b->height &&
gdk_color_equal (&gradient_a->color_one, &gradient_b->color_one) &&
gdk_color_equal (&gradient_a->color_two, &gradient_b->color_two);
}
static void
hash_listify (gpointer key, gpointer value, gpointer data)
{
GSList **list = data;
if (key != value)
meta_bug ("Gradient cache got munged (value was overwritten)\n");
*list = g_slist_prepend (*list, value);
}
/* sort gradients so that least-recently-used are first */
static int
gradient_lru_compare (gconstpointer a,
gconstpointer b)
{
const CachedGradient *gradient_a = a;
const CachedGradient *gradient_b = b;
if (gradient_a->access_serial < gradient_b->access_serial)
return -1;
else if (gradient_a->access_serial > gradient_b->access_serial)
return 1;
else
return 0;
}
static void
expire_some_old_gradients (void)
{
GSList *all_gradients;
GSList *tmp;
all_gradients = NULL;
g_hash_table_foreach (gradient_cache, hash_listify, &all_gradients);
all_gradients = g_slist_sort (all_gradients, gradient_lru_compare);
tmp = all_gradients;
while (tmp != NULL)
{
CachedGradient *gradient = tmp->data;
if (cache_size < MAX_CACHE_SIZE)
break;
meta_topic (META_DEBUG_GRADIENT_CACHE,
" Removing gradient of size %d from cache of size %d\n",
GRADIENT_SIZE (gradient), cache_size);
cache_size -= GRADIENT_SIZE (gradient);
g_hash_table_remove (gradient_cache, gradient);
g_object_unref (G_OBJECT (gradient->pixbuf));
g_free (gradient);
tmp = tmp->next;
}
g_slist_free (all_gradients);
meta_topic (META_DEBUG_GRADIENT_CACHE,
"Cache reduced to size %d bytes %d gradients after expiring old gradients\n",
cache_size, g_hash_table_size (gradient_cache));
} }
GdkPixbuf* GdkPixbuf*
meta_theme_get_gradient (MetaGradientType type, meta_gradient_spec_render (const MetaGradientSpec *spec,
const GdkColor *color_one, GtkWidget *widget,
const GdkColor *color_two,
int width, int width,
int height) int height)
{ {
CachedGradient gradient; int n_colors;
CachedGradient *cached; GdkColor *colors;
GdkPixbuf *retval; GSList *tmp;
int i;
GdkPixbuf *pixbuf;
meta_topic (META_DEBUG_GRADIENT_CACHE, n_colors = g_slist_length (spec->color_specs);
"Requesting %s gradient one %d/%d/%d two %d/%d/%d "
"%d x %d\n",
type == META_GRADIENT_VERTICAL ? "vertical" : "horizontal",
color_one->red / 256, color_one->green / 256, color_one->blue / 256,
color_two->red / 256, color_two->green / 256, color_two->blue / 256,
width, height);
if (gradient_cache == NULL) if (n_colors == 0)
{
gradient_cache = g_hash_table_new (cached_gradient_hash,
cached_gradient_equal);
}
gradient.type = type;
gradient.color_one = *color_one;
gradient.color_two = *color_two;
gradient.width = width;
gradient.height = height;
gradient.pixbuf = NULL;
gradient.access_serial = access_counter;
cached = g_hash_table_lookup (gradient_cache, &gradient);
if (cached)
{
meta_topic (META_DEBUG_GRADIENT_CACHE,
"Found gradient in cache\n");
++access_counter;
cached->access_serial = access_counter;
g_object_ref (G_OBJECT (cached->pixbuf));
return cached->pixbuf;
}
#if 0
gradient.pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
gradient.width, gradient.height);
fill_gradient (gradient.pixbuf,
&gradient.color_one,
&gradient.color_two,
type == META_GRADIENT_VERTICAL ? TRUE : FALSE,
gradient.width,
gradient.height,
0, 0);
#else
gradient.pixbuf = meta_gradient_create_simple (gradient.width,
gradient.height,
&gradient.color_one,
&gradient.color_two,
type);
if (gradient.pixbuf == NULL)
{
meta_topic (META_DEBUG_GRADIENT_CACHE,
"Not enough memory to create gradient of size %d bytes\n",
GRADIENT_SIZE (&gradient));
return NULL; return NULL;
}
#endif
if (GRADIENT_SIZE (&gradient) > MAX_CACHE_SIZE) colors = g_new (GdkColor, n_colors);
i = 0;
tmp = spec->color_specs;
while (tmp != NULL)
{ {
cached = g_new (CachedGradient, 1); meta_color_spec_render (tmp->data, widget, &colors[i]);
*cached = gradient;
g_hash_table_insert (gradient_cache, cached, cached); tmp = tmp->next;
++i;
}
meta_topic (META_DEBUG_GRADIENT_CACHE, pixbuf = meta_gradient_create_multi (width, height,
"Caching newly-created gradient, size is %d bytes, total cache size %d bytes %d gradients, maximum %d bytes\n", colors, n_colors,
GRADIENT_SIZE (cached), spec->type);
cache_size, g_hash_table_size (gradient_cache), MAX_CACHE_SIZE);
cache_size += GRADIENT_SIZE (cached); g_free (colors);
g_object_ref (G_OBJECT (cached->pixbuf)); /* to return to caller */ return pixbuf;
retval = cached->pixbuf; }
if (cache_size > MAX_CACHE_SIZE) MetaColorSpec*
expire_some_old_gradients (); /* may unref "cached->pixbuf" and free "cached" */ meta_color_spec_new (MetaColorSpecType type)
{
MetaColorSpec *spec;
MetaColorSpec dummy;
int size;
size = G_STRUCT_OFFSET (MetaColorSpec, data);
switch (type)
{
case META_COLOR_SPEC_BASIC:
size += sizeof (dummy.data.basic);
break;
case META_COLOR_SPEC_GTK:
size += sizeof (dummy.data.gtk);
break;
case META_COLOR_SPEC_BLEND:
size += sizeof (dummy.data.blend);
break;
}
spec = g_malloc0 (size);
spec->type = type;
return spec;
}
void
meta_color_spec_free (MetaColorSpec *spec)
{
g_return_if_fail (spec != NULL);
switch (spec->type)
{
case META_COLOR_SPEC_BASIC:
break;
case META_COLOR_SPEC_GTK:
break;
case META_COLOR_SPEC_BLEND:
if (spec->data.blend.foreground)
meta_color_spec_free (spec->data.blend.foreground);
if (spec->data.blend.background)
meta_color_spec_free (spec->data.blend.background);
break;
}
g_free (spec);
}
void
meta_color_spec_render (MetaColorSpec *spec,
GtkWidget *widget,
GdkColor *color)
{
g_return_if_fail (spec != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (widget->style != NULL);
switch (spec->type)
{
case META_COLOR_SPEC_BASIC:
*color = spec->data.basic.color;
break;
case META_COLOR_SPEC_GTK:
switch (spec->data.gtk.component)
{
case GTK_RC_BG:
*color = widget->style->bg[spec->data.gtk.state];
break;
case GTK_RC_FG:
*color = widget->style->fg[spec->data.gtk.state];
break;
case GTK_RC_BASE:
*color = widget->style->base[spec->data.gtk.state];
break;
case GTK_RC_TEXT:
*color = widget->style->text[spec->data.gtk.state];
break;
}
break;
case META_COLOR_SPEC_BLEND:
{
GdkColor fg, bg;
int alpha;
meta_color_spec_render (spec->data.blend.foreground, widget, &fg);
meta_color_spec_render (spec->data.blend.background, widget, &bg);
*color = fg;
alpha = spec->data.blend.alpha * 0xffff;
color->red = color->red + (((bg.red - color->red) * alpha + 0x8000) >> 16);
color->green = color->green + (((bg.green - color->green) * alpha + 0x8000) >> 16);
color->blue = color->blue + (((bg.blue - color->blue) * alpha + 0x8000) >> 16);
}
break;
}
}
MetaTextureSpec*
meta_texture_spec_new (MetaTextureType type)
{
MetaTextureSpec *spec;
MetaTextureSpec dummy;
int size;
size = G_STRUCT_OFFSET (MetaTextureSpec, data);
switch (type)
{
case META_TEXTURE_SOLID:
size += sizeof (dummy.data.solid);
break;
case META_TEXTURE_GRADIENT:
size += sizeof (dummy.data.gradient);
break;
case META_TEXTURE_IMAGE:
size += sizeof (dummy.data.image);
break;
}
spec = g_malloc0 (size);
spec->type = type;
return spec;
}
void
meta_texture_spec_free (MetaTextureSpec *spec)
{
g_return_if_fail (spec != NULL);
switch (spec->type)
{
case META_TEXTURE_SOLID:
if (spec->data.solid.color_spec)
meta_color_spec_free (spec->data.solid.color_spec);
break;
case META_TEXTURE_GRADIENT:
if (spec->data.gradient.gradient_spec)
meta_gradient_spec_free (spec->data.gradient.gradient_spec);
break;
case META_TEXTURE_IMAGE:
if (spec->data.image.pixbuf)
g_object_unref (G_OBJECT (spec->data.image.pixbuf));
break;
}
g_free (spec);
}
static void
render_pixbuf (GdkDrawable *drawable,
const GdkRectangle *clip,
GdkPixbuf *pixbuf,
int x,
int y)
{
/* grumble, render_to_drawable_alpha does not accept a clip
* mask, so we have to go through some BS
*/
GdkRectangle pixbuf_rect;
GdkRectangle draw_rect;
pixbuf_rect.x = x;
pixbuf_rect.y = y;
pixbuf_rect.width = gdk_pixbuf_get_width (pixbuf);
pixbuf_rect.height = gdk_pixbuf_get_height (pixbuf);
if (clip)
{
if (!gdk_rectangle_intersect ((GdkRectangle*)clip,
&pixbuf_rect, &draw_rect))
return;
} }
else else
{ {
meta_topic (META_DEBUG_GRADIENT_CACHE, draw_rect = pixbuf_rect;
"Gradient of size %d bytes is too large to cache\n",
GRADIENT_SIZE (&gradient));
retval = gradient.pixbuf;
} }
return retval; gdk_pixbuf_render_to_drawable_alpha (pixbuf,
drawable,
draw_rect.x - pixbuf_rect.x,
draw_rect.y - pixbuf_rect.y,
draw_rect.x, draw_rect.y,
draw_rect.width,
draw_rect.height,
GDK_PIXBUF_ALPHA_FULL, /* ignored */
128, /* ignored */
GDK_RGB_DITHER_NORMAL,
draw_rect.x - pixbuf_rect.x,
draw_rect.y - pixbuf_rect.y);
} }
void
meta_texture_spec_draw (const MetaTextureSpec *spec,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
MetaTextureDrawMode mode,
int x,
int y,
int width,
int height)
{
g_return_if_fail (spec != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GDK_IS_DRAWABLE (drawable));
g_return_if_fail (widget->style != NULL);
switch (spec->type)
{
case META_TEXTURE_SOLID:
{
GdkGC *gc;
GdkGCValues values;
g_return_if_fail (spec->data.solid.color_spec != NULL);
meta_color_spec_render (spec->data.solid.color_spec,
widget,
&values.foreground);
gdk_rgb_find_color (widget->style->colormap, &values.foreground);
gc = gdk_gc_new_with_values (drawable, &values, GDK_GC_FOREGROUND);
gdk_draw_rectangle (drawable,
gc, TRUE, x, y, width, height);
g_object_unref (G_OBJECT (gc));
}
break;
case META_TEXTURE_GRADIENT:
{
GdkPixbuf *pixbuf;
g_return_if_fail (spec->data.gradient.gradient_spec != NULL);
pixbuf = meta_gradient_spec_render (spec->data.gradient.gradient_spec,
widget, width, height);
if (pixbuf == NULL)
return;
render_pixbuf (drawable, clip, pixbuf, x, y);
g_object_unref (G_OBJECT (pixbuf));
}
break;
case META_TEXTURE_IMAGE:
{
GdkPixbuf *pixbuf;
g_return_if_fail (spec->data.image.pixbuf != NULL);
pixbuf = NULL;
switch (mode)
{
case META_TEXTURE_DRAW_UNSCALED:
pixbuf = spec->data.image.pixbuf;
g_object_ref (G_OBJECT (pixbuf));
break;
case META_TEXTURE_DRAW_SCALED_VERTICALLY:
pixbuf = spec->data.image.pixbuf;
if (gdk_pixbuf_get_height (pixbuf) == height)
{
g_object_ref (G_OBJECT (pixbuf));
}
else
{
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
gdk_pixbuf_get_width (pixbuf),
height,
GDK_INTERP_BILINEAR);
if (pixbuf == NULL)
return;
}
break;
case META_TEXTURE_DRAW_SCALED_HORIZONTALLY:
pixbuf = spec->data.image.pixbuf;
if (gdk_pixbuf_get_width (pixbuf) == width)
{
g_object_ref (G_OBJECT (pixbuf));
}
else
{
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
width,
gdk_pixbuf_get_height (pixbuf),
GDK_INTERP_BILINEAR);
if (pixbuf == NULL)
return;
}
break;
case META_TEXTURE_DRAW_SCALED_BOTH:
pixbuf = spec->data.image.pixbuf;
if (gdk_pixbuf_get_width (pixbuf) == width &&
gdk_pixbuf_get_height (pixbuf) == height)
{
g_object_ref (G_OBJECT (pixbuf));
}
else
{
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
width, height,
GDK_INTERP_BILINEAR);
if (pixbuf == NULL)
return;
}
break;
}
g_return_if_fail (pixbuf != NULL);
render_pixbuf (drawable, clip, pixbuf, x, y);
g_object_unref (G_OBJECT (pixbuf));
}
break;
}
}

View File

@ -24,22 +24,203 @@
#include "frames.h" #include "frames.h"
#include "gradient.h" #include "gradient.h"
#include <gtk/gtkrc.h>
/* theme.[hc] is basically responsible for drawing parts of the UI using
* theme data
*/
typedef struct _MetaFrameStyle MetaFrameStyle; typedef struct _MetaFrameStyle MetaFrameStyle;
typedef struct _MetaFrameStyleSet MetaFrameStyleSet;
typedef struct _MetaTextureSpec MetaTextureSpec;
typedef struct _MetaGradientSpec MetaGradientSpec;
typedef struct _MetaColorSpec MetaColorSpec;
typedef enum
{
META_COLOR_SPEC_BASIC,
META_COLOR_SPEC_GTK,
META_COLOR_SPEC_BLEND
} MetaColorSpecType;
struct _MetaColorSpec
{
MetaColorSpecType type;
union
{
struct {
GdkColor color;
} basic;
struct {
GtkRcFlags component;
GtkStateType state;
} gtk;
struct {
MetaColorSpec *foreground;
MetaColorSpec *background;
double alpha;
} blend;
} data;
};
struct _MetaGradientSpec
{
MetaGradientType type;
GSList *color_specs;
};
typedef enum
{
META_TEXTURE_SOLID,
META_TEXTURE_GRADIENT,
META_TEXTURE_IMAGE
} MetaTextureType;
struct _MetaTextureSpec
{
MetaTextureType type;
union
{
struct {
MetaColorSpec *color_spec;
} solid;
struct {
MetaGradientSpec *gradient_spec;
} gradient;
struct {
GdkPixbuf *pixbuf;
} image;
} data;
};
typedef enum
{
META_BUTTON_STATE_UNFOCUSED,
META_BUTTON_STATE_FOCUSED,
META_BUTTON_STATE_INSENSITIVE,
META_BUTTON_STATE_PRESSED,
META_BUTTON_STATE_PRELIGHT,
META_BUTTON_STATE_LAST
} MetaButtonState;
typedef enum
{
META_BUTTON_TYPE_CLOSE,
META_BUTTON_TYPE_MAXIMIZE,
META_BUTTON_TYPE_MINIMIZE,
META_BUTTON_TYPE_MENU,
META_BUTTON_TYPE_LAST
} MetaButtonType;
typedef enum
{
/* Listed in the order in which the textures are drawn.
* (though this only matters for overlaps of course.)
* Buttons are drawn after the frame textures.
*
* On the corners, horizontal pieces are arbitrarily given the
* corner area:
*
* ===== |====
* | |
* | rather than |
*
*/
/* place over entire frame, scaled both */
META_FRAME_PIECE_ENTIRE_BACKGROUND,
/* place over entire titlebar background, scaled both */
META_FRAME_PIECE_TITLEBAR_BACKGROUND,
/* place on left end of titlebar, scaled vert */
META_FRAME_PIECE_LEFT_TITLEBAR_EDGE,
/* place on right end of titlebar, scaled vert */
META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE,
/* place on top edge of titlebar, scaled horiz */
META_FRAME_PIECE_TOP_TITLEBAR_EDGE,
/* place on bottom edge of titlebar, scaled horiz */
META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE,
/* place on left end of top edge of titlebar, unscaled */
META_FRAME_PIECE_LEFT_END_OF_TOP_TITLEBAR_EDGE,
/* place on right end of top edge of titlebar, unscaled */
META_FRAME_PIECE_RIGHT_END_OF_TOP_TITLEBAR_EDGE,
/* place on left end of bottom edge of titlebar, unscaled */
META_FRAME_PIECE_LEFT_END_OF_BOTTOM_TITLEBAR_EDGE,
/* place on right end of bottom edge of titlebar, unscaled */
META_FRAME_PIECE_RIGHT_END_OF_BOTTOM_TITLEBAR_EDGE,
/* place on top end of left titlebar edge, unscaled */
META_FRAME_PIECE_TOP_END_OF_LEFT_TITLEBAR_EDGE,
/* place on bottom end of left titlebar edge, unscaled */
META_FRAME_PIECE_BOTTOM_END_OF_LEFT_TITLEBAR_EDGE,
/* place on top end of right titlebar edge, unscaled */
META_FRAME_PIECE_TOP_END_OF_RIGHT_TITLEBAR_EDGE,
/* place on bottom end of right titlebar edge, unscaled */
META_FRAME_PIECE_BOTTOM_END_OF_RIGHT_TITLEBAR_EDGE,
/* render over title background (text area), scaled both */
META_FRAME_PIECE_TITLE_BACKGROUND,
/* render over left side of TITLE_BACKGROUND, scaled vert */
META_FRAME_PIECE_LEFT_TITLE_BACKGROUND,
/* render over right side of TITLE_BACKGROUND, scaled vert */
META_FRAME_PIECE_RIGHT_TITLE_BACKGROUND,
/* place on left edge of the frame, scaled vert */
META_FRAME_PIECE_LEFT_EDGE,
/* place on right edge of the frame, scaled vert */
META_FRAME_PIECE_RIGHT_EDGE,
/* place on bottom edge of the frame, scaled horiz */
META_FRAME_PIECE_BOTTOM_EDGE,
/* place on top end of left edge of the frame, unscaled */
META_FRAME_PIECE_TOP_END_OF_LEFT_EDGE,
/* place on bottom end of left edge of the frame, unscaled */
META_FRAME_PIECE_BOTTOM_END_OF_LEFT_EDGE,
/* place on top end of right edge of the frame, unscaled */
META_FRAME_PIECE_TOP_END_OF_RIGHT_EDGE,
/* place on bottom end of right edge of the frame, unscaled */
META_FRAME_PIECE_BOTTOM_END_OF_RIGHT_EDGE,
/* place on left end of bottom edge of the frame, unscaled */
META_FRAME_PIECE_LEFT_END_OF_BOTTOM_EDGE,
/* place on right end of bottom edge of the frame, unscaled */
META_FRAME_PIECE_RIGHT_END_OF_BOTTOM_EDGE,
/* Used to get size of the enum */
META_FRAME_PIECE_LAST
} MetaFramePiece;
struct _MetaFrameStyle struct _MetaFrameStyle
{ {
MetaGradientDescription *title_gradient; MetaTextureSpec *button_icons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
MetaTextureSpec *button_backgrounds[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
MetaTextureSpec *pieces[META_FRAME_PIECE_LAST];
}; };
GdkPixbuf* meta_theme_get_gradient (MetaGradientType type, typedef enum
const GdkColor *color_one, {
const GdkColor *color_two, META_TEXTURE_DRAW_UNSCALED,
META_TEXTURE_DRAW_SCALED_VERTICALLY,
META_TEXTURE_DRAW_SCALED_HORIZONTALLY,
META_TEXTURE_DRAW_SCALED_BOTH
} MetaTextureDrawMode;
MetaColorSpec* meta_color_spec_new (MetaColorSpecType type);
void meta_color_spec_free (MetaColorSpec *spec);
void meta_color_spec_render (MetaColorSpec *spec,
GtkWidget *widget,
GdkColor *color);
MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type);
void meta_gradient_spec_free (MetaGradientSpec *desc);
GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc,
GtkWidget *widget,
int width,
int height);
MetaTextureSpec* meta_texture_spec_new (MetaTextureType type);
void meta_texture_spec_free (MetaTextureSpec *desc);
void meta_texture_spec_draw (const MetaTextureSpec *desc,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
MetaTextureDrawMode mode,
/* logical region being drawn,
* scale to this area if in SCALED
* mode
*/
int x,
int y,
int width, int width,
int height); int height);

View File

@ -2712,11 +2712,11 @@ meta_window_notify_focus (MetaWindow *window,
meta_topic (META_DEBUG_FOCUS, meta_topic (META_DEBUG_FOCUS,
"New focus window %s\n", window->desc); "New focus window %s\n", window->desc);
window->display->focus_window = window; window->display->focus_window = window;
}
window->has_focus = TRUE; window->has_focus = TRUE;
if (window->frame) if (window->frame)
meta_frame_queue_draw (window->frame); meta_frame_queue_draw (window->frame);
} }
}
else if (event->type == FocusOut || else if (event->type == FocusOut ||
event->type == UnmapNotify) event->type == UnmapNotify)
{ {
@ -2742,11 +2742,11 @@ meta_window_notify_focus (MetaWindow *window,
"Clearing focus window (was %s)\n", window->desc); "Clearing focus window (was %s)\n", window->desc);
window->display->focus_window = NULL; window->display->focus_window = NULL;
}
window->has_focus = FALSE; window->has_focus = FALSE;
if (window->frame) if (window->frame)
meta_frame_queue_draw (window->frame); meta_frame_queue_draw (window->frame);
} }
}
/* Now set _NET_ACTIVE_WINDOW hint */ /* Now set _NET_ACTIVE_WINDOW hint */
meta_display_update_active_window_hint (window->display); meta_display_update_active_window_hint (window->display);