diff options
author | Benjamin Otte <otte@redhat.com> | 2010-10-06 16:19:41 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2010-10-06 16:21:39 +0200 |
commit | 1857f00faa225c41a3d5d1ca5bce0c10e1c7deb6 (patch) | |
tree | 73d5da1065667eac146180ba9a53db8132493022 | |
parent | 211a61d40b3cbac8ac38d3efe17e885b00e85f0e (diff) | |
download | libwnck-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.c | 216 |
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) |