=> de1cbd837abc6a7dcfef6ed3ee357721cbc2907f
[1mdiff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c[m [1mindex a1b26e7f..78036ef1 100644[m [1m--- a/src/ui/documentwidget.c[m [1m+++ b/src/ui/documentwidget.c[m [36m@@ -159,6 +159,9 @@[m [mstruct Impl_DocumentWidget {[m iPtrArray visibleLinks;[m iPtrArray visibleWideRuns; /* scrollable blocks */[m iArray wideRunOffsets;[m [32m+[m[32m iAnim animWideRunOffset;[m [32m+[m[32m uint16_t animWideRunId;[m [32m+[m[32m iGmRunRange animWideRunRange;[m iPtrArray visiblePlayers; /* currently playing audio */[m const iGmRun * grabbedPlayer; /* currently adjusting volume in a player */[m float grabbedStartVolume;[m [36m@@ -204,6 +207,8 @@[m [mvoid init_DocumentWidget(iDocumentWidget *d) {[m d->redirectCount = 0;[m d->initNormScrollY = 0;[m init_Anim(&d->scrollY, 0);[m [32m+[m[32m d->animWideRunId = 0;[m [32m+[m[32m init_Anim(&d->animWideRunOffset, 0);[m d->selectMark = iNullRange;[m d->foundMark = iNullRange;[m d->pageMargin = 5;[m [36m@@ -270,6 +275,13 @@[m [mvoid deinit_DocumentWidget(iDocumentWidget *d) {[m deinit_PersistentDocumentState(&d->mod);[m }[m [m [32m+[m[32mstatic void resetWideRuns_DocumentWidget_(iDocumentWidget *d) {[m [32m+[m[32m clear_Array(&d->wideRunOffsets);[m [32m+[m[32m d->animWideRunId = 0;[m [32m+[m[32m init_Anim(&d->animWideRunOffset, 0);[m [32m+[m[32m iZap(d->animWideRunRange);[m [32m+[m[32m}[m [32m+[m static void requestUpdated_DocumentWidget_(iAnyObject *obj) {[m iDocumentWidget *d = obj;[m const int wasUpdated = exchange_Atomic(&d->isRequestUpdated, iTrue);[m [36m@@ -386,6 +398,29 @@[m [mstatic void invalidateVisibleLinks_DocumentWidget_(iDocumentWidget *d) {[m }[m }[m [m [32m+[m[32mstatic int runOffset_DocumentWidget_(const iDocumentWidget *d, const iGmRun *run) {[m [32m+[m[32m if (run->preId && run->flags & wide_GmRunFlag) {[m [32m+[m[32m if (d->animWideRunId == run->preId) {[m [32m+[m[32m return -value_Anim(&d->animWideRunOffset);[m [32m+[m[32m }[m [32m+[m[32m const size_t numOffsets = size_Array(&d->wideRunOffsets);[m [32m+[m[32m const int *offsets = constData_Array(&d->wideRunOffsets);[m [32m+[m[32m if (run->preId <= numOffsets) {[m [32m+[m[32m return -offsets[run->preId - 1];[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m return 0;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void invalidateWideRunsWithNonzeroOffset_DocumentWidget_(iDocumentWidget *d) {[m [32m+[m[32m iConstForEach(PtrArray, i, &d->visibleWideRuns) {[m [32m+[m[32m const iGmRun *run = i.ptr;[m [32m+[m[32m if (runOffset_DocumentWidget_(d, run)) {[m [32m+[m[32m insert_PtrSet(d->invalidRuns, run);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) {[m const iWidget *w = constAs_Widget(d);[m const iRect docBounds = documentBounds_DocumentWidget_(d);[m [36m@@ -762,7 +797,7 @@[m [mstatic void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode[m updateTheme_DocumentWidget_(d);[m init_Anim(&d->scrollY, 0);[m init_Anim(&d->sideOpacity, 0);[m [31m- clear_Array(&d->wideRunOffsets);[m [32m+[m[32m resetWideRuns_DocumentWidget_(d);[m d->state = ready_RequestState;[m }[m [m [36m@@ -951,7 +986,7 @@[m [mstatic iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) {[m reset_GmDocument(d->doc);[m d->state = fetching_RequestState;[m d->initNormScrollY = recent->normScrollY;[m [31m- clear_Array(&d->wideRunOffsets);[m [32m+[m[32m resetWideRuns_DocumentWidget_(d);[m /* Use the cached response data. */[m updateTrust_DocumentWidget_(d, resp);[m d->sourceTime = resp->when;[m [36m@@ -977,15 +1012,20 @@[m [mstatic void refreshWhileScrolling_DocumentWidget_(iAny *ptr) {[m iDocumentWidget *d = ptr;[m updateVisible_DocumentWidget_(d);[m refresh_Widget(d);[m [31m- if (!isFinished_Anim(&d->scrollY)) {[m [32m+[m[32m if (d->animWideRunId) {[m [32m+[m[32m for (const iGmRun *r = d->animWideRunRange.start; r != d->animWideRunRange.end; r++) {[m [32m+[m[32m insert_PtrSet(d->invalidRuns, r);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m if (isFinished_Anim(&d->animWideRunOffset)) {[m [32m+[m[32m d->animWideRunId = 0;[m [32m+[m[32m }[m [32m+[m[32m if (!isFinished_Anim(&d->scrollY) || !isFinished_Anim(&d->animWideRunOffset)) {[m addTicker_App(refreshWhileScrolling_DocumentWidget_, d);[m }[m }[m [m static void smoothScroll_DocumentWidget_(iDocumentWidget *d, int offset, int duration) {[m [31m- if (offset == 0) {[m [31m- return;[m [31m- }[m /* Get rid of link numbers when scrolling. */[m if (offset && d->flags & showLinkNumbers_DocumentWidgetFlag) {[m d->flags &= ~showLinkNumbers_DocumentWidgetFlag;[m [36m@@ -1030,7 +1070,8 @@[m [mstatic void scrollTo_DocumentWidget_(iDocumentWidget *d, int documentY, iBool ce[m scroll_DocumentWidget_(d, 0); /* clamp it */[m }[m [m [31m-static void scrollWideBlock_DocumentWidget_(iDocumentWidget *d, iInt2 mousePos, int delta) {[m [32m+[m[32mstatic void scrollWideBlock_DocumentWidget_(iDocumentWidget *d, iInt2 mousePos, int delta,[m [32m+[m[32m int duration) {[m if (delta == 0) {[m return;[m }[m [36m@@ -1057,6 +1098,21 @@[m [mstatic void scrollWideBlock_DocumentWidget_(iDocumentWidget *d, iInt2 mousePos,[m insert_PtrSet(d->invalidRuns, r);[m }[m refresh_Widget(d);[m [32m+[m[32m d->selectMark = iNullRange;[m [32m+[m[32m d->foundMark = iNullRange;[m [32m+[m[32m }[m [32m+[m[32m if (duration) {[m [32m+[m[32m if (d->animWideRunId != run->preId || isFinished_Anim(&d->animWideRunOffset)) {[m [32m+[m[32m d->animWideRunId = run->preId;[m [32m+[m[32m init_Anim(&d->animWideRunOffset, oldOffset);[m [32m+[m[32m }[m [32m+[m[32m setValueEased_Anim(&d->animWideRunOffset, *offset, duration);[m [32m+[m[32m d->animWideRunRange = range;[m [32m+[m[32m addTicker_App(refreshWhileScrolling_DocumentWidget_, d);[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m d->animWideRunId = 0;[m [32m+[m[32m init_Anim(&d->animWideRunOffset, 0);[m }[m break;[m }[m [36m@@ -1097,7 +1153,7 @@[m [mstatic void checkResponse_DocumentWidget_(iDocumentWidget *d) {[m case categorySuccess_GmStatusCode:[m init_Anim(&d->scrollY, 0);[m reset_GmDocument(d->doc); /* new content incoming */[m [31m- clear_Array(&d->wideRunOffsets);[m [32m+[m[32m resetWideRuns_DocumentWidget_(d);[m updateDocument_DocumentWidget_(d, resp, iTrue);[m break;[m case categoryRedirect_GmStatusCode:[m [36m@@ -1764,6 +1820,8 @@[m [mstatic iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)[m }[m }[m }[m [32m+[m[32m invalidateWideRunsWithNonzeroOffset_DocumentWidget_(d); /* markers don't support offsets */[m [32m+[m[32m resetWideRuns_DocumentWidget_(d);[m refresh_Widget(w);[m return iTrue;[m }[m [36m@@ -2063,6 +2121,7 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m if (ev->wheel.which == 0) { /* Trackpad with precise scrolling w/inertia. */[m stop_Anim(&d->scrollY);[m iInt2 wheel = init_I2(ev->wheel.x, ev->wheel.y);[m [32m+[m[32m /* Only scroll on one axis at a time. */[m if (iAbs(wheel.x) > iAbs(wheel.y)) {[m wheel.y = 0;[m }[m [36m@@ -2070,7 +2129,7 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m wheel.x = 0;[m }[m scroll_DocumentWidget_(d, -wheel.y * get_Window()->pixelRatio * acceleration);[m [31m- scrollWideBlock_DocumentWidget_(d, mouseCoord, wheel.x * get_Window()->pixelRatio);[m [32m+[m[32m scrollWideBlock_DocumentWidget_(d, mouseCoord, wheel.x * get_Window()->pixelRatio, 0);[m }[m else[m #endif[m [36m@@ -2092,7 +2151,7 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m /* accelerated speed for repeated wheelings */[m (!isFinished_Anim(&d->scrollY) && pos_Anim(&d->scrollY) < 0.25f ? 0.5f : 1.0f));[m scrollWideBlock_DocumentWidget_([m [31m- d, mouseCoord, ev->wheel.x * lineHeight_Text(paragraph_FontId));[m [32m+[m[32m d, mouseCoord, ev->wheel.x * lineHeight_Text(paragraph_FontId) * 3, 167);[m }[m iChangeFlags(d->flags, noHoverWhileScrolling_DocumentWidgetFlag, iTrue);[m return iTrue;[m [36m@@ -2244,6 +2303,8 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m /* Begin selecting a range of text. */[m if (~d->flags & selecting_DocumentWidgetFlag) {[m setFocus_Widget(NULL); /* TODO: Focus this document? */[m [32m+[m[32m invalidateWideRunsWithNonzeroOffset_DocumentWidget_(d);[m [32m+[m[32m resetWideRuns_DocumentWidget_(d); /* Selections don't support horizontal scrolling. */[m iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iTrue);[m d->selectMark.start = d->selectMark.end =[m sourceLoc_DocumentWidget_(d, d->click.startPos);[m [36m@@ -2444,15 +2505,9 @@[m [mstatic void drawRun_DrawContext_(void *context, const iGmRun *run) {[m const iBool isHover =[m (run->linkId && d->widget->hoverLink && run->linkId == d->widget->hoverLink->linkId &&[m ~run->flags & decoration_GmRunFlag);[m [31m- iInt2 visPos = add_I2(run->visBounds.pos, origin);[m [31m- /* Preformatted runs can be scrolled. */[m [31m- if (run->preId && run->flags & wide_GmRunFlag) {[m [31m- const size_t numOffsets = size_Array(&d->widget->wideRunOffsets);[m [31m- const int *offsets = constData_Array(&d->widget->wideRunOffsets);[m [31m- if (run->preId <= numOffsets) {[m [31m- visPos.x -= offsets[run->preId - 1];[m [31m- }[m [31m- }[m [32m+[m[32m const iInt2 visPos = addX_I2(add_I2(run->visBounds.pos, origin),[m [32m+[m[32m /* Preformatted runs can be scrolled. */[m [32m+[m[32m runOffset_DocumentWidget_(d->widget, run));[m fillRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmBackground_ColorId);[m if (run->linkId && ~run->flags & decoration_GmRunFlag) {[m fg = linkColor_GmDocument(doc, run->linkId, isHover ? textHover_GmLinkPart : text_GmLinkPart);[m [36m@@ -3015,7 +3070,7 @@[m [miBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) {[m [m void updateSize_DocumentWidget(iDocumentWidget *d) {[m setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d));[m [31m- clear_Array(&d->wideRunOffsets);[m [32m+[m[32m resetWideRuns_DocumentWidget_(d);[m updateSideIconBuf_DocumentWidget_(d);[m updateOutline_DocumentWidget_(d);[m updateVisible_DocumentWidget_(d);[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).