Index: /trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java	(revision 4505)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java	(revision 4506)
@@ -2,4 +2,5 @@
 package org.openstreetmap.josm.data.imagery;
 
+import java.awt.Image;
 import java.util.Arrays;
 import java.util.ArrayList;
@@ -18,6 +19,8 @@
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.gui.jmapviewer.Coordinate;
+import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
 import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource.Mapnik;
-import org.openstreetmap.gui.jmapviewer.tilesources.TMSTileSource;
+import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource;
 
 /**
@@ -26,5 +29,5 @@
  * @author Frederik Ramm <frederik@remote.org>
  */
-public class ImageryInfo implements Comparable<ImageryInfo> {
+public class ImageryInfo implements Comparable<ImageryInfo>, Attributed {
 
     public enum ImageryType {
@@ -325,6 +328,41 @@
     }
 
-    public String getAttributionText() {
+    @Override
+    public boolean requiresAttribution() {
+        return attributionText != null || attributionImage != null || termsOfUseText != null || termsOfUseURL != null;
+    }
+
+    @Override
+    public String getAttributionText(int zoom, Coordinate topLeft, Coordinate botRight) {
         return attributionText;
+    }
+
+    @Override
+    public String getAttributionLinkURL() {
+        return attributionLinkURL;
+    }
+
+    @Override
+    public Image getAttributionImage() {
+        ImageIcon i = ImageProvider.getIfAvailable(attributionImage);
+        if (i != null) {
+            return i.getImage();
+        }
+        return null;
+    }
+
+    @Override
+    public String getAttributionImageURL() {
+        return attributionImageURL;
+    }
+
+    @Override
+    public String getTermsOfUseText() {
+        return termsOfUseText;
+    }
+
+    @Override
+    public String getTermsOfUseURL() {
+        return termsOfUseURL;
     }
 
@@ -333,16 +371,12 @@
     }
 
+    public void setAttributionImageURL(String text) {
+        attributionImageURL = text;
+    }
+
     public void setAttributionImage(String text) {
         attributionImage = text;
     }
 
-    public void setAttributionImageURL(String text) {
-        attributionImageURL = text;
-    }
-
-    public String getAttributionLinkURL() {
-        return attributionLinkURL;
-    }
-
     public void setAttributionLinkURL(String text) {
         attributionLinkURL = text;
@@ -351,8 +385,4 @@
     public void setTermsOfUseText(String text) {
         termsOfUseText = text;
-    }
-
-    public String getTermsOfUseURL() {
-        return termsOfUseURL;
     }
 
@@ -542,5 +572,5 @@
      * Applies the attribution from this object to a TMSTileSource.
      */
-    public void setAttribution(TMSTileSource s) {
+    public void setAttribution(AbstractTileSource s) {
         if (attributionText != null) {
             if (attributionText.equals("osm")) {
Index: /trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java	(revision 4505)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java	(revision 4506)
@@ -1216,5 +1216,5 @@
             this.paintTileText(ts, t, g, mv, displayZoomLevel, t);
         }
-        
+
         attribution.paintAttribution(g, mv.getWidth(), mv.getHeight(), getShiftedCoord(topLeft), getShiftedCoord(botRight), displayZoomLevel, this);
 
Index: /trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java	(revision 4505)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java	(revision 4506)
@@ -7,6 +7,10 @@
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.awt.Image;
 import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
 import java.io.File;
 import java.io.FileInputStream;
@@ -30,5 +34,7 @@
 import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
-
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.gui.jmapviewer.AttributionSupport;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.DiskAccessAction;
@@ -51,4 +57,5 @@
 import org.openstreetmap.josm.data.preferences.IntegerProperty;
 import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
@@ -63,5 +70,5 @@
  * fetched this way is tiled and managed to the disc to reduce server load.
  */
-public class WMSLayer extends ImageryLayer implements PreferenceChangedListener {
+public class WMSLayer extends ImageryLayer implements ImageObserver, PreferenceChangedListener {
     public static final BooleanProperty PROP_ALPHA_CHANNEL = new BooleanProperty("imagery.wms.alpha_channel", true);
     public static final IntegerProperty PROP_SIMULTANEOUS_CONNECTIONS = new IntegerProperty("imagery.wms.simultaneousConnections", 3);
@@ -85,5 +92,5 @@
     protected final MapView mv;
     public WmsCache cache;
-
+    private AttributionSupport attribution = new AttributionSupport();
 
     // Image index boundary for current view
@@ -142,8 +149,46 @@
         resolution = mv.getDist100PixelText();
 
+        attribution.initialize(this.info);
+
         if(info.getUrl() != null)
             startGrabberThreads();
 
         Main.pref.addPreferenceChangeListener(this);
+
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                final MouseAdapter adapter = new MouseAdapter() {
+                    @Override
+                    public void mouseClicked(MouseEvent e) {
+                        if (!isVisible()) return;
+                        if (e.getButton() == MouseEvent.BUTTON1) {
+                            attribution.handleAttribution(e.getPoint(), true);
+                        }
+                    }
+                };
+                Main.map.mapView.addMouseListener(adapter);
+
+                MapView.addLayerChangeListener(new LayerChangeListener() {
+                    @Override
+                    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+                        //
+                    }
+
+                    @Override
+                    public void layerAdded(Layer newLayer) {
+                        //
+                    }
+
+                    @Override
+                    public void layerRemoved(Layer oldLayer) {
+                        if (oldLayer == WMSLayer.this) {
+                            Main.map.mapView.removeMouseListener(adapter);
+                            MapView.removeLayerChangeListener(this);
+                        }
+                    }
+                });
+            }
+        });
     }
 
@@ -230,4 +275,7 @@
             downloadAndPaintVisible(g, mv, false);
         }
+
+        attribution.paintAttribution(g, mv.getWidth(), mv.getHeight(), null, null, 0, this);
+
     }
 
@@ -289,5 +337,5 @@
 
     /**
-     * 
+     *
      * @return When overlapping is enabled, return visible part of tile. Otherwise return original image
      */
@@ -886,3 +934,11 @@
         return tr("Supported projections are: {0}", res);
     }
+
+    @Override
+    public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
+        boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
+        Main.map.repaint(done ? 0 : 100);
+        return !done;
+    }
+
 }
Index: /trunk/src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 4505)
+++ /trunk/src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 4506)
@@ -99,4 +99,8 @@
     public static ImageIcon get(String name) {
         return get("", name);
+    }
+
+    public static ImageIcon getIfAvailable(String name) {
+        return getIfAvailable((Collection<String>) null, null, "", name);
     }
 
