#define SCROLL_FADE_TIMEOUT 100
#define MOTION_EVENTS_PER_SECOND 25
#define CURSOR_STOPPED_TIMEOUT 80
+#define MAX_SPEED_THRESHOLD 250
#define PANNABLE_MAX_WIDTH 788
#define PANNABLE_MAX_HEIGHT 378
gdouble ex; /* Used to store mouse co-ordinates of the last */
gdouble ey; /* motion event in acceleration mode */
gboolean enabled;
- gboolean clicked;
+ gboolean button_pressed;
guint32 last_time; /* Last event time, to stop infinite loops */
gint last_type;
gboolean last_in;
"Minimum scroll velocity",
"Minimum distance the child widget should scroll "
"per 'frame', in pixels per frame.",
- 0, G_MAXDOUBLE, 20,
+ 0, G_MAXDOUBLE, 10,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
"Threshold to consider a motion event an scroll",
"Amount of pixels to consider a motion event an scroll, if it is less"
"it is a click detected incorrectly by the touch screen.",
- 0, G_MAXUINT, 6,
+ 0, G_MAXUINT, 25,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
"Multiplier of the calculated speed",
"Force applied to the movement, multiplies the calculated speed of the"
"user movement the cursor in the screen",
- 0, G_MAXUINT, 120,
+ 0, G_MAXUINT, 50,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
area->priv = priv;
priv->moved = FALSE;
- priv->clicked = FALSE;
+ priv->button_pressed = FALSE;
priv->last_time = 0;
priv->last_type = 0;
priv->vscroll_visible = TRUE;
priv->scroll_indicator_timeout = 0;
priv->motion_event_scroll_timeout = 0;
priv->scroll_indicator_event_interrupt = 0;
- priv->scroll_delay_counter = priv->scrollbar_fade_delay;
+ priv->scroll_delay_counter = 0;
+ priv->scrollbar_fade_delay = 0;
priv->scroll_to_x = -1;
priv->scroll_to_y = -1;
priv->first_drag = TRUE;
priv->sps = g_value_get_uint (value);
break;
case PROP_PANNING_THRESHOLD:
- priv->panning_threshold = g_value_get_uint (value);
+ {
+ GtkSettings *settings = gtk_settings_get_default ();
+ GtkSettingsValue svalue = { NULL, { 0, }, };
+
+ priv->panning_threshold = g_value_get_uint (value);
+
+ /* insure gtk dnd is the same we are using, not allowed
+ different thresholds in the same application */
+ svalue.origin = "panning_threshold";
+ g_value_init (&svalue.value, G_TYPE_LONG);
+ g_value_set_long (&svalue.value, priv->panning_threshold);
+ gtk_settings_set_property_value (settings, "gtk-dnd-drag-threshold", &svalue);
+ g_value_unset (&svalue.value);
+ }
break;
case PROP_SCROLLBAR_FADE_DELAY:
/* convert to miliseconds */
hildon_pannable_area_initial_effect (GtkWidget * widget)
{
HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv;
- gboolean hscroll_visible, vscroll_visible;
-
- if (priv->initial_hint) {
- vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower >
- priv->vadjust->page_size);
- hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower >
- priv->hadjust->page_size);
+ if (priv->vscroll_visible || priv->hscroll_visible) {
- if (priv->vscroll_visible || priv->hscroll_visible) {
+ priv->scroll_indicator_event_interrupt = 0;
+ priv->scroll_delay_counter = priv->scrollbar_fade_delay;
- priv->scroll_indicator_event_interrupt = 0;
- priv->scroll_delay_counter = priv->scrollbar_fade_delay;
+ hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), 1.0);
- hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), 1.0);
- }
+ priv->initial_effect = FALSE;
}
}
HildonPannableAreaPrivate *priv = area->priv;
/* if moving do not fade out */
- if (((ABS (priv->vel_y)>1.0)||
- (ABS (priv->vel_x)>1.0))&&(!priv->clicked)) {
+ if (((ABS (priv->vel_y)>priv->vmin)||
+ (ABS (priv->vel_x)>priv->vmin))&&(!priv->button_pressed)) {
return TRUE;
}
GdkColor scroll_color = widget->style->fg[GTK_STATE_INSENSITIVE];
#endif
+ if (G_UNLIKELY ((priv->initial_hint) && (priv->initial_effect))) {
+ hildon_pannable_area_initial_effect (widget);
+ }
+
if (gtk_bin_get_child (GTK_BIN (widget))) {
if (priv->scroll_indicator_alpha > 0.1) {
}
- if (G_UNLIKELY (priv->initial_effect)) {
-
- hildon_pannable_area_initial_effect (widget);
-
- priv->initial_effect = FALSE;
- }
-
return GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->expose_event (widget, event);
}
priv->scroll_to_x = -1;
priv->scroll_to_y = -1;
- if (priv->clicked && priv->child) {
+ if (priv->button_pressed && priv->child) {
/* Widget stole focus on last click, send crossing-out event */
synth_crossing (priv->child, 0, 0, event->x_root, event->y_root,
event->time, FALSE);
else
priv->child = NULL;
- priv->clicked = TRUE;
+ priv->button_pressed = TRUE;
/* Stop scrolling on mouse-down (so you can flick, then hold to stop) */
priv->vel_x = 0;
gtk_adjustment_set_value (adjust, dist);
} else {
- if (!priv->clicked) {
+ if (!priv->button_pressed) {
/* When the overshoot has started we continue for
* PROP_BOUNCE_STEPS more steps into the overshoot before we
return FALSE;
}
- if (!priv->clicked) {
+ if (!priv->button_pressed) {
/* Decelerate gradually when pointer is raised */
if ((!priv->overshot_dist_y) &&
(!priv->overshot_dist_x)) {
if (gtk_bin_get_child (GTK_BIN (widget)) == NULL)
return TRUE;
- if ((!priv->enabled) || (!priv->clicked) ||
+ if ((!priv->enabled) || (!priv->button_pressed) ||
((event->time == priv->last_time) && (priv->last_type == 2))) {
gdk_window_get_pointer (widget->window, NULL, NULL, 0);
return TRUE;
if (((event->time == priv->last_time) && (priv->last_type == 3))
|| (gtk_bin_get_child (GTK_BIN (widget)) == NULL)
- || (!priv->clicked) || (!priv->enabled) || (event->button != 1))
+ || (!priv->button_pressed) || (!priv->enabled) || (event->button != 1))
return TRUE;
priv->scroll_indicator_event_interrupt = 0;
}
}
- if ((ABS (priv->vel_y) > 1.0)||
- (ABS (priv->vel_x) > 1.0)) {
+ if ((ABS (priv->vel_y) > priv->vmin)||
+ (ABS (priv->vel_x) > priv->vmin)) {
priv->scroll_indicator_alpha = 1.0;
}
hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget),
priv->scroll_indicator_alpha);
- priv->clicked = FALSE;
+ priv->button_pressed = FALSE;
if (priv->mode == HILDON_PANNABLE_AREA_MODE_AUTO ||
priv->mode == HILDON_PANNABLE_AREA_MODE_ACCEL) {
if ((ABS (priv->vel_y) >= priv->vmin) ||
(ABS (priv->vel_x) >= priv->vmin)) {
+ if (ABS (priv->vel_x) > MAX_SPEED_THRESHOLD)
+ priv->vel_x = (priv->vel_x > 0) ? priv->vmax : -priv->vmax;
+
+ if (ABS (priv->vel_y) > MAX_SPEED_THRESHOLD)
+ priv->vel_y = (priv->vel_y > 0) ? priv->vmax : -priv->vmax;
+
if (!priv->idle_id)
priv->idle_id = gdk_threads_add_timeout ((gint) (1000.0 / (gdouble) priv->sps),
(GSourceFunc)
GTK_CONTAINER_CLASS (hildon_pannable_area_parent_class)->remove (container, child);
}
+/**
+ * This method calculates a factor necessary to determine the initial distance
+ * to jump in hildon_pannable_area_scroll_to(). For fixed time and frames per
+ * second, we know in how many frames 'n' we need to reach the destination
+ * point. We know that, for a distance d,
+ *
+ * d = d_0 + d_1 + ... + d_n
+ *
+ * where d_i is the distance travelled in the i-th frame and decel_factor is
+ * the deceleration factor. This can be rewritten as
+ *
+ * d = d_0 + (d_0 * decel_factor) + ... + (d_n-1 * decel_factor),
+ *
+ * since the distance travelled on each frame is the distance travelled in the
+ * previous frame reduced by the deceleration factor. Reducing this and
+ * factoring d_0 out, we get
+ *
+ * d = d_0 (1 + decel_factor + ... + decel_factor^(n-1)).
+ *
+ * Since the sum is independent of the distance to be travelled, we can define
+ * vel_factor as
+ *
+ * vel_factor = 1 + decel_factor + ... + decel_factor^(n-1).
+ *
+ * That's the gem we calculate in this method.
+ **/
static void
hildon_pannable_calculate_vel_factor (HildonPannableArea * self)
{