Index: libwnck/tasklist.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/tasklist.c,v
retrieving revision 1.90
diff -r1.90 tasklist.c
125a126,127
>   GdkPixbuf *screenshot_fade1;
>   GdkPixbuf *screenshot_fade2;
202a205,206
>   
>   GdkPixmap *background;
241a246,247
> static gint     wnck_tasklist_expose        (GtkWidget        *widget,
>                                              GdkEventExpose    *event);
347a354,367
> static void
> cleanup_screenshots (WnckTask *task)
> {
>   if (task->screenshot != NULL)
>     {
>       g_object_unref (task->screenshot);
>       g_object_unref (task->screenshot_fade1);
>       g_object_unref (task->screenshot_fade2);
>       task->screenshot = NULL;
>       task->screenshot_fade1 = NULL;
>       task->screenshot_fade2 = NULL;
>     }
> }
> 
387a408,409
>   task->screenshot_fade1 = NULL;
>   task->screenshot_fade2 = NULL;
410c432
< glow_pixbuf (const GdkPixbuf *source, 
---
> glow_pixbuf (WnckTask        *task,
413,421d434
<   gint i, j;
<   gint width, height, has_alpha, rowstride;
<   guchar *destination_data;
<   guchar *source_data;
<   guchar *source_pixel;
<   guchar *destination_pixel;
<   int channel_intensity;
<   guchar r, g, b;
< 
422a436,437
>   
>   destination = gdk_pixbuf_copy (task->screenshot);
424,433c439
<   has_alpha = gdk_pixbuf_get_has_alpha (source);
<   width = gdk_pixbuf_get_width (source);
<   height = gdk_pixbuf_get_height (source);
<   rowstride = gdk_pixbuf_get_rowstride (source);
<   source_data = gdk_pixbuf_get_pixels (source);
< 
<   destination = gdk_pixbuf_copy (source);
<   destination_data = gdk_pixbuf_get_pixels (destination);
< 
<   for (i = 0; i < height; i++)
---
>   if (factor > 0)
435,466c441,453
<       source_pixel = source_data + i * rowstride;
<       destination_pixel = destination_data + i * rowstride;
< 
<       for (j = 0; j < width; j++)
<         {
<           enum
<             {
<               CHANNEL_RED = 0,
<               CHANNEL_GREEN,
<               CHANNEL_BLUE,
<               CHANNELS_PER_COLOR_STIMULUS
<             };
<           r = source_pixel[CHANNEL_RED];
<           g = source_pixel[CHANNEL_GREEN];
<           b = source_pixel[CHANNEL_BLUE];
<           source_pixel += CHANNELS_PER_COLOR_STIMULUS;
< 
<           channel_intensity = r * factor;
<           destination_pixel[CHANNEL_RED] = CLAMP (channel_intensity, 0, 255);
<           channel_intensity = g * factor;
<           destination_pixel[CHANNEL_GREEN] = CLAMP (channel_intensity, 0, 255);
<           channel_intensity = b * factor;
<           destination_pixel[CHANNEL_BLUE] = CLAMP (channel_intensity, 0, 255);
<           destination_pixel += CHANNELS_PER_COLOR_STIMULUS;
< 
<           if (has_alpha)
<             {
<               destination_pixel[0] = source_pixel[0];
<               source_pixel++;
<               destination_pixel++;
<             }
<         }
---
>       gdk_pixbuf_composite (task->screenshot_fade1, destination, 0, 0,
>                             gdk_pixbuf_get_width (task->screenshot),
>                             gdk_pixbuf_get_height (task->screenshot),
>                             0, 0, 1, 1, GDK_INTERP_NEAREST,
>                             ABS((int)(factor * G_MAXUINT8)));
>     }
>   else
>     {
>       gdk_pixbuf_composite (task->screenshot_fade2, destination, 0, 0,
>                             gdk_pixbuf_get_width (task->screenshot),
>                             gdk_pixbuf_get_height (task->screenshot),
>                             0, 0, 1, 1, GDK_INTERP_NEAREST,
>                             ABS((int)(factor * G_MAXUINT8)));
467a455
>   
476a465
>   gfloat fade_opacity, loop_time;
488,496c477,488
<   /* These numbers can probably be tweaked some.
<    * The 1.0 is the first value it will get and .4 is
<    * the "radius" from 1.0 that it will go; i.e.,
<    * it will go up from 1.0 to 1.4 then down from
<    * 1.4 to .6, then back up again. The 2.0 in the
<    * denomator is how many seconds it takes to travel 
<    * through the entire range of numbers.
<    */
<   glow_factor = .4 * sin ((now - task->glow_start_time) * (2.0 * M_PI) / 2.0) + 1.0;
---
>   gtk_widget_style_get (GTK_WIDGET (task->tasklist), "fade-opacity", &fade_opacity,
>                                                      "fade-loop-time", &loop_time,
>                                                      NULL);
>   
>   /* This is basically a cos curve which is moved up by 1, and every second
>    * iteration is flipped down.
>    * So below is a cos function, that is between 0 and 1 starting at 0. */
>   glow_factor = fade_opacity * (0.5 - 0.5 * cos ((now - task->glow_start_time) * M_PI * 4.0 / loop_time));
> 
>   /* and this will flip every second iteration down. */
>   if ((int)((now - task->glow_start_time) / loop_time * 2.0) % 2 == 1)
>   	glow_factor = -glow_factor;
498c490
<   glowing_screenshot = glow_pixbuf (task->screenshot, glow_factor);
---
>   glowing_screenshot = glow_pixbuf (task, glow_factor);
705a698,699
>   
>   tasklist->priv->background = NULL;
728a723
>   widget_class->expose_event = wnck_tasklist_expose;
731a727,774
>   
>   gtk_widget_class_install_style_property (widget_class,
>                                            g_param_spec_boolean ("fade-using-state",
>                                                                  ("Whether or not the Tasklist uses the theme to do fading."),
>                                                                  ("If set to TRUE the Tasklist will fade between the current state and the one selected in fade_state. Default: FALSE"),
>                                                                  FALSE,
>                                                                  G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
>   gtk_widget_class_install_style_property (widget_class,
>                                            g_param_spec_enum ("fade-state1",
>                                                               ("Sets the state used to do the fading."),
>                                                               ("Sets the state used to do the fading. Default: GTK_STATE_PRELIGHT"),
>                                                               GTK_TYPE_STATE_TYPE,
>                                                               GTK_STATE_PRELIGHT,
>                                                               G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
>   gtk_widget_class_install_style_property (widget_class,
>                                            g_param_spec_enum ("fade-state2",
>                                                               ("Sets the state used to do the fading."),
>                                                               ("Sets the state used to do the fading. Default: GTK_STATE_PRELIGHT"),
>                                                               GTK_TYPE_STATE_TYPE,
>                                                               GTK_STATE_PRELIGHT,
>                                                               G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
>   gtk_widget_class_install_style_property (widget_class,
>                                            g_param_spec_boxed ("fade-color1",
>                                                                ("Sets the first color used for the fading."),
>                                                                (""),
>                                                                GDK_TYPE_COLOR,
>                                                                G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
> 
>   gtk_widget_class_install_style_property (widget_class,
>                                            g_param_spec_boxed ("fade-color2",
>                                                                ("Sets the second color used for the fading."),
>                                                                (""),
>                                                                GDK_TYPE_COLOR,
>                                                                G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
>   
>   gtk_widget_class_install_style_property (widget_class,
>                                            g_param_spec_float ("fade-opacity",
>                                                               ("The final opacity that will be reached."),
>                                                               (""),
>                                                               0.0, 1.0, 0.4,
>                                                               G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
>   
>   gtk_widget_class_install_style_property (widget_class,
>                                            g_param_spec_float ("fade-loop-time",
>                                                               ("The time one loop takes when fading in seconds."),
>                                                               (""),
>                                                               0.2, 10.0, 3.0,
>                                                               G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
800a844,846
>   g_object_unref (tasklist->priv->background);
>   tasklist->priv->background = NULL;
>   
1346,1350c1392,1393
<               if (win_task->screenshot != NULL)
<                 {
<                   g_object_unref (win_task->screenshot);
<                   win_task->screenshot = NULL;
<                 }
---
>               cleanup_screenshots (win_task);
>               
1359,1363c1402
<           if (class_group_task->screenshot != NULL)
<             {
<               g_object_unref (class_group_task->screenshot);
<               class_group_task->screenshot = NULL;
<             }
---
>           cleanup_screenshots (class_group_task);
1381,1385c1420,1421
<       if (class_group_task->screenshot != NULL)
<         {
<           g_object_unref (class_group_task->screenshot);
<           class_group_task->screenshot = NULL;
<         }
---
>       
>       cleanup_screenshots (class_group_task);
1493a1530,1562
> static gint
> wnck_tasklist_expose (GtkWidget      *widget,
>                       GdkEventExpose *event)
> {
>   WnckTasklist *tasklist;
>   GdkGC *gc;
>   
>   g_return_val_if_fail (WNCK_IS_TASKLIST (widget), FALSE);
>   g_return_val_if_fail (event != NULL, FALSE);
>   
>   if (GTK_WIDGET_DRAWABLE (widget))
>     {
>       tasklist = WNCK_TASKLIST (widget);
>       /* get a screenshot of the background */
>       
>       if (tasklist->priv->background != NULL)
>         g_object_unref (tasklist->priv->background);
>       
>       tasklist->priv->background = gdk_pixmap_new (widget->window,
>                                                    widget->allocation.width,
>                                                    widget->allocation.height,
>                                                    -1);
>       gc = gdk_gc_new (tasklist->priv->background);
>       gdk_draw_drawable (tasklist->priv->background, gc, widget->window,
>                          widget->allocation.x, widget->allocation.y, 0, 0,
>                          widget->allocation.width, widget->allocation.height);
>       
>       g_object_unref (gc);
>     }
>   
>   return (* GTK_WIDGET_CLASS (tasklist_parent_class)->expose_event) (widget, event);
> }
> 
3173a3243,3346
> static void
> fake_expose_widget (GtkWidget *widget,
>                     GdkPixmap *pixmap,
>                     gint       x,
>                     gint       y)
> {
>   GdkWindow *tmp_window;
>   GdkEventExpose event;
> 
>   event.type = GDK_EXPOSE;
>   event.window = pixmap;
>   event.send_event = FALSE;
>   event.region = NULL;
>   event.count = 0;
> 
>   tmp_window = widget->window;
>   widget->window = pixmap;
>   widget->allocation.x += x;
>   widget->allocation.y += y;
> 
>   event.area = widget->allocation;
> 
>   gtk_widget_send_expose (widget, (GdkEvent *) &event);
> 
>   widget->window = tmp_window;
>   widget->allocation.x -= x;
>   widget->allocation.y -= y;
> }
> 
> static GdkPixbuf*
> take_screenshot (WnckTask *task, gint pos)
> {
>   WnckTasklist *tasklist;
>   GtkWidget    *tasklist_widget;
>   GdkGC *gc;
>   GdkPixmap *pixmap;
>   GdkPixbuf *screenshot;
>   gint width, height;
>   gboolean fade_using_state;
>   
>   width = task->button->allocation.width;
>   height = task->button->allocation.height;
>   
>   pixmap = gdk_pixmap_new (task->button->window, width, height, -1);
>   
>   tasklist = WNCK_TASKLIST (task->tasklist);
>   tasklist_widget = GTK_WIDGET (task->tasklist);
> 
> 
>   gc = gdk_gc_new (pixmap);
>   
>   /* first draw the button */
>   gtk_widget_style_get (tasklist_widget, "fade-using-state", &fade_using_state, NULL);
>   if (!fade_using_state)
>     {
>       GdkColor *color;
>       
>       if (pos == 1)
>         gtk_widget_style_get (tasklist_widget, "fade-color1", &color, NULL);
>       else
>         gtk_widget_style_get (tasklist_widget, "fade-color2", &color, NULL);
>       
>       if (color == NULL)
>         color = gdk_color_copy (&task->button->style->base[GTK_STATE_SELECTED]);
>         
>       gdk_gc_set_rgb_fg_color (gc, color);
>       gdk_draw_rectangle (pixmap, gc, TRUE, 0, 0, width + 1, height + 1);
>       
>       gdk_color_free (color);
>     }
>   else
>     {
>       GtkStateType state;
>       if (pos == 1)
>         gtk_widget_style_get (tasklist_widget, "fade-state1", &state, NULL);
>       else
>         gtk_widget_style_get (tasklist_widget, "fade-state2", &state, NULL);
>       
>       /* copy the background */
>       gdk_draw_drawable (pixmap, gc, tasklist->priv->background,
>                          task->button->allocation.x, task->button->allocation.y,
>                          0, 0, width, height);
>       
>       /* draw the button */
>       gtk_paint_box (task->button->style, (GdkWindow*) pixmap,
>                      state, GTK_SHADOW_OUT, NULL, task->button, "button",
>                      0, 0, width, height);
>     }
>   g_object_unref (gc);
>   
>   /* then the image and label */
>   fake_expose_widget (task->image, pixmap,
>                       -task->button->allocation.x, -task->button->allocation.y);
>   fake_expose_widget (task->label, pixmap,
>                       -task->button->allocation.x, -task->button->allocation.y);
>   
>   /* get the screenshot, and return */
>   screenshot = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0,
>                                              0, 0, width, height);
>   g_object_unref (pixmap);
>   
>   return screenshot;
> }
> 
3185a3359,3361
>   if (task->button_glow == 0)
>     cleanup_screenshots (task);
>   
3211,3217d3386
< 
<           if (task->screenshot != NULL)
<             {
<               g_object_unref (task->screenshot);
<               task->screenshot = NULL;
<             }
< 
3227a3397,3400
>               
>               /* we also need to take screenshots for screenshot_fade1 and screenshot_fade2 */
>               task->screenshot_fade1 = take_screenshot (task, 1);
>               task->screenshot_fade2 = take_screenshot (task, 2);
3233,3239d3405
<     }
< 
<   if ((task->button_glow == 0) &&
<       (task->screenshot != NULL))
<     {
<       g_object_unref (task->screenshot);
<       task->screenshot = NULL;
