summaryrefslogtreecommitdiff
path: root/src/ui/touch.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-04-20 22:39:00 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-04-20 22:39:00 +0300
commit982b0250255624e6bdf8782dcd2e7cb512f0bd4d (patch)
tree3540f25f88b3b3a5704bc3a822abfba15eacb085 /src/ui/touch.c
parenteaaecf50a5ec64e9c344d195a3a74c7a46c8797c (diff)
iOS: Fixed momentum scroll timing
The scrolling stutters were being caused by timing and not slow text rendering. Now the momentum scroll is locked to display refresh rate.
Diffstat (limited to 'src/ui/touch.c')
-rw-r--r--src/ui/touch.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/src/ui/touch.c b/src/ui/touch.c
index 4498efae..8a532821 100644
--- a/src/ui/touch.c
+++ b/src/ui/touch.c
@@ -99,6 +99,8 @@ struct Impl_TouchState {
99 iArray *touches; 99 iArray *touches;
100 iArray *pinches; 100 iArray *pinches;
101 iArray *moms; 101 iArray *moms;
102 double stepDurationMs;
103 double momFrictionPerStep;
102 double lastMomTime; 104 double lastMomTime;
103 iInt2 currentTouchPos; /* for emulating SDL_GetMouseState() */ 105 iInt2 currentTouchPos; /* for emulating SDL_GetMouseState() */
104}; 106};
@@ -107,10 +109,15 @@ static iTouchState *touchState_(void) {
107 static iTouchState state_; 109 static iTouchState state_;
108 iTouchState *d = &state_; 110 iTouchState *d = &state_;
109 if (!d->touches) { 111 if (!d->touches) {
110 d->touches = new_Array(sizeof(iTouch)); 112 d->touches = new_Array(sizeof(iTouch));
111 d->pinches = new_Array(sizeof(iPinch)); 113 d->pinches = new_Array(sizeof(iPinch));
112 d->moms = new_Array(sizeof(iMomentum)); 114 d->moms = new_Array(sizeof(iMomentum));
113 d->lastMomTime = SDL_GetTicks(); 115 d->lastMomTime = 0.0;
116 d->stepDurationMs = 1000.0 / 60.0; /* TODO: Ask SDL about the display refresh rate. */
117#if defined (iPlatformAppleMobile)
118 d->stepDurationMs = 1000.0 / (double) displayRefreshRate_iOS();
119#endif
120 d->momFrictionPerStep = pow(0.985, 120.0 / (1000.0 / d->stepDurationMs));
114 } 121 }
115 return d; 122 return d;
116} 123}
@@ -229,10 +236,16 @@ static void dispatchNotification_Touch_(const iTouch *d, int code) {
229 } 236 }
230} 237}
231 238
239iLocalDef double accurateTicks_(void) {
240 const uint64_t freq = SDL_GetPerformanceFrequency();
241 const uint64_t count = SDL_GetPerformanceCounter();
242 return 1000.0 * (double) count / (double) freq;
243}
244
232static void update_TouchState_(void *ptr) { 245static void update_TouchState_(void *ptr) {
233 iTouchState *d = ptr; 246 iTouchState *d = ptr;
234 const uint32_t nowTime = SDL_GetTicks();
235 /* Check for long presses to simulate right clicks. */ 247 /* Check for long presses to simulate right clicks. */
248 const uint32_t nowTime = SDL_GetTicks();
236 iForEach(Array, i, d->touches) { 249 iForEach(Array, i, d->touches) {
237 iTouch *touch = i.value; 250 iTouch *touch = i.value;
238 if (touch->pinchId || touch->isTouchDrag) { 251 if (touch->pinchId || touch->isTouchDrag) {
@@ -275,14 +288,17 @@ static void update_TouchState_(void *ptr) {
275 } 288 }
276 /* Update/cancel momentum scrolling. */ { 289 /* Update/cancel momentum scrolling. */ {
277 const float minSpeed = 15.0f; 290 const float minSpeed = 15.0f;
278 const float momFriction = 0.985f; /* per step */ 291 if (d->lastMomTime < 0.001) {
279 const float stepDurationMs = 1000.0f / 120.0f; 292 d->lastMomTime = accurateTicks_();
280 double momAvailMs = nowTime - d->lastMomTime; 293 }
281 int numSteps = (int) (momAvailMs / stepDurationMs); 294 const double momAvailMs = accurateTicks_() - d->lastMomTime;
282 d->lastMomTime += numSteps * stepDurationMs; 295 /* Display refresh is vsynced and we'll be here at most once per frame.
296 However, we may come here TOO early, which would cause a hiccup in the scrolling,
297 so always do at least one step. */
298 int numSteps = iMax(1, momAvailMs / d->stepDurationMs);
299 d->lastMomTime += numSteps * d->stepDurationMs;
283 numSteps = iMin(numSteps, 10); /* don't spend too much time here */ 300 numSteps = iMin(numSteps, 10); /* don't spend too much time here */
284 // printf("mom steps:%d\n", numSteps); 301// printf("mom steps:%d\n", numSteps);
285// iWindow *window = get_Window();
286 iForEach(Array, m, d->moms) { 302 iForEach(Array, m, d->moms) {
287 if (numSteps == 0) break; 303 if (numSteps == 0) break;
288 iMomentum *mom = m.value; 304 iMomentum *mom = m.value;
@@ -291,8 +307,8 @@ static void update_TouchState_(void *ptr) {
291 continue; 307 continue;
292 } 308 }
293 for (int step = 0; step < numSteps; step++) { 309 for (int step = 0; step < numSteps; step++) {
294 mulvf_F3(&mom->velocity, momFriction); 310 mulvf_F3(&mom->velocity, d->momFrictionPerStep);
295 addv_F3(&mom->accum, mulf_F3(mom->velocity, stepDurationMs / 1000.0f)); 311 addv_F3(&mom->accum, mulf_F3(mom->velocity, d->stepDurationMs / 1000.0f));
296 } 312 }
297 const iInt2 pixels = initF3_I2(mom->accum); 313 const iInt2 pixels = initF3_I2(mom->accum);
298 if (pixels.x || pixels.y) { 314 if (pixels.x || pixels.y) {
@@ -664,7 +680,7 @@ iBool processEvent_Touch(const SDL_Event *ev) {
664 .velocity = velocity 680 .velocity = velocity
665 }; 681 };
666 if (isEmpty_Array(d->moms)) { 682 if (isEmpty_Array(d->moms)) {
667 d->lastMomTime = nowTime; 683 d->lastMomTime = accurateTicks_();
668 } 684 }
669 pushBack_Array(d->moms, &mom); 685 pushBack_Array(d->moms, &mom);
670 //dispatchMotion_Touch_(touch->startPos, 0); 686 //dispatchMotion_Touch_(touch->startPos, 0);