diff --git a/src/org/openstreetmap/josm/gui/MapMover.java b/src/org/openstreetmap/josm/gui/MapMover.java
index ed694864cc..c2338f6e53 100644
--- a/src/org/openstreetmap/josm/gui/MapMover.java
+++ b/src/org/openstreetmap/josm/gui/MapMover.java
@@ -185,7 +185,7 @@ public class MapMover extends MouseAdapter implements Destroyable {
         if (allowMovement) {
             doMoveForDrag(e);
         } else {
-            endMovement();
+            endMovement(e);
         }
     }
 
@@ -195,7 +195,7 @@ public class MapMover extends MouseAdapter implements Destroyable {
         }
         EastNorth center = nc.getCenter();
         EastNorth mouseCenter = nc.getEastNorth(e.getX(), e.getY());
-        nc.zoomTo(mousePosMoveStart.getEastNorth().add(center).subtract(mouseCenter));
+        nc.zoomTo(e, mousePosMoveStart.getEastNorth().add(center).subtract(mouseCenter));
     }
 
     /**
@@ -217,7 +217,7 @@ public class MapMover extends MouseAdapter implements Destroyable {
     @Override
     public void mouseReleased(MouseEvent e) {
         if (e.getButton() == MouseEvent.BUTTON3 || (PlatformManager.isPlatformOsx() && e.getButton() == MouseEvent.BUTTON1)) {
-            endMovement();
+            endMovement(e);
         }
     }
 
@@ -237,10 +237,11 @@ public class MapMover extends MouseAdapter implements Destroyable {
     /**
      * End the movement. Setting back the cursor and clear the movement variables
      */
-    private void endMovement() {
+    private void endMovement(MouseEvent e) {
         if (!movementInProgress()) {
             return;
         }
+        doMoveForDrag(e);
         nc.resetCursor(this);
         mousePosMoveStart = null;
         MainApplication.getLayerManager().getLayers().forEach(Layer::invalidate);
@@ -270,7 +271,7 @@ public class MapMover extends MouseAdapter implements Destroyable {
             if (e.getModifiersEx() == MouseEvent.CTRL_DOWN_MASK) {
                 doMoveForDrag(e);
             } else {
-                endMovement();
+                endMovement(e);
             }
         }
     }
diff --git a/src/org/openstreetmap/josm/gui/NavigatableComponent.java b/src/org/openstreetmap/josm/gui/NavigatableComponent.java
index cde5057396..224d980482 100644
--- a/src/org/openstreetmap/josm/gui/NavigatableComponent.java
+++ b/src/org/openstreetmap/josm/gui/NavigatableComponent.java
@@ -8,6 +8,8 @@ import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.awt.event.HierarchyEvent;
 import java.awt.event.HierarchyListener;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
 import java.nio.charset.StandardCharsets;
@@ -77,6 +79,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
 
     /**
      * Interface to notify listeners of the change of the zoom area.
+     * If you need to not paint during panning, override {@link #zoomChanged(InputEvent)}.
      * @since 10600 (functional interface)
      */
     @FunctionalInterface
@@ -85,6 +88,15 @@ public class NavigatableComponent extends JComponent implements Helpful {
          * Method called when the zoom area has changed.
          */
         void zoomChanged();
+
+        /**
+         * Method called when the zoom area has changed.
+         * @param event The originating input event. May be {@code null}.
+         * @since xxx
+         */
+        default void zoomChanged(InputEvent event) {
+            zoomChanged();
+        }
     }
 
     /**
@@ -141,12 +153,23 @@ public class NavigatableComponent extends JComponent implements Helpful {
         }
     }
 
+    /**
+     * Fire zoom changed events. Kept for backwards compatibility.
+     * @deprecated Since xxx, use {@link #fireZoomChanged(InputEvent)} instead ({@code null} safe)
+     */
+    @Deprecated
     protected static void fireZoomChanged() {
+
+    }
+
+    protected static void fireZoomChanged(InputEvent originatingEvent) {
         GuiHelper.runInEDTAndWait(() -> {
             for (ZoomChangeListener l : zoomChangeListeners) {
-                l.zoomChanged();
+                l.zoomChanged(originatingEvent);
             }
         });
+        // Just in case someone, somewhere, decided to subclass this and override fireZoomChanged.
+        fireZoomChanged();
     }
 
     // The only events that may move/resize this map view are window movements or changes to the map view size.
@@ -617,6 +640,18 @@ public class NavigatableComponent extends JComponent implements Helpful {
      * @param initial true if this call initializes the viewport.
      */
     public void zoomTo(EastNorth center, double scale, boolean initial) {
+        zoomTo(null, center, scale, initial);
+    }
+
+    /**
+     * Zoom to the given coordinate and scale.
+     *
+     * @param e The originating input event
+     * @param center The center x-value (easting) to zoom to.
+     * @param scale The scale to use.
+     * @param initial true if this call initializes the viewport.
+     */
+    void zoomTo(InputEvent e, EastNorth center, double scale, boolean initial) {
         Bounds b = getProjection().getWorldBoundsLatLon();
         ProjectionBounds pb = getProjection().getWorldBoundsBoxEastNorth();
         double newScale = scale;
@@ -682,22 +717,24 @@ public class NavigatableComponent extends JComponent implements Helpful {
         newCenter = newCenter.subtract(enShift);
 
         EastNorth oldCenter = getCenter();
-        if (!newCenter.equals(oldCenter) || !Utils.equalsEpsilon(getScale(), newScale)) {
+        if (!newCenter.equals(oldCenter) || !Utils.equalsEpsilon(getScale(), newScale)
+                || (e != null && e.getID() == MouseEvent.MOUSE_RELEASED)) {
             if (!initial) {
                 pushZoomUndo(oldCenter, getScale());
             }
-            zoomNoUndoTo(newCenter, newScale, initial);
+            zoomNoUndoTo(e, newCenter, newScale, initial);
         }
     }
 
     /**
      * Zoom to the given coordinate without adding to the zoom undo buffer.
      *
+     * @param originatingEvent The originating input event
      * @param newCenter The center x-value (easting) to zoom to.
      * @param newScale The scale to use.
      * @param initial true if this call initializes the viewport.
      */
-    private void zoomNoUndoTo(EastNorth newCenter, double newScale, boolean initial) {
+    private void zoomNoUndoTo(InputEvent originatingEvent, EastNorth newCenter, double newScale, boolean initial) {
         if (!Utils.equalsEpsilon(getScale(), newScale)) {
             state = state.usingScale(newScale);
         }
@@ -706,7 +743,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
         }
         if (!initial) {
             repaint();
-            fireZoomChanged();
+            fireZoomChanged(originatingEvent);
         }
     }
 
@@ -718,6 +755,15 @@ public class NavigatableComponent extends JComponent implements Helpful {
         zoomTo(newCenter, getScale());
     }
 
+    /**
+     * Zoom to given east/north.
+     * @param e The originating input event
+     * @param newCenter new center coordinates
+     */
+    void zoomTo(InputEvent e, EastNorth newCenter) {
+        zoomTo(e, newCenter, getScale(), false);
+    }
+
     /**
      * Zoom to given lat/lon.
      * @param newCenter new center coordinates
@@ -943,7 +989,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
         if (!zoomUndoBuffer.isEmpty()) {
             ZoomData zoom = zoomUndoBuffer.pop();
             zoomRedoBuffer.push(new ZoomData(getCenter(), getScale()));
-            zoomNoUndoTo(zoom.getCenterEastNorth(), zoom.getScale(), false);
+            zoomNoUndoTo(null, zoom.getCenterEastNorth(), zoom.getScale(), false);
         }
     }
 
@@ -954,7 +1000,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
         if (!zoomRedoBuffer.isEmpty()) {
             ZoomData zoom = zoomRedoBuffer.pop();
             zoomUndoBuffer.push(new ZoomData(getCenter(), getScale()));
-            zoomNoUndoTo(zoom.getCenterEastNorth(), zoom.getScale(), false);
+            zoomNoUndoTo(null, zoom.getCenterEastNorth(), zoom.getScale(), false);
         }
     }
 
diff --git a/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java b/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java
index 3a7ccb67a2..c96baef2b3 100644
--- a/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java
+++ b/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java
@@ -4,6 +4,8 @@ package org.openstreetmap.josm.gui.autofilter;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Graphics2D;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -127,7 +129,16 @@ implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc
         registerAutoFilterRules(AutoFilterRule.defaultRules());
     }
 
-    private synchronized void updateButtons() {
+    private void updateButtons() {
+        updateButtons(null);
+    }
+
+    private synchronized void updateButtons(InputEvent inputEvent) {
+        // Don't update while dragging
+        if (inputEvent != null && inputEvent instanceof MouseEvent &&
+                ((MouseEvent) inputEvent).getID() == MouseEvent.MOUSE_DRAGGED) {
+            return;
+        }
         MapFrame map = MainApplication.getMap();
         if (enabledRule != null && map != null
                 && enabledRule.getMinZoomLevel() <= Selector.GeneralSelector.scale2level(map.mapView.getDist100Pixel())) {
@@ -261,7 +272,12 @@ implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc
 
     @Override
     public void zoomChanged() {
-        updateButtons();
+        this.zoomChanged(null);
+    }
+
+    @Override
+    public void zoomChanged(InputEvent event) {
+        updateButtons(event);
     }
 
     @Override
