~cjcurran/gnome-control-center/expose-card-ports

« back to all changes in this revision

Viewing changes to capplets/common/theme-thumbnail.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Moya
  • Date: 2011-05-17 10:47:27 UTC
  • mfrom: (0.1.11 experimental) (1.1.45 upstream)
  • Revision ID: james.westby@ubuntu.com-20110517104727-lqel6m8vhfw5jby1
Tags: 1:3.0.1.1-1ubuntu1
* Rebase on Debian, remaining Ubuntu changes:
* debian/control:
  - Build-Depend on hardening-wrapper, dpkg-dev and dh-autoreconf
  - Add dependency on ubuntu-system-service
  - Remove dependency on gnome-icon-theme-symbolic
  - Move dependency on apg, gnome-icon-theme-symbolic and accountsservice to
    be a Recommends: until we get them in main
* debian/rules:
  - Use autoreconf
  - Add binary-post-install rule for gnome-control-center-data
  - Run dh-autoreconf
* debian/gnome-control-center.dirs:
* debian/gnome-control-center.links:
  - Add a link to the control center shell for indicators
* debian/patches/00_disable-nm.patch:
  - Temporary patch to disable building with NetworkManager until we get
    the new one in the archive
* debian/patches/01_git_remove_gettext_calls.patch:
  - Remove calls to AM_GNU_GETTEXT, IT_PROG_INTLTOOL should be enough
* debian/patches/01_git_kill_warning.patch:
  - Kill warning
* debian/patches/50_ubuntu_systemwide_prefs.patch:
  - Ubuntu specific proxy preferences
* debian/patches/51_ubuntu_system_keyboard.patch:
  - Implement the global keyboard spec at https://wiki.ubuntu.com/DefaultKeyboardSettings

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <config.h>
2
 
#include <unistd.h>
3
 
#include <string.h>
4
 
#include <metacity-private/util.h>
5
 
#include <metacity-private/theme.h>
6
 
#include <metacity-private/theme-parser.h>
7
 
#include <metacity-private/preview-widget.h>
8
 
#include <signal.h>
9
 
#include <errno.h>
10
 
#include <math.h>
11
 
 
12
 
/* We have to #undef this as metacity #defines these. */
13
 
#undef _
14
 
#undef N_
15
 
 
16
 
#include <glib.h>
17
 
 
18
 
#include "theme-thumbnail.h"
19
 
#include "gtkrc-utils.h"
20
 
#include "capplet-util.h"
21
 
 
22
 
typedef struct
23
 
{
24
 
  gboolean set;
25
 
  gint thumbnail_width;
26
 
  gint thumbnail_height;
27
 
  GByteArray *data;
28
 
  gchar *theme_name;
29
 
  ThemeThumbnailFunc func;
30
 
  gpointer user_data;
31
 
  GDestroyNotify destroy;
32
 
  GIOChannel *channel;
33
 
  guint watch_id;
34
 
} ThemeThumbnailAsyncData;
35
 
 
36
 
 
37
 
static ThemeThumbnailAsyncData async_data;
38
 
 
39
 
/* Protocol */
40
 
 
41
 
/* Our protocol is pretty simple.  The parent process will write several strings
42
 
 * (separated by a '\000'). They are the widget theme, the wm theme, the icon
43
 
 * theme, etc.  Then, it will wait for the child to write back the data.  The
44
 
 * parent expects ICON_SIZE_WIDTH * ICON_SIZE_HEIGHT * 4 bytes of information.
45
 
 * After that, the child is ready for the next theme to render.
46
 
 */
47
 
 
48
 
enum
49
 
{
50
 
  READY_FOR_THEME,
51
 
  READING_TYPE,
52
 
  READING_CONTROL_THEME_NAME,
53
 
  READING_GTK_COLOR_SCHEME,
54
 
  READING_WM_THEME_NAME,
55
 
  READING_ICON_THEME_NAME,
56
 
  READING_APPLICATION_FONT,
57
 
  WRITING_PIXBUF_DATA
58
 
};
59
 
 
60
 
typedef struct
61
 
{
62
 
  gint status;
63
 
  GByteArray *type;
64
 
  GByteArray *control_theme_name;
65
 
  GByteArray *gtk_color_scheme;
66
 
  GByteArray *wm_theme_name;
67
 
  GByteArray *icon_theme_name;
68
 
  GByteArray *application_font;
69
 
} ThemeThumbnailData;
70
 
 
71
 
typedef struct
72
 
{
73
 
  gchar *thumbnail_type;
74
 
  gpointer theme_info;
75
 
  ThemeThumbnailFunc func;
76
 
  gpointer user_data;
77
 
  GDestroyNotify destroy;
78
 
} ThemeQueueItem;
79
 
 
80
 
static GList *theme_queue = NULL;
81
 
 
82
 
static int pipe_to_factory_fd[2];
83
 
static int pipe_from_factory_fd[2];
84
 
 
85
 
#define THUMBNAIL_TYPE_META     "meta"
86
 
#define THUMBNAIL_TYPE_GTK      "gtk"
87
 
#define THUMBNAIL_TYPE_METACITY "metacity"
88
 
#define THUMBNAIL_TYPE_ICON     "icon"
89
 
 
90
 
#define META_THUMBNAIL_SIZE       128
91
 
#define GTK_THUMBNAIL_SIZE         96
92
 
#define METACITY_THUMBNAIL_WIDTH  120
93
 
#define METACITY_THUMBNAIL_HEIGHT  60
94
 
 
95
 
static GdkPixmap*
96
 
draw_window_on_pixbuf (GtkWidget *widget)
97
 
{
98
 
  GdkVisual *visual;
99
 
  GdkPixmap *pixmap;
100
 
  GtkStyle  *style;
101
 
  GdkScreen *screen = gdk_screen_get_default ();
102
 
  GdkWindow *window;
103
 
  gint width, height;
104
 
 
105
 
  gtk_widget_ensure_style (widget);
106
 
 
107
 
  style = gtk_widget_get_style (widget);
108
 
 
109
 
  g_assert (style);
110
 
  g_assert (style->font_desc);
111
 
 
112
 
  gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
113
 
 
114
 
  visual = gtk_widget_get_visual (widget);
115
 
  pixmap = gdk_pixmap_new (NULL, width, height, visual->depth);
116
 
  gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), gtk_widget_get_colormap (widget));
117
 
 
118
 
  window = gtk_widget_get_window (widget);
119
 
 
120
 
  gdk_window_redirect_to_drawable (window, pixmap, 0, 0, 0, 0, width, height);
121
 
  gdk_window_set_override_redirect (window, TRUE);
122
 
  gtk_window_move (GTK_WINDOW (widget), gdk_screen_get_width (screen), gdk_screen_get_height (screen));
123
 
  gtk_widget_show(widget);
124
 
 
125
 
  gdk_window_process_updates (window, TRUE);
126
 
  gtk_widget_hide(widget);
127
 
 
128
 
  return pixmap;
129
 
}
130
 
 
131
 
static void
132
 
pixbuf_apply_mask_region (GdkPixbuf *pixbuf, GdkRegion *region)
133
 
{
134
 
  gint nchannels, rowstride, w, h;
135
 
  guchar *pixels, *p;
136
 
 
137
 
  g_return_if_fail (pixbuf);
138
 
  g_return_if_fail (region);
139
 
 
140
 
  nchannels = gdk_pixbuf_get_n_channels (pixbuf);
141
 
  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
142
 
  pixels = gdk_pixbuf_get_pixels (pixbuf);
143
 
 
144
 
 
145
 
  /* we need an alpha channel ... */
146
 
  if (!gdk_pixbuf_get_has_alpha (pixbuf) || nchannels != 4)
147
 
    return;
148
 
 
149
 
  for (w = 0; w < gdk_pixbuf_get_width (pixbuf); ++w)
150
 
    for (h = 0; h < gdk_pixbuf_get_height (pixbuf); ++h)
151
 
    {
152
 
      if (!gdk_region_point_in (region, w, h))
153
 
      {
154
 
        p = pixels + h * rowstride + w * nchannels;
155
 
        if (G_BYTE_ORDER == G_BIG_ENDIAN)
156
 
          p[0] = 0x0;
157
 
        else
158
 
          p[3] = 0x0;
159
 
      }
160
 
    }
161
 
 
162
 
}
163
 
 
164
 
static GdkPixbuf *
165
 
create_folder_icon (char *icon_theme_name)
166
 
{
167
 
  GtkIconTheme *icon_theme;
168
 
  GdkPixbuf *folder_icon = NULL;
169
 
  GtkIconInfo *folder_icon_info;
170
 
  gchar *example_icon_name;
171
 
  const gchar *icon_names[5];
172
 
  gint i;
173
 
 
174
 
  icon_theme = gtk_icon_theme_new ();
175
 
  gtk_icon_theme_set_custom_theme (icon_theme, icon_theme_name);
176
 
 
177
 
  i = 0;
178
 
  /* Get the Example icon name in the theme if specified */
179
 
  example_icon_name = gtk_icon_theme_get_example_icon_name (icon_theme);
180
 
  if (example_icon_name != NULL)
181
 
    icon_names[i++] = example_icon_name;
182
 
  icon_names[i++] = "x-directory-normal";
183
 
  icon_names[i++] = "gnome-fs-directory";
184
 
  icon_names[i++] = "folder";
185
 
  icon_names[i++] = NULL;
186
 
 
187
 
  folder_icon_info = gtk_icon_theme_choose_icon (icon_theme, icon_names, 48, GTK_ICON_LOOKUP_FORCE_SIZE);
188
 
  if (folder_icon_info != NULL)
189
 
  {
190
 
    folder_icon = gtk_icon_info_load_icon (folder_icon_info, NULL);
191
 
    gtk_icon_info_free (folder_icon_info);
192
 
  }
193
 
 
194
 
  g_object_unref (icon_theme);
195
 
  g_free (example_icon_name);
196
 
 
197
 
  /* render the icon to the thumbnail */
198
 
  if (folder_icon == NULL)
199
 
  {
200
 
    GtkWidget *dummy;
201
 
    dummy = gtk_label_new ("");
202
 
 
203
 
    folder_icon = gtk_widget_render_icon (dummy,
204
 
                                          GTK_STOCK_MISSING_IMAGE,
205
 
                                          GTK_ICON_SIZE_DIALOG,
206
 
                                          NULL);
207
 
 
208
 
    gtk_widget_destroy (dummy);
209
 
  }
210
 
 
211
 
  return folder_icon;
212
 
}
213
 
 
214
 
static GdkPixbuf *
215
 
create_meta_theme_pixbuf (ThemeThumbnailData *theme_thumbnail_data)
216
 
{
217
 
  GtkWidget *window;
218
 
  GtkWidget *preview;
219
 
  GtkWidget *vbox;
220
 
  GtkWidget *align;
221
 
  GtkWidget *box;
222
 
  GtkWidget *stock_button;
223
 
  GtkWidget *checkbox;
224
 
  GtkWidget *radio;
225
 
 
226
 
  GtkRequisition requisition;
227
 
  GtkAllocation allocation;
228
 
  GtkAllocation vbox_allocation;
229
 
  GdkPixmap *pixmap;
230
 
  MetaFrameFlags flags;
231
 
  MetaTheme *theme;
232
 
  GdkPixbuf *pixbuf, *icon;
233
 
  int icon_width, icon_height;
234
 
  GdkRegion *region;
235
 
 
236
 
  g_object_set (gtk_settings_get_default (),
237
 
    "gtk-theme-name", (char *) theme_thumbnail_data->control_theme_name->data,
238
 
    "gtk-font-name", (char *) theme_thumbnail_data->application_font->data,
239
 
    "gtk-icon-theme-name", (char *) theme_thumbnail_data->icon_theme_name->data,
240
 
    "gtk-color-scheme", (char *) theme_thumbnail_data->gtk_color_scheme->data,
241
 
    NULL);
242
 
 
243
 
  theme = meta_theme_load ((char *) theme_thumbnail_data->wm_theme_name->data, NULL);
244
 
  if (theme == NULL)
245
 
    return NULL;
246
 
 
247
 
  /* Represent the icon theme */
248
 
  icon = create_folder_icon ((char *) theme_thumbnail_data->icon_theme_name->data);
249
 
  icon_width = gdk_pixbuf_get_width (icon);
250
 
  icon_height = gdk_pixbuf_get_height (icon);
251
 
 
252
 
  /* Create a fake window */
253
 
  flags = META_FRAME_ALLOWS_DELETE |
254
 
          META_FRAME_ALLOWS_MENU |
255
 
          META_FRAME_ALLOWS_MINIMIZE |
256
 
          META_FRAME_ALLOWS_MAXIMIZE |
257
 
          META_FRAME_ALLOWS_VERTICAL_RESIZE |
258
 
          META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
259
 
          META_FRAME_HAS_FOCUS |
260
 
          META_FRAME_ALLOWS_SHADE |
261
 
          META_FRAME_ALLOWS_MOVE;
262
 
 
263
 
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
264
 
  preview = meta_preview_new ();
265
 
  gtk_container_add (GTK_CONTAINER (window), preview);
266
 
  gtk_widget_realize (window);
267
 
  gtk_widget_realize (preview);
268
 
  vbox = gtk_vbox_new (FALSE, 6);
269
 
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
270
 
  gtk_container_add (GTK_CONTAINER (preview), vbox);
271
 
  align = gtk_alignment_new (0, 0, 0.0, 0.0);
272
 
  gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
273
 
  stock_button = gtk_button_new_from_stock (GTK_STOCK_OPEN);
274
 
  gtk_container_add (GTK_CONTAINER (align), stock_button);
275
 
  box = gtk_hbox_new (FALSE, 0);
276
 
  gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 0);
277
 
  checkbox = gtk_check_button_new ();
278
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox), TRUE);
279
 
  gtk_box_pack_start (GTK_BOX (box), checkbox, FALSE, FALSE, 0);
280
 
  radio = gtk_radio_button_new (NULL);
281
 
  gtk_box_pack_start (GTK_BOX (box), radio, FALSE, FALSE, 0);
282
 
 
283
 
  gtk_widget_show_all (preview);
284
 
 
285
 
  meta_preview_set_frame_flags (META_PREVIEW (preview), flags);
286
 
  meta_preview_set_theme (META_PREVIEW (preview), theme);
287
 
  meta_preview_set_title (META_PREVIEW (preview), "");
288
 
 
289
 
  gtk_window_set_default_size (GTK_WINDOW (window), META_THUMBNAIL_SIZE, META_THUMBNAIL_SIZE);
290
 
 
291
 
  gtk_widget_size_request (window, &requisition);
292
 
  allocation.x = 0;
293
 
  allocation.y = 0;
294
 
  allocation.width = META_THUMBNAIL_SIZE;
295
 
  allocation.height = META_THUMBNAIL_SIZE;
296
 
  gtk_widget_size_allocate (window, &allocation);
297
 
  gtk_widget_size_request (window, &requisition);
298
 
 
299
 
  pixmap = draw_window_on_pixbuf (window);
300
 
 
301
 
  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, META_THUMBNAIL_SIZE, META_THUMBNAIL_SIZE);
302
 
  gdk_pixbuf_get_from_drawable (pixbuf, pixmap, NULL, 0, 0, 0, 0, META_THUMBNAIL_SIZE, META_THUMBNAIL_SIZE);
303
 
 
304
 
  gtk_widget_get_allocation (vbox, &vbox_allocation);
305
 
 
306
 
  /* Add the icon theme to the pixbuf */
307
 
  gdk_pixbuf_composite (icon, pixbuf,
308
 
                        vbox_allocation.x + vbox_allocation.width - icon_width - 5,
309
 
                        vbox_allocation.y + vbox_allocation.height - icon_height - 5,
310
 
                        icon_width, icon_height,
311
 
                        vbox_allocation.x + vbox_allocation.width - icon_width - 5,
312
 
                        vbox_allocation.y + vbox_allocation.height - icon_height - 5,
313
 
                        1.0, 1.0, GDK_INTERP_BILINEAR, 255);
314
 
  region = meta_preview_get_clip_region (META_PREVIEW (preview),
315
 
      META_THUMBNAIL_SIZE, META_THUMBNAIL_SIZE);
316
 
  pixbuf_apply_mask_region (pixbuf, region);
317
 
  gdk_region_destroy (region);
318
 
 
319
 
  g_object_unref (icon);
320
 
  gtk_widget_destroy (window);
321
 
  meta_theme_free (theme);
322
 
  g_object_unref (pixmap);
323
 
 
324
 
  return pixbuf;
325
 
}
326
 
 
327
 
static GdkPixbuf *
328
 
create_gtk_theme_pixbuf (ThemeThumbnailData *theme_thumbnail_data)
329
 
{
330
 
  GtkSettings *settings;
331
 
  GtkWidget *window, *vbox, *box, *stock_button, *checkbox, *radio;
332
 
  GtkRequisition requisition;
333
 
  GtkAllocation allocation;
334
 
  GdkPixmap *pixmap;
335
 
  GdkPixbuf *pixbuf, *retval;
336
 
  gint width, height;
337
 
 
338
 
  settings = gtk_settings_get_default ();
339
 
  g_object_set (settings, "gtk-theme-name", (char *) theme_thumbnail_data->control_theme_name->data,
340
 
                          "gtk-color-scheme", (char *) theme_thumbnail_data->gtk_color_scheme->data,
341
 
                          NULL);
342
 
 
343
 
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
344
 
 
345
 
  vbox = gtk_vbox_new (FALSE, 0);
346
 
  gtk_container_add (GTK_CONTAINER (window), vbox);
347
 
  box = gtk_hbox_new (FALSE, 6);
348
 
  gtk_container_set_border_width (GTK_CONTAINER (box), 6);
349
 
  gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 0);
350
 
  stock_button = gtk_button_new_from_stock (GTK_STOCK_OPEN);
351
 
  gtk_box_pack_start (GTK_BOX (box), stock_button, FALSE, FALSE, 0);
352
 
  checkbox = gtk_check_button_new ();
353
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox), TRUE);
354
 
  gtk_box_pack_start (GTK_BOX (box), checkbox, FALSE, FALSE, 0);
355
 
  radio = gtk_radio_button_new_from_widget (NULL);
356
 
  gtk_box_pack_start (GTK_BOX (box), radio, FALSE, FALSE, 0);
357
 
 
358
 
  gtk_widget_show_all (vbox);
359
 
  gtk_widget_realize (stock_button);
360
 
  gtk_widget_realize (gtk_bin_get_child (GTK_BIN (stock_button)));
361
 
  gtk_widget_realize (checkbox);
362
 
  gtk_widget_realize (radio);
363
 
  gtk_widget_map (stock_button);
364
 
  gtk_widget_map (gtk_bin_get_child (GTK_BIN (stock_button)));
365
 
  gtk_widget_map (checkbox);
366
 
  gtk_widget_map (radio);
367
 
 
368
 
  gtk_widget_size_request (window, &requisition);
369
 
  allocation.x = 0;
370
 
  allocation.y = 0;
371
 
  allocation.width = requisition.width;
372
 
  allocation.height = requisition.height;
373
 
  gtk_widget_size_allocate (window, &allocation);
374
 
  gtk_widget_size_request (window, &requisition);
375
 
 
376
 
  gtk_window_get_size (GTK_WINDOW (window), &width, &height);
377
 
 
378
 
  pixmap = draw_window_on_pixbuf (window);
379
 
 
380
 
  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
381
 
  gdk_pixbuf_get_from_drawable (pixbuf, pixmap, NULL, 0, 0, 0, 0, width, height);
382
 
 
383
 
  retval = gdk_pixbuf_scale_simple (pixbuf,
384
 
                                    GTK_THUMBNAIL_SIZE,
385
 
                                    (int) GTK_THUMBNAIL_SIZE * (((double) height) / ((double) width)),
386
 
                                    GDK_INTERP_BILINEAR);
387
 
  g_object_unref (pixbuf);
388
 
  gtk_widget_destroy (window);
389
 
  g_object_unref (pixmap);
390
 
 
391
 
  return retval;
392
 
}
393
 
 
394
 
static GdkPixbuf *
395
 
create_metacity_theme_pixbuf (ThemeThumbnailData *theme_thumbnail_data)
396
 
{
397
 
  GtkWidget *window, *preview, *dummy;
398
 
  MetaFrameFlags flags;
399
 
  MetaTheme *theme;
400
 
  GtkRequisition requisition;
401
 
  GtkAllocation allocation;
402
 
  GdkPixmap *pixmap;
403
 
  GdkPixbuf *pixbuf, *retval;
404
 
  GdkRegion *region;
405
 
 
406
 
  theme = meta_theme_load ((char *) theme_thumbnail_data->wm_theme_name->data, NULL);
407
 
  if (theme == NULL)
408
 
    return NULL;
409
 
 
410
 
  flags = META_FRAME_ALLOWS_DELETE |
411
 
          META_FRAME_ALLOWS_MENU |
412
 
          META_FRAME_ALLOWS_MINIMIZE |
413
 
          META_FRAME_ALLOWS_MAXIMIZE |
414
 
          META_FRAME_ALLOWS_VERTICAL_RESIZE |
415
 
          META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
416
 
          META_FRAME_HAS_FOCUS |
417
 
          META_FRAME_ALLOWS_SHADE |
418
 
          META_FRAME_ALLOWS_MOVE;
419
 
 
420
 
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
421
 
  gtk_window_set_default_size (GTK_WINDOW (window), (int) METACITY_THUMBNAIL_WIDTH * 1.2, (int) METACITY_THUMBNAIL_HEIGHT * 1.2);
422
 
 
423
 
  preview = meta_preview_new ();
424
 
  meta_preview_set_frame_flags (META_PREVIEW (preview), flags);
425
 
  meta_preview_set_theme (META_PREVIEW (preview), theme);
426
 
  meta_preview_set_title (META_PREVIEW (preview), "");
427
 
  gtk_container_add (GTK_CONTAINER (window), preview);
428
 
 
429
 
  dummy = gtk_label_new ("");
430
 
  gtk_container_add (GTK_CONTAINER (preview), dummy);
431
 
 
432
 
  gtk_widget_realize (window);
433
 
  gtk_widget_realize (preview);
434
 
  gtk_widget_realize (dummy);
435
 
  gtk_widget_show_all (preview);
436
 
  gtk_widget_map (dummy);
437
 
 
438
 
  gtk_widget_size_request (window, &requisition);
439
 
  allocation.x = 0;
440
 
  allocation.y = 0;
441
 
  allocation.width = (int) METACITY_THUMBNAIL_WIDTH * 1.2;
442
 
  allocation.height = (int) METACITY_THUMBNAIL_HEIGHT * 1.2;
443
 
  gtk_widget_size_allocate (window, &allocation);
444
 
  gtk_widget_size_request (window, &requisition);
445
 
 
446
 
  pixmap = draw_window_on_pixbuf (window);
447
 
 
448
 
  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, (int) METACITY_THUMBNAIL_WIDTH * 1.2, (int) METACITY_THUMBNAIL_HEIGHT * 1.2);
449
 
  gdk_pixbuf_get_from_drawable (pixbuf, pixmap, NULL, 0, 0, 0, 0, (int) METACITY_THUMBNAIL_WIDTH * 1.2, (int) METACITY_THUMBNAIL_HEIGHT * 1.2);
450
 
 
451
 
  region = meta_preview_get_clip_region (META_PREVIEW (preview),
452
 
      METACITY_THUMBNAIL_WIDTH * 1.2, METACITY_THUMBNAIL_HEIGHT * 1.2);
453
 
  pixbuf_apply_mask_region (pixbuf, region);
454
 
  gdk_region_destroy (region);
455
 
 
456
 
 
457
 
  retval = gdk_pixbuf_scale_simple (pixbuf,
458
 
                                    METACITY_THUMBNAIL_WIDTH,
459
 
                                    METACITY_THUMBNAIL_HEIGHT,
460
 
                                    GDK_INTERP_BILINEAR);
461
 
  g_object_unref (pixbuf);
462
 
 
463
 
  gtk_widget_destroy (window);
464
 
  meta_theme_free (theme);
465
 
  g_object_unref (pixmap);
466
 
 
467
 
  return retval;
468
 
}
469
 
 
470
 
static GdkPixbuf *
471
 
create_icon_theme_pixbuf (ThemeThumbnailData *theme_thumbnail_data)
472
 
{
473
 
  return create_folder_icon ((char *) theme_thumbnail_data->icon_theme_name->data);
474
 
}
475
 
 
476
 
 
477
 
static void
478
 
handle_bytes (const gchar        *buffer,
479
 
              gint                bytes_read,
480
 
              ThemeThumbnailData *theme_thumbnail_data)
481
 
{
482
 
  const gchar *ptr;
483
 
  ptr = buffer;
484
 
 
485
 
  while (bytes_read > 0)
486
 
  {
487
 
    char *nil;
488
 
 
489
 
    switch (theme_thumbnail_data->status)
490
 
    {
491
 
      case READY_FOR_THEME:
492
 
        theme_thumbnail_data->status = READING_TYPE;
493
 
        /* fall through */
494
 
      case READING_TYPE:
495
 
        nil = memchr (ptr, '\000', bytes_read);
496
 
        if (nil == NULL)
497
 
        {
498
 
          g_byte_array_append (theme_thumbnail_data->type, ptr, bytes_read);
499
 
          bytes_read = 0;
500
 
        }
501
 
        else
502
 
        {
503
 
          g_byte_array_append (theme_thumbnail_data->type, ptr, nil - ptr + 1);
504
 
          bytes_read -= (nil - ptr + 1);
505
 
          ptr = nil + 1;
506
 
          theme_thumbnail_data->status = READING_CONTROL_THEME_NAME;
507
 
        }
508
 
        break;
509
 
 
510
 
      case READING_CONTROL_THEME_NAME:
511
 
        nil = memchr (ptr, '\000', bytes_read);
512
 
        if (nil == NULL)
513
 
        {
514
 
          g_byte_array_append (theme_thumbnail_data->control_theme_name, ptr, bytes_read);
515
 
          bytes_read = 0;
516
 
        }
517
 
        else
518
 
        {
519
 
          g_byte_array_append (theme_thumbnail_data->control_theme_name, ptr, nil - ptr + 1);
520
 
          bytes_read -= (nil - ptr + 1);
521
 
          ptr = nil + 1;
522
 
          theme_thumbnail_data->status = READING_GTK_COLOR_SCHEME;
523
 
        }
524
 
        break;
525
 
 
526
 
      case READING_GTK_COLOR_SCHEME:
527
 
        nil = memchr (ptr, '\000', bytes_read);
528
 
        if (nil == NULL)
529
 
        {
530
 
          g_byte_array_append (theme_thumbnail_data->gtk_color_scheme, ptr, bytes_read);
531
 
          bytes_read = 0;
532
 
        }
533
 
        else
534
 
        {
535
 
          g_byte_array_append (theme_thumbnail_data->gtk_color_scheme, ptr, nil - ptr + 1);
536
 
          bytes_read -= (nil - ptr + 1);
537
 
          ptr = nil + 1;
538
 
          theme_thumbnail_data->status = READING_WM_THEME_NAME;
539
 
        }
540
 
        break;
541
 
 
542
 
      case READING_WM_THEME_NAME:
543
 
        nil = memchr (ptr, '\000', bytes_read);
544
 
        if (nil == NULL)
545
 
        {
546
 
          g_byte_array_append (theme_thumbnail_data->wm_theme_name, ptr, bytes_read);
547
 
          bytes_read = 0;
548
 
        }
549
 
        else
550
 
        {
551
 
          g_byte_array_append (theme_thumbnail_data->wm_theme_name, ptr, nil - ptr + 1);
552
 
          bytes_read -= (nil - ptr + 1);
553
 
          ptr = nil + 1;
554
 
          theme_thumbnail_data->status = READING_ICON_THEME_NAME;
555
 
        }
556
 
        break;
557
 
 
558
 
      case READING_ICON_THEME_NAME:
559
 
        nil = memchr (ptr, '\000', bytes_read);
560
 
        if (nil == NULL)
561
 
        {
562
 
          g_byte_array_append (theme_thumbnail_data->icon_theme_name, ptr, bytes_read);
563
 
          bytes_read = 0;
564
 
        }
565
 
        else
566
 
        {
567
 
          g_byte_array_append (theme_thumbnail_data->icon_theme_name, ptr, nil - ptr + 1);
568
 
          bytes_read -= (nil - ptr + 1);
569
 
          ptr = nil + 1;
570
 
          theme_thumbnail_data->status = READING_APPLICATION_FONT;
571
 
        }
572
 
        break;
573
 
 
574
 
      case READING_APPLICATION_FONT:
575
 
        nil = memchr (ptr, '\000', bytes_read);
576
 
        if (nil == NULL)
577
 
        {
578
 
          g_byte_array_append (theme_thumbnail_data->application_font, ptr, bytes_read);
579
 
          bytes_read = 0;
580
 
        }
581
 
        else
582
 
        {
583
 
          g_byte_array_append (theme_thumbnail_data->application_font, ptr, nil - ptr + 1);
584
 
          bytes_read -= (nil - ptr + 1);
585
 
          ptr = nil + 1;
586
 
          theme_thumbnail_data->status = WRITING_PIXBUF_DATA;
587
 
        }
588
 
        break;
589
 
 
590
 
      default:
591
 
        g_assert_not_reached ();
592
 
    }
593
 
  }
594
 
}
595
 
 
596
 
static gboolean
597
 
message_from_capplet (GIOChannel   *source,
598
 
                      GIOCondition  condition,
599
 
                      gpointer      data)
600
 
{
601
 
  gchar buffer[1024];
602
 
  GIOStatus status;
603
 
  gsize bytes_read;
604
 
  ThemeThumbnailData *theme_thumbnail_data;
605
 
 
606
 
  theme_thumbnail_data = (ThemeThumbnailData *) data;
607
 
  status = g_io_channel_read_chars (source,
608
 
                                    buffer,
609
 
                                    1024,
610
 
                                    &bytes_read,
611
 
                                    NULL);
612
 
 
613
 
  switch (status)
614
 
  {
615
 
    case G_IO_STATUS_NORMAL:
616
 
      handle_bytes (buffer, bytes_read, theme_thumbnail_data);
617
 
 
618
 
      if (theme_thumbnail_data->status == WRITING_PIXBUF_DATA)
619
 
      {
620
 
        GdkPixbuf *pixbuf = NULL;
621
 
        gint i, rowstride;
622
 
        guchar *pixels;
623
 
        gint width, height;
624
 
        const gchar *type = (const gchar *) theme_thumbnail_data->type->data;
625
 
 
626
 
        if (!strcmp (type, THUMBNAIL_TYPE_META))
627
 
          pixbuf = create_meta_theme_pixbuf (theme_thumbnail_data);
628
 
        else if (!strcmp (type, THUMBNAIL_TYPE_GTK))
629
 
          pixbuf = create_gtk_theme_pixbuf (theme_thumbnail_data);
630
 
        else if (!strcmp (type, THUMBNAIL_TYPE_METACITY))
631
 
          pixbuf = create_metacity_theme_pixbuf (theme_thumbnail_data);
632
 
        else if (!strcmp (type, THUMBNAIL_TYPE_ICON))
633
 
          pixbuf = create_icon_theme_pixbuf (theme_thumbnail_data);
634
 
        else
635
 
          g_assert_not_reached ();
636
 
 
637
 
        if (pixbuf == NULL) {
638
 
          width = height = rowstride = 0;
639
 
          pixels = NULL;
640
 
        } else {
641
 
          width = gdk_pixbuf_get_width (pixbuf);
642
 
          height = gdk_pixbuf_get_height (pixbuf);
643
 
          rowstride = gdk_pixbuf_get_rowstride (pixbuf);
644
 
          pixels = gdk_pixbuf_get_pixels (pixbuf);
645
 
        }
646
 
 
647
 
        /* Write the pixbuf's size */
648
 
        write (pipe_from_factory_fd[1], &width, sizeof (width));
649
 
        write (pipe_from_factory_fd[1], &height, sizeof (height));
650
 
 
651
 
        for (i = 0; i < height; i++)
652
 
        {
653
 
          write (pipe_from_factory_fd[1], pixels + rowstride * i, width * gdk_pixbuf_get_n_channels (pixbuf));
654
 
        }
655
 
 
656
 
        if (pixbuf)
657
 
          g_object_unref (pixbuf);
658
 
        g_byte_array_set_size (theme_thumbnail_data->type, 0);
659
 
        g_byte_array_set_size (theme_thumbnail_data->control_theme_name, 0);
660
 
        g_byte_array_set_size (theme_thumbnail_data->gtk_color_scheme, 0);
661
 
        g_byte_array_set_size (theme_thumbnail_data->wm_theme_name, 0);
662
 
        g_byte_array_set_size (theme_thumbnail_data->icon_theme_name, 0);
663
 
        g_byte_array_set_size (theme_thumbnail_data->application_font, 0);
664
 
        theme_thumbnail_data->status = READY_FOR_THEME;
665
 
      }
666
 
      return TRUE;
667
 
 
668
 
    case G_IO_STATUS_AGAIN:
669
 
      return TRUE;
670
 
 
671
 
    case G_IO_STATUS_EOF:
672
 
    case G_IO_STATUS_ERROR:
673
 
      _exit (0);
674
 
 
675
 
    default:
676
 
      g_assert_not_reached ();
677
 
    }
678
 
 
679
 
  return TRUE;
680
 
}
681
 
 
682
 
static void
683
 
generate_next_in_queue (void)
684
 
{
685
 
  ThemeQueueItem *item;
686
 
 
687
 
  if (theme_queue == NULL)
688
 
    return;
689
 
 
690
 
  item = theme_queue->data;
691
 
  theme_queue = g_list_delete_link (theme_queue, g_list_first (theme_queue));
692
 
 
693
 
  if (!strcmp (item->thumbnail_type, THUMBNAIL_TYPE_META))
694
 
    generate_meta_theme_thumbnail_async ((GnomeThemeMetaInfo *) item->theme_info,
695
 
                                         item->func,
696
 
                                         item->user_data,
697
 
                                         item->destroy);
698
 
  else if (!strcmp (item->thumbnail_type, THUMBNAIL_TYPE_GTK))
699
 
    generate_gtk_theme_thumbnail_async ((GnomeThemeInfo *) item->theme_info,
700
 
                                        item->func,
701
 
                                        item->user_data,
702
 
                                        item->destroy);
703
 
  else if (!strcmp (item->thumbnail_type, THUMBNAIL_TYPE_METACITY))
704
 
    generate_metacity_theme_thumbnail_async ((GnomeThemeInfo *) item->theme_info,
705
 
                                             item->func,
706
 
                                             item->user_data,
707
 
                                             item->destroy);
708
 
  else if (!strcmp (item->thumbnail_type, THUMBNAIL_TYPE_ICON))
709
 
    generate_icon_theme_thumbnail_async ((GnomeThemeIconInfo *) item->theme_info,
710
 
                                         item->func,
711
 
                                         item->user_data,
712
 
                                         item->destroy);
713
 
 
714
 
  g_free (item);
715
 
}
716
 
 
717
 
static gboolean
718
 
message_from_child (GIOChannel   *source,
719
 
                    GIOCondition  condition,
720
 
                    gpointer      data)
721
 
{
722
 
  gchar buffer[1024];
723
 
  GIOStatus status;
724
 
  gsize bytes_read;
725
 
 
726
 
  if (async_data.set == FALSE)
727
 
    return TRUE;
728
 
 
729
 
  if (condition == G_IO_HUP)
730
 
    return FALSE;
731
 
 
732
 
  status = g_io_channel_read_chars (source,
733
 
                                    buffer,
734
 
                                    1024,
735
 
                                    &bytes_read,
736
 
                                    NULL);
737
 
  switch (status)
738
 
  {
739
 
    case G_IO_STATUS_NORMAL:
740
 
      g_byte_array_append (async_data.data, (guchar *) buffer, bytes_read);
741
 
 
742
 
      if (async_data.thumbnail_width == -1 && async_data.data->len >= 2 * sizeof (gint))
743
 
      {
744
 
        async_data.thumbnail_width = *((gint *) async_data.data->data);
745
 
        async_data.thumbnail_height = *(((gint *) async_data.data->data) + 1);
746
 
        g_byte_array_remove_range (async_data.data, 0, 2 * sizeof (gint));
747
 
      }
748
 
 
749
 
      if (async_data.thumbnail_width >= 0 && async_data.data->len == async_data.thumbnail_width * async_data.thumbnail_height * 4)
750
 
      {
751
 
        GdkPixbuf *pixbuf = NULL;
752
 
 
753
 
        if (async_data.thumbnail_width > 0) {
754
 
          gchar *pixels;
755
 
          gint i, rowstride;
756
 
 
757
 
          pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, async_data.thumbnail_width, async_data.thumbnail_height);
758
 
          pixels = (gchar *) gdk_pixbuf_get_pixels (pixbuf);
759
 
          rowstride = gdk_pixbuf_get_rowstride (pixbuf);
760
 
 
761
 
          for (i = 0; i < async_data.thumbnail_height; ++i)
762
 
            memcpy (pixels + rowstride * i, async_data.data->data + 4 * async_data.thumbnail_width * i, async_data.thumbnail_width * 4);
763
 
        }
764
 
 
765
 
        /* callback function needs to ref the pixbuf if it wants to keep it */
766
 
        (* async_data.func) (pixbuf, async_data.theme_name, async_data.user_data);
767
 
 
768
 
        if (async_data.destroy)
769
 
          (* async_data.destroy) (async_data.user_data);
770
 
 
771
 
        if (pixbuf)
772
 
          g_object_unref (pixbuf);
773
 
 
774
 
        /* Clean up async_data */
775
 
        g_free (async_data.theme_name);
776
 
        g_source_remove (async_data.watch_id);
777
 
        g_io_channel_unref (async_data.channel);
778
 
 
779
 
        /* reset async_data */
780
 
        async_data.thumbnail_width = -1;
781
 
        async_data.thumbnail_height = -1;
782
 
        async_data.theme_name = NULL;
783
 
        async_data.channel = NULL;
784
 
        async_data.func = NULL;
785
 
        async_data.user_data = NULL;
786
 
        async_data.destroy = NULL;
787
 
        async_data.set = FALSE;
788
 
        g_byte_array_set_size (async_data.data, 0);
789
 
 
790
 
        generate_next_in_queue ();
791
 
      }
792
 
      return TRUE;
793
 
 
794
 
    case G_IO_STATUS_AGAIN:
795
 
      return TRUE;
796
 
 
797
 
    case G_IO_STATUS_EOF:
798
 
    case G_IO_STATUS_ERROR:
799
 
      return FALSE;
800
 
 
801
 
    default:
802
 
      g_assert_not_reached ();
803
 
  }
804
 
 
805
 
  return TRUE;
806
 
}
807
 
 
808
 
static void
809
 
send_thumbnail_request (gchar *thumbnail_type,
810
 
                        gchar *gtk_theme_name,
811
 
                        gchar *gtk_color_scheme,
812
 
                        gchar *metacity_theme_name,
813
 
                        gchar *icon_theme_name,
814
 
                        gchar *application_font)
815
 
{
816
 
  write (pipe_to_factory_fd[1], thumbnail_type, strlen (thumbnail_type) + 1);
817
 
 
818
 
  if (gtk_theme_name)
819
 
    write (pipe_to_factory_fd[1], gtk_theme_name, strlen (gtk_theme_name) + 1);
820
 
  else
821
 
    write (pipe_to_factory_fd[1], "", 1);
822
 
 
823
 
  if (gtk_color_scheme)
824
 
    write (pipe_to_factory_fd[1], gtk_color_scheme, strlen (gtk_color_scheme) + 1);
825
 
  else
826
 
    write (pipe_to_factory_fd[1], "", 1);
827
 
 
828
 
  if (metacity_theme_name)
829
 
    write (pipe_to_factory_fd[1], metacity_theme_name, strlen (metacity_theme_name) + 1);
830
 
  else
831
 
    write (pipe_to_factory_fd[1], "", 1);
832
 
 
833
 
  if (icon_theme_name)
834
 
    write (pipe_to_factory_fd[1], icon_theme_name, strlen (icon_theme_name) + 1);
835
 
  else
836
 
    write (pipe_to_factory_fd[1], "", 1);
837
 
 
838
 
  if (application_font)
839
 
    write (pipe_to_factory_fd[1], application_font, strlen (application_font) + 1);
840
 
  else
841
 
     write (pipe_to_factory_fd[1], "Sans 10", strlen ("Sans 10") + 1);
842
 
 
843
 
}
844
 
 
845
 
static GdkPixbuf *
846
 
read_pixbuf (void)
847
 
{
848
 
  gint bytes_read, i, j = 0;
849
 
  gint size[2];
850
 
  GdkPixbuf *pixbuf;
851
 
  gint rowstride;
852
 
  guchar *pixels;
853
 
 
854
 
  do
855
 
  {
856
 
    bytes_read = read (pipe_from_factory_fd[0], ((guint8*) size) + j, 2 * sizeof (gint));
857
 
    if (bytes_read == 0)
858
 
      goto eof;
859
 
    j += bytes_read;
860
 
  }
861
 
  while (j < 2 * sizeof (gint));
862
 
 
863
 
  if (size[0] <= 0 || size[1] <= 0)
864
 
    return NULL;
865
 
 
866
 
  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size[0], size[1]);
867
 
  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
868
 
  pixels = gdk_pixbuf_get_pixels (pixbuf);
869
 
 
870
 
  for (i = 0; i < size[1]; i++)
871
 
  {
872
 
    j = 0;
873
 
 
874
 
    do
875
 
    {
876
 
      bytes_read = read (pipe_from_factory_fd[0], pixels + rowstride * i + j, size[0] * gdk_pixbuf_get_n_channels (pixbuf) - j);
877
 
 
878
 
      if (bytes_read > 0)
879
 
        j += bytes_read;
880
 
      else if (bytes_read == 0)
881
 
      {
882
 
        g_object_unref (pixbuf);
883
 
        goto eof;
884
 
      }
885
 
    }
886
 
    while (j < size[0] * gdk_pixbuf_get_n_channels (pixbuf));
887
 
  }
888
 
 
889
 
  return pixbuf;
890
 
 
891
 
eof:
892
 
  g_warning ("Received EOF while reading thumbnail");
893
 
  close (pipe_to_factory_fd[1]);
894
 
  pipe_to_factory_fd[1] = 0;
895
 
  close (pipe_from_factory_fd[0]);
896
 
  pipe_from_factory_fd[0] = 0;
897
 
  return NULL;
898
 
}
899
 
 
900
 
static GdkPixbuf *
901
 
generate_theme_thumbnail (gchar *thumbnail_type,
902
 
                          gchar *gtk_theme_name,
903
 
                          gchar *gtk_color_scheme,
904
 
                          gchar *metacity_theme_name,
905
 
                          gchar *icon_theme_name,
906
 
                          gchar *application_font)
907
 
{
908
 
  if (async_data.set || !pipe_to_factory_fd[1] || !pipe_from_factory_fd[0])
909
 
    return NULL;
910
 
 
911
 
  send_thumbnail_request (thumbnail_type,
912
 
                          gtk_theme_name,
913
 
                          gtk_color_scheme,
914
 
                          metacity_theme_name,
915
 
                          icon_theme_name,
916
 
                          application_font);
917
 
 
918
 
  return read_pixbuf ();
919
 
}
920
 
 
921
 
GdkPixbuf *
922
 
generate_meta_theme_thumbnail (GnomeThemeMetaInfo *theme_info)
923
 
{
924
 
  return generate_theme_thumbnail (THUMBNAIL_TYPE_META,
925
 
                                   theme_info->gtk_theme_name,
926
 
                                   theme_info->gtk_color_scheme,
927
 
                                   theme_info->metacity_theme_name,
928
 
                                   theme_info->icon_theme_name,
929
 
                                   theme_info->application_font);
930
 
}
931
 
 
932
 
GdkPixbuf *
933
 
generate_gtk_theme_thumbnail (GnomeThemeInfo *theme_info)
934
 
{
935
 
  gchar *scheme;
936
 
 
937
 
  scheme = gtkrc_get_color_scheme_for_theme (theme_info->name);
938
 
 
939
 
  return generate_theme_thumbnail (THUMBNAIL_TYPE_GTK,
940
 
                                   theme_info->name,
941
 
                                   scheme,
942
 
                                   NULL,
943
 
                                   NULL,
944
 
                                   NULL);
945
 
  g_free (scheme);
946
 
}
947
 
 
948
 
GdkPixbuf *
949
 
generate_metacity_theme_thumbnail (GnomeThemeInfo *theme_info)
950
 
{
951
 
  return generate_theme_thumbnail (THUMBNAIL_TYPE_METACITY,
952
 
                                   NULL,
953
 
                                   NULL,
954
 
                                   theme_info->name,
955
 
                                   NULL,
956
 
                                   NULL);
957
 
}
958
 
 
959
 
GdkPixbuf *
960
 
generate_icon_theme_thumbnail (GnomeThemeIconInfo *theme_info)
961
 
{
962
 
  return generate_theme_thumbnail (THUMBNAIL_TYPE_ICON,
963
 
                                   NULL,
964
 
                                   NULL,
965
 
                                   NULL,
966
 
                                   theme_info->name,
967
 
                                   NULL);
968
 
}
969
 
 
970
 
static void
971
 
generate_theme_thumbnail_async (gpointer            theme_info,
972
 
                                gchar              *theme_name,
973
 
                                gchar              *thumbnail_type,
974
 
                                gchar              *gtk_theme_name,
975
 
                                gchar              *gtk_color_scheme,
976
 
                                gchar              *metacity_theme_name,
977
 
                                gchar              *icon_theme_name,
978
 
                                gchar              *application_font,
979
 
                                ThemeThumbnailFunc  func,
980
 
                                gpointer            user_data,
981
 
                                GDestroyNotify      destroy)
982
 
{
983
 
  if (async_data.set)
984
 
  {
985
 
    ThemeQueueItem *item;
986
 
 
987
 
    item = g_new0 (ThemeQueueItem, 1);
988
 
    item->thumbnail_type = thumbnail_type;
989
 
    item->theme_info = theme_info;
990
 
    item->func = func;
991
 
    item->user_data = user_data;
992
 
    item->destroy = destroy;
993
 
 
994
 
    theme_queue = g_list_append (theme_queue, item);
995
 
    return;
996
 
  }
997
 
 
998
 
  if (!pipe_to_factory_fd[1] || !pipe_from_factory_fd[0])
999
 
  {
1000
 
    (* func) (NULL, theme_name, user_data);
1001
 
 
1002
 
    if (destroy)
1003
 
      (* destroy) (user_data);
1004
 
 
1005
 
    return;
1006
 
  }
1007
 
 
1008
 
  if (async_data.channel == NULL)
1009
 
  {
1010
 
    async_data.channel = g_io_channel_unix_new (pipe_from_factory_fd[0]);
1011
 
    g_io_channel_set_flags (async_data.channel, g_io_channel_get_flags (async_data.channel) | G_IO_FLAG_NONBLOCK, NULL);
1012
 
    g_io_channel_set_encoding (async_data.channel, NULL, NULL);
1013
 
    async_data.watch_id = g_io_add_watch (async_data.channel, G_IO_IN | G_IO_HUP, message_from_child, NULL);
1014
 
  }
1015
 
 
1016
 
  async_data.set = TRUE;
1017
 
  async_data.thumbnail_width = -1;
1018
 
  async_data.thumbnail_height = -1;
1019
 
  async_data.theme_name = g_strdup (theme_name);
1020
 
  async_data.func = func;
1021
 
  async_data.user_data = user_data;
1022
 
  async_data.destroy = destroy;
1023
 
 
1024
 
  send_thumbnail_request (thumbnail_type,
1025
 
                          gtk_theme_name,
1026
 
                          gtk_color_scheme,
1027
 
                          metacity_theme_name,
1028
 
                          icon_theme_name,
1029
 
                          application_font);
1030
 
}
1031
 
 
1032
 
void
1033
 
generate_meta_theme_thumbnail_async (GnomeThemeMetaInfo *theme_info,
1034
 
                                     ThemeThumbnailFunc  func,
1035
 
                                     gpointer            user_data,
1036
 
                                     GDestroyNotify      destroy)
1037
 
{
1038
 
  generate_theme_thumbnail_async (theme_info,
1039
 
                                         theme_info->name,
1040
 
                                         THUMBNAIL_TYPE_META,
1041
 
                                         theme_info->gtk_theme_name,
1042
 
                                         theme_info->gtk_color_scheme,
1043
 
                                         theme_info->metacity_theme_name,
1044
 
                                         theme_info->icon_theme_name,
1045
 
                                         theme_info->application_font,
1046
 
                                         func, user_data, destroy);
1047
 
}
1048
 
 
1049
 
void
1050
 
generate_gtk_theme_thumbnail_async (GnomeThemeInfo *theme_info,
1051
 
                                    ThemeThumbnailFunc  func,
1052
 
                                    gpointer            user_data,
1053
 
                                    GDestroyNotify      destroy)
1054
 
{
1055
 
  gchar *scheme;
1056
 
 
1057
 
  scheme = gtkrc_get_color_scheme_for_theme (theme_info->name);
1058
 
 
1059
 
  generate_theme_thumbnail_async (theme_info,
1060
 
                                  theme_info->name,
1061
 
                                  THUMBNAIL_TYPE_GTK,
1062
 
                                  theme_info->name,
1063
 
                                  scheme,
1064
 
                                  NULL,
1065
 
                                  NULL,
1066
 
                                  NULL,
1067
 
                                  func, user_data, destroy);
1068
 
  g_free (scheme);
1069
 
}
1070
 
 
1071
 
void
1072
 
generate_metacity_theme_thumbnail_async (GnomeThemeInfo *theme_info,
1073
 
                                         ThemeThumbnailFunc  func,
1074
 
                                         gpointer            user_data,
1075
 
                                         GDestroyNotify      destroy)
1076
 
{
1077
 
  generate_theme_thumbnail_async (theme_info,
1078
 
                                         theme_info->name,
1079
 
                                         THUMBNAIL_TYPE_METACITY,
1080
 
                                         NULL,
1081
 
                                         NULL,
1082
 
                                         theme_info->name,
1083
 
                                         NULL,
1084
 
                                         NULL,
1085
 
                                         func, user_data, destroy);
1086
 
}
1087
 
 
1088
 
void
1089
 
generate_icon_theme_thumbnail_async (GnomeThemeIconInfo *theme_info,
1090
 
                                     ThemeThumbnailFunc  func,
1091
 
                                     gpointer            user_data,
1092
 
                                     GDestroyNotify      destroy)
1093
 
{
1094
 
  generate_theme_thumbnail_async (theme_info,
1095
 
                                         theme_info->name,
1096
 
                                         THUMBNAIL_TYPE_ICON,
1097
 
                                         NULL,
1098
 
                                         NULL,
1099
 
                                         NULL,
1100
 
                                         theme_info->name,
1101
 
                                         NULL,
1102
 
                                         func, user_data, destroy);
1103
 
}
1104
 
 
1105
 
void
1106
 
theme_thumbnail_factory_init (int argc, char *argv[])
1107
 
{
1108
 
#ifndef __APPLE__
1109
 
  gint child_pid;
1110
 
#endif
1111
 
 
1112
 
  pipe (pipe_to_factory_fd);
1113
 
  pipe (pipe_from_factory_fd);
1114
 
 
1115
 
/* Apple's CoreFoundation classes must not be used from forked
1116
 
 * processes. Since freetype (and thus GTK) uses them, we simply
1117
 
 * disable the thumbnailer on MacOS for now. That means no thumbs
1118
 
 * until the thumbnailing process is rewritten, but at least we won't
1119
 
 * make apps crash. */
1120
 
#ifndef __APPLE__
1121
 
  child_pid = fork ();
1122
 
  if (child_pid == 0)
1123
 
  {
1124
 
    ThemeThumbnailData data;
1125
 
    GIOChannel *channel;
1126
 
 
1127
 
    /* Child */
1128
 
    gtk_init (&argc, &argv);
1129
 
 
1130
 
    close (pipe_to_factory_fd[1]);
1131
 
    pipe_to_factory_fd[1] = 0;
1132
 
    close (pipe_from_factory_fd[0]);
1133
 
    pipe_from_factory_fd[0] = 0;
1134
 
 
1135
 
    data.status = READY_FOR_THEME;
1136
 
    data.type = g_byte_array_new ();
1137
 
    data.control_theme_name = g_byte_array_new ();
1138
 
    data.gtk_color_scheme = g_byte_array_new ();
1139
 
    data.wm_theme_name = g_byte_array_new ();
1140
 
    data.icon_theme_name = g_byte_array_new ();
1141
 
    data.application_font = g_byte_array_new ();
1142
 
 
1143
 
    channel = g_io_channel_unix_new (pipe_to_factory_fd[0]);
1144
 
    g_io_channel_set_flags (channel, g_io_channel_get_flags (channel) |
1145
 
          G_IO_FLAG_NONBLOCK, NULL);
1146
 
    g_io_channel_set_encoding (channel, NULL, NULL);
1147
 
    g_io_add_watch (channel, G_IO_IN | G_IO_HUP, message_from_capplet, &data);
1148
 
    g_io_channel_unref (channel);
1149
 
 
1150
 
    gtk_main ();
1151
 
    _exit (0);
1152
 
  }
1153
 
 
1154
 
  g_assert (child_pid > 0);
1155
 
 
1156
 
  /* Parent */
1157
 
  close (pipe_to_factory_fd[0]);
1158
 
  close (pipe_from_factory_fd[1]);
1159
 
#endif /* __APPLE__ */
1160
 
 
1161
 
  async_data.set = FALSE;
1162
 
  async_data.theme_name = NULL;
1163
 
  async_data.data = g_byte_array_new ();
1164
 
}