Index: src/org/openstreetmap/josm/data/ImageData.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/data/ImageData.java b/src/org/openstreetmap/josm/data/ImageData.java
--- a/src/org/openstreetmap/josm/data/ImageData.java	(revision 18565)
+++ b/src/org/openstreetmap/josm/data/ImageData.java	(date 1664895748752)
@@ -10,6 +10,7 @@
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.gpx.GpxImageEntry;
 import org.openstreetmap.josm.data.osm.QuadBuckets;
+import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
 import org.openstreetmap.josm.tools.ListenerList;
 
@@ -41,6 +42,8 @@
 
     private final ListenerList<ImageDataUpdateListener> listeners = ListenerList.create();
     private final QuadBuckets<ImageEntry> geoImages = new QuadBuckets<>();
+    private Layer layer;
+
 
     /**
      * Construct a new image container without images
@@ -375,6 +378,25 @@
         notifyImageUpdate();
     }
 
+    /**
+     * Set the layer for use with {@link org.openstreetmap.josm.gui.layer.geoimage.ImageViewerDialog#displayImages(Layer, List)}
+     * @param layer The layer to use for organization
+     * @since xxx
+     */
+    public void setLayer(Layer layer) {
+        this.layer = layer;
+    }
+
+    /**
+     * Get the layer that this data is associated with. May be {@code null}.
+     * @return The layer this data is associated with.
+     * @since xxx
+     */
+    public Layer getLayer() {
+        return this.layer;
+    }
+
+
     /**
      * Add a listener that listens to image data changes
      * @param listener the {@link ImageDataUpdateListener}
Index: src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java b/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 18565)
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(date 1664895748774)
@@ -171,6 +171,7 @@
         this.gpxData = gpxData;
         this.useThumbs = useThumbs;
         this.data.addImageDataUpdateListener(this);
+        this.data.setLayer(this);
     }
 
     private final class ImageMouseListener extends MouseAdapter {
@@ -231,6 +232,7 @@
                     }
                 } else {
                     data.setSelectedImage(img);
+                    ImageViewerDialog.getInstance().displayImages(GeoImageLayer.this, Collections.singletonList(img));
                 }
             }
         }
@@ -521,9 +523,6 @@
      * Show current photo on map and in image viewer.
      */
     public void showCurrentPhoto() {
-        if (data.getSelectedImage() != null) {
-            clearOtherCurrentPhotos();
-        }
         updateBufferAndRepaint();
     }
 
@@ -628,18 +627,6 @@
         }
     }
 
-    /**
-     * Clears the currentPhoto of the other GeoImageLayer's. Otherwise there could be multiple selected photos.
-     */
-    private void clearOtherCurrentPhotos() {
-        for (GeoImageLayer layer:
-                 MainApplication.getLayerManager().getLayersOfType(GeoImageLayer.class)) {
-            if (layer != this) {
-                layer.getImageData().clearSelectedImage();
-            }
-        }
-    }
-
     /**
      * Registers a map mode for which the functionality of this layer should be available.
      * @param mapMode Map mode to be registered
Index: src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java	(revision 18565)
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java	(date 1664895748788)
@@ -8,6 +8,7 @@
 import java.awt.BorderLayout;
 import java.awt.Component;
 import java.awt.Dimension;
+import java.awt.FlowLayout;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
@@ -21,7 +22,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.Future;
@@ -52,6 +55,7 @@
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager;
 import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
 import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings;
@@ -120,6 +124,8 @@
     private JButton btnOpenExternal;
     private JButton btnDeleteFromDisk;
     private JToggleButton tbCentre;
+    /** The layer tab (used to select images when multiple layers provide images, makes for easy switching) */
+    private JPanel layers;
 
     private ImageViewerDialog() {
         super(tr("Geotagged Images"), "geoimage", tr("Display geotagged images"), Shortcut.registerShortcut("tools:geotagged",
@@ -152,6 +158,8 @@
 
     private void build() {
         JPanel content = new JPanel(new BorderLayout());
+        this.layers = new JPanel(new FlowLayout(FlowLayout.LEADING));
+        content.add(layers, BorderLayout.NORTH);
 
         content.add(imgDisplay, BorderLayout.CENTER);
 
@@ -213,6 +221,34 @@
         createLayout(content, false, null);
     }
 
+    private void updateLayers() {
+        if (this.tabbedEntries.size() <= 1) {
+            this.layers.setVisible(false);
+        } else {
+            final IImageEntry<?> current;
+            synchronized (this) {
+                current = this.currentEntry;
+            }
+            this.layers.setVisible(true);
+            // Remove all old components
+            this.layers.removeAll();
+            MainLayerManager layerManager = MainApplication.getLayerManager();
+            List<Layer> invalidLayers = this.tabbedEntries.keySet().stream().filter(layer -> !layerManager.containsLayer(layer))
+                    .collect(Collectors.toList());
+            // We need to do multiple calls to avoid ConcurrentModificationExceptions
+            invalidLayers.forEach(this.tabbedEntries::remove);
+            for (Map.Entry<Layer, List<IImageEntry<?>>> entry : this.tabbedEntries.entrySet()) {
+                JButton layerButton = new JButton(tr(entry.getKey().getLabel()));
+                layerButton.addActionListener(l -> this.displayImages(entry.getKey(), entry.getValue()));
+                if (entry.getValue().contains(current)) {
+                    layerButton.setSelected(true);
+                }
+                this.layers.add(layerButton);
+            }
+            this.layers.invalidate();
+        }
+    }
+
     @Override
     public void destroy() {
         MainApplication.getLayerManager().removeActiveLayerChangeListener(this);
@@ -551,6 +587,8 @@
         return wasEnabled;
     }
 
+    /** Used for tabbed panes */
+    private final transient Map<Layer, List<IImageEntry<?>>> tabbedEntries = new HashMap<>();
     private transient IImageEntry<? extends IImageEntry<?>> currentEntry;
 
     /**
@@ -578,6 +616,16 @@
      * @since 18246
      */
     public void displayImages(List<IImageEntry<?>> entries) {
+        this.displayImages((Layer) null, entries);
+    }
+
+    /**
+     * Displays images for the given layer.
+     * @param layer The layer to use for the tab ui
+     * @param entries image entries
+     * @since xxx
+     */
+    public void displayImages(Layer layer, List<IImageEntry<?>> entries) {
         boolean imageChanged;
         IImageEntry<?> entry = entries != null && entries.size() == 1 ? entries.get(0) : null;
 
@@ -598,6 +646,12 @@
             }
         }
 
+        if (entries == null || entries.isEmpty()) {
+            this.tabbedEntries.remove(layer);
+        } else {
+            this.tabbedEntries.put(layer, entries);
+        }
+        this.updateLayers();
         if (entry != null) {
             this.updateButtonsNonNullEntry(entry, imageChanged);
         } else {
@@ -819,11 +873,11 @@
 
     @Override
     public void selectedImageChanged(ImageData data) {
-        displayImages(new ArrayList<>(data.getSelectedImages()));
+        displayImages(data.getLayer(), new ArrayList<>(data.getSelectedImages()));
     }
 
     @Override
     public void imageDataUpdated(ImageData data) {
-        displayImages(new ArrayList<>(data.getSelectedImages()));
+        displayImages(data.getLayer(), new ArrayList<>(data.getSelectedImages()));
     }
 }
