diff --git a/autotests/data/simple-multipage.pdf b/autotests/data/simple-multipage.pdf new file mode 100755 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@resize(800, 600); + part.widget()->show(); + QVERIFY( QTest::qWaitForWindowExposed( part.widget() ) ); + + part.m_document->pages(); + part.m_document->setViewportPage( targetPage ); + + /* Document::setViewportPage triggers pixmap rendering in another thread. + * We want to test how things look AFTER finished signal arrives back, + * because PageView::slotRelayoutPages may displace the viewport again. + */ + QTRY_VERIFY( part.m_document->page( targetPage )->hasPixmap( part.m_pageView ) ); + + const int contentAreaHeight = part.m_pageView->verticalScrollBar()->maximum() + part.m_pageView->viewport()->height(); + const int pageWithSpaceTop = contentAreaHeight / part.m_document->pages() * targetPage; + + /* + * This is a test for a "known by trial" displacement. + * We'd need access to part.m_pageView->d->items[targetPage]->croppedGeometry().top(), + * to determine the expected viewport position, but we don't have access. + */ + QCOMPARE(part.m_pageView->verticalScrollBar()->value(), pageWithSpaceTop - 4); +} + } // namespace Okular int main(int argc, char *argv[]) diff --git a/ui/pageview.h b/ui/pageview.h --- a/ui/pageview.h +++ b/ui/pageview.h @@ -198,6 +198,7 @@ QMenu* createProcessLinkMenu( PageViewItem *item, const QPoint & eventPos ); // used when selecting stuff, makes the view scroll as necessary to keep the mouse inside the view void scrollPosIntoView( const QPoint & pos ); + QPoint viewportToContentArea( const Okular::DocumentViewport & vp ) const; // called from slots to turn off trim modes mutually exclusive to id void updateTrimMode( int except_id ); diff --git a/ui/pageview.cpp b/ui/pageview.cpp --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -1331,36 +1331,15 @@ slotRelayoutPages(); // restore viewport center or use default {x-center,v-top} alignment - const QRect & r = item->croppedGeometry(); - int newCenterX = r.left(), - newCenterY = r.top(); - if ( vp.rePos.enabled ) - { - if ( vp.rePos.pos == Okular::DocumentViewport::Center ) - { - newCenterX += (int)( normClamp( vp.rePos.normalizedX, 0.5 ) * (double)r.width() ); - newCenterY += (int)( normClamp( vp.rePos.normalizedY, 0.0 ) * (double)r.height() ); - } - else - { - // TopLeft - newCenterX += (int)( normClamp( vp.rePos.normalizedX, 0.0 ) * (double)r.width() + viewport()->width() / 2 ); - newCenterY += (int)( normClamp( vp.rePos.normalizedY, 0.0 ) * (double)r.height() + viewport()->height() / 2 ); - } - } - else - { - newCenterX += r.width() / 2; - newCenterY += viewport()->height() / 2 - 10; - } + const QPoint centerCoord = viewportToContentArea( vp ); // if smooth movement requested, setup parameters and start it if ( smoothMove ) { d->viewportMoveActive = true; d->viewportMoveTime.start(); - d->viewportMoveDest.setX( newCenterX ); - d->viewportMoveDest.setY( newCenterY ); + d->viewportMoveDest.setX( centerCoord.x() ); + d->viewportMoveDest.setY( centerCoord.y() ); if ( !d->viewportMoveTimer ) { d->viewportMoveTimer = new QTimer( this ); @@ -1372,7 +1351,7 @@ horizontalScrollBar()->setEnabled( false ); } else - center( newCenterX, newCenterY ); + center( centerCoord.x(), centerCoord.y() ); d->blockPixmapsRequest = false; // request visible pixmaps in the current viewport and recompute it @@ -3805,6 +3784,35 @@ else d->dragScrollTimer.stop(); } +QPoint PageView::viewportToContentArea( const Okular::DocumentViewport & vp ) const { + Q_ASSERT( vp.pageNumber >= 0 ); + + const QRect & r = d->items[ vp.pageNumber ]->croppedGeometry(); + QPoint c { r.left(), r.top() }; + + if ( vp.rePos.enabled ) + { + if ( vp.rePos.pos == Okular::DocumentViewport::Center ) + { + c.rx() += qRound( normClamp( vp.rePos.normalizedX, 0.5 ) * (double)r.width() ); + c.ry() += qRound( normClamp( vp.rePos.normalizedY, 0.0 ) * (double)r.height() ); + } + else + { + // TopLeft + c.rx() += qRound( normClamp( vp.rePos.normalizedX, 0.0 ) * (double)r.width() + viewport()->width() / 2 ); + c.ry() += qRound( normClamp( vp.rePos.normalizedY, 0.0 ) * (double)r.height() + viewport()->height() / 2 ); + } + } + else + { + // exact repositioning disabled, align page top margin with viewport top border by default + c.rx() += r.width() / 2; + c.ry() += viewport()->height() / 2 - 10; + } + return c; +} + void PageView::updateSelection( const QPoint & pos ) { if ( d->mouseSelecting ) @@ -4644,11 +4652,10 @@ { int prevX = horizontalScrollBar()->value(), prevY = verticalScrollBar()->value(); - const QRect & geometry = d->items[ vp.pageNumber ]->croppedGeometry(); - double nX = vp.rePos.enabled ? normClamp( vp.rePos.normalizedX, 0.5 ) : 0.5, - nY = vp.rePos.enabled ? normClamp( vp.rePos.normalizedY, 0.0 ) : 0.0; - center( geometry.left() + qRound( nX * (double)geometry.width() ), - geometry.top() + qRound( nY * (double)geometry.height() ) ); + + const QPoint centerPos = viewportToContentArea( vp ); + center( centerPos.x(), centerPos.y() ); + // center() usually moves the viewport, that requests pixmaps too. // if that doesn't happen we have to request them by hand if ( prevX == horizontalScrollBar()->value() && prevY == verticalScrollBar()->value() )