[libwnck/gtk3: 4/4] tasklist: Reorganize how the glow button works



commit 1857f00faa225c41a3d5d1ca5bce0c10e1c7deb6
Author: Benjamin Otte <otte redhat com>
Date:   Wed Oct 6 16:19:41 2010 +0200

    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.

 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)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]