[gtk+] GtkEntry: Make progress pulsing smooth



commit ef0e164a4c9acf68dc12ea1493c7468dd5da7e0f
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jun 28 15:51:33 2014 -0400

    GtkEntry: Make progress pulsing smooth
    
    This changes the calculation of activity mode progress in the
    same way as was done in GtkProgressBar a while ago, and make it
    smooth, using a tick callback.

 gtk/gtkentry.c |  155 +++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 114 insertions(+), 41 deletions(-)
---
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index f438887..d77c50f 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -155,6 +155,11 @@ struct _GtkEntryPrivate
   gdouble       progress_pulse_fraction;
   gdouble       progress_pulse_current;
 
+  guint         tick_id;
+  gint64        pulse1;
+  gint64        pulse2;
+  gint64        frame1;
+
   gchar        *placeholder_text;
 
   GtkWidget     *bubble_window;
@@ -2970,6 +2975,9 @@ gtk_entry_finalize (GObject *object)
   EntryIconInfo *icon_info = NULL;
   gint i;
 
+  if (priv->tick_id)
+    gtk_widget_remove_tick_callback (GTK_WIDGET (entry), priv->tick_id);
+
   for (i = 0; i < MAX_ICONS; i++)
     {
       if ((icon_info = priv->icons[i]) != NULL)
@@ -10373,6 +10381,108 @@ gtk_entry_get_cursor_hadjustment (GtkEntry *entry)
   return g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
 }
 
+static gboolean
+tick_cb (GtkWidget     *widget,
+         GdkFrameClock *frame_clock,
+         gpointer       user_data)
+{
+  GtkEntry *entry = GTK_ENTRY (widget);
+  GtkEntryPrivate *priv = entry->priv;
+  gint64 frame2;
+  gdouble fraction;
+
+  frame2 = gdk_frame_clock_get_frame_time (frame_clock);
+  if (priv->frame1 == 0)
+    priv->frame1 = frame2 - 16667;
+  if (priv->pulse1 == 0)
+    priv->pulse1 = priv->pulse2 - 250 * 1000000;
+
+  g_assert (priv->pulse2 > priv->pulse1);
+  g_assert (frame2 > priv->frame1);
+
+  if (frame2 - priv->pulse2 > 3 * (priv->pulse2 - priv->pulse1))
+    {
+      priv->pulse1 = 0;
+      return G_SOURCE_CONTINUE;
+    }
+
+  /* Determine the fraction to move the block from one frame
+   * to the next when pulse_fraction is how far the block should
+   * move between two calls to gtk_entry_progress_pulse().
+   */
+  fraction = priv->progress_pulse_fraction * (frame2 - priv->frame1) / MAX (frame2 - priv->pulse2, 
priv->pulse2 - priv->pulse1);
+
+  priv->frame1 = frame2;
+
+  /* advance the block */
+  if (priv->progress_pulse_way_back)
+    {
+      priv->progress_pulse_current -= fraction;
+
+      if (priv->progress_pulse_current < 0.0)
+        {
+          priv->progress_pulse_current = 0.0;
+          priv->progress_pulse_way_back = FALSE;
+        }
+    }
+  else
+    {
+      priv->progress_pulse_current += fraction;
+
+      if (priv->progress_pulse_current > 1.0 - priv->progress_pulse_fraction)
+        {
+          priv->progress_pulse_current = 1.0 - priv->progress_pulse_fraction;
+          priv->progress_pulse_way_back = TRUE;
+        }
+    }
+
+  gtk_widget_queue_draw (widget);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+gtk_entry_start_pulse_mode (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv = entry->priv;
+
+  if (!priv->progress_pulse_mode)
+    {
+      priv->progress_pulse_mode = TRUE;
+      priv->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (entry), tick_cb, NULL, NULL);
+
+      priv->progress_fraction = 0.0;
+      priv->progress_pulse_way_back = FALSE;
+      priv->progress_pulse_current = 0.0;
+
+      priv->pulse2 = 0;
+      priv->pulse1 = 0;
+      priv->frame1 = 0;
+    }
+}
+
+static void
+gtk_entry_stop_pulse_mode (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv = entry->priv;
+
+  if (priv->progress_pulse_mode)
+    {
+      priv->progress_pulse_mode = FALSE;
+      gtk_widget_remove_tick_callback (GTK_WIDGET (entry), priv->tick_id);
+      priv->tick_id = 0;
+    }
+}
+
+static void
+gtk_entry_update_pulse (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv = entry->priv;
+
+  priv->pulse1 = priv->pulse2;
+  priv->pulse2 = g_get_monotonic_time ();
+}
+
 /**
  * gtk_entry_set_progress_fraction:
  * @entry: a #GtkEntry
@@ -10404,13 +10514,13 @@ gtk_entry_set_progress_fraction (GtkEntry *entry,
   else
     old_fraction = private->progress_fraction;
 
+  gtk_entry_stop_pulse_mode (entry);
+
   if (gtk_widget_is_drawable (widget))
     get_progress_area (widget, &old_x, &old_y, &old_width, &old_height);
 
   fraction = CLAMP (fraction, 0.0, 1.0);
-
   private->progress_fraction = fraction;
-  private->progress_pulse_mode = FALSE;
   private->progress_pulse_current = 0.0;
 
   if (gtk_widget_is_drawable (widget))
@@ -10469,9 +10579,6 @@ gtk_entry_set_progress_pulse_step (GtkEntry *entry,
   if (fraction != private->progress_pulse_fraction)
     {
       private->progress_pulse_fraction = fraction;
-
-      gtk_widget_queue_draw (GTK_WIDGET (entry));
-
       g_object_notify (G_OBJECT (entry), "progress-pulse-step");
     }
 }
@@ -10510,44 +10617,10 @@ gtk_entry_get_progress_pulse_step (GtkEntry *entry)
 void
 gtk_entry_progress_pulse (GtkEntry *entry)
 {
-  GtkEntryPrivate *private;
-
   g_return_if_fail (GTK_IS_ENTRY (entry));
 
-  private = entry->priv;
-
-  if (private->progress_pulse_mode)
-    {
-      if (private->progress_pulse_way_back)
-        {
-          private->progress_pulse_current -= private->progress_pulse_fraction;
-
-          if (private->progress_pulse_current < 0.0)
-            {
-              private->progress_pulse_current = 0.0;
-              private->progress_pulse_way_back = FALSE;
-            }
-        }
-      else
-        {
-          private->progress_pulse_current += private->progress_pulse_fraction;
-
-          if (private->progress_pulse_current > 1.0 - private->progress_pulse_fraction)
-            {
-              private->progress_pulse_current = 1.0 - private->progress_pulse_fraction;
-              private->progress_pulse_way_back = TRUE;
-            }
-        }
-    }
-  else
-    {
-      private->progress_fraction = 0.0;
-      private->progress_pulse_mode = TRUE;
-      private->progress_pulse_way_back = FALSE;
-      private->progress_pulse_current = 0.0;
-    }
-
-  gtk_widget_queue_draw (GTK_WIDGET (entry));
+  gtk_entry_start_pulse_mode (entry);
+  gtk_entry_update_pulse (entry);
 }
 
 /**


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