diff options
-rw-r--r-- | src/ios.h | 1 | ||||
-rw-r--r-- | src/ios.m | 17 | ||||
-rw-r--r-- | src/ui/touch.c | 46 |
3 files changed, 47 insertions, 17 deletions
@@ -38,3 +38,4 @@ void exportDownloadedFile_iOS(const iString *path); | |||
38 | 38 | ||
39 | iBool isPhone_iOS (void); | 39 | iBool isPhone_iOS (void); |
40 | void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom); | 40 | void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom); |
41 | int displayRefreshRate_iOS (void); | ||
@@ -33,11 +33,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
33 | static iBool isSystemDarkMode_ = iFalse; | 33 | static iBool isSystemDarkMode_ = iFalse; |
34 | static iBool isPhone_ = iFalse; | 34 | static iBool isPhone_ = iFalse; |
35 | 35 | ||
36 | static UIViewController *viewController_(iWindow *window) { | 36 | static 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 | |||
46 | static 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 | ||
260 | int displayRefreshRate_iOS(void) { | ||
261 | return uiWindow_(get_Window()).screen.maximumFramesPerSecond; | ||
262 | } | ||
263 | |||
251 | void setupWindow_iOS(iWindow *window) { | 264 | void 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 | ||
239 | iLocalDef 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 | |||
232 | static void update_TouchState_(void *ptr) { | 245 | static 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); |