From 2932f7c6761fc523087c0d514b93488eb92e7236 Mon Sep 17 00:00:00 2001
From: Rob Wu <rob@robwu.nl>
Date: Thu, 2 Jul 2015 23:20:37 +0200
Subject: [PATCH] Zoom relative to cursor position via mouse wheel

Before this patch, zooming in/out via the scroll wheel caused the page
to be zoomed relative to the upper-left corner of the page, i.e. the
upper-left corner of the page stays at a fixed position.

After this patch, the page is zoomed relative to the cursor position,
i.e. after zooming in/out, the part under the cursor 'has not moved'.

This only applies when the page does not fit in the viewport, because
pages smaller than the viewpoer are always centered.
---
 web/viewer.js | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/web/viewer.js b/web/viewer.js
index 1588ad605..c42545f21 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -1811,14 +1811,31 @@ function handleMouseWheel(evt) {
               evt.wheelDelta / MOUSE_WHEEL_DELTA_FACTOR;
   var direction = (ticks < 0) ? 'zoomOut' : 'zoomIn';
 
-  if (PDFViewerApplication.pdfViewer.isInPresentationMode) {
+  var pdfViewer = PDFViewerApplication.pdfViewer;
+  if (pdfViewer.isInPresentationMode) {
     evt.preventDefault();
     PDFViewerApplication.scrollPresentationMode(ticks *
                                                 MOUSE_WHEEL_DELTA_FACTOR);
   } else if (evt.ctrlKey || evt.metaKey) {
     // Only zoom the pages, not the entire viewer.
     evt.preventDefault();
+
+    var previousScale = pdfViewer.currentScale;
+
     PDFViewerApplication[direction](Math.abs(ticks));
+
+    var currentScale = pdfViewer.currentScale;
+    if (previousScale !== currentScale) {
+      // After scaling the page via zoomIn/zoomOut, the position of the upper-
+      // left corner is restored. When the mouse wheel is used, the position
+      // under the cursor should be restored instead.
+      var scaleCorrectionFactor = currentScale / previousScale - 1;
+      var rect = pdfViewer.container.getBoundingClientRect();
+      var dx = evt.clientX - rect.left;
+      var dy = evt.clientY - rect.top;
+      pdfViewer.container.scrollLeft += dx * scaleCorrectionFactor;
+      pdfViewer.container.scrollTop += dy * scaleCorrectionFactor;
+    }
   }
 }