From e6002e798d06cf52a71d9d35716c4d0b9c282d99 Mon Sep 17 00:00:00 2001 From: Nikola Nikolic Date: Sun, 16 Oct 2022 23:23:52 +0200 Subject: [PATCH] Fix: Involuntary scrolling when annotations encounter the edge of the page There are three reasons why scrolling happens (first two cases of scrolling are actually due to viewport transition that is triggered by annotation being traslated/created): 1. VisiblePageRect are NormalizedRect and should be represented by four values in [0, 1] interval. Due to rounding errors caused by using QRect, they only reach the [0, 0.999] interval. That means that right and bottom edge of the page are never visible so if annotation is translated along the right/bottom edge viewport transition occurs (fixed in PageView::slotRequestVisiblePixmaps) 2. For freehand line there are some constants (dX, dY) that make a line to be drawn outside the page borders causing viewport transition. Removing these constants solves the problem (fixed in SmoothPathEngine::event) 3. Browse mode is activated as soon as the cursor is moved outside the viewport. Instead, we should forward the move event to the annotation which than can ignore the event (fixed in PageView::mouseMoveEvent) BUG: 436742 --- part/annotationtools.cpp | 18 ++++++++---------- part/pageview.cpp | 17 +++++++++++------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/part/annotationtools.cpp b/part/annotationtools.cpp index b9a727944..ea6dff3da 100644 --- a/part/annotationtools.cpp +++ b/part/annotationtools.cpp @@ -127,18 +127,16 @@ QRect SmoothPathEngine::event(EventType type, Button button, Modifiers /*modifie Okular::NormalizedPoint nextPoint = Okular::NormalizedPoint(nX, nY); points.append(nextPoint); // update total rect - double dX = 2.0 / (double)xScale; - double dY = 2.0 / (double)yScale; - totalRect.left = qMin(totalRect.left, nX - dX); - totalRect.top = qMin(totalRect.top, nY - dY); - totalRect.right = qMax(nX + dX, totalRect.right); - totalRect.bottom = qMax(nY + dY, totalRect.bottom); + totalRect.left = qMin(totalRect.left, nX); + totalRect.top = qMin(totalRect.top, nY); + totalRect.right = qMax(nX, totalRect.right); + totalRect.bottom = qMax(nY, totalRect.bottom); // paint the difference to previous full rect Okular::NormalizedRect incrementalRect; - incrementalRect.left = qMin(nextPoint.x, lastPoint.x) - dX; - incrementalRect.right = qMax(nextPoint.x, lastPoint.x) + dX; - incrementalRect.top = qMin(nextPoint.y, lastPoint.y) - dY; - incrementalRect.bottom = qMax(nextPoint.y, lastPoint.y) + dY; + incrementalRect.left = qMin(nextPoint.x, lastPoint.x); + incrementalRect.right = qMax(nextPoint.x, lastPoint.x); + incrementalRect.top = qMin(nextPoint.y, lastPoint.y); + incrementalRect.bottom = qMax(nextPoint.y, lastPoint.y); lastPoint = nextPoint; return incrementalRect.geometry((int)xScale, (int)yScale); //} diff --git a/part/pageview.cpp b/part/pageview.cpp index d6680a582..05498334e 100644 --- a/part/pageview.cpp +++ b/part/pageview.cpp @@ -2267,7 +2267,7 @@ void PageView::mouseMoveEvent(QMouseEvent *e) PageViewItem *pageItem = pickItemOnPoint(eventPos.x(), eventPos.y()); if (leftButton) { d->leftClickTimer.stop(); - if (pageItem && d->mouseAnnotation->isActive()) { + if (d->mouseAnnotation->isActive()) { // if left button pressed and annotation is focused, forward move event d->mouseAnnotation->routeMouseMoveEvent(pageItem, eventPos, leftButton); } @@ -4680,8 +4680,8 @@ void PageView::slotRequestVisiblePixmaps(int newValue) // precalc view limits for intersecting with page coords inside the loop const bool isEvent = newValue != -1 && !d->blockViewport; - const QRect viewportRect(horizontalScrollBar()->value(), verticalScrollBar()->value(), viewport()->width(), viewport()->height()); - const QRect viewportRectAtZeroZero(0, 0, viewport()->width(), viewport()->height()); + const QRectF viewportRect(horizontalScrollBar()->value(), verticalScrollBar()->value(), viewport()->width(), viewport()->height()); + const QRectF viewportRectAtZeroZero(0, 0, viewport()->width(), viewport()->height()); // some variables used to determine the viewport int nearPageNumber = -1; @@ -4720,14 +4720,18 @@ void PageView::slotRequestVisiblePixmaps(int newValue) qWarning().nospace() << "viewportRect is " << viewportRect << ", page item is " << i->croppedGeometry() << " intersect : " << viewportRect.intersects(i->croppedGeometry()); #endif // if the item doesn't intersect the viewport, skip it - QRect intersectionRect = viewportRect.intersected(i->croppedGeometry()); + QRectF intersectionRect = viewportRect.intersected(i->croppedGeometry()); if (intersectionRect.isEmpty()) { continue; } // add the item to the 'visible list' d->visibleItems.push_back(i); - Okular::VisiblePageRect *vItem = new Okular::VisiblePageRect(i->pageNumber(), Okular::NormalizedRect(intersectionRect.translated(-i->uncroppedGeometry().topLeft()), i->uncroppedWidth(), i->uncroppedHeight())); + + intersectionRect.translate(-i->uncroppedGeometry().topLeft()); + const Okular::NormalizedRect normRect(intersectionRect.left() / i->uncroppedWidth(), intersectionRect.top() / i->uncroppedHeight(), intersectionRect.right() / i->uncroppedWidth(), intersectionRect.bottom() / i->uncroppedHeight()); + + Okular::VisiblePageRect *vItem = new Okular::VisiblePageRect(i->pageNumber(), normRect); visibleRects.push_back(vItem); #ifdef PAGEVIEW_DEBUG qWarning() << "checking for pixmap for page" << i->pageNumber() << "=" << i->page()->hasPixmap(this, i->uncroppedWidth(), i->uncroppedHeight()); @@ -4793,7 +4797,8 @@ void PageView::slotRequestVisiblePixmaps(int newValue) pagesToPreload = d->items.count(); } - const QRect expandedViewportRect = viewportRect.adjusted(0, -pixelsToExpand, 0, pixelsToExpand); + const QRectF adjustedViewportRect = viewportRect.adjusted(0, -pixelsToExpand, 0, pixelsToExpand); + const QRect expandedViewportRect(adjustedViewportRect.x(), adjustedViewportRect.y(), adjustedViewportRect.width(), adjustedViewportRect.height()); for (int j = 1; j <= pagesToPreload; j++) { // add the page after the 'visible series' in preload