X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hildon%2Fhildon-pannable-area.c;h=f3f9effc8872478da3bb07afc6d5794e1205b36f;hb=5ac0144d169e602b4afbbb590a5735b1f2f4b55e;hp=18c4a11f74dbb262ae679210c31b775d124761bf;hpb=b37ebda02cb1766800778421b650adf35b83663b;p=hildon diff --git a/hildon/hildon-pannable-area.c b/hildon/hildon-pannable-area.c index 18c4a11..f3f9eff 100644 --- a/hildon/hildon-pannable-area.c +++ b/hildon/hildon-pannable-area.c @@ -57,6 +57,7 @@ #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 @@ -75,7 +76,7 @@ struct _HildonPannableAreaPrivate { 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; @@ -369,7 +370,7 @@ hildon_pannable_area_class_init (HildonPannableAreaClass * klass) "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)); @@ -440,7 +441,7 @@ hildon_pannable_area_class_init (HildonPannableAreaClass * klass) "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)); @@ -470,7 +471,7 @@ hildon_pannable_area_class_init (HildonPannableAreaClass * klass) "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)); @@ -630,7 +631,7 @@ hildon_pannable_area_init (HildonPannableArea * area) 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; @@ -647,7 +648,8 @@ hildon_pannable_area_init (HildonPannableArea * area) 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; @@ -823,7 +825,20 @@ hildon_pannable_area_set_property (GObject * object, 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 */ @@ -1469,22 +1484,15 @@ static void 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; } } @@ -1554,8 +1562,8 @@ hildon_pannable_area_scroll_indicator_fade(HildonPannableArea * area) 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; } @@ -1614,6 +1622,10 @@ hildon_pannable_area_expose_event (GtkWidget * widget, 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) { @@ -1702,13 +1714,6 @@ hildon_pannable_area_expose_event (GtkWidget * widget, } - 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); } @@ -1826,7 +1831,7 @@ hildon_pannable_area_button_press_cb (GtkWidget * widget, 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); @@ -1846,7 +1851,7 @@ hildon_pannable_area_button_press_cb (GtkWidget * widget, 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; @@ -2021,7 +2026,7 @@ hildon_pannable_axis_scroll (HildonPannableArea *area, 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 @@ -2147,7 +2152,7 @@ hildon_pannable_area_timeout (HildonPannableArea * area) return FALSE; } - if (!priv->clicked) { + if (!priv->button_pressed) { /* Decelerate gradually when pointer is raised */ if ((!priv->overshot_dist_y) && (!priv->overshot_dist_x)) { @@ -2264,7 +2269,7 @@ hildon_pannable_area_motion_notify_cb (GtkWidget * widget, 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; @@ -2500,7 +2505,7 @@ hildon_pannable_area_button_release_cb (GtkWidget * widget, 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; @@ -2559,15 +2564,15 @@ hildon_pannable_area_button_release_cb (GtkWidget * widget, } } - 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) { @@ -2586,6 +2591,12 @@ hildon_pannable_area_button_release_cb (GtkWidget * widget, 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) @@ -2743,6 +2754,32 @@ hildon_pannable_area_remove (GtkContainer *container, GtkWidget *child) 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) {