diff --git a/ui/pageview.h b/ui/pageview.h --- a/ui/pageview.h +++ b/ui/pageview.h @@ -210,6 +210,7 @@ void createAnnotationsVideoWidgets(PageViewItem *item, const QLinkedList< Okular::Annotation * > &annotations); + void holdZoomCenter( ZoomMode newZm, QPointF zoomCenter, float newZoom = 0.0 ); // don't want to expose classes in here class PageViewPrivate * d; diff --git a/ui/pageview.cpp b/ui/pageview.cpp --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -245,6 +245,7 @@ // Keep track of mouse over link object const Okular::ObjectRect * mouseOverLinkObject; + bool pinchActive; }; PageViewPrivate::PageViewPrivate( PageView *qq ) @@ -365,6 +366,7 @@ d->aMouseMagnifier = nullptr; d->aFitWindowToPage = nullptr; d->trimBoundingBox = Okular::NormalizedRect(); // Null box + d->pinchActive = false; switch( Okular::Settings::zoomMode() ) { @@ -1579,19 +1581,15 @@ if (pinch->state() == Qt::GestureStarted) { vanillaZoom = d->zoomFactor; + d->pinchActive = true; } const QPinchGesture::ChangeFlags changeFlags = pinch->changeFlags(); // Zoom if (pinch->changeFlags() & QPinchGesture::ScaleFactorChanged) { - d->zoomFactor = vanillaZoom * pinch->totalScaleFactor(); - - d->blockPixmapsRequest = true; - updateZoom( ZoomRefreshCurrent ); - d->blockPixmapsRequest = false; - viewport()->repaint(); + holdZoomCenter( ZoomRefreshCurrent, mapFromGlobal( pinch->centerPoint().toPoint()), vanillaZoom * pinch->totalScaleFactor() ); } // Count the number of 90-degree rotations we did since the start of the pinch gesture. @@ -1618,6 +1616,7 @@ if (pinch->state() == Qt::GestureFinished) { rotations = 0; + d->pinchActive = false; } return true; @@ -2051,6 +2050,9 @@ void PageView::mouseMoveEvent( QMouseEvent * e ) { + if ( e->source() == Qt::MouseEventSynthesizedByQt && d->pinchActive ) + return; + // For some reason in Qt 5.11.2 (no idea when this started) all wheel // events are followed by mouse move events (without changing position), // so we only actually reset the controlWheelAccumulatedDelta if there is a mouse movement @@ -2102,11 +2104,7 @@ // update zoom level, perform zoom and redraw if ( deltaY ) { - d->zoomFactor *= ( 1.0 + ( (double)deltaY / 500.0 ) ); - d->blockPixmapsRequest = true; - updateZoom( ZoomRefreshCurrent ); - d->blockPixmapsRequest = false; - viewport()->repaint(); + holdZoomCenter( ZoomRefreshCurrent , mapFromGlobal(d->mousePressPos), d->zoomFactor * ( 1.0 + ( (double)deltaY / 500.0 ) )); } return; } @@ -2253,6 +2251,9 @@ d->autoScrollTimer->stop(); } + // update press / 'start drag' mouse position + d->mousePressPos = e->globalPos(); + // if pressing mid mouse button while not doing other things, begin 'continuous zoom' mode if ( e->button() == Qt::MidButton ) { @@ -2283,9 +2284,6 @@ return; } - // update press / 'start drag' mouse position - d->mousePressPos = e->globalPos(); - // handle mode dependent mouse press actions bool leftButton = e->button() == Qt::LeftButton, rightButton = e->button() == Qt::RightButton; @@ -3302,12 +3300,12 @@ d->controlWheelAccumulatedDelta += delta; if ( d->controlWheelAccumulatedDelta <= -QWheelEvent::DefaultDeltasPerStep ) { - slotZoomOut(); + holdZoomCenter( ZoomOut, e->pos() ); d->controlWheelAccumulatedDelta = 0; } else if ( d->controlWheelAccumulatedDelta >= QWheelEvent::DefaultDeltasPerStep ) { - slotZoomIn(); + holdZoomCenter( ZoomIn, e->pos() ); d->controlWheelAccumulatedDelta = 0; } } @@ -4438,6 +4436,27 @@ return nullptr; } +void PageView::holdZoomCenter(PageView::ZoomMode newZm, QPointF zoomCenter, float newZoom) +{ + const QPointF centerBegin = viewportToContentArea( d->document->viewport() ); + const QPointF oldScroll = contentAreaPosition(); + + d->blockPixmapsRequest = true; + + if ( newZoom ) + d->zoomFactor = newZoom; + + updateZoom( newZm ); + + const QPointF centerEnd = viewportToContentArea( d->document->viewport() ); + //The calculation for newScroll is taken from Gwenview class Abstractimageview::setZoom + const double zoomFactor = centerEnd.y() / centerBegin.y(); + const QPointF newScroll = zoomFactor * ( oldScroll + zoomCenter ) - zoomCenter; + + d->blockPixmapsRequest = false; + scrollTo( newScroll.x(), newScroll.y() ); +} + //BEGIN private SLOTS void PageView::slotRelayoutPages() // called by: notifySetup, viewportResizeEvent, slotViewMode, slotContinuousToggled, updateZoom