diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/documentwidget.c | 113 |
1 files changed, 73 insertions, 40 deletions
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 | ||
2631 | static 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 | |||
2631 | static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | 2648 | static 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 | /*----------------------------------------------------------------------------------------------*/ |