summaryrefslogtreecommitdiff
path: root/src/ui/documentwidget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r--src/ui/documentwidget.c103
1 files changed, 79 insertions, 24 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index eae5d713..3fc22bdf 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -130,7 +130,8 @@ void deinit_PersistentDocumentState(iPersistentDocumentState *d) {
130 130
131void serialize_PersistentDocumentState(const iPersistentDocumentState *d, iStream *outs) { 131void serialize_PersistentDocumentState(const iPersistentDocumentState *d, iStream *outs) {
132 serialize_String(d->url, outs); 132 serialize_String(d->url, outs);
133 writeU16_Stream(outs, d->reloadInterval & 7); 133 uint16_t params = d->reloadInterval & 7;
134 writeU16_Stream(outs, params);
134 serialize_History(d->history, outs); 135 serialize_History(d->history, outs);
135} 136}
136 137
@@ -223,6 +224,7 @@ enum iDocumentWidgetFlag {
223 movingSelectMarkEnd_DocumentWidgetFlag = iBit(11), 224 movingSelectMarkEnd_DocumentWidgetFlag = iBit(11),
224 otherRootByDefault_DocumentWidgetFlag = iBit(12), /* links open to other root by default */ 225 otherRootByDefault_DocumentWidgetFlag = iBit(12), /* links open to other root by default */
225 urlChanged_DocumentWidgetFlag = iBit(13), 226 urlChanged_DocumentWidgetFlag = iBit(13),
227 openedFromSidebar_DocumentWidgetFlag = iBit(14),
226}; 228};
227 229
228enum iDocumentLinkOrdinalMode { 230enum iDocumentLinkOrdinalMode {
@@ -1606,7 +1608,8 @@ static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float n
1606 format_String(&d->sourceHeader, cstr_Lang("pageinfo.header.cached")); 1608 format_String(&d->sourceHeader, cstr_Lang("pageinfo.header.cached"));
1607 set_Block(&d->sourceContent, &resp->body); 1609 set_Block(&d->sourceContent, &resp->body);
1608 updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue); 1610 updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue);
1609 setCachedDocument_History(d->mod.history, d->doc); 1611 setCachedDocument_History(d->mod.history, d->doc,
1612 (d->flags & openedFromSidebar_DocumentWidgetFlag) != 0);
1610 } 1613 }
1611 d->state = ready_RequestState; 1614 d->state = ready_RequestState;
1612 postProcessRequestContent_DocumentWidget_(d, iTrue); 1615 postProcessRequestContent_DocumentWidget_(d, iTrue);
@@ -1626,6 +1629,9 @@ static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float n
1626static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) { 1629static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) {
1627 const iRecentUrl *recent = findUrl_History(d->mod.history, withSpacesEncoded_String(d->mod.url)); 1630 const iRecentUrl *recent = findUrl_History(d->mod.history, withSpacesEncoded_String(d->mod.url));
1628 if (recent && recent->cachedResponse) { 1631 if (recent && recent->cachedResponse) {
1632 iChangeFlags(d->flags,
1633 openedFromSidebar_DocumentWidgetFlag,
1634 recent->flags.openedFromSidebar);
1629 updateFromCachedResponse_DocumentWidget_( 1635 updateFromCachedResponse_DocumentWidget_(
1630 d, recent->normScrollY, recent->cachedResponse, recent->cachedDoc); 1636 d, recent->normScrollY, recent->cachedResponse, recent->cachedDoc);
1631 return iTrue; 1637 return iTrue;
@@ -2282,6 +2288,9 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2282 /* The temporary "swipeIn" will display the previous page until the finger is lifted. */ 2288 /* The temporary "swipeIn" will display the previous page until the finger is lifted. */
2283 iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); 2289 iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein");
2284 if (!swipeIn) { 2290 if (!swipeIn) {
2291 const iBool sidebarSwipe = (isPortraitPhone_App() &&
2292 d->flags & openedFromSidebar_DocumentWidgetFlag &&
2293 !isVisible_Widget(findWidget_App("sidebar")));
2285 swipeIn = new_DocumentWidget(); 2294 swipeIn = new_DocumentWidget();
2286 setId_Widget(as_Widget(swipeIn), "swipein"); 2295 setId_Widget(as_Widget(swipeIn), "swipein");
2287 setFlags_Widget(as_Widget(swipeIn), 2296 setFlags_Widget(as_Widget(swipeIn),
@@ -2290,16 +2299,18 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2290 swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); 2299 swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos));
2291 swipeIn->widget.rect.size = d->widget.rect.size; 2300 swipeIn->widget.rect.size = d->widget.rect.size;
2292 swipeIn->widget.offsetRef = parent_Widget(w); 2301 swipeIn->widget.offsetRef = parent_Widget(w);
2293 iRecentUrl *recent = new_RecentUrl(); 2302 if (!sidebarSwipe) {
2294 preceding_History(d->mod.history, recent); 2303 iRecentUrl *recent = new_RecentUrl();
2295 if (recent->cachedDoc) { 2304 preceding_History(d->mod.history, recent);
2296 iChangeRef(swipeIn->doc, recent->cachedDoc); 2305 if (recent->cachedDoc) {
2297 updateScrollMax_DocumentWidget_(d); 2306 iChangeRef(swipeIn->doc, recent->cachedDoc);
2298 setValue_Anim(&swipeIn->scrollY.pos, size_GmDocument(swipeIn->doc).y * recent->normScrollY, 0); 2307 updateScrollMax_DocumentWidget_(d);
2299 updateVisible_DocumentWidget_(swipeIn); 2308 setValue_Anim(&swipeIn->scrollY.pos, size_GmDocument(swipeIn->doc).y * recent->normScrollY, 0);
2300 swipeIn->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag; 2309 updateVisible_DocumentWidget_(swipeIn);
2310 swipeIn->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag;
2311 }
2312 delete_RecentUrl(recent);
2301 } 2313 }
2302 delete_RecentUrl(recent);
2303 addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos); 2314 addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos);
2304 } 2315 }
2305 } 2316 }
@@ -2326,7 +2337,9 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) {
2326 destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ 2337 destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */
2327 } 2338 }
2328 if (flags_Widget(w) & dragged_WidgetFlag) { 2339 if (flags_Widget(w) & dragged_WidgetFlag) {
2329 setVisualOffset_Widget(w, width_Widget(w) + offset, animSpan, 0); 2340 setVisualOffset_Widget(w, width_Widget(w) +
2341 width_Widget(d) * offset / size_Root(w->root).x,
2342 animSpan, 0);
2330 } 2343 }
2331 else { 2344 else {
2332 setVisualOffset_Widget(w, offset / 4, animSpan, 0); 2345 setVisualOffset_Widget(w, offset / 4, animSpan, 0);
@@ -2426,6 +2439,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2426 return iFalse; 2439 return iFalse;
2427 } 2440 }
2428 else if (equal_Command(cmd, "theme.changed") && document_App() == d) { 2441 else if (equal_Command(cmd, "theme.changed") && document_App() == d) {
2442// invalidateTheme_History(d->mod.history); /* cached colors */
2429 updateTheme_DocumentWidget_(d); 2443 updateTheme_DocumentWidget_(d);
2430 updateVisible_DocumentWidget_(d); 2444 updateVisible_DocumentWidget_(d);
2431 updateTrust_DocumentWidget_(d, NULL); 2445 updateTrust_DocumentWidget_(d, NULL);
@@ -2691,7 +2705,8 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2691 (startsWithCase_String(meta_GmRequest(d->request), "text/") || 2705 (startsWithCase_String(meta_GmRequest(d->request), "text/") ||
2692 !cmp_String(&d->sourceMime, mimeType_Gempub))) { 2706 !cmp_String(&d->sourceMime, mimeType_Gempub))) {
2693 setCachedResponse_History(d->mod.history, lockResponse_GmRequest(d->request)); 2707 setCachedResponse_History(d->mod.history, lockResponse_GmRequest(d->request));
2694 setCachedDocument_History(d->mod.history, d->doc); /* keeps a ref */ 2708 setCachedDocument_History(d->mod.history, d->doc, /* keeps a ref */
2709 (d->flags & openedFromSidebar_DocumentWidgetFlag) != 0);
2695 unlockResponse_GmRequest(d->request); 2710 unlockResponse_GmRequest(d->request);
2696 } 2711 }
2697 } 2712 }
@@ -2821,6 +2836,15 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2821 return iTrue; 2836 return iTrue;
2822 } 2837 }
2823 else if (equal_Command(cmd, "navigate.back") && document_App() == d) { 2838 else if (equal_Command(cmd, "navigate.back") && document_App() == d) {
2839 if (isPortraitPhone_App()) {
2840 if (d->flags & openedFromSidebar_DocumentWidgetFlag &&
2841 !isVisible_Widget(findWidget_App("sidebar"))) {
2842 postCommand_App("sidebar.toggle");
2843 showToolbars_Root(get_Root(), iTrue);
2844 return iTrue;
2845 }
2846 d->flags &= ~openedFromSidebar_DocumentWidgetFlag;
2847 }
2824 if (d->request) { 2848 if (d->request) {
2825 postCommandf_Root(w->root, 2849 postCommandf_Root(w->root,
2826 "document.request.cancelled doc:%p url:%s", d, cstr_String(d->mod.url)); 2850 "document.request.cancelled doc:%p url:%s", d, cstr_String(d->mod.url));
@@ -3499,7 +3523,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
3499 pushBack_Array( 3523 pushBack_Array(
3500 &items, 3524 &items,
3501 &(iMenuItem){ delete_Icon " " uiTextCaution_ColorEscape 3525 &(iMenuItem){ delete_Icon " " uiTextCaution_ColorEscape
3502 " ${link.file.delete}", 3526 "${link.file.delete}",
3503 0, 3527 0,
3504 0, 3528 0,
3505 format_CStr("!file.delete confirm:1 path:%s", 3529 format_CStr("!file.delete confirm:1 path:%s",
@@ -4366,7 +4390,7 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
4366 iDrawBufs * dbuf = d->drawBufs; 4390 iDrawBufs * dbuf = d->drawBufs;
4367 iPaint p; 4391 iPaint p;
4368 init_Paint(&p); 4392 init_Paint(&p);
4369 setClip_Paint(&p, bounds); 4393 setClip_Paint(&p, boundsWithoutVisualOffset_Widget(w));
4370 /* Side icon and current heading. */ 4394 /* Side icon and current heading. */
4371 if (prefs_App()->sideIcon && opacity > 0 && dbuf->sideIconBuf) { 4395 if (prefs_App()->sideIcon && opacity > 0 && dbuf->sideIconBuf) {
4372 const iInt2 texSize = size_SDLTexture(dbuf->sideIconBuf); 4396 const iInt2 texSize = size_SDLTexture(dbuf->sideIconBuf);
@@ -4616,12 +4640,17 @@ static void prerender_DocumentWidget_(iAny *context) {
4616} 4640}
4617 4641
4618static void draw_DocumentWidget_(const iDocumentWidget *d) { 4642static void draw_DocumentWidget_(const iDocumentWidget *d) {
4619 const iWidget *w = constAs_Widget(d); 4643 const iWidget *w = constAs_Widget(d);
4620 const iRect bounds = bounds_Widget(w); 4644 const iRect bounds = bounds_Widget(w);
4645 const iRect boundsWithoutVisOff = boundsWithoutVisualOffset_Widget(w);
4646 const iRect clipBounds = intersect_Rect(bounds, boundsWithoutVisOff);
4621 if (width_Rect(bounds) <= 0) { 4647 if (width_Rect(bounds) <= 0) {
4622 return; 4648 return;
4623 } 4649 }
4624// draw_Widget(w); 4650 /* TODO: Come up with a better palette caching system.
4651 It should be able to recompute cached colors in `History` when the theme has changed.
4652 Cache the theme seed in `GmDocument`? */
4653// makePaletteGlobal_GmDocument(d->doc);
4625 if (d->drawBufs->flags & updateTimestampBuf_DrawBufsFlag) { 4654 if (d->drawBufs->flags & updateTimestampBuf_DrawBufsFlag) {
4626 updateTimestampBuf_DocumentWidget_(d); 4655 updateTimestampBuf_DocumentWidget_(d);
4627 } 4656 }
@@ -4638,7 +4667,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
4638 }; 4667 };
4639 init_Paint(&ctx.paint); 4668 init_Paint(&ctx.paint);
4640 render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); 4669 render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */);
4641 setClip_Paint(&ctx.paint, bounds); 4670 setClip_Paint(&ctx.paint, clipBounds);
4642 int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); 4671 int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY);
4643 draw_VisBuf(d->visBuf, init_I2(bounds.pos.x, yTop), ySpan_Rect(bounds)); 4672 draw_VisBuf(d->visBuf, init_I2(bounds.pos.x, yTop), ySpan_Rect(bounds));
4644 /* Text markers. */ 4673 /* Text markers. */
@@ -4673,7 +4702,6 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
4673 } 4702 }
4674 } 4703 }
4675 drawMedia_DocumentWidget_(d, &ctx.paint); 4704 drawMedia_DocumentWidget_(d, &ctx.paint);
4676 unsetClip_Paint(&ctx.paint);
4677 /* Fill the top and bottom, in case the document is short. */ 4705 /* Fill the top and bottom, in case the document is short. */
4678 if (yTop > top_Rect(bounds)) { 4706 if (yTop > top_Rect(bounds)) {
4679 fillRect_Paint(&ctx.paint, 4707 fillRect_Paint(&ctx.paint,
@@ -4687,6 +4715,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
4687 init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom), 4715 init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom),
4688 tmBackground_ColorId); 4716 tmBackground_ColorId);
4689 } 4717 }
4718 unsetClip_Paint(&ctx.paint);
4690 drawSideElements_DocumentWidget_(d); 4719 drawSideElements_DocumentWidget_(d);
4691 if (prefs_App()->hoverLink && d->hoverLink) { 4720 if (prefs_App()->hoverLink && d->hoverLink) {
4692 const int font = uiLabel_FontId; 4721 const int font = uiLabel_FontId;
@@ -4748,6 +4777,23 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
4748 drawCentered_Text(uiLabelBold_FontId, rect, iFalse, uiBackground_ColorId, "%zu bytes selected", 4777 drawCentered_Text(uiLabelBold_FontId, rect, iFalse, uiBackground_ColorId, "%zu bytes selected",
4749 size_Range(&mark)); 4778 size_Range(&mark));
4750 } 4779 }
4780 if (w->offsetRef) {
4781 const int offX = visualOffsetByReference_Widget(w);
4782 if (offX) {
4783 setClip_Paint(&ctx.paint, clipBounds);
4784 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND);
4785 ctx.paint.alpha = iAbs(offX) / (float) get_Window()->size.x * 300;
4786 fillRect_Paint(&ctx.paint, bounds, backgroundFadeColor_Widget());
4787 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE);
4788 unsetClip_Paint(&ctx.paint);
4789 }
4790 else {
4791 /* TODO: Should have a better place to do this; drawing is supposed to be immutable. */
4792 iWidget *mut = iConstCast(iWidget *, w);
4793 mut->offsetRef = NULL;
4794 mut->flags &= ~refChildrenOffset_WidgetFlag;
4795 }
4796 }
4751} 4797}
4752 4798
4753/*----------------------------------------------------------------------------------------------*/ 4799/*----------------------------------------------------------------------------------------------*/
@@ -4814,10 +4860,13 @@ static void setUrl_DocumentWidget_(iDocumentWidget *d, const iString *url) {
4814 if (!equal_String(d->mod.url, url)) { 4860 if (!equal_String(d->mod.url, url)) {
4815 d->flags |= urlChanged_DocumentWidgetFlag; 4861 d->flags |= urlChanged_DocumentWidgetFlag;
4816 set_String(d->mod.url, url); 4862 set_String(d->mod.url, url);
4817} 4863 }
4818} 4864}
4819 4865
4820void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBool isFromCache) { 4866void setUrlFlags_DocumentWidget(iDocumentWidget *d, const iString *url, int setUrlFlags) {
4867 iChangeFlags(d->flags, openedFromSidebar_DocumentWidgetFlag,
4868 (setUrlFlags & openedFromSidebar_DocumentWidgetSetUrlFlag) != 0);
4869 const iBool isFromCache = (setUrlFlags & useCachedContentIfAvailable_DocumentWidgetSetUrlFlag) != 0;
4821 setLinkNumberMode_DocumentWidget_(d, iFalse); 4870 setLinkNumberMode_DocumentWidget_(d, iFalse);
4822 setUrl_DocumentWidget_(d, urlFragmentStripped_String(url)); 4871 setUrl_DocumentWidget_(d, urlFragmentStripped_String(url));
4823 /* See if there a username in the URL. */ 4872 /* See if there a username in the URL. */
@@ -4829,6 +4878,7 @@ void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBoo
4829 4878
4830void setUrlAndSource_DocumentWidget(iDocumentWidget *d, const iString *url, const iString *mime, 4879void setUrlAndSource_DocumentWidget(iDocumentWidget *d, const iString *url, const iString *mime,
4831 const iBlock *source) { 4880 const iBlock *source) {
4881 d->flags &= ~openedFromSidebar_DocumentWidgetFlag;
4832 setLinkNumberMode_DocumentWidget_(d, iFalse); 4882 setLinkNumberMode_DocumentWidget_(d, iFalse);
4833 setUrl_DocumentWidget_(d, url); 4883 setUrl_DocumentWidget_(d, url);
4834 parseUser_DocumentWidget_(d); 4884 parseUser_DocumentWidget_(d);
@@ -4846,12 +4896,12 @@ iDocumentWidget *duplicate_DocumentWidget(const iDocumentWidget *orig) {
4846 delete_History(d->mod.history); 4896 delete_History(d->mod.history);
4847 d->initNormScrollY = normScrollPos_DocumentWidget_(d); 4897 d->initNormScrollY = normScrollPos_DocumentWidget_(d);
4848 d->mod.history = copy_History(orig->mod.history); 4898 d->mod.history = copy_History(orig->mod.history);
4849 setUrlFromCache_DocumentWidget(d, orig->mod.url, iTrue); 4899 setUrlFlags_DocumentWidget(d, orig->mod.url, useCachedContentIfAvailable_DocumentWidgetSetUrlFlag);
4850 return d; 4900 return d;
4851} 4901}
4852 4902
4853void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { 4903void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) {
4854 setUrlFromCache_DocumentWidget(d, url, iFalse); 4904 setUrlFlags_DocumentWidget(d, url, 0);
4855} 4905}
4856 4906
4857void setInitialScroll_DocumentWidget(iDocumentWidget *d, float normScrollY) { 4907void setInitialScroll_DocumentWidget(iDocumentWidget *d, float normScrollY) {
@@ -4862,6 +4912,11 @@ void setRedirectCount_DocumentWidget(iDocumentWidget *d, int count) {
4862 d->redirectCount = count; 4912 d->redirectCount = count;
4863} 4913}
4864 4914
4915void setOpenedFromSidebar_DocumentWidget(iDocumentWidget *d, iBool fromSidebar) {
4916 iChangeFlags(d->flags, openedFromSidebar_DocumentWidgetFlag, fromSidebar);
4917 setCachedDocument_History(d->mod.history, d->doc, fromSidebar);
4918}
4919
4865iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) { 4920iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) {
4866 return d->request != NULL; 4921 return d->request != NULL;
4867} 4922}