Index: src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 19557)
+++ src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(working copy)
@@ -792,13 +792,21 @@
             return ds.update(() -> {
                 if (mode == Mode.ROTATE) {
                     if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand) c).getTransformedNodes())) {
-                        ((RotateCommand) c).handleEvent(currentEN);
+                        if (didMouseDrag) {
+                            ((RotateCommand) c).handleEvent(currentEN);
+                        } else {
+                            ((RotateCommand) c).handleUpdate(currentEN);
+                        }
                     } else {
                         UndoRedoHandler.getInstance().add(new RotateCommand(selection, currentEN));
                     }
                 } else if (mode == Mode.SCALE) {
                     if (c instanceof ScaleCommand && affectedNodes.equals(((ScaleCommand) c).getTransformedNodes())) {
-                        ((ScaleCommand) c).handleEvent(currentEN);
+                        if (didMouseDrag) {
+                            ((ScaleCommand) c).handleEvent(currentEN);
+                        } else {
+                            ((ScaleCommand) c).handleUpdate(currentEN);
+                        }
                     } else {
                         UndoRedoHandler.getInstance().add(new ScaleCommand(selection, currentEN));
                     }
@@ -821,6 +829,21 @@
         }
     }
 
+    private boolean movesOutside() {
+        DataSet ds = getLayerManager().getEditDataSet();
+        if (ds.getDataSourceBounds().isEmpty())
+            return false;
+        final Collection<Node> elementsToTest = new HashSet<>(ds.getSelectedNodes());
+        for (Way osm : ds.getSelectedWays()) {
+            elementsToTest.addAll(osm.getNodes());
+        }
+        for (Node n : elementsToTest) {
+            if (n.isOutsideDownloadArea())
+                return true;
+        }
+        return false;
+    }
+
     private static boolean doesImpactStatusLine(Collection<Node> affectedNodes, Collection<Way> selectedWays) {
         return selectedWays.stream()
                 .flatMap(w -> w.getNodes().stream())
@@ -870,6 +893,12 @@
      * @param e the mouse event causing the action (mouse released)
      */
     private void confirmOrUndoMovement(MouseEvent e) {
+        final Command lastCommand = UndoRedoHandler.getInstance().getLastCommand();
+        if (lastCommand == null) {
+            Logging.warn("No command found in undo/redo history, skipping confirmOrUndoMovement");
+            return;
+        }
+
         if (movesHiddenWay()) {
             final ConfirmMoveDialog ed = new ConfirmMoveDialog();
             ed.setContent(tr("Are you sure that you want to move elements with attached ways that are hidden by filters?"));
@@ -876,12 +905,19 @@
             ed.toggleEnable("movedHiddenElements");
             showConfirmMoveDialog(ed);
         }
+        // check if move was cancelled
+        if (UndoRedoHandler.getInstance().getLastCommand() != lastCommand)
+            return;
 
-        final Command lastCommand = UndoRedoHandler.getInstance().getLastCommand();
-        if (lastCommand == null) {
-            Logging.warn("No command found in undo/redo history, skipping confirmOrUndoMovement");
+        if (movesOutside()) {
+            final ConfirmMoveDialog ed = new ConfirmMoveDialog();
+            ed.setContent(tr("Are you sure that you want to move nodes outside the downloaded area?"));
+            ed.toggleEnable("movedOutsideNodes");
+            showConfirmMoveDialog(ed);
+        }
+        // check if move was cancelled
+        if (UndoRedoHandler.getInstance().getLastCommand() != lastCommand)
             return;
-        }
 
         SelectAction.checkCommandForLargeDistance(lastCommand);
 
Index: src/org/openstreetmap/josm/command/RotateCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/RotateCommand.java	(revision 19557)
+++ src/org/openstreetmap/josm/command/RotateCommand.java	(working copy)
@@ -25,7 +25,7 @@
     /**
      * angle of rotation starting click to pivot
      */
-    private final double startAngle;
+    private double startAngle;
 
     /**
      * computed rotation angle between starting click and current mouse pos
@@ -32,6 +32,8 @@
      */
     private double rotationAngle;
 
+    private double deltaAngle;
+
     /**
      * Creates a RotateCommand.
      * Assign the initial object set, compute pivot point and initial rotation angle.
@@ -65,11 +67,21 @@
     @Override
     public final void handleEvent(EastNorth currentEN) {
         double currentAngle = getAngle(currentEN);
-        rotationAngle = currentAngle - startAngle;
+        rotationAngle = currentAngle - startAngle + deltaAngle;
         transformNodes();
     }
 
     /**
+     * Handle a repeated rotation action where the mouse was moved to a different position
+     * see #24695
+     * @param startEN start cursor position of a repeated rotation
+     */
+    public void handleUpdate(EastNorth startEN) {
+        deltaAngle = rotationAngle;
+        startAngle = getAngle(startEN);
+    }
+
+    /**
      * Set the rotation angle.
      * @param rotationAngle The rotate angle
      */
Index: src/org/openstreetmap/josm/command/ScaleCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/ScaleCommand.java	(revision 19557)
+++ src/org/openstreetmap/josm/command/ScaleCommand.java	(working copy)
@@ -26,9 +26,14 @@
     private double scalingFactor;
 
     /**
+     * scaling factor applied previously
+     */
+    private double deltaScalingFactor;
+
+    /**
      * World position of the mouse when the user started the command.
      */
-    private final EastNorth startEN;
+    private EastNorth startEN;
 
     /**
      * Creates a ScaleCommand.
@@ -57,12 +62,26 @@
      */
     @Override
     public final void handleEvent(EastNorth currentEN) {
-        double startAngle = Math.atan2(startEN.east()-pivot.east(), startEN.north()-pivot.north());
-        double endAngle = Math.atan2(currentEN.east()-pivot.east(), currentEN.north()-pivot.north());
+        setScalingFactor(deltaScalingFactor + calcScalingFactor(currentEN));
+        transformNodes();
+    }
+
+    /**
+     * Handle a repeated scaling action where the mouse was moved to a different position
+     * see #24695
+     * @param newStartEN start cursor position of a repeated scaling
+     */
+    public void handleUpdate(EastNorth newStartEN) {
+        startEN = newStartEN;
+        deltaScalingFactor = scalingFactor - calcScalingFactor(newStartEN);
+    }
+
+    private double calcScalingFactor(EastNorth currentEN) {
+        double startAngle = Math.atan2(startEN.east() - pivot.east(), startEN.north() - pivot.north());
+        double endAngle = Math.atan2(currentEN.east() - pivot.east(), currentEN.north() - pivot.north());
         double startDistance = pivot.distance(startEN);
         double currentDistance = pivot.distance(currentEN);
-        setScalingFactor(Math.cos(startAngle-endAngle) * currentDistance / startDistance);
-        transformNodes();
+        return Math.cos(startAngle - endAngle) * currentDistance / startDistance;
     }
 
     /**
