From 9d0a2117d8788a7864ef53074e66067e609fa1bc Mon Sep 17 00:00:00 2001 From: Jonathan Blandford Date: Wed, 27 Nov 2002 00:03:37 +0000 Subject: [PATCH] sync --- capplets/common/gnome-theme-info.c | 8 +- capplets/theme-switcher/gnome-theme-manager.c | 41 +++- .../theme-switcher/theme-properties.glade | 99 ++++++--- capplets/theme-switcher/theme-thumbnail.c | 207 ++++++++++++++++-- capplets/theme-switcher/theme-thumbnail.h | 16 +- 5 files changed, 307 insertions(+), 64 deletions(-) diff --git a/capplets/common/gnome-theme-info.c b/capplets/common/gnome-theme-info.c index df5fe99b2..5ff22abca 100644 --- a/capplets/common/gnome-theme-info.c +++ b/capplets/common/gnome-theme-info.c @@ -28,10 +28,10 @@ typedef struct _ThemeCallbackData } ThemeCallbackData; -GHashTable *theme_hash = NULL; -GHashTable *icon_theme_hash = NULL; -GHashTable *meta_theme_hash = NULL; -GList *callbacks = NULL; +static GHashTable *theme_hash = NULL; +static GHashTable *icon_theme_hash = NULL; +static GHashTable *meta_theme_hash = NULL; +static GList *callbacks = NULL; const gchar *gtk2_suffix = "gtk-2.0"; diff --git a/capplets/theme-switcher/gnome-theme-manager.c b/capplets/theme-switcher/gnome-theme-manager.c index a8327d7f6..8288bb1e7 100644 --- a/capplets/theme-switcher/gnome-theme-manager.c +++ b/capplets/theme-switcher/gnome-theme-manager.c @@ -33,7 +33,7 @@ #define WINDOW_THEME_DEFAULT_NAME "Atlanta" #define ICON_THEME_DEFAULT_NAME "Default" -#define MAX_ELEMENTS_BEFORE_SCROLLING 8 +#define MAX_ELEMENTS_BEFORE_SCROLLING 3 static void read_themes (GladeXML *dialog); @@ -83,6 +83,19 @@ create_dialog (void) } +static void +async_func (GdkPixbuf *pixbuf, + gpointer data) +{ + GList *list = data; + GtkTreeIter *iter = list->next->data; + GtkTreeModel *model = list->data; + + gtk_list_store_set (GTK_LIST_STORE (model), iter, + PIXBUF_COLUMN, pixbuf, + -1); +} + static void load_meta_themes (GtkTreeView *tree_view, GList *meta_theme_list, @@ -127,9 +140,22 @@ load_meta_themes (GtkTreeView *tree_view, gtk_tree_path_free (path); current_theme_found = TRUE; } - blurb = g_strdup_printf ("%s\n\n%s", + blurb = g_strdup_printf ("%s\n%s", meta_theme_info->readable_name, meta_theme_info->comment); + pixbuf = NULL; pixbuf = generate_theme_thumbnail (meta_theme_info); + if (i <= MAX_ELEMENTS_BEFORE_SCROLLING) + { + GtkTreeIter *new_iter = gtk_tree_iter_copy (&iter); + GList *list_data = NULL; + + list_data = g_list_prepend (list_data, new_iter); + list_data = g_list_prepend (list_data, model); +#if 0 + //pixbuf = generate_theme_thumbnail (meta_theme_info); +#endif + } + gtk_list_store_set (GTK_LIST_STORE (model), &iter, PIXBUF_COLUMN, pixbuf, THEME_NAME_COLUMN, blurb, @@ -343,7 +369,6 @@ meta_theme_setup_info (GnomeThemeMetaInfo *meta_theme_info, { GtkWidget *notebook; GtkWidget *toggle; - gulong signal_id; notebook = WID ("meta_theme_notebook"); @@ -882,7 +907,17 @@ setup_dialog (GladeXML *dialog) size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget (size_group, WID ("meta_theme_install_button")); gtk_size_group_add_widget (size_group, WID ("meta_theme_save_button")); + g_object_unref (size_group); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + gtk_size_group_add_widget (size_group, WID ("meta_theme_font1_button")); + gtk_size_group_add_widget (size_group, WID ("meta_theme_background1_button")); + gtk_size_group_add_widget (size_group, WID ("meta_theme_font2_button")); + gtk_size_group_add_widget (size_group, WID ("meta_theme_background2_button")); + g_object_unref (size_group); + + setup_tree_view (GTK_TREE_VIEW (WID ("meta_theme_treeview")), (GCallback) meta_theme_selection_changed, dialog); diff --git a/capplets/theme-switcher/theme-properties.glade b/capplets/theme-switcher/theme-properties.glade index 45ec52401..6ef2a9842 100644 --- a/capplets/theme-switcher/theme-properties.glade +++ b/capplets/theme-switcher/theme-properties.glade @@ -250,7 +250,8 @@ True - This theme suggests a matching font: + This theme suggests a +font: False False GTK_JUSTIFY_LEFT @@ -269,15 +270,22 @@ - + True - True - Use _Font - True - GTK_RELIEF_NORMAL - False - False - True + 0 + 0.5 + 0 + 0 + + + + True + True + Apply _Font + True + GTK_RELIEF_NORMAL + + 0 @@ -320,7 +328,7 @@ True - This theme suggests a matching + This theme suggests a background: False False @@ -340,15 +348,22 @@ background: - + True - True - Use _background - True - GTK_RELIEF_NORMAL - False - False - True + 0 + 0.5 + 0 + 0 + + + + True + True + Apply _Background + True + GTK_RELIEF_NORMAL + + 0 @@ -391,7 +406,7 @@ background: True - This theme suggests a matching + This theme suggests a font and background False False @@ -411,15 +426,22 @@ font and background - + True - True - Use _Font - True - GTK_RELIEF_NORMAL - False - False - True + 0 + 0.5 + 0 + 0 + + + + True + True + Apply _Font + True + GTK_RELIEF_NORMAL + + 0 @@ -429,15 +451,22 @@ font and background - + True - True - Use _Background - True - GTK_RELIEF_NORMAL - False - False - True + 0 + 0.5 + 0 + 1 + + + + True + True + Apply _Background + True + GTK_RELIEF_NORMAL + + 0 diff --git a/capplets/theme-switcher/theme-thumbnail.c b/capplets/theme-switcher/theme-thumbnail.c index cbdfd0ec0..a52f03f38 100644 --- a/capplets/theme-switcher/theme-thumbnail.c +++ b/capplets/theme-switcher/theme-thumbnail.c @@ -17,15 +17,34 @@ #include "capplet-util.h" static gint child_pid; +#define ICON_SIZE_WIDTH 150 +#define ICON_SIZE_HEIGHT 150 +typedef struct +{ + gboolean set; + GByteArray *data; + gchar *meta_theme_name; + ThemeThumbnailFunc func; + gpointer user_data; + GDestroyNotify destroy; + GIOChannel *channel; + guint watch_id; +} ThemeThumbnailAsyncData; + + + +GHashTable *theme_hash = NULL; + +ThemeThumbnailAsyncData async_data; /* Protocol */ /* Our protocol is pretty simple. The parent process will write three strings * (separated by a '\000') They are the widget theme, the wm theme, and the icon * theme. Then, it will wait for the child to write back the data. It expects - * 100x100x3 bytes of information. After that, the child is ready for the next - * theme to render. + * ICON_SIZE_WIDTH * ICON_SIZE_HEIGHT * 4 bytes of information. After that, the + * child is ready for the next theme to render. */ enum @@ -34,6 +53,7 @@ enum READING_CONTROL_THEME_NAME, READING_WM_THEME_NAME, READING_ICON_THEME_NAME, + READING_APPLICATION_FONT, WRITING_PIXBUF_DATA }; @@ -43,6 +63,7 @@ typedef struct GByteArray *control_theme_name; GByteArray *wm_theme_name; GByteArray *icon_theme_name; + GByteArray *application_font; } ThemeThumbnailData; int pipe_to_factory_fd[2]; @@ -99,12 +120,15 @@ create_image (ThemeThumbnailData *theme_thumbnail_data, GnomeIconTheme *icon_theme; GdkPixbuf *folder_icon; char *folder_icon_name; - + char *foo; settings = gtk_settings_get_default (); g_object_set (G_OBJECT (settings), "gtk-theme-name", (char *) theme_thumbnail_data->control_theme_name->data, + "gtk-font-name", (char *) theme_thumbnail_data->application_font->data, + NULL); + g_object_get (G_OBJECT (settings), + "gtk-icon-sizes", &foo, NULL); - theme = meta_theme_load ((char *) theme_thumbnail_data->wm_theme_name->data, NULL); flags = META_FRAME_ALLOWS_DELETE | @@ -140,19 +164,19 @@ create_image (ThemeThumbnailData *theme_thumbnail_data, meta_preview_set_title (META_PREVIEW (preview), ""); - gtk_window_set_default_size (GTK_WINDOW (window), 100, 100); + gtk_window_set_default_size (GTK_WINDOW (window), ICON_SIZE_WIDTH, ICON_SIZE_HEIGHT); gtk_widget_size_request (window, &requisition); allocation.x = 0; allocation.y = 0; - allocation.width = 100; - allocation.height = 100; + allocation.width = ICON_SIZE_WIDTH; + allocation.height = ICON_SIZE_HEIGHT; gtk_widget_size_allocate (window, &allocation); gtk_widget_size_request (window, &requisition); /* Create a pixmap */ visual = gtk_widget_get_visual (window); - pixmap = gdk_pixmap_new (NULL, 100, 100, gdk_visual_get_best_depth()); + pixmap = gdk_pixmap_new (NULL, ICON_SIZE_WIDTH, ICON_SIZE_HEIGHT, gdk_visual_get_best_depth()); gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), gtk_widget_get_colormap (window)); /* Draw the window */ @@ -169,7 +193,7 @@ create_image (ThemeThumbnailData *theme_thumbnail_data, fake_expose_widget (GTK_BIN (stock_button)->child, pixmap); - gdk_pixbuf_get_from_drawable (pixbuf, pixmap, NULL, 0, 0, 0, 0, 100, 100); + gdk_pixbuf_get_from_drawable (pixbuf, pixmap, NULL, 0, 0, 0, 0, ICON_SIZE_WIDTH, ICON_SIZE_HEIGHT); /* Handle the icon theme */ icon_theme = gnome_icon_theme_new (); @@ -257,6 +281,21 @@ handle_bytes (const gchar *buffer, g_byte_array_append (theme_thumbnail_data->icon_theme_name, ptr, nil - ptr + 1); bytes_read -= (nil - ptr + 1); ptr = nil + 1; + theme_thumbnail_data->status = READING_APPLICATION_FONT; + } + break; + case READING_APPLICATION_FONT: + nil = memchr (ptr, '\000', bytes_read); + if (nil == NULL) + { + g_byte_array_append (theme_thumbnail_data->application_font, ptr, bytes_read); + bytes_read = 0; + } + else + { + g_byte_array_append (theme_thumbnail_data->application_font, ptr, nil - ptr + 1); + bytes_read -= (nil - ptr + 1); + ptr = nil + 1; theme_thumbnail_data->status = WRITING_PIXBUF_DATA; } break; @@ -294,19 +333,19 @@ message_from_capplet (GIOChannel *source, if (theme_thumbnail_data->status == WRITING_PIXBUF_DATA) { - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 100, 100); + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, ICON_SIZE_WIDTH, ICON_SIZE_HEIGHT); create_image (theme_thumbnail_data, pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf); - - for (i = 0; i < 100; i ++) + for (i = 0; i < ICON_SIZE_HEIGHT; i ++) { - write (pipe_from_factory_fd[1], pixels + (rowstride)*i, 100*4); + write (pipe_from_factory_fd[1], pixels + (rowstride)*i, ICON_SIZE_WIDTH * gdk_pixbuf_get_n_channels (pixbuf)); } theme_thumbnail_data->status = READY_FOR_THEME; g_byte_array_set_size (theme_thumbnail_data->control_theme_name, 0); g_byte_array_set_size (theme_thumbnail_data->wm_theme_name, 0); g_byte_array_set_size (theme_thumbnail_data->icon_theme_name, 0); + g_byte_array_set_size (theme_thumbnail_data->application_font, 0); } return TRUE; case G_IO_STATUS_AGAIN: @@ -321,29 +360,153 @@ message_from_capplet (GIOChannel *source, return TRUE; } +static gboolean +message_from_child (GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + + gchar buffer[1024]; + GIOStatus status; + gsize bytes_read; + + if (async_data.set == FALSE) + return TRUE; + + status = g_io_channel_read_chars (source, + buffer, + 1024, + &bytes_read, + NULL); + + switch (status) + { + case G_IO_STATUS_NORMAL: + g_byte_array_append (async_data.data, buffer, bytes_read); + if (async_data.data->len == ICON_SIZE_WIDTH * ICON_SIZE_HEIGHT * 4) + { + GdkPixbuf *pixbuf; + GdkPixbuf *scaled_pixbuf; + gchar *pixels; + gint i, rowstride; + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, ICON_SIZE_WIDTH, ICON_SIZE_HEIGHT); + pixels = gdk_pixbuf_get_pixels (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + for (i = 0; i < ICON_SIZE_HEIGHT; i++) + memcpy (pixels + rowstride * i, async_data.data->data + 4 * ICON_SIZE_WIDTH * i, ICON_SIZE_WIDTH * 4); + + scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf, ICON_SIZE_WIDTH/2, ICON_SIZE_HEIGHT/2, GDK_INTERP_BILINEAR); + g_hash_table_insert (theme_hash, async_data.meta_theme_name, scaled_pixbuf); + g_object_unref (pixbuf); + + (* async_data.func) (scaled_pixbuf, async_data.user_data); + + g_source_remove (async_data.watch_id); + g_io_channel_unref (async_data.channel); + async_data.channel = NULL; + if (async_data.destroy) + (* async_data.destroy) (async_data.data); + g_free (async_data.meta_theme_name); + async_data.meta_theme_name = NULL; + async_data.set = FALSE; + } + return TRUE; + case G_IO_STATUS_AGAIN: + return TRUE; + + case G_IO_STATUS_EOF: + case G_IO_STATUS_ERROR: + return TRUE; + default: + g_assert_not_reached (); + } + + return TRUE; +} GdkPixbuf * generate_theme_thumbnail (GnomeThemeMetaInfo *meta_theme_info) { GdkPixbuf *retval = NULL; + GdkPixbuf *pixbuf = NULL; gint i, rowstride; char *pixels; - retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 100, 100); + + g_return_val_if_fail (async_data.set == FALSE, NULL); + + pixbuf = g_hash_table_lookup (theme_hash, meta_theme_info->name); + if (pixbuf != NULL) + { + return pixbuf; + } + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, ICON_SIZE_WIDTH, ICON_SIZE_HEIGHT); write (pipe_to_factory_fd[1], meta_theme_info->gtk_theme_name, strlen (meta_theme_info->gtk_theme_name) + 1); write (pipe_to_factory_fd[1], meta_theme_info->metacity_theme_name, strlen (meta_theme_info->metacity_theme_name) + 1); write (pipe_to_factory_fd[1], meta_theme_info->icon_theme_name, strlen (meta_theme_info->icon_theme_name) + 1); + if (meta_theme_info->application_font == NULL) + write (pipe_to_factory_fd[1], "Sans 10", strlen ("Sans 10") + 1); + else + write (pipe_to_factory_fd[1], meta_theme_info->application_font, strlen (meta_theme_info->application_font) + 1); - rowstride = gdk_pixbuf_get_rowstride (retval); - pixels = gdk_pixbuf_get_pixels (retval); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + pixels = gdk_pixbuf_get_pixels (pixbuf); - for (i = 0; i < 100; i++) + for (i = 0; i < ICON_SIZE_HEIGHT; i++) { - read (pipe_from_factory_fd[0], pixels + (rowstride)*i, 100*4); + read (pipe_from_factory_fd[0], pixels + (rowstride)*i, ICON_SIZE_WIDTH * gdk_pixbuf_get_n_channels (pixbuf)); } + + retval = gdk_pixbuf_scale_simple (pixbuf, ICON_SIZE_WIDTH/2, ICON_SIZE_HEIGHT/2, GDK_INTERP_BILINEAR); + + g_hash_table_insert (theme_hash, meta_theme_info->name, retval); return retval; } +void +generate_theme_thumbnail_async (GnomeThemeMetaInfo *meta_theme_info, + ThemeThumbnailFunc func, + gpointer user_data, + GDestroyNotify destroy) +{ + GdkPixbuf *pixbuf; + + g_return_if_fail (async_data.set == FALSE); + + pixbuf = g_hash_table_lookup (theme_hash, meta_theme_info->name); + if (pixbuf != NULL) + { + (* func) (pixbuf, user_data); + if (destroy) + (* destroy) (user_data); + return; + } + + async_data.channel = g_io_channel_unix_new (pipe_from_factory_fd[0]); + + g_io_channel_set_flags (async_data.channel, g_io_channel_get_flags (async_data.channel) | + G_IO_FLAG_NONBLOCK, NULL); + g_io_channel_set_encoding (async_data.channel, NULL, NULL); + async_data.watch_id = g_io_add_watch (async_data.channel, G_IO_IN | G_IO_HUP, message_from_child, NULL); + + async_data.set = TRUE; + async_data.meta_theme_name = g_strdup (meta_theme_info->name); + async_data.func = func; + async_data.user_data = user_data; + async_data.destroy = destroy; + + + write (pipe_to_factory_fd[1], meta_theme_info->gtk_theme_name, strlen (meta_theme_info->gtk_theme_name) + 1); + write (pipe_to_factory_fd[1], meta_theme_info->metacity_theme_name, strlen (meta_theme_info->metacity_theme_name) + 1); + write (pipe_to_factory_fd[1], meta_theme_info->icon_theme_name, strlen (meta_theme_info->icon_theme_name) + 1); + if (meta_theme_info->application_font == NULL) + write (pipe_to_factory_fd[1], "Sans 10", strlen ("Sans 10") + 1); + else + write (pipe_to_factory_fd[1], meta_theme_info->application_font, strlen (meta_theme_info->application_font) + 1); +} + void setup_theme_thumbnail_factory (int argc, char *argv[]) { @@ -353,8 +516,8 @@ setup_theme_thumbnail_factory (int argc, char *argv[]) child_pid = fork (); if (child_pid == 0) { - GIOChannel *channel; ThemeThumbnailData data; + GIOChannel *channel; /* Child */ gtk_init (&argc, &argv); @@ -366,6 +529,7 @@ setup_theme_thumbnail_factory (int argc, char *argv[]) data.control_theme_name = g_byte_array_new (); data.wm_theme_name = g_byte_array_new (); data.icon_theme_name = g_byte_array_new (); + data.application_font = g_byte_array_new (); channel = g_io_channel_unix_new (pipe_to_factory_fd[0]); g_io_channel_set_flags (channel, g_io_channel_get_flags (channel) | @@ -381,4 +545,9 @@ setup_theme_thumbnail_factory (int argc, char *argv[]) /* Parent */ close (pipe_to_factory_fd[0]); close (pipe_from_factory_fd[1]); + async_data.set = FALSE; + async_data.meta_theme_name = NULL; + async_data.data = g_byte_array_new (); + + theme_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); } diff --git a/capplets/theme-switcher/theme-thumbnail.h b/capplets/theme-switcher/theme-thumbnail.h index 2113042c1..94bc1c763 100644 --- a/capplets/theme-switcher/theme-thumbnail.h +++ b/capplets/theme-switcher/theme-thumbnail.h @@ -5,8 +5,18 @@ #include #include "gnome-theme-info.h" -GdkPixbuf *generate_theme_thumbnail (GnomeThemeMetaInfo *meta_theme_info); -void setup_theme_thumbnail_factory (int argc, - char *argv[]); +typedef void (* ThemeThumbnailFunc) (GdkPixbuf *pixbuf, + gpointer data); + + +GdkPixbuf *generate_theme_thumbnail (GnomeThemeMetaInfo *meta_theme_info); +void generate_theme_thumbnail_async (GnomeThemeMetaInfo *meta_theme_info, + ThemeThumbnailFunc func, + gpointer data, + GDestroyNotify destroy); +void setup_theme_thumbnail_factory (int argc, + char *argv[]); + + #endif /* __THEME_THUMBNAIL_H__ */