summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2010-10-06 16:19:41 +0200
committerBenjamin Otte <otte@redhat.com>2010-10-06 16:21:39 +0200
commit1857f00faa225c41a3d5d1ca5bce0c10e1c7deb6 (patch)
tree73d5da1065667eac146180ba9a53db8132493022
parent211a61d40b3cbac8ac38d3efe17e885b00e85f0e (diff)
downloadlibwnck-1857f00faa225c41a3d5d1ca5bce0c10e1c7deb6.tar.gz
tasklist: Reorganize how the glow button works
Instead of screenshotting twice and blending the two screenshots in a timeout handler, we now do the blending in the draw handler and only compute the glow factor in the timeout handler. This way we ensure that drawing only happens in the draw handler. Also, the code looks much nicer now.
-rw-r--r--libwnck/tasklist.c216
1 files changed, 61 insertions, 155 deletions
diff --git a/libwnck/tasklist.c b/libwnck/tasklist.c
index 5095898..1a21b7e 100644
--- a/libwnck/tasklist.c
+++ b/libwnck/tasklist.c
@@ -154,11 +154,9 @@ struct _WnckTask
guint32 dnd_timestamp;
- cairo_surface_t *screenshot;
- cairo_surface_t *screenshot_faded;
-
time_t start_needs_attention;
gdouble glow_start_time;
+ gdouble glow_factor;
guint button_glow;
@@ -364,21 +362,6 @@ static GType
wnck_task_get_type (void) G_GNUC_CONST;
static void
-cleanup_screenshots (WnckTask *task)
-{
- if (task->screenshot != NULL)
- {
- cairo_surface_destroy (task->screenshot);
- task->screenshot = NULL;
- }
- if (task->screenshot_faded != NULL)
- {
- cairo_surface_destroy (task->screenshot_faded);
- task->screenshot_faded = NULL;
- }
-}
-
-static void
wnck_task_init (WnckTask *task)
{
task->tasklist = NULL;
@@ -416,11 +399,9 @@ wnck_task_init (WnckTask *task)
task->dnd_timestamp = 0;
- task->screenshot = NULL;
- task->screenshot_faded = NULL;
-
task->start_needs_attention = 0;
task->glow_start_time = 0.0;
+ task->glow_factor = 0.0;
task->button_glow = 0;
@@ -450,16 +431,10 @@ static gboolean
wnck_task_button_glow (WnckTask *task)
{
GTimeVal tv;
- gdouble glow_factor, now;
+ gdouble now;
gfloat fade_opacity, loop_time;
gint fade_max_loops;
gboolean stopped;
- GdkWindow *window;
- GtkAllocation allocation;
- cairo_t *cr;
-
- if (task->screenshot == NULL)
- return TRUE;
g_get_current_time (&tv);
now = (tv.tv_sec * (1.0 * G_USEC_PER_SEC) +
@@ -476,45 +451,22 @@ wnck_task_button_glow (WnckTask *task)
if (task->button_glow == 0)
{
/* we're in "has stopped glowing" mode */
- glow_factor = fade_opacity * 0.5;
+ task->glow_factor = fade_opacity * 0.5;
stopped = TRUE;
}
else
{
- glow_factor = fade_opacity * (0.5 -
- 0.5 * cos ((now - task->glow_start_time) *
- M_PI * 2.0 / loop_time));
+ task->glow_factor = fade_opacity * (0.5 -
+ 0.5 * cos ((now - task->glow_start_time) *
+ M_PI * 2.0 / loop_time));
if (now - task->start_needs_attention > loop_time * 1.0 * fade_max_loops)
- stopped = ABS (glow_factor - fade_opacity * 0.5) < 0.05;
+ stopped = ABS (task->glow_factor - fade_opacity * 0.5) < 0.05;
else
stopped = FALSE;
}
- window = gtk_widget_get_window (task->button);
- gtk_widget_get_allocation (task->button, &allocation);
-
- gdk_window_begin_paint_rect (window, &allocation);
-
- cr = gdk_cairo_create (window);
- gdk_cairo_rectangle (cr, &allocation);
- cairo_translate (cr, allocation.x, allocation.y);
- cairo_clip (cr);
-
- cairo_save (cr);
-
- cairo_set_source_surface (cr, task->screenshot, 0., 0.);
- cairo_paint (cr);
-
- cairo_restore (cr);
-
- cairo_set_source_surface (cr, task->screenshot_faded, 0., 0.);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_paint_with_alpha (cr, glow_factor);
-
- cairo_destroy (cr);
-
- gdk_window_end_paint (window);
+ gtk_widget_queue_draw (task->button);
if (stopped)
wnck_task_stop_glow (task);
@@ -654,8 +606,6 @@ wnck_task_finalize (GObject *object)
wnck_task_stop_glow (task);
- cleanup_screenshots (task);
-
G_OBJECT_CLASS (wnck_task_parent_class)->finalize (object);
}
@@ -1559,8 +1509,6 @@ wnck_tasklist_size_allocate (GtkWidget *widget,
gtk_widget_set_child_visible (GTK_WIDGET (win_task->button), FALSE);
- cleanup_screenshots (win_task);
-
l = l->next;
}
}
@@ -1568,8 +1516,6 @@ wnck_tasklist_size_allocate (GtkWidget *widget,
{
visible_tasks = g_list_prepend (visible_tasks, class_group_task->windows->data);
gtk_widget_set_child_visible (GTK_WIDGET (class_group_task->button), FALSE);
-
- cleanup_screenshots (class_group_task);
}
button_width = wnck_tasklist_layout (allocation,
@@ -1588,8 +1534,6 @@ wnck_tasklist_size_allocate (GtkWidget *widget,
visible_tasks = g_list_concat (visible_tasks, g_list_copy (class_group_task->windows));
gtk_widget_set_child_visible (GTK_WIDGET (class_group_task->button), FALSE);
- cleanup_screenshots (class_group_task);
-
l = l->next;
}
@@ -3356,6 +3300,7 @@ wnck_task_update_visible_state (WnckTask *task)
{
_make_gtk_label_normal ((GTK_LABEL (task->label)));
wnck_task_stop_glow (task);
+ task->glow_factor = 0.0;
}
g_free (text);
}
@@ -3906,25 +3851,52 @@ wnck_task_create_widgets (WnckTask *task, GtkReliefStyle relief)
G_CONNECT_AFTER);
}
-static cairo_surface_t *
-take_screenshot (WnckTask *task)
+static gboolean
+wnck_task_draw (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data)
{
+ int x, y;
+ WnckTask *task;
+ GtkStyle *style;
+ GtkAllocation allocation, child_allocation;
WnckTasklist *tasklist;
- GtkWidget *tasklist_widget;
- cairo_surface_t *surface;
- GtkAllocation allocation;
- cairo_t *cr;
+ GtkWidget *tasklist_widget, *child;
gint width, height;
gboolean overlay_rect;
+ task = WNCK_TASK (data);
+
+ switch (task->type)
+ {
+ case WNCK_TASK_CLASS_GROUP:
+ style = gtk_widget_get_style (widget);
+
+ x = gtk_widget_get_allocated_width (widget) -
+ (gtk_container_get_border_width (GTK_CONTAINER (widget)) + style->ythickness + 12);
+ y = gtk_widget_get_allocated_height (widget) / 2 - 5;
+
+ gtk_paint_tab (style,
+ cr,
+ task->tasklist->priv->active_class_group == task ?
+ GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE, widget, NULL, x, y, 10, 10);
+ break;
+
+ case WNCK_TASK_WINDOW:
+ case WNCK_TASK_STARTUP_SEQUENCE:
+ break;
+ }
+
+ if (task->glow_factor == 0.0)
+ return FALSE;
+
+ /* push a translucent overlay to paint to, so we can blend later */
+ cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
+
width = gtk_widget_get_allocated_width (task->button);
height = gtk_widget_get_allocated_height (task->button);
- surface = gdk_window_create_similar_surface (gtk_widget_get_window (task->button),
- CAIRO_CONTENT_COLOR_ALPHA,
- width, height);
- cr = cairo_create (surface);
-
tasklist = WNCK_TASKLIST (task->tasklist);
tasklist_widget = GTK_WIDGET (task->tasklist);
@@ -3965,92 +3937,26 @@ take_screenshot (WnckTask *task)
g_object_unref (attached_style);
}
- /* then the image and label */
- cairo_save (cr);
- gtk_widget_get_allocation (task->image, &allocation);
- cairo_translate (cr, allocation.x, allocation.y);
- gtk_widget_draw (task->image, cr);
- cairo_restore (cr);
-
+ /* then the contents */
+
cairo_save (cr);
- gtk_widget_get_allocation (task->label, &allocation);
- cairo_translate (cr, allocation.x, allocation.y);
- gtk_widget_draw (task->label, cr);
+ gtk_widget_get_allocation (task->button, &allocation);
+ child = gtk_bin_get_child (GTK_BIN (task->button));
+ gtk_widget_get_allocation (child, &child_allocation);
+ cairo_translate (cr,
+ child_allocation.x - allocation.x,
+ child_allocation.y - allocation.y);
+ gtk_widget_draw (gtk_bin_get_child (GTK_BIN (task->button)), cr);
cairo_restore (cr);
-
- return surface;
-}
-
-static cairo_surface_t *
-copy_surface (GtkWidget *widget)
-{
- cairo_surface_t *surface;
- cairo_t *cr;
-
- surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
- CAIRO_CONTENT_COLOR_ALPHA,
- gtk_widget_get_allocated_width (widget),
- gtk_widget_get_allocated_height (widget));
-
- cr = cairo_create (surface);
- gtk_widget_draw (widget, cr);
- cairo_destroy (cr);
-
- return surface;
-}
-
-static gboolean
-wnck_task_draw (GtkWidget *widget,
- cairo_t *cr,
- gpointer data)
-{
- int x, y;
- WnckTask *task;
- GtkStyle *style;
-
- task = WNCK_TASK (data);
-
- cleanup_screenshots (task);
-
- switch (task->type)
- {
- case WNCK_TASK_CLASS_GROUP:
- style = gtk_widget_get_style (widget);
- x = gtk_widget_get_allocated_width (widget) -
- (gtk_container_get_border_width (GTK_CONTAINER (widget)) + style->ythickness + 12);
- y = gtk_widget_get_allocated_height (widget) / 2 - 5;
-
- gtk_paint_tab (style,
- cr,
- task->tasklist->priv->active_class_group == task ?
- GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
- GTK_SHADOW_NONE, widget, NULL, x, y, 10, 10);
-
- /* Fall through to get screenshot
- */
- case WNCK_TASK_WINDOW:
- if (task->start_needs_attention)
- {
- time_t attention = task->start_needs_attention;
-
- task->start_needs_attention = 0;
-
- task->screenshot = copy_surface (widget);
- task->screenshot_faded = take_screenshot (task);
-
- task->start_needs_attention = attention;
-
- wnck_task_button_glow (task);
- }
-
- case WNCK_TASK_STARTUP_SEQUENCE:
- break;
- }
+ /* finally blend it */
+ cairo_pop_group_to_source (cr);
+ cairo_paint_with_alpha (cr, task->glow_factor);
return FALSE;
}
+
static gint
wnck_task_compare_alphabetically (gconstpointer a,
gconstpointer b)