diff options
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 603af076..232b4140 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -133,6 +133,7 @@ enum iDocumentWidgetFlag { | |||
133 | showLinkNumbers_DocumentWidgetFlag = iBit(3), | 133 | showLinkNumbers_DocumentWidgetFlag = iBit(3), |
134 | setHoverViaKeys_DocumentWidgetFlag = iBit(4), | 134 | setHoverViaKeys_DocumentWidgetFlag = iBit(4), |
135 | newTabViaHomeKeys_DocumentWidgetFlag = iBit(5), | 135 | newTabViaHomeKeys_DocumentWidgetFlag = iBit(5), |
136 | centerVertically_DocumentWidgetFlag = iBit(6), | ||
136 | }; | 137 | }; |
137 | 138 | ||
138 | enum iDocumentLinkOrdinalMode { | 139 | enum iDocumentLinkOrdinalMode { |
@@ -151,6 +152,7 @@ struct Impl_DocumentWidget { | |||
151 | iGmRequest * request; | 152 | iGmRequest * request; |
152 | iAtomicInt isRequestUpdated; /* request has new content, need to parse it */ | 153 | iAtomicInt isRequestUpdated; /* request has new content, need to parse it */ |
153 | iObjectList * media; | 154 | iObjectList * media; |
155 | enum iGmStatusCode sourceStatus; | ||
154 | iString sourceHeader; | 156 | iString sourceHeader; |
155 | iString sourceMime; | 157 | iString sourceMime; |
156 | iBlock sourceContent; /* original content as received, for saving */ | 158 | iBlock sourceContent; /* original content as received, for saving */ |
@@ -231,6 +233,7 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
231 | init_Array(&d->outline, sizeof(iOutlineItem)); | 233 | init_Array(&d->outline, sizeof(iOutlineItem)); |
232 | init_Anim(&d->sideOpacity, 0); | 234 | init_Anim(&d->sideOpacity, 0); |
233 | init_Anim(&d->outlineOpacity, 0); | 235 | init_Anim(&d->outlineOpacity, 0); |
236 | d->sourceStatus = none_GmStatusCode; | ||
234 | init_String(&d->sourceHeader); | 237 | init_String(&d->sourceHeader); |
235 | init_String(&d->sourceMime); | 238 | init_String(&d->sourceMime); |
236 | init_Block(&d->sourceContent, 0); | 239 | init_Block(&d->sourceContent, 0); |
@@ -332,7 +335,7 @@ static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { | |||
332 | rect.pos.y += margin; | 335 | rect.pos.y += margin; |
333 | rect.size.y -= margin; | 336 | rect.size.y -= margin; |
334 | } | 337 | } |
335 | if (prefs_App()->centerShortDocs) { | 338 | if (d->flags & centerVertically_DocumentWidgetFlag) { |
336 | const iInt2 docSize = size_GmDocument(d->doc); | 339 | const iInt2 docSize = size_GmDocument(d->doc); |
337 | if (docSize.y < rect.size.y) { | 340 | if (docSize.y < rect.size.y) { |
338 | /* Center vertically if short. There is one empty paragraph line's worth of margin | 341 | /* Center vertically if short. There is one empty paragraph line's worth of margin |
@@ -592,6 +595,10 @@ static iRangecc currentHeading_DocumentWidget_(const iDocumentWidget *d) { | |||
592 | } | 595 | } |
593 | 596 | ||
594 | static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | 597 | static void updateVisible_DocumentWidget_(iDocumentWidget *d) { |
598 | iChangeFlags(d->flags, | ||
599 | centerVertically_DocumentWidgetFlag, | ||
600 | prefs_App()->centerShortDocs || startsWithCase_String(d->mod.url, "about:") || | ||
601 | !isSuccess_GmStatusCode(d->sourceStatus)); | ||
595 | const iRangei visRange = visibleRange_DocumentWidget_(d); | 602 | const iRangei visRange = visibleRange_DocumentWidget_(d); |
596 | const iRect bounds = bounds_Widget(as_Widget(d)); | 603 | const iRect bounds = bounds_Widget(as_Widget(d)); |
597 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax_DocumentWidget_(d) }); | 604 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax_DocumentWidget_(d) }); |
@@ -1038,6 +1045,7 @@ static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) { | |||
1038 | /* Use the cached response data. */ | 1045 | /* Use the cached response data. */ |
1039 | updateTrust_DocumentWidget_(d, resp); | 1046 | updateTrust_DocumentWidget_(d, resp); |
1040 | d->sourceTime = resp->when; | 1047 | d->sourceTime = resp->when; |
1048 | d->sourceStatus = success_GmStatusCode; | ||
1041 | format_String(&d->sourceHeader, "(cached content)"); | 1049 | format_String(&d->sourceHeader, "(cached content)"); |
1042 | updateTimestampBuf_DocumentWidget_(d); | 1050 | updateTimestampBuf_DocumentWidget_(d); |
1043 | set_Block(&d->sourceContent, &resp->body); | 1051 | set_Block(&d->sourceContent, &resp->body); |
@@ -1113,6 +1121,9 @@ static void scroll_DocumentWidget_(iDocumentWidget *d, int offset) { | |||
1113 | } | 1121 | } |
1114 | 1122 | ||
1115 | static void scrollTo_DocumentWidget_(iDocumentWidget *d, int documentY, iBool centered) { | 1123 | static void scrollTo_DocumentWidget_(iDocumentWidget *d, int documentY, iBool centered) { |
1124 | if (!hasSiteBanner_GmDocument(d->doc)) { | ||
1125 | documentY += d->pageMargin * gap_UI; | ||
1126 | } | ||
1116 | init_Anim(&d->scrollY, | 1127 | init_Anim(&d->scrollY, |
1117 | documentY - (centered ? documentBounds_DocumentWidget_(d).size.y / 2 | 1128 | documentY - (centered ? documentBounds_DocumentWidget_(d).size.y / 2 |
1118 | : lineHeight_Text(paragraph_FontId))); | 1129 | : lineHeight_Text(paragraph_FontId))); |
@@ -1192,6 +1203,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | |||
1192 | updateTrust_DocumentWidget_(d, resp); | 1203 | updateTrust_DocumentWidget_(d, resp); |
1193 | init_Anim(&d->sideOpacity, 0); | 1204 | init_Anim(&d->sideOpacity, 0); |
1194 | format_String(&d->sourceHeader, "%d %s", statusCode, get_GmError(statusCode)->title); | 1205 | format_String(&d->sourceHeader, "%d %s", statusCode, get_GmError(statusCode)->title); |
1206 | d->sourceStatus = statusCode; | ||
1195 | switch (category_GmStatusCode(statusCode)) { | 1207 | switch (category_GmStatusCode(statusCode)) { |
1196 | case categoryInput_GmStatusCode: { | 1208 | case categoryInput_GmStatusCode: { |
1197 | iUrl parts; | 1209 | iUrl parts; |
@@ -1538,28 +1550,43 @@ static const int homeRowKeys_[] = { | |||
1538 | 't', 'y', | 1550 | 't', 'y', |
1539 | }; | 1551 | }; |
1540 | 1552 | ||
1553 | static void updateDocumentWidthRetainingScrollPosition_DocumentWidget_(iDocumentWidget *d, | ||
1554 | iBool keepCenter) { | ||
1555 | /* Font changes (i.e., zooming) will keep the view centered, otherwise keep the top | ||
1556 | of the visible area fixed. */ | ||
1557 | const iGmRun *run = keepCenter ? middleRun_DocumentWidget_(d) : d->firstVisibleRun; | ||
1558 | const char * runLoc = (run ? run->text.start : NULL); | ||
1559 | int voffset = 0; | ||
1560 | if (!keepCenter && run) { | ||
1561 | /* Keep the first visible run visible at the same position. */ | ||
1562 | /* TODO: First *fully* visible run? */ | ||
1563 | voffset = visibleRange_DocumentWidget_(d).start - top_Rect(run->visBounds); | ||
1564 | } | ||
1565 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); | ||
1566 | if (runLoc && !keepCenter) { | ||
1567 | run = findRunAtLoc_GmDocument(d->doc, runLoc); | ||
1568 | if (run) { | ||
1569 | scrollTo_DocumentWidget_(d, | ||
1570 | top_Rect(run->visBounds) + | ||
1571 | lineHeight_Text(paragraph_FontId) + voffset, | ||
1572 | iFalse); | ||
1573 | } | ||
1574 | } | ||
1575 | else if (runLoc && keepCenter) { | ||
1576 | run = findRunAtLoc_GmDocument(d->doc, runLoc); | ||
1577 | if (run) { | ||
1578 | scrollTo_DocumentWidget_(d, mid_Rect(run->bounds).y, iTrue); | ||
1579 | } | ||
1580 | } | ||
1581 | } | ||
1582 | |||
1541 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | 1583 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { |
1542 | iWidget *w = as_Widget(d); | 1584 | iWidget *w = as_Widget(d); |
1543 | if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed")) { | 1585 | if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed")) { |
1544 | const iBool isVerticalOnly = | ||
1545 | !argLabel_Command(cmd, "horiz") && argLabel_Command(cmd, "vert"); | ||
1546 | /* Alt/Option key may be involved in window size changes. */ | 1586 | /* Alt/Option key may be involved in window size changes. */ |
1547 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse); | 1587 | iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse); |
1548 | if (isVerticalOnly) { | 1588 | const iBool keepCenter = equal_Command(cmd, "font.changed"); |
1549 | scroll_DocumentWidget_(d, 0); /* prevent overscroll */ | 1589 | updateDocumentWidthRetainingScrollPosition_DocumentWidget_(d, keepCenter); |
1550 | } | ||
1551 | else { | ||
1552 | const iGmRun *mid = middleRun_DocumentWidget_(d); | ||
1553 | const char *midLoc = (mid ? mid->text.start : NULL); | ||
1554 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); | ||
1555 | scroll_DocumentWidget_(d, 0); | ||
1556 | if (midLoc) { | ||
1557 | mid = findRunAtLoc_GmDocument(d->doc, midLoc); | ||
1558 | if (mid) { | ||
1559 | scrollTo_DocumentWidget_(d, mid_Rect(mid->bounds).y, iTrue); | ||
1560 | } | ||
1561 | } | ||
1562 | } | ||
1563 | updateSideIconBuf_DocumentWidget_(d); | 1590 | updateSideIconBuf_DocumentWidget_(d); |
1564 | updateOutline_DocumentWidget_(d); | 1591 | updateOutline_DocumentWidget_(d); |
1565 | invalidate_DocumentWidget_(d); | 1592 | invalidate_DocumentWidget_(d); |
@@ -1581,6 +1608,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1581 | } | 1608 | } |
1582 | else if (equal_Command(cmd, "theme.changed") && document_App() == d) { | 1609 | else if (equal_Command(cmd, "theme.changed") && document_App() == d) { |
1583 | updateTheme_DocumentWidget_(d); | 1610 | updateTheme_DocumentWidget_(d); |
1611 | updateVisible_DocumentWidget_(d); | ||
1584 | updateTrust_DocumentWidget_(d, NULL); | 1612 | updateTrust_DocumentWidget_(d, NULL); |
1585 | updateSideIconBuf_DocumentWidget_(d); | 1613 | updateSideIconBuf_DocumentWidget_(d); |
1586 | invalidate_DocumentWidget_(d); | 1614 | invalidate_DocumentWidget_(d); |
@@ -3398,7 +3426,7 @@ iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) { | |||
3398 | } | 3426 | } |
3399 | 3427 | ||
3400 | void updateSize_DocumentWidget(iDocumentWidget *d) { | 3428 | void updateSize_DocumentWidget(iDocumentWidget *d) { |
3401 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); | 3429 | updateDocumentWidthRetainingScrollPosition_DocumentWidget_(d, iFalse); |
3402 | resetWideRuns_DocumentWidget_(d); | 3430 | resetWideRuns_DocumentWidget_(d); |
3403 | updateSideIconBuf_DocumentWidget_(d); | 3431 | updateSideIconBuf_DocumentWidget_(d); |
3404 | updateOutline_DocumentWidget_(d); | 3432 | updateOutline_DocumentWidget_(d); |