2009-01-15 Alejandro G. Castro <alex@igalia.com>
authorAlejandro G. Castro <alex@igalia.com>
Thu, 15 Jan 2009 13:58:08 +0000 (13:58 +0000)
committerAlejandro G. Castro <alex@igalia.com>
Thu, 15 Jan 2009 13:58:08 +0000 (13:58 +0000)
Added delayed motion notify event handling, this way we can
discard redrawing if more than 25 events arrive per second.

* src/hildon-pannable-area.c,
(hildon_pannable_area_init): Initialized the new private atributes
controlling this timeout
(hildon_pannable_area_dispose): Remove the timeout that controls
the motion notify events.
(hildon_pannable_area_scroll): Added a condition to control the
use of the acceleration.
(hildon_pannable_area_motion_event_scroll_timeout),
(hildon_pannable_area_motion_event_scroll): Added this two
functions, they handle the motion notify events inside the
timeout.
(hildon_pannable_area_motion_notify_cb): Replaced the direct call
to the scroll method with the new function.
(hildon_pannable_area_button_release_cb): We have to remove the
timeout handler and move to the last position if the last motion
events were not handled.

Fixes: NB#97028 (Pannable area updates on every motion event)

ChangeLog
src/hildon-pannable-area.c

index ee44934..b8b75a6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,29 @@
 2009-01-15  Alejandro G. Castro  <alex@igalia.com>
 
+       Added delayed motion notify event handling, this way we can
+       discard redrawing if more than 25 events arrive per second.
+
+       * src/hildon-pannable-area.c,
+       (hildon_pannable_area_init): Initialized the new private atributes
+       controlling this timeout
+       (hildon_pannable_area_dispose): Remove the timeout that controls
+       the motion notify events.
+       (hildon_pannable_area_scroll): Added a condition to control the
+       use of the acceleration.
+       (hildon_pannable_area_motion_event_scroll_timeout),
+       (hildon_pannable_area_motion_event_scroll): Added this two
+       functions, they handle the motion notify events inside the
+       timeout.
+       (hildon_pannable_area_motion_notify_cb): Replaced the direct call
+       to the scroll method with the new function.
+       (hildon_pannable_area_button_release_cb): We have to remove the
+       timeout handler and move to the last position if the last motion
+       events were not handled.
+
+       Fixes: NB#97028 (Pannable area updates on every motion event)
+
+2009-01-15  Alejandro G. Castro  <alex@igalia.com>
+
        * src/hildon-pannable-area.c,
        (hildon_pannable_area_get_topmost): Added a new parameter to
        filter the the windows that do not include those events. Added
index b108506..c09c6ef 100644 (file)
@@ -47,6 +47,7 @@
 #define RATIO_TOLERANCE 0.000001
 #define SCROLLBAR_FADE_DELAY 30
 #define SCROLL_FADE_TIMEOUT 10
+#define MOTION_EVENTS_PER_SECOND 25
 
 G_DEFINE_TYPE (HildonPannableArea, hildon_pannable_area, GTK_TYPE_BIN)
 
@@ -84,11 +85,14 @@ struct _HildonPannableAreaPrivate {
   guint idle_id;
   gdouble scroll_to_x;
   gdouble scroll_to_y;
+  gdouble motion_x;
+  gdouble motion_y;
   gint overshot_dist_x;
   gint overshot_dist_y;
   gint overshooting_y;
   gint overshooting_x;
   gdouble scroll_indicator_alpha;
+  gint motion_event_scroll_timeout;
   gint scroll_indicator_timeout;
   gint scroll_indicator_event_interrupt;
   gint scroll_delay_counter;
@@ -206,6 +210,9 @@ static void hildon_pannable_area_calculate_velocity (gdouble *vel,
                                                      gdouble dist,
                                                      gdouble vmax,
                                                      guint sps);
+static gboolean hildon_pannable_area_motion_event_scroll_timeout (HildonPannableArea *area);
+static void hildon_pannable_area_motion_event_scroll (HildonPannableArea *area,
+                                                      gdouble x, gdouble y);
 static gboolean hildon_pannable_area_motion_notify_cb (GtkWidget * widget,
                                                        GdkEventMotion * event);
 static gboolean hildon_pannable_area_button_release_cb (GtkWidget * widget,
@@ -472,6 +479,7 @@ hildon_pannable_area_init (HildonPannableArea * area)
   priv->vel_y = 0;
   priv->scroll_indicator_alpha = 0.0;
   priv->scroll_indicator_timeout = 0;
+  priv->motion_event_scroll_timeout = 0;
   priv->scroll_indicator_event_interrupt = 0;
   priv->scroll_delay_counter = SCROLLBAR_FADE_DELAY;
   priv->scroll_to_x = -1;
@@ -663,6 +671,11 @@ hildon_pannable_area_dispose (GObject * object)
     priv->scroll_indicator_timeout = 0;
   }
 
+  if (priv->motion_event_scroll_timeout){
+    g_source_remove (priv->motion_event_scroll_timeout);
+    priv->motion_event_scroll_timeout = 0;
+  }
+
   if (priv->hadjust) {
     g_object_unref (priv->hadjust);
     priv->hadjust = NULL;
@@ -1676,14 +1689,15 @@ hildon_pannable_area_scroll (HildonPannableArea *area,
    * initial scroll position to the new mouse co-ordinate. This means
    * when you get to the top of the page, dragging down works immediately.
    */
-  if (!sx) {
-    priv->x = priv->ex;
-  }
-
-  if (!sy) {
-    priv->y = priv->ey;
-  }
+  if (priv->mode == HILDON_PANNABLE_AREA_MODE_ACCEL) {
+      if (!sx) {
+        priv->x = priv->ex;
+      }
 
+      if (!sy) {
+        priv->y = priv->ey;
+      }
+    }
 }
 
 static gboolean
@@ -1757,6 +1771,44 @@ hildon_pannable_area_calculate_velocity (gdouble *vel,
 }
 
 static gboolean
+hildon_pannable_area_motion_event_scroll_timeout (HildonPannableArea *area)
+{
+  HildonPannableAreaPrivate *priv = area->priv;
+
+  if ((priv->motion_x != 0)||(priv->motion_y != 0))
+    hildon_pannable_area_scroll (area, priv->motion_x, priv->motion_y);
+
+  priv->motion_event_scroll_timeout = 0;
+
+  return FALSE;
+}
+
+static void
+hildon_pannable_area_motion_event_scroll (HildonPannableArea *area,
+                                          gdouble x, gdouble y)
+{
+  HildonPannableAreaPrivate *priv = area->priv;
+
+  if (priv->motion_event_scroll_timeout) {
+
+    priv->motion_x += x;
+    priv->motion_y += y;
+
+  } else {
+
+  /* we do not delay the first event but the next ones */
+    hildon_pannable_area_scroll (area, x, y);
+
+    priv->motion_x = 0;
+    priv->motion_y = 0;
+
+    priv->motion_event_scroll_timeout = gdk_threads_add_timeout
+      ((gint) (1000.0 / (gdouble) MOTION_EVENTS_PER_SECOND),
+       (GSourceFunc) hildon_pannable_area_motion_event_scroll_timeout, area);
+  }
+}
+
+static gboolean
 hildon_pannable_area_motion_notify_cb (GtkWidget * widget,
                                       GdkEventMotion * event)
 {
@@ -1852,7 +1904,7 @@ hildon_pannable_area_motion_notify_cb (GtkWidget * widget,
       /* Scroll by the amount of pixels the cursor has moved
        * since the last motion event.
        */
-      hildon_pannable_area_scroll (area, x, y);
+      hildon_pannable_area_motion_event_scroll (area, x, y);
       priv->x = event->x;
       priv->y = event->y;
       break;
@@ -1900,7 +1952,7 @@ hildon_pannable_area_motion_notify_cb (GtkWidget * widget,
         priv->vel_x = 0;
       }
 
-      hildon_pannable_area_scroll (area, x, y);
+      hildon_pannable_area_motion_event_scroll (area, x, y);
 
       if (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ)
         priv->x = event->x;
@@ -1950,6 +2002,12 @@ hildon_pannable_area_button_release_cb (GtkWidget * widget,
     priv->scroll_indicator_alpha = 1.0;
   }
 
+  /* move all the way to the last position */
+  if (priv->motion_event_scroll_timeout) {
+    g_source_remove (priv->motion_event_scroll_timeout);
+    hildon_pannable_area_motion_event_scroll_timeout (HILDON_PANNABLE_AREA (widget));
+  }
+
   if (!priv->scroll_indicator_timeout) {
     priv->scroll_indicator_timeout = gdk_threads_add_timeout
       ((gint) (1000.0 / (gdouble) SCROLL_FADE_TIMEOUT),