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:
parent
9ed27d3dcb
commit
402c0b5036
18
ChangeLog
18
ChangeLog
@ -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>
|
||||
|
||||
* 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
|
||||
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>
|
||||
|
||||
* src/window.c (meta_window_notify_focus): put in attempted fix
|
||||
|
@ -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")
|
||||
|
14
src/frames.c
14
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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
654
src/theme.c
654
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);
|
||||
MetaGradientSpec *spec;
|
||||
|
||||
#define R1 c1->red
|
||||
#define G1 c1->green
|
||||
#define B1 c1->blue
|
||||
#define R2 c2->red
|
||||
#define G2 c2->green
|
||||
#define B2 c2->blue
|
||||
spec = g_new (MetaGradientSpec, 1);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
spec->type = type;
|
||||
spec->color_specs = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#undef R1
|
||||
#undef G1
|
||||
#undef B1
|
||||
#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;
|
||||
return spec;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cached_gradient_equal (gconstpointer value_a,
|
||||
gconstpointer value_b)
|
||||
void
|
||||
meta_gradient_spec_free (MetaGradientSpec *spec)
|
||||
{
|
||||
const CachedGradient *gradient_a = value_a;
|
||||
const CachedGradient *gradient_b = value_b;
|
||||
g_return_if_fail (spec != NULL);
|
||||
|
||||
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));
|
||||
g_slist_foreach (spec->color_specs, (GFunc) meta_color_spec_free, NULL);
|
||||
g_slist_free (spec->color_specs);
|
||||
g_free (spec);
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_theme_get_gradient (MetaGradientType type,
|
||||
const GdkColor *color_one,
|
||||
const GdkColor *color_two,
|
||||
int width,
|
||||
int height)
|
||||
meta_gradient_spec_render (const MetaGradientSpec *spec,
|
||||
GtkWidget *widget,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
CachedGradient gradient;
|
||||
CachedGradient *cached;
|
||||
GdkPixbuf *retval;
|
||||
int n_colors;
|
||||
GdkColor *colors;
|
||||
GSList *tmp;
|
||||
int i;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
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);
|
||||
n_colors = g_slist_length (spec->color_specs);
|
||||
|
||||
if (n_colors == 0)
|
||||
return NULL;
|
||||
|
||||
if (gradient_cache == NULL)
|
||||
colors = g_new (GdkColor, n_colors);
|
||||
|
||||
i = 0;
|
||||
tmp = spec->color_specs;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GRADIENT_SIZE (&gradient) > MAX_CACHE_SIZE)
|
||||
{
|
||||
cached = g_new (CachedGradient, 1);
|
||||
*cached = gradient;
|
||||
meta_color_spec_render (tmp->data, widget, &colors[i]);
|
||||
|
||||
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);
|
||||
tmp = tmp->next;
|
||||
++i;
|
||||
}
|
||||
|
||||
cache_size += GRADIENT_SIZE (cached);
|
||||
|
||||
g_object_ref (G_OBJECT (cached->pixbuf)); /* to return to caller */
|
||||
retval = cached->pixbuf;
|
||||
pixbuf = meta_gradient_create_multi (width, height,
|
||||
colors, n_colors,
|
||||
spec->type);
|
||||
|
||||
if (cache_size > MAX_CACHE_SIZE)
|
||||
expire_some_old_gradients (); /* may unref "cached->pixbuf" and free "cached" */
|
||||
g_free (colors);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
MetaColorSpec*
|
||||
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
|
||||
{
|
||||
meta_topic (META_DEBUG_GRADIENT_CACHE,
|
||||
"Gradient of size %d bytes is too large to cache\n",
|
||||
GRADIENT_SIZE (&gradient));
|
||||
|
||||
retval = gradient.pixbuf;
|
||||
draw_rect = pixbuf_rect;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
203
src/theme.h
203
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;
|
||||
|
||||
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
|
||||
{
|
||||
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,
|
||||
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
|
||||
|
12
src/window.c
12
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user