summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@pobox.com>2002-01-08 07:23:35 +0000
committerHavoc Pennington <hp@src.gnome.org>2002-01-08 07:23:35 +0000
commit402c0b5036b26a202a888ebd6314a50a4190e589 (patch)
treecc454963a9bfe4cccd51515e3beac757eebba008
parent9ed27d3dcb87fbbdf6991bb4b23dbf1d24039efb (diff)
downloadmetacity-402c0b5036b26a202a888ebd6314a50a4190e589.tar.gz
metacity-402c0b5036b26a202a888ebd6314a50a4190e589.tar.bz2
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
-rw-r--r--ChangeLog18
-rw-r--r--configure.in3
-rw-r--r--src/frames.c14
-rw-r--r--src/gradient.c51
-rw-r--r--src/gradient.h22
-rw-r--r--src/testgradient.c2
-rw-r--r--src/theme.c604
-rw-r--r--src/theme.h203
-rw-r--r--src/window.c12
9 files changed, 580 insertions, 349 deletions
diff --git a/ChangeLog b/ChangeLog
index 76ef57a..d25ed18 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+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>
* src/frames.c (meta_frames_expose_event): make gradient a bit
@@ -6,6 +18,12 @@
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>
+
* src/window.c (meta_window_notify_focus): put in attempted fix
for the GTK 1.2 plug/socket screwup, now that my fixed debug spew
reveals what's actually happening. ;-)
diff --git a/configure.in b/configure.in
index 24dafe7..6172acb 100644
--- a/configure.in
+++ b/configure.in
@@ -4,6 +4,9 @@ AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(metacity, 2.3.34)
+# Honor aclocal flags
+ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS"
+
GETTEXT_PACKAGE=metacity
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE")
diff --git a/src/frames.c b/src/frames.c
index cb93a23..84eedae 100644
--- a/src/frames.c
+++ b/src/frames.c
@@ -1771,12 +1771,12 @@ meta_frames_expose_event (GtkWidget *widget,
layout_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
- gradient = meta_theme_get_gradient (META_GRADIENT_DIAGONAL,
- &selected_faded,
- &widget->style->bg[GTK_STATE_SELECTED],
- fgeom.title_rect.width,
- fgeom.title_rect.height);
-
+ gradient = meta_gradient_create_simple (fgeom.title_rect.width,
+ fgeom.title_rect.height,
+ &selected_faded,
+ &widget->style->bg[GTK_STATE_SELECTED],
+ META_GRADIENT_DIAGONAL);
+
if (gradient != NULL)
{
gdk_pixbuf_render_to_drawable (gradient,
@@ -1787,7 +1787,7 @@ meta_frames_expose_event (GtkWidget *widget,
fgeom.title_rect.y,
fgeom.title_rect.width,
fgeom.title_rect.height,
- GDK_RGB_DITHER_NORMAL,
+ GDK_RGB_DITHER_MAX,
0, 0);
g_object_unref (G_OBJECT (gradient));
diff --git a/src/gradient.c b/src/gradient.c
index 2fcfc8b..7be76d9 100644
--- a/src/gradient.c
+++ b/src/gradient.c
@@ -20,6 +20,7 @@
* 02111-1307, USA. */
#include "gradient.h"
+#include "util.h"
#include <string.h>
/* 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 rowstride;
- /* FIXME the no_padding = TRUE here is a workaround for a problem
- * create_diagonal that can't handle a funky rowstride
- */
- pixbuf = blank_pixbuf (width, height, TRUE);
+ pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -448,9 +446,6 @@ meta_gradient_create_diagonal (int width, int height,
pixels = gdk_pixbuf_get_pixels (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);
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 */
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);
offset += a;
}
@@ -702,9 +694,6 @@ meta_gradient_create_multi_diagonal (int width, int height,
if (count > height)
count = height;
- /* FIXME here again is a bug that requires multi_horizontal
- * to have width == rowstride
- */
if (count > 2)
tmp = meta_gradient_create_multi_horizontal (2*width-1, 1, colors, count);
else
@@ -736,39 +725,3 @@ meta_gradient_create_multi_diagonal (int width, int height,
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);
-}
diff --git a/src/gradient.h b/src/gradient.h
index 4b14475..785a1a8 100644
--- a/src/gradient.h
+++ b/src/gradient.h
@@ -32,27 +32,6 @@ typedef enum
META_GRADIENT_DIAGONAL
} 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,
int height,
const GdkColor *from,
@@ -70,4 +49,5 @@ GdkPixbuf* meta_gradient_create_interwoven (int width,
const GdkColor colors2[2],
int thickness2);
+
#endif
diff --git a/src/testgradient.c b/src/testgradient.c
index aac882a..007b441 100644
--- a/src/testgradient.c
+++ b/src/testgradient.c
@@ -47,7 +47,7 @@ render_simple (GdkDrawable *drawable,
gc,
0, 0,
0, 0, width, height,
- GDK_RGB_DITHER_NORMAL,
+ GDK_RGB_DITHER_MAX,
0, 0);
g_object_unref (G_OBJECT (pixbuf));
diff --git a/src/theme.c b/src/theme.c
index c42a336..1629c5c 100644
--- a/src/theme.c
+++ b/src/theme.c
@@ -24,307 +24,403 @@
#include "gradient.h"
#include <string.h>
-#if 0
-/* fill_gradient routine from GNOME background-properties, CVS says
- * Michael Fulbright checked it in, Copyright 1998 Red Hat Inc.
- */
-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)
+
+MetaGradientSpec*
+meta_gradient_spec_new (MetaGradientType type)
{
- int i, j;
- 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
-#define G1 c1->green
-#define B1 c1->blue
-#define R2 c2->red
-#define G2 c2->green
-#define B2 c2->blue
-
- dr = R2 - R1;
- dg = G2 - G1;
- db = B2 - B1;
-
- gs1 = (vertical) ? gradient_height - 1 : gradient_width - 1;
-
- 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++)
- {
- if (!vc)
- {
- 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;
- }
+ MetaGradientSpec *spec;
+
+ spec = g_new (MetaGradientSpec, 1);
+
+ spec->type = type;
+ spec->color_specs = NULL;
-#undef R1
-#undef G1
-#undef B1
-#undef R2
-#undef G2
-#undef B2
-
- g_free (row);
+ return spec;
}
-#endif
-typedef struct _CachedGradient CachedGradient;
-
-struct _CachedGradient
+void
+meta_gradient_spec_free (MetaGradientSpec *spec)
{
- 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;
+ g_return_if_fail (spec != NULL);
+
+ g_slist_foreach (spec->color_specs, (GFunc) meta_color_spec_free, NULL);
+ g_slist_free (spec->color_specs);
+ g_free (spec);
+}
-#define GRADIENT_SIZE(g) ((g)->width * (g)->height * 4)
+GdkPixbuf*
+meta_gradient_spec_render (const MetaGradientSpec *spec,
+ GtkWidget *widget,
+ int width,
+ int height)
+{
+ int n_colors;
+ GdkColor *colors;
+ GSList *tmp;
+ int i;
+ GdkPixbuf *pixbuf;
+
+ n_colors = g_slist_length (spec->color_specs);
-#define MAX_CACHE_SIZE (1024 * 128) /* 128k */
+ if (n_colors == 0)
+ return NULL;
+
+ colors = g_new (GdkColor, n_colors);
-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);
+ i = 0;
+ tmp = spec->color_specs;
+ while (tmp != NULL)
+ {
+ meta_color_spec_render (tmp->data, widget, &colors[i]);
+
+ tmp = tmp->next;
+ ++i;
+ }
+
+ pixbuf = meta_gradient_create_multi (width, height,
+ colors, n_colors,
+ spec->type);
- hash ^= gradient->width << 22;
- hash ^= gradient->height;
- hash ^= gradient->type << 15;
+ g_free (colors);
- return hash;
+ return pixbuf;
}
-static gboolean
-cached_gradient_equal (gconstpointer value_a,
- gconstpointer value_b)
+MetaColorSpec*
+meta_color_spec_new (MetaColorSpecType type)
{
- const CachedGradient *gradient_a = value_a;
- const CachedGradient *gradient_b = value_b;
+ MetaColorSpec *spec;
+ MetaColorSpec dummy;
+ int size;
+
+ size = G_STRUCT_OFFSET (MetaColorSpec, data);
- 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);
-}
+ switch (type)
+ {
+ case META_COLOR_SPEC_BASIC:
+ size += sizeof (dummy.data.basic);
+ break;
-static void
-hash_listify (gpointer key, gpointer value, gpointer data)
-{
- GSList **list = data;
+ 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);
- if (key != value)
- meta_bug ("Gradient cache got munged (value was overwritten)\n");
+ spec->type = type;
- *list = g_slist_prepend (*list, value);
+ return spec;
}
-/* sort gradients so that least-recently-used are first */
-static int
-gradient_lru_compare (gconstpointer a,
- gconstpointer b)
+void
+meta_color_spec_free (MetaColorSpec *spec)
{
- 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;
+ 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);
}
-static void
-expire_some_old_gradients (void)
+void
+meta_color_spec_render (MetaColorSpec *spec,
+ GtkWidget *widget,
+ GdkColor *color)
{
- GSList *all_gradients;
- GSList *tmp;
+ g_return_if_fail (spec != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (widget->style != NULL);
- all_gradients = NULL;
+ switch (spec->type)
+ {
+ case META_COLOR_SPEC_BASIC:
+ *color = spec->data.basic.color;
+ break;
- g_hash_table_foreach (gradient_cache, hash_listify, &all_gradients);
+ 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;
+ }
+}
- 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;
+MetaTextureSpec*
+meta_texture_spec_new (MetaTextureType type)
+{
+ MetaTextureSpec *spec;
+ MetaTextureSpec dummy;
+ int size;
- 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);
+ size = G_STRUCT_OFFSET (MetaTextureSpec, data);
+
+ switch (type)
+ {
+ case META_TEXTURE_SOLID:
+ size += sizeof (dummy.data.solid);
+ break;
- g_hash_table_remove (gradient_cache, gradient);
+ case META_TEXTURE_GRADIENT:
+ size += sizeof (dummy.data.gradient);
+ break;
- g_object_unref (G_OBJECT (gradient->pixbuf));
- g_free (gradient);
-
- tmp = tmp->next;
+ case META_TEXTURE_IMAGE:
+ size += sizeof (dummy.data.image);
+ break;
}
+
+ spec = g_malloc0 (size);
- 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));
+ spec->type = type;
+
+ return spec;
}
-GdkPixbuf*
-meta_theme_get_gradient (MetaGradientType type,
- const GdkColor *color_one,
- const GdkColor *color_two,
- int width,
- int height)
+void
+meta_texture_spec_free (MetaTextureSpec *spec)
{
- CachedGradient gradient;
- CachedGradient *cached;
- GdkPixbuf *retval;
+ g_return_if_fail (spec != NULL);
- meta_topic (META_DEBUG_GRADIENT_CACHE,
- "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)
+ switch (spec->type)
{
- gradient_cache = g_hash_table_new (cached_gradient_hash,
- cached_gradient_equal);
+ 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;
}
- 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;
+ 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;
- cached = g_hash_table_lookup (gradient_cache, &gradient);
+ 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 (cached)
+ if (clip)
{
- 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 (!gdk_rectangle_intersect ((GdkRectangle*)clip,
+ &pixbuf_rect, &draw_rect))
+ return;
}
-
-#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)
+ else
{
- meta_topic (META_DEBUG_GRADIENT_CACHE,
- "Not enough memory to create gradient of size %d bytes\n",
- GRADIENT_SIZE (&gradient));
- return NULL;
+ draw_rect = pixbuf_rect;
}
-#endif
-
- if (GRADIENT_SIZE (&gradient) > MAX_CACHE_SIZE)
- {
- cached = g_new (CachedGradient, 1);
- *cached = gradient;
-
- g_hash_table_insert (gradient_cache, cached, cached);
-
- meta_topic (META_DEBUG_GRADIENT_CACHE,
- "Caching newly-created gradient, size is %d bytes, total cache size %d bytes %d gradients, maximum %d bytes\n",
- GRADIENT_SIZE (cached),
- cache_size, g_hash_table_size (gradient_cache), MAX_CACHE_SIZE);
- cache_size += GRADIENT_SIZE (cached);
-
- g_object_ref (G_OBJECT (cached->pixbuf)); /* to return to caller */
- retval = cached->pixbuf;
+ 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);
+}
- if (cache_size > MAX_CACHE_SIZE)
- expire_some_old_gradients (); /* may unref "cached->pixbuf" and free "cached" */
- }
- else
- {
- meta_topic (META_DEBUG_GRADIENT_CACHE,
- "Gradient of size %d bytes is too large to cache\n",
- GRADIENT_SIZE (&gradient));
- retval = gradient.pixbuf;
- }
+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);
- return retval;
+ 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;
+ }
}
-
diff --git a/src/theme.h b/src/theme.h
index 78a9675..b14142a 100644
--- a/src/theme.h
+++ b/src/theme.h
@@ -24,23 +24,204 @@
#include "frames.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 _MetaFrameStyleSet MetaFrameStyleSet;
+typedef struct _MetaTextureSpec MetaTextureSpec;
+typedef struct _MetaGradientSpec MetaGradientSpec;
+typedef struct _MetaColorSpec MetaColorSpec;
-struct _MetaFrameStyle
+typedef enum
{
- MetaGradientDescription *title_gradient;
-
+ 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
+{
+ 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,
- const GdkColor *color_one,
- const GdkColor *color_two,
- int width,
- int height);
+typedef enum
+{
+ 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 height);
#endif
diff --git a/src/window.c b/src/window.c
index bd4b219..914a0c3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2712,10 +2712,10 @@ meta_window_notify_focus (MetaWindow *window,
meta_topic (META_DEBUG_FOCUS,
"New focus window %s\n", window->desc);
window->display->focus_window = window;
+ window->has_focus = TRUE;
+ if (window->frame)
+ meta_frame_queue_draw (window->frame);
}
- window->has_focus = TRUE;
- if (window->frame)
- meta_frame_queue_draw (window->frame);
}
else if (event->type == FocusOut ||
event->type == UnmapNotify)
@@ -2742,10 +2742,10 @@ meta_window_notify_focus (MetaWindow *window,
"Clearing focus window (was %s)\n", window->desc);
window->display->focus_window = NULL;
+ window->has_focus = FALSE;
+ if (window->frame)
+ meta_frame_queue_draw (window->frame);
}
- window->has_focus = FALSE;
- if (window->frame)
- meta_frame_queue_draw (window->frame);
}
/* Now set _NET_ACTIVE_WINDOW hint */