diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-06-13 15:28:58 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-06-13 15:28:58 +0300 |
commit | eb04ac7a1921b7c7f534a7a63cffc4c7a35c0900 (patch) | |
tree | a84fd4b4630f7469caa6e6a5df50fb13e12f8437 | |
parent | 4a29ccb82910503fe1c44fbf493caf0945714705 (diff) |
Mobile: Working on swipe navigation
Swipes back and forward are now working, although there are some glitches remaining. Most notably, when swiping back the previous document does not appear until the finger is released.
-rw-r--r-- | src/history.c | 30 | ||||
-rw-r--r-- | src/history.h | 2 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 144 | ||||
-rw-r--r-- | src/ui/mobile.c | 2 | ||||
-rw-r--r-- | src/ui/root.c | 13 | ||||
-rw-r--r-- | src/ui/touch.c | 6 | ||||
-rw-r--r-- | src/ui/widget.c | 15 | ||||
-rw-r--r-- | src/ui/widget.h | 2 |
8 files changed, 202 insertions, 12 deletions
diff --git a/src/history.c b/src/history.c index 740830e9..f6ad4771 100644 --- a/src/history.c +++ b/src/history.c | |||
@@ -284,6 +284,36 @@ void add_History(iHistory *d, const iString *url ){ | |||
284 | unlock_Mutex(d->mtx); | 284 | unlock_Mutex(d->mtx); |
285 | } | 285 | } |
286 | 286 | ||
287 | iBool preceding_History(iHistory *d, iRecentUrl *recent_out) { | ||
288 | iBool ok = iFalse; | ||
289 | lock_Mutex(d->mtx); | ||
290 | if (!isEmpty_Array(&d->recent) && d->recentPos < size_Array(&d->recent) - 1) { | ||
291 | const iRecentUrl *recent = constAt_Array(&d->recent, d->recentPos + 1); | ||
292 | set_String(&recent_out->url, &recent->url); | ||
293 | recent_out->normScrollY = recent->normScrollY; | ||
294 | recent_out->cachedDoc = ref_Object(recent->cachedDoc); | ||
295 | /* Cached response is not returned, would involve a deep copy. */ | ||
296 | ok = iTrue; | ||
297 | } | ||
298 | unlock_Mutex(d->mtx); | ||
299 | return ok; | ||
300 | } | ||
301 | |||
302 | iBool following_History(iHistory *d, iRecentUrl *recent_out) { | ||
303 | iBool ok = iFalse; | ||
304 | lock_Mutex(d->mtx); | ||
305 | if (!isEmpty_Array(&d->recent) && d->recentPos > 0) { | ||
306 | const iRecentUrl *recent = constAt_Array(&d->recent, d->recentPos - 1); | ||
307 | set_String(&recent_out->url, &recent->url); | ||
308 | recent_out->normScrollY = recent->normScrollY; | ||
309 | recent_out->cachedDoc = ref_Object(recent->cachedDoc); | ||
310 | /* Cached response is not returned, would involve a deep copy. */ | ||
311 | ok = iTrue; | ||
312 | } | ||
313 | unlock_Mutex(d->mtx); | ||
314 | return ok; | ||
315 | } | ||
316 | |||
287 | iBool goBack_History(iHistory *d) { | 317 | iBool goBack_History(iHistory *d) { |
288 | lock_Mutex(d->mtx); | 318 | lock_Mutex(d->mtx); |
289 | if (!isEmpty_Array(&d->recent) && d->recentPos < size_Array(&d->recent) - 1) { | 319 | if (!isEmpty_Array(&d->recent) && d->recentPos < size_Array(&d->recent) - 1) { |
diff --git a/src/history.h b/src/history.h index eb35b1df..9c900b82 100644 --- a/src/history.h +++ b/src/history.h | |||
@@ -63,6 +63,8 @@ void setCachedResponse_History (iHistory *, const iGmResponse *response | |||
63 | void setCachedDocument_History (iHistory *, iGmDocument *doc); | 63 | void setCachedDocument_History (iHistory *, iGmDocument *doc); |
64 | iBool goBack_History (iHistory *); | 64 | iBool goBack_History (iHistory *); |
65 | iBool goForward_History (iHistory *); | 65 | iBool goForward_History (iHistory *); |
66 | iBool preceding_History (iHistory *d, iRecentUrl *recent_out); | ||
67 | iBool following_History (iHistory *d, iRecentUrl *recent_out); | ||
66 | iRecentUrl *recentUrl_History (iHistory *, size_t pos); | 68 | iRecentUrl *recentUrl_History (iHistory *, size_t pos); |
67 | iRecentUrl *mostRecentUrl_History (iHistory *); | 69 | iRecentUrl *mostRecentUrl_History (iHistory *); |
68 | iRecentUrl *findUrl_History (iHistory *, const iString *url); | 70 | iRecentUrl *findUrl_History (iHistory *, const iString *url); |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 936c3cb7..70201d7b 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -315,6 +315,10 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
315 | init_Widget(w); | 315 | init_Widget(w); |
316 | setId_Widget(w, format_CStr("document%03d", ++docEnum_)); | 316 | setId_Widget(w, format_CStr("document%03d", ++docEnum_)); |
317 | setFlags_Widget(w, hover_WidgetFlag | noBackground_WidgetFlag, iTrue); | 317 | setFlags_Widget(w, hover_WidgetFlag | noBackground_WidgetFlag, iTrue); |
318 | if (deviceType_App() != desktop_AppDeviceType) { | ||
319 | setFlags_Widget(w, leftEdgeDraggable_WidgetFlag | rightEdgeDraggable_WidgetFlag | | ||
320 | horizontalOffset_WidgetFlag, iTrue); | ||
321 | } | ||
318 | init_PersistentDocumentState(&d->mod); | 322 | init_PersistentDocumentState(&d->mod); |
319 | d->flags = 0; | 323 | d->flags = 0; |
320 | d->phoneToolbar = NULL; | 324 | d->phoneToolbar = NULL; |
@@ -977,6 +981,9 @@ static void updateTimestampBuf_DocumentWidget_(const iDocumentWidget *d) { | |||
977 | } | 981 | } |
978 | 982 | ||
979 | static void invalidate_DocumentWidget_(iDocumentWidget *d) { | 983 | static void invalidate_DocumentWidget_(iDocumentWidget *d) { |
984 | if (flags_Widget(as_Widget(d)) & destroyPending_WidgetFlag) { | ||
985 | return; | ||
986 | } | ||
980 | invalidate_VisBuf(d->visBuf); | 987 | invalidate_VisBuf(d->visBuf); |
981 | clear_PtrSet(d->invalidRuns); | 988 | clear_PtrSet(d->invalidRuns); |
982 | } | 989 | } |
@@ -2237,6 +2244,133 @@ static iBool handlePinch_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | |||
2237 | return iTrue; | 2244 | return iTrue; |
2238 | } | 2245 | } |
2239 | 2246 | ||
2247 | static void swap_DocumentWidget_(iDocumentWidget *d, iGmDocument *doc, | ||
2248 | iDocumentWidget *swapBuffersWith) { | ||
2249 | if (doc) { | ||
2250 | iAssert(isInstance_Object(doc, &Class_GmDocument)); | ||
2251 | iGmDocument *copy = ref_Object(doc); | ||
2252 | iRelease(d->doc); | ||
2253 | d->doc = copy; | ||
2254 | d->scrollY = swapBuffersWith->scrollY; | ||
2255 | updateVisible_DocumentWidget_(d); | ||
2256 | iSwap(iVisBuf *, d->visBuf, swapBuffersWith->visBuf); | ||
2257 | iSwap(iVisBufMeta *, d->visBufMeta, swapBuffersWith->visBufMeta); | ||
2258 | iSwap(iDrawBufs *, d->drawBufs, swapBuffersWith->drawBufs); | ||
2259 | invalidate_DocumentWidget_(swapBuffersWith); | ||
2260 | } | ||
2261 | } | ||
2262 | |||
2263 | static iWidget *swipeParent_DocumentWidget_(iDocumentWidget *d) { | ||
2264 | return findChild_Widget(as_Widget(d)->root->widget, "doctabs"); | ||
2265 | } | ||
2266 | |||
2267 | static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | ||
2268 | iWidget *w = as_Widget(d); | ||
2269 | if (equal_Command(cmd, "edgeswipe.moved")) { | ||
2270 | as_Widget(d)->offsetRef = NULL; | ||
2271 | const int side = argLabel_Command(cmd, "side"); | ||
2272 | const int offset = arg_Command(cmd); | ||
2273 | if (side == 1) { | ||
2274 | if (atOldest_History(d->mod.history)) { | ||
2275 | return iTrue; | ||
2276 | } | ||
2277 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | ||
2278 | /* The temporary "swipeIn" will display the previous page until the finger is lifted. */ | ||
2279 | iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); | ||
2280 | if (!swipeIn) { | ||
2281 | swipeIn = new_DocumentWidget(); | ||
2282 | setId_Widget(as_Widget(swipeIn), "swipein"); | ||
2283 | setFlags_Widget(as_Widget(swipeIn), | ||
2284 | disabled_WidgetFlag | refChildrenOffset_WidgetFlag | | ||
2285 | fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue); | ||
2286 | swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); | ||
2287 | swipeIn->widget.rect.size = d->widget.rect.size; | ||
2288 | swipeIn->widget.offsetRef = w; | ||
2289 | iRecentUrl *recent = new_RecentUrl(); | ||
2290 | preceding_History(d->mod.history, recent); | ||
2291 | if (recent->cachedDoc) { | ||
2292 | iChangeRef(swipeIn->doc, recent->cachedDoc); | ||
2293 | updateScrollMax_DocumentWidget_(d); | ||
2294 | setValue_Anim(&swipeIn->scrollY.pos, size_GmDocument(swipeIn->doc).y * recent->normScrollY, 0); | ||
2295 | updateVisible_DocumentWidget_(swipeIn); | ||
2296 | } | ||
2297 | delete_RecentUrl(recent); | ||
2298 | addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos); | ||
2299 | } | ||
2300 | } | ||
2301 | if (side == 2) { | ||
2302 | if (offset < -get_Window()->pixelRatio * 10) { | ||
2303 | if (!atLatest_History(d->mod.history) && | ||
2304 | ~flags_Widget(w) & dragged_WidgetFlag) { | ||
2305 | postCommand_Widget(d, "navigate.forward"); | ||
2306 | setFlags_Widget(w, dragged_WidgetFlag, iTrue); | ||
2307 | /* Set up the swipe dummy. */ | ||
2308 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | ||
2309 | iDocumentWidget *target = new_DocumentWidget(); | ||
2310 | setId_Widget(as_Widget(target), "swipeout"); | ||
2311 | /* The target takes the old document and jumps on top. */ | ||
2312 | target->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); | ||
2313 | target->widget.rect.size = d->widget.rect.size; | ||
2314 | setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue); | ||
2315 | swap_DocumentWidget_(target, d->doc, d); | ||
2316 | addChildPos_Widget(swipeParent, iClob(target), front_WidgetAddPos); | ||
2317 | setFlags_Widget(as_Widget(target), refChildrenOffset_WidgetFlag, iTrue); | ||
2318 | as_Widget(target)->offsetRef = parent_Widget(w); | ||
2319 | destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ | ||
2320 | } | ||
2321 | if (flags_Widget(w) & dragged_WidgetFlag) { | ||
2322 | setVisualOffset_Widget(w, width_Widget(w) + offset, 10, 0); | ||
2323 | } | ||
2324 | else { | ||
2325 | setVisualOffset_Widget(w, offset / 4, 10, 0); | ||
2326 | } | ||
2327 | } | ||
2328 | return iTrue; | ||
2329 | } | ||
2330 | } | ||
2331 | if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 2) { | ||
2332 | if (argLabel_Command(cmd, "abort") && flags_Widget(w) & dragged_WidgetFlag) { | ||
2333 | postCommand_Widget(d, "navigate.back"); | ||
2334 | } | ||
2335 | setFlags_Widget(w, dragged_WidgetFlag, iFalse); | ||
2336 | setVisualOffset_Widget(w, 0, 100, 0); | ||
2337 | return iTrue; | ||
2338 | } | ||
2339 | if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 1) { | ||
2340 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | ||
2341 | iWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); | ||
2342 | if (swipeIn) { | ||
2343 | swipeIn->offsetRef = NULL; | ||
2344 | destroy_Widget(swipeIn); | ||
2345 | } | ||
2346 | } | ||
2347 | if (equal_Command(cmd, "swipe.back")) { | ||
2348 | if (atOldest_History(d->mod.history)) { | ||
2349 | setVisualOffset_Widget(w, 0, 100, 0); | ||
2350 | return iTrue; | ||
2351 | } | ||
2352 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | ||
2353 | iDocumentWidget *target = new_DocumentWidget(); | ||
2354 | setId_Widget(as_Widget(target), "swipeout"); | ||
2355 | /* The target takes the old document and jumps on top. */ | ||
2356 | target->widget.rect.pos = windowToInner_Widget(swipeParent, innerToWindow_Widget(w, zero_I2())); | ||
2357 | /* Note: `innerToWindow_Widget` does not apply visual offset. */ | ||
2358 | target->widget.rect.size = w->rect.size; | ||
2359 | setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue); | ||
2360 | swap_DocumentWidget_(target, d->doc, d); | ||
2361 | addChildPos_Widget(swipeParent, iClob(target), back_WidgetAddPos); | ||
2362 | setFlags_Widget(as_Widget(d), refChildrenOffset_WidgetFlag, iTrue); | ||
2363 | as_Widget(d)->offsetRef = swipeParent; | ||
2364 | setVisualOffset_Widget(as_Widget(target), value_Anim(&w->visualOffset), 0, 0); | ||
2365 | setVisualOffset_Widget(as_Widget(target), width_Widget(target), 150, 0); | ||
2366 | destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ | ||
2367 | setVisualOffset_Widget(w, 0, 0, 0); | ||
2368 | postCommand_Widget(d, "navigate.back"); | ||
2369 | return iTrue; | ||
2370 | } | ||
2371 | return iFalse; | ||
2372 | } | ||
2373 | |||
2240 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | 2374 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { |
2241 | iWidget *w = as_Widget(d); | 2375 | iWidget *w = as_Widget(d); |
2242 | if (equal_Command(cmd, "document.openurls.changed")) { | 2376 | if (equal_Command(cmd, "document.openurls.changed")) { |
@@ -2842,7 +2976,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2842 | uiHeading_ColorEscape "${heading.import.bookmarks}", | 2976 | uiHeading_ColorEscape "${heading.import.bookmarks}", |
2843 | formatCStrs_Lang("dlg.import.found.n", count), | 2977 | formatCStrs_Lang("dlg.import.found.n", count), |
2844 | (iMenuItem[]){ { "${cancel}", 0, 0, NULL }, | 2978 | (iMenuItem[]){ { "${cancel}", 0, 0, NULL }, |
2845 | { format_CStr(cstrCount_Lang("dlg.import.add.n", count), | 2979 | { format_CStr(cstrCount_Lang("dlg.import.add.n", (int) count), |
2846 | uiTextAction_ColorEscape, | 2980 | uiTextAction_ColorEscape, |
2847 | count), | 2981 | count), |
2848 | 0, | 2982 | 0, |
@@ -2901,6 +3035,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2901 | else if (startsWith_CStr(cmd, "pinch.") && document_Command(cmd) == d) { | 3035 | else if (startsWith_CStr(cmd, "pinch.") && document_Command(cmd) == d) { |
2902 | return handlePinch_DocumentWidget_(d, cmd); | 3036 | return handlePinch_DocumentWidget_(d, cmd); |
2903 | } | 3037 | } |
3038 | else if ((startsWith_CStr(cmd, "edgeswipe.") || startsWith_CStr(cmd, "swipe.")) && | ||
3039 | document_App() == d) { | ||
3040 | return handleSwipe_DocumentWidget_(d, cmd); | ||
3041 | } | ||
2904 | return iFalse; | 3042 | return iFalse; |
2905 | } | 3043 | } |
2906 | 3044 | ||
@@ -4306,7 +4444,8 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, | |||
4306 | /* Swap buffers around to have room available both before and after the visible region. */ | 4444 | /* Swap buffers around to have room available both before and after the visible region. */ |
4307 | allocVisBuffer_DocumentWidget_(d); | 4445 | allocVisBuffer_DocumentWidget_(d); |
4308 | reposition_VisBuf(visBuf, vis); | 4446 | reposition_VisBuf(visBuf, vis); |
4309 | /* Redraw the invalid ranges. */ { | 4447 | /* Redraw the invalid ranges. */ |
4448 | if (~flags_Widget(constAs_Widget(d)) & destroyPending_WidgetFlag) { | ||
4310 | iPaint *p = &ctx->paint; | 4449 | iPaint *p = &ctx->paint; |
4311 | init_Paint(p); | 4450 | init_Paint(p); |
4312 | iForIndices(i, visBuf->buffers) { | 4451 | iForIndices(i, visBuf->buffers) { |
@@ -4490,6 +4629,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4490 | .vis = vis, | 4629 | .vis = vis, |
4491 | .showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0, | 4630 | .showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0, |
4492 | }; | 4631 | }; |
4632 | init_Paint(&ctx.paint); | ||
4493 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); | 4633 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); |
4494 | setClip_Paint(&ctx.paint, bounds); | 4634 | setClip_Paint(&ctx.paint, bounds); |
4495 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); | 4635 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); |
diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 1bf289a7..7c0c8b60 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c | |||
@@ -447,7 +447,7 @@ void finalizeSheet_Mobile(iWidget *sheet) { | |||
447 | } | 447 | } |
448 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_())))); | 448 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_())))); |
449 | /* Slide top panel with detail panels. */ { | 449 | /* Slide top panel with detail panels. */ { |
450 | setFlags_Widget(topPanel, refChildrenOffset_WidgetFlag, iTrue); | 450 | setFlags_Widget(topPanel, refChildrenOffset_WidgetFlag, iTrue); |
451 | topPanel->offsetRef = detailStack; | 451 | topPanel->offsetRef = detailStack; |
452 | } | 452 | } |
453 | if (prefsTabs) { | 453 | if (prefsTabs) { |
diff --git a/src/ui/root.c b/src/ui/root.c index 2d69970d..e279a048 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -271,7 +271,8 @@ void destroyPending_Root(iRoot *d) { | |||
271 | setCurrent_Root(d); | 271 | setCurrent_Root(d); |
272 | iForEach(PtrSet, i, d->pendingDestruction) { | 272 | iForEach(PtrSet, i, d->pendingDestruction) { |
273 | iWidget *widget = *i.value; | 273 | iWidget *widget = *i.value; |
274 | if (!isFinished_Anim(&widget->visualOffset)) { | 274 | if (!isFinished_Anim(&widget->visualOffset) || |
275 | isBeingVisuallyOffsetByReference_Widget(widget)) { | ||
275 | continue; | 276 | continue; |
276 | } | 277 | } |
277 | if (widget->flags & keepOnTop_WidgetFlag) { | 278 | if (widget->flags & keepOnTop_WidgetFlag) { |
@@ -1169,11 +1170,11 @@ void createUserInterface_Root(iRoot *d) { | |||
1169 | setId_Widget(mainStack, "stack"); | 1170 | setId_Widget(mainStack, "stack"); |
1170 | addChildFlags_Widget(div, iClob(mainStack), resizeChildren_WidgetFlag | expand_WidgetFlag | | 1171 | addChildFlags_Widget(div, iClob(mainStack), resizeChildren_WidgetFlag | expand_WidgetFlag | |
1171 | unhittable_WidgetFlag); | 1172 | unhittable_WidgetFlag); |
1172 | iWidget *tabBar = makeTabs_Widget(mainStack); | 1173 | iWidget *docTabs = makeTabs_Widget(mainStack); |
1173 | setId_Widget(tabBar, "doctabs"); | 1174 | setId_Widget(docTabs, "doctabs"); |
1174 | setBackgroundColor_Widget(tabBar, uiBackground_ColorId); | 1175 | setBackgroundColor_Widget(docTabs, uiBackground_ColorId); |
1175 | appendTabPage_Widget(tabBar, iClob(new_DocumentWidget()), "Document", 0, 0); | 1176 | appendTabPage_Widget(docTabs, iClob(new_DocumentWidget()), "Document", 0, 0); |
1176 | iWidget *buttons = findChild_Widget(tabBar, "tabs.buttons"); | 1177 | iWidget *buttons = findChild_Widget(docTabs, "tabs.buttons"); |
1177 | setFlags_Widget(buttons, collapse_WidgetFlag | hidden_WidgetFlag | | 1178 | setFlags_Widget(buttons, collapse_WidgetFlag | hidden_WidgetFlag | |
1178 | drawBackgroundToHorizontalSafeArea_WidgetFlag, iTrue); | 1179 | drawBackgroundToHorizontalSafeArea_WidgetFlag, iTrue); |
1179 | if (deviceType_App() == phone_AppDeviceType) { | 1180 | if (deviceType_App() == phone_AppDeviceType) { |
diff --git a/src/ui/touch.c b/src/ui/touch.c index 236601e8..36bac267 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c | |||
@@ -273,8 +273,9 @@ static void update_TouchState_(void *ptr) { | |||
273 | // touch->edge == right_TouchEdge && swipeDir < 0 ? SDL_BUTTON_X2 : 0); | 273 | // touch->edge == right_TouchEdge && swipeDir < 0 ? SDL_BUTTON_X2 : 0); |
274 | // setHover_Widget(NULL); | 274 | // setHover_Widget(NULL); |
275 | postCommandf_App("edgeswipe.ended abort:1 side:%d id:%llu", touch->edge, touch->id); | 275 | postCommandf_App("edgeswipe.ended abort:1 side:%d id:%llu", touch->edge, touch->id); |
276 | touch->edge = none_TouchEdge; | 276 | touch->edge = none_TouchEdge; |
277 | remove_ArrayIterator(&i); | 277 | /* May be a regular drag along the edge so don't remove. */ |
278 | //remove_ArrayIterator(&i); | ||
278 | } | 279 | } |
279 | continue; | 280 | continue; |
280 | } | 281 | } |
@@ -516,6 +517,7 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
516 | else if (ev->type == SDL_FINGERMOTION) { | 517 | else if (ev->type == SDL_FINGERMOTION) { |
517 | iTouch *touch = find_TouchState_(d, fing->fingerId); | 518 | iTouch *touch = find_TouchState_(d, fing->fingerId); |
518 | if (touch && touch->edge) { | 519 | if (touch && touch->edge) { |
520 | clear_Array(d->moms); | ||
519 | pushPos_Touch_(touch, pos, nowTime); | 521 | pushPos_Touch_(touch, pos, nowTime); |
520 | postCommandf_App("edgeswipe.moved arg:%d side:%d id:%llu", | 522 | postCommandf_App("edgeswipe.moved arg:%d side:%d id:%llu", |
521 | (int) (x_F3(pos) - x_F3(touch->startPos)), | 523 | (int) (x_F3(pos) - x_F3(touch->startPos)), |
diff --git a/src/ui/widget.c b/src/ui/widget.c index f1d1dae4..3b67684b 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -759,6 +759,19 @@ void arrange_Widget(iWidget *d) { | |||
759 | } | 759 | } |
760 | } | 760 | } |
761 | 761 | ||
762 | iBool isBeingVisuallyOffsetByReference_Widget(const iWidget *d) { | ||
763 | if (d->flags & refChildrenOffset_WidgetFlag) { | ||
764 | iConstForEach(ObjectList, i, children_Widget(d->offsetRef)) { | ||
765 | const iWidget *child = i.object; | ||
766 | if (child == d) continue; | ||
767 | if (child->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { | ||
768 | return iTrue; | ||
769 | } | ||
770 | } | ||
771 | } | ||
772 | return iFalse; | ||
773 | } | ||
774 | |||
762 | static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) { | 775 | static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) { |
763 | if (d->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { | 776 | if (d->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { |
764 | const int off = iRound(value_Anim(&d->visualOffset)); | 777 | const int off = iRound(value_Anim(&d->visualOffset)); |
@@ -1075,12 +1088,12 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
1075 | if (d->flags & dragged_WidgetFlag && equal_Command(cmd, "edgeswipe.ended")) { | 1088 | if (d->flags & dragged_WidgetFlag && equal_Command(cmd, "edgeswipe.ended")) { |
1076 | if (argLabel_Command(cmd, "abort")) { | 1089 | if (argLabel_Command(cmd, "abort")) { |
1077 | setVisualOffset_Widget(d, 0, 200, easeOut_AnimFlag); | 1090 | setVisualOffset_Widget(d, 0, 200, easeOut_AnimFlag); |
1078 | setFlags_Widget(d, dragged_WidgetFlag, iFalse); | ||
1079 | } | 1091 | } |
1080 | else { | 1092 | else { |
1081 | postCommand_Widget( | 1093 | postCommand_Widget( |
1082 | d, argLabel_Command(cmd, "side") == 1 ? "swipe.back" : "swipe.forward"); | 1094 | d, argLabel_Command(cmd, "side") == 1 ? "swipe.back" : "swipe.forward"); |
1083 | } | 1095 | } |
1096 | setFlags_Widget(d, dragged_WidgetFlag, iFalse); | ||
1084 | } | 1097 | } |
1085 | if (d->commandHandler && d->commandHandler(d, ev->user.data1)) { | 1098 | if (d->commandHandler && d->commandHandler(d, ev->user.data1)) { |
1086 | iAssert(get_Root() == d->root); | 1099 | iAssert(get_Root() == d->root); |
diff --git a/src/ui/widget.h b/src/ui/widget.h index 7255b975..b2310f21 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -244,6 +244,8 @@ iBool isCommand_Widget (const iWidget *d, const SDL_Event *ev, cons | |||
244 | iBool hasParent_Widget (const iWidget *d, const iWidget *someParent); | 244 | iBool hasParent_Widget (const iWidget *d, const iWidget *someParent); |
245 | iBool isAffectedByVisualOffset_Widget | 245 | iBool isAffectedByVisualOffset_Widget |
246 | (const iWidget *); | 246 | (const iWidget *); |
247 | iBool isBeingVisuallyOffsetByReference_Widget | ||
248 | (const iWidget *); | ||
247 | void setId_Widget (iWidget *, const char *id); | 249 | void setId_Widget (iWidget *, const char *id); |
248 | void setFlags_Widget (iWidget *, int64_t flags, iBool set); | 250 | void setFlags_Widget (iWidget *, int64_t flags, iBool set); |
249 | void setPos_Widget (iWidget *, iInt2 pos); | 251 | void setPos_Widget (iWidget *, iInt2 pos); |