summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ios.h1
-rw-r--r--src/ios.m17
-rw-r--r--src/ui/touch.c46
3 files changed, 47 insertions, 17 deletions
diff --git a/src/ios.h b/src/ios.h
index 29669a26..ba462834 100644
--- a/src/ios.h
+++ b/src/ios.h
@@ -38,3 +38,4 @@ void exportDownloadedFile_iOS(const iString *path);
38 38
39iBool isPhone_iOS (void); 39iBool isPhone_iOS (void);
40void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom); 40void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom);
41int displayRefreshRate_iOS (void);
diff --git a/src/ios.m b/src/ios.m
index 9aca5a19..58557ef5 100644
--- a/src/ios.m
+++ b/src/ios.m
@@ -33,11 +33,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
33static iBool isSystemDarkMode_ = iFalse; 33static iBool isSystemDarkMode_ = iFalse;
34static iBool isPhone_ = iFalse; 34static iBool isPhone_ = iFalse;
35 35
36static UIViewController *viewController_(iWindow *window) { 36static UIWindow *uiWindow_(iWindow *window) {
37 SDL_SysWMinfo wm; 37 SDL_SysWMinfo wm;
38 SDL_VERSION(&wm.version); 38 SDL_VERSION(&wm.version);
39 if (SDL_GetWindowWMInfo(window->win, &wm)) { 39 if (SDL_GetWindowWMInfo(window->win, &wm)) {
40 return wm.info.uikit.window.rootViewController; 40 return wm.info.uikit.window;
41 }
42 iAssert(false);
43 return NULL;
44}
45
46static UIViewController *viewController_(iWindow *window) {
47 UIWindow *uiWin = uiWindow_(window);
48 if (uiWin) {
49 return uiWin.rootViewController;
41 } 50 }
42 iAssert(false); 51 iAssert(false);
43 return NULL; 52 return NULL;
@@ -248,6 +257,10 @@ iBool isPhone_iOS(void) {
248 return isPhone_; 257 return isPhone_;
249} 258}
250 259
260int displayRefreshRate_iOS(void) {
261 return uiWindow_(get_Window()).screen.maximumFramesPerSecond;
262}
263
251void setupWindow_iOS(iWindow *window) { 264void setupWindow_iOS(iWindow *window) {
252 UIViewController *ctl = viewController_(window); 265 UIViewController *ctl = viewController_(window);
253 isSystemDarkMode_ = isDarkMode_(window); 266 isSystemDarkMode_ = isDarkMode_(window);
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);