summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/history.c2
-rw-r--r--src/history.h2
-rw-r--r--src/ui/documentwidget.c113
3 files changed, 75 insertions, 42 deletions
diff --git a/src/history.c b/src/history.c
index 8c268ec0..d1a731fb 100644
--- a/src/history.c
+++ b/src/history.c
@@ -370,7 +370,7 @@ iBool goForward_History(iHistory *d) {
370 return iFalse; 370 return iFalse;
371} 371}
372 372
373iBool atLatest_History(const iHistory *d) { 373iBool atNewest_History(const iHistory *d) {
374 iBool isLatest; 374 iBool isLatest;
375 iGuardMutex(d->mtx, isLatest = (d->recentPos == 0)); 375 iGuardMutex(d->mtx, isLatest = (d->recentPos == 0));
376 return isLatest; 376 return isLatest;
diff --git a/src/history.h b/src/history.h
index 0c07759b..3bb3808e 100644
--- a/src/history.h
+++ b/src/history.h
@@ -79,7 +79,7 @@ size_t pruneLeastImportantMemory_History (iHistory *);
79void invalidateTheme_History (iHistory *); /* theme has changed, cached contents need updating */ 79void invalidateTheme_History (iHistory *); /* theme has changed, cached contents need updating */
80void invalidateCachedLayout_History (iHistory *); 80void invalidateCachedLayout_History (iHistory *);
81 81
82iBool atLatest_History (const iHistory *); 82iBool atNewest_History (const iHistory *);
83iBool atOldest_History (const iHistory *); 83iBool atOldest_History (const iHistory *);
84 84
85const iStringArray * searchContents_History (const iHistory *, const iRegExp *pattern); /* chronologically ascending */ 85const iStringArray * searchContents_History (const iHistory *, const iRegExp *pattern); /* chronologically ascending */
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index f4c934f6..2b46c7b5 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -2628,11 +2628,36 @@ static void setUrl_DocumentWidget_(iDocumentWidget *d, const iString *url) {
2628 } 2628 }
2629} 2629}
2630 2630
2631static void setupSwipeOverlay_DocumentWidget_(iDocumentWidget *d, iWidget *overlay) {
2632 iWidget *w = as_Widget(d);
2633 iWidget *swipeParent = swipeParent_DocumentWidget_(d);
2634 /* The target takes the old document and jumps on top. */
2635 overlay->rect.pos = windowToInner_Widget(swipeParent, innerToWindow_Widget(w, zero_I2()));
2636 /* Note: `innerToWindow_Widget` does not apply visual offset. */
2637 overlay->rect.size = w->rect.size;
2638 setFlags_Widget(overlay, fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue);
2639// swap_DocumentWidget_(target, d->doc, d);
2640 setFlags_Widget(as_Widget(d), refChildrenOffset_WidgetFlag, iTrue);
2641 as_Widget(d)->offsetRef = swipeParent;
2642 /* `overlay` animates off the screen to the right. */
2643 setVisualOffset_Widget(overlay, value_Anim(&w->visualOffset), 0, 0);
2644 setVisualOffset_Widget(overlay, width_Widget(overlay), 150, 0);
2645 setVisualOffset_Widget(w, 0, 0, 0);
2646}
2647
2631static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { 2648static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2649 /* TODO: Cleanup
2650 If DocumentWidget is refactored to split the document presentation from state
2651 and request management (a new DocumentView class), plain views could be used for this
2652 animation without having to mess with the complete state of the DocumentWidget. That
2653 seems like a less error-prone approach -- the current implementation will likely break
2654 down (again) if anything is changed in the document internals.
2655 */
2632 iWidget *w = as_Widget(d); 2656 iWidget *w = as_Widget(d);
2633 /* Swipe animations are rather complex and utilize both cached GmDocument content 2657 /* The swipe animation is implemented in a rather complex way. It utilizes both cached
2634 and temporary DocumentWidgets. Depending on the swipe direction, this DocumentWidget 2658 GmDocument content and temporary underlay/overlay DocumentWidgets. Depending on the
2635 may wait until the finger is released to actually perform the navigation action. */ 2659 swipe direction, the DocumentWidget `d` may wait until the finger is released to actually
2660 perform the navigation action. */
2636 if (equal_Command(cmd, "edgeswipe.moved")) { 2661 if (equal_Command(cmd, "edgeswipe.moved")) {
2637 //printf("[%p] responds to edgeswipe.moved\n", d); 2662 //printf("[%p] responds to edgeswipe.moved\n", d);
2638 as_Widget(d)->offsetRef = NULL; 2663 as_Widget(d)->offsetRef = NULL;
@@ -2651,34 +2676,27 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2651 setFlags_Widget(as_Widget(swipeIn), 2676 setFlags_Widget(as_Widget(swipeIn),
2652 disabled_WidgetFlag | refChildrenOffset_WidgetFlag | 2677 disabled_WidgetFlag | refChildrenOffset_WidgetFlag |
2653 fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue); 2678 fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue);
2679 setFlags_Widget(findChild_Widget(as_Widget(swipeIn), "scroll"), hidden_WidgetFlag, iTrue);
2654 swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); 2680 swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos));
2655 swipeIn->widget.rect.size = d->widget.rect.size; 2681 swipeIn->widget.rect.size = d->widget.rect.size;
2656 swipeIn->widget.offsetRef = parent_Widget(w); 2682 swipeIn->widget.offsetRef = parent_Widget(w);
2657 /* Use a cached document for the layer underneath. */ { 2683 /* Use a cached document for the layer underneath. */ {
2658// iRecentUrl *recent = new_RecentUrl();
2659 lock_History(d->mod.history); 2684 lock_History(d->mod.history);
2660 iRecentUrl *recent = precedingLocked_History(d->mod.history); 2685 iRecentUrl *recent = precedingLocked_History(d->mod.history);
2661 if (recent && recent->cachedResponse) { 2686 if (recent && recent->cachedResponse) {
2662 /*
2663 iChangeRef(swipeIn->doc, recent->cachedDoc);
2664 updateBanner_DocumentWidget_(swipeIn);
2665 updateScrollMax_DocumentWidget_(d);
2666 setValue_Anim(&swipeIn->scrollY.pos,
2667 pageHeight_DocumentWidget_(d) * recent->normScrollY, 0);
2668 updateVisible_DocumentWidget_(swipeIn);
2669 swipeIn->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag;*/
2670 setUrl_DocumentWidget_(swipeIn, &recent->url); 2687 setUrl_DocumentWidget_(swipeIn, &recent->url);
2671 updateFromCachedResponse_DocumentWidget_(swipeIn, 2688 updateFromCachedResponse_DocumentWidget_(swipeIn,
2672 recent->normScrollY, 2689 recent->normScrollY,
2673 recent->cachedResponse, 2690 recent->cachedResponse,
2674 recent->cachedDoc); 2691 recent->cachedDoc);
2692 parseUser_DocumentWidget_(swipeIn);
2693 updateBanner_DocumentWidget_(swipeIn);
2675 } 2694 }
2676 else { 2695 else {
2677 setUrlAndSource_DocumentWidget(swipeIn, &recent->url, 2696 setUrlAndSource_DocumentWidget(swipeIn, &recent->url,
2678 collectNewCStr_String("text/gemini"), 2697 collectNewCStr_String("text/gemini"),
2679 collect_Block(new_Block(0))); 2698 collect_Block(new_Block(0)));
2680 } 2699 }
2681// delete_RecentUrl(recent);
2682 unlock_History(d->mod.history); 2700 unlock_History(d->mod.history);
2683 } 2701 }
2684 addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos); 2702 addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos);
@@ -2687,7 +2705,8 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2687 if (side == 2) { /* right edge */ 2705 if (side == 2) { /* right edge */
2688 if (offset < -get_Window()->pixelRatio * 10) { 2706 if (offset < -get_Window()->pixelRatio * 10) {
2689 int animSpan = 10; 2707 int animSpan = 10;
2690 if (!atLatest_History(d->mod.history) && ~flags_Widget(w) & dragged_WidgetFlag) { 2708 if (!atNewest_History(d->mod.history) && ~flags_Widget(w) & dragged_WidgetFlag) {
2709 /* Setup the drag. `d` will be moving with the finger. */
2691 animSpan = 0; 2710 animSpan = 0;
2692 postCommand_Widget(d, "navigate.forward"); 2711 postCommand_Widget(d, "navigate.forward");
2693 setFlags_Widget(w, dragged_WidgetFlag, iTrue); 2712 setFlags_Widget(w, dragged_WidgetFlag, iTrue);
@@ -2695,7 +2714,7 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2695 iWidget *swipeParent = swipeParent_DocumentWidget_(d); 2714 iWidget *swipeParent = swipeParent_DocumentWidget_(d);
2696 iDocumentWidget *target = new_DocumentWidget(); 2715 iDocumentWidget *target = new_DocumentWidget();
2697 setId_Widget(as_Widget(target), "swipeout"); 2716 setId_Widget(as_Widget(target), "swipeout");
2698 /* The target takes the old document and goes underneath. */ 2717 /* "swipeout" takes `d`'s document and goes underneath. */
2699 target->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); 2718 target->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos));
2700 target->widget.rect.size = d->widget.rect.size; 2719 target->widget.rect.size = d->widget.rect.size;
2701 setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue); 2720 setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue);
@@ -2703,7 +2722,8 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2703 addChildPos_Widget(swipeParent, iClob(target), front_WidgetAddPos); 2722 addChildPos_Widget(swipeParent, iClob(target), front_WidgetAddPos);
2704 setFlags_Widget(as_Widget(target), refChildrenOffset_WidgetFlag, iTrue); 2723 setFlags_Widget(as_Widget(target), refChildrenOffset_WidgetFlag, iTrue);
2705 as_Widget(target)->offsetRef = parent_Widget(w); 2724 as_Widget(target)->offsetRef = parent_Widget(w);
2706 destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ 2725 /* Mark it for deletion after animation finishes. */
2726 destroy_Widget(as_Widget(target));
2707 /* The `d` document will now navigate forward and be replaced with a cached 2727 /* The `d` document will now navigate forward and be replaced with a cached
2708 copy. However, if a cached response isn't available, we'll need to show a 2728 copy. However, if a cached response isn't available, we'll need to show a
2709 blank page. */ 2729 blank page. */
@@ -2726,10 +2746,26 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2726 } 2746 }
2727 if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 2) { 2747 if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 2) {
2728 if (argLabel_Command(cmd, "abort") && flags_Widget(w) & dragged_WidgetFlag) { 2748 if (argLabel_Command(cmd, "abort") && flags_Widget(w) & dragged_WidgetFlag) {
2749 setFlags_Widget(w, dragged_WidgetFlag, iFalse);
2729 postCommand_Widget(d, "navigate.back"); 2750 postCommand_Widget(d, "navigate.back");
2751 /* We must now undo the swap that was done when the drag started. */
2752 /* TODO: Currently not animated! What exactly is the appropriate thing to do here? */
2753 iWidget *swipeParent = swipeParent_DocumentWidget_(d);
2754 iDocumentWidget *swipeOut = findChild_Widget(swipeParent, "swipeout");
2755 swap_DocumentWidget_(d, swipeOut->doc, swipeOut);
2756// const int visOff = visualOffsetByReference_Widget(w);
2757 w->offsetRef = NULL;
2758// setVisualOffset_Widget(w, visOff, 0, 0);
2759// setVisualOffset_Widget(w, 0, 150, 0);
2760 setVisualOffset_Widget(w, 0, 0, 0);
2761 /* Make it an overlay instead. */
2762// removeChild_Widget(swipeParent, swipeOut);
2763// addChildPos_Widget(swipeParent, iClob(swipeOut), back_WidgetAddPos);
2764// setupSwipeOverlay_DocumentWidget_(d, as_Widget(swipeOut));
2765 return iTrue;
2730 } 2766 }
2731 setFlags_Widget(w, dragged_WidgetFlag, iFalse); 2767 setFlags_Widget(w, dragged_WidgetFlag, iFalse);
2732 setVisualOffset_Widget(w, 0, 100, 0); 2768 setVisualOffset_Widget(w, 0, 150, 0);
2733 return iTrue; 2769 return iTrue;
2734 } 2770 }
2735 if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 1) { 2771 if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 1) {
@@ -2739,16 +2775,20 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2739 switching immediately to a cached page. However, if one is not available, we'll need 2775 switching immediately to a cached page. However, if one is not available, we'll need
2740 to show a blank page for a while. */ 2776 to show a blank page for a while. */
2741 if (swipeIn) { 2777 if (swipeIn) {
2742 iWidget *swipeParent = swipeParent_DocumentWidget_(d); 2778 if (!argLabel_Command(cmd, "abort")) {
2743 iDocumentWidget *target = new_DocumentWidget(); 2779 iWidget *swipeParent = swipeParent_DocumentWidget_(d);
2744 addChildPos_Widget(swipeParent, iClob(target), back_WidgetAddPos); 2780 /* What was being shown in the `d` document is now being swapped to
2745 setId_Widget(as_Widget(target), "swipeout"); 2781 the outgoing page animation. */
2746 swap_DocumentWidget_(target, d->doc, d); 2782 iDocumentWidget *target = new_DocumentWidget();
2747 setUrlAndSource_DocumentWidget(d, 2783 addChildPos_Widget(swipeParent, iClob(target), back_WidgetAddPos);
2748 swipeIn->mod.url, 2784 setId_Widget(as_Widget(target), "swipeout");
2749 collectNewCStr_String("text/gemini"), 2785 swap_DocumentWidget_(target, d->doc, d);
2750 collect_Block(new_Block(0))); 2786 setUrlAndSource_DocumentWidget(d,
2751 as_Widget(swipeIn)->offsetRef = NULL; 2787 swipeIn->mod.url,
2788 collectNewCStr_String("text/gemini"),
2789 collect_Block(new_Block(0)));
2790 as_Widget(swipeIn)->offsetRef = NULL;
2791 }
2752 destroy_Widget(as_Widget(swipeIn)); 2792 destroy_Widget(as_Widget(swipeIn));
2753 } 2793 }
2754 } 2794 }
@@ -2762,20 +2802,8 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2762 } 2802 }
2763 return iTrue; 2803 return iTrue;
2764 } 2804 }
2765// iDocumentWidget *target = new_DocumentWidget(); 2805 setupSwipeOverlay_DocumentWidget_(d, as_Widget(target));
2766// setId_Widget(as_Widget(target), "swipeout");
2767 /* The target takes the old document and jumps on top. */
2768 target->widget.rect.pos = windowToInner_Widget(swipeParent, innerToWindow_Widget(w, zero_I2()));
2769 /* Note: `innerToWindow_Widget` does not apply visual offset. */
2770 target->widget.rect.size = w->rect.size;
2771 setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue);
2772// swap_DocumentWidget_(target, d->doc, d);
2773 setFlags_Widget(as_Widget(d), refChildrenOffset_WidgetFlag, iTrue);
2774 as_Widget(d)->offsetRef = swipeParent;
2775 setVisualOffset_Widget(as_Widget(target), value_Anim(&w->visualOffset), 0, 0);
2776 setVisualOffset_Widget(as_Widget(target), width_Widget(target), 150, 0);
2777 destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ 2806 destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */
2778 setVisualOffset_Widget(w, 0, 0, 0);
2779 postCommand_Widget(d, "navigate.back"); 2807 postCommand_Widget(d, "navigate.back");
2780 return iTrue; 2808 return iTrue;
2781 } 2809 }
@@ -5292,6 +5320,11 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
5292 } 5320 }
5293 } 5321 }
5294// drawRect_Paint(&ctx.paint, docBounds, red_ColorId); 5322// drawRect_Paint(&ctx.paint, docBounds, red_ColorId);
5323 if (deviceType_App() == phone_AppDeviceType) {
5324 /* The phone toolbar uses the palette of the active tab, but there may be other
5325 documents drawn before the toolbar, causing the colors to be incorrect. */
5326 makePaletteGlobal_GmDocument(document_App()->doc);
5327 }
5295} 5328}
5296 5329
5297/*----------------------------------------------------------------------------------------------*/ 5330/*----------------------------------------------------------------------------------------------*/