summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler <raster@rasterman.com>2011-06-09 10:14:16 +0000
committerCarsten Haitzler <raster@rasterman.com>2011-06-09 10:14:16 +0000
commite7698f53e2571a8142bf50f7ddbd232f8057633a (patch)
tree7c40710cbe47a6da836e37c67d8fde7d3578d306
parent3f5b8095d7e3065ef4fc3ba47d5867c4179f2804 (diff)
scroller smoothing stuff.
SVN revision: 60126
-rw-r--r--config/illume/base.src3
-rw-r--r--config/standard/base.src3
-rw-r--r--src/lib/elm_config.c12
-rw-r--r--src/lib/elm_priv.h3
-rw-r--r--src/lib/els_scroller.c144
5 files changed, 158 insertions, 7 deletions
diff --git a/config/illume/base.src b/config/illume/base.src
index d5f558a67..02a73c57e 100644
--- a/config/illume/base.src
+++ b/config/illume/base.src
@@ -12,6 +12,9 @@ group "Elm_Config" struct {
12 value "bring_in_scroll_friction" double: 0.5; 12 value "bring_in_scroll_friction" double: 0.5;
13 value "zoom_friction" double: 0.5; 13 value "zoom_friction" double: 0.5;
14 value "thumbscroll_border_friction" double: 0.5; 14 value "thumbscroll_border_friction" double: 0.5;
15 value "scroll_smooth_amount" double: 1.0;
16 value "scroll_smooth_history_weight" double: 0.3;
17 value "scroll_smooth_future_time" double: 0.033;
15 value "scale" double: 1.0; 18 value "scale" double: 1.0;
16 value "bgpixmap" int: 0; 19 value "bgpixmap" int: 0;
17 value "compositing" int: 1; 20 value "compositing" int: 1;
diff --git a/config/standard/base.src b/config/standard/base.src
index 3b18fa10a..d87ce46eb 100644
--- a/config/standard/base.src
+++ b/config/standard/base.src
@@ -12,6 +12,9 @@ group "Elm_Config" struct {
12 value "bring_in_scroll_friction" double: 0.5; 12 value "bring_in_scroll_friction" double: 0.5;
13 value "zoom_friction" double: 0.5; 13 value "zoom_friction" double: 0.5;
14 value "thumbscroll_border_friction" double: 0.5; 14 value "thumbscroll_border_friction" double: 0.5;
15 value "scroll_smooth_amount" double: 0.0;
16 value "scroll_smooth_history_weight" double: 0.3;
17 value "scroll_smooth_future_time" double: 0.033;
15 value "scale" double: 1.0; 18 value "scale" double: 1.0;
16 value "bgpixmap" int: 0; 19 value "bgpixmap" int: 0;
17 value "compositing" int: 1; 20 value "compositing" int: 1;
diff --git a/src/lib/elm_config.c b/src/lib/elm_config.c
index 3dad01622..9465b9b53 100644
--- a/src/lib/elm_config.c
+++ b/src/lib/elm_config.c
@@ -568,6 +568,9 @@ _desc_init(void)
568 ELM_CONFIG_VAL(D, T, bring_in_scroll_friction, T_DOUBLE); 568 ELM_CONFIG_VAL(D, T, bring_in_scroll_friction, T_DOUBLE);
569 ELM_CONFIG_VAL(D, T, zoom_friction, T_DOUBLE); 569 ELM_CONFIG_VAL(D, T, zoom_friction, T_DOUBLE);
570 ELM_CONFIG_VAL(D, T, thumbscroll_bounce_enable, T_UCHAR); 570 ELM_CONFIG_VAL(D, T, thumbscroll_bounce_enable, T_UCHAR);
571 ELM_CONFIG_VAL(D, T, scroll_smooth_amount, T_DOUBLE);
572 ELM_CONFIG_VAL(D, T, scroll_smooth_history_weight, T_DOUBLE);
573 ELM_CONFIG_VAL(D, T, scroll_smooth_future_time, T_DOUBLE);
571 ELM_CONFIG_VAL(D, T, scale, T_DOUBLE); 574 ELM_CONFIG_VAL(D, T, scale, T_DOUBLE);
572 ELM_CONFIG_VAL(D, T, bgpixmap, T_INT); 575 ELM_CONFIG_VAL(D, T, bgpixmap, T_INT);
573 ELM_CONFIG_VAL(D, T, compositing, T_INT); 576 ELM_CONFIG_VAL(D, T, compositing, T_INT);
@@ -1118,6 +1121,9 @@ _config_load(void)
1118 _elm_config->bring_in_scroll_friction = 0.5; 1121 _elm_config->bring_in_scroll_friction = 0.5;
1119 _elm_config->zoom_friction = 0.5; 1122 _elm_config->zoom_friction = 0.5;
1120 _elm_config->thumbscroll_border_friction = 0.5; 1123 _elm_config->thumbscroll_border_friction = 0.5;
1124 _elm_config->scroll_smooth_amount = 1.0;
1125 _elm_config->scroll_smooth_history_weight = 0.3;
1126 _elm_config->scroll_smooth_future_time = 2.0 / 60.0;
1121 _elm_config->scale = 1.0; 1127 _elm_config->scale = 1.0;
1122 _elm_config->bgpixmap = 0; 1128 _elm_config->bgpixmap = 0;
1123 _elm_config->compositing = 1; 1129 _elm_config->compositing = 1;
@@ -1469,6 +1475,12 @@ _env_get(void)
1469 1475
1470 _elm_config->thumbscroll_border_friction = friction; 1476 _elm_config->thumbscroll_border_friction = friction;
1471 } 1477 }
1478 s = getenv("ELM_SCROLL_SMOOTH_AMOUNT");
1479 if (s) _elm_config->scroll_smooth_amount = atof(s);
1480 s = getenv("ELM_SCROLL_SMOOTH_HISTORY_WEIGHT");
1481 if (s) _elm_config->scroll_smooth_history_weight = atof(s);
1482 s = getenv("ELM_SCROLL_SMOOTH_FUTURE_TIME");
1483 if (s) _elm_config->scroll_smooth_future_time = atof(s);
1472 s = getenv("ELM_THEME"); 1484 s = getenv("ELM_THEME");
1473 if (s) eina_stringshare_replace(&_elm_config->theme, s); 1485 if (s) eina_stringshare_replace(&_elm_config->theme, s);
1474 1486
diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h
index af2d89ede..4e02833f5 100644
--- a/src/lib/elm_priv.h
+++ b/src/lib/elm_priv.h
@@ -96,6 +96,9 @@ struct _Elm_Config
96 double zoom_friction; 96 double zoom_friction;
97 unsigned char thumbscroll_bounce_enable; 97 unsigned char thumbscroll_bounce_enable;
98 double thumbscroll_border_friction; 98 double thumbscroll_border_friction;
99 double scroll_smooth_amount;
100 double scroll_smooth_history_weight;
101 double scroll_smooth_future_time;
99 double scale; 102 double scale;
100 int bgpixmap; 103 int bgpixmap;
101 int compositing; 104 int compositing;
diff --git a/src/lib/els_scroller.c b/src/lib/els_scroller.c
index 40721cb3f..bf513632c 100644
--- a/src/lib/els_scroller.c
+++ b/src/lib/els_scroller.c
@@ -36,8 +36,12 @@ struct _Smart_Data
36 Evas_Coord b2x, b2y; 36 Evas_Coord b2x, b2y;
37 struct { 37 struct {
38 Evas_Coord x, y; 38 Evas_Coord x, y;
39 double timestamp; 39 double timestamp, localtimestamp;
40 } history[20]; 40 } history[60];
41 struct {
42 double tadd, dxsum, dysum;
43 double est_timestamp_diff;
44 } hist;
41 double anim_start; 45 double anim_start;
42 double anim_start2; 46 double anim_start2;
43 double anim_start3; 47 double anim_start3;
@@ -1589,6 +1593,8 @@ _smart_event_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSE
1589 } 1593 }
1590 if (ev->button == 1) 1594 if (ev->button == 1)
1591 { 1595 {
1596 sd->down.hist.est_timestamp_diff =
1597 ecore_loop_time_get() - ((double)ev->timestamp / 1000.0);
1592 sd->down.now = 1; 1598 sd->down.now = 1;
1593 sd->down.dragged = 0; 1599 sd->down.dragged = 0;
1594 sd->down.dir_x = 0; 1600 sd->down.dir_x = 0;
@@ -1599,9 +1605,10 @@ _smart_event_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSE
1599 sd->down.sx = x; 1605 sd->down.sx = x;
1600 sd->down.sy = y; 1606 sd->down.sy = y;
1601 sd->down.locked = 0; 1607 sd->down.locked = 0;
1602 memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 20); 1608 memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 60);
1603#ifdef EVTIME 1609#ifdef EVTIME
1604 sd->down.history[0].timestamp = ev->timestamp / 1000.0; 1610 sd->down.history[0].timestamp = ev->timestamp / 1000.0;
1611 sd->down.history[0].localtimestamp = ecore_loop_time_get();
1605#else 1612#else
1606 sd->down.history[0].timestamp = ecore_loop_time_get(); 1613 sd->down.history[0].timestamp = ecore_loop_time_get();
1607#endif 1614#endif
@@ -1614,12 +1621,131 @@ _smart_event_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSE
1614 } 1621 }
1615} 1622}
1616 1623
1624static void
1625_down_coord_eval(Smart_Data *sd, Evas_Coord *x, Evas_Coord *y)
1626{
1627 Evas_Coord minx, miny;
1628
1629 if (sd->down.dir_x) *x = sd->down.sx - (*x - sd->down.x);
1630 else *x = sd->down.sx;
1631 if (sd->down.dir_y) *y = sd->down.sy - (*y - sd->down.y);
1632 else *y = sd->down.sy;
1633
1634 if ((sd->down.dir_x) || (sd->down.dir_y))
1635 {
1636 if (!((sd->down.dir_x) && (sd->down.dir_y)))
1637 {
1638 if (sd->down.dir_x) *y = sd->down.locked_y;
1639 else *x = sd->down.locked_x;
1640 }
1641 }
1642
1643 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1644
1645 if (*x < minx)
1646 *x += (minx - *x) * _elm_config->thumbscroll_border_friction;
1647 else if (sd->child.w <= sd->w)
1648 *x += (sd->down.sx - *x) * _elm_config->thumbscroll_border_friction;
1649 else if ((sd->child.w - sd->w + minx) < *x)
1650 *x += (sd->child.w - sd->w + minx - *x) *
1651 _elm_config->thumbscroll_border_friction;
1652
1653 if (*y < miny)
1654 *y += (miny - *y) * _elm_config->thumbscroll_border_friction;
1655 else if (sd->child.h <= sd->h)
1656 *y += (sd->down.sy - *y) * _elm_config->thumbscroll_border_friction;
1657 else if ((sd->child.h - sd->h + miny) < *y)
1658 *y += (sd->child.h - sd->h + miny - *y) *
1659 _elm_config->thumbscroll_border_friction;
1660}
1661
1617static Eina_Bool 1662static Eina_Bool
1618_smart_hold_animator(void *data) 1663_smart_hold_animator(void *data)
1619{ 1664{
1620 Smart_Data *sd = data; 1665 Smart_Data *sd = data;
1621 Evas_Coord ox, oy; 1666 Evas_Coord ox = 0, oy = 0, fx, fy;
1667
1668 fx = sd->down.hold_x;
1669 fy = sd->down.hold_y;
1670 if (_elm_config->scroll_smooth_amount > 0.0)
1671 {
1672 int i, count = 0;
1673 Evas_Coord basex, basey, x, y;
1674 double dt, t, tdiff, tnow;
1675 struct {
1676 Evas_Coord x, y, dx, dy;
1677 double t, dt;
1678 } pos[60];
1679
1680 // FIXME: assume server and client have the same "timezone"
1681 // (0 timepoint) for now. this needs to be figured out in advance
1682 // though.
1683 tdiff = sd->down.hist.est_timestamp_diff;
1684 tnow = ecore_time_get() - tdiff;
1685 t = tnow;
1686 for (i = 0; i < 60; i++)
1687 {
1688 // oldest point is sd->down.history[i]
1689 // newset is sd->down.history[0]
1690 dt = t - sd->down.history[i].timestamp;
1691 if (dt > 0.1)
1692 {
1693 i--;
1694 break;
1695 }
1696 x = sd->down.history[i].x;
1697 y = sd->down.history[i].y;
1698 _down_coord_eval(sd, &x, &y);
1699 if (i == 0)
1700 {
1701 basex = x;
1702 basey = y;
1703 }
1704 pos[i].x = x - basex;
1705 pos[i].y = y - basey;
1706 pos[i].t =
1707 sd->down.history[i].timestamp - sd->down.history[0].timestamp;
1708 count++;
1709 }
1710 count = i;
1711 if (count >= 2)
1712 {
1713 double dtsum = 0.0, tadd, maxdt;
1714 double dxsum = 0.0, dysum = 0.0, xsum = 0.0, ysum = 0.0;
1622 1715
1716 for (i = 0; i < (count - 1); i++)
1717 {
1718 pos[i].dx = pos[i].x - pos[i + 1].x;
1719 pos[i].dy = pos[i].y - pos[i + 1].y;
1720 pos[i].dt = pos[i].t - pos[i + 1].t;
1721 dxsum += pos[i].dx;
1722 dysum += pos[i].dy;
1723 dtsum += pos[i].dt;
1724 xsum += pos[i].x;
1725 ysum += pos[i].y;
1726 }
1727 maxdt = pos[i].t;
1728 dxsum /= (double)i;
1729 dysum /= (double)i;
1730 dtsum /= (double)i;
1731 xsum /= (double)i;
1732 ysum /= (double)i;
1733 tadd = tnow - sd->down.history[0].timestamp + _elm_config->scroll_smooth_future_time;
1734 tadd = tadd - (maxdt / 2);
1735#define WEIGHT(n, o, v) n = (o * (v - 1.0)) + (n * v)
1736 WEIGHT(tadd, sd->down.hist.tadd, _elm_config->scroll_smooth_history_weight);
1737 WEIGHT(dxsum, sd->down.hist.dxsum, _elm_config->scroll_smooth_history_weight);
1738 WEIGHT(dysum, sd->down.hist.dysum, _elm_config->scroll_smooth_history_weight);
1739 fx = basex + xsum + ((dxsum * tadd) / dtsum);
1740 fy = basey + ysum + ((dysum * tadd) / dtsum);
1741 sd->down.hist.tadd = tadd;
1742 sd->down.hist.dxsum = dxsum;
1743 sd->down.hist.dysum = dysum;
1744 fx = WEIGHT(fx, sd->down.hold_x, _elm_config->scroll_smooth_amount);
1745 fy = WEIGHT(fy, sd->down.hold_y, _elm_config->scroll_smooth_amount);
1746 }
1747 }
1748
1623 elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy); 1749 elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy);
1624 if (sd->down.dir_x) 1750 if (sd->down.dir_x)
1625 { 1751 {
@@ -1627,6 +1753,7 @@ _smart_hold_animator(void *data)
1627 (!elm_widget_drag_child_locked_x_get(sd->widget))) 1753 (!elm_widget_drag_child_locked_x_get(sd->widget)))
1628 { 1754 {
1629 ox = sd->down.hold_x; 1755 ox = sd->down.hold_x;
1756 ox = fx;
1630 } 1757 }
1631 } 1758 }
1632 if (sd->down.dir_y) 1759 if (sd->down.dir_y)
@@ -1635,8 +1762,10 @@ _smart_hold_animator(void *data)
1635 (!elm_widget_drag_child_locked_y_get(sd->widget))) 1762 (!elm_widget_drag_child_locked_y_get(sd->widget)))
1636 { 1763 {
1637 oy = sd->down.hold_y; 1764 oy = sd->down.hold_y;
1765 oy = fy;
1638 } 1766 }
1639 } 1767 }
1768
1640 elm_smart_scroller_child_pos_set(sd->smart_obj, ox, oy); 1769 elm_smart_scroller_child_pos_set(sd->smart_obj, ox, oy);
1641 return ECORE_CALLBACK_RENEW; 1770 return ECORE_CALLBACK_RENEW;
1642} 1771}
@@ -1701,7 +1830,7 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *ev
1701#ifdef SCROLLDBG 1830#ifdef SCROLLDBG
1702 printf("------ %i %i\n", ev->canvas.x, ev->canvas.y); 1831 printf("------ %i %i\n", ev->canvas.x, ev->canvas.y);
1703#endif 1832#endif
1704 for (i = 0; i < 20; i++) 1833 for (i = 0; i < 60; i++)
1705 { 1834 {
1706 dt = t - sd->down.history[i].timestamp; 1835 dt = t - sd->down.history[i].timestamp;
1707 if (dt > 0.2) break; 1836 if (dt > 0.2) break;
@@ -1994,9 +2123,10 @@ _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *
1994 printf("::: %i %i\n", ev->cur.canvas.x, ev->cur.canvas.y); 2123 printf("::: %i %i\n", ev->cur.canvas.x, ev->cur.canvas.y);
1995#endif 2124#endif
1996 memmove(&(sd->down.history[1]), &(sd->down.history[0]), 2125 memmove(&(sd->down.history[1]), &(sd->down.history[0]),
1997 sizeof(sd->down.history[0]) * 19); 2126 sizeof(sd->down.history[0]) * (60 - 1));
1998#ifdef EVTIME 2127#ifdef EVTIME
1999 sd->down.history[0].timestamp = ev->timestamp / 1000.0; 2128 sd->down.history[0].timestamp = ev->timestamp / 1000.0;
2129 sd->down.history[0].localtimestamp = ecore_loop_time_get();
2000#else 2130#else
2001 sd->down.history[0].timestamp = ecore_loop_time_get(); 2131 sd->down.history[0].timestamp = ecore_loop_time_get();
2002#endif 2132#endif
@@ -2121,7 +2251,7 @@ _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *
2121 x += (sd->child.w - sd->w + minx - x) * 2251 x += (sd->child.w - sd->w + minx - x) *
2122 _elm_config->thumbscroll_border_friction; 2252 _elm_config->thumbscroll_border_friction;
2123 } 2253 }
2124 2254
2125 sd->down.hold_x = x; 2255 sd->down.hold_x = x;
2126 sd->down.hold_y = y; 2256 sd->down.hold_y = y;
2127 if (!sd->down.hold_animator) 2257 if (!sd->down.hold_animator)