static GList *desktop_names;
static GtkListStore *theme_store;
+static RrFont *active_window_font, *inactive_window_font, *menu_title_font, *menu_item_font, *osd_font;
+
+static gchar *titlelayout;
+
static void on_desktop_names_cell_edited(GtkCellRendererText *cell,
const gchar *path_string,
const gchar *new_text,
static void on_theme_names_selection_changed(GtkTreeSelection *sel,
gpointer data);
+static void handlers_update_theme_previews();
void setup_behavior_tab()
GList *it, *next;
gint i;
+ RrFont *active, *inactive, *menu_t, *menu_i, *osd;
+
name = tree_get_string("theme/name", "TheBear");
for (it = themes; it; it = g_list_next(it))
gtk_list_store_append(theme_store, &iter);
gtk_list_store_set(theme_store, &iter,
0, it->data,
- 1, TRUE,
+ 1, NULL,
-1);
if(!strcmp(name, it->data)) {
mapping = TRUE;
/* widget setup */
- theme_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN);
+ theme_store = gtk_list_store_new(2, G_TYPE_STRING, GDK_TYPE_PIXBUF);
gtk_tree_view_set_model(GTK_TREE_VIEW(w), GTK_TREE_MODEL(theme_store));
g_object_unref (theme_store);
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)),
GTK_SELECTION_SINGLE);
+ /* text column for the names */
render = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes
("Name", render, "text", 0, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
+ /* pixbuf column, for theme previews */
+ render = gtk_cell_renderer_pixbuf_new();
+ g_object_set(render, "xalign", 1.0);
+ column = gtk_tree_view_column_new_with_attributes
+ ("Preview", render, "pixbuf", 1, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
+
+
/* setup the selection handler */
select = gtk_tree_view_get_selection(GTK_TREE_VIEW (w));
gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
reset_theme_names(w);
+ handlers_update_theme_previews();
+
mapping = FALSE;
}
mapping = TRUE;
layout = tree_get_string("theme/titleLayout", "NLIMC");
+ titlelayout = g_strdup(layout);
gtk_entry_set_text(GTK_ENTRY(w), layout);
g_free(layout);
mapping = FALSE;
}
-static void setup_font(GtkWidget *w, const gchar *place)
+static RrFont *setup_font(GtkWidget *w, const gchar *place)
{
+ RrFont *font;
gchar *fontstring, *node;
gchar *name, **names;
gchar *size;
gchar *weight;
gchar *slant;
+ RrFontWeight rr_weight = RR_FONTWEIGHT_NORMAL;
+ RrFontSlant rr_slant = RR_FONTSLANT_NORMAL;
+
mapping = TRUE;
node = g_strdup_printf("theme/font:place=%s/name", place);
fontstring = g_strdup_printf("%s %s %s %s", name, weight, slant, size);
gtk_font_button_set_font_name(GTK_FONT_BUTTON(w), fontstring);
+
+ if (!g_ascii_strcasecmp(weight, "Bold")) rr_weight = RR_FONTWEIGHT_BOLD;
+ if (!g_ascii_strcasecmp(slant, "Italic")) rr_slant = RR_FONTSLANT_ITALIC;
+ if (!g_ascii_strcasecmp(slant, "Oblique")) rr_slant = RR_FONTSLANT_OBLIQUE;
+
+ font = RrFontOpen(rrinst, name, atoi(size), rr_weight, rr_slant);
g_free(fontstring);
g_free(slant);
g_free(weight);
g_free(name);
mapping = FALSE;
+
+ return font;
}
void setup_font_active(GtkWidget *w)
{
- setup_font(w, "ActiveWindow");
+ active_window_font = setup_font(w, "ActiveWindow");
}
void setup_font_inactive(GtkWidget *w)
{
- setup_font(w, "InactiveWindow");
+ inactive_window_font = setup_font(w, "InactiveWindow");
}
void setup_font_menu_header(GtkWidget *w)
{
- setup_font(w, "MenuHeader");
+ menu_title_font = setup_font(w, "MenuHeader");
}
void setup_font_menu_item(GtkWidget *w)
{
- setup_font(w, "MenuItem");
+ menu_item_font = setup_font(w, "MenuItem");
}
void setup_font_display(GtkWidget *w)
{
- setup_font(w, "OnScreenDisplay");
+ osd_font = setup_font(w, "OnScreenDisplay");
}
tree_set_bool("theme/keepBorder", b);
}
-static void on_font_set(GtkFontButton *w, const gchar *place)
+static RrFont *on_font_set(GtkFontButton *w, const gchar *place)
{
gchar *c;
gchar *font, *node;
const gchar *bold = NULL;
const gchar *italic = NULL;
+ RrFontWeight weight = RR_FONTWEIGHT_NORMAL;
+ RrFontSlant slant = RR_FONTSLANT_NORMAL;
+
if (mapping) return;
font = g_strdup(gtk_font_button_get_font_name(w));
tree_set_string(node, italic);
g_free(node);
+ if (!g_ascii_strcasecmp(bold, "Bold")) weight = RR_FONTWEIGHT_BOLD;
+ if (!g_ascii_strcasecmp(italic, "Italic")) slant = RR_FONTSLANT_ITALIC;
+ if (!g_ascii_strcasecmp(italic, "Oblique")) slant = RR_FONTSLANT_OBLIQUE;
+
+ return RrFontOpen(rrinst, font, atoi(size), weight, slant);
+
g_free(font);
+
}
void on_font_active_font_set(GtkFontButton *w, gpointer data)
{
- on_font_set(w, "ActiveWindow");
+ RrFontClose(active_window_font);
+ active_window_font = on_font_set(w, "ActiveWindow");
+ handlers_update_theme_previews();
}
void on_font_inactive_font_set(GtkFontButton *w, gpointer data)
{
- on_font_set(w, "InactiveWindow");
+ RrFontClose(inactive_window_font);
+ inactive_window_font = on_font_set(w, "InactiveWindow");
+ handlers_update_theme_previews();
}
void on_font_menu_header_font_set(GtkFontButton *w, gpointer data)
{
- on_font_set(w, "MenuHeader");
+ RrFontClose(menu_title_font);
+ menu_title_font = on_font_set(w, "MenuHeader");
+ handlers_update_theme_previews();
}
void on_font_menu_item_font_set(GtkFontButton *w, gpointer data)
{
- on_font_set(w, "MenuItem");
+ RrFontClose(menu_item_font);
+ menu_item_font = on_font_set(w, "MenuItem");
+ handlers_update_theme_previews();
}
void on_font_display_font_set(GtkFontButton *w, gpointer data)
{
- on_font_set(w, "OnScreenDisplay");
+ RrFontClose(osd_font);
+ osd_font = on_font_set(w, "OnScreenDisplay");
+ handlers_update_theme_previews();
}
void on_focus_mouse_toggled(GtkToggleButton *w, gpointer data)
gtk_entry_set_text(w, layout);
tree_set_string("theme/titleLayout", layout);
+
+ g_free(titlelayout);
+ titlelayout = g_strdup(layout);
g_free(layout);
+
+
}
static void set_desktop_names()
g_free(name);
}
}
+
+
+static gboolean update_theme_preview_iterate(gpointer data)
+{
+ GtkListStore *ls = data;
+ static GtkTreeIter iter;
+ static gboolean restart = TRUE;
+ gchar *name;
+
+ if (restart) {
+ if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ls), &iter))
+ return;
+ restart = FALSE;
+ } else {
+ if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(ls), &iter)) {
+ restart = TRUE;
+ return;
+ }
+ }
+
+ gtk_tree_model_get(GTK_TREE_MODEL(ls), &iter, 0, &name, -1);
+
+ gtk_list_store_set(GTK_LIST_STORE(ls), &iter, 1,
+ preview_theme(name, titlelayout, active_window_font,
+ inactive_window_font, menu_title_font,
+ menu_item_font, osd_font),
+ -1);
+}
+
+static void handlers_update_theme_previews()
+{
+ g_idle_remove_by_data(theme_store);
+ g_idle_add_full(G_PRIORITY_LOW, update_theme_preview_iterate,
+ theme_store, NULL);
+}
--- /dev/null
+#include "theme.h"
+#include "main.h"
+#include "tree.h"
+
+#include <string.h>
+
+#include <openbox/theme.h>
+
+#define PADDING 2 /* openbox does it :/ */
+
+static void theme_pixmap_paint(RrAppearance *a, gint w, gint h)
+{
+ Pixmap out = RrPaintPixmap(a, w, h);
+ if (out) XFreePixmap(RrDisplay(a->inst), out);
+}
+
+static guint32 rr_color_pixel(const RrColor *c)
+{
+ return (guint32)((RrColorRed(c) << 24) | (RrColorGreen(c) << 16)
+ | (RrColorBlue(c) << 8) | 255);
+}
+
+/* XXX: Make this more general */
+static GdkPixbuf* preview_menu(RrTheme *theme)
+{
+ RrAppearance *title;
+ RrAppearance *title_text;
+
+ RrAppearance *menu;
+ RrAppearance *background;
+
+ RrAppearance *normal;
+ RrAppearance *disabled;
+ RrAppearance *selected;
+ RrAppearance *bullet; /* for submenu */
+
+ GdkPixmap *pixmap;
+ GdkPixbuf *pixbuf;
+
+ /* width and height of the whole menu */
+ gint width, height;
+ gint x, y;
+ gint title_h;
+ gint tw, th;
+ gint bw, bh;
+ gint unused;
+
+ /* set up appearances */
+ title = theme->a_menu_title;
+
+ title_text = theme->a_menu_text_title;
+ title_text->surface.parent = title;
+ title_text->texture[0].data.text.string = "menu";
+
+ normal = theme->a_menu_text_normal;
+ normal->texture[0].data.text.string = "normal";
+
+ disabled = theme->a_menu_text_disabled;
+ disabled->texture[0].data.text.string = "disabled";
+
+ selected = theme->a_menu_text_selected;
+ selected->texture[0].data.text.string = "selected";
+
+ bullet = theme->a_menu_bullet_normal;
+
+ /* determine window size */
+ RrMinSize(normal, &width, &th);
+ width += th + PADDING; /* make space for the bullet */
+ //height = th;
+
+ width += 2*theme->mbwidth + 2*PADDING;
+
+ /* get minimum title size */
+ RrMinSize(title, &tw, &title_h);
+
+ /* size of background behind each text line */
+ bw = width - 2*theme->mbwidth;
+ //title_h += 2*PADDING;
+ title_h = theme->menu_title_height;
+
+ RrMinSize(normal, &unused, &th);
+ bh = th + 2*PADDING;
+
+ height = title_h + 3*bh + 3*theme->mbwidth;
+
+ //height += 3*th + 3*theme->mbwidth + 5*PADDING;
+
+ /* set border */
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+ gdk_pixbuf_fill(pixbuf, rr_color_pixel(theme->menu_border_color));
+
+ /* draw title */
+ x = y = theme->mbwidth;
+ theme_pixmap_paint(title, bw, title_h);
+
+ /* draw title text */
+ title_text->surface.parentx = 0;
+ title_text->surface.parenty = 0;
+
+ theme_pixmap_paint(title_text, bw, title_h);
+
+ pixmap = gdk_pixmap_foreign_new(title_text->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, bw, title_h);
+
+ /* menu appears after title */
+ y += theme->mbwidth + title_h;
+
+ /* fill in menu appearance, used as the parent to every menu item's bg */
+ menu = theme->a_menu;
+ th = height - 3*theme->mbwidth - title_h;
+ theme_pixmap_paint(menu, bw, th);
+
+ pixmap = gdk_pixmap_foreign_new(menu->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, bw, th);
+
+ /* fill in background appearance, used as the parent to text items */
+ background = theme->a_menu_normal;
+ background->surface.parent = menu;
+ background->surface.parentx = 0;
+ background->surface.parenty = 0;
+
+ /* draw background for normal entry */
+ theme_pixmap_paint(background, bw, bh);
+ pixmap = gdk_pixmap_foreign_new(background->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, bw, bh);
+
+ /* draw normal entry */
+ normal->surface.parent = background;
+ normal->surface.parentx = PADDING;
+ normal->surface.parenty = PADDING;
+ x += PADDING;
+ y += PADDING;
+ RrMinSize(normal, &tw, &th);
+ theme_pixmap_paint(normal, tw, th);
+ pixmap = gdk_pixmap_foreign_new(normal->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, tw, th);
+
+ /* draw bullet */
+ RrMinSize(normal, &tw, &th);
+ bullet->surface.parent = background;
+ bullet->surface.parentx = bw - th;
+ bullet->surface.parenty = PADDING;
+ theme_pixmap_paint(bullet, th, th);
+ pixmap = gdk_pixmap_foreign_new(bullet->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, width - theme->mbwidth - th, y, th, th);
+
+ y += th + 2*PADDING;
+
+ /* draw background for disabled entry */
+ background->surface.parenty = bh;
+ theme_pixmap_paint(background, bw, bh);
+ pixmap = gdk_pixmap_foreign_new(background->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x - PADDING, y - PADDING, bw, bh);
+
+ /* draw disabled entry */
+ RrMinSize(disabled, &tw, &th);
+ disabled->surface.parent = background;
+ disabled->surface.parentx = PADDING;
+ disabled->surface.parenty = PADDING;
+ theme_pixmap_paint(disabled, tw, th);
+ pixmap = gdk_pixmap_foreign_new(disabled->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, tw, th);
+
+ y += th + 2*PADDING;
+
+ /* draw background for selected entry */
+ background = theme->a_menu_selected;
+ background->surface.parent = menu;
+ background->surface.parentx = 2*bh;
+
+ theme_pixmap_paint(background, bw, bh);
+ pixmap = gdk_pixmap_foreign_new(background->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x - PADDING, y - PADDING, bw, bh);
+
+ /* draw selected entry */
+ RrMinSize(selected, &tw, &th);
+ selected->surface.parent = background;
+ selected->surface.parentx = PADDING;
+ selected->surface.parenty = PADDING;
+ theme_pixmap_paint(selected, tw, th);
+ pixmap = gdk_pixmap_foreign_new(selected->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, tw, th);
+
+ return pixbuf;
+}
+
+static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, gboolean focus, gint width, gint height)
+{
+ RrAppearance *title;
+ RrAppearance *handle;
+ RrAppearance *a;
+
+ GdkPixmap *pixmap;
+ GdkPixbuf *pixbuf = NULL;
+ GdkPixbuf *scratch;
+
+ gint w, label_w, h, x, y;
+
+ const gchar *layout;
+
+ title = focus ? theme->a_focused_title : theme->a_unfocused_title;
+
+ /* set border */
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+ gdk_pixbuf_fill(pixbuf, rr_color_pixel(theme->menu_border_color));
+
+ /* title */
+ w = width - 2*theme->fbwidth;
+ h = theme->title_height;
+ theme_pixmap_paint(title, w, h);
+
+ x = y = theme->fbwidth;;
+ pixmap = gdk_pixmap_foreign_new(title->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, w, h);
+
+ /* calculate label width */
+ label_w = width - (theme->paddingx + theme->fbwidth + 1) * 2;
+
+ for (layout = titlelayout; *layout; layout++) {
+ switch (*layout) {
+ case 'N':
+ label_w -= theme->button_size + 2 + theme->paddingx + 1;
+ break;
+ case 'D':
+ case 'S':
+ case 'I':
+ case 'M':
+ case 'C':
+ label_w -= theme->button_size + theme->paddingx + 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ x = theme->paddingx + theme->fbwidth + 1;
+ y += theme->paddingy + 1;
+ for (layout = titlelayout; *layout; layout++) {
+ /* icon */
+ if (*layout == 'N') {
+ a = theme->a_icon;
+ /* set default icon */
+ a->texture[0].type = RR_TEXTURE_RGBA;
+ a->texture[0].data.rgba.width = 48;
+ a->texture[0].data.rgba.height = 48;
+ a->texture[0].data.rgba.data = theme->def_win_icon;
+
+ a->surface.parent = title;
+ a->surface.parentx = x;
+ a->surface.parenty = theme->paddingy;
+
+ w = h = theme->button_size + 2;
+
+ theme_pixmap_paint(a, w, h);
+ pixmap = gdk_pixmap_foreign_new(a->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y - 1, w, h);
+
+ x += theme->button_size + 2 + theme->paddingx + 1;
+ } else if (*layout == 'L') { /* label */
+ a = focus ? theme->a_focused_label : theme->a_unfocused_label;
+ a->texture[0].data.text.string = focus ? "active" : "inactive";
+
+ a->surface.parent = title;
+ a->surface.parentx = x;
+ a->surface.parenty = theme->paddingy;
+ w = label_w;
+ h = theme->label_height;
+
+ theme_pixmap_paint(a, w, h);
+ pixmap = gdk_pixmap_foreign_new(a->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y - 1, w, h);
+
+ x += w + theme->paddingx + 1;
+ } else {
+ /* buttons */
+ switch (*layout) {
+ case 'D':
+ a = focus ? theme->a_focused_unpressed_desk : theme->a_unfocused_unpressed_desk;
+ break;
+ case 'S':
+ a = focus ? theme->a_focused_unpressed_shade : theme->a_unfocused_unpressed_shade;
+ break;
+ case 'I':
+ a = focus ? theme->a_focused_unpressed_iconify : theme->a_unfocused_unpressed_iconify;
+ break;
+ case 'M':
+ a = focus ? theme->a_focused_unpressed_max : theme->a_unfocused_unpressed_max;
+ break;
+ case 'C':
+ a = focus ? theme->a_focused_unpressed_close : theme->a_unfocused_unpressed_close;
+ break;
+ default:
+ continue;
+ }
+
+ a->surface.parent = title;
+ a->surface.parentx = x;
+ a->surface.parenty = theme->paddingy + 1;
+
+ w = theme->button_size;
+ h = theme->button_size;
+
+ theme_pixmap_paint(a, w, h);
+ pixmap = gdk_pixmap_foreign_new(a->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, w, h);
+
+ x += theme->button_size + theme->paddingx + 1;
+ }
+ }
+
+ if (theme->handle_height) {
+ /* handle */
+ handle = focus ? theme->a_focused_handle : theme->a_unfocused_handle;
+ x = 2*theme->fbwidth + theme->grip_width;
+ y = height - theme->fbwidth - theme->handle_height;
+ w = width - 4*theme->fbwidth - 2*theme->grip_width;
+ h = theme->handle_height;
+
+ theme_pixmap_paint(handle, w, h);
+ pixmap = gdk_pixmap_foreign_new(handle->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, w, h);
+
+ /* openbox handles this drawing stuff differently (it fills the bottom
+ * of the window with the handle), so it avoids this bug where
+ * parentrelative grips are not fully filled. i'm avoiding it slightly
+ * differently. */
+
+ theme_pixmap_paint(handle, width, h);
+
+ /* grips */
+ a = focus ? theme->a_focused_grip : theme->a_unfocused_grip;
+ a->surface.parent = handle;
+
+ x = theme->fbwidth;
+ /* same y and h as handle */
+ w = theme->grip_width;
+
+ theme_pixmap_paint(a, w, h);
+ pixmap = gdk_pixmap_foreign_new(a->pixmap);
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, w, h);
+
+ /* right grip */
+ x = width - theme->fbwidth - theme->grip_width;
+ pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, gdk_colormap_get_system(), 0, 0, x, y, w, h);
+ }
+
+ /* retarded way of adding client colour */
+ x = theme->fbwidth;
+ y = theme->title_height + 2*theme->fbwidth;
+ w = width - 2*theme->fbwidth;
+ h = height - theme->title_height - 3*theme->fbwidth - (theme->handle_height ? (theme->fbwidth + theme->handle_height) : 0);
+
+ scratch = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, w, h);
+ gdk_pixbuf_fill(scratch, rr_color_pixel((focus ? theme->cb_focused_color : theme->cb_unfocused_color)));
+
+ gdk_pixbuf_copy_area(scratch, 0, 0, w, h, pixbuf, x, y);
+
+ return pixbuf;
+}
+
+static gint theme_label_width(RrTheme *theme, gboolean active)
+{
+ gint w, h;
+ RrAppearance *label;
+
+ if (active) {
+ label = theme->a_focused_label;
+ label->texture[0].data.text.string = "active";
+ } else {
+ label = theme->a_unfocused_label;
+ label->texture[0].data.text.string = "inactive";
+ }
+
+ return RrMinWidth(label);
+}
+
+static gint theme_window_min_width(RrTheme *theme, const gchar *titlelayout)
+{
+ gint numbuttons = strlen(titlelayout);
+ gint w = 2 * (theme->fbwidth + theme->paddingx + 1);
+
+ if (g_strrstr(titlelayout, "L")) {
+ numbuttons--;
+ w += MAX(theme_label_width(theme, TRUE), theme_label_width(theme, FALSE)) + theme->paddingx + 1;
+ }
+
+ w += (theme->button_size + theme->paddingx + 1) * numbuttons;
+
+ return w;
+}
+
+GdkPixbuf *preview_theme(const gchar *name, const gchar *titlelayout,
+ RrFont *active_window_font,
+ RrFont *inactive_window_font,
+ RrFont *menu_title_font,
+ RrFont *menu_item_font,
+ RrFont *osd_font)
+{
+
+ GdkPixbuf *preview;
+ GdkPixbuf *menu;
+ GdkPixbuf *window;
+
+ gint window_w;
+ gint menu_w;
+
+ gint w, h;
+
+ RrTheme *theme = RrThemeNew(rrinst, name,
+ active_window_font, inactive_window_font,
+ menu_title_font, menu_item_font, osd_font);
+
+ menu = preview_menu(theme);
+
+ window_w = theme_window_min_width(theme, titlelayout);
+
+ menu_w = gdk_pixbuf_get_width(menu);
+ h = gdk_pixbuf_get_height(menu);
+
+ w = MAX(window_w, menu_w) + 20;
+
+ preview = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h + 2*(theme->title_height +5) + 1);
+ gdk_pixbuf_fill(preview, 0); /* clear */
+
+ window = preview_window(theme, titlelayout, FALSE, window_w, h);
+ gdk_pixbuf_copy_area(window, 0, 0, window_w, h, preview, 20, 0);
+
+ window = preview_window(theme, titlelayout, TRUE, window_w, h);
+ gdk_pixbuf_copy_area(window, 0, 0, window_w, h, preview, 10, theme->title_height + 5);
+
+ gdk_pixbuf_copy_area(menu, 0, 0, menu_w, h, preview, 0, 2 * (theme->title_height + 5));
+
+ RrThemeFree(theme);
+
+ return preview;
+}