Index: applications/editors/josm/plugins/photoadjust/README
===================================================================
--- applications/editors/josm/plugins/photoadjust/README	(revision 35107)
+++ applications/editors/josm/plugins/photoadjust/README	(revision 35108)
@@ -32,6 +32,6 @@
     License: GPL v2 or later
   src/org/openstreetmap/josm/plugins/photoadjust/
-    self written code
-    License: CC0
+    different authors (see SVN log)
+    License: GPL v2 or later
   data:
     translations (*.lang):
Index: applications/editors/josm/plugins/photoadjust/build.xml
===================================================================
--- applications/editors/josm/plugins/photoadjust/build.xml	(revision 35107)
+++ applications/editors/josm/plugins/photoadjust/build.xml	(revision 35108)
@@ -5,5 +5,5 @@
     <property name="commit.message" value="Commit message"/>
     <!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
-    <property name="plugin.main.version" value="14625"/>
+    <property name="plugin.main.version" value="15334"/>
 
     <!-- Configure these properties (replace "..." accordingly).
Index: applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustMapMode.java
===================================================================
--- applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustMapMode.java	(revision 35107)
+++ applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustMapMode.java	(revision 35108)
@@ -84,5 +84,5 @@
     public String getModeHelpText() {
         if (hasLayersToAdjust()) {
-            return tr("Click+drag photo, shift+click to position photo, control+click to set direction.");
+            return tr("Click+drag photo, control+alt+click to position photo, control+click to set direction.");
         } else {
             return tr("Please load some photos.");
Index: applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustWorker.java
===================================================================
--- applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustWorker.java	(revision 35107)
+++ applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustWorker.java	(revision 35108)
@@ -2,11 +2,11 @@
 package org.openstreetmap.josm.plugins.photoadjust;
 
-import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
-import java.awt.geom.Point2D;
 import java.util.List;
 
 import org.openstreetmap.josm.data.ImageData;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.projection.ProjectionRegistry;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
@@ -24,5 +24,5 @@
     // clicked.  This must be in pixels to maintain the same offset if
     // the photo is moved very far.
-    private Point2D dragOffset;
+    private EastNorth dragOffset;
     private boolean centerViewIsDisabled = false;
     private boolean centerViewNeedsEnable = false;
@@ -34,5 +34,5 @@
         dragPhoto = null;
         dragData = null;
-        dragOffset = null;
+        dragOffset = EastNorth.ZERO;
     }
 
@@ -66,7 +66,7 @@
     /**
      * Mouse click handler.  Control+click changes the image direction if
-     * there is a photo selected on the map.  Shift+click positions the photo
-     * from the ImageViewerDialog.  Click without shift or control checks if
-     * there is a photo under the mouse.
+     * there is a photo selected on the map.  Control+alt+click positions the
+     * selected photo.  Click without shift or control checks if there is a
+     * photo under the mouse and uses it for dragging.
      *
      * @param evt Mouse event from MouseAdapter mousePressed().
@@ -81,35 +81,39 @@
             // Check if modifier key is pressed and change to
             // image viewer photo if it is.
-            final boolean isShift = (evt.getModifiers() & InputEvent.SHIFT_MASK) != 0;
-            final boolean isCtrl = (evt.getModifiers() & InputEvent.CTRL_MASK) != 0;
-            if (isShift || isCtrl) {
+            final boolean isAlt = (evt.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) == MouseEvent.ALT_DOWN_MASK;
+            final boolean isCtrl = (evt.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK;
+            final boolean isShift = (evt.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) == MouseEvent.SHIFT_DOWN_MASK;
+            // ignore key press with shift, to not conflict with selection
+            if (isShift) {
+                return;
+            }
+            if (isAlt || isCtrl) {
                 for (GeoImageLayer layer: imageLayers) {
                     if (layer.isVisible()) {
-                        final ImageEntry img = layer.getImageData().getSelectedImage();
-                        if (img != null) {
+                        final List<ImageEntry> entries = layer.getImageData().getSelectedImages();
+                        if (!entries.isEmpty()) {
                             // Change direction if control is pressed, position
-                            // otherwise.  Shift+control changes direction, similar to
-                            // rotate in select mode.
+                            // with control+alt.
                             //
                             // Combinations:
-                            // S ... shift pressed
+                            // A ... alt pressed
                             // C ... control pressed
                             // pos ... photo has a position set == is displayed on the map
                             // nopos ... photo has no position set
                             //
-                            // S + pos: position at mouse
-                            // S + nopos: position at mouse
+                            // C + A + pos: position at mouse
+                            // C + A + nopos: position at mouse
                             // C + pos: change orientation
                             // C + nopos: ignored
-                            // S + C + pos: change orientation
-                            // S + C + nopos: ignore
-                            if (isCtrl) {
-                                if (img.getPos() != null) {
-                                    changeDirection(img, layer.getImageData(), evt);
+                            for (ImageEntry img: entries) {
+                                if (isCtrl && !isAlt) {
+                                    if (img.getPos() != null) {
+                                        changeDirection(img, layer.getImageData(), evt);
+                                    }
+                                } else if (isCtrl && isAlt) {
+                                    movePhoto(img, layer.getImageData(), evt);
                                 }
-                            } else { // shift pressed
-                                movePhoto(img, layer.getImageData(), evt);
+                                dragPhoto = img;
                             }
-                            dragPhoto = img;
                             dragData = layer.getImageData();
                             break;
@@ -141,8 +145,4 @@
     public void doMouseReleased(MouseEvent evt) {
         restoreCenterView();
-        //if (dragLayer != null && dragPhoto != null) {
-        //    // Re-display the photo to update the OSD.
-        //    ImageViewerDialog.showImage(dragLayer, dragPhoto);
-        //}
     }
 
@@ -154,9 +154,26 @@
     public void doMouseDragged(MouseEvent evt) {
         if (dragData != null && dragPhoto != null) {
-            if ((evt.getModifiers() & InputEvent.CTRL_MASK) != 0) {
-                changeDirection(dragPhoto, dragData, evt);
+            if ((evt.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) {
+                if (dragData.isImageSelected(dragPhoto)) {
+                    for (ImageEntry photo: dragData.getSelectedImages()) {
+                        changeDirection(photo, dragData, evt);
+                    }
+                } else {
+                    changeDirection(dragPhoto, dragData, evt);
+                }
             } else {
                 disableCenterView();
-                movePhoto(dragPhoto, dragData, evt);
+                final EastNorth startEN = dragPhoto.getPos().getEastNorth(ProjectionRegistry.getProjection()).subtract(dragOffset);
+                final EastNorth currentEN = MainApplication.getMap().mapView.getEastNorth(evt.getX(), evt.getY());
+                final EastNorth translation = currentEN.subtract(startEN);
+
+                if (dragData.isImageSelected(dragPhoto)) {
+                    for (ImageEntry photo: dragData.getSelectedImages()) {
+                        translatePhoto(photo, translation);
+                    }
+                } else {
+                    translatePhoto(dragPhoto, translation);
+                }
+                dragData.notifyImageUpdate();
             }
         }
@@ -170,7 +187,7 @@
      */
     private void setDragOffset(ImageEntry photo, MouseEvent evt) {
-        final Point2D centerPoint = MainApplication.getMap().mapView.getPoint2D(photo.getPos());
-        dragOffset = new Point2D.Double(centerPoint.getX() - evt.getX(),
-                                        centerPoint.getY() - evt.getY());
+        final EastNorth centerEN = photo.getPos().getEastNorth(ProjectionRegistry.getProjection());
+        final EastNorth offsetEN = MainApplication.getMap().mapView.getEastNorth(evt.getX(), evt.getY());
+        dragOffset = centerEN.subtract(offsetEN);
     }
 
@@ -182,18 +199,20 @@
      * @param evt Mouse event from one of the mouse adapters.
      */
-    private void movePhoto(ImageEntry photo, ImageData data,
-            MouseEvent evt) {
-        LatLon newPos;
-        if (dragOffset != null) {
-            newPos = MainApplication.getMap().mapView.getLatLon(
-                dragOffset.getX() + evt.getX(),
-                dragOffset.getY() + evt.getY());
-        } else {
-            newPos = MainApplication.getMap().mapView.getLatLon(evt.getX(), evt.getY());
-        }
+    private void movePhoto(ImageEntry photo, ImageData data, MouseEvent evt) {
+        LatLon newPos = MainApplication.getMap().mapView.getLatLon(evt.getX(), evt.getY());
         data.updateImagePosition(photo, newPos);
-        // Re-display the photo because the OSD data might change (new
-        // coordinates).  Or do that in doMouseReleased().
-        //ImageViewerDialog.showImage(layer, photo);
+    }
+
+    /**
+     * Apply the given translation to the photo
+     * @param photo The photo to move
+     * @param translation the translation to apply
+     */
+    private void translatePhoto(ImageEntry photo, EastNorth translation) {
+        final EastNorth startEN = photo.getPos().getEastNorth(ProjectionRegistry.getProjection());
+        final EastNorth newPosEN = startEN.add(translation);
+        final LatLon newPos = MainApplication.getMap().mapView.getProjection().eastNorth2latlon(newPosEN);
+        photo.setPos(newPos);
+        photo.flagNewGpsData();
     }
 
Index: applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoPropertyEditor.java
===================================================================
--- applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoPropertyEditor.java	(revision 35107)
+++ applications/editors/josm/plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoPropertyEditor.java	(revision 35108)
@@ -87,6 +87,6 @@
         @Override
         public void actionPerformed(ActionEvent evt) {
-            final ImageData data = getLayerWithSelectedImage().get().getImageData();
-            final ImageEntry photo = data.getSelectedImage();
+            final ImageData data = getLayerWithOneSelectedImage().get().getImageData();
+            final ImageEntry photo = data.getSelectedImages().get(0);
 
             StringBuilder title =
@@ -117,10 +117,10 @@
          */
         private static boolean enabled() {
-            return getLayerWithSelectedImage().isPresent();
-        }
-
-        private static Optional<GeoImageLayer> getLayerWithSelectedImage() {
+            return getLayerWithOneSelectedImage().isPresent();
+        }
+
+        private static Optional<GeoImageLayer> getLayerWithOneSelectedImage() {
             List<GeoImageLayer> list = MainApplication.getLayerManager().getLayersOfType(GeoImageLayer.class);
-            return list.stream().filter(l -> l.getImageData().getSelectedImage() != null).findFirst();
+            return list.stream().filter(l -> l.getImageData().getSelectedImages().size() == 1).findFirst();
         }
 
