diff --git a/fsl/fsleyes/displaycontext/canvasopts.py b/fsl/fsleyes/displaycontext/canvasopts.py
index 94a99d17c0d0364c58edebf791fc218cd623d0d4..2f7e214eac651cf182c4f874e67aa8df203fbe00 100644
--- a/fsl/fsleyes/displaycontext/canvasopts.py
+++ b/fsl/fsleyes/displaycontext/canvasopts.py
@@ -36,7 +36,7 @@ class SliceCanvasOpts(props.HasProperties):
 
     
     zoom = props.Percentage(minval=100.0,
-                            maxval=1000.0,
+                            maxval=5000.0,
                             default=100.0,
                             clamped=True)
     """The :attr:`.DisplayContext.bounds` are divided by this zoom
diff --git a/fsl/fsleyes/displaycontext/lightboxopts.py b/fsl/fsleyes/displaycontext/lightboxopts.py
index 5189ec75790e175d9ef5e4df70d2c4d845753952..6c40f30ad2b5354df1357a78daa51f2dda7c5449 100644
--- a/fsl/fsleyes/displaycontext/lightboxopts.py
+++ b/fsl/fsleyes/displaycontext/lightboxopts.py
@@ -48,6 +48,7 @@ class LightBoxOpts(sceneopts.SceneOpts):
         """
         sceneopts.SceneOpts.__init__(self, *args, **kwargs)
         self.setConstraint('zoom', 'minval', 10)
+        self.setConstraint('zoom', 'maxval', 1000)
 
         
     def _onPerformanceChange(self, *a):
diff --git a/fsl/fsleyes/gl/lightboxcanvas.py b/fsl/fsleyes/gl/lightboxcanvas.py
index 5879c5854215141249fb59a20a733076aae7520f..fd05154b074bf410d31be543e9866a3327940de5 100644
--- a/fsl/fsleyes/gl/lightboxcanvas.py
+++ b/fsl/fsleyes/gl/lightboxcanvas.py
@@ -478,7 +478,7 @@ class LightBoxCanvas(slicecanvas.SliceCanvas):
         self._genSliceLocations()
         
         
-    def _updateDisplayBounds(self):
+    def _updateDisplayBounds(self, *args, **kwargs):
         """Overrides :meth:`.SliceCanvas._updateDisplayBounds`.
 
         Called on canvas resizes, display bound changes and lightbox slice
diff --git a/fsl/fsleyes/gl/slicecanvas.py b/fsl/fsleyes/gl/slicecanvas.py
index 25b1425714dd24296ab4df19410ba4e39ce598a9..08068e11dc54dd3064ac495113b9c15ff794a75e 100644
--- a/fsl/fsleyes/gl/slicecanvas.py
+++ b/fsl/fsleyes/gl/slicecanvas.py
@@ -859,15 +859,18 @@ class SliceCanvas(props.HasProperties):
         """
 
         ovlBounds = self.displayCtx.bounds
+        oldPos    = self.pos.xy
 
+        self.disableNotification('pos')
         self.pos.setMin(0, ovlBounds.getLo(self.xax))
         self.pos.setMax(0, ovlBounds.getHi(self.xax))
         self.pos.setMin(1, ovlBounds.getLo(self.yax))
         self.pos.setMax(1, ovlBounds.getHi(self.yax))
         self.pos.setMin(2, ovlBounds.getLo(self.zax))
         self.pos.setMax(2, ovlBounds.getHi(self.zax))
+        self.enableNotification('pos')
 
-        self._updateDisplayBounds()
+        self._updateDisplayBounds(oldLoc=oldPos)
 
 
     def _zoomChanged(self, *a):
@@ -931,10 +934,15 @@ class SliceCanvas(props.HasProperties):
         return (xmin, xmax, ymin, ymax)
 
         
-    def _updateDisplayBounds(self, xmin=None, xmax=None, ymin=None, ymax=None):
+    def _updateDisplayBounds(self,
+                             xmin=None,
+                             xmax=None,
+                             ymin=None,
+                             ymax=None,
+                             oldLoc=None):
         """Called on canvas resizes, overlay bound changes, and zoom changes.
         
-        Calculates the bounding box, in world coordinates, to be displayed on
+        Calculates the bounding box, in display coordinates, to be displayed on
         the canvas. Stores this bounding box in the displayBounds property. If
         any of the parameters are not provided, the
         :attr:`.DisplayContext.bounds` are used.
@@ -943,11 +951,20 @@ class SliceCanvas(props.HasProperties):
         .. note:: This method is used internally, and also by the
                   :class:`.WXGLSliceCanvas` class.
 
+        .. warning:: This code assumes that, if the display coordinate system
+                     has changed, the display context location has already
+                     been updated.  See the
+                     :meth:`.DisplayContext.__displaySpaceChanged` method.
+        
         
-        :arg xmin: Minimum x (horizontal) value to be in the display bounds.
-        :arg xmax: Maximum x value to be in the display bounds.
-        :arg ymin: Minimum y (vertical) value to be in the display bounds.
-        :arg ymax: Maximum y value to be in the display bounds.
+        :arg xmin:   Minimum x (horizontal) value to be in the display bounds.
+        :arg xmax:   Maximum x value to be in the display bounds.
+        :arg ymin:   Minimum y (vertical) value to be in the display bounds.
+        :arg ymax:   Maximum y value to be in the display bounds.
+        :arg oldLoc: If provided, should be the ``(x, y)`` location shown on
+                     this ``SliceCanvas`` - the new display bounds will be
+                     adjusted so that this location remains the same, with
+                     respect to the new field of view.
         """
 
         if xmin is None: xmin = self.displayCtx.bounds.getLo(self.xax)
@@ -991,11 +1008,44 @@ class SliceCanvas(props.HasProperties):
             ymin          = ymin - 0.5 * (newDispHeight - dispHeight)
             ymax          = ymax + 0.5 * (newDispHeight - dispHeight)
 
+        oldxmin, oldxmax, oldymin, oldymax = self.displayBounds[:]
+
+        self.disableNotification('displayBounds')
         self.displayBounds.setLimits(0, xmin, xmax)
-        self.displayBounds.setLimits(1, ymin, ymax) 
+        self.displayBounds.setLimits(1, ymin, ymax)
+        self.enableNotification('displayBounds')
 
         xmin, xmax, ymin, ymax = self._applyZoom(xmin, xmax, ymin, ymax)
 
+        if oldLoc and (oldxmax > oldxmin) and (oldymax > oldymin):
+
+            # Calculate the normalised distance from the
+            # old cursor loaction to the old bound corner
+            oldxoff = (oldLoc[0] - oldxmin) / (oldxmax - oldxmin)
+            oldyoff = (oldLoc[1] - oldymin) / (oldymax - oldymin)
+
+            # Re-set the new bounds to the current
+            # display location, offset by the same
+            # amount that it used to be (as 
+            # calculated above).
+            #
+            # N.B. This code assumes that, if the display
+            #      coordinate system has changed, the display
+            #      context location has already been updated.
+            #      See the DisplayContext.__displaySpaceChanged
+            #      method.
+            xloc = self.displayCtx.location[self.xax]
+            yloc = self.displayCtx.location[self.yax]
+ 
+            xlen = xmax - xmin
+            ylen = ymax - ymin
+
+            xmin = xloc - oldxoff * xlen
+            ymin = yloc - oldyoff * ylen
+            
+            xmax = xmin + xlen
+            ymax = ymin + ylen
+            
         log.debug('Final display bounds: X: ({}, {}) Y: ({}, {})'.format(
             xmin, xmax, ymin, ymax))