+2008-05-19 Alejandro G. Castro <alex@igalia.com>
+
+ Reviewed the interaction of the AUTO mode, now we use the time
+ attribute of the events and calculate the velocity in the motion,
+ doing a gimp like calculation. The velocity is calculated in each
+ motion event using the last velocity and the current one, the
+ SMOOTH_FACTOR controls the percentage of the new velocity we use.
+
+ * src/hildon-pannable-area.c: Replaced the time based algorithm
+ for the AUTO mode.
+ (hildon_pannable_area_motion_notify_cb): now we do not launch the
+ timeout for the AUTO mode when we are still moving the cursor. We
+ added also the velocity calculation in this function.
+ (hildon_pannable_area_button_release_cb): launch the timeout in
+ case we are in AUTO mode. There are still some constants here that
+ come from the old implementation that should be reviewed and
+ handled properly.
+
2008-05-15 Alberto Garcia <agarcia@igalia.com>
* doc/hildon-docs.sgml
* - 'Physical' mode for acceleration scrolling
*/
+#define SMOOTH_FACTOR 0.85
+#define FORCE 5
+
#include <gdk/gdkx.h>
#include "hildon-pannable-area.h"
guint32 last_time; /* Last event time, to stop infinite loops */
gint last_type;
gboolean moved;
- GTimeVal click_start;
- GTimeVal last_click;
gdouble vmin;
gdouble vmax;
gdouble decel;
};
-static gdouble
-hildon_get_time_delta (GTimeVal *start, GTimeVal *end)
-{
- gdouble x, y;
-
- x = start->tv_sec;
- x *= 1000000;
- x += start->tv_usec;
-
- y = end->tv_sec;
- y *= 1000000;
- y += end->tv_usec;
-
- return y-x;
-
-}
-
/* Following function inherited from libhildondesktop */
static GList *
get_ordered_children (GdkWindow *window)
event->time, FALSE);
}
- g_get_current_time (&priv->click_start);
priv->x = event->x;
priv->y = event->y;
priv->ix = priv->x;
return FALSE;
}
} else if (priv->mode == HILDON_PANNABLE_AREA_MODE_AUTO) {
- return TRUE;
+ priv->idle_id = 0;
+ return FALSE;
}
hildon_pannable_area_scroll (area, priv->vel_x, priv->vel_y, &sx, &sy);
HildonPannableAreaPrivate *priv = PANNABLE_AREA_PRIVATE (area);
gint dnd_threshold;
gdouble x, y;
+ gdouble delta, rawvel_x, rawvel_y;
+ gint direction_x, direction_y;
if ((!priv->enabled) || (!priv->clicked) ||
((event->time == priv->last_time) &&
if ((!priv->moved) && (
(ABS (x) > dnd_threshold) || (ABS (y) > dnd_threshold))) {
priv->moved = TRUE;
- if (priv->mode != HILDON_PANNABLE_AREA_MODE_PUSH) {
+ if ((priv->mode != HILDON_PANNABLE_AREA_MODE_PUSH)&&
+ (priv->mode != HILDON_PANNABLE_AREA_MODE_AUTO)) {
+
+ if (priv->idle_id)
+ g_source_remove (priv->idle_id);
+
priv->idle_id = g_timeout_add (
(gint)(1000.0/(gdouble)priv->sps),
(GSourceFunc)hildon_pannable_area_timeout,
(priv->vmax-priv->vmin)) + priv->vmin);
break;
case HILDON_PANNABLE_AREA_MODE_AUTO:
+
+ delta = event->time - priv->last_time;
+
+ rawvel_x = (((event->x - priv->x) / ABS (delta)) *
+ (gdouble)priv->sps) * FORCE;
+ rawvel_y = (((event->y - priv->y) / ABS (delta)) *
+ (gdouble)priv->sps) * FORCE;
+
+ /* we store the direction and after the calculation we
+ change it, this reduces the ifs for the calculation*/
+ direction_x = rawvel_x < 0 ? -1 : 1;
+ direction_y = rawvel_y < 0 ? -1 : 1;
+
+ rawvel_y = ABS (rawvel_y);
+ rawvel_x = ABS (rawvel_x);
+
+ priv->vel_x = priv->vel_x * (1 - SMOOTH_FACTOR) +
+ direction_x * rawvel_x * SMOOTH_FACTOR;
+ priv->vel_y = priv->vel_y * (1 - SMOOTH_FACTOR) +
+ direction_y * rawvel_y * SMOOTH_FACTOR;
+
+ priv->vel_x = priv->vel_x > 0 ? MIN (priv->vel_x, priv->vmax)
+ : MAX (priv->vel_x, -1 * priv->vmax);
+ priv->vel_y = priv->vel_y > 0 ? MIN (priv->vel_y, priv->vmax)
+ : MAX (priv->vel_y, -1 * priv->vmax);
+
hildon_pannable_area_scroll (area, x, y, NULL, NULL);
+
priv->x = event->x;
priv->y = event->y;
gpointer user_data)
{
HildonPannableAreaPrivate *priv = PANNABLE_AREA_PRIVATE (area);
- GTimeVal current;
gint x, y;
GdkWindow *child;
- gdouble delta, speed_x, speed_y;
if ((!priv->clicked) || (!priv->enabled) || (event->button != 1) ||
((event->time == priv->last_time) &&
(priv->last_type == 3)))
return TRUE;
+ if (priv->mode == HILDON_PANNABLE_AREA_MODE_AUTO)
+ {
+ if (priv->idle_id)
+ g_source_remove (priv->idle_id);
+
+ priv->idle_id = g_timeout_add (
+ (gint)(1000.0/(gdouble)priv->sps),
+ (GSourceFunc)hildon_pannable_area_timeout,
+ area);
+ }
+
priv->last_time = event->time;
priv->last_type = 3;
- g_get_current_time (¤t);
-
priv->clicked = FALSE;
- if (priv->mode == HILDON_PANNABLE_AREA_MODE_AUTO) {
- delta = hildon_get_time_delta (&priv->click_start, ¤t);
- speed_x = event->x - priv->click_x;
- speed_y = event->y - priv->click_y;
-
- speed_x = speed_x * 1000000 / delta;
- speed_y = speed_y * 1000000 / delta;
-
- priv->vel_x = speed_x * (gdouble)priv->sps / 1000;
- priv->vel_y = speed_y * (gdouble)priv->sps / 1000;
-
- /*if( ABS(priv->vel_x )<20)
- {
- priv->vel_x = 0;
- }
- if(ABS(priv->vel_y )<20)
- {
- priv->vel_y = 0;
- }*/
+ if (!priv->child) {
+ priv->moved = FALSE;
+ return TRUE;
}
child = hildon_pannable_area_get_topmost (
GTK_BIN (priv->align)->child->window,
event->x, event->y, &x, &y);
- if (!priv->child) {
- priv->moved = FALSE;
- return TRUE;
- }
-
event = (GdkEventButton *)gdk_event_copy ((GdkEvent *)event);
event->x = x;
event->y = y;