[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/plain
This content has been proxied by September (ba2dc).