Index: src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 5088)
+++ src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(working copy)
@@ -251,6 +251,7 @@
      * @return true if a repaint is required
      */
     private boolean removeHighlighting() {
+        System.out.println("removing highlights");
         boolean needsRepaint = false;
         DataSet ds = getCurrentDataSet();
         if(ds != null && !ds.getHighlightedVirtualNodes().isEmpty()) {
@@ -267,6 +268,30 @@
         return true;
     }
 
+    private boolean repaintIfRequired(HashSet<OsmPrimitive> newHighlights) {
+        if(!drawTargetHighlight)
+            return false;
+
+        boolean needsRepaint = false;
+        for(OsmPrimitive x : newHighlights) {
+            if(oldHighlights.contains(x)) {
+                continue;
+            }
+            needsRepaint = true;
+            x.setHighlighted(true);
+        }
+        oldHighlights.removeAll(newHighlights);
+        for(OsmPrimitive x : oldHighlights) {
+            x.setHighlighted(false);
+            needsRepaint = true;
+        }
+        oldHighlights = newHighlights;
+        if(needsRepaint) {
+            System.out.println("repainting" + System.currentTimeMillis());
+        }
+        return needsRepaint;
+    }
+
     /**
      * handles adding highlights and updating the cursor for the given mouse event.
      * Please note that the highlighting for merging while moving is handled via mouseDragged.
@@ -285,35 +310,31 @@
      * @return true if repaint is required
      */
     private boolean giveUserFeedback(MouseEvent e, int modifiers) {
-        boolean needsRepaint = false;
-
         Collection<OsmPrimitive> c = MapView.asColl(
                 mv.getNearestNodeOrWay(e.getPoint(), OsmPrimitive.isSelectablePredicate, true));
 
         updateKeyModifiers(modifiers);
         determineMapMode(!c.isEmpty());
 
-        if(drawTargetHighlight) {
-            needsRepaint = removeHighlighting();
-        }
+        HashSet<OsmPrimitive> newHighlights = new HashSet<OsmPrimitive>();
 
         virtualWays.clear();
         virtualNode = null;
         if(mode == Mode.move && setupVirtual(e)) {
             DataSet ds = getCurrentDataSet();
-            if (ds != null) {
-                if(drawTargetHighlight) ds.setHighlightedVirtualNodes(virtualWays);
+            if (ds != null && drawTargetHighlight) {
+                ds.setHighlightedVirtualNodes(virtualWays);
             }
             mv.setNewCursor(SelectActionCursor.virtual_node.cursor(), this);
             // don't highlight anything else if a virtual node will be
-            return drawTargetHighlight; // if no highlighting, repaint is not needed
+            return repaintIfRequired(newHighlights);
         }
 
         mv.setNewCursor(getCursor(c), this);
 
         // return early if there can't be any highlights
         if(!drawTargetHighlight || mode != Mode.move || c.isEmpty())
-            return needsRepaint;
+            return repaintIfRequired(newHighlights);
 
         // CTRL toggles selection, but if while dragging CTRL means merge
         final boolean isToggleMode = ctrl && !dragInProgress();
@@ -322,11 +343,10 @@
             // when clicked. I.e. don't highlight selected elements unless
             // we are in toggle mode.
             if(isToggleMode || !x.isSelected()) {
-                x.setHighlighted(true);
-                oldHighlights.add(x);
+                newHighlights.add(x);
             }
         }
-        return needsRepaint || !oldHighlights.isEmpty();
+        return repaintIfRequired(newHighlights);
     }
 
     /**
@@ -445,7 +465,7 @@
                 return;
 
             Command c = !Main.main.undoRedo.commands.isEmpty()
-                    ? Main.main.undoRedo.commands.getLast() : null;
+            ? Main.main.undoRedo.commands.getLast() : null;
             if (c instanceof SequenceCommand) {
                 c = ((SequenceCommand) c).getLastCommand();
             }
