summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--src/Makefile.am2
-rw-r--r--src/frames.c26
-rw-r--r--src/theme.c965
-rw-r--r--src/theme.h124
-rw-r--r--src/util.c3
-rw-r--r--src/util.h3
7 files changed, 268 insertions, 864 deletions
diff --git a/ChangeLog b/ChangeLog
index df35791..e03a1ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2002-01-05 Havoc Pennington <hp@pobox.com>
+ * src/frames.c (meta_frames_expose_event): draw titlebar highlight
+ with snazzy gradient that needs some tweaking to be less
+ dumb-looking
+
+ * src/theme.c: replace old theme.[hc] contents with newer stuff
+ that doesn't do anything
+
+2002-01-05 Havoc Pennington <hp@pobox.com>
+
GTK 1.2 plug/socket clients still broken, don't know why.
* src/screen.c (meta_screen_new): select focus change on root
diff --git a/src/Makefile.am b/src/Makefile.am
index 5e79e91..7bca75d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,6 +40,8 @@ metacity_SOURCES= \
stack.h \
tabpopup.c \
tabpopup.h \
+ theme.c \
+ theme.h \
ui.c \
ui.h \
util.c \
diff --git a/src/frames.c b/src/frames.c
index ba81fca..6a6549a 100644
--- a/src/frames.c
+++ b/src/frames.c
@@ -25,6 +25,7 @@
#include "core.h"
#include "menu.h"
#include "fixedtip.h"
+#include "theme.h"
#define DEFAULT_INNER_BUTTON_BORDER 3
@@ -1759,6 +1760,7 @@ meta_frames_expose_event (GtkWidget *widget,
{
layout_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
+#if 0
/* Draw blue background */
gdk_draw_rectangle (frame->window,
widget->style->bg_gc[GTK_STATE_SELECTED],
@@ -1767,6 +1769,30 @@ meta_frames_expose_event (GtkWidget *widget,
fgeom.title_rect.y,
fgeom.title_rect.width,
fgeom.title_rect.height);
+#else
+ {
+ GdkPixbuf *gradient;
+
+ gradient = meta_theme_get_gradient (META_GRADIENT_HORIZONTAL,
+ &widget->style->bg[GTK_STATE_SELECTED],
+ &widget->style->bg[GTK_STATE_NORMAL],
+ fgeom.title_rect.width,
+ fgeom.title_rect.height);
+
+ gdk_pixbuf_render_to_drawable (gradient,
+ frame->window,
+ widget->style->bg_gc[GTK_STATE_SELECTED],
+ 0, 0,
+ fgeom.title_rect.x,
+ fgeom.title_rect.y,
+ fgeom.title_rect.width,
+ fgeom.title_rect.height,
+ GDK_RGB_DITHER_NORMAL,
+ 0, 0);
+
+ g_object_unref (G_OBJECT (gradient));
+ }
+#endif
}
if (frame->layout)
diff --git a/src/theme.c b/src/theme.c
index 76d104b..ada597a 100644
--- a/src/theme.c
+++ b/src/theme.c
@@ -1,4 +1,4 @@
-/* Metacity Default Theme Engine */
+/* Metacity Theme Rendering */
/*
* Copyright (C) 2001 Havoc Pennington
@@ -20,822 +20,281 @@
*/
#include "theme.h"
-#include "api.h"
#include "util.h"
+#include <string.h>
-typedef struct _DefaultFrameData DefaultFrameData;
-typedef struct _DefaultScreenData DefaultScreenData;
-typedef struct _DefaultFrameGeometry DefaultFrameGeometry;
-
-struct _DefaultFrameGeometry
-{
- /* We recalculate this every time, to save RAM */
- int left_width;
- int right_width;
- int top_height;
- int bottom_height;
-
- MetaRectangle close_rect;
- MetaRectangle max_rect;
- MetaRectangle min_rect;
- MetaRectangle spacer_rect;
- MetaRectangle menu_rect;
- MetaRectangle title_rect;
-};
-
-struct _DefaultFrameData
-{
- PangoLayout *layout;
- int layout_height;
-};
-
-struct _DefaultScreenData
-{
- GC text_gc;
- GC fg_gc;
- GC light_gc;
- GC dark_gc;
- GC black_gc;
- GC selected_gc;
- GC selected_text_gc;
- GC active_gc;
- GC prelight_gc;
-};
-
-/* FIXME store this on the screen */
-static DefaultScreenData *screen_data = NULL;
-
-static gpointer
-default_acquire_frame (MetaFrameInfo *info)
-{
- DefaultFrameData *d;
- PangoFontDescription *desc;
- XGCValues vals;
-
- if (screen_data == NULL)
- {
- PangoColor color;
-
- screen_data = g_new (DefaultScreenData, 1);
-
- vals.foreground = meta_get_x_pixel (info->screen,
- &info->colors->fg[META_STATE_NORMAL]);
-
- screen_data->text_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
- screen_data->fg_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
-
- vals.foreground = meta_get_x_pixel (info->screen,
- &info->colors->light[META_STATE_NORMAL]);
- screen_data->light_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
-
- vals.foreground = meta_get_x_pixel (info->screen,
- &info->colors->dark[META_STATE_NORMAL]);
- screen_data->dark_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
-
- vals.foreground = meta_get_x_pixel (info->screen,
- &info->colors->bg[META_STATE_SELECTED]);
- screen_data->selected_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
- vals.foreground = meta_get_x_pixel (info->screen,
- &info->colors->fg[META_STATE_SELECTED]);
- screen_data->selected_text_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
-
- vals.foreground = meta_get_x_pixel (info->screen,
- &info->colors->bg[META_STATE_ACTIVE]);
- screen_data->active_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
-
- vals.foreground = meta_get_x_pixel (info->screen,
- &info->colors->bg[META_STATE_PRELIGHT]);
- screen_data->prelight_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
-
-
- color.red = color.green = color.blue = 0;
- vals.foreground = meta_get_x_pixel (info->screen,
- &color);
- screen_data->black_gc = XCreateGC (info->display,
- RootWindowOfScreen (info->screen),
- GCForeground,
- &vals);
- }
-
- d = g_new (DefaultFrameData, 1);
-
- desc = pango_font_description_from_string ("Sans 12");
- d->layout = pango_layout_new (meta_get_pango_context (info->screen,
- desc));
- pango_font_description_free (desc);
-
- d->layout_height = 0;
-
- return d;
-}
-
-static void
-default_release_frame (MetaFrameInfo *info,
- gpointer frame_data)
-{
- DefaultFrameData *d;
-
- d = frame_data;
-
- if (d->layout)
- g_object_unref (G_OBJECT (d->layout));
-
- g_free (d);
-}
-
-#define ABOVE_TITLE_PAD 4
-#define BELOW_TITLE_PAD 3
-#define RIGHT_TITLE_PAD 4
-#define LEFT_TITLE_PAD 3
-#define VERTICAL_TEXT_PAD 2
-#define HORIZONTAL_TEXT_PAD 2
-#define LEFT_WIDTH 6
-#define RIGHT_WIDTH 6
-#define BOTTOM_HEIGHT 7
-#define SPACER_SPACING 3
-#define SPACER_WIDTH 2
-#define SPACER_HEIGHT 10
-#define BUTTON_WIDTH 14
-#define BUTTON_HEIGHT 14
-#define BUTTON_PAD 1
-#define INNER_BUTTON_PAD 3
+/* fill_gradient routine from GNOME background-properties, CVS says
+ * Michael Fulbright checked it in, Copyright 1998 Red Hat Inc.
+ */
static void
-calc_geometry (MetaFrameInfo *info,
- DefaultFrameData *d,
- DefaultFrameGeometry *fgeom)
+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 x;
- int button_y;
- int title_right_edge;
- gboolean shaded;
-
- shaded = (info->flags & META_FRAME_SHADED) != 0;
-
- fgeom->top_height = MAX (d->layout_height + VERTICAL_TEXT_PAD * 2 + ABOVE_TITLE_PAD + BELOW_TITLE_PAD,
- BUTTON_HEIGHT + BUTTON_PAD * 2);
-
- fgeom->left_width = LEFT_WIDTH;
- fgeom->right_width = RIGHT_WIDTH;
-
- if (shaded)
- fgeom->bottom_height = 0;
- else
- fgeom->bottom_height = BOTTOM_HEIGHT;
-
- x = info->width - fgeom->right_width;
- button_y = (fgeom->top_height - BUTTON_HEIGHT) / 2;
-
- if (info->flags & META_FRAME_ALLOWS_DELETE)
- {
- fgeom->close_rect.x = x - BUTTON_PAD - BUTTON_WIDTH;
- fgeom->close_rect.y = button_y;
- fgeom->close_rect.width = BUTTON_WIDTH;
- fgeom->close_rect.height = BUTTON_HEIGHT;
-
- x = fgeom->close_rect.x;
- }
- else
+ 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)
{
- fgeom->close_rect.x = 0;
- fgeom->close_rect.y = 0;
- fgeom->close_rect.width = 0;
- fgeom->close_rect.height = 0;
- }
-
- if (info->flags & META_FRAME_ALLOWS_MAXIMIZE)
- {
- fgeom->max_rect.x = x - BUTTON_PAD - BUTTON_WIDTH;
- fgeom->max_rect.y = button_y;
- fgeom->max_rect.width = BUTTON_WIDTH;
- fgeom->max_rect.height = BUTTON_HEIGHT;
-
- x = fgeom->max_rect.x;
- }
- else
- {
- fgeom->max_rect.x = 0;
- fgeom->max_rect.y = 0;
- fgeom->max_rect.width = 0;
- fgeom->max_rect.height = 0;
+ 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;
+ }
}
- if (info->flags & META_FRAME_ALLOWS_ICONIFY)
- {
- fgeom->min_rect.x = x - BUTTON_PAD - BUTTON_WIDTH;
- fgeom->min_rect.y = button_y;
- fgeom->min_rect.width = BUTTON_WIDTH;
- fgeom->min_rect.height = BUTTON_HEIGHT;
-
- x = fgeom->min_rect.x;
- }
- else
+ for (i = 0; i < h; i++)
{
- fgeom->min_rect.x = 0;
- fgeom->min_rect.y = 0;
- fgeom->min_rect.width = 0;
- fgeom->min_rect.height = 0;
+ 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);
+}
- if (fgeom->close_rect.width > 0 ||
- fgeom->max_rect.width > 0 ||
- fgeom->min_rect.width > 0)
- {
- fgeom->spacer_rect.x = x - SPACER_SPACING - SPACER_WIDTH;
- fgeom->spacer_rect.y = (fgeom->top_height - SPACER_HEIGHT) / 2;
- fgeom->spacer_rect.width = SPACER_WIDTH;
- fgeom->spacer_rect.height = SPACER_HEIGHT;
+typedef struct _CachedGradient CachedGradient;
- x = fgeom->spacer_rect.x;
- }
- else
- {
- fgeom->spacer_rect.x = 0;
- fgeom->spacer_rect.y = 0;
- fgeom->spacer_rect.width = 0;
- fgeom->spacer_rect.height = 0;
- }
+struct _CachedGradient
+{
+ MetaGradientType type;
+ GdkColor color_one;
+ GdkColor color_two;
+ int width;
+ int height;
+ GdkPixbuf *pixbuf;
+ int access_serial;
+};
- title_right_edge = x - RIGHT_TITLE_PAD;
+static GHashTable *gradient_cache = NULL;
+static int access_counter = 0;
+static int cache_size = 0;
- /* Now x changes to be position from the left */
- x = fgeom->left_width;
-
- if (info->flags & META_FRAME_ALLOWS_MENU)
- {
- fgeom->menu_rect.x = x + BUTTON_PAD;
- fgeom->menu_rect.y = button_y;
- fgeom->menu_rect.width = BUTTON_WIDTH;
- fgeom->menu_rect.height = BUTTON_HEIGHT;
+#define GRADIENT_SIZE(g) ((g)->width * (g)->height * 4)
- x = fgeom->menu_rect.x + fgeom->menu_rect.width;
- }
- else
- {
- fgeom->menu_rect.x = 0;
- fgeom->menu_rect.y = 0;
- fgeom->menu_rect.width = 0;
- fgeom->menu_rect.height = 0;
- }
-
- fgeom->title_rect.x = x + LEFT_TITLE_PAD;
- fgeom->title_rect.y = ABOVE_TITLE_PAD;
- fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x;
- fgeom->title_rect.height = fgeom->top_height - ABOVE_TITLE_PAD - BELOW_TITLE_PAD;
+#define MAX_CACHE_SIZE (1024 * 128) /* 128k */
- if (fgeom->title_rect.width < 0)
- fgeom->title_rect.width = 0;
-}
-
-static void
-default_fill_frame_geometry (MetaFrameInfo *info,
- MetaFrameGeometry *geom,
- gpointer frame_data)
+static guint
+cached_gradient_hash (gconstpointer value)
{
- DefaultFrameData *d;
- PangoRectangle rect;
- DefaultFrameGeometry fgeom;
-
- d = frame_data;
-
- if (info->title)
- pango_layout_set_text (d->layout, info->title, -1);
- else
- pango_layout_set_text (d->layout, " ", -1);
-
- pango_layout_get_pixel_extents (d->layout, NULL, &rect);
-
- d->layout_height = rect.height;
+ /* 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);
- calc_geometry (info, d, &fgeom);
- geom->top_height = fgeom.top_height;
- geom->left_width = fgeom.left_width;
- geom->right_width = fgeom.right_width;
- geom->bottom_height = fgeom.bottom_height;
+ hash ^= gradient->width << 22;
+ hash ^= gradient->height;
+ hash ^= gradient->type << 15;
- geom->background_pixel = meta_get_x_pixel (info->screen,
- &info->colors->bg[META_STATE_NORMAL]);
+ return hash;
}
-static void
-draw_vline (MetaFrameInfo *info,
- Drawable drawable,
- GC light_gc,
- GC dark_gc,
- int y1,
- int y2,
- int x)
+static gboolean
+cached_gradient_equal (gconstpointer value_a,
+ gconstpointer value_b)
{
- int thickness_light;
- int thickness_dark;
- int i;
-
- /* From GTK+ */
-
- thickness_light = 1;
- thickness_dark = 1;
-
- for (i = 0; i < thickness_dark; i++)
- {
- XDrawLine (info->display, drawable, light_gc,
- x + i, y2 - i - 1, x + i, y2);
- XDrawLine (info->display, drawable, dark_gc,
- x + i, y1, x + i, y2 - i - 1);
- }
+ const CachedGradient *gradient_a = value_a;
+ const CachedGradient *gradient_b = value_b;
- x += thickness_dark;
- for (i = 0; i < thickness_light; i++)
- {
- XDrawLine (info->display, drawable, dark_gc,
- x + i, y1, x + i, y1 + thickness_light - i);
- XDrawLine (info->display, drawable, light_gc,
- x + i, y1 + thickness_light - i, x + i, y2);
- }
+ 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
-draw_varrow (MetaFrameInfo *info,
- Drawable drawable,
- GC gc,
- gboolean down,
- gint x,
- gint y,
- gint width,
- gint height)
+hash_listify (gpointer key, gpointer value, gpointer data)
{
- gint steps, extra;
- gint y_start, y_increment;
- gint i;
+ GSList **list = data;
- /* From GTK+ */
+ if (key != value)
+ meta_bug ("Gradient cache got munged (value was overwritten)\n");
- width = width + width % 2 - 1; /* Force odd */
-
- steps = 1 + width / 2;
+ *list = g_slist_prepend (*list, value);
+}
- extra = height - steps;
+/* 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 (down)
- {
- y_start = y;
- y_increment = 1;
- }
+ if (gradient_a->access_serial < gradient_b->access_serial)
+ return -1;
+ else if (gradient_a->access_serial > gradient_b->access_serial)
+ return 1;
else
- {
- y_start = y + height - 1;
- y_increment = -1;
- }
-
- for (i = 0; i < extra; i++)
- {
- XDrawLine (info->display, drawable,
- gc,
- x, y_start + i * y_increment,
- x + width - 1, y_start + i * y_increment);
- }
- for (; i < height; i++)
- {
- XDrawLine (info->display, drawable,
- gc,
- x + (i - extra), y_start + i * y_increment,
- x + width - (i - extra) - 1, y_start + i * y_increment);
- }
+ return 0;
}
static void
-set_clip (Display *display, GC gc, MetaRectangle *rect)
+expire_some_old_gradients (void)
{
- if (rect)
- {
- XRectangle xrect;
+ GSList *all_gradients;
+ GSList *tmp;
+
+ all_gradients = NULL;
- xrect.x = rect->x;
- xrect.y = rect->y;
- xrect.width = rect->width;
- xrect.height = rect->height;
+ g_hash_table_foreach (gradient_cache, hash_listify, &all_gradients);
- XSetClipRectangles (display, gc, 0, 0,
- &xrect, 1, YXBanded);
- }
- else
- {
- XSetClipMask (display, gc, None);
- }
-}
+ all_gradients = g_slist_sort (all_gradients, gradient_lru_compare);
-static MetaRectangle*
-control_rect (MetaFrameControl control,
- DefaultFrameGeometry *fgeom)
-{
- MetaRectangle *rect;
-
- rect = NULL;
- switch (control)
+ tmp = all_gradients;
+ while (tmp != NULL)
{
- case META_FRAME_CONTROL_TITLE:
- rect = &fgeom->title_rect;
- break;
- case META_FRAME_CONTROL_DELETE:
- rect = &fgeom->close_rect;
- break;
- case META_FRAME_CONTROL_MENU:
- rect = &fgeom->menu_rect;
- break;
- case META_FRAME_CONTROL_ICONIFY:
- rect = &fgeom->min_rect;
- break;
- case META_FRAME_CONTROL_MAXIMIZE:
- rect = &fgeom->max_rect;
- break;
- case META_FRAME_CONTROL_RESIZE_SE:
- break;
- case META_FRAME_CONTROL_RESIZE_S:
- break;
- case META_FRAME_CONTROL_RESIZE_SW:
- break;
- case META_FRAME_CONTROL_RESIZE_N:
- break;
- case META_FRAME_CONTROL_RESIZE_NE:
- break;
- case META_FRAME_CONTROL_RESIZE_NW:
- break;
- case META_FRAME_CONTROL_RESIZE_W:
- break;
- case META_FRAME_CONTROL_RESIZE_E:
- break;
- case META_FRAME_CONTROL_NONE:
- break;
- }
+ CachedGradient *gradient = tmp->data;
+
+ if (cache_size < MAX_CACHE_SIZE)
+ break;
- return rect;
-}
+ 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);
-static void
-draw_current_control_bg (MetaFrameInfo *info,
- DefaultFrameGeometry *fgeom)
-{
- int xoff, yoff;
- MetaRectangle *rect;
-
- xoff = info->xoffset;
- yoff = info->yoffset;
+ g_hash_table_remove (gradient_cache, gradient);
- rect = control_rect (info->current_control, fgeom);
+ g_object_unref (G_OBJECT (gradient->pixbuf));
+ g_free (gradient);
+
+ tmp = tmp->next;
+ }
- if (rect == NULL)
- return;
+ g_slist_free (all_gradients);
- if (info->current_control == META_FRAME_CONTROL_TITLE)
- return;
-
- switch (info->current_control_state)
- {
- /* FIXME turn this off after testing */
- case META_STATE_PRELIGHT:
- XFillRectangle (info->display,
- info->drawable,
- screen_data->prelight_gc,
- xoff + rect->x,
- yoff + rect->y,
- rect->width, rect->height);
- break;
-
- case META_STATE_ACTIVE:
- XFillRectangle (info->display,
- info->drawable,
- screen_data->active_gc,
- xoff + rect->x,
- yoff + rect->y,
- rect->width, rect->height);
- break;
-
- default:
- break;
- }
+ 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));
}
-static void
-default_expose_frame (MetaFrameInfo *info,
- int x, int y,
- int width, int height,
- gpointer frame_data)
+GdkPixbuf*
+meta_theme_get_gradient (MetaGradientType type,
+ const GdkColor *color_one,
+ const GdkColor *color_two,
+ int width,
+ int height)
{
- DefaultFrameData *d;
- XGCValues vals;
- int xoff, yoff;
- DefaultFrameGeometry fgeom;
+ CachedGradient gradient;
+ CachedGradient *cached;
+ GdkPixbuf *retval;
- d = frame_data;
-
- calc_geometry (info, d, &fgeom);
+ 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 / 255, color_one->green / 255, color_one->blue / 255,
+ color_two->red / 255, color_two->green / 255, color_two->blue / 255,
+ width, height);
- xoff = info->xoffset;
- yoff = info->yoffset;
-
- /* Black line around outside to give definition */
- XDrawRectangle (info->display,
- info->drawable,
- screen_data->black_gc,
- xoff, yoff,
- info->width - 1,
- info->height - 1);
-
- /* Light GC on top/left edges */
- XDrawLine (info->display,
- info->drawable,
- screen_data->light_gc,
- xoff + 1, yoff + 1,
- xoff + 1, yoff + info->height - 2);
- XDrawLine (info->display,
- info->drawable,
- screen_data->light_gc,
- xoff + 1, yoff + 1,
- xoff + info->width - 2, yoff + 1);
-
- /* Dark GC on bottom/right edges */
- XDrawLine (info->display,
- info->drawable,
- screen_data->dark_gc,
- xoff + info->width - 2, yoff + 1,
- xoff + info->width - 2, yoff + info->height - 2);
- XDrawLine (info->display,
- info->drawable,
- screen_data->dark_gc,
- xoff + 1, yoff + info->height - 2,
- xoff + info->width - 2, yoff + info->height - 2);
-
- if (info->flags & META_FRAME_HAS_FOCUS)
+ if (gradient_cache == NULL)
{
- /* Black line around inside while we have focus */
- XDrawRectangle (info->display,
- info->drawable,
- screen_data->black_gc,
- xoff + fgeom.left_width - 1,
- yoff + fgeom.top_height - 1,
- info->width - fgeom.right_width - fgeom.left_width + 1,
- info->height - fgeom.bottom_height - fgeom.top_height + 1);
+ gradient_cache = g_hash_table_new (cached_gradient_hash,
+ cached_gradient_equal);
}
- draw_current_control_bg (info, &fgeom);
+ 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;
- if (y < fgeom.top_height &&
- fgeom.title_rect.width > 0 && fgeom.title_rect.height > 0)
- {
- int layout_y;
- MetaRectangle clip;
- GC layout_gc;
-
- /* center vertically */
- layout_y = fgeom.title_rect.y +
- (fgeom.title_rect.height - d->layout_height) / 2;
-
- clip = fgeom.title_rect;
- clip.x += xoff;
- clip.y += yoff;
- clip.width -= HORIZONTAL_TEXT_PAD;
-
- layout_gc = screen_data->text_gc;
-
- if (info->flags & META_FRAME_HAS_FOCUS)
- {
- layout_gc = screen_data->selected_text_gc;
-
- /* Draw blue background */
- XFillRectangle (info->display,
- info->drawable,
- screen_data->selected_gc,
- xoff + fgeom.title_rect.x,
- yoff + fgeom.title_rect.y,
- fgeom.title_rect.width,
- fgeom.title_rect.height);
- }
-
- set_clip (info->display, layout_gc, &clip);
-
- pango_x_render_layout (info->display,
- info->drawable,
- layout_gc,
- d->layout,
- xoff + fgeom.title_rect.x + HORIZONTAL_TEXT_PAD,
- yoff + layout_y);
- set_clip (info->display, screen_data->text_gc, NULL);
- }
+ cached = g_hash_table_lookup (gradient_cache, &gradient);
- if (fgeom.close_rect.width > 0 && fgeom.close_rect.height > 0)
+ if (cached)
{
- XDrawLine (info->display,
- info->drawable,
- screen_data->fg_gc,
- xoff + fgeom.close_rect.x + INNER_BUTTON_PAD,
- yoff + fgeom.close_rect.y + INNER_BUTTON_PAD,
- xoff + fgeom.close_rect.x + fgeom.close_rect.width - INNER_BUTTON_PAD,
- yoff + fgeom.close_rect.y + fgeom.close_rect.height - INNER_BUTTON_PAD);
-
-
- XDrawLine (info->display,
- info->drawable,
- screen_data->fg_gc,
- xoff + fgeom.close_rect.x + INNER_BUTTON_PAD,
- yoff + fgeom.close_rect.y + fgeom.close_rect.height - INNER_BUTTON_PAD,
- xoff + fgeom.close_rect.x + fgeom.close_rect.width - INNER_BUTTON_PAD,
- yoff + fgeom.close_rect.y + INNER_BUTTON_PAD);
+ 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 (fgeom.max_rect.width > 0 && fgeom.max_rect.height > 0)
- {
- XDrawRectangle (info->display,
- info->drawable,
- screen_data->fg_gc,
- xoff + fgeom.max_rect.x + INNER_BUTTON_PAD,
- yoff + fgeom.max_rect.y + INNER_BUTTON_PAD,
- fgeom.max_rect.width - INNER_BUTTON_PAD * 2,
- fgeom.max_rect.height - INNER_BUTTON_PAD * 2);
-
- vals.line_width = 3;
- XChangeGC (info->display,
- screen_data->fg_gc,
- GCLineWidth,
- &vals);
-
- XDrawLine (info->display,
- info->drawable,
- screen_data->fg_gc,
- xoff + fgeom.max_rect.x + INNER_BUTTON_PAD,
- yoff + fgeom.max_rect.y + INNER_BUTTON_PAD + vals.line_width / 2,
- xoff + fgeom.max_rect.x + fgeom.max_rect.width - INNER_BUTTON_PAD,
- yoff + fgeom.max_rect.y + INNER_BUTTON_PAD + vals.line_width / 2);
-
- vals.line_width = 0;
- XChangeGC (info->display,
- screen_data->fg_gc,
- GCLineWidth,
- &vals);
- }
-
- if (fgeom.min_rect.width > 0 && fgeom.min_rect.height > 0)
- {
- vals.line_width = 3;
- XChangeGC (info->display,
- screen_data->fg_gc,
- GCLineWidth,
- &vals);
-
- XDrawLine (info->display,
- info->drawable,
- screen_data->fg_gc,
- xoff + fgeom.min_rect.x + INNER_BUTTON_PAD,
- yoff + fgeom.min_rect.y + fgeom.min_rect.height - INNER_BUTTON_PAD - vals.line_width / 2,
- xoff + fgeom.min_rect.x + fgeom.min_rect.width - INNER_BUTTON_PAD,
- yoff + fgeom.min_rect.y + fgeom.min_rect.height - INNER_BUTTON_PAD - vals.line_width / 2);
-
- vals.line_width = 0;
- XChangeGC (info->display,
- screen_data->fg_gc,
- GCLineWidth,
- &vals);
- }
-
- if (fgeom.spacer_rect.width > 0 && fgeom.spacer_rect.height > 0)
- {
- draw_vline (info, info->drawable,
- screen_data->light_gc,
- screen_data->dark_gc,
- yoff + fgeom.spacer_rect.y,
- yoff + fgeom.spacer_rect.y + fgeom.spacer_rect.height,
- xoff + fgeom.spacer_rect.x);
- }
+ gradient.pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+ gradient.width, gradient.height);
- if (fgeom.menu_rect.width > 0 && fgeom.menu_rect.height > 0)
- {
- int x, y;
- x = fgeom.menu_rect.x;
- y = fgeom.menu_rect.y;
- x += (fgeom.menu_rect.width - 7) / 2;
- y += (fgeom.menu_rect.height - 5) / 2;
-
- draw_varrow (info, info->drawable, screen_data->fg_gc, TRUE,
- xoff + x, yoff + y, 7, 5);
- }
-}
+ fill_gradient (gradient.pixbuf,
+ &gradient.color_one,
+ &gradient.color_two,
+ type == META_GRADIENT_VERTICAL ? TRUE : FALSE,
+ gradient.width,
+ gradient.height,
+ 0, 0);
-#define POINT_IN_RECT(xcoord, ycoord, rect) \
- ((xcoord) >= (rect).x && \
- (xcoord) < ((rect).x + (rect).width) && \
- (ycoord) >= (rect).y && \
- (ycoord) < ((rect).y + (rect).height))
-
-#define RESIZE_EXTENDS 10
-static MetaFrameControl
-default_get_control (MetaFrameInfo *info,
- int x, int y,
- gpointer frame_data)
-{
- DefaultFrameData *d;
- DefaultFrameGeometry fgeom;
+ cached = g_new (CachedGradient, 1);
+ *cached = gradient;
- d = frame_data;
+ g_hash_table_insert (gradient_cache, cached, cached);
- calc_geometry (info, d, &fgeom);
+ 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);
- if (POINT_IN_RECT (x, y, fgeom.close_rect))
- return META_FRAME_CONTROL_DELETE;
-
- if (POINT_IN_RECT (x, y, fgeom.min_rect))
- return META_FRAME_CONTROL_ICONIFY;
-
- if (POINT_IN_RECT (x, y, fgeom.max_rect))
- return META_FRAME_CONTROL_MAXIMIZE;
+ cache_size += GRADIENT_SIZE (cached);
- if (POINT_IN_RECT (x, y, fgeom.menu_rect))
- return META_FRAME_CONTROL_MENU;
+ g_object_ref (G_OBJECT (cached->pixbuf)); /* to return to caller */
+ retval = cached->pixbuf;
- if (POINT_IN_RECT (x, y, fgeom.title_rect))
- return META_FRAME_CONTROL_TITLE;
+ if (cache_size > MAX_CACHE_SIZE)
+ expire_some_old_gradients (); /* may unref "cached->pixbuf" and free "cached" */
- if (y > (info->height - fgeom.bottom_height - RESIZE_EXTENDS) &&
- x > (info->width - fgeom.right_width - RESIZE_EXTENDS))
- return META_FRAME_CONTROL_RESIZE_SE;
-
- return META_FRAME_CONTROL_NONE;
+ return retval;
}
-static void
-default_get_control_rect (MetaFrameInfo *info,
- MetaFrameControl control,
- int *x, int *y,
- int *width, int *height,
- gpointer frame_data)
-{
- MetaRectangle *rect;
- DefaultFrameData *d;
- DefaultFrameGeometry fgeom;
-
- d = frame_data;
-
- calc_geometry (info, d, &fgeom);
-
- rect = control_rect (control, &fgeom);
-
- if (rect)
- {
- *x = rect->x;
- *y = rect->y;
- *width = rect->width;
- *height = rect->height;
- }
- else
- {
- *x = *y = *width = *height = 0;
- }
-}
-
-/* FIXME add this to engine vtable */
-static void
-default_release_screen (Screen *screen)
-{
- if (screen_data)
- {
- XFreeGC (DisplayOfScreen (screen), screen_data->text_gc);
- XFreeGC (DisplayOfScreen (screen), screen_data->fg_gc);
- XFreeGC (DisplayOfScreen (screen), screen_data->selected_gc);
- XFreeGC (DisplayOfScreen (screen), screen_data->selected_text_gc);
- XFreeGC (DisplayOfScreen (screen), screen_data->black_gc);
- XFreeGC (DisplayOfScreen (screen), screen_data->light_gc);
- XFreeGC (DisplayOfScreen (screen), screen_data->dark_gc);
- XFreeGC (DisplayOfScreen (screen), screen_data->active_gc);
- XFreeGC (DisplayOfScreen (screen), screen_data->prelight_gc);
- }
-}
-
-MetaThemeEngine meta_default_engine = {
- NULL,
- default_acquire_frame,
- default_release_frame,
- default_fill_frame_geometry,
- default_expose_frame,
- default_get_control,
- default_get_control_rect
-};
diff --git a/src/theme.h b/src/theme.h
index 37c46ab..ee27367 100644
--- a/src/theme.h
+++ b/src/theme.h
@@ -1,4 +1,4 @@
-/* Metacity Theme Engine Header */
+/* Metacity Theme Rendering */
/*
* Copyright (C) 2001 Havoc Pennington
@@ -22,118 +22,22 @@
#ifndef META_THEME_H
#define META_THEME_H
-/* don't add any internal headers here; theme.h is an installed/public
- * header.
- */
-#include <X11/Xlib.h>
-#include <glib.h>
-#include "api.h"
-
-typedef struct _MetaFrameInfo MetaFrameInfo;
-typedef struct _MetaFrameGeometry MetaFrameGeometry;
-typedef struct _MetaThemeEngine MetaThemeEngine;
+#include "frames.h"
-typedef enum
-{
- META_FRAME_ALLOWS_DELETE = 1 << 0,
- META_FRAME_ALLOWS_MENU = 1 << 1,
- META_FRAME_ALLOWS_ICONIFY = 1 << 2,
- META_FRAME_ALLOWS_MAXIMIZE = 1 << 3,
- META_FRAME_ALLOWS_RESIZE = 1 << 4,
- META_FRAME_TRANSIENT = 1 << 5,
- META_FRAME_HAS_FOCUS = 1 << 6,
- META_FRAME_SHADED = 1 << 7,
- META_FRAME_STUCK = 1 << 8
-} MetaFrameFlags;
+/* theme.[hc] is basically responsible for drawing parts of the UI using
+ * theme data
+ */
typedef enum
{
- META_FRAME_CONTROL_NONE,
- META_FRAME_CONTROL_TITLE,
- META_FRAME_CONTROL_DELETE,
- META_FRAME_CONTROL_MENU,
- META_FRAME_CONTROL_ICONIFY,
- META_FRAME_CONTROL_MAXIMIZE,
- META_FRAME_CONTROL_RESIZE_SE,
- META_FRAME_CONTROL_RESIZE_S,
- META_FRAME_CONTROL_RESIZE_SW,
- META_FRAME_CONTROL_RESIZE_N,
- META_FRAME_CONTROL_RESIZE_NE,
- META_FRAME_CONTROL_RESIZE_NW,
- META_FRAME_CONTROL_RESIZE_W,
- META_FRAME_CONTROL_RESIZE_E
-} MetaFrameControl;
-
-struct _MetaFrameInfo
-{
- /* These are read-only to engines */
- MetaFrameFlags flags;
- Window drawable; /* == None except in expose */
- int xoffset, yoffset; /* add to frame coords to get drawable coords */
- Display *display;
- Screen *screen;
- Visual *visual;
- int depth;
-
- const char *title;
-
- const MetaUIColors *colors;
-
- MetaFrameControl current_control;
- MetaUIState current_control_state;
-
- /* Equal to child size before fill_frame_geometry
- * has been called
- */
- int width;
- int height;
-};
-
-struct _MetaFrameGeometry
-{
- /* border sizes (space between frame and child) */
- int left_width;
- int right_width;
- int top_height;
- int bottom_height;
-
- /* background color */
- unsigned long background_pixel;
-
- Pixmap shape_mask;
- /* FIXME shape region? */
-};
-
-struct _MetaThemeEngine
-{
- void (* unload_engine) (void);
-
- /* returns frame_data to use */
- gpointer (* acquire_frame) (MetaFrameInfo *info);
- /* should free frame_data */
- void (* release_frame) (MetaFrameInfo *info,
- gpointer frame_data);
-
- void (* fill_frame_geometry) (MetaFrameInfo *info,
- MetaFrameGeometry *geom,
- gpointer frame_data);
-
- void (* expose_frame) (MetaFrameInfo *info,
- int x, int y,
- int width, int height,
- gpointer frame_data);
-
- MetaFrameControl (* get_control) (MetaFrameInfo *info,
- int x, int y,
- gpointer frame_data);
-
- void (* get_control_rect) (MetaFrameInfo *info,
- MetaFrameControl control,
- int *x, int *y,
- int *width, int *height,
- gpointer frame_data);
-};
-
-extern MetaThemeEngine meta_default_engine;
+ META_GRADIENT_VERTICAL,
+ META_GRADIENT_HORIZONTAL
+} MetaGradientType;
+
+GdkPixbuf* meta_theme_get_gradient (MetaGradientType type,
+ const GdkColor *color_one,
+ const GdkColor *color_two,
+ int width,
+ int height);
#endif
diff --git a/src/util.c b/src/util.c
index fbf36b6..40673ac 100644
--- a/src/util.c
+++ b/src/util.c
@@ -175,6 +175,9 @@ topic_name (MetaDebugTopic topic)
case META_DEBUG_FOCUS:
return "FOCUS";
break;
+ case META_DEBUG_GRADIENT_CACHE:
+ return "GRADIENT_CACHE";
+ break;
}
return "Window manager";
diff --git a/src/util.h b/src/util.h
index cd71129..1e324cb 100644
--- a/src/util.h
+++ b/src/util.h
@@ -45,7 +45,8 @@ void meta_fatal (const char *format,
typedef enum
{
- META_DEBUG_FOCUS
+ META_DEBUG_FOCUS,
+ META_DEBUG_GRADIENT_CACHE
} MetaDebugTopic;