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
remotes/origin/esari-master-patch-95617
Nikola Nikolic 3 years ago committed by Oliver Sander
parent e4b1d3d776
commit e6002e798d
  1. 18
      part/annotationtools.cpp
  2. 17
      part/pageview.cpp

@ -127,18 +127,16 @@ QRect SmoothPathEngine::event(EventType type, Button button, Modifiers /*modifie
Okular::NormalizedPoint nextPoint = Okular::NormalizedPoint(nX, nY); Okular::NormalizedPoint nextPoint = Okular::NormalizedPoint(nX, nY);
points.append(nextPoint); points.append(nextPoint);
// update total rect // update total rect
double dX = 2.0 / (double)xScale; totalRect.left = qMin(totalRect.left, nX);
double dY = 2.0 / (double)yScale; totalRect.top = qMin(totalRect.top, nY);
totalRect.left = qMin(totalRect.left, nX - dX); totalRect.right = qMax(nX, totalRect.right);
totalRect.top = qMin(totalRect.top, nY - dY); totalRect.bottom = qMax(nY, totalRect.bottom);
totalRect.right = qMax(nX + dX, totalRect.right);
totalRect.bottom = qMax(nY + dY, totalRect.bottom);
// paint the difference to previous full rect // paint the difference to previous full rect
Okular::NormalizedRect incrementalRect; Okular::NormalizedRect incrementalRect;
incrementalRect.left = qMin(nextPoint.x, lastPoint.x) - dX; incrementalRect.left = qMin(nextPoint.x, lastPoint.x);
incrementalRect.right = qMax(nextPoint.x, lastPoint.x) + dX; incrementalRect.right = qMax(nextPoint.x, lastPoint.x);
incrementalRect.top = qMin(nextPoint.y, lastPoint.y) - dY; incrementalRect.top = qMin(nextPoint.y, lastPoint.y);
incrementalRect.bottom = qMax(nextPoint.y, lastPoint.y) + dY; incrementalRect.bottom = qMax(nextPoint.y, lastPoint.y);
lastPoint = nextPoint; lastPoint = nextPoint;
return incrementalRect.geometry((int)xScale, (int)yScale); return incrementalRect.geometry((int)xScale, (int)yScale);
//} //}

@ -2267,7 +2267,7 @@ void PageView::mouseMoveEvent(QMouseEvent *e)
PageViewItem *pageItem = pickItemOnPoint(eventPos.x(), eventPos.y()); PageViewItem *pageItem = pickItemOnPoint(eventPos.x(), eventPos.y());
if (leftButton) { if (leftButton) {
d->leftClickTimer.stop(); d->leftClickTimer.stop();
if (pageItem && d->mouseAnnotation->isActive()) { if (d->mouseAnnotation->isActive()) {
// if left button pressed and annotation is focused, forward move event // if left button pressed and annotation is focused, forward move event
d->mouseAnnotation->routeMouseMoveEvent(pageItem, eventPos, leftButton); 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 // precalc view limits for intersecting with page coords inside the loop
const bool isEvent = newValue != -1 && !d->blockViewport; const bool isEvent = newValue != -1 && !d->blockViewport;
const QRect viewportRect(horizontalScrollBar()->value(), verticalScrollBar()->value(), viewport()->width(), viewport()->height()); const QRectF viewportRect(horizontalScrollBar()->value(), verticalScrollBar()->value(), viewport()->width(), viewport()->height());
const QRect viewportRectAtZeroZero(0, 0, viewport()->width(), viewport()->height()); const QRectF viewportRectAtZeroZero(0, 0, viewport()->width(), viewport()->height());
// some variables used to determine the viewport // some variables used to determine the viewport
int nearPageNumber = -1; 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()); qWarning().nospace() << "viewportRect is " << viewportRect << ", page item is " << i->croppedGeometry() << " intersect : " << viewportRect.intersects(i->croppedGeometry());
#endif #endif
// if the item doesn't intersect the viewport, skip it // 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()) { if (intersectionRect.isEmpty()) {
continue; continue;
} }
// add the item to the 'visible list' // add the item to the 'visible list'
d->visibleItems.push_back(i); 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); visibleRects.push_back(vItem);
#ifdef PAGEVIEW_DEBUG #ifdef PAGEVIEW_DEBUG
qWarning() << "checking for pixmap for page" << i->pageNumber() << "=" << i->page()->hasPixmap(this, i->uncroppedWidth(), i->uncroppedHeight()); 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(); 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++) { for (int j = 1; j <= pagesToPreload; j++) {
// add the page after the 'visible series' in preload // add the page after the 'visible series' in preload

Loading…
Cancel
Save